File makedumpfile-ppc64-vmalloc-initialize.patch of Package makedumpfile
From: Hari Bathini <hbathini@linux.vnet.ibm.com>
Date: Fri Aug 8 22:23:40 2014 +0900
Subject: Initialize for vmalloc address translation support in PPC64 arch
References: FATE#318012
Patch-mainline: v1.5.7
Git-commit: 7e213b8fc5a6d9fb115af74f68066cbd1d872dfe
In this patch, initializing of page table information that is to be
used for virtual to physical address translation of vmalloc region
is added to the initialization sequence.
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
arch/ppc64.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++
makedumpfile.c | 7 ++++
makedumpfile.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 158 insertions(+), 1 deletion(-)
--- a/arch/ppc64.c
+++ b/arch/ppc64.c
@@ -149,6 +149,58 @@ ppc64_vmemmap_init(void)
return TRUE;
}
+static int
+ppc64_vmalloc_init(void)
+{
+ if (info->page_size == 65536) {
+ /*
+ * 64K pagesize
+ */
+ if (info->kernel_version >= KERNEL_VERSION(3, 10, 0)) {
+ info->l1_index_size = PTE_INDEX_SIZE_L4_64K_3_10;
+ info->l2_index_size = PMD_INDEX_SIZE_L4_64K_3_10;
+ info->l3_index_size = PUD_INDEX_SIZE_L4_64K;
+ } else {
+ info->l1_index_size = PTE_INDEX_SIZE_L4_64K;
+ info->l2_index_size = PMD_INDEX_SIZE_L4_64K;
+ info->l3_index_size = PUD_INDEX_SIZE_L4_64K;
+ }
+
+ info->pte_shift = SYMBOL(demote_segment_4k) ?
+ PTE_SHIFT_L4_64K_V2 : PTE_SHIFT_L4_64K_V1;
+ info->l2_masked_bits = PMD_MASKED_BITS_64K;
+ } else {
+ /*
+ * 4K pagesize
+ */
+ info->l1_index_size = PTE_INDEX_SIZE_L4_4K;
+ info->l2_index_size = PMD_INDEX_SIZE_L4_4K;
+ info->l3_index_size = PUD_INDEX_SIZE_L4_4K;
+
+ info->pte_shift = PTE_SHIFT_L4_4K;
+ info->l2_masked_bits = PMD_MASKED_BITS_4K;
+ }
+
+ /*
+ * Compute ptrs per each level
+ */
+ info->l1_shift = info->page_shift;
+ info->ptrs_per_l1 = (1 << info->l1_index_size);
+ info->ptrs_per_l2 = (1 << info->l2_index_size);
+ info->ptrs_per_l3 = (1 << info->l3_index_size);
+
+ info->ptrs_per_pgd = info->ptrs_per_l3;
+
+ /*
+ * Compute shifts
+ */
+ info->l2_shift = info->l1_shift + info->l1_index_size;
+ info->l3_shift = info->l2_shift + info->l2_index_size;
+ info->l4_shift = info->l3_shift + info->l3_index_size;
+
+ return TRUE;
+}
+
/*
* If the vmemmap address translation information is stored in the kernel,
* make the translation.
@@ -251,6 +303,15 @@ get_machdep_info_ppc64(void)
info->vmalloc_start = vmalloc_start;
DEBUG_MSG("vmalloc_start: %lx\n", vmalloc_start);
+ if (SYMBOL(swapper_pg_dir) != NOT_FOUND_SYMBOL) {
+ info->kernel_pgd = SYMBOL(swapper_pg_dir);
+ } else if (SYMBOL(cpu_pgd) != NOT_FOUND_SYMBOL) {
+ info->kernel_pgd = SYMBOL(cpu_pgd);
+ } else {
+ ERRMSG("No swapper_pg_dir or cpu_pgd symbols exist\n");
+ return FALSE;
+ }
+
if (SYMBOL(vmemmap_list) != NOT_FOUND_SYMBOL) {
info->vmemmap_start = VMEMMAP_REGION_ID << REGION_SHIFT;
info->vmemmap_end = info->vmemmap_start;
@@ -262,6 +323,17 @@ get_machdep_info_ppc64(void)
}
return TRUE;
+}
+
+int
+get_versiondep_info_ppc64()
+{
+ if (ppc64_vmalloc_init() == FALSE) {
+ ERRMSG("Can't initialize for vmalloc translation\n");
+ return FALSE;
+ }
+
+ return TRUE;
}
int
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1179,6 +1179,9 @@ get_symbol_info(void)
SYMBOL_INIT(mmu_vmemmap_psize, "mmu_vmemmap_psize");
SYMBOL_INIT(free_huge_page, "free_huge_page");
+ SYMBOL_INIT(cpu_pgd, "cpu_pgd");
+ SYMBOL_INIT(demote_segment_4k, "demote_segment_4k");
+
return TRUE;
}
@@ -1705,6 +1708,8 @@ write_vmcoreinfo_data(void)
WRITE_SYMBOL("mmu_psize_defs", mmu_psize_defs);
WRITE_SYMBOL("mmu_vmemmap_psize", mmu_vmemmap_psize);
WRITE_SYMBOL("free_huge_page", free_huge_page);
+ WRITE_SYMBOL("cpu_pgd", cpu_pgd);
+ WRITE_SYMBOL("demote_segment_4k", demote_segment_4k);
/*
* write the structure size of 1st kernel
@@ -2046,6 +2051,8 @@ read_vmcoreinfo(void)
READ_SYMBOL("mmu_psize_defs", mmu_psize_defs);
READ_SYMBOL("mmu_vmemmap_psize", mmu_vmemmap_psize);
READ_SYMBOL("free_huge_page", free_huge_page);
+ READ_SYMBOL("cpu_pgd", cpu_pgd);
+ READ_SYMBOL("demote_segment_4k", demote_segment_4k);
READ_STRUCTURE_SIZE("page", page);
READ_STRUCTURE_SIZE("mem_section", mem_section);
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -599,6 +599,58 @@ int get_va_bits_arm64(void);
#define _MAX_PHYSMEM_BITS_3_7 (46)
#define REGION_SHIFT (60UL)
#define VMEMMAP_REGION_ID (0xfUL)
+
+#define PGDIR_SHIFT \
+ (PAGESHIFT() + (PAGESHIFT() - 3) + (PAGESHIFT() - 2))
+#define PMD_SHIFT (PAGESHIFT() + (PAGESHIFT() - 3))
+
+/* shift to put page number into pte */
+#define PTE_SHIFT 16
+
+#define PTE_INDEX_SIZE 9
+#define PMD_INDEX_SIZE 10
+#define PGD_INDEX_SIZE 10
+
+#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE)
+#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE)
+#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE)
+
+#define PGD_OFFSET(vaddr) ((vaddr >> PGDIR_SHIFT) & 0x7ff)
+#define PMD_OFFSET(vaddr) ((vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+
+/* 4-level page table support */
+
+/* 4K pagesize */
+#define PTE_INDEX_SIZE_L4_4K 9
+#define PMD_INDEX_SIZE_L4_4K 7
+#define PUD_INDEX_SIZE_L4_4K 7
+#define PGD_INDEX_SIZE_L4_4K 9
+#define PTE_SHIFT_L4_4K 17
+#define PMD_MASKED_BITS_4K 0
+
+/* 64K pagesize */
+#define PTE_INDEX_SIZE_L4_64K 12
+#define PMD_INDEX_SIZE_L4_64K 12
+#define PUD_INDEX_SIZE_L4_64K 0
+#define PGD_INDEX_SIZE_L4_64K 4
+#define PTE_INDEX_SIZE_L4_64K_3_10 8
+#define PMD_INDEX_SIZE_L4_64K_3_10 10
+#define PGD_INDEX_SIZE_L4_64K_3_10 12
+#define PTE_SHIFT_L4_64K_V1 32
+#define PTE_SHIFT_L4_64K_V2 30
+#define PMD_MASKED_BITS_64K 0x1ff
+
+#define L4_MASK \
+ (info->kernel_version >= KERNEL_VERSION(3, 10, 0) ? 0xfff : 0x1ff)
+#define L4_OFFSET(vaddr) ((vaddr >> (info->l4_shift)) & L4_MASK)
+
+#define PGD_OFFSET_L4(vaddr) \
+ ((vaddr >> (info->l3_shift)) & (info->ptrs_per_l3 - 1))
+
+#define PMD_OFFSET_L4(vaddr) \
+ ((vaddr >> (info->l2_shift)) & (info->ptrs_per_l2 - 1))
+
+#define _PAGE_PRESENT 0x1UL
#endif
#ifdef __powerpc32__
@@ -760,10 +812,11 @@ unsigned long long vaddr_to_paddr_x86_64
#ifdef __powerpc64__ /* powerpc64 */
int get_machdep_info_ppc64(void);
+int get_versiondep_info_ppc64(void);
unsigned long long vaddr_to_paddr_ppc64(unsigned long vaddr);
#define get_phys_base() TRUE
#define get_machdep_info() get_machdep_info_ppc64()
-#define get_versiondep_info() TRUE
+#define get_versiondep_info() get_versiondep_info_ppc64()
#define vaddr_to_paddr(X) vaddr_to_paddr_ppc64(X)
#endif /* powerpc64 */
@@ -959,6 +1012,25 @@ struct DumpInfo {
struct ppc64_vmemmap *vmemmap_list;
/*
+ * page table info for ppc64
+ */
+ int ptrs_per_pgd;
+ uint l3_index_size;
+ uint l2_index_size;
+ uint l1_index_size;
+ uint ptrs_per_l3;
+ uint ptrs_per_l2;
+ uint ptrs_per_l1;
+ uint l4_shift;
+ uint l3_shift;
+ uint l2_shift;
+ uint l1_shift;
+ uint pte_shift;
+ uint l2_masked_bits;
+ ulong kernel_pgd;
+ char *page_buf; /* Page buffer to read page tables */
+
+ /*
* Filter config file containing filter commands to filter out kernel
* data from vmcore.
*/
@@ -1220,6 +1292,12 @@ struct symbol_table {
unsigned long long vmemmap_list;
unsigned long long mmu_vmemmap_psize;
unsigned long long mmu_psize_defs;
+
+ /*
+ * vm related symbols for ppc64 arch
+ */
+ unsigned long long cpu_pgd;
+ unsigned long long demote_segment_4k;
};
struct size_table {