diff options
author | David S. Miller <davem@davemloft.net> | 2013-09-25 17:33:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-12 18:22:35 -0500 |
commit | 2b77933c28f5044629bb19e8045aae65b72b939d (patch) | |
tree | ecb5e23e19599a77748ec54b116ac59341c25a38 /arch/sparc | |
parent | 37b3a8ff3e086cd5c369e77d2383b691b2874cd6 (diff) |
sparc64: Move to 64-bit PGDs and PMDs.
To make the page tables compact, we were using 32-bit PGDs and PMDs.
We only had to support <= 43 bits of physical addresses so this was
quite feasible.
In order to support larger physical addresses we have to move to
64-bit PGDs and PMDs.
Most of the changes are straight-forward:
1) {pgd,pmd}_t --> unsigned long
2) Anything that tries to use plain "unsigned int" types with pgd/pmd
values needs to be adjusted. In particular things like "0U" become
"0UL".
3) {PGDIR,PMD}_BITS decrease by one.
4) In the assembler page table walkers, use "ldxa" instead of "lduwa"
and adjust the low bit masks to clear out the low 3 bits instead of
just the low 2 bits during pgd/pmd address formation.
Also, use PTRS_PER_PGD and PTRS_PER_PMD in the sizing of the
swapper_{pg_dir,low_pmd_dir} arrays.
This patch does not try to take advantage of having 64-bits in the
PMDs to simplify the hugepage code, that will come in a subsequent
change.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/include/asm/page_64.h | 25 | ||||
-rw-r--r-- | arch/sparc/include/asm/pgtable_64.h | 22 | ||||
-rw-r--r-- | arch/sparc/include/asm/tsb.h | 16 | ||||
-rw-r--r-- | arch/sparc/mm/init_64.c | 2 |
4 files changed, 34 insertions, 31 deletions
diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h index 1958bfbe300c..aac53fcea807 100644 --- a/arch/sparc/include/asm/page_64.h +++ b/arch/sparc/include/asm/page_64.h | |||
@@ -56,8 +56,8 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct pag | |||
56 | /* These are used to make use of C type-checking.. */ | 56 | /* These are used to make use of C type-checking.. */ |
57 | typedef struct { unsigned long pte; } pte_t; | 57 | typedef struct { unsigned long pte; } pte_t; |
58 | typedef struct { unsigned long iopte; } iopte_t; | 58 | typedef struct { unsigned long iopte; } iopte_t; |
59 | typedef struct { unsigned int pmd; } pmd_t; | 59 | typedef struct { unsigned long pmd; } pmd_t; |
60 | typedef struct { unsigned int pgd; } pgd_t; | 60 | typedef struct { unsigned long pgd; } pgd_t; |
61 | typedef struct { unsigned long pgprot; } pgprot_t; | 61 | typedef struct { unsigned long pgprot; } pgprot_t; |
62 | 62 | ||
63 | #define pte_val(x) ((x).pte) | 63 | #define pte_val(x) ((x).pte) |
@@ -76,8 +76,8 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
76 | /* .. while these make it easier on the compiler */ | 76 | /* .. while these make it easier on the compiler */ |
77 | typedef unsigned long pte_t; | 77 | typedef unsigned long pte_t; |
78 | typedef unsigned long iopte_t; | 78 | typedef unsigned long iopte_t; |
79 | typedef unsigned int pmd_t; | 79 | typedef unsigned long pmd_t; |
80 | typedef unsigned int pgd_t; | 80 | typedef unsigned long pgd_t; |
81 | typedef unsigned long pgprot_t; | 81 | typedef unsigned long pgprot_t; |
82 | 82 | ||
83 | #define pte_val(x) (x) | 83 | #define pte_val(x) (x) |
@@ -97,15 +97,18 @@ typedef unsigned long pgprot_t; | |||
97 | typedef pte_t *pgtable_t; | 97 | typedef pte_t *pgtable_t; |
98 | 98 | ||
99 | /* These two values define the virtual address space range in which we | 99 | /* These two values define the virtual address space range in which we |
100 | * must forbid 64-bit user processes from making mappings. It | 100 | * must forbid 64-bit user processes from making mappings. It used to |
101 | * represents the virtual address space hole present in most early | 101 | * represent precisely the virtual address space hole present in most |
102 | * sparc64 chips including UltraSPARC-I. The next two defines specify | 102 | * early sparc64 chips including UltraSPARC-I. But now it also is |
103 | * the actual exclusion region we enforce, wherein we use a 4GB red | 103 | * further constrained by the limits of our page tables, which is |
104 | * zone on each side of the VA hole. | 104 | * 43-bits of virtual address. |
105 | */ | 105 | */ |
106 | #define SPARC64_VA_HOLE_TOP _AC(0xfffff80000000000,UL) | 106 | #define SPARC64_VA_HOLE_TOP _AC(0xfffffc0000000000,UL) |
107 | #define SPARC64_VA_HOLE_BOTTOM _AC(0x0000080000000000,UL) | 107 | #define SPARC64_VA_HOLE_BOTTOM _AC(0x0000040000000000,UL) |
108 | 108 | ||
109 | /* The next two defines specify the actual exclusion region we | ||
110 | * enforce, wherein we use a 4GB red zone on each side of the VA hole. | ||
111 | */ | ||
109 | #define VA_EXCLUDE_START (SPARC64_VA_HOLE_BOTTOM - (1UL << 32UL)) | 112 | #define VA_EXCLUDE_START (SPARC64_VA_HOLE_BOTTOM - (1UL << 32UL)) |
110 | #define VA_EXCLUDE_END (SPARC64_VA_HOLE_TOP + (1UL << 32UL)) | 113 | #define VA_EXCLUDE_END (SPARC64_VA_HOLE_TOP + (1UL << 32UL)) |
111 | 114 | ||
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 012b6eeeb06a..eee803e10b92 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h | |||
@@ -51,15 +51,15 @@ | |||
51 | #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3)) | 51 | #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3)) |
52 | #define PMD_SIZE (_AC(1,UL) << PMD_SHIFT) | 52 | #define PMD_SIZE (_AC(1,UL) << PMD_SHIFT) |
53 | #define PMD_MASK (~(PMD_SIZE-1)) | 53 | #define PMD_MASK (~(PMD_SIZE-1)) |
54 | #define PMD_BITS (PAGE_SHIFT - 2) | 54 | #define PMD_BITS (PAGE_SHIFT - 3) |
55 | 55 | ||
56 | /* PGDIR_SHIFT determines what a third-level page table entry can map */ | 56 | /* PGDIR_SHIFT determines what a third-level page table entry can map */ |
57 | #define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS) | 57 | #define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS) |
58 | #define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT) | 58 | #define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT) |
59 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | 59 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) |
60 | #define PGDIR_BITS (PAGE_SHIFT - 2) | 60 | #define PGDIR_BITS (PAGE_SHIFT - 3) |
61 | 61 | ||
62 | #if (PGDIR_SHIFT + PGDIR_BITS) != 45 | 62 | #if (PGDIR_SHIFT + PGDIR_BITS) != 43 |
63 | #error Page table parameters do not cover virtual address space properly. | 63 | #error Page table parameters do not cover virtual address space properly. |
64 | #endif | 64 | #endif |
65 | 65 | ||
@@ -714,7 +714,7 @@ extern pgprot_t pmd_pgprot(pmd_t entry); | |||
714 | 714 | ||
715 | static inline int pmd_present(pmd_t pmd) | 715 | static inline int pmd_present(pmd_t pmd) |
716 | { | 716 | { |
717 | return pmd_val(pmd) != 0U; | 717 | return pmd_val(pmd) != 0UL; |
718 | } | 718 | } |
719 | 719 | ||
720 | #define pmd_none(pmd) (!pmd_val(pmd)) | 720 | #define pmd_none(pmd) (!pmd_val(pmd)) |
@@ -741,7 +741,7 @@ static inline void pmd_set(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) | |||
741 | (pud_val(*(pudp)) = (__pa((unsigned long) (pmdp)) >> PGD_PADDR_SHIFT)) | 741 | (pud_val(*(pudp)) = (__pa((unsigned long) (pmdp)) >> PGD_PADDR_SHIFT)) |
742 | static inline unsigned long __pmd_page(pmd_t pmd) | 742 | static inline unsigned long __pmd_page(pmd_t pmd) |
743 | { | 743 | { |
744 | unsigned long paddr = (unsigned long) pmd_val(pmd); | 744 | unsigned long paddr = pmd_val(pmd); |
745 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 745 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
746 | if (pmd_val(pmd) & PMD_ISHUGE) | 746 | if (pmd_val(pmd) & PMD_ISHUGE) |
747 | paddr &= PMD_HUGE_PADDR; | 747 | paddr &= PMD_HUGE_PADDR; |
@@ -751,14 +751,14 @@ static inline unsigned long __pmd_page(pmd_t pmd) | |||
751 | } | 751 | } |
752 | #define pmd_page(pmd) virt_to_page((void *)__pmd_page(pmd)) | 752 | #define pmd_page(pmd) virt_to_page((void *)__pmd_page(pmd)) |
753 | #define pud_page_vaddr(pud) \ | 753 | #define pud_page_vaddr(pud) \ |
754 | ((unsigned long) __va((((unsigned long)pud_val(pud))<<PGD_PADDR_SHIFT))) | 754 | ((unsigned long) __va((pud_val(pud)<<PGD_PADDR_SHIFT))) |
755 | #define pud_page(pud) virt_to_page((void *)pud_page_vaddr(pud)) | 755 | #define pud_page(pud) virt_to_page((void *)pud_page_vaddr(pud)) |
756 | #define pmd_bad(pmd) (0) | 756 | #define pmd_bad(pmd) (0) |
757 | #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0U) | 757 | #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL) |
758 | #define pud_none(pud) (!pud_val(pud)) | 758 | #define pud_none(pud) (!pud_val(pud)) |
759 | #define pud_bad(pud) (0) | 759 | #define pud_bad(pud) (0) |
760 | #define pud_present(pud) (pud_val(pud) != 0U) | 760 | #define pud_present(pud) (pud_val(pud) != 0U) |
761 | #define pud_clear(pudp) (pud_val(*(pudp)) = 0U) | 761 | #define pud_clear(pudp) (pud_val(*(pudp)) = 0UL) |
762 | 762 | ||
763 | /* Same in both SUN4V and SUN4U. */ | 763 | /* Same in both SUN4V and SUN4U. */ |
764 | #define pte_none(pte) (!pte_val(pte)) | 764 | #define pte_none(pte) (!pte_val(pte)) |
@@ -793,7 +793,7 @@ static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, | |||
793 | pmd_t *pmdp) | 793 | pmd_t *pmdp) |
794 | { | 794 | { |
795 | pmd_t pmd = *pmdp; | 795 | pmd_t pmd = *pmdp; |
796 | set_pmd_at(mm, addr, pmdp, __pmd(0U)); | 796 | set_pmd_at(mm, addr, pmdp, __pmd(0UL)); |
797 | return pmd; | 797 | return pmd; |
798 | } | 798 | } |
799 | 799 | ||
@@ -841,8 +841,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
841 | }) | 841 | }) |
842 | #endif | 842 | #endif |
843 | 843 | ||
844 | extern pgd_t swapper_pg_dir[2048]; | 844 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
845 | extern pmd_t swapper_low_pmd_dir[2048]; | 845 | extern pmd_t swapper_low_pmd_dir[PTRS_PER_PMD]; |
846 | 846 | ||
847 | extern void paging_init(void); | 847 | extern void paging_init(void); |
848 | extern unsigned long find_ecache_flush_span(unsigned long size); | 848 | extern unsigned long find_ecache_flush_span(unsigned long size); |
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h index 16e577711a7b..cc0432f15817 100644 --- a/arch/sparc/include/asm/tsb.h +++ b/arch/sparc/include/asm/tsb.h | |||
@@ -142,14 +142,14 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; | |||
142 | or REG1, %lo(swapper_pg_dir), REG1; \ | 142 | or REG1, %lo(swapper_pg_dir), REG1; \ |
143 | sllx VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \ | 143 | sllx VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \ |
144 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ | 144 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ |
145 | andn REG2, 0x3, REG2; \ | 145 | andn REG2, 0x7, REG2; \ |
146 | lduw [REG1 + REG2], REG1; \ | 146 | ldx [REG1 + REG2], REG1; \ |
147 | brz,pn REG1, FAIL_LABEL; \ | 147 | brz,pn REG1, FAIL_LABEL; \ |
148 | sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ | 148 | sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ |
149 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ | 149 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ |
150 | sllx REG1, PGD_PADDR_SHIFT, REG1; \ | 150 | sllx REG1, PGD_PADDR_SHIFT, REG1; \ |
151 | andn REG2, 0x3, REG2; \ | 151 | andn REG2, 0x7, REG2; \ |
152 | lduwa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ | 152 | ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ |
153 | brz,pn REG1, FAIL_LABEL; \ | 153 | brz,pn REG1, FAIL_LABEL; \ |
154 | sllx VADDR, 64 - PMD_SHIFT, REG2; \ | 154 | sllx VADDR, 64 - PMD_SHIFT, REG2; \ |
155 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ | 155 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ |
@@ -260,14 +260,14 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; | |||
260 | #define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL) \ | 260 | #define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL) \ |
261 | sllx VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \ | 261 | sllx VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \ |
262 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ | 262 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ |
263 | andn REG2, 0x3, REG2; \ | 263 | andn REG2, 0x7, REG2; \ |
264 | lduwa [PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \ | 264 | ldxa [PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \ |
265 | brz,pn REG1, FAIL_LABEL; \ | 265 | brz,pn REG1, FAIL_LABEL; \ |
266 | sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ | 266 | sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ |
267 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ | 267 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ |
268 | sllx REG1, PGD_PADDR_SHIFT, REG1; \ | 268 | sllx REG1, PGD_PADDR_SHIFT, REG1; \ |
269 | andn REG2, 0x3, REG2; \ | 269 | andn REG2, 0x7, REG2; \ |
270 | lduwa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ | 270 | ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ |
271 | USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \ | 271 | USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \ |
272 | sllx VADDR, 64 - PMD_SHIFT, REG2; \ | 272 | sllx VADDR, 64 - PMD_SHIFT, REG2; \ |
273 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ | 273 | srlx REG2, 64 - PAGE_SHIFT, REG2; \ |
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 807e10833512..828784419e25 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -1842,7 +1842,7 @@ static void __init sun4v_linear_pte_xor_finalize(void) | |||
1842 | /* paging_init() sets up the page tables */ | 1842 | /* paging_init() sets up the page tables */ |
1843 | 1843 | ||
1844 | static unsigned long last_valid_pfn; | 1844 | static unsigned long last_valid_pfn; |
1845 | pgd_t swapper_pg_dir[2048]; | 1845 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
1846 | 1846 | ||
1847 | static void sun4u_pgprot_init(void); | 1847 | static void sun4u_pgprot_init(void); |
1848 | static void sun4v_pgprot_init(void); | 1848 | static void sun4v_pgprot_init(void); |