To use page level descriptors we need some pgd/pud/pmd/pte
methods, and a few more flags defined.

Signed-off-by: Andrew Jones <[email protected]>
---
 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to