aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-09-27 00:19:46 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-05 19:53:38 -0400
commitac55c768143aa34cc3789c4820cbb0809a76fd9c (patch)
treef6bb7af5b71e7935169a778e3f7e7694fbd1416f /arch/sparc
parent473ad7f4fb005d1bb727e4ef27d370d28703a062 (diff)
sparc64: Switch to 4-level page tables.
This has become necessary with chips that support more than 43-bits of physical addressing. Based almost entirely upon a patch by Bob Picco. Signed-off-by: David S. Miller <davem@davemloft.net> Acked-by: Bob Picco <bob.picco@oracle.com>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/include/asm/page_64.h6
-rw-r--r--arch/sparc/include/asm/pgalloc_64.h28
-rw-r--r--arch/sparc/include/asm/pgtable_64.h37
-rw-r--r--arch/sparc/include/asm/tsb.h10
-rw-r--r--arch/sparc/kernel/smp_64.c7
-rw-r--r--arch/sparc/mm/init_64.c31
6 files changed, 109 insertions, 10 deletions
diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h
index bf109984a032..09ceb68e72b7 100644
--- a/arch/sparc/include/asm/page_64.h
+++ b/arch/sparc/include/asm/page_64.h
@@ -57,18 +57,21 @@ void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *topa
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 long pmd; } pmd_t; 59typedef struct { unsigned long pmd; } pmd_t;
60typedef struct { unsigned long pud; } pud_t;
60typedef struct { unsigned long pgd; } pgd_t; 61typedef struct { unsigned long pgd; } pgd_t;
61typedef struct { unsigned long pgprot; } pgprot_t; 62typedef struct { unsigned long pgprot; } pgprot_t;
62 63
63#define pte_val(x) ((x).pte) 64#define pte_val(x) ((x).pte)
64#define iopte_val(x) ((x).iopte) 65#define iopte_val(x) ((x).iopte)
65#define pmd_val(x) ((x).pmd) 66#define pmd_val(x) ((x).pmd)
67#define pud_val(x) ((x).pud)
66#define pgd_val(x) ((x).pgd) 68#define pgd_val(x) ((x).pgd)
67#define pgprot_val(x) ((x).pgprot) 69#define pgprot_val(x) ((x).pgprot)
68 70
69#define __pte(x) ((pte_t) { (x) } ) 71#define __pte(x) ((pte_t) { (x) } )
70#define __iopte(x) ((iopte_t) { (x) } ) 72#define __iopte(x) ((iopte_t) { (x) } )
71#define __pmd(x) ((pmd_t) { (x) } ) 73#define __pmd(x) ((pmd_t) { (x) } )
74#define __pud(x) ((pud_t) { (x) } )
72#define __pgd(x) ((pgd_t) { (x) } ) 75#define __pgd(x) ((pgd_t) { (x) } )
73#define __pgprot(x) ((pgprot_t) { (x) } ) 76#define __pgprot(x) ((pgprot_t) { (x) } )
74 77
@@ -77,18 +80,21 @@ typedef struct { unsigned long pgprot; } pgprot_t;
77typedef unsigned long pte_t; 80typedef unsigned long pte_t;
78typedef unsigned long iopte_t; 81typedef unsigned long iopte_t;
79typedef unsigned long pmd_t; 82typedef unsigned long pmd_t;
83typedef unsigned long pud_t;
80typedef unsigned long pgd_t; 84typedef unsigned long pgd_t;
81typedef unsigned long pgprot_t; 85typedef unsigned long pgprot_t;
82 86
83#define pte_val(x) (x) 87#define pte_val(x) (x)
84#define iopte_val(x) (x) 88#define iopte_val(x) (x)
85#define pmd_val(x) (x) 89#define pmd_val(x) (x)
90#define pud_val(x) (x)
86#define pgd_val(x) (x) 91#define pgd_val(x) (x)
87#define pgprot_val(x) (x) 92#define pgprot_val(x) (x)
88 93
89#define __pte(x) (x) 94#define __pte(x) (x)
90#define __iopte(x) (x) 95#define __iopte(x) (x)
91#define __pmd(x) (x) 96#define __pmd(x) (x)
97#define __pud(x) (x)
92#define __pgd(x) (x) 98#define __pgd(x) (x)
93#define __pgprot(x) (x) 99#define __pgprot(x) (x)
94 100
diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h
index 39a7ac49b00c..5e3187185b4a 100644
--- a/arch/sparc/include/asm/pgalloc_64.h
+++ b/arch/sparc/include/asm/pgalloc_64.h
@@ -15,6 +15,13 @@
15 15
16extern struct kmem_cache *pgtable_cache; 16extern struct kmem_cache *pgtable_cache;
17 17
18static inline void __pgd_populate(pgd_t *pgd, pud_t *pud)
19{
20 pgd_set(pgd, pud);
21}
22
23#define pgd_populate(MM, PGD, PUD) __pgd_populate(PGD, PUD)
24
18static inline pgd_t *pgd_alloc(struct mm_struct *mm) 25static inline pgd_t *pgd_alloc(struct mm_struct *mm)
19{ 26{
20 return kmem_cache_alloc(pgtable_cache, GFP_KERNEL); 27 return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
@@ -25,7 +32,23 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
25 kmem_cache_free(pgtable_cache, pgd); 32 kmem_cache_free(pgtable_cache, pgd);
26} 33}
27 34
28#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) 35static inline void __pud_populate(pud_t *pud, pmd_t *pmd)
36{
37 pud_set(pud, pmd);
38}
39
40#define pud_populate(MM, PUD, PMD) __pud_populate(PUD, PMD)
41
42static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
43{
44 return kmem_cache_alloc(pgtable_cache,
45 GFP_KERNEL|__GFP_REPEAT);
46}
47
48static inline void pud_free(struct mm_struct *mm, pud_t *pud)
49{
50 kmem_cache_free(pgtable_cache, pud);
51}
29 52
30static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 53static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
31{ 54{
@@ -91,4 +114,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pte_t *pte,
91#define __pmd_free_tlb(tlb, pmd, addr) \ 114#define __pmd_free_tlb(tlb, pmd, addr) \
92 pgtable_free_tlb(tlb, pmd, false) 115 pgtable_free_tlb(tlb, pmd, false)
93 116
117#define __pud_free_tlb(tlb, pud, addr) \
118 pgtable_free_tlb(tlb, pud, false)
119
94#endif /* _SPARC64_PGALLOC_H */ 120#endif /* _SPARC64_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 3770bf5c6e1b..31ac919920a9 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -20,8 +20,6 @@
20#include <asm/page.h> 20#include <asm/page.h>
21#include <asm/processor.h> 21#include <asm/processor.h>
22 22
23#include <asm-generic/pgtable-nopud.h>
24
25/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). 23/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB).
26 * The page copy blockops can use 0x6000000 to 0x8000000. 24 * The page copy blockops can use 0x6000000 to 0x8000000.
27 * The 8K TSB is mapped in the 0x8000000 to 0x8400000 range. 25 * The 8K TSB is mapped in the 0x8000000 to 0x8400000 range.
@@ -55,13 +53,21 @@
55#define PMD_MASK (~(PMD_SIZE-1)) 53#define PMD_MASK (~(PMD_SIZE-1))
56#define PMD_BITS (PAGE_SHIFT - 3) 54#define PMD_BITS (PAGE_SHIFT - 3)
57 55
58/* PGDIR_SHIFT determines what a third-level page table entry can map */ 56/* PUD_SHIFT determines the size of the area a third-level page
59#define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS) 57 * table can map
58 */
59#define PUD_SHIFT (PMD_SHIFT + PMD_BITS)
60#define PUD_SIZE (_AC(1,UL) << PUD_SHIFT)
61#define PUD_MASK (~(PUD_SIZE-1))
62#define PUD_BITS (PAGE_SHIFT - 3)
63
64/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
65#define PGDIR_SHIFT (PUD_SHIFT + PUD_BITS)
60#define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT) 66#define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT)
61#define PGDIR_MASK (~(PGDIR_SIZE-1)) 67#define PGDIR_MASK (~(PGDIR_SIZE-1))
62#define PGDIR_BITS (PAGE_SHIFT - 3) 68#define PGDIR_BITS (PAGE_SHIFT - 3)
63 69
64#if (PGDIR_SHIFT + PGDIR_BITS) != 43 70#if (PGDIR_SHIFT + PGDIR_BITS) != 53
65#error Page table parameters do not cover virtual address space properly. 71#error Page table parameters do not cover virtual address space properly.
66#endif 72#endif
67 73
@@ -93,6 +99,7 @@ static inline bool kern_addr_valid(unsigned long addr)
93/* Entries per page directory level. */ 99/* Entries per page directory level. */
94#define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) 100#define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3))
95#define PTRS_PER_PMD (1UL << PMD_BITS) 101#define PTRS_PER_PMD (1UL << PMD_BITS)
102#define PTRS_PER_PUD (1UL << PUD_BITS)
96#define PTRS_PER_PGD (1UL << PGDIR_BITS) 103#define PTRS_PER_PGD (1UL << PGDIR_BITS)
97 104
98/* Kernel has a separate 44bit address space. */ 105/* Kernel has a separate 44bit address space. */
@@ -101,6 +108,9 @@ static inline bool kern_addr_valid(unsigned long addr)
101#define pmd_ERROR(e) \ 108#define pmd_ERROR(e) \
102 pr_err("%s:%d: bad pmd %p(%016lx) seen at (%pS)\n", \ 109 pr_err("%s:%d: bad pmd %p(%016lx) seen at (%pS)\n", \
103 __FILE__, __LINE__, &(e), pmd_val(e), __builtin_return_address(0)) 110 __FILE__, __LINE__, &(e), pmd_val(e), __builtin_return_address(0))
111#define pud_ERROR(e) \
112 pr_err("%s:%d: bad pud %p(%016lx) seen at (%pS)\n", \
113 __FILE__, __LINE__, &(e), pud_val(e), __builtin_return_address(0))
104#define pgd_ERROR(e) \ 114#define pgd_ERROR(e) \
105 pr_err("%s:%d: bad pgd %p(%016lx) seen at (%pS)\n", \ 115 pr_err("%s:%d: bad pgd %p(%016lx) seen at (%pS)\n", \
106 __FILE__, __LINE__, &(e), pgd_val(e), __builtin_return_address(0)) 116 __FILE__, __LINE__, &(e), pgd_val(e), __builtin_return_address(0))
@@ -779,6 +789,11 @@ static inline int pmd_present(pmd_t pmd)
779#define pud_bad(pud) ((pud_val(pud) & ~PAGE_MASK) || \ 789#define pud_bad(pud) ((pud_val(pud) & ~PAGE_MASK) || \
780 !__kern_addr_valid(pud_val(pud))) 790 !__kern_addr_valid(pud_val(pud)))
781 791
792#define pgd_none(pgd) (!pgd_val(pgd))
793
794#define pgd_bad(pgd) ((pgd_val(pgd) & ~PAGE_MASK) || \
795 !__kern_addr_valid(pgd_val(pgd)))
796
782#ifdef CONFIG_TRANSPARENT_HUGEPAGE 797#ifdef CONFIG_TRANSPARENT_HUGEPAGE
783void set_pmd_at(struct mm_struct *mm, unsigned long addr, 798void set_pmd_at(struct mm_struct *mm, unsigned long addr,
784 pmd_t *pmdp, pmd_t pmd); 799 pmd_t *pmdp, pmd_t pmd);
@@ -815,10 +830,17 @@ static inline unsigned long __pmd_page(pmd_t pmd)
815#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL) 830#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL)
816#define pud_present(pud) (pud_val(pud) != 0U) 831#define pud_present(pud) (pud_val(pud) != 0U)
817#define pud_clear(pudp) (pud_val(*(pudp)) = 0UL) 832#define pud_clear(pudp) (pud_val(*(pudp)) = 0UL)
833#define pgd_page_vaddr(pgd) \
834 ((unsigned long) __va(pgd_val(pgd)))
835#define pgd_present(pgd) (pgd_val(pgd) != 0U)
836#define pgd_clear(pgdp) (pgd_val(*(pgd)) = 0UL)
818 837
819/* Same in both SUN4V and SUN4U. */ 838/* Same in both SUN4V and SUN4U. */
820#define pte_none(pte) (!pte_val(pte)) 839#define pte_none(pte) (!pte_val(pte))
821 840
841#define pgd_set(pgdp, pudp) \
842 (pgd_val(*(pgdp)) = (__pa((unsigned long) (pudp))))
843
822/* to find an entry in a page-table-directory. */ 844/* to find an entry in a page-table-directory. */
823#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) 845#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
824#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) 846#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
@@ -826,6 +848,11 @@ static inline unsigned long __pmd_page(pmd_t pmd)
826/* to find an entry in a kernel page-table-directory */ 848/* to find an entry in a kernel page-table-directory */
827#define pgd_offset_k(address) pgd_offset(&init_mm, address) 849#define pgd_offset_k(address) pgd_offset(&init_mm, address)
828 850
851/* Find an entry in the third-level page table.. */
852#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
853#define pud_offset(pgdp, address) \
854 ((pud_t *) pgd_page_vaddr(*(pgdp)) + pud_index(address))
855
829/* Find an entry in the second-level page table.. */ 856/* Find an entry in the second-level page table.. */
830#define pmd_offset(pudp, address) \ 857#define pmd_offset(pudp, address) \
831 ((pmd_t *) pud_page_vaddr(*(pudp)) + \ 858 ((pmd_t *) pud_page_vaddr(*(pudp)) + \
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
index 90916f955cac..2e268b646348 100644
--- a/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -145,6 +145,11 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
145 andn REG2, 0x7, REG2; \ 145 andn REG2, 0x7, REG2; \
146 ldx [REG1 + REG2], REG1; \ 146 ldx [REG1 + REG2], REG1; \
147 brz,pn REG1, FAIL_LABEL; \ 147 brz,pn REG1, FAIL_LABEL; \
148 sllx VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \
149 srlx REG2, 64 - PAGE_SHIFT, REG2; \
150 andn REG2, 0x7, REG2; \
151 ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
152 brz,pn REG1, FAIL_LABEL; \
148 sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ 153 sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
149 srlx REG2, 64 - PAGE_SHIFT, REG2; \ 154 srlx REG2, 64 - PAGE_SHIFT, REG2; \
150 andn REG2, 0x7, REG2; \ 155 andn REG2, 0x7, REG2; \
@@ -198,6 +203,11 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
198 andn REG2, 0x7, REG2; \ 203 andn REG2, 0x7, REG2; \
199 ldxa [PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \ 204 ldxa [PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \
200 brz,pn REG1, FAIL_LABEL; \ 205 brz,pn REG1, FAIL_LABEL; \
206 sllx VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \
207 srlx REG2, 64 - PAGE_SHIFT, REG2; \
208 andn REG2, 0x7, REG2; \
209 ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
210 brz,pn REG1, FAIL_LABEL; \
201 sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ 211 sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
202 srlx REG2, 64 - PAGE_SHIFT, REG2; \ 212 srlx REG2, 64 - PAGE_SHIFT, REG2; \
203 andn REG2, 0x7, REG2; \ 213 andn REG2, 0x7, REG2; \
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index f7ba87543e5f..c9300bfaee5a 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -1467,6 +1467,13 @@ static void __init pcpu_populate_pte(unsigned long addr)
1467 pud_t *pud; 1467 pud_t *pud;
1468 pmd_t *pmd; 1468 pmd_t *pmd;
1469 1469
1470 if (pgd_none(*pgd)) {
1471 pud_t *new;
1472
1473 new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
1474 pgd_populate(&init_mm, pgd, new);
1475 }
1476
1470 pud = pud_offset(pgd, addr); 1477 pud = pud_offset(pgd, addr);
1471 if (pud_none(*pud)) { 1478 if (pud_none(*pud)) {
1472 pmd_t *new; 1479 pmd_t *new;
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index bd08ed49bbaa..091f846e6192 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1390,6 +1390,13 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
1390 pmd_t *pmd; 1390 pmd_t *pmd;
1391 pte_t *pte; 1391 pte_t *pte;
1392 1392
1393 if (pgd_none(*pgd)) {
1394 pud_t *new;
1395
1396 new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
1397 alloc_bytes += PAGE_SIZE;
1398 pgd_populate(&init_mm, pgd, new);
1399 }
1393 pud = pud_offset(pgd, vstart); 1400 pud = pud_offset(pgd, vstart);
1394 if (pud_none(*pud)) { 1401 if (pud_none(*pud)) {
1395 pmd_t *new; 1402 pmd_t *new;
@@ -1856,7 +1863,12 @@ static void __init sun4v_linear_pte_xor_finalize(void)
1856/* paging_init() sets up the page tables */ 1863/* paging_init() sets up the page tables */
1857 1864
1858static unsigned long last_valid_pfn; 1865static unsigned long last_valid_pfn;
1859pgd_t swapper_pg_dir[PTRS_PER_PGD]; 1866
1867/* These must be page aligned in order to not trigger the
1868 * alignment tests of pgd_bad() and pud_bad().
1869 */
1870pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned (PAGE_SIZE)));
1871static pud_t swapper_pud_dir[PTRS_PER_PUD] __attribute__ ((aligned (PAGE_SIZE)));
1860 1872
1861static void sun4u_pgprot_init(void); 1873static void sun4u_pgprot_init(void);
1862static void sun4v_pgprot_init(void); 1874static void sun4v_pgprot_init(void);
@@ -1911,6 +1923,8 @@ void __init paging_init(void)
1911{ 1923{
1912 unsigned long end_pfn, shift, phys_base; 1924 unsigned long end_pfn, shift, phys_base;
1913 unsigned long real_end, i; 1925 unsigned long real_end, i;
1926 pud_t *pud;
1927 pmd_t *pmd;
1914 int node; 1928 int node;
1915 1929
1916 setup_page_offset(); 1930 setup_page_offset();
@@ -2008,9 +2022,18 @@ void __init paging_init(void)
2008 2022
2009 memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir)); 2023 memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir));
2010 2024
2011 /* Now can init the kernel/bad page tables. */ 2025 /* The kernel page tables we publish into what the rest of the
2012 pud_set(pud_offset(&swapper_pg_dir[0], 0), 2026 * world sees must be adjusted so that they see the PAGE_OFFSET
2013 swapper_low_pmd_dir + (shift / sizeof(pgd_t))); 2027 * address of these in-kerenel data structures. However right
2028 * here we must access them from the kernel image side, because
2029 * the trap tables haven't been taken over and therefore we cannot
2030 * take TLB misses in the PAGE_OFFSET linear mappings yet.
2031 */
2032 pud = swapper_pud_dir + (shift / sizeof(pud_t));
2033 pgd_set(&swapper_pg_dir[0], pud);
2034
2035 pmd = swapper_low_pmd_dir + (shift / sizeof(pmd_t));
2036 pud_set(&swapper_pud_dir[0], pmd);
2014 2037
2015 inherit_prom_mappings(); 2038 inherit_prom_mappings();
2016 2039