Skip to content

Commit de0f938

Browse files
chleroympe
authored andcommitted
powerpc/8xx: Remove _PAGE_USER and handle user access at PMD level
As Linux kernel separates KERNEL and USER address spaces, there is therefore no need to flag USER access at page level. Today, the 8xx TLB handlers already handle user access in the L1 entry through Access Protection Groups, it is then natural to move the user access handling at PMD level once _PAGE_NA allows to handle PAGE_NONE protection without _PAGE_USER In the mean time, as we free up one bit in the PTE, we can use it to include SPS (page size flag) in the PTE and avoid handling it at every TLB miss hence removing special handling based on compiled page size. For _PAGE_EXEC, we rework it to use PP PTE bits, avoiding the copy of _PAGE_EXEC bit into the L1 entry. Unfortunatly we are not able to put it at the correct location as it conflicts with NA/RO/RW bits for data entries. Upper bits of APG in L1 entry overlap with PMD base address. In order to avoid having to filter that out, we set up all groups so that upper bits can have any value. Signed-off-by: Christophe Leroy <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 3517503 commit de0f938

File tree

8 files changed

+48
-62
lines changed

8 files changed

+48
-62
lines changed

arch/powerpc/include/asm/hugetlb.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ static inline pte_t *hugepd_page(hugepd_t hpd)
4747
{
4848
BUG_ON(!hugepd_ok(hpd));
4949
#ifdef CONFIG_PPC_8xx
50-
return (pte_t *)__va(hpd_val(hpd) &
51-
~(_PMD_PAGE_MASK | _PMD_PRESENT_MASK));
50+
return (pte_t *)__va(hpd_val(hpd) & ~HUGEPD_SHIFT_MASK);
5251
#else
5352
return (pte_t *)((hpd_val(hpd) &
5453
~HUGEPD_SHIFT_MASK) | PD_HUGE);

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

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@
2929
#define MI_Kp 0x40000000 /* Should always be set */
3030

3131
/*
32-
* All pages' PP exec bits are set to 000, which means Execute for Supervisor
33-
* and no Execute for User.
34-
* Then we use the APG to say whether accesses are according to Page rules,
35-
* "all Supervisor" rules (Exec for all) and "all User" rules (Exec for noone)
36-
* Therefore, we define 4 APG groups. msb is _PAGE_EXEC, lsb is _PAGE_USER
37-
* 0 (00) => Not User, no exec => 11 (all accesses performed as user)
38-
* 1 (01) => User but no exec => 11 (all accesses performed as user)
39-
* 2 (10) => Not User, exec => 01 (rights according to page definition)
40-
* 3 (11) => User, exec => 00 (all accesses performed as supervisor)
41-
*/
42-
#define MI_APG_INIT 0xf4ffffff
32+
* All pages' PP data bits are set to either 001 or 011 by copying _PAGE_EXEC
33+
* into bit 21 in the ITLBmiss handler (bit 21 is the middle bit), which means
34+
* respectively NA for All or X for Supervisor and no access for User.
35+
* Then we use the APG to say whether accesses are according to Page rules or
36+
* "all Supervisor" rules (Access to all)
37+
* Therefore, we define 2 APG groups. lsb is _PMD_USER
38+
* 0 => No user => 01 (all accesses performed according to page definition)
39+
* 1 => User => 00 (all accesses performed as supervisor iaw page definition)
40+
* We define all 16 groups so that all other bits of APG can take any value
41+
*/
42+
#define MI_APG_INIT 0x44444444
4343

4444
/* The effective page number register. When read, contains the information
4545
* about the last instruction TLB miss. When MI_RPN is written, bits in
@@ -102,17 +102,17 @@
102102
#define MD_Kp 0x40000000 /* Should always be set */
103103

104104
/*
105-
* All pages' PP data bits are set to either 000 or 011, which means
105+
* All pages' PP data bits are set to either 000 or 011 or 001, which means
106106
* respectively RW for Supervisor and no access for User, or RO for
107-
* Supervisor and no access for user.
107+
* Supervisor and no access for user and NA for ALL.
108108
* Then we use the APG to say whether accesses are according to Page rules or
109109
* "all Supervisor" rules (Access to all)
110-
* Therefore, we define 2 APG groups. lsb is _PAGE_USER
110+
* Therefore, we define 2 APG groups. lsb is _PMD_USER
111111
* 0 => No user => 01 (all accesses performed according to page definition)
112-
* 1 => User => 00 (all accesses performed as supervisor
113-
* according to page definition)
112+
* 1 => User => 00 (all accesses performed as supervisor iaw page definition)
113+
* We define all 16 groups so that all other bits of APG can take any value
114114
*/
115-
#define MD_APG_INIT 0x4fffffff
115+
#define MD_APG_INIT 0x44444444
116116

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

arch/powerpc/include/asm/nohash/32/pgalloc.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp,
6161
static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp,
6262
pgtable_t pte_page)
6363
{
64-
*pmdp = __pmd((page_to_pfn(pte_page) << PAGE_SHIFT) | _PMD_PRESENT);
64+
*pmdp = __pmd((page_to_pfn(pte_page) << PAGE_SHIFT) | _PMD_USER |
65+
_PMD_PRESENT);
6566
}
6667

6768
#define pmd_pgtable(pmd) pmd_page(pmd)

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,33 @@
3232
#define _PAGE_PRESENT 0x0001 /* Page is valid */
3333
#define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */
3434
#define _PAGE_PRIVILEGED 0x0004 /* No ASID (context) compare */
35-
#define _PAGE_SPECIAL 0x0008 /* SW entry, forced to 0 by the TLB miss */
35+
#define _PAGE_HUGE 0x0008 /* SPS: Small Page Size (1 if 16k, 512k or 8M)*/
3636
#define _PAGE_DIRTY 0x0100 /* C: page changed */
3737

3838
/* These 4 software bits must be masked out when the L2 entry is loaded
3939
* into the TLB.
4040
*/
4141
#define _PAGE_GUARDED 0x0010 /* Copied to L1 G entry in DTLB */
42-
#define _PAGE_USER 0x0020 /* Copied to L1 APG lsb */
43-
#define _PAGE_EXEC 0x0040 /* Copied to L1 APG */
42+
#define _PAGE_SPECIAL 0x0020 /* SW entry */
43+
#define _PAGE_EXEC 0x0040 /* Copied to PP (bit 21) in ITLB */
4444
#define _PAGE_ACCESSED 0x0080 /* software: page referenced */
4545

46+
#define _PAGE_NA 0x0200 /* Supervisor NA, User no access */
4647
#define _PAGE_RO 0x0600 /* Supervisor RO, User no access */
4748

4849
#define _PMD_PRESENT 0x0001
49-
#define _PMD_BAD 0x0ff0
50+
#define _PMD_BAD 0x0fd0
5051
#define _PMD_PAGE_MASK 0x000c
5152
#define _PMD_PAGE_8M 0x000c
5253
#define _PMD_PAGE_512K 0x0004
54+
#define _PMD_USER 0x0020 /* APG 1 */
5355

5456
/* Until my rework is finished, 8xx still needs atomic PTE updates */
5557
#define PTE_ATOMIC_UPDATES 1
5658

59+
#ifdef CONFIG_PPC_16K_PAGES
60+
#define _PAGE_PSIZE _PAGE_HUGE
61+
#endif
62+
5763
#endif /* __KERNEL__ */
5864
#endif /* _ASM_POWERPC_NOHASH_32_PTE_8xx_H */

arch/powerpc/include/asm/nohash/pgtable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ static inline pte_t pte_mkspecial(pte_t pte)
126126

127127
static inline pte_t pte_mkhuge(pte_t pte)
128128
{
129-
return pte;
129+
return __pte(pte_val(pte) | _PAGE_HUGE);
130130
}
131131

132132
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)

arch/powerpc/include/asm/pte-common.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
#ifndef _PAGE_NA
5454
#define _PAGE_NA 0
5555
#endif
56+
#ifndef _PAGE_HUGE
57+
#define _PAGE_HUGE 0
58+
#endif
5659

5760
#ifndef _PMD_PRESENT_MASK
5861
#define _PMD_PRESENT_MASK _PMD_PRESENT
@@ -61,6 +64,9 @@
6164
#define _PMD_SIZE 0
6265
#define PMD_PAGE_SIZE(pmd) bad_call_to_PMD_PAGE_SIZE()
6366
#endif
67+
#ifndef _PMD_USER
68+
#define _PMD_USER 0
69+
#endif
6470
#ifndef _PAGE_KERNEL_RO
6571
#define _PAGE_KERNEL_RO (_PAGE_PRIVILEGED | _PAGE_RO)
6672
#endif

arch/powerpc/kernel/head_8xx.S

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,7 @@
5252
* Value for the bits that have fixed value in RPN entries.
5353
* Also used for tagging DAR for DTLBerror.
5454
*/
55-
#ifdef CONFIG_PPC_16K_PAGES
56-
#define RPN_PATTERN (0x00f0 | MD_SPS16K)
57-
#else
5855
#define RPN_PATTERN 0x00f0
59-
#endif
6056

6157
#define PAGE_SHIFT_512K 19
6258
#define PAGE_SHIFT_8M 23
@@ -358,31 +354,23 @@ _ENTRY(ITLBMiss_cmp)
358354
#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_HUGETLB_PAGE)
359355
mtcr r12
360356
#endif
361-
/* Insert the APG into the TWC from the Linux PTE. */
362-
rlwimi r11, r10, 0, 25, 26
363357
/* Load the MI_TWC with the attributes for this "segment." */
364358
mtspr SPRN_MI_TWC, r11 /* Set segment attributes */
365359

366-
#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
367-
rlwimi r10, r11, 1, MI_SPS16K
368-
#endif
369360
#ifdef CONFIG_SWAP
370361
rlwinm r11, r10, 32-5, _PAGE_PRESENT
371362
and r11, r11, r10
372363
rlwimi r10, r11, 0, _PAGE_PRESENT
373364
#endif
374-
li r11, RPN_PATTERN
365+
li r11, RPN_PATTERN | 0x200
375366
/* The Linux PTE won't go exactly into the MMU TLB.
376-
* Software indicator bits 20-23 and 28 must be clear.
377-
* Software indicator bits 24, 25, 26, and 27 must be
367+
* Software indicator bits 20 and 23 must be clear.
368+
* Software indicator bits 22, 24, 25, 26, and 27 must be
378369
* set. All other Linux PTE bits control the behavior
379370
* of the MMU.
380371
*/
381-
#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
382-
rlwimi r10, r11, 0, 0x0ff0 /* Set 24-27, clear 20-23 */
383-
#else
384-
rlwimi r10, r11, 0, 0x0ff8 /* Set 24-27, clear 20-23,28 */
385-
#endif
372+
rlwimi r11, r10, 4, 0x0400 /* Copy _PAGE_EXEC into bit 21 */
373+
rlwimi r10, r11, 0, 0x0ff0 /* Set 22, 24-27, clear 20,23 */
386374
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
387375

388376
/* Restore registers */
@@ -419,7 +407,6 @@ _ENTRY(itlb_miss_perf)
419407
rlwinm r10, r11, 0, ~HUGEPD_SHIFT_MASK
420408
#endif
421409
lwz r10, 0(r10) /* Get the pte */
422-
rlwinm r11, r11, 0, 0xf
423410
b 4b
424411

425412
20: /* 512k pages */
@@ -428,7 +415,6 @@ _ENTRY(itlb_miss_perf)
428415
/* Add level 2 base */
429416
rlwimi r10, r11, 0, 0, 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1) - 1
430417
lwz r10, 0(r10) /* Get the pte */
431-
rlwinm r11, r11, 0, 0xf
432418
b 4b
433419
#endif
434420

@@ -479,20 +465,15 @@ _ENTRY(DTLBMiss_jmp)
479465
4:
480466
mtcr r12
481467

482-
/* Insert the Guarded flag and APG into the TWC from the Linux PTE.
483-
* It is bit 26-27 of both the Linux PTE and the TWC (at least
468+
/* Insert the Guarded flag into the TWC from the Linux PTE.
469+
* It is bit 27 of both the Linux PTE and the TWC (at least
484470
* I got that right :-). It will be better when we can put
485471
* this into the Linux pgd/pmd and load it in the operation
486472
* above.
487473
*/
488-
rlwimi r11, r10, 0, 26, 27
474+
rlwimi r11, r10, 0, _PAGE_GUARDED
489475
mtspr SPRN_MD_TWC, r11
490476

491-
/* In 4k pages mode, SPS (bit 28) in RPN must match PS[1] (bit 29)
492-
* In 16k pages mode, SPS is always 1 */
493-
#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
494-
rlwimi r10, r11, 1, MD_SPS16K
495-
#endif
496477
/* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
497478
* We also need to know if the insn is a load/store, so:
498479
* Clear _PAGE_PRESENT and load that which will
@@ -508,17 +489,12 @@ _ENTRY(DTLBMiss_jmp)
508489
rlwimi r10, r11, 0, _PAGE_PRESENT
509490
#endif
510491
/* The Linux PTE won't go exactly into the MMU TLB.
511-
* Software indicator bits 22 and 28 must be clear.
512492
* Software indicator bits 24, 25, 26, and 27 must be
513493
* set. All other Linux PTE bits control the behavior
514494
* of the MMU.
515495
*/
516496
li r11, RPN_PATTERN
517-
#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
518497
rlwimi r10, r11, 0, 24, 27 /* Set 24-27 */
519-
#else
520-
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
521-
#endif
522498
mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
523499

524500
/* Restore registers */
@@ -552,7 +528,6 @@ _ENTRY(dtlb_miss_perf)
552528
rlwinm r10, r11, 0, ~HUGEPD_SHIFT_MASK
553529
#endif
554530
lwz r10, 0(r10) /* Get the pte */
555-
rlwinm r11, r11, 0, 0xf
556531
b 4b
557532

558533
20: /* 512k pages */
@@ -561,7 +536,6 @@ _ENTRY(dtlb_miss_perf)
561536
/* Add level 2 base */
562537
rlwimi r10, r11, 0, 0, 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1) - 1
563538
lwz r10, 0(r10) /* Get the pte */
564-
rlwinm r11, r11, 0, 0xf
565539
b 4b
566540
#endif
567541

@@ -712,7 +686,7 @@ _ENTRY(dtlb_miss_exit_3)
712686
ITLBMissLinear:
713687
mtcr r12
714688
/* Set 8M byte page and mark it valid */
715-
li r11, MI_PS8MEG | MI_SVALID | _PAGE_EXEC
689+
li r11, MI_PS8MEG | MI_SVALID
716690
mtspr SPRN_MI_TWC, r11
717691
rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */
718692
ori r10, r10, 0xf0 | MI_SPS16K | _PAGE_PRIVILEGED | _PAGE_DIRTY | \
@@ -994,7 +968,7 @@ initial_mmu:
994968
lis r8, KERNELBASE@h /* Create vaddr for TLB */
995969
ori r8, r8, MI_EVALID /* Mark it valid */
996970
mtspr SPRN_MI_EPN, r8
997-
li r8, MI_PS8MEG | (2 << 5) /* Set 8M byte page, APG 2 */
971+
li r8, MI_PS8MEG /* Set 8M byte page */
998972
ori r8, r8, MI_SVALID /* Make it valid */
999973
mtspr SPRN_MI_TWC, r8
1000974
li r8, MI_BOOTINIT /* Create RPN for address 0 */

arch/powerpc/mm/hugetlbpage.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
9696
*hpdp = __hugepd(__pa(new) |
9797
(shift_to_mmu_psize(pshift) << 2));
9898
#elif defined(CONFIG_PPC_8xx)
99-
*hpdp = __hugepd(__pa(new) |
99+
*hpdp = __hugepd(__pa(new) | _PMD_USER |
100100
(pshift == PAGE_SHIFT_8M ? _PMD_PAGE_8M :
101101
_PMD_PAGE_512K) | _PMD_PRESENT);
102102
#else

0 commit comments

Comments
 (0)