[PATCH 1/2] makedumpfile: Initialize for vmalloc address translation support in PPC64 arch
Hari Bathini
hbathini at linux.vnet.ibm.com
Thu Jul 17 07:19:07 PDT 2014
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 at linux.vnet.ibm.com>
---
arch/ppc64.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
makedumpfile.c | 7 +++++
makedumpfile.h | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 158 insertions(+), 1 deletion(-)
diff --git a/arch/ppc64.c b/arch/ppc64.c
index 09c0eb3..dabf2e7 100644
--- a/arch/ppc64.c
+++ b/arch/ppc64.c
@@ -149,6 +149,58 @@ ppc64_vmemmap_init(void)
return TRUE;
}
+static int
+ppc64_vmalloc_init(void)
+{
+ info->page_buf = (char *)calloc(1, PAGESIZE());
+ if (info->page_buf == NULL) {
+ ERRMSG("Can't allocate memory for page tables. %s\n",
+ strerror(errno));
+ return FALSE;
+ }
+
+ /* 2.6.14 layout */
+ 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;
@@ -265,6 +326,17 @@ get_machdep_info_ppc64(void)
}
int
+get_versiondep_info_ppc64()
+{
+ if (ppc64_vmalloc_init() == FALSE) {
+ ERRMSG("Can't initialize for vmalloc translation\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int
is_vmalloc_addr_ppc64(unsigned long vaddr)
{
return (info->vmalloc_start && vaddr >= info->vmalloc_start);
diff --git a/makedumpfile.c b/makedumpfile.c
index 3884aa5..f54ff8f 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1181,6 +1181,9 @@ get_symbol_info(void)
SYMBOL_INIT(mmu_psize_defs, "mmu_psize_defs");
SYMBOL_INIT(mmu_vmemmap_psize, "mmu_vmemmap_psize");
+ SYMBOL_INIT(cpu_pgd, "cpu_pgd");
+ SYMBOL_INIT(demote_segment_4k, "demote_segment_4k");
+
return TRUE;
}
@@ -1694,6 +1697,8 @@ write_vmcoreinfo_data(void)
WRITE_SYMBOL("vmemmap_list", vmemmap_list);
WRITE_SYMBOL("mmu_psize_defs", mmu_psize_defs);
WRITE_SYMBOL("mmu_vmemmap_psize", mmu_vmemmap_psize);
+ WRITE_SYMBOL("cpu_pgd", cpu_pgd);
+ WRITE_SYMBOL("demote_segment_4k", demote_segment_4k);
/*
* write the structure size of 1st kernel
@@ -2033,6 +2038,8 @@ read_vmcoreinfo(void)
READ_SYMBOL("vmemmap_list", vmemmap_list);
READ_SYMBOL("mmu_psize_defs", mmu_psize_defs);
READ_SYMBOL("mmu_vmemmap_psize", mmu_vmemmap_psize);
+ 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);
diff --git a/makedumpfile.h b/makedumpfile.h
index 9402f05..7816241 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -586,6 +586,58 @@ do { \
#define _MAX_PHYSMEM_BITS_3_7 (46)
#define REGION_SHIFT (60UL)
#define VMEMMAP_REGION_ID (0xfUL)
+
+#define PGDIR_SHIFT \
+ (info->page_shift + (info->page_shift -3) + (info->page_shift - 2))
+#define PMD_SHIFT (info->page_shift + (info->page_shift - 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__
@@ -731,10 +783,11 @@ unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr);
#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 */
@@ -932,6 +985,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; /* A page buffer to hold page table data */
+
+ /*
* Filter config file containing filter commands to filter out kernel
* data from vmcore.
*/
@@ -1192,6 +1264,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 {
More information about the kexec
mailing list