static void update_dtlb(unsigned long address, pte_t pte) { u32 tlbehi; u32 mmucr; tlbehi = sysreg_read(TLBEHI); tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi)); tlbehi |= address & MMU_VPN_MASK; tlbehi |= SYSREG_BIT(TLBEHI_V); sysreg_write(TLBEHI, tlbehi); __builtin_tlbs(); mmucr = sysreg_read(MMUCR); if (mmucr & SYSREG_BIT(MMUCR_N)) { unsigned int rp; u32 tlbar = sysreg_read(TLBARLO); rp = 32 - fls(tlbar); if (rp == 32) { rp = 0; sysreg_write(TLBARLO, -1L); } mmucr = SYSREG_BFINS(DRP, rp, mmucr); sysreg_write(MMUCR, mmucr); } sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK); __builtin_tlbw(); }
static void __flush_tlb_page(unsigned long asid, unsigned long page) { u32 mmucr, tlbehi; /* * Caller is responsible for masking out non-PFN bits in page * and changing the current ASID if necessary. This means that * we don't need to flush the pipeline after writing TLBEHI. */ tlbehi = page | asid; sysreg_write(TLBEHI, tlbehi); __builtin_tlbs(); mmucr = sysreg_read(MMUCR); if (!(mmucr & SYSREG_BIT(MMUCR_N))) { unsigned int entry; u32 tlbarlo; /* Clear the "valid" bit */ sysreg_write(TLBEHI, tlbehi); /* mark the entry as "not accessed" */ entry = SYSREG_BFEXT(DRP, mmucr); tlbarlo = sysreg_read(TLBARLO); tlbarlo |= (0x80000000UL >> entry); sysreg_write(TLBARLO, tlbarlo); /* update the entry with valid bit clear */ __builtin_tlbw(); }
static void __flush_tlb_page(unsigned long asid, unsigned long page) { u32 mmucr, tlbehi; tlbehi = page | asid; sysreg_write(TLBEHI, tlbehi); __builtin_tlbs(); mmucr = sysreg_read(MMUCR); if (!(mmucr & SYSREG_BIT(MMUCR_N))) { unsigned int entry; u32 tlbarlo; sysreg_write(TLBEHI, tlbehi); entry = SYSREG_BFEXT(DRP, mmucr); tlbarlo = sysreg_read(TLBARLO); tlbarlo |= (0x80000000UL >> entry); sysreg_write(TLBARLO, tlbarlo); __builtin_tlbw(); }
static void update_dtlb(unsigned long address, pte_t pte) { u32 tlbehi; u32 mmucr; /* * We're not changing the ASID here, so no need to flush the * pipeline. */ tlbehi = sysreg_read(TLBEHI); tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi)); tlbehi |= address & MMU_VPN_MASK; tlbehi |= SYSREG_BIT(TLBEHI_V); sysreg_write(TLBEHI, tlbehi); /* Does this mapping already exist? */ __builtin_tlbs(); mmucr = sysreg_read(MMUCR); if (mmucr & SYSREG_BIT(MMUCR_N)) { /* Not found -- pick a not-recently-accessed entry */ unsigned int rp; u32 tlbar = sysreg_read(TLBARLO); rp = 32 - fls(tlbar); if (rp == 32) { rp = 0; sysreg_write(TLBARLO, -1L); } mmucr = SYSREG_BFINS(DRP, rp, mmucr); sysreg_write(MMUCR, mmucr); } sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK); /* Let's go */ __builtin_tlbw(); }