[PATCH 1/2] makedumpfile: Initialize for vmalloc address translation support in PPC64 arch

Atsushi Kumagai kumagai-atsushi at mxc.nes.nec.co.jp
Wed Jul 23 04:07:28 PDT 2014


Hello Hari,

>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>

Thanks for your work, I have some comments:

>---
> 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))

Please use PAGESHIFT() instead of info->page_shift like other arches.

>+
>+/* 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 */

Is it necessary to define page_buf as a member of struct DumpInfo ?
It's used only in ppc64_vtop_level4().

BTW, [PATCH 2/2] includes some spaces, I hope you will convert them
into tabs.


Thanks
Atsushi Kumagai

>+	/*
> 	 * 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