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);
}