diff options
Diffstat (limited to 'arch/mips/include/asm/pgtable-64.h')
-rw-r--r-- | arch/mips/include/asm/pgtable-64.h | 88 |
1 files changed, 83 insertions, 5 deletions
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index 130a2a6c1531..67fe6dc5211c 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h @@ -20,7 +20,7 @@ #define __ARCH_USE_5LEVEL_HACK #if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48) #include <asm-generic/pgtable-nopmd.h> -#else +#elif !(defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_MIPS_VA_BITS_48)) #include <asm-generic/pgtable-nopud.h> #endif @@ -54,9 +54,18 @@ #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) +# ifdef __PAGETABLE_PUD_FOLDED +# define PGDIR_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3)) +# endif +#endif -#define PGDIR_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3)) +#ifndef __PAGETABLE_PUD_FOLDED +#define PUD_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3)) +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE-1)) +#define PGDIR_SHIFT (PUD_SHIFT + (PAGE_SHIFT + PUD_ORDER - 3)) #endif + #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) @@ -79,8 +88,13 @@ * of virtual address space. */ #ifdef CONFIG_PAGE_SIZE_4KB -#define PGD_ORDER 1 -#define PUD_ORDER aieeee_attempt_to_allocate_pud +# ifdef CONFIG_MIPS_VA_BITS_48 +# define PGD_ORDER 0 +# define PUD_ORDER 0 +# else +# define PGD_ORDER 1 +# define PUD_ORDER aieeee_attempt_to_allocate_pud +# endif #define PMD_ORDER 0 #define PTE_ORDER 0 #endif @@ -118,6 +132,9 @@ #endif #define PTRS_PER_PGD ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t)) +#ifndef __PAGETABLE_PUD_FOLDED +#define PTRS_PER_PUD ((PAGE_SIZE << PUD_ORDER) / sizeof(pud_t)) +#endif #ifndef __PAGETABLE_PMD_FOLDED #define PTRS_PER_PMD ((PAGE_SIZE << PMD_ORDER) / sizeof(pmd_t)) #endif @@ -134,7 +151,7 @@ #define VMALLOC_START (MAP_BASE + (2 * PAGE_SIZE)) #define VMALLOC_END \ (MAP_BASE + \ - min(PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, \ + min(PTRS_PER_PGD * PTRS_PER_PUD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, \ (1UL << cpu_vmbits)) - (1UL << 32)) #if defined(CONFIG_MODULES) && defined(KBUILD_64BIT_SYM32) && \ @@ -150,12 +167,72 @@ #define pmd_ERROR(e) \ printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e)) #endif +#ifndef __PAGETABLE_PUD_FOLDED +#define pud_ERROR(e) \ + printk("%s:%d: bad pud %016lx.\n", __FILE__, __LINE__, pud_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_PUD_FOLDED +/* + * For 4-level pagetables we defines these ourselves, for 3-level the + * definitions are below, for 2-level the + * definitions are supplied by <asm-generic/pgtable-nopmd.h>. + */ +typedef struct { unsigned long pud; } pud_t; +#define pud_val(x) ((x).pud) +#define __pud(x) ((pud_t) { (x) }) + +extern pud_t invalid_pud_table[PTRS_PER_PUD]; + +/* + * Empty pgd entries point to the invalid_pud_table. + */ +static inline int pgd_none(pgd_t pgd) +{ + return pgd_val(pgd) == (unsigned long)invalid_pud_table; +} + +static inline int pgd_bad(pgd_t pgd) +{ + if (unlikely(pgd_val(pgd) & ~PAGE_MASK)) + return 1; + + return 0; +} + +static inline int pgd_present(pgd_t pgd) +{ + return pgd_val(pgd) != (unsigned long)invalid_pud_table; +} + +static inline void pgd_clear(pgd_t *pgdp) +{ + pgd_val(*pgdp) = (unsigned long)invalid_pud_table; +} + +#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) + +static inline unsigned long pgd_page_vaddr(pgd_t pgd) +{ + return pgd_val(pgd); +} + +static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) +{ + return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address); +} + +static inline void set_pgd(pgd_t *pgd, pgd_t pgdval) +{ + *pgd = pgdval; +} + +#endif #ifndef __PAGETABLE_PMD_FOLDED /* @@ -281,6 +358,7 @@ static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) * Initialize a new pgd / pmd table with invalid pointers. */ extern void pgd_init(unsigned long page); +extern void pud_init(unsigned long page, unsigned long pagetable); extern void pmd_init(unsigned long page, unsigned long pagetable); /* |