[PATCH Makedumpfile 09/10] arm64: Add support for 4level 4K page translations table

Pratyush Anand panand at redhat.com
Tue Oct 25 00:23:01 PDT 2016


From: Azriel Samson <asamson at codeaurora.org>

Add PUD translation for 4 level page tables.

Signed-off-by: Mansi Patel <mansip at codeaurora.org>
Signed-off-by: Azriel Samson <asamson at codeaurora.org>
Signed-off-by: Sameer Goel <sgoel at codeaurora.org>
Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index da8f43c62380..df58e92536e2 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -54,7 +54,9 @@ static int va_bits;
 #define PAGE_MASK		(~(PAGESIZE() - 1))
 #define PGDIR_SHIFT		((PAGESHIFT() - 3) * pgtable_level + 3)
 #define PTRS_PER_PGD		(1 << (va_bits - PGDIR_SHIFT))
+#define PUD_SHIFT		get_pud_shift_arm64()
 #define PTRS_PER_PTE		(1 << (PAGESHIFT() - 3))
+#define PTRS_PER_PUD		PTRS_PER_PTE
 #define PMD_SHIFT		((PAGESHIFT() - 3) * 2 + 3)
 #define PMD_SIZE		(1UL << PMD_SHIFT)
 #define PMD_MASK		(~(PMD_SIZE - 1))
@@ -89,6 +91,18 @@ static int va_bits;
 #define pmd_offset_pgtbl_lvl_2(pud, vaddr) ((pmd_t *)pud)
 #define pmd_offset_pgtbl_lvl_3(pud, vaddr) ((pmd_t *)pud_page_paddr((*pud)) + pmd_index(vaddr))
 
+#define pud_index(vaddr)		(((vaddr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
+#define pgd_page_paddr(pgd)		(pgd_val(pgd) & PHYS_MASK & (int32_t)PAGE_MASK)
+
+static int
+get_pud_shift_arm64(void)
+{
+	if (pgtable_level == 4)
+		return ((PAGESHIFT() - 3) * 3 + 3);
+	else
+		return PGDIR_SHIFT;
+}
+
 static pmd_t *
 pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 {
@@ -99,6 +113,15 @@ pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 	}
 }
 
+static pud_t *
+pud_offset(pgd_t *pgda, pgd_t *pgdv, unsigned long vaddr)
+{
+	if (pgtable_level == 4)
+		return ((pud_t *)pgd_page_paddr((*pgdv)) + pud_index(vaddr));
+	else
+		return (pud_t *)(pgda);
+}
+
 static int calculate_plat_config(void)
 {
 	va_bits = NUMBER(VA_BITS);
@@ -212,8 +235,11 @@ vaddr_to_paddr_arm64(unsigned long vaddr)
 		return NOT_PADDR;
 	}
 
-	pudv.pgd = pgdv;
-	puda = (pud_t *)pgda;
+	puda = pud_offset(pgda, &pgdv, vaddr);
+	if (!readmem(PADDR, (unsigned long long)puda, &pudv, sizeof(pudv))) {
+		ERRMSG("Can't read pud\n");
+		return NOT_PADDR;
+	}
 
 	pmda = pmd_offset(puda, &pudv, vaddr);
 	if (!readmem(PADDR, (unsigned long long)pmda, &pmdv, sizeof(pmdv))) {
-- 
2.7.4




More information about the kexec mailing list