diff options
author | Steven J. Hill <Steven.Hill@imgtec.com> | 2015-02-26 19:16:38 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-03-19 12:39:49 -0400 |
commit | c5b367835cfc7a8ef53b9670a409ffcc95194344 (patch) | |
tree | 23a6be89021f93b09bb0f2340bc995c21bcab79b /arch/mips/include/asm | |
parent | be0c37c985eddc46d0d67543898c086f60460e2e (diff) |
MIPS: Add support for XPA.
Add support for extended physical addressing (XPA) so that
32-bit platforms can access equal to or greater than 40 bits
of physical addresses.
NOTE:
1) XPA and EVA are not the same and cannot be used
simultaneously.
2) If you configure your kernel for XPA, the PTEs
and all address sizes become 64-bit.
3) Your platform MUST have working HIGHMEM support.
Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9355/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/include/asm')
-rw-r--r-- | arch/mips/include/asm/cpu-features.h | 3 | ||||
-rw-r--r-- | arch/mips/include/asm/cpu.h | 1 | ||||
-rw-r--r-- | arch/mips/include/asm/pgtable-32.h | 15 | ||||
-rw-r--r-- | arch/mips/include/asm/pgtable-bits.h | 13 | ||||
-rw-r--r-- | arch/mips/include/asm/pgtable.h | 36 |
5 files changed, 38 insertions, 30 deletions
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 0d8208de9a3f..a324751b02ff 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h | |||
@@ -139,6 +139,9 @@ | |||
139 | # endif | 139 | # endif |
140 | #endif | 140 | #endif |
141 | 141 | ||
142 | #ifndef cpu_has_xpa | ||
143 | #define cpu_has_xpa (cpu_data[0].options & MIPS_CPU_XPA) | ||
144 | #endif | ||
142 | #ifndef cpu_has_vtag_icache | 145 | #ifndef cpu_has_vtag_icache |
143 | #define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG) | 146 | #define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG) |
144 | #endif | 147 | #endif |
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 15687234d70a..e492c740bb94 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h | |||
@@ -377,6 +377,7 @@ enum cpu_type_enum { | |||
377 | #define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */ | 377 | #define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */ |
378 | #define MIPS_CPU_FRE 0x800000000ull /* FRE & UFE bits implemented */ | 378 | #define MIPS_CPU_FRE 0x800000000ull /* FRE & UFE bits implemented */ |
379 | #define MIPS_CPU_RW_LLB 0x1000000000ull /* LLADDR/LLB writes are allowed */ | 379 | #define MIPS_CPU_RW_LLB 0x1000000000ull /* LLADDR/LLB writes are allowed */ |
380 | #define MIPS_CPU_XPA 0x2000000000ull /* CPU supports Extended Physical Addressing */ | ||
380 | 381 | ||
381 | /* | 382 | /* |
382 | * CPU ASE encodings | 383 | * CPU ASE encodings |
diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index a6be006b6f75..7d56686c0e62 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h | |||
@@ -105,13 +105,16 @@ static inline void pmd_clear(pmd_t *pmdp) | |||
105 | 105 | ||
106 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) | 106 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
107 | #define pte_page(x) pfn_to_page(pte_pfn(x)) | 107 | #define pte_page(x) pfn_to_page(pte_pfn(x)) |
108 | #define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) | 108 | #define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT)) |
109 | static inline pte_t | 109 | static inline pte_t |
110 | pfn_pte(unsigned long pfn, pgprot_t prot) | 110 | pfn_pte(unsigned long pfn, pgprot_t prot) |
111 | { | 111 | { |
112 | pte_t pte; | 112 | pte_t pte; |
113 | pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f); | 113 | |
114 | pte.pte_low = pgprot_val(prot); | 114 | pte.pte_low = (pfn >> _PAGE_PRESENT_SHIFT) | |
115 | (pgprot_val(prot) & ~_PFNX_MASK); | ||
116 | pte.pte_high = (pfn << _PFN_SHIFT) | | ||
117 | (pgprot_val(prot) & ~_PFN_MASK); | ||
115 | return pte; | 118 | return pte; |
116 | } | 119 | } |
117 | 120 | ||
@@ -166,9 +169,9 @@ pfn_pte(unsigned long pfn, pgprot_t prot) | |||
166 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) | 169 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
167 | 170 | ||
168 | /* Swap entries must have VALID and GLOBAL bits cleared. */ | 171 | /* Swap entries must have VALID and GLOBAL bits cleared. */ |
169 | #define __swp_type(x) (((x).val >> 2) & 0x1f) | 172 | #define __swp_type(x) (((x).val >> 4) & 0x1f) |
170 | #define __swp_offset(x) ((x).val >> 7) | 173 | #define __swp_offset(x) ((x).val >> 9) |
171 | #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 7) }) | 174 | #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 4) | ((offset) << 9) }) |
172 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) | 175 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) |
173 | #define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) | 176 | #define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) |
174 | 177 | ||
diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 8e432a8ec4fe..18ae5ddef118 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h | |||
@@ -37,7 +37,11 @@ | |||
37 | /* | 37 | /* |
38 | * The following bits are implemented by the TLB hardware | 38 | * The following bits are implemented by the TLB hardware |
39 | */ | 39 | */ |
40 | #define _PAGE_GLOBAL_SHIFT 0 | 40 | #define _PAGE_NO_EXEC_SHIFT 0 |
41 | #define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) | ||
42 | #define _PAGE_NO_READ_SHIFT (_PAGE_NO_EXEC_SHIFT + 1) | ||
43 | #define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) | ||
44 | #define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1) | ||
41 | #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) | 45 | #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) |
42 | #define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) | 46 | #define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) |
43 | #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) | 47 | #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) |
@@ -49,7 +53,7 @@ | |||
49 | /* | 53 | /* |
50 | * The following bits are implemented in software | 54 | * The following bits are implemented in software |
51 | */ | 55 | */ |
52 | #define _PAGE_PRESENT_SHIFT (_CACHE_SHIFT + 3) | 56 | #define _PAGE_PRESENT_SHIFT (24) |
53 | #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) | 57 | #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) |
54 | #define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) | 58 | #define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) |
55 | #define _PAGE_READ (1 << _PAGE_READ_SHIFT) | 59 | #define _PAGE_READ (1 << _PAGE_READ_SHIFT) |
@@ -62,6 +66,11 @@ | |||
62 | 66 | ||
63 | #define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) | 67 | #define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) |
64 | 68 | ||
69 | /* | ||
70 | * Bits for extended EntryLo0/EntryLo1 registers | ||
71 | */ | ||
72 | #define _PFNX_MASK 0xffffff | ||
73 | |||
65 | #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | 74 | #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) |
66 | 75 | ||
67 | /* | 76 | /* |
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index e1fec0237ce2..bffd46ca3694 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h | |||
@@ -133,7 +133,7 @@ extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | |||
133 | 133 | ||
134 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) | 134 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
135 | 135 | ||
136 | #define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL)) | 136 | #define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) |
137 | #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) | 137 | #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) |
138 | 138 | ||
139 | static inline void set_pte(pte_t *ptep, pte_t pte) | 139 | static inline void set_pte(pte_t *ptep, pte_t pte) |
@@ -142,16 +142,14 @@ static inline void set_pte(pte_t *ptep, pte_t pte) | |||
142 | smp_wmb(); | 142 | smp_wmb(); |
143 | ptep->pte_low = pte.pte_low; | 143 | ptep->pte_low = pte.pte_low; |
144 | 144 | ||
145 | if (pte.pte_low & _PAGE_GLOBAL) { | 145 | if (pte.pte_high & _PAGE_GLOBAL) { |
146 | pte_t *buddy = ptep_buddy(ptep); | 146 | pte_t *buddy = ptep_buddy(ptep); |
147 | /* | 147 | /* |
148 | * Make sure the buddy is global too (if it's !none, | 148 | * Make sure the buddy is global too (if it's !none, |
149 | * it better already be global) | 149 | * it better already be global) |
150 | */ | 150 | */ |
151 | if (pte_none(*buddy)) { | 151 | if (pte_none(*buddy)) |
152 | buddy->pte_low |= _PAGE_GLOBAL; | ||
153 | buddy->pte_high |= _PAGE_GLOBAL; | 152 | buddy->pte_high |= _PAGE_GLOBAL; |
154 | } | ||
155 | } | 153 | } |
156 | } | 154 | } |
157 | 155 | ||
@@ -161,8 +159,8 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt | |||
161 | 159 | ||
162 | htw_stop(); | 160 | htw_stop(); |
163 | /* Preserve global status for the pair */ | 161 | /* Preserve global status for the pair */ |
164 | if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL) | 162 | if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) |
165 | null.pte_low = null.pte_high = _PAGE_GLOBAL; | 163 | null.pte_high = _PAGE_GLOBAL; |
166 | 164 | ||
167 | set_pte_at(mm, addr, ptep, null); | 165 | set_pte_at(mm, addr, ptep, null); |
168 | htw_start(); | 166 | htw_start(); |
@@ -242,21 +240,21 @@ static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; } | |||
242 | 240 | ||
243 | static inline pte_t pte_wrprotect(pte_t pte) | 241 | static inline pte_t pte_wrprotect(pte_t pte) |
244 | { | 242 | { |
245 | pte.pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); | 243 | pte.pte_low &= ~_PAGE_WRITE; |
246 | pte.pte_high &= ~_PAGE_SILENT_WRITE; | 244 | pte.pte_high &= ~_PAGE_SILENT_WRITE; |
247 | return pte; | 245 | return pte; |
248 | } | 246 | } |
249 | 247 | ||
250 | static inline pte_t pte_mkclean(pte_t pte) | 248 | static inline pte_t pte_mkclean(pte_t pte) |
251 | { | 249 | { |
252 | pte.pte_low &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); | 250 | pte.pte_low &= ~_PAGE_MODIFIED; |
253 | pte.pte_high &= ~_PAGE_SILENT_WRITE; | 251 | pte.pte_high &= ~_PAGE_SILENT_WRITE; |
254 | return pte; | 252 | return pte; |
255 | } | 253 | } |
256 | 254 | ||
257 | static inline pte_t pte_mkold(pte_t pte) | 255 | static inline pte_t pte_mkold(pte_t pte) |
258 | { | 256 | { |
259 | pte.pte_low &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ); | 257 | pte.pte_low &= ~_PAGE_ACCESSED; |
260 | pte.pte_high &= ~_PAGE_SILENT_READ; | 258 | pte.pte_high &= ~_PAGE_SILENT_READ; |
261 | return pte; | 259 | return pte; |
262 | } | 260 | } |
@@ -264,30 +262,24 @@ static inline pte_t pte_mkold(pte_t pte) | |||
264 | static inline pte_t pte_mkwrite(pte_t pte) | 262 | static inline pte_t pte_mkwrite(pte_t pte) |
265 | { | 263 | { |
266 | pte.pte_low |= _PAGE_WRITE; | 264 | pte.pte_low |= _PAGE_WRITE; |
267 | if (pte.pte_low & _PAGE_MODIFIED) { | 265 | if (pte.pte_low & _PAGE_MODIFIED) |
268 | pte.pte_low |= _PAGE_SILENT_WRITE; | ||
269 | pte.pte_high |= _PAGE_SILENT_WRITE; | 266 | pte.pte_high |= _PAGE_SILENT_WRITE; |
270 | } | ||
271 | return pte; | 267 | return pte; |
272 | } | 268 | } |
273 | 269 | ||
274 | static inline pte_t pte_mkdirty(pte_t pte) | 270 | static inline pte_t pte_mkdirty(pte_t pte) |
275 | { | 271 | { |
276 | pte.pte_low |= _PAGE_MODIFIED; | 272 | pte.pte_low |= _PAGE_MODIFIED; |
277 | if (pte.pte_low & _PAGE_WRITE) { | 273 | if (pte.pte_low & _PAGE_WRITE) |
278 | pte.pte_low |= _PAGE_SILENT_WRITE; | ||
279 | pte.pte_high |= _PAGE_SILENT_WRITE; | 274 | pte.pte_high |= _PAGE_SILENT_WRITE; |
280 | } | ||
281 | return pte; | 275 | return pte; |
282 | } | 276 | } |
283 | 277 | ||
284 | static inline pte_t pte_mkyoung(pte_t pte) | 278 | static inline pte_t pte_mkyoung(pte_t pte) |
285 | { | 279 | { |
286 | pte.pte_low |= _PAGE_ACCESSED; | 280 | pte.pte_low |= _PAGE_ACCESSED; |
287 | if (pte.pte_low & _PAGE_READ) { | 281 | if (pte.pte_low & _PAGE_READ) |
288 | pte.pte_low |= _PAGE_SILENT_READ; | ||
289 | pte.pte_high |= _PAGE_SILENT_READ; | 282 | pte.pte_high |= _PAGE_SILENT_READ; |
290 | } | ||
291 | return pte; | 283 | return pte; |
292 | } | 284 | } |
293 | #else | 285 | #else |
@@ -391,10 +383,10 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot) | |||
391 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) | 383 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
392 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 384 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
393 | { | 385 | { |
394 | pte.pte_low &= _PAGE_CHG_MASK; | 386 | pte.pte_low &= (_PAGE_MODIFIED | _PAGE_ACCESSED | _PFNX_MASK); |
395 | pte.pte_high &= (_PFN_MASK | _CACHE_MASK); | 387 | pte.pte_high &= (_PFN_MASK | _CACHE_MASK); |
396 | pte.pte_low |= pgprot_val(newprot); | 388 | pte.pte_low |= pgprot_val(newprot) & ~_PFNX_MASK; |
397 | pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK); | 389 | pte.pte_high |= pgprot_val(newprot) & ~_PFN_MASK; |
398 | return pte; | 390 | return pte; |
399 | } | 391 | } |
400 | #else | 392 | #else |