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/pgtable.h | |
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/pgtable.h')
-rw-r--r-- | arch/mips/include/asm/pgtable.h | 36 |
1 files changed, 14 insertions, 22 deletions
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 |