diff options
author | Alex Belits <alex.belits@cavium.com> | 2017-02-17 04:27:34 +0300 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2017-04-10 12:56:06 +0300 |
commit | 3377e227af441aff710726437adc20efc359fd9c (patch) | |
tree | d05610ba07eca74f783b42fbbd5110b7876d8c9b /arch/mips/include/asm/pgtable-64.h | |
parent | dfa32261fa0ed1821c7d5dbb9e93eddfe311a0d9 (diff) | |
download | linux-3377e227af441aff710726437adc20efc359fd9c.tar.xz |
MIPS: Add 48-bit VA space (and 4-level page tables) for 4K pages.
Some users must have 4K pages while needing a 48-bit VA space size.
The cleanest way do do this is to go to a 4-level page table for this
case. Each page table level using order-0 pages adds 9 bits to the
VA size (at 4K pages, so for four levels we get 9 * 4 + 12 == 48-bits.
For the 4K page size case only we add support functions for the PUD
level of the page table tree, also the TLB exception handlers get an
extra level of tree walk.
[david.daney@cavium.com: Forward port to v4.10.]
[david.daney@cavium.com: Forward port to v4.11.]
Signed-off-by: Alex Belits <alex.belits@cavium.com>
Signed-off-by: David Daney <david.daney@cavium.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Alex Belits <alex.belits@cavium.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/15312/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
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); /* |