Skip to contentSkip to conversation

Implement memory regions on IA64

PATCH In review Bernhard Walle 2 participants 9 messages Apr 26, 2007 – May 21, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Implement memory regions on IA64

This patch fixes an error in vaddr_to_offset_ia64() which happened on a SGI machine here while retrieving the utsname from the kernel dump image. It implements memory region support for IA64.

The code is mainly from crash (http://people.redhat.com/~anderson/).

---
 ia64.c         |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 makedumpfile.c |    4 ++++
 makedumpfile.h |    9 ++++++++-
 3 files changed, 69 insertions(+), 1 deletion(-)
ia64.c +57 -0
@@ -23,6 +23,8 @@ get_phys_base_ia64(struct DumpInfo *info
 	int i;
 	struct pt_load_segment *pls;
 
+	info->phys_base = 0;
+
 	/*
 	 *  Default to 64MB.
 	 */
@@ -48,5 +50,60 @@ get_machdep_info_ia64(struct DumpInfo *i
 	return TRUE;
 }
 
+/*
+ * Convert Virtual Address to File Offest.
+ */
+off_t
+vaddr_to_offset_ia64(struct DumpInfo *info, unsigned long long vaddr)
+{
+	int i;
+	off_t offset;
+	struct pt_load_segment *pls;
+	unsigned long paddr;
+
+
+	switch (VADDR_REGION(vaddr)) {
+		case KERNEL_CACHED_REGION:
+			paddr = vaddr - (ulong)(KERNEL_CACHED_BASE);
+			break;
+
+		case KERNEL_UNCACHED_REGION:
+			paddr = vaddr - (ulong)(KERNEL_UNCACHED_BASE);
+			break;
+
+		case KERNEL_VMALLOC_REGION:
+			paddr = vaddr - info->kernel_start +
+				(info->phys_base & KERNEL_TR_PAGE_MASK);
+			break;
+
+		default:
+			ERRMSG("Unknown region (%d)\n", VADDR_REGION(vaddr));
+			return 0;
+	}
+
+	for (i = offset = 0; i < info->num_load_memory; i++) {
+		pls = &info->pt_load_segments[i];
+		if ((paddr >= pls->phys_start)
+		    && (paddr < pls->phys_end)) {
+			offset = (off_t)(paddr - pls->phys_start) +
+				pls->file_offset;
+				break;
+		}
+	}
+
+	return offset;
+}
+
+int
+get_machdep_kernel_start_ia64(struct DumpInfo *info)
+{
+	if (SYMBOL(_stext) != NOT_FOUND_SYMBOL)
+		info->kernel_start = SYMBOL(_stext);
+
+	/* TODO: fallback */
+
+	return TRUE;
+}
+
 #endif /* ia64 */
 
makedumpfile.c +4 -0
@@ -2206,6 +2206,10 @@ initial(struct DumpInfo *info)
 		if (!get_structure_info(info))
 			return FALSE;
 	}
+
+	if (!get_machdep_kernel_start(info))
+		return FALSE;
+
 	if (!check_release(info))
 		return FALSE;
 
makedumpfile.h +8 -1
@@ -377,6 +377,7 @@ int get_machdep_info_x86();
 #define get_phys_base(X)	TRUE
 #define get_machdep_info(X)	get_machdep_info_x86(X)
 #define vaddr_to_offset(X, Y)	vaddr_to_offset_general(X,Y)
+#define get_machdep_kernel_start(X)	TRUE
 #endif /* x86 */
 
 #ifdef __x86_64__
@@ -386,6 +387,7 @@ off_t vaddr_to_offset_x86_64();
 #define get_phys_base(X)	get_phys_base_x86_64(X)
 #define get_machdep_info(X)	get_machdep_info_x86_64(X)
 #define vaddr_to_offset(X, Y)	vaddr_to_offset_x86_64(X, Y)
+#define get_machdep_kernel_start(X)	TRUE
 #endif /* x86_64 */
 
 #ifdef __powerpc__ /* powerpc */
@@ -393,14 +395,18 @@ int get_machdep_info_ppc64();
 #define get_machdep_info(X)	get_machdep_info_ppc64(X)
 #define get_phys_base(X)	TRUE
 #define vaddr_to_offset(X, Y)	vaddr_to_offset_general(X, Y)
+#define get_machdep_kernel_start(X)	TRUE
 #endif          /* powerpc */
 
 #ifdef __ia64__ /* ia64 */
 int get_phys_base_ia64();
 int get_machdep_info_ia64();
+int get_machdep_kernel_start_ia64();
+off_t vaddr_to_offset_ia64();
 #define get_machdep_info(X)	get_machdep_info_ia64(X)
 #define get_phys_base(X)	get_phys_base_ia64(X)
-#define vaddr_to_offset(X, Y)	vaddr_to_offset_general(X, Y)
+#define get_machdep_kernel_start(X)	get_machdep_kernel_start_ia64(X)
+#define vaddr_to_offset(X, Y)	vaddr_to_offset_ia64(X, Y)
 #define VADDR_REGION(X)		((X) >> REGION_SHIFT)
 #endif          /* ia64 */
 
@@ -491,6 +497,7 @@ struct DumpInfo {
 	unsigned long   max_physmem_bits;
 	unsigned long   sections_per_root;
 	unsigned long	phys_base;
+	unsigned long   kernel_start;
 
 	/*
 	 * diskdimp info:

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#1 lore raw

Hi Bernhard,

Quoted 3 lines · Bernhard Walle

This patch fixes an error in vaddr_to_offset_ia64() which happened on a SGI machine here while retrieving the utsname from the kernel dump image. It implements memory region support for IA64.

Thank you for the patch.

For ia64 DISCONTIGMEM support, I added the translation (virtual address to physical address) by using layer 3 paging into your patch. I created 2 attached patches for ia64 DISCONTIGMEM support.

I confirmed makedumpfile with these patches can run on linux-2.6.18 kernel (made of RHEL5 kernel by changing configs from SPARSEMEM to DISCONTIGMEM). Could you please test them on SLES10 ?

BTW, the patches don't run on stock linux-2.6.20 w/DISCONTIGMEM (it works with stock linux-2.6.20 w/SPARSEMEM)
I am trying to resolve the problem and if you have any idea about kernel changes between 2.6.18-20, please let me know.

The attached patches (for makedumpfile version 1.1.3):
- 01-vaddr_to_offset_ia64.patch
The translation by using layer 3 paging is added to Bernhard's patch.

- 02-ia64-discontigmem.patch
ia64 DISCONTIGMEM support.

Thanks
Ken'ichi Ohmichi

makedumpfile.c +40 -1
diff -puN makedumpfile.org/makedumpfile.c makedumpfile/makedumpfile.c
@@ -1455,6 +1455,8 @@ get_structure_info(struct DumpInfo *info
 	OFFSET_INIT(pglist_data.node_start_pfn, "pglist_data","node_start_pfn");
 	OFFSET_INIT(pglist_data.node_spanned_pages, "pglist_data",
 	    "node_spanned_pages");
+	OFFSET_INIT(pglist_data.pgdat_next, "pglist_data",
+	    "pgdat_next");
 
 	/*
 	 * Get offsets of the zone's members.
@@ -1502,7 +1504,12 @@ get_mem_type(struct DumpInfo *info)
 	    || (OFFSET(page._count) == NOT_FOUND_STRUCTURE)
 	    || (OFFSET(page.mapping) == NOT_FOUND_STRUCTURE)) {
 		ret = NOT_FOUND_MEMTYPE;
-	} else if ((SYMBOL(node_data) != NOT_FOUND_SYMBOL)
+	} else if ((((SYMBOL(node_data) != NOT_FOUND_SYMBOL)
+	        && (ARRAY_LENGTH(node_data) != NOT_FOUND_STRUCTURE))
+	    || ((SYMBOL(pgdat_list) != NOT_FOUND_SYMBOL)
+	        && (OFFSET(pglist_data.pgdat_next) != NOT_FOUND_STRUCTURE))
+	    || ((SYMBOL(pgdat_list) != NOT_FOUND_SYMBOL)
+	        && (ARRAY_LENGTH(pgdat_list) != NOT_FOUND_STRUCTURE)))
 	    && (SIZE(pglist_data) != NOT_FOUND_STRUCTURE)
 	    && (OFFSET(pglist_data.node_mem_map) != NOT_FOUND_STRUCTURE)
 	    && (OFFSET(pglist_data.node_start_pfn) != NOT_FOUND_STRUCTURE)
@@ -1613,6 +1620,8 @@ generate_config(struct DumpInfo *info)
 	    pglist_data.node_start_pfn);
 	WRITE_MEMBER_OFFSET("pglist_data.node_spanned_pages",
 	    pglist_data.node_spanned_pages);
+	WRITE_MEMBER_OFFSET("pglist_data.pgdat_next",
+	    pglist_data.pgdat_next);
 	WRITE_MEMBER_OFFSET("zone.free_pages", zone.free_pages);
 	WRITE_MEMBER_OFFSET("zone.free_area", zone.free_area);
 	WRITE_MEMBER_OFFSET("zone.vm_stat", zone.vm_stat);
@@ -1782,6 +1791,8 @@ read_config(struct DumpInfo *info)
 	    pglist_data.node_start_pfn);
 	READ_MEMBER_OFFSET("pglist_data.node_spanned_pages",
 	    pglist_data.node_spanned_pages);
+	READ_MEMBER_OFFSET("pglist_data.pgdat_next",
+	    pglist_data.pgdat_next);
 	READ_MEMBER_OFFSET("zone.free_pages", zone.free_pages);
 	READ_MEMBER_OFFSET("zone.free_area", zone.free_area);
 	READ_MEMBER_OFFSET("zone.vm_stat", zone.vm_stat);
@@ -1880,6 +1891,7 @@ next_online_node(int first)
 unsigned long
 next_online_pgdat(struct DumpInfo *info, int node)
 {
+	int i;
 	unsigned long pgdat;
 
 	/*
@@ -1926,6 +1938,33 @@ pgdat2:
 
 pgdat3:
 	/*
+	 * linux-2.6.16 or before
+	 */
+	if ((SYMBOL(pgdat_list) == NOT_FOUND_SYMBOL)
+	    || (OFFSET(pglist_data.pgdat_next) == NOT_FOUND_STRUCTURE))
+		goto pgdat4;
+
+	if (!readmem(info, SYMBOL(pgdat_list), &pgdat, sizeof pgdat))
+		goto pgdat4;
+
+	if (!is_kvaddr(pgdat))
+		goto pgdat4;
+
+	if (node == 0)
+		return pgdat;
+
+	for (i = 1; i < node; i++) {
+		if (!readmem(info, pgdat + OFFSET(pglist_data.pgdat_next),
+		    &pgdat, sizeof pgdat))
+			goto pgdat4;
+
+		if (!is_kvaddr(pgdat))
+			goto pgdat4;
+	}
+	return pgdat;
+
+pgdat4:
+	/*
 	 * Get the pglist_data structure from symbol "contig_page_data".
 	 */
 	if (SYMBOL(contig_page_data) == NOT_FOUND_SYMBOL)
makedumpfile.h +1 -0
diff -puN makedumpfile.org/makedumpfile.h makedumpfile/makedumpfile.h
@@ -612,6 +612,7 @@ struct offset_table {
 		long	node_mem_map;
 		long	node_start_pfn;
 		long	node_spanned_pages;
+		long	pgdat_next;
 	} pglist_data;
 	struct free_area {
 		long	free_list;

---

ia64.c renamed from v1.1.3/ia64.c +122 -0

133 lines not on this page · raw message

makedumpfile.c renamed from v1.1.3/makedumpfile.c +44 -0

86 lines not on this page · raw message

makedumpfile.h renamed from v1.1.3/makedumpfile.h +25 -2
diff -puN backup/v1.1.3/makedumpfile.h makedumpfile/makedumpfile.h
@@ -367,6 +367,22 @@ do { \
 #define _SECTION_SIZE_BITS	(30)
 #define _MAX_PHYSMEM_BITS	(50)
 #define SIZEOF_NODE_ONLINE_MAP	(32)
+
+/*
+ * Layer 3 paging
+ */
+#define _PAGE_PPN_MASK		(((1UL << _MAX_PHYSMEM_BITS) - 1) & ~0xfffUL)
+#define PAGE_SHIFT		(info->page_shift)
+#define PTRS_PER_PTD_SHIFT	(PAGE_SHIFT - 3)
+
+#define PMD_SHIFT		(PAGE_SHIFT + PTRS_PER_PTD_SHIFT)
+#define PGDIR_SHIFT		(PMD_SHIFT  + PTRS_PER_PTD_SHIFT)
+
+#define MASK_POFFSET	((1UL << PAGE_SHIFT) - 1)
+#define MASK_PTE	((1UL << PMD_SHIFT) - 1) &~((1UL << PAGE_SHIFT) - 1)
+#define MASK_PMD	((1UL << PGDIR_SHIFT) - 1) &~((1UL << PMD_SHIFT) - 1)
+#define MASK_PGD	((1UL << REGION_SHIFT) - 1) & (~((1UL << PGDIR_SHIFT) - 1))
+
 #endif          /* ia64 */
 
 /*
@@ -398,10 +414,11 @@ int get_machdep_info_ppc64();
 #ifdef __ia64__ /* ia64 */
 int get_phys_base_ia64();
 int get_machdep_info_ia64();
+off_t vaddr_to_offset_ia64();
 #define get_machdep_info(X)	get_machdep_info_ia64(X)
 #define get_phys_base(X)	get_phys_base_ia64(X)
-#define vaddr_to_offset(X, Y)	vaddr_to_offset_general(X, Y)
-#define VADDR_REGION(X)		((X) >> REGION_SHIFT)
+#define vaddr_to_offset(X, Y)	vaddr_to_offset_ia64(X, Y)
+#define VADDR_REGION(X)		(((unsigned long)(X)) >> REGION_SHIFT)
 #endif          /* ia64 */
 
 #define MSG(x...)	fprintf(stderr, x)
@@ -486,6 +503,7 @@ struct DumpInfo {
 	int		flag_rearrange;      /* flag of creating dumpfile from
 						flattened format */
 	long		page_size;           /* size of page */
+	long		page_shift;
 	unsigned long long	max_mapnr;   /* number of page descriptor */
 	unsigned long   section_size_bits;
 	unsigned long   max_physmem_bits;
@@ -555,6 +573,7 @@ struct symbol_table {
 	unsigned long	system_utsname;
 	unsigned long	init_uts_ns;
 	unsigned long	_stext;
+	unsigned long	swapper_pg_dir;
 	unsigned long	phys_base;
 	unsigned long	node_online_map;
 	unsigned long	node_data;
@@ -651,3 +670,7 @@ struct dwarf_info {
 
 extern struct dwarf_info	dwarf_info;
 
+int readmem();
+unsigned long long vaddr_to_paddr();
+unsigned long long paddr_to_vaddr();
+

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#2 lore raw

Hi,

sorry for the late reply, but I was out of office last week.

Quoted 5 lines · Ken'ichi Ohmichi
Quoted 3 lines · Bernhard Walle

This patch fixes an error in vaddr_to_offset_ia64() which happened on a SGI machine here while retrieving the utsname from the kernel dump image. It implements memory region support for IA64.

Quoted 7 lines

For ia64 DISCONTIGMEM support, I added the translation (virtual address to physical address) by using layer 3 paging into your patch. I created 2 attached patches for ia64 DISCONTIGMEM support.

I confirmed makedumpfile with these patches can run on linux-2.6.18 kernel (made of RHEL5 kernel by changing configs from SPARSEMEM to DISCONTIGMEM). Could you please test them on SLES10 ?

it doesn't work here. The config file is generated, but at runtime I get a SEGV which is caused by a endless recusion of ia64_vtop() while resolving the utsname.

I'm looking into this ...

Quoted 4 lines

BTW, the patches don't run on stock linux-2.6.20 w/DISCONTIGMEM (it works with stock linux-2.6.20 w/SPARSEMEM)
I am trying to resolve the problem and if you have any idea about kernel changes between 2.6.18-20, please let me know.

Sorry, no.

Thanks,
Bernhard

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#3 lore raw
Quoted 10 lines · Bernhard Walle
Quoted 9 lines · Ken'ichi Ohmichi
Quoted 3 lines · Bernhard Walle

This patch fixes an error in vaddr_to_offset_ia64() which happened on a SGI machine here while retrieving the utsname from the kernel dump image. It implements memory region support for IA64.

For ia64 DISCONTIGMEM support, I added the translation (virtual address to physical address) by using layer 3 paging into your patch. I created 2 attached patches for ia64 DISCONTIGMEM support.

Quoted 7 lines
Quoted 3 lines

I confirmed makedumpfile with these patches can run on linux-2.6.18 kernel (made of RHEL5 kernel by changing configs from SPARSEMEM to DISCONTIGMEM). Could you please test them on SLES10 ?

it doesn't work here. The config file is generated, but at runtime I get a SEGV which is caused by a endless recusion of ia64_vtop() while resolving the utsname.

Because of CONFIG_PGTABLE_4=y in SUSE kernels. Your implementation assumes a 3-level-pagetable.

Quoted 6 lines
Quoted 4 lines

BTW, the patches don't run on stock linux-2.6.20 w/DISCONTIGMEM (it works with stock linux-2.6.20 w/SPARSEMEM)
I am trying to resolve the problem and if you have any idea about kernel changes between 2.6.18-20, please let me know.

Sorry, no.

And I guess because of the same reason (maybe the default changed?).

I'm working on support for the 4 layer pagetable.

Thanks,
Bernhard

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#4 lore raw

Hello,

Quoted 2 lines · Bernhard Walle

I'm working on support for the 4 layer pagetable.

Here's my first attempt. It works with SLES 10, SP1 on a Tiger4 machine with 16 GiB of memory. (I had still problems with a big SGI machine when creating the bitmap. I'm investigating this, too.)

The problem is not to implement the 4 layer page table, but to *detect* it. crash uses the built-in configuration data in the kernel image, and that's what I used in my patch. If you have a better and still reliable method, I'm open to suggestions. :-)

Also, I only use the page table translation when the memory is vmalloc'd. That's the same way crash does it and that should be well-tested.

The patch requires your two patches. Please give me your feedback! And I hope I didn't accidentally break the 3 layer page table.

Thanks,
Bernhard

---
 ia64.c         |  148 +++++++++++++++++++++++++++++++++++++++++++++---
 makedumpfile.c |  174 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 makedumpfile.h |   43 +++++++++++++-
 3 files changed, 354 insertions(+), 11 deletions(-)
ia64.c +140 -8
@@ -3,6 +3,9 @@
  *
  * Copyright (C) 2006  NEC Corporation
  *
+ * Some parts are taken and adapted from the crash-utility,
+ * (c) by RedHat Inc.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -17,6 +20,18 @@
 
 #include "makedumpfile.h"
 
+
+/*
+ *  vmalloc() starting address is either the traditional 0xa000000000000000 or
+ *  bumped up in 2.6 to 0xa000000200000000.
+ */
+int
+is_vmalloc_addr_ia64(struct DumpInfo *info, unsigned long vaddr)
+{
+	return ((vaddr >= info->vmalloc_start) &&
+			(vaddr < (ulong)KERNEL_UNCACHED_BASE));
+}
+
 int
 get_phys_base_ia64(struct DumpInfo *info)
 {
@@ -51,18 +66,80 @@ get_machdep_info_ia64(struct DumpInfo *i
 }
 
 unsigned long
-ia64_vtop(struct DumpInfo *info, unsigned long long vaddr)
+ia64_vtop3(struct DumpInfo *info, unsigned long long vaddr)
 {
 	unsigned long paddr = 0, temp, page_dir, pgd_pte, page_middle, pmd_pte;
 	unsigned long page_table, pte;
 
-	if (VADDR_REGION(vaddr) != KERNEL_VMALLOC_REGION) {
-		ERRMSG("vaddr(%llx) is not KERNEL_VMALLOC_REGION.\n", vaddr);
+
+	/*
+	 * Translate a virtual address to a physical address
+	 * by using Layer 3 paging.
+	 */
+	if (SYMBOL(swapper_pg_dir) == NOT_FOUND_SYMBOL) {
+		ERRMSG("Can't get the symbol of swapper_pg_dir.\n");
 		return paddr;
 	}
-	paddr = vaddr_to_paddr(info, vaddr);
-	if (paddr)
+
+	/*
+	 * Get PGD
+	 */
+	temp = vaddr & MASK_PGD_3L;
+	temp = temp >> (PGDIR_SHIFT_3L - 3);
+	page_dir = SYMBOL(swapper_pg_dir) + temp;
+	if (!readmem(info, page_dir, &pgd_pte, sizeof pgd_pte)) {
+		ERRMSG("Can't get pgd_pte (page_dir:%lx).\n", page_dir);
 		return paddr;
+	}
+
+	/*
+	 * Get PMD
+	 */
+	temp = vaddr & MASK_PMD;
+	temp = temp >> (PMD_SHIFT - 3);
+	page_middle = pgd_pte + temp;
+	/*
+	 * Convert physical address to virtual address
+	 */
+	page_middle = paddr_to_vaddr(info, page_middle);
+	if (!readmem(info, page_middle, &pmd_pte, sizeof pmd_pte)) {
+		ERRMSG("Can't get pmd_pte (page_middle:%lx).\n", page_middle);
+		return paddr;
+	}
+
+	/*
+	 * Get PTE
+	 */
+	temp = vaddr & MASK_PTE;
+	temp = temp >> (PAGE_SHIFT - 3);
+	page_table = pmd_pte + temp;
+	/*
+	 * Convert physical address to virtual address
+	 */
+	page_table = paddr_to_vaddr(info, page_table);
+	if (!readmem(info, page_table, &pte, sizeof pte)) {
+		ERRMSG("Can't get pte (page_table:%lx).\n", page_table);
+		return paddr;
+	}
+
+	/*
+	 * Get physical address
+	 */
+	temp = vaddr & MASK_POFFSET;
+	paddr = (pte & _PAGE_PPN_MASK) + temp;
+	if (info->flag_debug) {
+		MSG("vaddr:%llx -> paddr:%lx\n", vaddr, paddr);
+	}
+
+	return paddr;
+}
+
+unsigned long
+ia64_vtop4(struct DumpInfo *info, unsigned long long vaddr)
+{
+	unsigned long paddr = 0, temp, page_dir, pgd_pte, page_upper,
+		      pud_pte, page_middle, pmd_pte;
+	unsigned long page_table, pte;
 
 	/*
 	 * Translate a virtual address to a physical address
@@ -76,8 +153,8 @@ ia64_vtop(struct DumpInfo *info, unsigne
 	/*
 	 * Get PGD
 	 */
-	temp = vaddr & MASK_PGD;
-	temp = temp >> (PGDIR_SHIFT - 3);
+	temp = vaddr & MASK_PGD_4L;
+	temp = temp >> (PGDIR_SHIFT_4L - 3);
 	page_dir = SYMBOL(swapper_pg_dir) + temp;
 	if (!readmem(info, page_dir, &pgd_pte, sizeof pgd_pte)) {
 		ERRMSG("Can't get pgd_pte (page_dir:%lx).\n", page_dir);
@@ -85,11 +162,26 @@ ia64_vtop(struct DumpInfo *info, unsigne
 	}
 
 	/*
+	 * Get PUD
+	 */
+	temp = vaddr & MASK_PUD;
+	temp = temp >> (PUD_SHIFT - 3);
+	page_upper = pgd_pte + temp;
+	/*
+	 * Convert physical address to virtual address
+	 */
+	page_upper = paddr_to_vaddr(info, page_upper);
+	if (!readmem(info, page_upper, &pud_pte, sizeof pud_pte)) {
+		ERRMSG("Can't get pud_pte (page_upper:%lx).\n", page_upper);
+		return paddr;
+	}
+
+	/*
 	 * Get PMD
 	 */
 	temp = vaddr & MASK_PMD;
 	temp = temp >> (PMD_SHIFT - 3);
-	page_middle = pgd_pte + temp;
+	page_middle = pud_pte + temp;
 	/*
 	 * Convert physical address to virtual address
 	 */
@@ -126,6 +218,30 @@ ia64_vtop(struct DumpInfo *info, unsigne
 	return paddr;
 }
 
+unsigned long
+ia64_vtop(struct DumpInfo *info, unsigned long long vaddr)
+{
+	unsigned long paddr = 0;
+
+	if (VADDR_REGION(vaddr) != KERNEL_VMALLOC_REGION) {
+		ERRMSG("vaddr(%llx) is not KERNEL_VMALLOC_REGION.\n", vaddr);
+		return paddr;
+	}
+	paddr = vaddr_to_paddr(info, vaddr);
+	if (paddr)
+		return paddr;
+
+	if (!is_vmalloc_addr_ia64(info, vaddr)) {
+		paddr = vaddr - info->kernel_start +
+			(info->phys_base & KERNEL_TR_PAGE_MASK);
+		return paddr;
+	}
+
+	if (info->mem_flags & MEMORY_4LAYER_PAGETABLE)
+		return ia64_vtop4(info, vaddr);
+	else
+		return ia64_vtop3(info, vaddr);
+}
 
 /*
  * Convert Virtual Address to File Offest.
@@ -170,5 +286,21 @@ vaddr_to_offset_ia64(struct DumpInfo *in
 	return offset;
 }
 
+int
+get_machdep_kernel_start_ia64(struct DumpInfo *info)
+{
+	if (SYMBOL(_stext) == NOT_FOUND_SYMBOL)
+		return FALSE;
+
+	info->kernel_start = SYMBOL(_stext);
+
+	if (VADDR_REGION(info->kernel_start) == KERNEL_VMALLOC_REGION)
+		info->vmalloc_start = info->kernel_start + 4*1024UL*1024UL*1024UL;
+	else
+		info->vmalloc_start = KERNEL_VMALLOC_BASE;
+
+	return TRUE;
+}
+
 #endif /* ia64 */
 
makedumpfile.c +174 -0

189 lines not on this page · raw message

makedumpfile.h +40 -3

110 lines not on this page · raw message

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#5 lore raw

Hi Bernhard,

Quoted 6 lines · Bernhard Walle

Hello,

Quoted 2 lines · Bernhard Walle

I'm working on support for the 4 layer pagetable.

Quoted 8 lines

Here's my first attempt. It works with SLES 10, SP1 on a Tiger4 machine with 16 GiB of memory. (I had still problems with a big SGI machine when creating the bitmap. I'm investigating this, too.)

The problem is not to implement the 4 layer page table, but to *detect* it. crash uses the built-in configuration data in the kernel image, and that's what I used in my patch. If you have a better and still reliable method, I'm open to suggestions. :-)

Thank you for the patch.
I tested makedumpfile with your patch on linux-2.6.18 ia64, and it output the following message and failed.

Error message:

  $ makedumpfile -cd 31 -x vmlinux vmcore dumpfile
  Can't read kernel cofiguration from kernel binary
  makedumpfile Failed.
  $

The reason was that kernel binary file didn't have "kernel_config_data" because CONFIG_IKCONFIG was not set in my .config.
It is uncertain that "kernel_config_data" exists in a kernel binary.

I propose that makedumpfile distinguishes the page table (3L or 4L) by checking the defined file name of pud_t.
I'm trying for the above implementation.
I will send you the patch when it is complete.

All the pud_t(s) of linux-2.6.16 - 2.6.21 are defined in the following files:

CONFIG_PGTABLE_4
include/asm-ia64/page.h

!CONFIG_PGTABLE_4
include/asm-generic/pgtable-nopud.h

Thanks
Ken'ichi Ohmichi

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#6 lore raw
Quoted 5 lines · Ken'ichi Ohmichi

I propose that makedumpfile distinguishes the page table (3L or 4L) by checking the defined file name of pud_t.
I'm trying for the above implementation.
I will send you the patch when it is complete.

If that works it's clearly the better approach.

Thanks,
Bernhard

Signature · 9 lines
SUSE LINUX Products GmbH          Tel. +49 (911) 74053-0
Maxfeldstr. 5                     GF: Markus Rex
90409 Nürnberg, Germany           HRB 16746 (AG Nürnberg)
OpenPGP DDAF6454: F61F 34CC 09CA FB82 C9F6  BA4B 8865 3696 DDAF 6454

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#7 lore raw
In reply to Ken'ichi Ohmichi

Hi Bernhard,

Quoted 4 lines · Ken'ichi Ohmichi

I propose that makedumpfile distinguishes the page table (3L or 4L) by checking the defined file name of pud_t.
I'm trying for the above implementation.
I will send you the patch when it is complete.

The attached patch is for the above implementation. It works fine with linux-2.6.18.
Could you test it with your environment ?

Please apply the attached patch with the following makedumpfile:

makedumpfile-1.1.3
+ 2007/05/11 by Ken'ichi, 01-vaddr_to_offset_ia64.patch
+ 2007/05/11 by Ken'ichi, 02-ia64-discontigmem.patch
+ 2007/05/16 by Bernhard, [Re: Implement memory regions on IA64] patch
+ 2007/05/21 by Ken'ichi, [Re: Fix missing last node] patch

Thanks
Ken'ichi Ohmichi

--

ia64.c +9 -0
diff -puN makedumpfile.org/ia64.c makedumpfile/ia64.c
@@ -62,6 +62,15 @@ get_machdep_info_ia64(struct DumpInfo *i
 	info->section_size_bits = _SECTION_SIZE_BITS;
 	info->max_physmem_bits  = _MAX_PHYSMEM_BITS;
 
+	if (!strncmp(SRCFILE(pud_t), STR_PUD_T_4L, strlen(STR_PUD_T_4L)))
+		info->mem_flags |= MEMORY_4LAYER_PAGETABLE;
+
+	else if (!strncmp(SRCFILE(pud_t), STR_PUD_T_3L, strlen(STR_PUD_T_3L)))
+		info->mem_flags |= MEMORY_3LAYER_PAGETABLE;
+
+	else
+		MSG("Can't distinguish the pgtable.\n");
+
 	return TRUE;
 }
 
makedumpfile.c +118 -171

367 lines not on this page · raw message

makedumpfile.h +44 -14

118 lines not on this page · raw message

_

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#8 lore raw
Quoted 9 lines · Ken'ichi Ohmichi
Quoted 4 lines · Ken'ichi Ohmichi

I propose that makedumpfile distinguishes the page table (3L or 4L) by checking the defined file name of pud_t.
I'm trying for the above implementation.
I will send you the patch when it is complete.

The attached patch is for the above implementation. It works fine with linux-2.6.18.
Could you test it with your environment ?

works, thanks.

Bernhard

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec