Re: [PATCH] add support to "virsh dump-guest-memory"(qemu memory dump)

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

 



Hello Dave,

The patch has been modified. For every bit of flag has been occupied, I
use flag2 to indicate qemu memory dump.

According to HATAYAMA's suggest, I made another two patch. The 0002
patch is used to deal with the reserved 640KB area. And the 0003 is
used to display register in qemu note section.

Now, I am still working on "see dump image from the 2nd kernel's
view"(See HATAYAMA's mail). As HATAYAMA suggested, only hint message
about calculating phys_base is needed. Then what do think? Is it
suitable add some brief explanation in program_usage_info?

BTW, the following files are what you want, including the core of
RHEL6.2 x86_64 & RHEL6.2 i386

https://skydrive.live.com/redir?resid=62F21E6013CBFCB9!111&authkey=!AF1s2nd-xYJnL3w

https://skydrive.live.com/redir?resid=62F21E6013CBFCB9!112&authkey=!AIp0uoevnNiJLYY

https://skydrive.live.com/redir?resid=62F21E6013CBFCB9!113&authkey=!ACnO0HEhUQmhz4M

https://skydrive.live.com/redir?resid=62F21E6013CBFCB9!114&authkey=!AD58FzZrGwz3H0E

--
--
Regards
Qiao Nuohan


>From cd2b212a947426f9c3f72af8371c5dbd2c3a565e Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@xxxxxxxxxxxxxx>
Date: Mon, 16 Jul 2012 05:26:27 +0800
Subject: [PATCH 3/3] display registers stored in qemu note section

---
 netdump.c |  210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 210 insertions(+), 0 deletions(-)

diff --git a/netdump.c b/netdump.c
index db65704..61467b9 100644
--- a/netdump.c
+++ b/netdump.c
@@ -1715,12 +1715,14 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
 	char *ptr;
 	ulong *uptr;
 	int xen_core, vmcoreinfo, eraseinfo;
+	int qemu_info;
 	uint64_t remaining, notesize;
 
 	note = (Elf32_Nhdr *)((char *)nd->elf32 + offset);
 
         BZERO(buf, BUFSIZE);
 	xen_core = vmcoreinfo = eraseinfo = FALSE;
+	qemu_info = FALSE;
         ptr = (char *)note + sizeof(Elf32_Nhdr);
 
 	if (ptr > (nd->elf_header + nd->header_size)) {
@@ -1811,6 +1813,7 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
 		xen_core = STRNEQ(buf, "XEN CORE") || STRNEQ(buf, "Xen");
 		vmcoreinfo = STRNEQ(buf, "VMCOREINFO");
 		eraseinfo = STRNEQ(buf, "ERASEINFO");
+		qemu_info = STRNEQ(buf, "QEMU");
 		if (xen_core) {
 			netdump_print("(unknown Xen n_type)\n"); 
 			if (store)
@@ -1904,6 +1907,103 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
 	if (xen_core)
 		uptr = (ulong *)roundup((ulong)uptr, 4);
 
+	if (CRASHDEBUG(1) & qemu_info) {
+		netdump_print("version:%08lx      size:%08lx\n",
+				((QEMUCPUState *)uptr)->version,
+				((QEMUCPUState *)uptr)->size);
+		netdump_print("rax:%016llx  rbx:%016llx  rcx:%016llx\n",
+				((QEMUCPUState *)uptr)->rax,
+				((QEMUCPUState *)uptr)->rbx,
+				((QEMUCPUState *)uptr)->rcx);
+		netdump_print("rdx:%016llx  rsi:%016llx  rdi:%016llx\n",
+				((QEMUCPUState *)uptr)->rdx,
+				((QEMUCPUState *)uptr)->rsi,
+				((QEMUCPUState *)uptr)->rdi);
+		netdump_print("rsp:%016llx  rbp:%016llx\n",
+				((QEMUCPUState *)uptr)->rsp,
+				((QEMUCPUState *)uptr)->rbp);
+		netdump_print("rip:%016llx  rflags:%016llx\n",
+				((QEMUCPUState *)uptr)->rip,
+				((QEMUCPUState *)uptr)->rflags);
+		netdump_print("cs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->cs.selector,
+				((QEMUCPUState *)uptr)->cs.limit,
+				((QEMUCPUState *)uptr)->cs.flags,
+				((QEMUCPUState *)uptr)->cs.pad,
+				((QEMUCPUState *)uptr)->cs.base);
+		netdump_print("ds:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ds.selector,
+				((QEMUCPUState *)uptr)->ds.limit,
+				((QEMUCPUState *)uptr)->ds.flags,
+				((QEMUCPUState *)uptr)->ds.pad,
+				((QEMUCPUState *)uptr)->ds.base);
+		netdump_print("es:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->es.selector,
+				((QEMUCPUState *)uptr)->es.limit,
+				((QEMUCPUState *)uptr)->es.flags,
+				((QEMUCPUState *)uptr)->es.pad,
+				((QEMUCPUState *)uptr)->es.base);
+		netdump_print("fs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->fs.selector,
+				((QEMUCPUState *)uptr)->fs.limit,
+				((QEMUCPUState *)uptr)->fs.flags,
+				((QEMUCPUState *)uptr)->fs.pad,
+				((QEMUCPUState *)uptr)->fs.base);
+		netdump_print("gs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->gs.selector,
+				((QEMUCPUState *)uptr)->gs.limit,
+				((QEMUCPUState *)uptr)->gs.flags,
+				((QEMUCPUState *)uptr)->gs.pad,
+				((QEMUCPUState *)uptr)->gs.base);
+		netdump_print("ss:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ss.selector,
+				((QEMUCPUState *)uptr)->ss.limit,
+				((QEMUCPUState *)uptr)->ss.flags,
+				((QEMUCPUState *)uptr)->ss.pad,
+				((QEMUCPUState *)uptr)->ss.base);
+		netdump_print("ldt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ldt.selector,
+				((QEMUCPUState *)uptr)->ldt.limit,
+				((QEMUCPUState *)uptr)->ldt.flags,
+				((QEMUCPUState *)uptr)->ldt.pad,
+				((QEMUCPUState *)uptr)->ldt.base);
+		netdump_print("tr:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->tr.selector,
+				((QEMUCPUState *)uptr)->tr.limit,
+				((QEMUCPUState *)uptr)->tr.flags,
+				((QEMUCPUState *)uptr)->tr.pad,
+				((QEMUCPUState *)uptr)->tr.base);
+		netdump_print("gdt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->gdt.selector,
+				((QEMUCPUState *)uptr)->gdt.limit,
+				((QEMUCPUState *)uptr)->gdt.flags,
+				((QEMUCPUState *)uptr)->gdt.pad,
+				((QEMUCPUState *)uptr)->gdt.base);
+		netdump_print("idt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->idt.selector,
+				((QEMUCPUState *)uptr)->idt.limit,
+				((QEMUCPUState *)uptr)->idt.flags,
+				((QEMUCPUState *)uptr)->idt.pad,
+				((QEMUCPUState *)uptr)->idt.base);
+		netdump_print("cr[0]:%016llx  cr[1]:%016llx  cr[2]:%016llx\n",
+				((QEMUCPUState *)uptr)->cr[0],
+				((QEMUCPUState *)uptr)->cr[1],
+				((QEMUCPUState *)uptr)->cr[2]);
+		netdump_print("cr[3]:%016llx  cr[4]:%016llx\n",
+				((QEMUCPUState *)uptr)->cr[3],
+				((QEMUCPUState *)uptr)->cr[4]);
+	}
+
 	if (vmcoreinfo || eraseinfo) {
                 netdump_print("                         ");
                 ptr += note->n_namesz + 1;
@@ -1948,6 +2048,7 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 	int *iptr;
 	ulong *up;
 	int xen_core, vmcoreinfo, eraseinfo;
+	int qemu_info;
 	uint64_t remaining, notesize;
 
 	note = (Elf64_Nhdr *)((char *)nd->elf64 + offset);
@@ -1955,6 +2056,7 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
         BZERO(buf, BUFSIZE);
         ptr = (char *)note + sizeof(Elf64_Nhdr);
 	xen_core = vmcoreinfo = eraseinfo = FALSE;
+	qemu_info = FALSE;
 
 	if (ptr > (nd->elf_header + nd->header_size)) {
 		error(WARNING, 
@@ -2075,6 +2177,7 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 		xen_core = STRNEQ(buf, "XEN CORE") || STRNEQ(buf, "Xen");
 		vmcoreinfo = STRNEQ(buf, "VMCOREINFO");
 		eraseinfo = STRNEQ(buf, "ERASEINFO");
+		qemu_info = STRNEQ(buf, "QEMU");
                 if (xen_core) {
                         netdump_print("(unknown Xen n_type)\n");
 			if (store)
@@ -2180,6 +2283,113 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 			uptr = (ulonglong *)roundup((ulong)uptr, 4);
 	}
 
+	if (CRASHDEBUG(1) & qemu_info) {
+		netdump_print("version:%08lx      size:%08lx\n",
+				((QEMUCPUState *)uptr)->version,
+				((QEMUCPUState *)uptr)->size);
+		netdump_print("rax:%016llx  rbx:%016llx  rcx:%016llx\n",
+				((QEMUCPUState *)uptr)->rax,
+				((QEMUCPUState *)uptr)->rbx,
+				((QEMUCPUState *)uptr)->rcx);
+		netdump_print("rdx:%016llx  rsi:%016llx  rdi:%016llx\n",
+				((QEMUCPUState *)uptr)->rdx,
+				((QEMUCPUState *)uptr)->rsi,
+				((QEMUCPUState *)uptr)->rdi);
+		netdump_print("rsp:%016llx  rbp:%016llx  r8:%016llx\n",
+				((QEMUCPUState *)uptr)->rsp,
+				((QEMUCPUState *)uptr)->rbp,
+				((QEMUCPUState *)uptr)->r8);
+		netdump_print("r9:%016llx   r10:%016llx  r11:%016llx\n",
+				((QEMUCPUState *)uptr)->r9,
+				((QEMUCPUState *)uptr)->r10,
+				((QEMUCPUState *)uptr)->r11);
+		netdump_print("r12:%016llx  r13:%016llx  r14:%016llx\n",
+				((QEMUCPUState *)uptr)->r12,
+				((QEMUCPUState *)uptr)->r13,
+				((QEMUCPUState *)uptr)->r14);
+		netdump_print("r15:%016llx  rip:%016llx  rflags:%016llx\n",
+				((QEMUCPUState *)uptr)->r15,
+				((QEMUCPUState *)uptr)->rip,
+				((QEMUCPUState *)uptr)->rflags);
+		netdump_print("cs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->cs.selector,
+				((QEMUCPUState *)uptr)->cs.limit,
+				((QEMUCPUState *)uptr)->cs.flags,
+				((QEMUCPUState *)uptr)->cs.pad,
+				((QEMUCPUState *)uptr)->cs.base);
+		netdump_print("ds:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ds.selector,
+				((QEMUCPUState *)uptr)->ds.limit,
+				((QEMUCPUState *)uptr)->ds.flags,
+				((QEMUCPUState *)uptr)->ds.pad,
+				((QEMUCPUState *)uptr)->ds.base);
+		netdump_print("es:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->es.selector,
+				((QEMUCPUState *)uptr)->es.limit,
+				((QEMUCPUState *)uptr)->es.flags,
+				((QEMUCPUState *)uptr)->es.pad,
+				((QEMUCPUState *)uptr)->es.base);
+		netdump_print("fs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->fs.selector,
+				((QEMUCPUState *)uptr)->fs.limit,
+				((QEMUCPUState *)uptr)->fs.flags,
+				((QEMUCPUState *)uptr)->fs.pad,
+				((QEMUCPUState *)uptr)->fs.base);
+		netdump_print("gs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->gs.selector,
+				((QEMUCPUState *)uptr)->gs.limit,
+				((QEMUCPUState *)uptr)->gs.flags,
+				((QEMUCPUState *)uptr)->gs.pad,
+				((QEMUCPUState *)uptr)->gs.base);
+		netdump_print("ss:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ss.selector,
+				((QEMUCPUState *)uptr)->ss.limit,
+				((QEMUCPUState *)uptr)->ss.flags,
+				((QEMUCPUState *)uptr)->ss.pad,
+				((QEMUCPUState *)uptr)->ss.base);
+		netdump_print("ldt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ldt.selector,
+				((QEMUCPUState *)uptr)->ldt.limit,
+				((QEMUCPUState *)uptr)->ldt.flags,
+				((QEMUCPUState *)uptr)->ldt.pad,
+				((QEMUCPUState *)uptr)->ldt.base);
+		netdump_print("tr:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->tr.selector,
+				((QEMUCPUState *)uptr)->tr.limit,
+				((QEMUCPUState *)uptr)->tr.flags,
+				((QEMUCPUState *)uptr)->tr.pad,
+				((QEMUCPUState *)uptr)->tr.base);
+		netdump_print("gdt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->gdt.selector,
+				((QEMUCPUState *)uptr)->gdt.limit,
+				((QEMUCPUState *)uptr)->gdt.flags,
+				((QEMUCPUState *)uptr)->gdt.pad,
+				((QEMUCPUState *)uptr)->gdt.base);
+		netdump_print("idt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->idt.selector,
+				((QEMUCPUState *)uptr)->idt.limit,
+				((QEMUCPUState *)uptr)->idt.flags,
+				((QEMUCPUState *)uptr)->idt.pad,
+				((QEMUCPUState *)uptr)->idt.base);
+		netdump_print("cr[0]:%016llx  cr[1]:%016llx  cr[2]:%016llx\n",
+				((QEMUCPUState *)uptr)->cr[0],
+				((QEMUCPUState *)uptr)->cr[1],
+				((QEMUCPUState *)uptr)->cr[2]);
+		netdump_print("cr[3]:%016llx  cr[4]:%016llx\n",
+				((QEMUCPUState *)uptr)->cr[3],
+				((QEMUCPUState *)uptr)->cr[4]);
+	}
+
 	if (BITS32() && (xen_core || (note->n_type == NT_PRSTATUS))) {
 		iptr = (int *)uptr;
 		for (i = lf = 0; i < note->n_descsz/sizeof(ulong); i++) {
-- 
1.7.1

>From 600d836e6735c7ed4658cfbb4e5638424ec25d9f Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@xxxxxxxxxxxxxx>
Date: Mon, 16 Jul 2012 05:10:08 +0800
Subject: [PATCH 1/3] add support to qemu memory dump

---
 defs.h    |   18 +++++-
 filesys.c |    6 ++-
 kernel.c  |    2 +
 main.c    |   35 +++++++---
 memory.c  |   18 ++++-
 netdump.c |  211 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 netdump.h |   23 +++++++
 task.c    |    8 ++-
 tools.c   |    4 +-
 x86_64.c  |    2 +-
 10 files changed, 296 insertions(+), 31 deletions(-)

diff --git a/defs.h b/defs.h
index caa87c0..698240a 100755
--- a/defs.h
+++ b/defs.h
@@ -250,6 +250,7 @@ struct number_option {
 #define NETDUMP_DUMPFILE()  (pc->flags & (NETDUMP|REM_NETDUMP))
 #define DISKDUMP_DUMPFILE() (pc->flags & DISKDUMP)
 #define KDUMP_DUMPFILE()    (pc->flags & KDUMP)
+#define QEMU_MEM_DUMP_DUMPFILE() (pc->flags2 & QEMU_MEM_DUMP)
 #define XENDUMP_DUMPFILE()  (pc->flags & XENDUMP)
 #define XEN_HYPER_MODE()    (pc->flags & XEN_HYPER)
 #define SYSRQ_TASK(X)       ((pc->flags & SYSRQ) && is_task_active(X))
@@ -260,7 +261,7 @@ struct number_option {
 
 #define NETDUMP_LOCAL    (0x1)  /* netdump_data flags */
 #define NETDUMP_REMOTE   (0x2)  
-#define VMCORE_VALID()   (nd->flags & (NETDUMP_LOCAL|NETDUMP_REMOTE|KDUMP_LOCAL))
+#define VMCORE_VALID()   (nd->flags & (NETDUMP_LOCAL|NETDUMP_REMOTE|KDUMP_LOCAL|QEMU_MEM_DUMP_LOCAL))
 #define NETDUMP_ELF32    (0x4)
 #define NETDUMP_ELF64    (0x8)
 #define PARTIAL_DUMP    (0x10)  /* netdump or diskdump */
@@ -270,11 +271,14 @@ struct number_option {
 #define KCORE_LOCAL    (0x100)     
 #define KCORE_ELF32    (0x200)
 #define KCORE_ELF64    (0x400)
+#define QEMU_MEM_DUMP_LOCAL (0x800)
+#define QEMU_MEM_DUMP_ELF32 (0x1000)
+#define QEMU_MEM_DUMP_ELF64 (0x2000)
 #define KVMDUMP_LOCAL    (0x1)
 #define KVMDUMP_VALID()  (kvm->flags & (KVMDUMP_LOCAL))
 
 #define DUMPFILE_FORMAT(flags) ((flags) & \
-		        (NETDUMP_ELF32|NETDUMP_ELF64|KDUMP_ELF32|KDUMP_ELF64))
+		        (NETDUMP_ELF32|NETDUMP_ELF64|KDUMP_ELF32|KDUMP_ELF64|QEMU_MEM_DUMP_ELF32|QEMU_MEM_DUMP_ELF64))
 
 #define DISKDUMP_LOCAL      (0x1)
 #define KDUMP_CMPRS_LOCAL   (0x2)
@@ -484,6 +488,7 @@ struct program_context {
 #define ERASEINFO_DATA (0x10ULL)
 #define GDB_CMD_MODE   (0x20ULL)
 #define LIVE_DUMP      (0x40ULL)
+#define QEMU_MEM_DUMP  (0x80ULL)
 #define FLAT_FORMAT() (pc->flags2 & FLAT)
 #define ELF_NOTES_VALID() (pc->flags2 & ELF_NOTES)
 	char *cleanup;
@@ -4982,6 +4987,15 @@ int proc_kcore_init(FILE *);
 int read_proc_kcore(int, void *, int, ulong, physaddr_t);
 int write_proc_kcore(int, void *, int, ulong, physaddr_t);
 int kcore_memory_dump(FILE *);
+struct vmcore_data *get_qemu_mem_dump_vmcore_data(void);
+int is_qemu_mem_dump(char *, ulong);
+int qemu_mem_dump_init(char *, FILE *);
+ulong get_qemu_mem_dump_panic_task(void);
+uint qemu_mem_dump_page_size(void);
+int qemu_mem_dump_free_memory(void);
+int qemu_mem_dump_memory_used(void);
+int qemu_mem_dump_memory_dump(FILE *);
+void get_qemu_mem_dump_regs(struct bt_info *, ulong *, ulong *);
 
 /*
  *  diskdump.c
diff --git a/filesys.c b/filesys.c
index 6fc7d42..4295fa6 100755
--- a/filesys.c
+++ b/filesys.c
@@ -207,7 +207,7 @@ memory_source_init(void)
 	        	error(FATAL, "%s: %s\n", pc->dumpfile, 
 				strerror(ENOENT));
 	
-		if (!(pc->flags & DUMPFILE_TYPES)) 
+		if (!(pc->flags & DUMPFILE_TYPES || pc->flags2 & QEMU_MEM_DUMP)) 
 			error(FATAL, "%s: dump format not supported!\n",
 				pc->dumpfile);
 	
@@ -215,6 +215,10 @@ memory_source_init(void)
                         if (!netdump_init(pc->dumpfile, fp))
                                 error(FATAL, "%s: initialization failed\n",
                                         pc->dumpfile);
+		} else if (pc->flags2 & QEMU_MEM_DUMP) {
+			if (!qemu_mem_dump_init(pc->dumpfile, fp))
+                               	error(FATAL, "%s: initialization failed\n",
+                                       	pc->dumpfile);
 		} else if (pc->flags & KDUMP) {
                         if (!kdump_init(pc->dumpfile, fp))
                                 error(FATAL, "%s: initialization failed\n",
diff --git a/kernel.c b/kernel.c
index e2707d3..a5c49a7 100755
--- a/kernel.c
+++ b/kernel.c
@@ -2382,6 +2382,8 @@ back_trace(struct bt_info *bt)
                 get_netdump_regs(bt, &eip, &esp);
 	else if (KDUMP_DUMPFILE())
                 get_kdump_regs(bt, &eip, &esp);
+	else if (QEMU_MEM_DUMP_DUMPFILE())
+		get_qemu_mem_dump_regs(bt, &eip, &esp);
 	else if (DISKDUMP_DUMPFILE())
                 get_diskdump_regs(bt, &eip, &esp);
 	else if (KVMDUMP_DUMPFILE())
diff --git a/main.c b/main.c
index 7b06cc9..5c363c5 100755
--- a/main.c
+++ b/main.c
@@ -425,7 +425,7 @@ main(int argc, char **argv)
 				pc->flags2 |= FLAT;
 
 			if (STREQ(argv[optind], "/dev/mem")) {
-                        	if (pc->flags & MEMORY_SOURCES) {
+                        	if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
                                 	error(INFO, 
                                             "too many dumpfile arguments\n");
                                 	program_usage(SHORT_FORM);
@@ -437,7 +437,7 @@ main(int argc, char **argv)
 				pc->live_memsrc = argv[optind];
 
 			} else if (is_proc_kcore(argv[optind], KCORE_LOCAL)) {
-				if (pc->flags & MEMORY_SOURCES) {
+				if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
 					error(INFO, 
 					    "too many dumpfile arguments\n");
 					program_usage(SHORT_FORM);
@@ -449,7 +449,7 @@ main(int argc, char **argv)
 				pc->live_memsrc = argv[optind];
 
 			} else if (is_netdump(argv[optind], NETDUMP_LOCAL)) {
-                                if (pc->flags & MEMORY_SOURCES) {
+                                if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
                                         error(INFO,
                                             "too many dumpfile arguments\n");
                                         program_usage(SHORT_FORM);
@@ -466,7 +466,7 @@ main(int argc, char **argv)
 				}
 
                         } else if (is_kdump(argv[optind], KDUMP_LOCAL)) {
-                                if (pc->flags & MEMORY_SOURCES) {
+                                if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
                                         error(INFO,
                                             "too many dumpfile arguments\n");
                                         program_usage(SHORT_FORM);
@@ -476,8 +476,19 @@ main(int argc, char **argv)
                                 pc->readmem = read_kdump;
                                 pc->writemem = write_kdump;
 
+                        } else if (is_qemu_mem_dump(argv[optind], QEMU_MEM_DUMP_LOCAL)) {
+                                if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
+                                        error(INFO,
+                                            "too many dumpfile arguments\n");
+                                        program_usage(SHORT_FORM);
+                                }
+				pc->flags2 |= QEMU_MEM_DUMP;
+                                pc->dumpfile = argv[optind];
+                                pc->readmem = read_netdump;
+                                pc->writemem = write_netdump;
+
                         } else if (is_kvmdump(argv[optind])) {
-                                if (pc->flags & MEMORY_SOURCES) {
+                                if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
                                         error(INFO,
                                             "too many dumpfile arguments\n");
                                         program_usage(SHORT_FORM);
@@ -496,7 +507,7 @@ main(int argc, char **argv)
 				pc->kvmdump_mapfile = argv[optind];
                                 
                         } else if (is_xendump(argv[optind])) {
-                                if (pc->flags & MEMORY_SOURCES) {
+                                if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
                                         error(INFO,
                                             "too many dumpfile arguments\n");
                                         program_usage(SHORT_FORM);
@@ -511,7 +522,7 @@ main(int argc, char **argv)
                                 pc->flags |= (SYSMAP|SYSMAP_ARG);
 
 			} else if (is_diskdump(argv[optind])) {
-                                if ((pc->flags & MEMORY_SOURCES) &&
+                                if ((pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) &&
                                     (!dumpfile_is_split())) {
                                         error(INFO,
                                             "too many dumpfile arguments\n");
@@ -523,7 +534,7 @@ main(int argc, char **argv)
                                 pc->writemem = write_diskdump;
 
 			} else if (is_lkcd_compressed_dump(argv[optind])) {
-				if (pc->flags & MEMORY_SOURCES) {
+				if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
                                         error(INFO,
                                             "too many dumpfile arguments\n");
                                         program_usage(SHORT_FORM);
@@ -534,7 +545,7 @@ main(int argc, char **argv)
 				pc->writemem = write_lkcd_dumpfile;
 
 			} else if (is_mclx_compressed_dump(argv[optind])) {
-				if (pc->flags & MEMORY_SOURCES) {
+				if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
 					error(INFO,
                                             "too many dumpfile arguments\n");
                                         program_usage(SHORT_FORM);
@@ -545,7 +556,7 @@ main(int argc, char **argv)
 				pc->writemem = write_mclx_dumpfile;
 
                         } else if (is_s390_dump(argv[optind])) {
-                                if (pc->flags & MEMORY_SOURCES) {
+                                if (pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) {
                                         error(INFO,
                                             "too many dumpfile arguments\n");
                                         program_usage(SHORT_FORM);
@@ -556,7 +567,7 @@ main(int argc, char **argv)
                                 pc->writemem = write_s390_dumpfile;
 
 			} else if (is_sadump(argv[optind])) {
-				if ((pc->flags & MEMORY_SOURCES) &&
+				if ((pc->flags & MEMORY_SOURCES || pc->flags2 & QEMU_MEM_DUMP) &&
 				    !sadump_is_diskset()) {
                                         error(INFO,
                                             "too many dumpfile arguments\n");
@@ -1315,6 +1326,8 @@ dump_program_context(void)
 		fprintf(fp, "%sREMOTE_DAEMON", others++ ? "|" : "");
 	if (pc->flags2 & LIVE_DUMP)
 		fprintf(fp, "%sLIVE_DUMP", others++ ? "|" : "");
+	if (pc->flags2 & QEMU_MEM_DUMP)
+		fprintf(fp, "%sQEMU_MEM_DUMP", others++ ? "|" : "");
 	fprintf(fp, ")\n");
 
 	fprintf(fp, "         namelist: %s\n", pc->namelist);
diff --git a/memory.c b/memory.c
index 703e623..20b5af8 100755
--- a/memory.c
+++ b/memory.c
@@ -14321,9 +14321,13 @@ memory_page_size(void)
 		break;
 
 	default:
-		psz = 0;
-		error(FATAL, "memory_page_size: invalid pc->flags: %lx\n", 
-			pc->flags & MEMORY_SOURCES); 
+		if (pc->flags2 & QEMU_MEM_DUMP)
+			psz = qemu_mem_dump_page_size();
+		else {
+			psz = 0;
+			error(FATAL, "memory_page_size: invalid pc->flags: %lx\n", 
+				pc->flags & MEMORY_SOURCES);
+		}
 	}
 
 	return psz;
@@ -14522,6 +14526,8 @@ dumpfile_memory(int cmd)
                         retval = remote_memory_used();
 		else if (pc->flags & NETDUMP)
         		retval = netdump_memory_used();
+		else if (pc->flags2 & QEMU_MEM_DUMP)
+			retval = qemu_mem_dump_memory_used();
 		else if (pc->flags & KDUMP)
         		retval = kdump_memory_used();
 		else if (pc->flags & XENDUMP)
@@ -14545,6 +14551,8 @@ dumpfile_memory(int cmd)
                         retval = remote_free_memory();
                 else if (pc->flags & NETDUMP)
 			retval = netdump_free_memory();
+		else if (pc->flags2 & QEMU_MEM_DUMP)
+			retval = qemu_mem_dump_free_memory();
                 else if (pc->flags & KDUMP)
 			retval = kdump_free_memory();
                 else if (pc->flags & XENDUMP)
@@ -14566,8 +14574,10 @@ dumpfile_memory(int cmd)
 	case DUMPFILE_MEM_DUMP:
 		if (REMOTE_DUMPFILE())
                         retval = remote_memory_dump(0);
-                else if (pc->flags & NETDUMP) 
+                else if (pc->flags & NETDUMP)
                         retval = netdump_memory_dump(fp);
+		else if (pc->flags2 & QEMU_MEM_DUMP)
+			retval = qemu_mem_dump_memory_dump(fp);
                 else if (pc->flags & KDUMP) 
                         retval = kdump_memory_dump(fp);
                 else if (pc->flags & XENDUMP) 
diff --git a/netdump.c b/netdump.c
index 9fecbf3..792881f 100644
--- a/netdump.c
+++ b/netdump.c
@@ -42,6 +42,7 @@ static int proc_kcore_init_32(FILE *fp);
 static int proc_kcore_init_64(FILE *fp);
 static char *get_regs_from_note(char *, ulong *, ulong *);
 static void kdump_get_osrelease(void);
+static int check_elf_note(char *, int , char *, int);
 
 #define ELFSTORE 1
 #define ELFREAD  0
@@ -205,9 +206,12 @@ is_netdump(char *file, ulong source_query)
                 size = (size_t)load32->p_offset;
 
 		if ((load32->p_offset & (MIN_PAGE_SIZE-1)) &&
-		    (load32->p_align == 0))
-                	tmp_flags |= KDUMP_ELF32;
-		else
+		    (load32->p_align == 0)) {
+			if (check_elf_note(eheader, fd, file, 0))
+				tmp_flags |= QEMU_MEM_DUMP_ELF32;
+                	else
+				tmp_flags |= KDUMP_ELF32;
+		} else
                 	tmp_flags |= NETDUMP_ELF32;
 	} else if ((elf64->e_ident[EI_CLASS] == ELFCLASS64) &&
 	    (swap16(elf64->e_type, swap) == ET_CORE) &&
@@ -258,9 +262,12 @@ is_netdump(char *file, ulong source_query)
                         &eheader[sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)];
                 size = (size_t)load64->p_offset;
 		if ((load64->p_offset & (MIN_PAGE_SIZE-1)) &&
-		    (load64->p_align == 0))
-                	tmp_flags |= KDUMP_ELF64;
-		else
+		    (load64->p_align == 0)) {
+			if (check_elf_note(eheader, fd, file, 1))
+				tmp_flags |= QEMU_MEM_DUMP_ELF64;
+                	else
+				tmp_flags |= KDUMP_ELF64;
+		} else
                 	tmp_flags |= NETDUMP_ELF64;
 	} else {
 		if (CRASHDEBUG(2))
@@ -292,6 +299,13 @@ is_netdump(char *file, ulong source_query)
 			break;
 		else
 			goto bailout;
+
+	case QEMU_MEM_DUMP_ELF32:
+	case QEMU_MEM_DUMP_ELF64:
+		if (source_query & QEMU_MEM_DUMP_LOCAL)
+			break;
+		else
+			goto bailout;
 	}
 
 	if ((tmp_elf_header = (char *)malloc(size)) == NULL) {
@@ -327,6 +341,7 @@ is_netdump(char *file, ulong source_query)
 	{
 	case NETDUMP_ELF32:
 	case KDUMP_ELF32:
+	case QEMU_MEM_DUMP_ELF32:
 		nd->header_size = load32->p_offset;
         	nd->elf32 = (Elf32_Ehdr *)&nd->elf_header[0];
 		nd->num_pt_load_segments = nd->elf32->e_phnum - 1;
@@ -356,6 +371,7 @@ is_netdump(char *file, ulong source_query)
 
 	case NETDUMP_ELF64:
 	case KDUMP_ELF64:
+	case QEMU_MEM_DUMP_ELF64:
                 nd->header_size = load64->p_offset;
                 nd->elf64 = (Elf64_Ehdr *)&nd->elf_header[0];
 		nd->num_pt_load_segments = nd->elf64->e_phnum - 1;
@@ -521,6 +537,8 @@ read_netdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
 	case NETDUMP_ELF64:
 	case KDUMP_ELF32:
 	case KDUMP_ELF64:
+	case QEMU_MEM_DUMP_ELF32:
+	case QEMU_MEM_DUMP_ELF64:
 		if (nd->num_pt_load_segments == 1) {
 			offset = (off_t)paddr + (off_t)nd->header_size -
 				(off_t)nd->pt_load_segments[0].phys_start;
@@ -611,6 +629,8 @@ write_netdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
 	case NETDUMP_ELF64:
 	case KDUMP_ELF32:
 	case KDUMP_ELF64:
+	case QEMU_MEM_DUMP_ELF32:
+	case QEMU_MEM_DUMP_ELF64:
 		if (nd->num_pt_load_segments == 1) {
 			offset = (off_t)paddr + (off_t)nd->header_size;
 			break;
@@ -744,6 +764,8 @@ get_netdump_panic_task(void)
 
         case KDUMP_ELF32:
         case KDUMP_ELF64:
+	case QEMU_MEM_DUMP_ELF32:
+	case QEMU_MEM_DUMP_ELF64:
 		crashing_cpu = -1;
 		if (kernel_symbol_exists("crashing_cpu")) {
 			get_symbol_data("crashing_cpu", sizeof(int), &i);
@@ -932,6 +954,12 @@ netdump_memory_dump(FILE *fp)
 		netdump_print("%sKDUMP_ELF64", others++ ? "|" : "");
 	if (nd->flags & PARTIAL_DUMP)
 		netdump_print("%sPARTIAL_DUMP", others++ ? "|" : "");
+	if (nd->flags & QEMU_MEM_DUMP_LOCAL)
+		netdump_print("%sQEMU_MEM_DUMP_LOCAL", others++ ? "|" : "");
+	if (nd->flags & QEMU_MEM_DUMP_ELF32)
+		netdump_print("%sQEMU_MEM_DUMP_ELF32", others++ ? "|" : "");
+	if (nd->flags & QEMU_MEM_DUMP_ELF64)
+		netdump_print("%sQEMU_MEM_DUMP_ELF64", others++ ? "|" : "");
 	netdump_print(") %s\n", FLAT_FORMAT() ? "[FLAT]" : "");
 	if ((pc->flags & RUNTIME) && symbol_exists("dump_level")) {
 		int dump_level;
@@ -1064,6 +1092,7 @@ netdump_memory_dump(FILE *fp)
 	{
 	case NETDUMP_ELF32:
 	case KDUMP_ELF32:
+	case QEMU_MEM_DUMP_ELF32:
 		dump_Elf32_Ehdr(nd->elf32);
 		dump_Elf32_Phdr(nd->notes32, ELFREAD);
                 for (i = 0; i < nd->num_pt_load_segments; i++) 
@@ -1078,6 +1107,7 @@ netdump_memory_dump(FILE *fp)
 
 	case NETDUMP_ELF64:
 	case KDUMP_ELF64:
+	case QEMU_MEM_DUMP_ELF64:
 		dump_Elf64_Ehdr(nd->elf64);
 		dump_Elf64_Phdr(nd->notes64, ELFREAD);
                 for (i = 0; i < nd->num_pt_load_segments; i++)
@@ -1854,6 +1884,9 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
 	if ((nd->flags & KDUMP_ELF32) && (note->n_namesz == 5))
 		uptr = (ulong *)(ptr + ((note->n_namesz + 3) & ~3));
 
+	if ((nd->flags & QEMU_MEM_DUMP_ELF32) && (note->n_namesz == 5))
+		uptr = (ulong *)(ptr + ((note->n_namesz + 3) & ~3));
+
 	if (xen_core)
 		uptr = (ulong *)roundup((ulong)uptr, 4);
 
@@ -2126,6 +2159,9 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 		if ((nd->flags & KDUMP_ELF64) && (note->n_namesz == 5))
 			uptr = (ulonglong *)(ptr + ((note->n_namesz + 3) & ~3));
 	
+		if ((nd->flags & QEMU_MEM_DUMP_ELF64) && (note->n_namesz == 5))
+			uptr = (ulonglong *)(ptr + ((note->n_namesz + 3) & ~3));
+
 		if (xen_core)
 			uptr = (ulonglong *)roundup((ulong)uptr, 4);
 	}
@@ -2290,7 +2326,7 @@ get_netdump_regs_x86_64(struct bt_info *bt, ulong *ripp, ulong *rspp)
         if (is_task_active(bt->task)) 
                 bt->flags |= BT_DUMPFILE_SEARCH;
 
-	if (((NETDUMP_DUMPFILE() || KDUMP_DUMPFILE()) &&
+	if (((NETDUMP_DUMPFILE() || KDUMP_DUMPFILE() || QEMU_MEM_DUMP_DUMPFILE()) &&
    	      VALID_STRUCT(user_regs_struct) && (bt->task == tt->panic_task)) ||
 	      (KDUMP_DUMPFILE() && (kt->flags & DWARF_UNWIND) && 
 	      (bt->flags & BT_DUMPFILE_SEARCH))) {
@@ -2321,7 +2357,7 @@ get_netdump_regs_x86_64(struct bt_info *bt, ulong *ripp, ulong *rspp)
                 		ULONG(user_regs + rsp_offset),
                 		ULONG(user_regs + rip_offset));
 
-		if (KDUMP_DUMPFILE()) {
+		if (KDUMP_DUMPFILE() || QEMU_MEM_DUMP_DUMPFILE()) {
 			*rspp = ULONG(user_regs + rsp_offset);
 			*ripp = ULONG(user_regs + rip_offset);
 
@@ -3475,3 +3511,162 @@ kdump_get_osrelease(void)
 	} else 
 		pc->flags2 &= ~GET_OSRELEASE;
 }
+
+int
+is_qemu_mem_dump(char *file, ulong source_query)
+{
+	return is_netdump(file, source_query);
+}
+
+int
+qemu_mem_dump_init(char *unused, FILE *fptr)
+{
+	return netdump_init(unused, fptr);
+}
+
+ulong 
+get_qemu_mem_dump_panic_task(void)
+{
+	return get_netdump_panic_task();
+}
+
+uint
+qemu_mem_dump_page_size()
+{
+	uint pagesz;
+
+	if (!VMCORE_VALID())
+		return 0;
+
+	if (!(pagesz = nd->page_size))
+		pagesz = (uint)getpagesize();
+
+	return pagesz;
+}
+
+int
+qemu_mem_dump_free_memory()
+{
+	return netdump_free_memory();
+}
+
+int
+qemu_mem_dump_memory_used()
+{
+	return netdump_memory_used();
+}
+
+int
+qemu_mem_dump_memory_dump(FILE *fp)
+{
+	return netdump_memory_dump(fp);
+}
+
+void
+get_qemu_mem_dump_regs(struct bt_info *bt, ulong *eip, ulong *esp)
+{
+	get_netdump_regs(bt, eip, esp);
+}
+
+struct vmcore_data *
+get_qemu_mem_dump_vmcore_data(void)
+{
+	if (!VMCORE_VALID() || !QEMU_MEM_DUMP_DUMPFILE())
+		return NULL;
+
+	return &vmcore_data;
+}
+
+static int
+check_elf_note(char *eheader, int fd, char *file, int machine_type)
+{
+	int qemu_memory_dump;
+	Elf32_Phdr *load32;
+	Elf64_Phdr *load64;
+	ulong offset;
+	ulong filesz;
+	char *pnotes;
+	char buf[BUFSIZE];
+	char *tmp_note;
+	Elf32_Nhdr *tmp_note32;
+	Elf64_Nhdr *tmp_note64;
+	uint32_t namesz, descsz, type;
+	char *name, *desc;
+	int num;
+
+	qemu_memory_dump  = FALSE;
+
+	load32 = (Elf32_Phdr *)&eheader[sizeof(Elf32_Ehdr)];
+	load64 = (Elf64_Phdr *)&eheader[sizeof(Elf64_Ehdr)];
+
+	if (machine_type == 0) {
+		if (!(load32->p_type == PT_NOTE))
+			return qemu_memory_dump;
+
+		offset = load32->p_offset;
+		filesz = load32->p_filesz;
+	} else {
+		if (!(load64->p_type == PT_NOTE))
+			return qemu_memory_dump;
+
+		offset = load64->p_offset;
+		filesz = load64->p_filesz;
+	}
+
+	if ((pnotes = (char *)malloc(filesz)) == NULL) {
+		fprintf(stderr, "cannot malloc elf note buffer\n");
+		clean_exit(1);
+	}
+
+	if (FLAT_FORMAT()) {
+		if (!read_flattened_format(fd, offset, pnotes, filesz)) {
+			free(pnotes);
+			return qemu_memory_dump;
+		}
+	} else {
+		if (lseek(fd, offset, SEEK_SET) != offset) {
+			sprintf(buf, "%s: lseek", file);
+			perror(buf);
+			return qemu_memory_dump;
+		}
+		if (read(fd, pnotes, filesz) != filesz) {
+			sprintf(buf, "%s: read", file);
+			perror(buf);
+			free(pnotes);
+			return qemu_memory_dump;
+		}
+	}
+
+	tmp_note = pnotes;
+	num = 0;
+
+	while (tmp_note < pnotes + filesz)
+	{
+		if (machine_type == 0) {
+			tmp_note32 = (Elf32_Nhdr *)tmp_note;
+			namesz = tmp_note32->n_namesz;
+			descsz = tmp_note32->n_descsz;
+			type = tmp_note32->n_type;
+
+			name = (char *)tmp_note + ((sizeof(Elf32_Nhdr) + 3) / 4) * 4;
+		} else {
+			tmp_note64 = (Elf64_Nhdr *)tmp_note;
+			namesz = tmp_note64->n_namesz;
+			descsz = tmp_note64->n_descsz;
+			type = tmp_note64->n_type;
+
+			name = (char *)tmp_note + ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
+		}
+		desc = name + ((namesz + 3) / 4) * 4;
+
+		if (STREQ(name, "QEMU")) {
+			qemu_memory_dump = TRUE;
+			nd->nt_qemu_percpu[num] = desc;
+			num++;
+		}
+		
+		tmp_note = desc + (descsz + 3) / 4 * 4;
+	}
+
+	return qemu_memory_dump;
+}
diff --git a/netdump.h b/netdump.h
index 2e296ad..ced0451 100644
--- a/netdump.h
+++ b/netdump.h
@@ -68,6 +68,7 @@ struct vmcore_data {
 	ulong switch_stack;
 	uint num_prstatus_notes;
 	void *nt_prstatus_percpu[NR_CPUS];
+	void *nt_qemu_percpu[NR_CPUS];
 	struct xen_kdump_data *xen_kdump_data;
 	void *vmcoreinfo;
 	uint size_vmcoreinfo;
@@ -172,3 +173,25 @@ struct proc_kcore_data {
 	Elf32_Phdr *load32;
 };
 
+struct QEMUCPUSegment {
+    uint32_t selector;
+    uint32_t limit;
+    uint32_t flags;
+    uint32_t pad;
+    uint64_t base;
+};
+
+typedef struct QEMUCPUSegment QEMUCPUSegment;
+
+struct QEMUCPUState {
+    uint32_t version;
+    uint32_t size;
+    uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
+    uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
+    uint64_t rip, rflags;
+    QEMUCPUSegment cs, ds, es, fs, gs, ss;
+    QEMUCPUSegment ldt, tr, gdt, idt;
+    uint64_t cr[5];
+};
+
+typedef struct QEMUCPUState QEMUCPUState;
diff --git a/task.c b/task.c
index 30de29a..e6fa46a 100755
--- a/task.c
+++ b/task.c
@@ -463,7 +463,7 @@ task_init(void)
 		tt->this_task = pid_to_task(active_pid);
 	}
 	else {
-		if (KDUMP_DUMPFILE())
+		if (KDUMP_DUMPFILE() || QEMU_MEM_DUMP_DUMPFILE())
 			map_cpus_to_prstatus();
 		else if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE())
 			map_cpus_to_prstatus_kdump_cmprs();
@@ -6031,6 +6031,10 @@ get_dumpfile_panic_task(void)
 			tt->panic_task : get_netdump_panic_task();
 		if (task) 
 			return task;
+	} else if (QEMU_MEM_DUMP_DUMPFILE()) {
+		task = get_qemu_mem_dump_panic_task();
+ 		if (task) 
+ 			return task;
 	} else if (KDUMP_DUMPFILE()) {
                 task = get_kdump_panic_task();
                 if (task)
@@ -6100,7 +6104,7 @@ populate_panic_threads(void)
 	}
 
 	if (!found && !(kt->flags & SMP) &&
-	    (LKCD_DUMPFILE() || NETDUMP_DUMPFILE() || 
+	    (LKCD_DUMPFILE() || NETDUMP_DUMPFILE() || QEMU_MEM_DUMP_DUMPFILE() ||
 	     KDUMP_DUMPFILE() || DISKDUMP_DUMPFILE() || KVMDUMP_DUMPFILE())) 
 		tt->panic_threads[0] = get_dumpfile_panic_task();
 }
diff --git a/tools.c b/tools.c
index 77f145e..48a14d3 100755
--- a/tools.c
+++ b/tools.c
@@ -5313,7 +5313,7 @@ machine_type_mismatch(char *file, char *e_machine, char *alt, ulong query)
 	if (machine_type(e_machine) || machine_type(alt))
 		return FALSE;
 
-	if (query == KDUMP_LOCAL)  /* already printed by NETDUMP_LOCAL */
+	if (query == KDUMP_LOCAL || query == QEMU_MEM_DUMP_LOCAL)  /* already printed by NETDUMP_LOCAL */
 		return TRUE;
 
 	error(WARNING, "machine type mismatch:\n");
@@ -5425,7 +5425,7 @@ endian_mismatch(char *file, char dumpfile_endian, ulong query)
 		break;
 	}
 
-	if (query == KDUMP_LOCAL)  /* already printed by NETDUMP_LOCAL */
+	if (query == KDUMP_LOCAL || query == QEMU_MEM_DUMP_LOCAL)  /* already printed by NETDUMP_LOCAL */
 		return TRUE;
 
         error(WARNING, "endian mismatch:\n");
diff --git a/x86_64.c b/x86_64.c
index 3ceae3e..64a3160 100755
--- a/x86_64.c
+++ b/x86_64.c
@@ -5865,7 +5865,7 @@ x86_64_calc_phys_base(void)
 		return;
 	}
 
-	if ((vd = get_kdump_vmcore_data())) {
+	if ((vd = get_kdump_vmcore_data()) || (vd = get_qemu_mem_dump_vmcore_data())) {
                 for (i = 0; i < vd->num_pt_load_segments; i++) {
 			phdr = vd->load64 + i;
 			if ((phdr->p_vaddr >= __START_KERNEL_map) &&
-- 
1.7.1

>From d45501b34baf8b4884d1a19ffc6325118c0fa21a Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@xxxxxxxxxxxxxx>
Date: Mon, 16 Jul 2012 05:11:03 +0800
Subject: [PATCH 2/3] support core dump file when kdump is operating

---
 defs.h    |    2 +
 main.c    |    2 +
 netdump.c |  224 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 netdump.h |    5 ++
 4 files changed, 233 insertions(+), 0 deletions(-)

diff --git a/defs.h b/defs.h
index 698240a..2967472 100755
--- a/defs.h
+++ b/defs.h
@@ -274,6 +274,7 @@ struct number_option {
 #define QEMU_MEM_DUMP_LOCAL (0x800)
 #define QEMU_MEM_DUMP_ELF32 (0x1000)
 #define QEMU_MEM_DUMP_ELF64 (0x2000)
+#define QEMU_MEM_DUMP_KDUMP_BACKUP (0x4000)
 #define KVMDUMP_LOCAL    (0x1)
 #define KVMDUMP_VALID()  (kvm->flags & (KVMDUMP_LOCAL))
 
@@ -4996,6 +4997,7 @@ int qemu_mem_dump_free_memory(void);
 int qemu_mem_dump_memory_used(void);
 int qemu_mem_dump_memory_dump(FILE *);
 void get_qemu_mem_dump_regs(struct bt_info *, ulong *, ulong *);
+void qemu_mem_dump_kdump_backup_region_init(void);
 
 /*
  *  diskdump.c
diff --git a/main.c b/main.c
index 5c363c5..92fa31a 100755
--- a/main.c
+++ b/main.c
@@ -638,6 +638,8 @@ main_loop(void)
         if (!(pc->flags & GDB_INIT)) {
 		gdb_session_init();
 		show_untrusted_files();
+		if (QEMU_MEM_DUMP_DUMPFILE())
+			qemu_mem_dump_kdump_backup_region_init();
 		if (SADUMP_DUMPFILE())
 			sadump_kdump_backup_region_init();
 		if (XEN_HYPER_MODE()) {
diff --git a/netdump.c b/netdump.c
index 792881f..db65704 100644
--- a/netdump.c
+++ b/netdump.c
@@ -519,6 +519,20 @@ read_netdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
 	struct pt_load_segment *pls;
 	int i;
 
+	if (nd->flags & QEMU_MEM_DUMP_KDUMP_BACKUP &&
+	    paddr >= nd->backup_src_start &&
+	    paddr < nd->backup_src_start + nd->backup_src_size) {
+		ulong orig_paddr;
+
+		orig_paddr = paddr;
+		paddr += nd->backup_offset - nd->backup_src_start;
+
+		if (CRASHDEBUG(1))
+			error(INFO,
+			    "qemu_mem_dump: kdump backup region: %#llx => %#llx\n",
+			    orig_paddr, paddr);
+	}
+
 	offset = 0;
 
 	/*
@@ -3670,3 +3684,213 @@ check_elf_note(char *eheader, int fd, char *file, int machine_type)
 
 	return qemu_memory_dump;
 }
+
+/**
+ * kdump saves the first 640kB physical memory for BIOS to use the
+ * range on boot of 2nd kernel. qemu mem dump translates read request to the
+ * 640kB region as to the back up region. This function seachs kexec
+ * resources for the backup region.
+ */
+void
+qemu_mem_dump_kdump_backup_region_init(void)
+{
+	char buf[BUFSIZE];
+	ulong i, total, kexec_crash_image_p, elfcorehdr_p;
+	uint16_t e_phnum, e_phentsize;
+	ulong backup_offset;
+	ulong backup_src_start, backup_src_size;
+	int kimage_segment_len;
+	size_t bufsize;
+
+	Elf64_Off e_phoff64 = 0;
+	Elf32_Off e_phoff32 = 0;
+
+	if (!readmem(symbol_value("kexec_crash_image"), KVADDR,
+		     &kexec_crash_image_p, sizeof(ulong),
+		     "kexec backup region: kexec_crash_image",
+		     QUIET|RETURN_ON_ERROR))
+		goto error;
+
+	if (!kexec_crash_image_p) {
+		if (CRASHDEBUG(1))
+			error(INFO, "qemu mem dump: kexec_crash_image not loaded\n");
+		return;
+	}
+
+	kimage_segment_len = get_array_length("kimage.segment", NULL,
+					      STRUCT_SIZE("kexec_segment"));
+
+	if (!readmem(kexec_crash_image_p + MEMBER_OFFSET("kimage", "segment"),
+		     KVADDR, buf, MEMBER_SIZE("kimage", "segment"),
+		     "kexec backup region: kexec_crash_image->segment",
+		     QUIET|RETURN_ON_ERROR))
+		goto error;
+
+	elfcorehdr_p = 0;
+	for (i = 0; i < kimage_segment_len; ++i) {
+		char e_ident[EI_NIDENT];
+		ulong mem;
+
+		mem = ULONG(buf + i * STRUCT_SIZE("kexec_segment") +
+			    MEMBER_OFFSET("kexec_segment", "mem"));
+		if (!mem)
+			continue;
+
+		if (!readmem(mem, PHYSADDR, e_ident, SELFMAG,
+			     "elfcorehdr: e_ident",
+			     QUIET|RETURN_ON_ERROR))
+			goto error;
+
+		if (strncmp(ELFMAG, e_ident, SELFMAG) == 0) {
+			elfcorehdr_p = mem;
+			break;
+		}
+	}
+	if (!elfcorehdr_p) {
+		if (CRASHDEBUG(1))
+			error(INFO,
+	"qemu mem dump: elfcorehdr not found in segments of kexec_crash_image\n");
+		goto error;
+	}
+	
+	if (nd->flags & QEMU_MEM_DUMP_ELF32) {
+		if (!readmem(elfcorehdr_p, PHYSADDR, buf, STRUCT_SIZE("elf32_hdr"),
+			"elfcorehdr", QUIET|RETURN_ON_ERROR))
+			goto error;
+
+		e_phnum = USHORT(buf + MEMBER_OFFSET("elf32_hdr", "e_phnum"));
+		e_phentsize = USHORT(buf + MEMBER_OFFSET("elf32_hdr", "e_phentsize"));
+		e_phoff32 = ULONG(buf + MEMBER_OFFSET("elf32_hdr", "e_phoff"));
+	} else {
+		if (!readmem(elfcorehdr_p, PHYSADDR, buf, STRUCT_SIZE("elf64_hdr"),
+			    "elfcorehdr", QUIET|RETURN_ON_ERROR))
+			goto error;
+
+		e_phnum = USHORT(buf + MEMBER_OFFSET("elf64_hdr", "e_phnum"));
+		e_phentsize = USHORT(buf + MEMBER_OFFSET("elf64_hdr", "e_phentsize"));
+		e_phoff64 = ULONG(buf + MEMBER_OFFSET("elf64_hdr", "e_phoff"));
+	}
+
+	backup_src_start = backup_src_size = backup_offset = 0;
+
+	for (i = 0; i < e_phnum; ++i) {
+		uint32_t p_type;
+		Elf32_Off p_offset32 = 0;
+		Elf64_Off p_offset64 = 0;
+		Elf32_Addr p_paddr32 = 0;
+		Elf64_Addr p_paddr64 = 0;
+		uint32_t p_memsz32 = 0;
+		uint64_t p_memsz64 = 0;
+
+		if (nd->flags & QEMU_MEM_DUMP_ELF32) {
+			if (!readmem(elfcorehdr_p + e_phoff32 + i * e_phentsize,
+				    PHYSADDR, buf, e_phentsize,
+				    "elfcorehdr: program header",
+				    QUIET|RETURN_ON_ERROR))
+				goto error;
+
+			p_type = UINT(buf+MEMBER_OFFSET("elf32_phdr","p_type"));
+			p_offset32 = ULONG(buf+MEMBER_OFFSET("elf32_phdr","p_offset"));
+			p_paddr32 = ULONG(buf+MEMBER_OFFSET("elf32_phdr","p_paddr"));
+			p_memsz32 = ULONG(buf+MEMBER_OFFSET("elf32_phdr","p_memsz"));
+		} else {
+			if (!readmem(elfcorehdr_p + e_phoff64 + i * e_phentsize,
+				    PHYSADDR, buf, e_phentsize,
+				    "elfcorehdr: program header",
+				    QUIET|RETURN_ON_ERROR))
+				goto error;
+
+			p_type = UINT(buf+MEMBER_OFFSET("elf64_phdr","p_type"));
+			p_offset64 = ULONG(buf+MEMBER_OFFSET("elf64_phdr","p_offset"));
+			p_paddr64 = ULONG(buf+MEMBER_OFFSET("elf64_phdr","p_paddr"));
+			p_memsz64 = ULONG(buf+MEMBER_OFFSET("elf64_phdr","p_memsz"));
+		}
+
+		/*
+		 * kexec marks backup region PT_LOAD by assigning
+		 * backup region address in p_offset, and p_addr in
+		 * p_offsets for other PT_LOAD entries.
+		 */
+		if (nd->flags & QEMU_MEM_DUMP_ELF32) {
+			if (p_type == PT_LOAD &&
+			    p_paddr32 <= KEXEC_BACKUP_SRC_END &&
+			    p_paddr32 != p_offset32) {
+
+				backup_src_start = p_paddr32;
+				backup_src_size = p_memsz32;
+				backup_offset = p_offset32;
+
+				if (CRASHDEBUG(1))
+					error(INFO,
+				"qemu mem dump: kexec backup region found: "
+				"START: %#08lx SIZE: %#08lx OFFSET: %#08lx\n",
+				backup_src_start, backup_src_size, backup_offset);
+
+				break;
+			}
+		} else {
+			if (p_type == PT_LOAD &&
+			    p_paddr64 <= KEXEC_BACKUP_SRC_END &&
+			    p_paddr64 != p_offset64) {
+
+				backup_src_start = p_paddr64;
+				backup_src_size = p_memsz64;
+				backup_offset = p_offset64;
+
+				if (CRASHDEBUG(1))
+					error(INFO,
+				"qemu mem dump: kexec backup region found: "
+				"START: %#016lx SIZE: %#016lx OFFSET: %#016lx\n",
+				backup_src_start, backup_src_size, backup_offset);
+
+				break;
+			}
+		}
+	}
+
+	if (!backup_offset) {
+		if (CRASHDEBUG(1))
+	error(WARNING, "qemu mem dump: backup region not found in elfcorehdr\n");
+		return;
+	}
+
+	bufsize = BUFSIZE;
+	for (total = 0; total < backup_src_size; total += bufsize) {
+		char backup_buf[BUFSIZE];
+		int j;
+
+		if (backup_src_size - total < BUFSIZE)
+			bufsize = backup_src_size - total;
+
+		if (!readmem(backup_offset + total, PHYSADDR, backup_buf,
+			     bufsize, "backup source", QUIET|RETURN_ON_ERROR))
+			goto error;
+
+		/*
+		 * We're assuming the backup resion is initialized
+		 * with 0 filled if kdump has not run.
+		 */
+		for (j = 0; j < bufsize; ++j) {
+			if (backup_buf[j]) {
+
+				nd->flags |= QEMU_MEM_DUMP_KDUMP_BACKUP;
+				nd->backup_src_start = backup_src_start;
+				nd->backup_src_size = backup_src_size;
+				nd->backup_offset = backup_offset;
+
+				if (CRASHDEBUG(1))
+error(INFO, "qemu mem dump: backup region is used: %lx\n", backup_offset + total + j);
+
+				return;
+			}
+		}
+	}
+
+	if (CRASHDEBUG(1))
+		error(INFO, "qemu mem dump: kexec backup region not used\n");
+
+	return;
+
+error:
+	error(WARNING, "failed to init kexec backup region\n");
+}
diff --git a/netdump.h b/netdump.h
index ced0451..f0cd43c 100644
--- a/netdump.h
+++ b/netdump.h
@@ -72,6 +72,11 @@ struct vmcore_data {
 	struct xen_kdump_data *xen_kdump_data;
 	void *vmcoreinfo;
 	uint size_vmcoreinfo;
+/* Backup Region, First 640K of System RAM. */
+#define KEXEC_BACKUP_SRC_END	0x0009ffff
+	ulong backup_src_start;
+	ulong backup_src_size;
+	ulong backup_offset;
 };
 
 /*
-- 
1.7.1

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux