All of 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.