aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-09-25 17:33:16 -0400
committerDavid S. Miller <davem@davemloft.net>2013-11-12 18:22:35 -0500
commit2b77933c28f5044629bb19e8045aae65b72b939d (patch)
treeecb5e23e19599a77748ec54b116ac59341c25a38 /arch/sparc
parent37b3a8ff3e086cd5c369e77d2383b691b2874cd6 (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.h25
-rw-r--r--arch/sparc/include/asm/pgtable_64.h22
-rw-r--r--arch/sparc/include/asm/tsb.h16
-rw-r--r--arch/sparc/mm/init_64.c2
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.. */
57typedef struct { unsigned long pte; } pte_t; 57typedef struct { unsigned long pte; } pte_t;
58typedef struct { unsigned long iopte; } iopte_t; 58typedef struct { unsigned long iopte; } iopte_t;
59typedef struct { unsigned int pmd; } pmd_t; 59typedef struct { unsigned long pmd; } pmd_t;
60typedef struct { unsigned int pgd; } pgd_t; 60typedef struct { unsigned long pgd; } pgd_t;
61typedef struct { unsigned long pgprot; } pgprot_t; 61typedef 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 */
77typedef unsigned long pte_t; 77typedef unsigned long pte_t;
78typedef unsigned long iopte_t; 78typedef unsigned long iopte_t;
79typedef unsigned int pmd_t; 79typedef unsigned long pmd_t;
80typedef unsigned int pgd_t; 80typedef unsigned long pgd_t;
81typedef unsigned long pgprot_t; 81typedef 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;
97typedef pte_t *pgtable_t; 97typedef 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
715static inline int pmd_present(pmd_t pmd) 715static 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))
742static inline unsigned long __pmd_page(pmd_t pmd) 742static 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
844extern pgd_t swapper_pg_dir[2048]; 844extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
845extern pmd_t swapper_low_pmd_dir[2048]; 845extern pmd_t swapper_low_pmd_dir[PTRS_PER_PMD];
846 846
847extern void paging_init(void); 847extern void paging_init(void);
848extern unsigned long find_ecache_flush_span(unsigned long size); 848extern 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
1844static unsigned long last_valid_pfn; 1844static unsigned long last_valid_pfn;
1845pgd_t swapper_pg_dir[2048]; 1845pgd_t swapper_pg_dir[PTRS_PER_PGD];
1846 1846
1847static void sun4u_pgprot_init(void); 1847static void sun4u_pgprot_init(void);
1848static void sun4v_pgprot_init(void); 1848static void sun4v_pgprot_init(void);