Commit 325f8a0a31df567dbafafc48f8e60f3c1f101a46

Authored by David Daney
Committed by Ralf Baechle
1 parent ef6c1fd662

MIPS: Two-level pagetables for 64-bit kernels with 64KB pages.

For 64-bit kernels with 64KB pages and two level page tables, there are
42 bits worth of virtual address space This is larger than the 40 bits of
virtual address space obtained with the default 4KB Page size and three
levels, so there are no draw backs for using two level tables with this
configuration.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: linux-mips@linux-mips.org
Patchwork: http://patchwork.linux-mips.org/patch/761/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

Showing 8 changed files with 71 additions and 35 deletions Side-by-side Diff

arch/mips/include/asm/page.h
... ... @@ -107,18 +107,6 @@
107 107 typedef struct page *pgtable_t;
108 108  
109 109 /*
110   - * For 3-level pagetables we defines these ourselves, for 2-level the
111   - * definitions are supplied by <asm-generic/pgtable-nopmd.h>.
112   - */
113   -#ifdef CONFIG_64BIT
114   -
115   -typedef struct { unsigned long pmd; } pmd_t;
116   -#define pmd_val(x) ((x).pmd)
117   -#define __pmd(x) ((pmd_t) { (x) } )
118   -
119   -#endif
120   -
121   -/*
122 110 * Right now we don't support 4-level pagetables, so all pud-related
123 111 * definitions come from <asm-generic/pgtable-nopud.h>.
124 112 */
arch/mips/include/asm/pgalloc.h
... ... @@ -31,7 +31,7 @@
31 31 */
32 32 extern void pmd_init(unsigned long page, unsigned long pagetable);
33 33  
34   -#ifdef CONFIG_64BIT
  34 +#ifndef __PAGETABLE_PMD_FOLDED
35 35  
36 36 static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
37 37 {
... ... @@ -104,7 +104,7 @@
104 104 tlb_remove_page((tlb), pte); \
105 105 } while (0)
106 106  
107   -#ifdef CONFIG_64BIT
  107 +#ifndef __PAGETABLE_PMD_FOLDED
108 108  
109 109 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
110 110 {
arch/mips/include/asm/pgtable-64.h
... ... @@ -16,7 +16,11 @@
16 16 #include <asm/cachectl.h>
17 17 #include <asm/fixmap.h>
18 18  
  19 +#ifdef CONFIG_PAGE_SIZE_64KB
  20 +#include <asm-generic/pgtable-nopmd.h>
  21 +#else
19 22 #include <asm-generic/pgtable-nopud.h>
  23 +#endif
20 24  
21 25 /*
22 26 * Each address space has 2 4K pages as its page directory, giving 1024
23 27  
24 28  
... ... @@ -37,13 +41,20 @@
37 41 * fault address - VMALLOC_START.
38 42 */
39 43  
  44 +
  45 +/* PGDIR_SHIFT determines what a third-level page table entry can map */
  46 +#ifdef __PAGETABLE_PMD_FOLDED
  47 +#define PGDIR_SHIFT (PAGE_SHIFT + PAGE_SHIFT + PTE_ORDER - 3)
  48 +#else
  49 +
40 50 /* PMD_SHIFT determines the size of the area a second-level page table can map */
41 51 #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT + PTE_ORDER - 3))
42 52 #define PMD_SIZE (1UL << PMD_SHIFT)
43 53 #define PMD_MASK (~(PMD_SIZE-1))
44 54  
45   -/* PGDIR_SHIFT determines what a third-level page table entry can map */
  55 +
46 56 #define PGDIR_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3))
  57 +#endif
47 58 #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
48 59 #define PGDIR_MASK (~(PGDIR_SIZE-1))
49 60  
50 61  
51 62  
... ... @@ -92,12 +103,14 @@
92 103 #ifdef CONFIG_PAGE_SIZE_64KB
93 104 #define PGD_ORDER 0
94 105 #define PUD_ORDER aieeee_attempt_to_allocate_pud
95   -#define PMD_ORDER 0
  106 +#define PMD_ORDER aieeee_attempt_to_allocate_pmd
96 107 #define PTE_ORDER 0
97 108 #endif
98 109  
99 110 #define PTRS_PER_PGD ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t))
  111 +#ifndef __PAGETABLE_PMD_FOLDED
100 112 #define PTRS_PER_PMD ((PAGE_SIZE << PMD_ORDER) / sizeof(pmd_t))
  113 +#endif
101 114 #define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
102 115  
103 116 #if PGDIR_SIZE >= TASK_SIZE
104 117  
105 118  
106 119  
... ... @@ -122,15 +135,30 @@
122 135  
123 136 #define pte_ERROR(e) \
124 137 printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
  138 +#ifndef __PAGETABLE_PMD_FOLDED
125 139 #define pmd_ERROR(e) \
126 140 printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
  141 +#endif
127 142 #define pgd_ERROR(e) \
128 143 printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
129 144  
130 145 extern pte_t invalid_pte_table[PTRS_PER_PTE];
131 146 extern pte_t empty_bad_page_table[PTRS_PER_PTE];
  147 +
  148 +
  149 +#ifndef __PAGETABLE_PMD_FOLDED
  150 +/*
  151 + * For 3-level pagetables we defines these ourselves, for 2-level the
  152 + * definitions are supplied by <asm-generic/pgtable-nopmd.h>.
  153 + */
  154 +typedef struct { unsigned long pmd; } pmd_t;
  155 +#define pmd_val(x) ((x).pmd)
  156 +#define __pmd(x) ((pmd_t) { (x) } )
  157 +
  158 +
132 159 extern pmd_t invalid_pmd_table[PTRS_PER_PMD];
133 160 extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD];
  161 +#endif
134 162  
135 163 /*
136 164 * Empty pgd/pmd entries point to the invalid_pte_table.
... ... @@ -151,6 +179,7 @@
151 179 {
152 180 pmd_val(*pmdp) = ((unsigned long) invalid_pte_table);
153 181 }
  182 +#ifndef __PAGETABLE_PMD_FOLDED
154 183  
155 184 /*
156 185 * Empty pud entries point to the invalid_pmd_table.
... ... @@ -174,6 +203,7 @@
174 203 {
175 204 pud_val(*pudp) = ((unsigned long) invalid_pmd_table);
176 205 }
  206 +#endif
177 207  
178 208 #define pte_page(x) pfn_to_page(pte_pfn(x))
179 209  
... ... @@ -198,6 +228,7 @@
198 228 /* to find an entry in a page-table-directory */
199 229 #define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
200 230  
  231 +#ifndef __PAGETABLE_PMD_FOLDED
201 232 static inline unsigned long pud_page_vaddr(pud_t pud)
202 233 {
203 234 return pud_val(pud);
... ... @@ -210,6 +241,7 @@
210 241 {
211 242 return (pmd_t *) pud_page_vaddr(*pud) + pmd_index(address);
212 243 }
  244 +#endif
213 245  
214 246 /* Find an entry in the third-level page table.. */
215 247 #define __pte_offset(address) \
arch/mips/include/asm/pgtable.h
... ... @@ -177,7 +177,7 @@
177 177 */
178 178 #define set_pmd(pmdptr, pmdval) do { *(pmdptr) = (pmdval); } while(0)
179 179  
180   -#ifdef CONFIG_64BIT
  180 +#ifndef __PAGETABLE_PMD_FOLDED
181 181 /*
182 182 * (puds are folded into pgds so this doesn't get actually called,
183 183 * but the define is needed for a generic inline function.)
arch/mips/kernel/asm-offsets.c
... ... @@ -188,11 +188,15 @@
188 188 DEFINE(_PTE_T_SIZE, sizeof(pte_t));
189 189 BLANK();
190 190 DEFINE(_PGD_T_LOG2, PGD_T_LOG2);
  191 +#ifndef __PAGETABLE_PMD_FOLDED
191 192 DEFINE(_PMD_T_LOG2, PMD_T_LOG2);
  193 +#endif
192 194 DEFINE(_PTE_T_LOG2, PTE_T_LOG2);
193 195 BLANK();
194 196 DEFINE(_PGD_ORDER, PGD_ORDER);
  197 +#ifndef __PAGETABLE_PMD_FOLDED
195 198 DEFINE(_PMD_ORDER, PMD_ORDER);
  199 +#endif
196 200 DEFINE(_PTE_ORDER, PTE_ORDER);
197 201 BLANK();
198 202 DEFINE(_PMD_SHIFT, PMD_SHIFT);
... ... @@ -477,7 +477,7 @@
477 477 * will officially be retired.
478 478 */
479 479 pgd_t swapper_pg_dir[_PTRS_PER_PGD] __page_aligned(_PGD_ORDER);
480   -#ifdef CONFIG_64BIT
  480 +#ifndef __PAGETABLE_PMD_FOLDED
481 481 pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned(PMD_ORDER);
482 482 #endif
483 483 pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned(PTE_ORDER);
arch/mips/mm/pgtable-64.c
... ... @@ -15,23 +15,31 @@
15 15 void pgd_init(unsigned long page)
16 16 {
17 17 unsigned long *p, *end;
  18 + unsigned long entry;
18 19  
  20 +#ifdef __PAGETABLE_PMD_FOLDED
  21 + entry = (unsigned long)invalid_pte_table;
  22 +#else
  23 + entry = (unsigned long)invalid_pmd_table;
  24 +#endif
  25 +
19 26 p = (unsigned long *) page;
20 27 end = p + PTRS_PER_PGD;
21 28  
22 29 while (p < end) {
23   - p[0] = (unsigned long) invalid_pmd_table;
24   - p[1] = (unsigned long) invalid_pmd_table;
25   - p[2] = (unsigned long) invalid_pmd_table;
26   - p[3] = (unsigned long) invalid_pmd_table;
27   - p[4] = (unsigned long) invalid_pmd_table;
28   - p[5] = (unsigned long) invalid_pmd_table;
29   - p[6] = (unsigned long) invalid_pmd_table;
30   - p[7] = (unsigned long) invalid_pmd_table;
  30 + p[0] = entry;
  31 + p[1] = entry;
  32 + p[2] = entry;
  33 + p[3] = entry;
  34 + p[4] = entry;
  35 + p[5] = entry;
  36 + p[6] = entry;
  37 + p[7] = entry;
31 38 p += 8;
32 39 }
33 40 }
34 41  
  42 +#ifndef __PAGETABLE_PMD_FOLDED
35 43 void pmd_init(unsigned long addr, unsigned long pagetable)
36 44 {
37 45 unsigned long *p, *end;
38 46  
... ... @@ -40,17 +48,18 @@
40 48 end = p + PTRS_PER_PMD;
41 49  
42 50 while (p < end) {
43   - p[0] = (unsigned long)pagetable;
44   - p[1] = (unsigned long)pagetable;
45   - p[2] = (unsigned long)pagetable;
46   - p[3] = (unsigned long)pagetable;
47   - p[4] = (unsigned long)pagetable;
48   - p[5] = (unsigned long)pagetable;
49   - p[6] = (unsigned long)pagetable;
50   - p[7] = (unsigned long)pagetable;
  51 + p[0] = pagetable;
  52 + p[1] = pagetable;
  53 + p[2] = pagetable;
  54 + p[3] = pagetable;
  55 + p[4] = pagetable;
  56 + p[5] = pagetable;
  57 + p[6] = pagetable;
  58 + p[7] = pagetable;
51 59 p += 8;
52 60 }
53 61 }
  62 +#endif
54 63  
55 64 void __init pagetable_init(void)
56 65 {
57 66  
... ... @@ -59,8 +68,9 @@
59 68  
60 69 /* Initialize the entire pgd. */
61 70 pgd_init((unsigned long)swapper_pg_dir);
  71 +#ifndef __PAGETABLE_PMD_FOLDED
62 72 pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
63   -
  73 +#endif
64 74 pgd_base = swapper_pg_dir;
65 75 /*
66 76 * Fixed mappings:
arch/mips/mm/tlbex.c
... ... @@ -549,11 +549,13 @@
549 549  
550 550 uasm_i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
551 551 uasm_i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
  552 +#ifndef __PAGETABLE_PMD_FOLDED
552 553 uasm_i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
553 554 uasm_i_ld(p, ptr, 0, ptr); /* get pmd pointer */
554 555 uasm_i_dsrl(p, tmp, tmp, PMD_SHIFT-3); /* get pmd offset in bytes */
555 556 uasm_i_andi(p, tmp, tmp, (PTRS_PER_PMD - 1)<<3);
556 557 uasm_i_daddu(p, ptr, ptr, tmp); /* add in pmd offset */
  558 +#endif
557 559 }
558 560  
559 561 /*