[PATCH Makedumpfile 07/10] arm64: use value of VA_BITS and PHYS_OFFSET embedded into vmcore

Pratyush Anand panand at redhat.com
Tue Oct 25 00:22:59 PDT 2016


ARM64 kdump-v26 patch (4/7) [1] has embedded VA_BITS and PHYS_OFFSET into
vmcore. Therefore this patch does following improvements:

1) Read value of VA_BITS from vmcore, instead of hard coding.
2) Remove calculation of PHYS_OFFSET from PT_LOAD and read it from vmcore
as well.
3) arch/arm64/Kconfig defines page table levels on the basic of page size and
VA bits. Use same definition in makedumpfile as well.
4) Since pgtable_level and va_bits are used only in arm64.c, therefore get rid
of get_pgtable_level_arm64() and get_va_bits_arm64() function.
5) Since va_bits and pgtable_levels are local to arch/arm64.c, therefore
remove #define of ARM64_PGTABLE_LEVELS and VA_BITS from makedumpfile.h

[1] https://www.mail-archive.com/kexec@lists.infradead.org/msg16298.html

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c   | 88 +++++++++++++++++-----------------------------------------
 makedumpfile.c |  8 ++++++
 makedumpfile.h |  7 +++--
 3 files changed, 38 insertions(+), 65 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index a5b1bca43e64..6f61b4c5497f 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -39,16 +39,23 @@ typedef struct {
 	unsigned long pte;
 } pte_t;
 
+static int pgtable_level;
+static int va_bits;
+
+#define SZ_4K			(4 * 1024)
+#define SZ_16K			(16 * 1024)
+#define SZ_64K			(64 * 1024)
+
 #define pgd_val(x)		((x).pgd)
 #define pud_val(x)		(pgd_val((x).pgd))
 #define pmd_val(x)		(pud_val((x).pud))
 #define pte_val(x)		((x).pte)
 
 #define PAGE_MASK		(~(PAGESIZE() - 1))
-#define PGDIR_SHIFT		((PAGESHIFT() - 3) * ARM64_PGTABLE_LEVELS + 3)
+#define PGDIR_SHIFT		((PAGESHIFT() - 3) * pgtable_level + 3)
 #define PUD_SHIFT		PGDIR_SHIFT
 #define PUD_SIZE		(1UL << PUD_SHIFT)
-#define PTRS_PER_PGD		(1 << (VA_BITS - PGDIR_SHIFT))
+#define PTRS_PER_PGD		(1 << (va_bits - PGDIR_SHIFT))
 #define PTRS_PER_PTE		(1 << (PAGESHIFT() - 3))
 #define PMD_SHIFT		((PAGESHIFT() - 3) * 2 + 3)
 #define PMD_SIZE		(1UL << PMD_SHIFT)
@@ -92,25 +99,10 @@ typedef struct {
 
 #define ALIGN(x, a) 			(((x) + (a) - 1) & ~((a) - 1))
 #define PFN_DOWN(x)			((x) >> PAGESHIFT())
-#define VMEMMAP_SIZE			ALIGN((1UL << (VA_BITS - PAGESHIFT())) * KERN_STRUCT_PAGE_SIZE, PUD_SIZE)
+#define VMEMMAP_SIZE			ALIGN((1UL << (va_bits - PAGESHIFT())) * KERN_STRUCT_PAGE_SIZE, PUD_SIZE)
 #define MODULES_END			PAGE_OFFSET
 #define MODULES_VADDR			(MODULES_END - 0x4000000)
 
-static int pgtable_level;
-static int va_bits;
-
-int
-get_pgtable_level_arm64(void)
-{
-	return pgtable_level;
-}
-
-int
-get_va_bits_arm64(void)
-{
-	return va_bits;
-}
-
 static pmd_t *
 pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 {
@@ -121,32 +113,23 @@ pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 	}
 }
 
-#define PAGE_OFFSET_39 (0xffffffffffffffffUL << 39)
-#define PAGE_OFFSET_42 (0xffffffffffffffffUL << 42)
 static int calculate_plat_config(void)
 {
-	unsigned long long stext;
-
-	/* Currently we assume that there are only two possible
-	 * configuration supported by kernel.
-	 * 1) Page Table Level:2, Page Size 64K and VA Bits 42
-	 * 1) Page Table Level:3, Page Size 4K and VA Bits 39
-	 * Ideally, we should have some mechanism to decide these values
-	 * from kernel symbols, but we have limited symbols in vmcore,
-	 * and we can not do much. So until some one comes with a better
-	 * way, we use following.
-	 */
-	stext = SYMBOL(_stext);
+	va_bits = NUMBER(VA_BITS);
 
-	/* condition for minimum VA bits must be checked first and so on */
-	if ((stext & PAGE_OFFSET_39) == PAGE_OFFSET_39) {
-		pgtable_level = 3;
-		va_bits = 39;
-	} else if ((stext & PAGE_OFFSET_42) == PAGE_OFFSET_42) {
+	/* derive pgtable_level as per arch/arm64/Kconfig */
+	if ((PAGESIZE() == SZ_16K && va_bits == 36) ||
+			(PAGESIZE() == SZ_64K && va_bits == 42)) {
 		pgtable_level = 2;
-		va_bits = 42;
+	} else if ((PAGESIZE() == SZ_64K && va_bits == 48) ||
+			(PAGESIZE() == SZ_4K && va_bits == 39) ||
+			(PAGESIZE() == SZ_16K && va_bits == 47)) {
+		pgtable_level = 3;
+	} else if ((PAGESIZE() != SZ_64K && va_bits == 48)) {
+		pgtable_level = 4;
 	} else {
-		ERRMSG("Kernel Configuration not supported\n");
+		ERRMSG("PAGE SIZE %#lx and VA Bits %d not supported\n",
+				PAGESIZE(), va_bits);
 		return FALSE;
 	}
 
@@ -167,28 +150,9 @@ is_vtop_from_page_table_arm64(unsigned long vaddr)
 int
 get_phys_base_arm64(void)
 {
-	unsigned long phys_base = ULONG_MAX;
-	unsigned long long phys_start;
-	int i;
-
-	/*
-	 * We resolve phys_base from PT_LOAD segments. LMA contains physical
-	 * address of the segment, and we use the lowest start as
-	 * phys_base.
-	 */
-	for (i = 0; get_pt_load(i, &phys_start, NULL, NULL, NULL); i++) {
-		if (phys_start < phys_base)
-			phys_base = phys_start;
-	}
-
-	if (phys_base == ULONG_MAX) {
-		ERRMSG("Can't determine phys_base\n");
-		return FALSE;
-	}
-
-	info->phys_base = phys_base;
+	info->phys_base = NUMBER(PHYS_OFFSET);
 
-	DEBUG_MSG("phys_base    : %lx\n", phys_base);
+	DEBUG_MSG("phys_base    : %lx\n", info->phys_base);
 
 	return TRUE;
 }
@@ -203,8 +167,8 @@ get_machdep_info_arm64(void)
 
 	info->max_physmem_bits = PHYS_MASK_SHIFT;
 	info->section_size_bits = SECTIONS_SIZE_BITS;
-	info->page_offset = 0xffffffffffffffffUL << (VA_BITS - 1);
-	info->vmalloc_start = 0xffffffffffffffffUL << VA_BITS;
+	info->page_offset = 0xffffffffffffffffUL << (va_bits - 1);
+	info->vmalloc_start = 0xffffffffffffffffUL << va_bits;
 	info->vmalloc_end = PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - 0x10000;
 	info->vmemmap_start = VMALLOC_END + 0x10000;
 	info->vmemmap_end = VMEMMAP_START + VMEMMAP_SIZE;
diff --git a/makedumpfile.c b/makedumpfile.c
index e248db876858..df413f066348 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -2263,6 +2263,10 @@ write_vmcoreinfo_data(void)
 	WRITE_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
 
 	WRITE_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
+#ifdef __aarch64__
+	WRITE_NUMBER("VA_BITS", VA_BITS);
+	WRITE_NUMBER_UNSIGNED("PHYS_OFFSET", PHYS_OFFSET);
+#endif
 
 	/*
 	 * write the source file of 1st kernel
@@ -2645,6 +2649,10 @@ read_vmcoreinfo(void)
 
 	READ_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
 	READ_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
+#ifdef __aarch64__
+	READ_NUMBER("VA_BITS", VA_BITS);
+	READ_NUMBER_UNSIGNED("PHYS_OFFSET", PHYS_OFFSET);
+#endif
 
 	READ_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
 
diff --git a/makedumpfile.h b/makedumpfile.h
index c363c547b448..1a119ac949b6 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -516,9 +516,6 @@ do { \
 #define PMASK			(0x7ffffffffffff000UL)
 
 #ifdef __aarch64__
-int get_va_bits_arm64(void);
-#define ARM64_PGTABLE_LEVELS	get_pgtable_level_arm64()
-#define VA_BITS			get_va_bits_arm64()
 #define KVBASE			VMALLOC_START
 #endif /* aarch64 */
 
@@ -1736,6 +1733,10 @@ struct number_table {
 	long	SECTION_SIZE_BITS;
 	long	MAX_PHYSMEM_BITS;
 	long    HUGETLB_PAGE_DTOR;
+#ifdef __aarch64__
+	long 	VA_BITS;
+	unsigned long	PHYS_OFFSET;
+#endif
 };
 
 struct srcfile_table {
-- 
2.7.4




More information about the kexec mailing list