Skip to content

Commit 33fe43c

Browse files
chleroympe
authored andcommitted
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: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/80f488db230c6b0e7b3b990d72bd94a8a069e93e.1602492856.git.christophe.leroy@csgroup.eu
1 parent 29daf86 commit 33fe43c

4 files changed

Lines changed: 28 additions & 66 deletions

File tree

arch/powerpc/include/asm/nohash/32/kup-8xx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static inline void restore_user_access(unsigned long flags)
6363
static inline bool
6464
bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
6565
{
66-
return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xf0000000),
66+
return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xff000000),
6767
"Bug: fault blocked by AP register !");
6868
}
6969

arch/powerpc/include/asm/nohash/32/mmu-8xx.h

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,18 @@
3333
* respectively NA for All or X for Supervisor and no access for User.
3434
* Then we use the APG to say whether accesses are according to Page rules or
3535
* "all Supervisor" rules (Access to all)
36-
* Therefore, we define 2 APG groups. lsb is _PMD_USER
37-
* 0 => Kernel => 01 (all accesses performed according to page definition)
38-
* 1 => User => 00 (all accesses performed as supervisor iaw page definition)
39-
* 2-15 => Not Used
40-
*/
41-
#define MI_APG_INIT 0x40000000
42-
43-
/*
44-
* 0 => Kernel => 01 (all accesses performed according to page definition)
45-
* 1 => User => 10 (all accesses performed according to swaped page definition)
46-
* 2-15 => Not Used
47-
*/
48-
#define MI_APG_KUEP 0x60000000
36+
* _PAGE_ACCESSED is also managed via APG. When _PAGE_ACCESSED is not set, say
37+
* "all User" rules, that will lead to NA for all.
38+
* Therefore, we define 4 APG groups. lsb is _PAGE_ACCESSED
39+
* 0 => Kernel => 11 (all accesses performed according as user iaw page definition)
40+
* 1 => Kernel+Accessed => 01 (all accesses performed according to page definition)
41+
* 2 => User => 11 (all accesses performed according as user iaw page definition)
42+
* 3 => User+Accessed => 00 (all accesses performed as supervisor iaw page definition) for INIT
43+
* => 10 (all accesses performed according to swaped page definition) for KUEP
44+
* 4-15 => Not Used
45+
*/
46+
#define MI_APG_INIT 0xdc000000
47+
#define MI_APG_KUEP 0xde000000
4948

5049
/* The effective page number register. When read, contains the information
5150
* about the last instruction TLB miss. When MI_RPN is written, bits in
@@ -106,25 +105,9 @@
106105
#define MD_Ks 0x80000000 /* Should not be set */
107106
#define MD_Kp 0x40000000 /* Should always be set */
108107

109-
/*
110-
* All pages' PP data bits are set to either 000 or 011 or 001, which means
111-
* respectively RW for Supervisor and no access for User, or RO for
112-
* Supervisor and no access for user and NA for ALL.
113-
* Then we use the APG to say whether accesses are according to Page rules or
114-
* "all Supervisor" rules (Access to all)
115-
* Therefore, we define 2 APG groups. lsb is _PMD_USER
116-
* 0 => Kernel => 01 (all accesses performed according to page definition)
117-
* 1 => User => 00 (all accesses performed as supervisor iaw page definition)
118-
* 2-15 => Not Used
119-
*/
120-
#define MD_APG_INIT 0x40000000
121-
122-
/*
123-
* 0 => No user => 01 (all accesses performed according to page definition)
124-
* 1 => User => 10 (all accesses performed according to swaped page definition)
125-
* 2-15 => Not Used
126-
*/
127-
#define MD_APG_KUAP 0x60000000
108+
/* See explanation above at the definition of MI_APG_INIT */
109+
#define MD_APG_INIT 0xdc000000
110+
#define MD_APG_KUAP 0xde000000
128111

129112
/* The effective page number register. When read, contains the information
130113
* about the last instruction TLB miss. When MD_RPN is written, bits in

arch/powerpc/include/asm/nohash/32/pte-8xx.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@
3939
* into the TLB.
4040
*/
4141
#define _PAGE_GUARDED 0x0010 /* Copied to L1 G entry in DTLB */
42-
#define _PAGE_SPECIAL 0x0020 /* SW entry */
42+
#define _PAGE_ACCESSED 0x0020 /* Copied to L1 APG 1 entry in I/DTLB */
4343
#define _PAGE_EXEC 0x0040 /* Copied to PP (bit 21) in ITLB */
44-
#define _PAGE_ACCESSED 0x0080 /* software: page referenced */
44+
#define _PAGE_SPECIAL 0x0080 /* SW entry */
4545

4646
#define _PAGE_NA 0x0200 /* Supervisor NA, User no access */
4747
#define _PAGE_RO 0x0600 /* Supervisor RO, User no access */
@@ -59,11 +59,12 @@
5959

6060
#define _PMD_PRESENT 0x0001
6161
#define _PMD_PRESENT_MASK _PMD_PRESENT
62-
#define _PMD_BAD 0x0fd0
62+
#define _PMD_BAD 0x0f90
6363
#define _PMD_PAGE_MASK 0x000c
6464
#define _PMD_PAGE_8M 0x000c
6565
#define _PMD_PAGE_512K 0x0004
66-
#define _PMD_USER 0x0020 /* APG 1 */
66+
#define _PMD_ACCESSED 0x0020 /* APG 1 */
67+
#define _PMD_USER 0x0040 /* APG 2 */
6768

6869
#define _PTE_NONE_MASK 0
6970

arch/powerpc/kernel/head_8xx.S

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -222,23 +222,13 @@ InstructionTLBMiss:
222222
3:
223223
mtcr r11
224224
#endif
225-
#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT)
226225
lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */
227226
mtspr SPRN_MD_TWC, r11
228-
#else
229-
lwz r10, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */
230-
mtspr SPRN_MI_TWC, r10 /* Set segment attributes */
231-
mtspr SPRN_MD_TWC, r10
232-
#endif
233227
mfspr r10, SPRN_MD_TWC
234228
lwz r10, 0(r10) /* Get the pte */
235-
#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT)
229+
rlwimi r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
236230
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
237231
mtspr SPRN_MI_TWC, r11
238-
#endif
239-
rlwinm r11, r10, 32-7, _PAGE_PRESENT
240-
and r11, r11, r10
241-
rlwimi r10, r11, 0, _PAGE_PRESENT
242232
/* The Linux PTE won't go exactly into the MMU TLB.
243233
* Software indicator bits 20 and 23 must be clear.
244234
* Software indicator bits 22, 24, 25, 26, and 27 must be
@@ -289,28 +279,16 @@ DataStoreTLBMiss:
289279
mfspr r10, SPRN_MD_TWC
290280
lwz r10, 0(r10) /* Get the pte */
291281

292-
/* Insert the Guarded flag into the TWC from the Linux PTE.
282+
/* Insert Guarded and Accessed flags into the TWC from the Linux PTE.
293283
* It is bit 27 of both the Linux PTE and the TWC (at least
294284
* I got that right :-). It will be better when we can put
295285
* this into the Linux pgd/pmd and load it in the operation
296286
* above.
297287
*/
298-
rlwimi r11, r10, 0, _PAGE_GUARDED
288+
rlwimi r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
299289
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
300290
mtspr SPRN_MD_TWC, r11
301291

302-
/* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
303-
* We also need to know if the insn is a load/store, so:
304-
* Clear _PAGE_PRESENT and load that which will
305-
* trap into DTLB Error with store bit set accordinly.
306-
*/
307-
/* PRESENT=0x1, ACCESSED=0x20
308-
* r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
309-
* r10 = (r10 & ~PRESENT) | r11;
310-
*/
311-
rlwinm r11, r10, 32-7, _PAGE_PRESENT
312-
and r11, r11, r10
313-
rlwimi r10, r11, 0, _PAGE_PRESENT
314292
/* The Linux PTE won't go exactly into the MMU TLB.
315293
* Software indicator bits 24, 25, 26, and 27 must be
316294
* set. All other Linux PTE bits control the behavior
@@ -701,7 +679,7 @@ initial_mmu:
701679
li r9, 4 /* up to 4 pages of 8M */
702680
mtctr r9
703681
lis r9, KERNELBASE@h /* Create vaddr for TLB */
704-
li r10, MI_PS8MEG | MI_SVALID /* Set 8M byte page */
682+
li r10, MI_PS8MEG | _PMD_ACCESSED | MI_SVALID
705683
li r11, MI_BOOTINIT /* Create RPN for address 0 */
706684
1:
707685
mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */
@@ -765,7 +743,7 @@ _GLOBAL(mmu_pin_tlb)
765743
#ifdef CONFIG_PIN_TLB_TEXT
766744
LOAD_REG_IMMEDIATE(r5, 28 << 8)
767745
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
768-
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG)
746+
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
769747
LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
770748
LOAD_REG_ADDR(r9, _sinittext)
771749
li r0, 4
@@ -787,7 +765,7 @@ _GLOBAL(mmu_pin_tlb)
787765
LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM)
788766
#ifdef CONFIG_PIN_TLB_DATA
789767
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
790-
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG)
768+
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
791769
#ifdef CONFIG_PIN_TLB_IMMR
792770
li r0, 3
793771
#else
@@ -824,7 +802,7 @@ _GLOBAL(mmu_pin_tlb)
824802
#endif
825803
#ifdef CONFIG_PIN_TLB_IMMR
826804
LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
827-
LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED)
805+
LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED | _PMD_ACCESSED)
828806
mfspr r8, SPRN_IMMR
829807
rlwinm r8, r8, 0, 0xfff80000
830808
ori r8, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \

0 commit comments

Comments
 (0)