OSDN Git Service

powerpc/32s: Prepare Kernel Userspace Access Protection
authorChristophe Leroy <christophe.leroy@c-s.fr>
Mon, 11 Mar 2019 08:30:36 +0000 (08:30 +0000)
committerMichael Ellerman <mpe@ellerman.id.au>
Sun, 21 Apr 2019 13:11:46 +0000 (23:11 +1000)
This patch prepares Kernel Userspace Access Protection for
book3s/32.

Due to limitations of the processor page protection capabilities,
the protection is only against writing. read protection cannot be
achieved using page protection.

book3s/32 provides the following values for PP bits:

PP00 provides RW for Key 0 and NA for Key 1
PP01 provides RW for Key 0 and RO for Key 1
PP10 provides RW for all
PP11 provides RO for all

Today PP10 is used for RW pages and PP11 for RO pages, and user
segment register's Kp and Ks are set to 1. This patch modifies
page protection to use PP01 for RW pages and sets user segment
registers to Kp 0 and Ks 0.

This will allow to setup Userspace write access protection by
settng Ks to 1 in the following patch.

Kernel space segment registers remain unchanged.

Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/book3s/32/mmu-hash.h
arch/powerpc/kernel/head_32.S
arch/powerpc/mm/hash_low_32.S

index 8c5727a..f9eae10 100644 (file)
@@ -65,6 +65,8 @@ typedef pte_t *pgtable_t;
 
 /* Values for Segment Registers */
 #define SR_NX  0x10000000      /* No Execute */
+#define SR_KP  0x20000000      /* User key */
+#define SR_KS  0x40000000      /* Supervisor key */
 
 #ifndef __ASSEMBLY__
 
index 19b46cb..69b97cc 100644 (file)
@@ -522,9 +522,9 @@ InstructionTLBMiss:
        andc.   r1,r1,r0                /* check access & ~permission */
        bne-    InstructionAddressInvalid /* return if access not permitted */
        /* Convert linux-style PTE to low word of PPC-style PTE */
-       rlwimi  r0,r0,32-1,30,30        /* _PAGE_USER -> PP msb */
-       ori     r1, r1, 0xe05           /* clear out reserved bits */
-       andc    r1, r0, r1              /* PP = user? 2 : 0 */
+       rlwimi  r0,r0,32-2,31,31        /* _PAGE_USER -> PP lsb */
+       ori     r1, r1, 0xe06           /* clear out reserved bits */
+       andc    r1, r0, r1              /* PP = user? 1 : 0 */
 BEGIN_FTR_SECTION
        rlwinm  r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */
 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
@@ -590,11 +590,11 @@ DataLoadTLBMiss:
         * we would need to update the pte atomically with lwarx/stwcx.
         */
        /* Convert linux-style PTE to low word of PPC-style PTE */
-       rlwinm  r1,r0,32-10,31,31       /* _PAGE_RW -> PP lsb */
+       rlwinm  r1,r0,32-9,30,30        /* _PAGE_RW -> PP msb */
        rlwimi  r0,r0,32-1,30,30        /* _PAGE_USER -> PP msb */
        rlwimi  r0,r0,32-1,31,31        /* _PAGE_USER -> PP lsb */
        ori     r1,r1,0xe04             /* clear out reserved bits */
-       andc    r1,r0,r1                /* PP = user? rw? 2: 3: 0 */
+       andc    r1,r0,r1                /* PP = user? rw? 1: 3: 0 */
 BEGIN_FTR_SECTION
        rlwinm  r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */
 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
@@ -670,9 +670,9 @@ DataStoreTLBMiss:
         * we would need to update the pte atomically with lwarx/stwcx.
         */
        /* Convert linux-style PTE to low word of PPC-style PTE */
-       rlwimi  r0,r0,32-1,30,30        /* _PAGE_USER -> PP msb */
-       li      r1,0xe05                /* clear out reserved bits & PP lsb */
-       andc    r1,r0,r1                /* PP = user? 2: 0 */
+       rlwimi  r0,r0,32-2,31,31        /* _PAGE_USER -> PP lsb */
+       li      r1,0xe06                /* clear out reserved bits & PP msb */
+       andc    r1,r0,r1                /* PP = user? 1: 0 */
 BEGIN_FTR_SECTION
        rlwinm  r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */
 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
@@ -896,9 +896,9 @@ load_up_mmu:
        tophys(r6,r6)
        lwz     r6,_SDR1@l(r6)
        mtspr   SPRN_SDR1,r6
-       li      r0, NUM_USER_SEGMENTS   /* load up segment register values */
+       li      r0, NUM_USER_SEGMENTS /* load up user segment register values */
        mtctr   r0              /* for context 0 */
-       lis     r3,0x2000       /* Ku = 1, VSID = 0 */
+       li      r3, 0           /* Kp = 0, Ks = 0, VSID = 0 */
 #ifdef CONFIG_PPC_KUEP
        oris    r3, r3, SR_NX@h /* Set Nx */
 #endif
@@ -910,6 +910,7 @@ load_up_mmu:
        li      r0, 16 - NUM_USER_SEGMENTS /* load up kernel segment registers */
        mtctr   r0                      /* for context 0 */
        rlwinm  r3, r3, 0, ~SR_NX       /* Nx = 0 */
+       oris    r3, r3, SR_KP@h         /* Kp = 1 */
 3:     mtsrin  r3, r4
        addi    r3, r3, 0x111   /* increment VSID */
        addis   r4, r4, 0x1000  /* address of next segment */
@@ -1016,7 +1017,6 @@ _ENTRY(switch_mmu_context)
        blt-    4f
        mulli   r3,r3,897       /* multiply context by skew factor */
        rlwinm  r3,r3,4,8,27    /* VSID = (context & 0xfffff) << 4 */
-       addis   r3,r3,0x6000    /* Set Ks, Ku bits */
 #ifdef CONFIG_PPC_KUEP
        oris    r3, r3, SR_NX@h /* Set Nx */
 #endif
index a6c491f..e27792d 100644 (file)
@@ -309,13 +309,13 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64)
 
 _GLOBAL(create_hpte)
        /* Convert linux-style PTE (r5) to low word of PPC-style PTE (r8) */
-       rlwinm  r8,r5,32-10,31,31       /* _PAGE_RW -> PP lsb */
-       rlwinm  r0,r5,32-7,31,31        /* _PAGE_DIRTY -> PP lsb */
+       rlwinm  r8,r5,32-9,30,30        /* _PAGE_RW -> PP msb */
+       rlwinm  r0,r5,32-6,30,30        /* _PAGE_DIRTY -> PP msb */
        and     r8,r8,r0                /* writable if _RW & _DIRTY */
        rlwimi  r5,r5,32-1,30,30        /* _PAGE_USER -> PP msb */
        rlwimi  r5,r5,32-2,31,31        /* _PAGE_USER -> PP lsb */
        ori     r8,r8,0xe04             /* clear out reserved bits */
-       andc    r8,r5,r8                /* PP = user? (rw&dirty? 2: 3): 0 */
+       andc    r8,r5,r8                /* PP = user? (rw&dirty? 1: 3): 0 */
 BEGIN_FTR_SECTION
        rlwinm  r8,r8,0,~_PAGE_COHERENT /* clear M (coherence not required) */
 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)