diff options
Diffstat (limited to 'arch/arc/mm/tlb.c')
-rw-r--r-- | arch/arc/mm/tlb.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 7957dc4e4d4a..f9908341e8a7 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c | |||
@@ -341,7 +341,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
341 | void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) | 341 | void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) |
342 | { | 342 | { |
343 | unsigned long flags; | 343 | unsigned long flags; |
344 | unsigned int idx, asid_or_sasid; | 344 | unsigned int idx, asid_or_sasid, rwx; |
345 | unsigned long pd0_flags; | 345 | unsigned long pd0_flags; |
346 | 346 | ||
347 | /* | 347 | /* |
@@ -393,8 +393,23 @@ void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) | |||
393 | 393 | ||
394 | write_aux_reg(ARC_REG_TLBPD0, address | pd0_flags | asid_or_sasid); | 394 | write_aux_reg(ARC_REG_TLBPD0, address | pd0_flags | asid_or_sasid); |
395 | 395 | ||
396 | /* | ||
397 | * ARC MMU provides fully orthogonal access bits for K/U mode, | ||
398 | * however Linux only saves 1 set to save PTE real-estate | ||
399 | * Here we convert 3 PTE bits into 6 MMU bits: | ||
400 | * -Kernel only entries have Kr Kw Kx 0 0 0 | ||
401 | * -User entries have mirrored K and U bits | ||
402 | */ | ||
403 | rwx = pte_val(*ptep) & PTE_BITS_RWX; | ||
404 | |||
405 | if (pte_val(*ptep) & _PAGE_GLOBAL) | ||
406 | rwx <<= 3; /* r w x => Kr Kw Kx 0 0 0 */ | ||
407 | else | ||
408 | rwx |= (rwx << 3); /* r w x => Kr Kw Kx Ur Uw Ux */ | ||
409 | |||
396 | /* Load remaining info in PD1 (Page Frame Addr and Kx/Kw/Kr Flags) */ | 410 | /* Load remaining info in PD1 (Page Frame Addr and Kx/Kw/Kr Flags) */ |
397 | write_aux_reg(ARC_REG_TLBPD1, (pte_val(*ptep) & PTE_BITS_IN_PD1)); | 411 | write_aux_reg(ARC_REG_TLBPD1, |
412 | rwx | (pte_val(*ptep) & PTE_BITS_NON_RWX_IN_PD1)); | ||
398 | 413 | ||
399 | /* First verify if entry for this vaddr+ASID already exists */ | 414 | /* First verify if entry for this vaddr+ASID already exists */ |
400 | write_aux_reg(ARC_REG_TLBCOMMAND, TLBProbe); | 415 | write_aux_reg(ARC_REG_TLBCOMMAND, TLBProbe); |