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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 {




[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux