static inline void load_ksp_mmu()

in include/asm/mmu_context.h [93:165]


static inline void load_ksp_mmu(struct task_struct *task)
{
	unsigned long flags;
	struct mm_struct *mm;
	int asid;
	pgd_t *pgd;
	p4d_t *p4d;
	pud_t *pud;
	pmd_t *pmd;
	pte_t *pte;
	unsigned long mmuar;

	local_irq_save(flags);
	mmuar = task->thread.ksp;

	/* Search for a valid TLB entry, if one is found, don't remap */
	mmu_write(MMUAR, mmuar);
	mmu_write(MMUOR, MMUOR_STLB | MMUOR_ADR);
	if (mmu_read(MMUSR) & MMUSR_HIT)
		goto end;

	if (mmuar >= PAGE_OFFSET) {
		mm = &init_mm;
	} else {
		pr_info("load_ksp_mmu: non-kernel mm found: 0x%p\n", task->mm);
		mm = task->mm;
	}

	if (!mm)
		goto bug;

	pgd = pgd_offset(mm, mmuar);
	if (pgd_none(*pgd))
		goto bug;

	p4d = p4d_offset(pgd, mmuar);
	if (p4d_none(*p4d))
		goto bug;

	pud = pud_offset(p4d, mmuar);
	if (pud_none(*pud))
		goto bug;

	pmd = pmd_offset(pud, mmuar);
	if (pmd_none(*pmd))
		goto bug;

	pte = (mmuar >= PAGE_OFFSET) ? pte_offset_kernel(pmd, mmuar)
				     : pte_offset_map(pmd, mmuar);
	if (pte_none(*pte) || !pte_present(*pte))
		goto bug;

	set_pte(pte, pte_mkyoung(*pte));
	asid = mm->context & 0xff;
	if (!pte_dirty(*pte) && mmuar <= PAGE_OFFSET)
		set_pte(pte, pte_wrprotect(*pte));

	mmu_write(MMUTR, (mmuar & PAGE_MASK) | (asid << MMUTR_IDN) |
		(((int)(pte->pte) & (int)CF_PAGE_MMUTR_MASK)
		>> CF_PAGE_MMUTR_SHIFT) | MMUTR_V);

	mmu_write(MMUDR, (pte_val(*pte) & PAGE_MASK) |
		((pte->pte) & CF_PAGE_MMUDR_MASK) | MMUDR_SZ_8KB | MMUDR_X);

	mmu_write(MMUOR, MMUOR_ACC | MMUOR_UAA);

	goto end;

bug:
	pr_info("ksp load failed: mm=0x%p ksp=0x08%lx\n", mm, mmuar);
end:
	local_irq_restore(flags);
}