Signed-off-by: Andrew Jones <[email protected]>
---
 lib/arm64/asm/page.h          |  66 +++++++++++++++++++-
 lib/arm64/asm/pgtable-hwdef.h | 136 ++++++++++++++++++++++++++++++++++++++++++
 lib/arm64/asm/pgtable.h       |  69 +++++++++++++++++++++
 3 files changed, 270 insertions(+), 1 deletion(-)
 create mode 100644 lib/arm64/asm/pgtable-hwdef.h
 create mode 100644 lib/arm64/asm/pgtable.h

diff --git a/lib/arm64/asm/page.h b/lib/arm64/asm/page.h
index 395760cad5f82..29ad1f1f720c4 100644
--- a/lib/arm64/asm/page.h
+++ b/lib/arm64/asm/page.h
@@ -1 +1,65 @@
-#include "../../arm/asm/page.h"
+#ifndef _ASMARM64_PAGE_H_
+#define _ASMARM64_PAGE_H_
+/*
+ * Adapted from
+ *   arch/arm64/include/asm/pgtable-types.h
+ *   include/asm-generic/pgtable-nopud.h
+ *   include/asm-generic/pgtable-nopmd.h
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+
+#include <const.h>
+
+#define PGTABLE_LEVELS         2
+#define VA_BITS                        42
+
+#define PAGE_SHIFT             16
+#define PAGE_SIZE              (_AC(1,UL) << PAGE_SHIFT)
+#define PAGE_MASK              (~(PAGE_SIZE-1))
+
+#ifndef __ASSEMBLY__
+
+#define PAGE_ALIGN(addr)       ALIGN(addr, PAGE_SIZE)
+
+#include <alloc.h>
+
+typedef u64 pteval_t;
+typedef u64 pmdval_t;
+typedef u64 pudval_t;
+typedef u64 pgdval_t;
+typedef struct { pteval_t pte; } pte_t;
+typedef struct { pgdval_t pgd; } pgd_t;
+typedef struct { pteval_t pgprot; } pgprot_t;
+
+#define pte_val(x)             ((x).pte)
+#define pgd_val(x)             ((x).pgd)
+#define pgprot_val(x)          ((x).pgprot)
+
+#define __pte(x)               ((pte_t) { (x) } )
+#define __pgd(x)               ((pgd_t) { (x) } )
+#define __pgprot(x)            ((pgprot_t) { (x) } )
+
+typedef struct { pgd_t pgd; } pud_t;
+#define pud_val(x)             (pgd_val((x).pgd))
+#define __pud(x)               ((pud_t) { __pgd(x) } )
+
+typedef struct { pud_t pud; } pmd_t;
+#define pmd_val(x)             (pud_val((x).pud))
+#define __pmd(x)               ((pmd_t) { __pud(x) } )
+
+#ifndef __virt_to_phys
+#define __phys_to_virt(x)      ((unsigned long) (x))
+#define __virt_to_phys(x)      (x)
+#endif
+
+#define __va(x)                        ((void 
*)__phys_to_virt((phys_addr_t)(x)))
+#define __pa(x)                        __virt_to_phys((unsigned long)(x))
+
+#define virt_to_pfn(kaddr)     (__pa(kaddr) >> PAGE_SHIFT)
+#define pfn_to_virt(pfn)       __va((pfn) << PAGE_SHIFT)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM64_PAGE_H_ */
diff --git a/lib/arm64/asm/pgtable-hwdef.h b/lib/arm64/asm/pgtable-hwdef.h
new file mode 100644
index 0000000000000..20ac9fa402987
--- /dev/null
+++ b/lib/arm64/asm/pgtable-hwdef.h
@@ -0,0 +1,136 @@
+#ifndef _ASMARM64_PGTABLE_HWDEF_H_
+#define _ASMARM64_PGTABLE_HWDEF_H_
+/*
+ * From arch/arm64/include/asm/pgtable-hwdef.h
+ *      arch/arm64/include/asm/memory.h
+ */
+#define UL(x) _AC(x, UL)
+
+#define PTRS_PER_PTE           (1 << (PAGE_SHIFT - 3))
+
+/*
+ * PGDIR_SHIFT determines the size a top-level page table entry can map
+ * (depending on the configuration, this level can be 0, 1 or 2).
+ */
+#define PGDIR_SHIFT            ((PAGE_SHIFT - 3) * PGTABLE_LEVELS + 3)
+#define PGDIR_SIZE             (_AC(1, UL) << PGDIR_SHIFT)
+#define PGDIR_MASK             (~(PGDIR_SIZE-1))
+#define PTRS_PER_PGD           (1 << (VA_BITS - PGDIR_SHIFT))
+
+/* From include/asm-generic/pgtable-nopud.h */
+#define PUD_SHIFT              PGDIR_SHIFT
+#define PTRS_PER_PUD           1
+#define PUD_SIZE               (UL(1) << PUD_SHIFT)
+#define PUD_MASK               (~(PUD_SIZE-1))
+/* From include/asm-generic/pgtable-nopmd.h */
+#define PMD_SHIFT              PUD_SHIFT
+#define PTRS_PER_PMD           1
+#define PMD_SIZE               (UL(1) << PMD_SHIFT)
+#define PMD_MASK               (~(PMD_SIZE-1))
+
+/*
+ * Section address mask and size definitions.
+ */
+#define SECTION_SHIFT          PMD_SHIFT
+#define SECTION_SIZE           (_AC(1, UL) << SECTION_SHIFT)
+#define SECTION_MASK           (~(SECTION_SIZE-1))
+
+/*
+ * Hardware page table definitions.
+ *
+ * Level 1 descriptor (PUD).
+ */
+#define PUD_TYPE_TABLE         (_AT(pudval_t, 3) << 0)
+#define PUD_TABLE_BIT          (_AT(pgdval_t, 1) << 1)
+#define PUD_TYPE_MASK          (_AT(pgdval_t, 3) << 0)
+#define PUD_TYPE_SECT          (_AT(pgdval_t, 1) << 0)
+
+/*
+ * Level 2 descriptor (PMD).
+ */
+#define PMD_TYPE_MASK          (_AT(pmdval_t, 3) << 0)
+#define PMD_TYPE_FAULT         (_AT(pmdval_t, 0) << 0)
+#define PMD_TYPE_TABLE         (_AT(pmdval_t, 3) << 0)
+#define PMD_TYPE_SECT          (_AT(pmdval_t, 1) << 0)
+#define PMD_TABLE_BIT          (_AT(pmdval_t, 1) << 1)
+
+/*
+ * Section
+ */
+#define PMD_SECT_VALID         (_AT(pmdval_t, 1) << 0)
+#define PMD_SECT_PROT_NONE     (_AT(pmdval_t, 1) << 58)
+#define PMD_SECT_USER          (_AT(pmdval_t, 1) << 6)         /* AP[1] */
+#define PMD_SECT_RDONLY                (_AT(pmdval_t, 1) << 7)         /* 
AP[2] */
+#define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
+#define PMD_SECT_AF            (_AT(pmdval_t, 1) << 10)
+#define PMD_SECT_NG            (_AT(pmdval_t, 1) << 11)
+#define PMD_SECT_PXN           (_AT(pmdval_t, 1) << 53)
+#define PMD_SECT_UXN           (_AT(pmdval_t, 1) << 54)
+
+/*
+ * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
+ */
+#define PMD_ATTRINDX(t)                (_AT(pmdval_t, (t)) << 2)
+#define PMD_ATTRINDX_MASK      (_AT(pmdval_t, 7) << 2)
+
+/*
+ * Level 3 descriptor (PTE).
+ */
+#define PTE_TYPE_MASK          (_AT(pteval_t, 3) << 0)
+#define PTE_TYPE_FAULT         (_AT(pteval_t, 0) << 0)
+#define PTE_TYPE_PAGE          (_AT(pteval_t, 3) << 0)
+#define PTE_TABLE_BIT          (_AT(pteval_t, 1) << 1)
+#define PTE_USER               (_AT(pteval_t, 1) << 6)         /* AP[1] */
+#define PTE_RDONLY             (_AT(pteval_t, 1) << 7)         /* AP[2] */
+#define PTE_SHARED             (_AT(pteval_t, 3) << 8)         /* SH[1:0], 
inner shareable */
+#define PTE_AF                 (_AT(pteval_t, 1) << 10)        /* Access Flag 
*/
+#define PTE_NG                 (_AT(pteval_t, 1) << 11)        /* nG */
+#define PTE_PXN                        (_AT(pteval_t, 1) << 53)        /* 
Privileged XN */
+#define PTE_UXN                        (_AT(pteval_t, 1) << 54)        /* User 
XN */
+
+/*
+ * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
+ */
+#define PTE_ATTRINDX(t)                (_AT(pteval_t, (t)) << 2)
+#define PTE_ATTRINDX_MASK      (_AT(pteval_t, 7) << 2)
+
+/*
+ * Highest possible physical address supported.
+ */
+#define PHYS_MASK_SHIFT                (48)
+#define PHYS_MASK              ((UL(1) << PHYS_MASK_SHIFT) - 1)
+
+/*
+ * TCR flags.
+ */
+#define TCR_TxSZ(x)            (((UL(64) - (x)) << 16) | ((UL(64) - (x)) << 0))
+#define TCR_IRGN_NC            ((UL(0) << 8) | (UL(0) << 24))
+#define TCR_IRGN_WBWA          ((UL(1) << 8) | (UL(1) << 24))
+#define TCR_IRGN_WT            ((UL(2) << 8) | (UL(2) << 24))
+#define TCR_IRGN_WBnWA         ((UL(3) << 8) | (UL(3) << 24))
+#define TCR_IRGN_MASK          ((UL(3) << 8) | (UL(3) << 24))
+#define TCR_ORGN_NC            ((UL(0) << 10) | (UL(0) << 26))
+#define TCR_ORGN_WBWA          ((UL(1) << 10) | (UL(1) << 26))
+#define TCR_ORGN_WT            ((UL(2) << 10) | (UL(2) << 26))
+#define TCR_ORGN_WBnWA         ((UL(3) << 10) | (UL(3) << 26))
+#define TCR_ORGN_MASK          ((UL(3) << 10) | (UL(3) << 26))
+#define TCR_SHARED             ((UL(3) << 12) | (UL(3) << 28))
+#define TCR_TG0_4K             (UL(0) << 14)
+#define TCR_TG0_64K            (UL(1) << 14)
+#define TCR_TG0_16K            (UL(2) << 14)
+#define TCR_TG1_16K            (UL(1) << 30)
+#define TCR_TG1_4K             (UL(2) << 30)
+#define TCR_TG1_64K            (UL(3) << 30)
+#define TCR_ASID16             (UL(1) << 36)
+#define TCR_TBI0               (UL(1) << 37)
+
+/*
+ * Memory types available.
+ */
+#define MT_DEVICE_nGnRnE       0       /* noncached */
+#define MT_DEVICE_nGnRE                1       /* device */
+#define MT_DEVICE_GRE          2
+#define MT_NORMAL_NC           3       /* writecombine */
+#define MT_NORMAL              4
+
+#endif /* _ASMARM64_PGTABLE_HWDEF_H_ */
diff --git a/lib/arm64/asm/pgtable.h b/lib/arm64/asm/pgtable.h
new file mode 100644
index 0000000000000..3635b075682ad
--- /dev/null
+++ b/lib/arm64/asm/pgtable.h
@@ -0,0 +1,69 @@
+#ifndef _ASMARM64_PGTABLE_H_
+#define _ASMARM64_PGTABLE_H_
+/*
+ * Adapted from arch/arm64/include/asm/pgtable.h
+ *              include/asm-generic/pgtable-nopmd.h
+ *              include/asm-generic/pgtable-nopud.h
+ *              include/linux/mm.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(PAGE_SIZE, 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)
+
+#define pmd_offset(pud, addr)  ((pmd_t *)pud)
+#define pmd_free(pmd)
+#define pmd_alloc(pud, addr)   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 /* _ASMARM64_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