Commit 33fe43cf authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman

powerpc/8xx: Manage _PAGE_ACCESSED through APG bits in L1 entry

When _PAGE_ACCESSED is not set, a minor fault is expected.
To do this, TLB miss exception ANDs _PAGE_PRESENT and _PAGE_ACCESSED
into the L2 entry valid bit.

To simplify the processing and reduce the number of instructions in
TLB miss exceptions, manage it as an APG bit and get it next to
_PAGE_GUARDED bit to allow a copy in one go. Then declare the
corresponding groups as handling all accesses as user accesses.
As the PP bits always define user as No Access, it will generate
a fault.
Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/80f488db230c6b0e7b3b990d72bd94a8a069e93e.1602492856.git.christophe.leroy@csgroup.eu
parent 29daf869
...@@ -63,7 +63,7 @@ static inline void restore_user_access(unsigned long flags) ...@@ -63,7 +63,7 @@ static inline void restore_user_access(unsigned long flags)
static inline bool static inline bool
bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
{ {
return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xf0000000), return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xff000000),
"Bug: fault blocked by AP register !"); "Bug: fault blocked by AP register !");
} }
......
...@@ -33,19 +33,18 @@ ...@@ -33,19 +33,18 @@
* respectively NA for All or X for Supervisor and no access for User. * respectively NA for All or X for Supervisor and no access for User.
* Then we use the APG to say whether accesses are according to Page rules or * Then we use the APG to say whether accesses are according to Page rules or
* "all Supervisor" rules (Access to all) * "all Supervisor" rules (Access to all)
* Therefore, we define 2 APG groups. lsb is _PMD_USER * _PAGE_ACCESSED is also managed via APG. When _PAGE_ACCESSED is not set, say
* 0 => Kernel => 01 (all accesses performed according to page definition) * "all User" rules, that will lead to NA for all.
* 1 => User => 00 (all accesses performed as supervisor iaw page definition) * Therefore, we define 4 APG groups. lsb is _PAGE_ACCESSED
* 2-15 => Not Used * 0 => Kernel => 11 (all accesses performed according as user iaw page definition)
*/ * 1 => Kernel+Accessed => 01 (all accesses performed according to page definition)
#define MI_APG_INIT 0x40000000 * 2 => User => 11 (all accesses performed according as user iaw page definition)
* 3 => User+Accessed => 00 (all accesses performed as supervisor iaw page definition) for INIT
/* * => 10 (all accesses performed according to swaped page definition) for KUEP
* 0 => Kernel => 01 (all accesses performed according to page definition) * 4-15 => Not Used
* 1 => User => 10 (all accesses performed according to swaped page definition) */
* 2-15 => Not Used #define MI_APG_INIT 0xdc000000
*/ #define MI_APG_KUEP 0xde000000
#define MI_APG_KUEP 0x60000000
/* The effective page number register. When read, contains the information /* The effective page number register. When read, contains the information
* about the last instruction TLB miss. When MI_RPN is written, bits in * about the last instruction TLB miss. When MI_RPN is written, bits in
...@@ -106,25 +105,9 @@ ...@@ -106,25 +105,9 @@
#define MD_Ks 0x80000000 /* Should not be set */ #define MD_Ks 0x80000000 /* Should not be set */
#define MD_Kp 0x40000000 /* Should always be set */ #define MD_Kp 0x40000000 /* Should always be set */
/* /* See explanation above at the definition of MI_APG_INIT */
* All pages' PP data bits are set to either 000 or 011 or 001, which means #define MD_APG_INIT 0xdc000000
* respectively RW for Supervisor and no access for User, or RO for #define MD_APG_KUAP 0xde000000
* Supervisor and no access for user and NA for ALL.
* Then we use the APG to say whether accesses are according to Page rules or
* "all Supervisor" rules (Access to all)
* Therefore, we define 2 APG groups. lsb is _PMD_USER
* 0 => Kernel => 01 (all accesses performed according to page definition)
* 1 => User => 00 (all accesses performed as supervisor iaw page definition)
* 2-15 => Not Used
*/
#define MD_APG_INIT 0x40000000
/*
* 0 => No user => 01 (all accesses performed according to page definition)
* 1 => User => 10 (all accesses performed according to swaped page definition)
* 2-15 => Not Used
*/
#define MD_APG_KUAP 0x60000000
/* The effective page number register. When read, contains the information /* The effective page number register. When read, contains the information
* about the last instruction TLB miss. When MD_RPN is written, bits in * about the last instruction TLB miss. When MD_RPN is written, bits in
......
...@@ -39,9 +39,9 @@ ...@@ -39,9 +39,9 @@
* into the TLB. * into the TLB.
*/ */
#define _PAGE_GUARDED 0x0010 /* Copied to L1 G entry in DTLB */ #define _PAGE_GUARDED 0x0010 /* Copied to L1 G entry in DTLB */
#define _PAGE_SPECIAL 0x0020 /* SW entry */ #define _PAGE_ACCESSED 0x0020 /* Copied to L1 APG 1 entry in I/DTLB */
#define _PAGE_EXEC 0x0040 /* Copied to PP (bit 21) in ITLB */ #define _PAGE_EXEC 0x0040 /* Copied to PP (bit 21) in ITLB */
#define _PAGE_ACCESSED 0x0080 /* software: page referenced */ #define _PAGE_SPECIAL 0x0080 /* SW entry */
#define _PAGE_NA 0x0200 /* Supervisor NA, User no access */ #define _PAGE_NA 0x0200 /* Supervisor NA, User no access */
#define _PAGE_RO 0x0600 /* Supervisor RO, User no access */ #define _PAGE_RO 0x0600 /* Supervisor RO, User no access */
...@@ -59,11 +59,12 @@ ...@@ -59,11 +59,12 @@
#define _PMD_PRESENT 0x0001 #define _PMD_PRESENT 0x0001
#define _PMD_PRESENT_MASK _PMD_PRESENT #define _PMD_PRESENT_MASK _PMD_PRESENT
#define _PMD_BAD 0x0fd0 #define _PMD_BAD 0x0f90
#define _PMD_PAGE_MASK 0x000c #define _PMD_PAGE_MASK 0x000c
#define _PMD_PAGE_8M 0x000c #define _PMD_PAGE_8M 0x000c
#define _PMD_PAGE_512K 0x0004 #define _PMD_PAGE_512K 0x0004
#define _PMD_USER 0x0020 /* APG 1 */ #define _PMD_ACCESSED 0x0020 /* APG 1 */
#define _PMD_USER 0x0040 /* APG 2 */
#define _PTE_NONE_MASK 0 #define _PTE_NONE_MASK 0
......
...@@ -222,23 +222,13 @@ InstructionTLBMiss: ...@@ -222,23 +222,13 @@ InstructionTLBMiss:
3: 3:
mtcr r11 mtcr r11
#endif #endif
#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT)
lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */ lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */
mtspr SPRN_MD_TWC, r11 mtspr SPRN_MD_TWC, r11
#else
lwz r10, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */
mtspr SPRN_MI_TWC, r10 /* Set segment attributes */
mtspr SPRN_MD_TWC, r10
#endif
mfspr r10, SPRN_MD_TWC mfspr r10, SPRN_MD_TWC
lwz r10, 0(r10) /* Get the pte */ lwz r10, 0(r10) /* Get the pte */
#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT) rlwimi r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
mtspr SPRN_MI_TWC, r11 mtspr SPRN_MI_TWC, r11
#endif
rlwinm r11, r10, 32-7, _PAGE_PRESENT
and r11, r11, r10
rlwimi r10, r11, 0, _PAGE_PRESENT
/* The Linux PTE won't go exactly into the MMU TLB. /* The Linux PTE won't go exactly into the MMU TLB.
* Software indicator bits 20 and 23 must be clear. * Software indicator bits 20 and 23 must be clear.
* Software indicator bits 22, 24, 25, 26, and 27 must be * Software indicator bits 22, 24, 25, 26, and 27 must be
...@@ -289,28 +279,16 @@ DataStoreTLBMiss: ...@@ -289,28 +279,16 @@ DataStoreTLBMiss:
mfspr r10, SPRN_MD_TWC mfspr r10, SPRN_MD_TWC
lwz r10, 0(r10) /* Get the pte */ lwz r10, 0(r10) /* Get the pte */
/* Insert the Guarded flag into the TWC from the Linux PTE. /* Insert Guarded and Accessed flags into the TWC from the Linux PTE.
* It is bit 27 of both the Linux PTE and the TWC (at least * It is bit 27 of both the Linux PTE and the TWC (at least
* I got that right :-). It will be better when we can put * I got that right :-). It will be better when we can put
* this into the Linux pgd/pmd and load it in the operation * this into the Linux pgd/pmd and load it in the operation
* above. * above.
*/ */
rlwimi r11, r10, 0, _PAGE_GUARDED rlwimi r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
mtspr SPRN_MD_TWC, r11 mtspr SPRN_MD_TWC, r11
/* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
* We also need to know if the insn is a load/store, so:
* Clear _PAGE_PRESENT and load that which will
* trap into DTLB Error with store bit set accordinly.
*/
/* PRESENT=0x1, ACCESSED=0x20
* r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
* r10 = (r10 & ~PRESENT) | r11;
*/
rlwinm r11, r10, 32-7, _PAGE_PRESENT
and r11, r11, r10
rlwimi r10, r11, 0, _PAGE_PRESENT
/* The Linux PTE won't go exactly into the MMU TLB. /* The Linux PTE won't go exactly into the MMU TLB.
* Software indicator bits 24, 25, 26, and 27 must be * Software indicator bits 24, 25, 26, and 27 must be
* set. All other Linux PTE bits control the behavior * set. All other Linux PTE bits control the behavior
...@@ -701,7 +679,7 @@ initial_mmu: ...@@ -701,7 +679,7 @@ initial_mmu:
li r9, 4 /* up to 4 pages of 8M */ li r9, 4 /* up to 4 pages of 8M */
mtctr r9 mtctr r9
lis r9, KERNELBASE@h /* Create vaddr for TLB */ lis r9, KERNELBASE@h /* Create vaddr for TLB */
li r10, MI_PS8MEG | MI_SVALID /* Set 8M byte page */ li r10, MI_PS8MEG | _PMD_ACCESSED | MI_SVALID
li r11, MI_BOOTINIT /* Create RPN for address 0 */ li r11, MI_BOOTINIT /* Create RPN for address 0 */
1: 1:
mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */ mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */
...@@ -765,7 +743,7 @@ _GLOBAL(mmu_pin_tlb) ...@@ -765,7 +743,7 @@ _GLOBAL(mmu_pin_tlb)
#ifdef CONFIG_PIN_TLB_TEXT #ifdef CONFIG_PIN_TLB_TEXT
LOAD_REG_IMMEDIATE(r5, 28 << 8) LOAD_REG_IMMEDIATE(r5, 28 << 8)
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET) LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG) LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT) LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
LOAD_REG_ADDR(r9, _sinittext) LOAD_REG_ADDR(r9, _sinittext)
li r0, 4 li r0, 4
...@@ -787,7 +765,7 @@ _GLOBAL(mmu_pin_tlb) ...@@ -787,7 +765,7 @@ _GLOBAL(mmu_pin_tlb)
LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM) LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM)
#ifdef CONFIG_PIN_TLB_DATA #ifdef CONFIG_PIN_TLB_DATA
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET) LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG) LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
#ifdef CONFIG_PIN_TLB_IMMR #ifdef CONFIG_PIN_TLB_IMMR
li r0, 3 li r0, 3
#else #else
...@@ -824,7 +802,7 @@ _GLOBAL(mmu_pin_tlb) ...@@ -824,7 +802,7 @@ _GLOBAL(mmu_pin_tlb)
#endif #endif
#ifdef CONFIG_PIN_TLB_IMMR #ifdef CONFIG_PIN_TLB_IMMR
LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID) LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED) LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED | _PMD_ACCESSED)
mfspr r8, SPRN_IMMR mfspr r8, SPRN_IMMR
rlwinm r8, r8, 0, 0xfff80000 rlwinm r8, r8, 0, 0xfff80000
ori r8, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \ ori r8, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment