To use page level descriptors we need some pgd/pud/pmd/pte methods, and a few more flags defined. Signed-off-by: Andrew Jones <drjones@xxxxxxxxxx> --- lib/arm/asm/mmu.h | 16 +------- lib/arm/asm/pgtable-hwdef.h | 38 ++++++++++++++++++- lib/arm/asm/pgtable.h | 91 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 16 deletions(-) create mode 100644 lib/arm/asm/pgtable.h diff --git a/lib/arm/asm/mmu.h b/lib/arm/asm/mmu.h index 8090a1b554820..254c29f84fe6f 100644 --- a/lib/arm/asm/mmu.h +++ b/lib/arm/asm/mmu.h @@ -5,22 +5,8 @@ * * This work is licensed under the terms of the GNU LGPL, version 2. */ -#include <asm/setup.h> +#include <asm/pgtable.h> #include <asm/barrier.h> -#include <alloc.h> - -#define PTRS_PER_PGD 4 -#define PGDIR_SHIFT 30 -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~((1 << PGDIR_SHIFT) - 1)) - -#define pgd_free(pgd) free(pgd) -static inline pgd_t *pgd_alloc(void) -{ - pgd_t *pgd = memalign(L1_CACHE_BYTES, PTRS_PER_PGD * sizeof(pgd_t)); - memset(pgd, 0, PTRS_PER_PGD * sizeof(pgd_t)); - return pgd; -} static inline void local_flush_tlb_all(void) { diff --git a/lib/arm/asm/pgtable-hwdef.h b/lib/arm/asm/pgtable-hwdef.h index b6850f64b0f52..13a273d36e8fe 100644 --- a/lib/arm/asm/pgtable-hwdef.h +++ b/lib/arm/asm/pgtable-hwdef.h @@ -1,9 +1,45 @@ #ifndef _ASMARM_PGTABLE_HWDEF_H_ #define _ASMARM_PGTABLE_HWDEF_H_ /* - * From arch/arm/include/asm/pgtable-3level-hwdef.h + * From arch/arm/include/asm/pgtable-3level.h + * arch/arm/include/asm/pgtable-3level-hwdef.h */ +#define PTRS_PER_PGD 4 +#define PGDIR_SHIFT 30 +#define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT) +#define PGDIR_MASK (~((1 << PGDIR_SHIFT) - 1)) + +#define PTRS_PER_PTE 512 +#define PTRS_PER_PMD 512 + +#define PMD_SHIFT 21 +#define PMD_SIZE (_AC(1,UL) << PMD_SHIFT) +#define PMD_MASK (~((1 << PMD_SHIFT) - 1)) + +#define L_PMD_SECT_VALID (_AT(pmdval_t, 1) << 0) + +#define L_PTE_VALID (_AT(pteval_t, 1) << 0) /* Valid */ +#define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Present */ +#define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ +#define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ +#define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */ +#define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ + +/* + * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). + */ +#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0) << 2) /* strongly ordered */ +#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 1) << 2) /* normal non-cacheable */ +#define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 2) << 2) /* normal inner write-through */ +#define L_PTE_MT_WRITEBACK (_AT(pteval_t, 3) << 2) /* normal inner write-back */ +#define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 7) << 2) /* normal inner write-alloc */ +#define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 4) << 2) /* device */ +#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 4) << 2) /* device */ +#define L_PTE_MT_DEV_WC (_AT(pteval_t, 1) << 2) /* normal non-cacheable */ +#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 3) << 2) /* normal inner write-back */ +#define L_PTE_MT_MASK (_AT(pteval_t, 7) << 2) + /* * Hardware page table definitions. * diff --git a/lib/arm/asm/pgtable.h b/lib/arm/asm/pgtable.h new file mode 100644 index 0000000000000..8a730f44e537b --- /dev/null +++ b/lib/arm/asm/pgtable.h @@ -0,0 +1,91 @@ +#ifndef _ASMARM_PGTABLE_H_ +#define _ASMARM_PGTABLE_H_ +/* + * Adapted from arch/arm/include/asm/pgtable.h + * arch/arm/include/asm/pgtable-3level.h + * arch/arm/include/asm/pgalloc.h + * include/asm-generic/pgtable-nopud.h + * + * Note: some Linux function APIs have been modified. Nothing crazy, + * but if a function took, for example, an mm_struct, then + * that was either removed or replaced. + */ +#include <alloc.h> +#include <asm/setup.h> +#include <asm/page.h> +#include <asm/pgtable-hwdef.h> + +#define pgd_none(pgd) (!pgd_val(pgd)) +#define pud_none(pud) (!pud_val(pud)) +#define pmd_none(pmd) (!pmd_val(pmd)) +#define pte_none(pte) (!pte_val(pte)) + +#define pgd_index(addr) \ + (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) +#define pgd_offset(pgtable, addr) ((pgtable) + pgd_index(addr)) + +#define pgd_free(pgd) free(pgd) +static inline pgd_t *pgd_alloc(void) +{ + pgd_t *pgd = memalign(L1_CACHE_BYTES, PTRS_PER_PGD * sizeof(pgd_t)); + memset(pgd, 0, PTRS_PER_PGD * sizeof(pgd_t)); + return pgd; +} + +#define pud_offset(pgd, addr) ((pud_t *)pgd) +#define pud_free(pud) +#define pud_alloc(pgd, addr) pud_offset(pgd, addr) + +static inline pmd_t *pud_page_vaddr(pud_t pud) +{ + return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK); +} + +#define pmd_index(addr) \ + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) +#define pmd_offset(pud, addr) \ + (pud_page_vaddr(*(pud)) + pmd_index(addr)) + +#define pmd_free(pmd) free(pmd) +static inline pmd_t *pmd_alloc_one(void) +{ + pmd_t *pmd = memalign(PAGE_SIZE, PTRS_PER_PMD * sizeof(pmd_t)); + memset(pmd, 0, PTRS_PER_PMD * sizeof(pmd_t)); + return pmd; +} +static inline pmd_t *pmd_alloc(pud_t *pud, unsigned long addr) +{ + if (pud_none(*pud)) { + pmd_t *pmd = pmd_alloc_one(); + pud_val(*pud) = __pa(pmd) | PMD_TYPE_TABLE; + } + return pmd_offset(pud, addr); +} + +static inline pte_t *pmd_page_vaddr(pmd_t pmd) +{ + return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK); +} + +#define pte_index(addr) \ + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) +#define pte_offset(pmd, addr) \ + (pmd_page_vaddr(*(pmd)) + pte_index(addr)) + +#define pte_free(pte) free(pte) +static inline pte_t *pte_alloc_one(void) +{ + pte_t *pte = memalign(PAGE_SIZE, PTRS_PER_PTE * sizeof(pte_t)); + memset(pte, 0, PTRS_PER_PTE * sizeof(pte_t)); + return pte; +} +static inline pte_t *pte_alloc(pmd_t *pmd, unsigned long addr) +{ + if (pmd_none(*pmd)) { + pte_t *pte = pte_alloc_one(); + pmd_val(*pmd) = __pa(pte) | PMD_TYPE_TABLE; + } + return pte_offset(pmd, addr); +} + +#endif /* _ASMARM_PGTABLE_H_ */ -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html