>From 600d836e6735c7ed4658cfbb4e5638424ec25d9f Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@cn.fujitsu.com>
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

