aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/mm/tlb.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/mm/tlb.c')
-rw-r--r--arch/arc/mm/tlb.c19
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)
341void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) 341void 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);