Kexec Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Ken'ichi Ohmichi" <oomichi@mxs.nes.nec.co.jp>
To: Bernhard Walle <bwalle@suse.de>
Cc: Jay Lan <jlan@sgi.com>, Kexec Mailing List <kexec@lists.infradead.org>
Subject: Re: [PATCH] [makedumpfile] Implement memory regions on IA64
Date: Fri, 11 May 2007 15:59:50 +0900	[thread overview]
Message-ID: <20070511155950oomichi@mail.jp.nec.com> (raw)
In-Reply-To: <20070426193725.GA2586@suse.de>

[-- Attachment #1: Type: text/plain, Size: 1165 bytes --]


Hi Bernhard,

2007/04/26 21:37:25 +0200, Bernhard Walle <bwalle@suse.de> wrote:
>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

[-- Attachment #2: 02-ia64-discontigmem.patch --]
[-- Type: application/octet-stream, Size: 3504 bytes --]

diff -puN makedumpfile.org/makedumpfile.c makedumpfile/makedumpfile.c
--- makedumpfile.org/makedumpfile.c	2007-05-11 23:06:33.000000000 +0900
+++ makedumpfile/makedumpfile.c	2007-05-11 23:55:33.000000000 +0900
@@ -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)
diff -puN makedumpfile.org/makedumpfile.h makedumpfile/makedumpfile.h
--- makedumpfile.org/makedumpfile.h	2007-05-11 23:06:33.000000000 +0900
+++ makedumpfile/makedumpfile.h	2007-05-11 23:20:00.000000000 +0900
@@ -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;

[-- Attachment #3: 01-vaddr_to_offset_ia64.patch --]
[-- Type: application/octet-stream, Size: 8580 bytes --]

Signed-off-by: Bernhard Walle <bwalle@suse.de>
Signed-off-by: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
---

diff -puN backup/v1.1.3/ia64.c makedumpfile/ia64.c
--- backup/v1.1.3/ia64.c	2007-04-13 15:44:45.000000000 +0900
+++ makedumpfile/ia64.c	2007-05-11 23:02:25.000000000 +0900
@@ -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,125 @@ get_machdep_info_ia64(struct DumpInfo *i
 	return TRUE;
 }
 
+unsigned long
+ia64_vtop(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);
+		return paddr;
+	}
+	paddr = vaddr_to_paddr(info, vaddr);
+	if (paddr)
+		return paddr;
+
+	/*
+	 * 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;
+	}
+
+	/*
+	 * Get PGD
+	 */
+	temp = vaddr & MASK_PGD;
+	temp = temp >> (PGDIR_SHIFT - 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;
+}
+
+
+/*
+ * 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 = ia64_vtop(info, vaddr);
+			break;
+
+		default:
+			ERRMSG("Unknown region (%ld)\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;
+}
+
 #endif /* ia64 */
 
diff -puN backup/v1.1.3/makedumpfile.c makedumpfile/makedumpfile.c
--- backup/v1.1.3/makedumpfile.c	2007-04-13 15:44:55.000000000 +0900
+++ makedumpfile/makedumpfile.c	2007-05-11 23:02:25.000000000 +0900
@@ -64,6 +64,44 @@ paddr_to_offset(struct DumpInfo *info, u
 	return offset;
 }
 
+unsigned long long
+vaddr_to_paddr(struct DumpInfo *info, unsigned long long vaddr)
+{
+	int i;
+	unsigned long long paddr;
+	struct pt_load_segment *pls;
+
+	for (i = paddr = 0; i < info->num_load_memory; i++) {
+		pls = &info->pt_load_segments[i];
+		if ((vaddr >= pls->virt_start)
+		    && (vaddr < pls->virt_end)) {
+			paddr = (off_t)(vaddr - pls->virt_start) +
+				pls->phys_start;
+				break;
+		}
+	}
+	return paddr;
+}
+
+unsigned long long
+paddr_to_vaddr(struct DumpInfo *info, unsigned long long paddr)
+{
+	int i;
+	unsigned long long vaddr;
+	struct pt_load_segment *pls;
+
+	for (i = vaddr = 0; i < info->num_load_memory; i++) {
+		pls = &info->pt_load_segments[i];
+		if ((paddr >= pls->phys_start)
+		    && (paddr < pls->phys_end)) {
+			vaddr = (off_t)(paddr - pls->phys_start) +
+				pls->virt_start;
+				break;
+		}
+	}
+	return vaddr;
+}
+
 /*
  * Convert Virtual Address to File Offest.
  *  If this function returns 0x0, File Offset isn't found.
@@ -735,6 +773,7 @@ get_elf_info(struct DumpInfo *info)
 	 *   capture(2nd)-kernel, the problem will happen.
 	 */
 	info->page_size = sysconf(_SC_PAGE_SIZE);
+	info->page_shift = ffs(info->page_size) - 1;
 
 	info->max_mapnr = get_max_mapnr(info);
 
@@ -1364,6 +1403,7 @@ get_symbol_info(struct DumpInfo *info)
 	SYMBOL_INIT(system_utsname, "system_utsname");
 	SYMBOL_INIT(init_uts_ns, "init_uts_ns");
 	SYMBOL_INIT(_stext, "_stext");
+	SYMBOL_INIT(swapper_pg_dir, "swapper_pg_dir");
 	SYMBOL_INIT(phys_base, "phys_base");
 	SYMBOL_INIT(node_online_map, "node_online_map");
 	SYMBOL_INIT(node_data, "node_data");
@@ -1539,6 +1579,7 @@ generate_config(struct DumpInfo *info)
 	WRITE_SYMBOL("system_utsname", system_utsname);
 	WRITE_SYMBOL("init_uts_ns", init_uts_ns);
 	WRITE_SYMBOL("_stext", _stext);
+	WRITE_SYMBOL("swapper_pg_dir", swapper_pg_dir);
 	WRITE_SYMBOL("phys_base", phys_base);
 	WRITE_SYMBOL("node_online_map", node_online_map);
 	WRITE_SYMBOL("node_data", node_data);
@@ -1631,6 +1672,7 @@ read_config_basic_info(struct DumpInfo *
 			break;
 	}
 	info->page_size = page_size;
+	info->page_shift = ffs(info->page_size) - 1;
 
 	if (!get_release || !info->page_size) {
 		ERRMSG("Invalid format in %s", info->name_configfile);
@@ -1713,6 +1755,7 @@ read_config(struct DumpInfo *info)
 	READ_SYMBOL("system_utsname", system_utsname);
 	READ_SYMBOL("init_uts_ns", init_uts_ns);
 	READ_SYMBOL("_stext", _stext);
+	READ_SYMBOL("swapper_pg_dir", swapper_pg_dir);
 	READ_SYMBOL("phys_base", phys_base);
 	READ_SYMBOL("node_online_map", node_online_map);
 	READ_SYMBOL("node_data", node_data);
@@ -2206,6 +2249,7 @@ initial(struct DumpInfo *info)
 		if (!get_structure_info(info))
 			return FALSE;
 	}
+
 	if (!check_release(info))
 		return FALSE;
 
diff -puN backup/v1.1.3/makedumpfile.h makedumpfile/makedumpfile.h
--- backup/v1.1.3/makedumpfile.h	2007-04-13 15:44:55.000000000 +0900
+++ makedumpfile/makedumpfile.h	2007-05-11 23:02:25.000000000 +0900
@@ -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();
+

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

  reply	other threads:[~2007-05-11  7:01 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-26 19:37 [PATCH] [makedumpfile] Implement memory regions on IA64 Bernhard Walle
2007-05-11  6:59 ` Ken'ichi Ohmichi [this message]
2007-05-14 18:15   ` Bernhard Walle
2007-05-14 21:49     ` Bernhard Walle
2007-05-15 22:08       ` Bernhard Walle
2007-05-16 11:20         ` Ken'ichi Ohmichi
2007-05-16 11:26           ` Bernhard Walle
2007-05-21  9:32           ` Ken'ichi Ohmichi
2007-05-21  9:54             ` Bernhard Walle
  -- strict thread matches above, loose matches on Subject: below --
2007-04-27 10:31 tachibana

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070511155950oomichi@mail.jp.nec.com \
    --to=oomichi@mxs.nes.nec.co.jp \
    --cc=bwalle@suse.de \
    --cc=jlan@sgi.com \
    --cc=kexec@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox