diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-06-11 01:37:10 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-06-30 08:30:53 -0400 |
commit | 41743a4e34f0777f51c1cf0675b91508ba143050 (patch) | |
tree | 9e63c8c8d70169e6c8be699167234db33b102a1f | |
parent | ff1f4ee94c3c4480b9cee95da2d19668262636c6 (diff) |
powerpc: Free a PTE bit on ppc64 with 64K pages
This frees a PTE bit when using 64K pages on ppc64. This is done
by getting rid of the separate _PAGE_HASHPTE bit. Instead, we just test
if any of the 16 sub-page bits is set. For non-combo pages (ie. real
64K pages), we set SUB0 and the location encoding in that field.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/mm/hash_low_64.S | 17 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 8 | ||||
-rw-r--r-- | include/asm-powerpc/pgtable-4k.h | 1 | ||||
-rw-r--r-- | include/asm-powerpc/pgtable-64k.h | 17 | ||||
-rw-r--r-- | include/asm-powerpc/pgtable-ppc64.h | 1 |
5 files changed, 31 insertions, 13 deletions
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index 70f4c833fa32..a719f53921a5 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S | |||
@@ -388,7 +388,7 @@ _GLOBAL(__hash_page_4K) | |||
388 | */ | 388 | */ |
389 | rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ | 389 | rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ |
390 | or r30,r30,r31 | 390 | or r30,r30,r31 |
391 | ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE | 391 | ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED |
392 | oris r30,r30,_PAGE_COMBO@h | 392 | oris r30,r30,_PAGE_COMBO@h |
393 | /* Write the linux PTE atomically (setting busy) */ | 393 | /* Write the linux PTE atomically (setting busy) */ |
394 | stdcx. r30,0,r6 | 394 | stdcx. r30,0,r6 |
@@ -468,7 +468,7 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) | |||
468 | * go to out-of-line code to try to modify the HPTE. We look for | 468 | * go to out-of-line code to try to modify the HPTE. We look for |
469 | * the bit at (1 >> (index + 32)) | 469 | * the bit at (1 >> (index + 32)) |
470 | */ | 470 | */ |
471 | andi. r0,r31,_PAGE_HASHPTE | 471 | rldicl. r0,r31,64-12,48 |
472 | li r26,0 /* Default hidx */ | 472 | li r26,0 /* Default hidx */ |
473 | beq htab_insert_pte | 473 | beq htab_insert_pte |
474 | 474 | ||
@@ -726,11 +726,11 @@ BEGIN_FTR_SECTION | |||
726 | bne- ht64_bail_ok | 726 | bne- ht64_bail_ok |
727 | END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE) | 727 | END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE) |
728 | /* Prepare new PTE value (turn access RW into DIRTY, then | 728 | /* Prepare new PTE value (turn access RW into DIRTY, then |
729 | * add BUSY,HASHPTE and ACCESSED) | 729 | * add BUSY and ACCESSED) |
730 | */ | 730 | */ |
731 | rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ | 731 | rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ |
732 | or r30,r30,r31 | 732 | or r30,r30,r31 |
733 | ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE | 733 | ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED |
734 | /* Write the linux PTE atomically (setting busy) */ | 734 | /* Write the linux PTE atomically (setting busy) */ |
735 | stdcx. r30,0,r6 | 735 | stdcx. r30,0,r6 |
736 | bne- 1b | 736 | bne- 1b |
@@ -798,18 +798,21 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) | |||
798 | /* Check if we may already be in the hashtable, in this case, we | 798 | /* Check if we may already be in the hashtable, in this case, we |
799 | * go to out-of-line code to try to modify the HPTE | 799 | * go to out-of-line code to try to modify the HPTE |
800 | */ | 800 | */ |
801 | andi. r0,r31,_PAGE_HASHPTE | 801 | rldicl. r0,r31,64-12,48 |
802 | bne ht64_modify_pte | 802 | bne ht64_modify_pte |
803 | 803 | ||
804 | ht64_insert_pte: | 804 | ht64_insert_pte: |
805 | /* Clear hpte bits in new pte (we also clear BUSY btw) and | 805 | /* Clear hpte bits in new pte (we also clear BUSY btw) and |
806 | * add _PAGE_HASHPTE | 806 | * add _PAGE_HPTE_SUB0 |
807 | */ | 807 | */ |
808 | lis r0,_PAGE_HPTEFLAGS@h | 808 | lis r0,_PAGE_HPTEFLAGS@h |
809 | ori r0,r0,_PAGE_HPTEFLAGS@l | 809 | ori r0,r0,_PAGE_HPTEFLAGS@l |
810 | andc r30,r30,r0 | 810 | andc r30,r30,r0 |
811 | #ifdef CONFIG_PPC_64K_PAGES | ||
812 | oris r30,r30,_PAGE_HPTE_SUB0@h | ||
813 | #else | ||
811 | ori r30,r30,_PAGE_HASHPTE | 814 | ori r30,r30,_PAGE_HASHPTE |
812 | 815 | #endif | |
813 | /* Phyical address in r5 */ | 816 | /* Phyical address in r5 */ |
814 | rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT | 817 | rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT |
815 | sldi r5,r5,PAGE_SHIFT | 818 | sldi r5,r5,PAGE_SHIFT |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index a02266dad215..8fa07f3f6c2b 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -458,8 +458,7 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, | |||
458 | old_pte = pte_val(*ptep); | 458 | old_pte = pte_val(*ptep); |
459 | if (old_pte & _PAGE_BUSY) | 459 | if (old_pte & _PAGE_BUSY) |
460 | goto out; | 460 | goto out; |
461 | new_pte = old_pte | _PAGE_BUSY | | 461 | new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED; |
462 | _PAGE_ACCESSED | _PAGE_HASHPTE; | ||
463 | } while(old_pte != __cmpxchg_u64((unsigned long *)ptep, | 462 | } while(old_pte != __cmpxchg_u64((unsigned long *)ptep, |
464 | old_pte, new_pte)); | 463 | old_pte, new_pte)); |
465 | 464 | ||
@@ -499,8 +498,11 @@ repeat: | |||
499 | HPTES_PER_GROUP) & ~0x7UL; | 498 | HPTES_PER_GROUP) & ~0x7UL; |
500 | 499 | ||
501 | /* clear HPTE slot informations in new PTE */ | 500 | /* clear HPTE slot informations in new PTE */ |
501 | #ifdef CONFIG_PPC_64K_PAGES | ||
502 | new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HPTE_SUB0; | ||
503 | #else | ||
502 | new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; | 504 | new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; |
503 | 505 | #endif | |
504 | /* Add in WIMG bits */ | 506 | /* Add in WIMG bits */ |
505 | /* XXX We should store these in the pte */ | 507 | /* XXX We should store these in the pte */ |
506 | /* --BenH: I think they are ... */ | 508 | /* --BenH: I think they are ... */ |
diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h index 818e2abc81e2..fd2090dc1dce 100644 --- a/include/asm-powerpc/pgtable-4k.h +++ b/include/asm-powerpc/pgtable-4k.h | |||
@@ -41,6 +41,7 @@ | |||
41 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | 41 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) |
42 | 42 | ||
43 | /* PTE bits */ | 43 | /* PTE bits */ |
44 | #define _PAGE_HASHPTE 0x0400 /* software: pte has an associated HPTE */ | ||
44 | #define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */ | 45 | #define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */ |
45 | #define _PAGE_GROUP_IX 0x7000 /* software: HPTE index within group */ | 46 | #define _PAGE_GROUP_IX 0x7000 /* software: HPTE index within group */ |
46 | #define _PAGE_F_SECOND _PAGE_SECONDARY | 47 | #define _PAGE_F_SECOND _PAGE_SECONDARY |
diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h index 1cbd6b377eea..c5007712473f 100644 --- a/include/asm-powerpc/pgtable-64k.h +++ b/include/asm-powerpc/pgtable-64k.h | |||
@@ -75,6 +75,20 @@ static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd) | |||
75 | #define _PAGE_COMBO 0x10000000 /* this is a combo 4k page */ | 75 | #define _PAGE_COMBO 0x10000000 /* this is a combo 4k page */ |
76 | #define _PAGE_4K_PFN 0x20000000 /* PFN is for a single 4k page */ | 76 | #define _PAGE_4K_PFN 0x20000000 /* PFN is for a single 4k page */ |
77 | 77 | ||
78 | /* For 64K page, we don't have a separate _PAGE_HASHPTE bit. Instead, | ||
79 | * we set that to be the whole sub-bits mask. The C code will only | ||
80 | * test this, so a multi-bit mask will work. For combo pages, this | ||
81 | * is equivalent as effectively, the old _PAGE_HASHPTE was an OR of | ||
82 | * all the sub bits. For real 64k pages, we now have the assembly set | ||
83 | * _PAGE_HPTE_SUB0 in addition to setting the HIDX bits which overlap | ||
84 | * that mask. This is fine as long as the HIDX bits are never set on | ||
85 | * a PTE that isn't hashed, which is the case today. | ||
86 | * | ||
87 | * A little nit is for the huge page C code, which does the hashing | ||
88 | * in C, we need to provide which bit to use. | ||
89 | */ | ||
90 | #define _PAGE_HASHPTE _PAGE_HPTE_SUB | ||
91 | |||
78 | /* Note the full page bits must be in the same location as for normal | 92 | /* Note the full page bits must be in the same location as for normal |
79 | * 4k pages as the same asssembly will be used to insert 64K pages | 93 | * 4k pages as the same asssembly will be used to insert 64K pages |
80 | * wether the kernel has CONFIG_PPC_64K_PAGES or not | 94 | * wether the kernel has CONFIG_PPC_64K_PAGES or not |
@@ -83,8 +97,7 @@ static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd) | |||
83 | #define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */ | 97 | #define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */ |
84 | 98 | ||
85 | /* PTE flags to conserve for HPTE identification */ | 99 | /* PTE flags to conserve for HPTE identification */ |
86 | #define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_HPTE_SUB |\ | 100 | #define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_COMBO) |
87 | _PAGE_COMBO) | ||
88 | 101 | ||
89 | /* Shift to put page number into pte. | 102 | /* Shift to put page number into pte. |
90 | * | 103 | * |
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h index cc6a43ba41d0..2e48be841cc9 100644 --- a/include/asm-powerpc/pgtable-ppc64.h +++ b/include/asm-powerpc/pgtable-ppc64.h | |||
@@ -91,7 +91,6 @@ | |||
91 | #define _PAGE_DIRTY 0x0080 /* C: page changed */ | 91 | #define _PAGE_DIRTY 0x0080 /* C: page changed */ |
92 | #define _PAGE_ACCESSED 0x0100 /* R: page referenced */ | 92 | #define _PAGE_ACCESSED 0x0100 /* R: page referenced */ |
93 | #define _PAGE_RW 0x0200 /* software: user write access allowed */ | 93 | #define _PAGE_RW 0x0200 /* software: user write access allowed */ |
94 | #define _PAGE_HASHPTE 0x0400 /* software: pte has an associated HPTE */ | ||
95 | #define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */ | 94 | #define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */ |
96 | 95 | ||
97 | #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT) | 96 | #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT) |