|
@@ -218,8 +218,15 @@ ex_saved_reg1:
|
|
|
; IN: r0 = PTE, r1 = ptr to PTE
|
|
|
|
|
|
.macro CONV_PTE_TO_TLB
|
|
|
- and r3, r0, PTE_BITS_IN_PD1 ; Extract permission flags+PFN from PTE
|
|
|
- sr r3, [ARC_REG_TLBPD1] ; these go in PD1
|
|
|
+ and r3, r0, PTE_BITS_RWX ; r w x
|
|
|
+ lsl r2, r3, 3 ; r w x 0 0 0
|
|
|
+ and.f 0, r0, _PAGE_GLOBAL
|
|
|
+ or.z r2, r2, r3 ; r w x r w x
|
|
|
+
|
|
|
+ and r3, r0, PTE_BITS_NON_RWX_IN_PD1 ; Extract PFN+cache bits from PTE
|
|
|
+ or r3, r3, r2
|
|
|
+
|
|
|
+ sr r3, [ARC_REG_TLBPD1] ; these go in PD1
|
|
|
|
|
|
and r2, r0, PTE_BITS_IN_PD0 ; Extract other PTE flags: (V)alid, (G)lb
|
|
|
#if (CONFIG_ARC_MMU_VER <= 2) /* Neednot be done with v3 onwards */
|
|
@@ -272,8 +279,8 @@ ARC_ENTRY EV_TLBMissI
|
|
|
;----------------------------------------------------------------
|
|
|
; VERIFY_PTE: Check if PTE permissions approp for executing code
|
|
|
cmp_s r2, VMALLOC_START
|
|
|
- mov.lo r2, (_PAGE_PRESENT | _PAGE_U_EXECUTE)
|
|
|
- mov.hs r2, (_PAGE_PRESENT | _PAGE_K_EXECUTE)
|
|
|
+ mov_s r2, (_PAGE_PRESENT | _PAGE_EXECUTE)
|
|
|
+ or.hs r2, r2, _PAGE_GLOBAL
|
|
|
|
|
|
and r3, r0, r2 ; Mask out NON Flag bits from PTE
|
|
|
xor.f r3, r3, r2 ; check ( ( pte & flags_test ) == flags_test )
|
|
@@ -312,26 +319,21 @@ ARC_ENTRY EV_TLBMissD
|
|
|
;----------------------------------------------------------------
|
|
|
; VERIFY_PTE: Chk if PTE permissions approp for data access (R/W/R+W)
|
|
|
|
|
|
- mov_s r2, 0
|
|
|
+ cmp_s r2, VMALLOC_START
|
|
|
+ mov_s r2, _PAGE_PRESENT ; common bit for K/U PTE
|
|
|
+ or.hs r2, r2, _PAGE_GLOBAL ; kernel PTE only
|
|
|
+
|
|
|
+ ; Linux PTE [RWX] bits are semantically overloaded:
|
|
|
+ ; -If PAGE_GLOBAL set, they refer to kernel-only flags (vmalloc)
|
|
|
+ ; -Otherwise they are user-mode permissions, and those are exactly
|
|
|
+ ; same for kernel mode as well (e.g. copy_(to|from)_user)
|
|
|
+
|
|
|
lr r3, [ecr]
|
|
|
btst_s r3, ECR_C_BIT_DTLB_LD_MISS ; Read Access
|
|
|
- or.nz r2, r2, _PAGE_U_READ ; chk for Read flag in PTE
|
|
|
+ or.nz r2, r2, _PAGE_READ ; chk for Read flag in PTE
|
|
|
btst_s r3, ECR_C_BIT_DTLB_ST_MISS ; Write Access
|
|
|
- or.nz r2, r2, _PAGE_U_WRITE ; chk for Write flag in PTE
|
|
|
- ; Above laddering takes care of XCHG access
|
|
|
- ; which is both Read and Write
|
|
|
-
|
|
|
- ; If kernel mode access, ; make _PAGE_xx flags as _PAGE_K_xx
|
|
|
- ; For copy_(to|from)_user, despite exception taken in kernel mode,
|
|
|
- ; this code is not hit, because EFA would still be the user mode
|
|
|
- ; address (EFA < 0x6000_0000).
|
|
|
- ; This code is for legit kernel mode faults, vmalloc specifically
|
|
|
- ; (EFA: 0x7000_0000 to 0x7FFF_FFFF)
|
|
|
-
|
|
|
- lr r3, [efa]
|
|
|
- cmp r3, VMALLOC_START - 1 ; If kernel mode access
|
|
|
- asl.hi r2, r2, 3 ; make _PAGE_xx flags as _PAGE_K_xx
|
|
|
- or r2, r2, _PAGE_PRESENT ; Common flag for K/U mode
|
|
|
+ or.nz r2, r2, _PAGE_WRITE ; chk for Write flag in PTE
|
|
|
+ ; Above laddering takes care of XCHG access (both R and W)
|
|
|
|
|
|
; By now, r2 setup with all the Flags we need to check in PTE
|
|
|
and r3, r0, r2 ; Mask out NON Flag bits from PTE
|