aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-sh/pgtable.h
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2007-09-20 22:55:03 -0400
committerPaul Mundt <lethal@linux-sh.org>2007-09-20 22:57:55 -0400
commitd04a0f79f502a87bb17b147afc4b3e39e75275c3 (patch)
tree9fcd7244769316e22ce54e11bd0b80f544b30f90 /include/asm-sh/pgtable.h
parentdb2504966ceb9f08557b6ea3ab7e367016fcaba9 (diff)
sh: Fix up extended mode TLB for SH-X2+ cores.
The extended mode TLB requires both 64-bit PTEs and a 64-bit pgprot, correspondingly, the PGD also has to be 64-bits, so fix that up. The kernel and user permission bits really are decoupled in early cuts of the silicon, which means that we also have to set corresponding kernel permissions on user pages or we end up with user pages that the kernel simply can't touch (!). Finally, with those things corrected, really enable MMUCR.ME and correct the PTEA value (this simply needs to be the upper 32-bits of the PTE, with the size and protection bit encoding). Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'include/asm-sh/pgtable.h')
-rw-r--r--include/asm-sh/pgtable.h112
1 files changed, 62 insertions, 50 deletions
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index 54ad5037fe40..cf0dd2b648c2 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -42,13 +42,12 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
42 42
43/* PGD bits */ 43/* PGD bits */
44#define PGDIR_SHIFT (PTE_SHIFT + PTE_BITS) 44#define PGDIR_SHIFT (PTE_SHIFT + PTE_BITS)
45#define PGDIR_BITS (32 - PGDIR_SHIFT)
46#define PGDIR_SIZE (1UL << PGDIR_SHIFT) 45#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
47#define PGDIR_MASK (~(PGDIR_SIZE-1)) 46#define PGDIR_MASK (~(PGDIR_SIZE-1))
48 47
49/* Entries per level */ 48/* Entries per level */
50#define PTRS_PER_PTE (PAGE_SIZE / (1 << PTE_MAGNITUDE)) 49#define PTRS_PER_PTE (PAGE_SIZE / (1 << PTE_MAGNITUDE))
51#define PTRS_PER_PGD (PAGE_SIZE / 4) 50#define PTRS_PER_PGD (PAGE_SIZE / sizeof(pgd_t))
52 51
53#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) 52#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
54#define FIRST_USER_ADDRESS 0 53#define FIRST_USER_ADDRESS 0
@@ -100,17 +99,18 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
100#define _PAGE_HW_SHARED 0x002 /* SH-bit : shared among processes */ 99#define _PAGE_HW_SHARED 0x002 /* SH-bit : shared among processes */
101#define _PAGE_DIRTY 0x004 /* D-bit : page changed */ 100#define _PAGE_DIRTY 0x004 /* D-bit : page changed */
102#define _PAGE_CACHABLE 0x008 /* C-bit : cachable */ 101#define _PAGE_CACHABLE 0x008 /* C-bit : cachable */
103#ifndef CONFIG_X2TLB 102#define _PAGE_SZ0 0x010 /* SZ0-bit : Size of page */
104# define _PAGE_SZ0 0x010 /* SZ0-bit : Size of page */ 103#define _PAGE_RW 0x020 /* PR0-bit : write access allowed */
105# define _PAGE_RW 0x020 /* PR0-bit : write access allowed */ 104#define _PAGE_USER 0x040 /* PR1-bit : user space access allowed*/
106# define _PAGE_USER 0x040 /* PR1-bit : user space access allowed*/ 105#define _PAGE_SZ1 0x080 /* SZ1-bit : Size of page (on SH-4) */
107# define _PAGE_SZ1 0x080 /* SZ1-bit : Size of page (on SH-4) */
108#endif
109#define _PAGE_PRESENT 0x100 /* V-bit : page is valid */ 106#define _PAGE_PRESENT 0x100 /* V-bit : page is valid */
110#define _PAGE_PROTNONE 0x200 /* software: if not present */ 107#define _PAGE_PROTNONE 0x200 /* software: if not present */
111#define _PAGE_ACCESSED 0x400 /* software: page referenced */ 108#define _PAGE_ACCESSED 0x400 /* software: page referenced */
112#define _PAGE_FILE _PAGE_WT /* software: pagecache or swap? */ 109#define _PAGE_FILE _PAGE_WT /* software: pagecache or swap? */
113 110
111#define _PAGE_SZ_MASK (_PAGE_SZ0 | _PAGE_SZ1)
112#define _PAGE_PR_MASK (_PAGE_RW | _PAGE_USER)
113
114/* Extended mode bits */ 114/* Extended mode bits */
115#define _PAGE_EXT_ESZ0 0x0010 /* ESZ0-bit: Size of page */ 115#define _PAGE_EXT_ESZ0 0x0010 /* ESZ0-bit: Size of page */
116#define _PAGE_EXT_ESZ1 0x0020 /* ESZ1-bit: Size of page */ 116#define _PAGE_EXT_ESZ1 0x0020 /* ESZ1-bit: Size of page */
@@ -126,11 +126,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
126#define _PAGE_EXT_KERN_READ 0x2000 /* EPR5-bit: Kernel space readable */ 126#define _PAGE_EXT_KERN_READ 0x2000 /* EPR5-bit: Kernel space readable */
127 127
128/* Wrapper for extended mode pgprot twiddling */ 128/* Wrapper for extended mode pgprot twiddling */
129#ifdef CONFIG_X2TLB 129#define _PAGE_EXT(x) ((unsigned long long)(x) << 32)
130# define _PAGE_EXT(x) ((unsigned long long)(x) << 32)
131#else
132# define _PAGE_EXT(x) (0)
133#endif
134 130
135/* software: moves to PTEA.TC (Timing Control) */ 131/* software: moves to PTEA.TC (Timing Control) */
136#define _PAGE_PCC_AREA5 0x00000000 /* use BSC registers for area5 */ 132#define _PAGE_PCC_AREA5 0x00000000 /* use BSC registers for area5 */
@@ -146,10 +142,14 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
146#define _PAGE_PCC_ATR16 0x60000001 /* Attribute Memory space, 6 bit bus */ 142#define _PAGE_PCC_ATR16 0x60000001 /* Attribute Memory space, 6 bit bus */
147 143
148/* Mask which drops unused bits from the PTEL value */ 144/* Mask which drops unused bits from the PTEL value */
149#ifdef CONFIG_CPU_SH3 145#if defined(CONFIG_CPU_SH3)
150#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED| \ 146#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED| \
151 _PAGE_FILE | _PAGE_SZ1 | \ 147 _PAGE_FILE | _PAGE_SZ1 | \
152 _PAGE_HW_SHARED) 148 _PAGE_HW_SHARED)
149#elif defined(CONFIG_X2TLB)
150/* Get rid of the legacy PR/SZ bits when using extended mode */
151#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED | \
152 _PAGE_FILE | _PAGE_PR_MASK | _PAGE_SZ_MASK)
153#else 153#else
154#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED | _PAGE_FILE) 154#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED | _PAGE_FILE)
155#endif 155#endif
@@ -212,27 +212,36 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
212 212
213#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ 213#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
214 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ 214 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
215 _PAGE_EXT(_PAGE_EXT_USER_READ | \ 215 _PAGE_EXT(_PAGE_EXT_KERN_READ | \
216 _PAGE_EXT_KERN_WRITE | \
217 _PAGE_EXT_USER_READ | \
216 _PAGE_EXT_USER_WRITE)) 218 _PAGE_EXT_USER_WRITE))
217 219
218#define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ 220#define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
219 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ 221 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
220 _PAGE_EXT(_PAGE_EXT_USER_EXEC | \ 222 _PAGE_EXT(_PAGE_EXT_KERN_EXEC | \
223 _PAGE_EXT_KERN_READ | \
224 _PAGE_EXT_USER_EXEC | \
221 _PAGE_EXT_USER_READ)) 225 _PAGE_EXT_USER_READ))
222 226
223#define PAGE_COPY PAGE_EXECREAD 227#define PAGE_COPY PAGE_EXECREAD
224 228
225#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ 229#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
226 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ 230 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
227 _PAGE_EXT(_PAGE_EXT_USER_READ)) 231 _PAGE_EXT(_PAGE_EXT_KERN_READ | \
232 _PAGE_EXT_USER_READ))
228 233
229#define PAGE_WRITEONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ 234#define PAGE_WRITEONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
230 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ 235 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
231 _PAGE_EXT(_PAGE_EXT_USER_WRITE)) 236 _PAGE_EXT(_PAGE_EXT_KERN_WRITE | \
237 _PAGE_EXT_USER_WRITE))
232 238
233#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ 239#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
234 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ 240 _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
235 _PAGE_EXT(_PAGE_EXT_USER_WRITE | \ 241 _PAGE_EXT(_PAGE_EXT_KERN_WRITE | \
242 _PAGE_EXT_KERN_READ | \
243 _PAGE_EXT_KERN_EXEC | \
244 _PAGE_EXT_USER_WRITE | \
236 _PAGE_EXT_USER_READ | \ 245 _PAGE_EXT_USER_READ | \
237 _PAGE_EXT_USER_EXEC)) 246 _PAGE_EXT_USER_EXEC))
238 247
@@ -373,11 +382,15 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
373#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) 382#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
374 383
375#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) 384#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
376#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
377#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
378 385
379#define pte_none(x) (!pte_val(x)) 386#define pfn_pte(pfn, prot) \
380#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) 387 __pte(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
388#define pfn_pmd(pfn, prot) \
389 __pmd(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
390
391#define pte_none(x) (!pte_val(x))
392#define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
393
381#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) 394#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
382 395
383#define pmd_none(x) (!pmd_val(x)) 396#define pmd_none(x) (!pmd_val(x))
@@ -392,15 +405,15 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
392 * The following only work if pte_present() is true. 405 * The following only work if pte_present() is true.
393 * Undefined behaviour if not.. 406 * Undefined behaviour if not..
394 */ 407 */
395#define pte_not_present(pte) (!(pte_val(pte) & _PAGE_PRESENT)) 408#define pte_not_present(pte) (!((pte).pte_low & _PAGE_PRESENT))
396#define pte_dirty(pte) (pte_val(pte) & _PAGE_DIRTY) 409#define pte_dirty(pte) ((pte).pte_low & _PAGE_DIRTY)
397#define pte_young(pte) (pte_val(pte) & _PAGE_ACCESSED) 410#define pte_young(pte) ((pte).pte_low & _PAGE_ACCESSED)
398#define pte_file(pte) (pte_val(pte) & _PAGE_FILE) 411#define pte_file(pte) ((pte).pte_low & _PAGE_FILE)
399 412
400#ifdef CONFIG_X2TLB 413#ifdef CONFIG_X2TLB
401#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE) 414#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE)
402#else 415#else
403#define pte_write(pte) (pte_val(pte) & _PAGE_RW) 416#define pte_write(pte) ((pte).pte_low & _PAGE_RW)
404#endif 417#endif
405 418
406#define PTE_BIT_FUNC(h,fn,op) \ 419#define PTE_BIT_FUNC(h,fn,op) \
@@ -429,17 +442,10 @@ PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED);
429/* 442/*
430 * Macro and implementation to make a page protection as uncachable. 443 * Macro and implementation to make a page protection as uncachable.
431 */ 444 */
432#define pgprot_noncached pgprot_noncached 445#define pgprot_writecombine(prot) \
446 __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE)
433 447
434static inline pgprot_t pgprot_noncached(pgprot_t _prot) 448#define pgprot_noncached pgprot_writecombine
435{
436 unsigned long prot = pgprot_val(_prot);
437
438 prot &= ~_PAGE_CACHABLE;
439 return __pgprot(prot);
440}
441
442#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE)
443 449
444/* 450/*
445 * Conversion functions: convert a page and protection to a page entry, 451 * Conversion functions: convert a page and protection to a page entry,
@@ -451,28 +457,33 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
451 457
452static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 458static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
453{ 459{
454 set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | 460 pte.pte_low &= _PAGE_CHG_MASK;
455 pgprot_val(newprot))); 461 pte.pte_low |= pgprot_val(newprot);
462
463#ifdef CONFIG_X2TLB
464 pte.pte_high |= pgprot_val(newprot) >> 32;
465#endif
466
456 return pte; 467 return pte;
457} 468}
458 469
459#define pmd_page_vaddr(pmd) pmd_val(pmd) 470#define pmd_page_vaddr(pmd) ((unsigned long)pmd_val(pmd))
460#define pmd_page(pmd) (virt_to_page(pmd_val(pmd))) 471#define pmd_page(pmd) (virt_to_page(pmd_val(pmd)))
461 472
462/* to find an entry in a page-table-directory. */ 473/* to find an entry in a page-table-directory. */
463#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) 474#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
464#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) 475#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
465 476
466/* to find an entry in a kernel page-table-directory */ 477/* to find an entry in a kernel page-table-directory */
467#define pgd_offset_k(address) pgd_offset(&init_mm, address) 478#define pgd_offset_k(address) pgd_offset(&init_mm, address)
468 479
469/* Find an entry in the third-level page table.. */ 480/* Find an entry in the third-level page table.. */
470#define pte_index(address) \ 481#define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
471 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
472#define pte_offset_kernel(dir, address) \ 482#define pte_offset_kernel(dir, address) \
473 ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) 483 ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address))
474#define pte_offset_map(dir, address) pte_offset_kernel(dir, address) 484#define pte_offset_map(dir, address) pte_offset_kernel(dir, address)
475#define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address) 485#define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address)
486
476#define pte_unmap(pte) do { } while (0) 487#define pte_unmap(pte) do { } while (0)
477#define pte_unmap_nested(pte) do { } while (0) 488#define pte_unmap_nested(pte) do { } while (0)
478 489
@@ -480,13 +491,14 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
480#define pte_ERROR(e) \ 491#define pte_ERROR(e) \
481 printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, \ 492 printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, \
482 &(e), (e).pte_high, (e).pte_low) 493 &(e), (e).pte_high, (e).pte_low)
494#define pgd_ERROR(e) \
495 printk("%s:%d: bad pgd %016llx.\n", __FILE__, __LINE__, pgd_val(e))
483#else 496#else
484#define pte_ERROR(e) \ 497#define pte_ERROR(e) \
485 printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) 498 printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
486#endif
487
488#define pgd_ERROR(e) \ 499#define pgd_ERROR(e) \
489 printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) 500 printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
501#endif
490 502
491struct vm_area_struct; 503struct vm_area_struct;
492extern void update_mmu_cache(struct vm_area_struct * vma, 504extern void update_mmu_cache(struct vm_area_struct * vma,