diff options
Diffstat (limited to 'arch/mips/include/asm/pgtable-64.h')
| -rw-r--r-- | arch/mips/include/asm/pgtable-64.h | 81 |
1 files changed, 65 insertions, 16 deletions
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index 9cd50899395..e1c49a96807 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h @@ -9,6 +9,7 @@ #ifndef _ASM_PGTABLE_64_H #define _ASM_PGTABLE_64_H +#include <linux/compiler.h> #include <linux/linkage.h> #include <asm/addrspace.h> @@ -16,7 +17,11 @@ #include <asm/cachectl.h> #include <asm/fixmap.h> +#ifdef CONFIG_PAGE_SIZE_64KB +#include <asm-generic/pgtable-nopmd.h> +#else #include <asm-generic/pgtable-nopud.h> +#endif /* * Each address space has 2 4K pages as its page directory, giving 1024 @@ -37,13 +42,20 @@ * fault address - VMALLOC_START. */ + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#ifdef __PAGETABLE_PMD_FOLDED +#define PGDIR_SHIFT (PAGE_SHIFT + PAGE_SHIFT + PTE_ORDER - 3) +#else + /* PMD_SHIFT determines the size of the area a second-level page table can map */ #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT + PTE_ORDER - 3)) #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) -/* PGDIR_SHIFT determines what a third-level page table entry can map */ + #define PGDIR_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3)) +#endif #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) @@ -92,25 +104,34 @@ #ifdef CONFIG_PAGE_SIZE_64KB #define PGD_ORDER 0 #define PUD_ORDER aieeee_attempt_to_allocate_pud -#define PMD_ORDER 0 +#define PMD_ORDER aieeee_attempt_to_allocate_pmd #define PTE_ORDER 0 #endif #define PTRS_PER_PGD ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t)) +#ifndef __PAGETABLE_PMD_FOLDED #define PTRS_PER_PMD ((PAGE_SIZE << PMD_ORDER) / sizeof(pmd_t)) +#endif #define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) -#if PGDIR_SIZE >= TASK_SIZE -#define USER_PTRS_PER_PGD (1) +#if PGDIR_SIZE >= TASK_SIZE64 +#define USER_PTRS_PER_PGD (1) #else -#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) +#define USER_PTRS_PER_PGD (TASK_SIZE64 / PGDIR_SIZE) #endif #define FIRST_USER_ADDRESS 0UL -#define VMALLOC_START MAP_BASE +/* + * TLB refill handlers also map the vmalloc area into xuseg. Avoid + * the first couple of pages so NULL pointer dereferences will still + * reliably trap. + */ +#define VMALLOC_START (MAP_BASE + (2 * PAGE_SIZE)) #define VMALLOC_END \ - (VMALLOC_START + \ - PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE - (1UL << 32)) + (MAP_BASE + \ + min(PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, \ + (1UL << cpu_vmbits)) - (1UL << 32)) + #if defined(CONFIG_MODULES) && defined(KBUILD_64BIT_SYM32) && \ VMALLOC_START != CKSSEG /* Load modules into 32bit-compatible segment. */ @@ -120,15 +141,29 @@ #define pte_ERROR(e) \ printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) +#ifndef __PAGETABLE_PMD_FOLDED #define pmd_ERROR(e) \ printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e)) +#endif #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e)) extern pte_t invalid_pte_table[PTRS_PER_PTE]; extern pte_t empty_bad_page_table[PTRS_PER_PTE]; + + +#ifndef __PAGETABLE_PMD_FOLDED +/* + * For 3-level pagetables we defines these ourselves, for 2-level the + * definitions are supplied by <asm-generic/pgtable-nopmd.h>. + */ +typedef struct { unsigned long pmd; } pmd_t; +#define pmd_val(x) ((x).pmd) +#define __pmd(x) ((pmd_t) { (x) } ) + + extern pmd_t invalid_pmd_table[PTRS_PER_PMD]; -extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD]; +#endif /* * Empty pgd/pmd entries point to the invalid_pte_table. @@ -138,7 +173,19 @@ static inline int pmd_none(pmd_t pmd) return pmd_val(pmd) == (unsigned long) invalid_pte_table; } -#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) +static inline int pmd_bad(pmd_t pmd) +{ +#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT + /* pmd_huge(pmd) but inline */ + if (unlikely(pmd_val(pmd) & _PAGE_HUGE)) + return 0; +#endif + + if (unlikely(pmd_val(pmd) & ~PAGE_MASK)) + return 1; + + return 0; +} static inline int pmd_present(pmd_t pmd) { @@ -149,6 +196,7 @@ static inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = ((unsigned long) invalid_pte_table); } +#ifndef __PAGETABLE_PMD_FOLDED /* * Empty pud entries point to the invalid_pmd_table. @@ -172,6 +220,7 @@ static inline void pud_clear(pud_t *pudp) { pud_val(*pudp) = ((unsigned long) invalid_pmd_table); } +#endif #define pte_page(x) pfn_to_page(pte_pfn(x)) @@ -179,8 +228,9 @@ static inline void pud_clear(pud_t *pudp) #define pte_pfn(x) ((unsigned long)((x).pte >> (PAGE_SHIFT + 2))) #define pfn_pte(pfn, prot) __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot)) #else -#define pte_pfn(x) ((unsigned long)((x).pte >> PAGE_SHIFT)) -#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) +#define pte_pfn(x) ((unsigned long)((x).pte >> _PFN_SHIFT)) +#define pfn_pte(pfn, prot) __pte(((pfn) << _PFN_SHIFT) | pgprot_val(prot)) +#define pfn_pmd(pfn, prot) __pmd(((pfn) << _PFN_SHIFT) | pgprot_val(prot)) #endif #define __pgd_offset(address) pgd_index(address) @@ -196,6 +246,7 @@ static inline void pud_clear(pud_t *pudp) /* to find an entry in a page-table-directory */ #define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr)) +#ifndef __PAGETABLE_PMD_FOLDED static inline unsigned long pud_page_vaddr(pud_t pud) { return pud_val(pud); @@ -208,6 +259,7 @@ static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) { return (pmd_t *) pud_page_vaddr(*pud) + pmd_index(address); } +#endif /* Find an entry in the third-level page table.. */ #define __pte_offset(address) \ @@ -218,10 +270,7 @@ static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) #define pte_offset_map(dir, address) \ ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) -#define pte_offset_map_nested(dir, address) \ - ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) #define pte_unmap(pte) ((void)(pte)) -#define pte_unmap_nested(pte) ((void)(pte)) /* * Initialize a new pgd / pmd table with invalid pointers. @@ -239,7 +288,7 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) #define __swp_type(x) (((x).val >> 32) & 0xff) #define __swp_offset(x) ((x).val >> 40) #define __swp_entry(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type), (offset))) }) -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) /* |
