>From 518dfa90c198fa75e715d9715b59f4a42902743c Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@cn.fujitsu.com>
Date: Wed, 22 Aug 2012 14:40:51 +0800
Subject: [PATCH 2/4] display registers stored in qemu note section

---
 defs.h    |    2 +
 help.c    |   15 ++++++-
 netdump.c |  132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 netdump.h |   24 +++++++++++
 4 files changed, 167 insertions(+), 6 deletions(-)

diff --git a/defs.h b/defs.h
index d37e453..96c9997 100755
--- a/defs.h
+++ b/defs.h
@@ -4211,6 +4211,7 @@ int cleanup_memory_driver(void);
 #define END_OF_HELP_DATA       "END_OF_HELP_DATA"
 void help_init(void);
 void cmd_usage(char *, int);
+void dump_register(void);
 void display_version(void);
 void display_help_screen(char *);
 #ifdef ARM
@@ -5004,6 +5005,7 @@ 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 *);
+void dump_register_for_qemu_mem_dump(void);
 
 /*
  *  diskdump.c
diff --git a/help.c b/help.c
index 6ab9eea..b292f24 100755
--- a/help.c
+++ b/help.c
@@ -466,7 +466,7 @@ cmd_help(void)
 	oflag = 0;
 
         while ((c = getopt(argcnt, args, 
-	        "efNDdmM:ngcaBbHhkKsvVoptTzLxO")) != EOF) {
+	        "efNDdmM:ngcaBbHhkKsvVoptTzLxOq")) != EOF) {
                 switch(c)
                 {
 		case 'e':
@@ -601,6 +601,10 @@ cmd_help(void)
 			dumpfile_memory(DUMPFILE_ENVIRONMENT);
 			return;
 
+		case 'q':
+			dump_register();
+			return;
+
                 default:  
 			argerrs++;
                         break;
@@ -627,6 +631,15 @@ cmd_help(void)
         } while (args[optind]);
 }
 
+void
+dump_register(void)
+{
+	if (pc->flags2 & QEMU_MEM_DUMP)
+		dump_register_for_qemu_mem_dump();
+	else
+		option_not_supported('q');
+}
+
 /*
  *  Format and display the help menu.
  */
diff --git a/netdump.c b/netdump.c
index 55073dd..bdc2757 100644
--- a/netdump.c
+++ b/netdump.c
@@ -1042,10 +1042,11 @@ netdump_memory_dump(FILE *fp)
 				nd->xen_kdump_data->p2m_mfn_frame_list[i]);
 		if (i) netdump_print("\n");
 	}
-	netdump_print("       num_prstatus_notes: %d\n", nd->num_prstatus_notes);	
-	netdump_print("               vmcoreinfo: %lx\n", (ulong)nd->vmcoreinfo);
-	netdump_print("          size_vmcoreinfo: %d\n", nd->size_vmcoreinfo);
-	netdump_print("       nt_prstatus_percpu: ");
+	netdump_print("     num_prstatus_notes: %d\n", nd->num_prstatus_notes);
+	netdump_print("         num_qemu_notes: %d\n", nd->num_qemu_notes);
+	netdump_print("             vmcoreinfo: %lx\n", (ulong)nd->vmcoreinfo);
+	netdump_print("        size_vmcoreinfo: %d\n", nd->size_vmcoreinfo);
+	netdump_print("     nt_prstatus_percpu: ");
         wrap = sizeof(void *) == SIZEOF_32BIT ? 8 : 4;
         flen = sizeof(void *) == SIZEOF_32BIT ? 8 : 16;
 	if (nd->num_prstatus_notes == 1)
@@ -1058,7 +1059,19 @@ netdump_memory_dump(FILE *fp)
 				nd->nt_prstatus_percpu[i]);
         	}
 	}
-	netdump_print("\n\n");
+	netdump_print("\n");
+	netdump_print("         nt_qemu_percpu: ");
+	if (nd->num_qemu_notes == 1)
+		netdump_print("%.*lx\n", flen, nd->nt_qemu_percpu[0]);
+	else {
+	       	for (i = 0; i < nd->num_qemu_notes; i++) {
+                	if ((i % wrap) == 0)
+                        	netdump_print("\n        ");
+                	netdump_print("%.*lx ", flen, 
+				nd->nt_qemu_percpu[i]);
+        	}
+	}
+	netdump_print("\n");
 
         switch (DUMPFILE_FORMAT(nd->flags))
 	{
@@ -1861,6 +1874,16 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
 	if (xen_core)
 		uptr = (ulong *)roundup((ulong)uptr, 4);
 
+	if (store && qemuinfo) {
+		for(i=0; i<NR_CPUS; i++) {
+			if (!nd->nt_qemu_percpu[i]) {
+				nd->nt_qemu_percpu[i] = (void *)uptr;
+				nd->num_qemu_notes++;
+				break;
+			}
+		}
+	}
+
 	if (vmcoreinfo || eraseinfo) {
                 netdump_print("                         ");
                 ptr += note->n_namesz + 1;
@@ -2138,6 +2161,16 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 			uptr = (ulonglong *)roundup((ulong)uptr, 4);
 	}
 
+	if (store && qemuinfo) {
+		for(i=0; i<NR_CPUS; i++) {
+			if (!nd->nt_qemu_percpu[i]) {
+				nd->nt_qemu_percpu[i] = (void *)uptr;
+				nd->num_qemu_notes++;
+				break;
+			}
+		}
+	}
+
 	if (BITS32() && (xen_core || (note->n_type == NT_PRSTATUS))) {
 		iptr = (int *)uptr;
 		for (i = lf = 0; i < note->n_descsz/sizeof(ulong); i++) {
@@ -3483,3 +3516,92 @@ kdump_get_osrelease(void)
 	} else 
 		pc->flags2 &= ~GET_OSRELEASE;
 }
+
+void
+dump_register_for_qemu_mem_dump(void)
+{
+	int i;
+	QEMUCPUState *ptr;
+	FILE *fpsave;
+
+	fpsave = nd->ofp;
+	nd->ofp = fp;
+
+	for (i=0; i<nd->num_qemu_notes; i++) {
+		ptr = (QEMUCPUState *)nd->nt_qemu_percpu[i];
+
+		if (i)
+			netdump_print("\n");
+		netdump_print("CPU %d:\n", i);
+
+		netdump_print("  version:%08lx      size:%08lx\n",
+			ptr->version, ptr->size);
+		netdump_print("  rax:%016llx  rbx:%016llx  rcx:%016llx\n",
+			ptr->rax, ptr->rbx, ptr->rcx);
+		netdump_print("  rdx:%016llx  rsi:%016llx  rdi:%016llx\n",
+			ptr->rdx, ptr->rsi, ptr->rdi);
+		netdump_print("  rsp:%016llx  rbp:%016llx  ",
+			ptr->rsp, ptr->rbp);
+	
+		if (DUMPFILE_FORMAT(nd->flags) == KDUMP_ELF64) {
+			netdump_print("r8:%016llx\n",
+				ptr->r8);
+			netdump_print("  r9:%016llx   r10:%016llx  r11:%016llx\n",
+				ptr->r9, ptr->r10, ptr->r11);
+			netdump_print("  r12:%016llx  r13:%016llx  r14:%016llx\n",
+				ptr->r12, ptr->r13, ptr->r14);
+			netdump_print("  r15:%016llx",
+				ptr->r15);
+		} else
+                        netdump_print("\n");
+
+		netdump_print("  rip:%016llx  rflags:%016llx\n",
+			ptr->rip, ptr->rflags);
+		netdump_print("  cs:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->cs.selector, ptr->cs.limit, ptr->cs.flags,
+			ptr->cs.pad, ptr->cs.base);
+		netdump_print("  ds:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->ds.selector, ptr->ds.limit, ptr->ds.flags,
+			ptr->ds.pad, ptr->ds.base);
+		netdump_print("  es:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->es.selector, ptr->es.limit, ptr->es.flags,
+			ptr->es.pad, ptr->es.base);
+		netdump_print("  fs:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->fs.selector, ptr->fs.limit, ptr->fs.flags,
+			ptr->fs.pad, ptr->fs.base);
+		netdump_print("  gs:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->gs.selector, ptr->gs.limit, ptr->gs.flags,
+			ptr->gs.pad, ptr->gs.base);
+		netdump_print("  ss:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->ss.selector, ptr->ss.limit, ptr->ss.flags,
+			ptr->ss.pad, ptr->ss.base);
+		netdump_print("  ldt:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->ldt.selector, ptr->ldt.limit, ptr->ldt.flags,
+			ptr->ldt.pad, ptr->ldt.base);
+		netdump_print("  tr:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->tr.selector, ptr->tr.limit, ptr->tr.flags,
+			ptr->tr.pad, ptr->tr.base);
+		netdump_print("  gdt:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->gdt.selector, ptr->gdt.limit, ptr->gdt.flags,
+			ptr->gdt.pad, ptr->gdt.base);
+		netdump_print("  idt:\n    selector:%08lx  limit:%08lx  flags:%08lx\n\
+    pad:%08lx  base:%016llx\n",
+			ptr->idt.selector, ptr->idt.limit, ptr->idt.flags,
+			ptr->idt.pad, ptr->idt.base);
+		netdump_print("  cr[0]:%016llx  cr[1]:%016llx  cr[2]:%016llx\n",
+			ptr->cr[0], ptr->cr[1], ptr->cr[2]);
+		netdump_print("  cr[3]:%016llx  cr[4]:%016llx\n",
+			ptr->cr[3], ptr->cr[4]);
+	}
+
+	nd->ofp = fpsave;
+}
diff --git a/netdump.h b/netdump.h
index 2e296ad..0c49871 100644
--- a/netdump.h
+++ b/netdump.h
@@ -67,7 +67,9 @@ struct vmcore_data {
 	uint page_size;
 	ulong switch_stack;
 	uint num_prstatus_notes;
+	uint num_qemu_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 +174,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;
-- 
1.7.1

