mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 04:06:46 +00:00 
			
		
		
		
	target-ppc: dump-guest-memory support
This patch add support for dumping guest memory using dump-guest-memory monitor command. Before patch: (qemu) dump-guest-memory testcrash this feature or command is not currently supported (qemu) After patch: (qemu) dump-guest-memory testcrash (qemu) crash was able to read the file crash> bt PID: 0 TASK: c000000000c0d0d0 CPU: 0 COMMAND: "swapper/0" R0: 0000000028000084 R1: c000000000cafa50 R2: c000000000cb05b0 R3: 0000000000000000 R4: c000000000bc4cb0 R5: 0000000000000000 R6: 001efe93b8000000 R7: 0000000000000000 R8: 0000000000000000 R9: b000000000001032 R10: 0000000000000001 R11: 0001eb2117e00d55 .... ... NOTE: Currently crash tools doesn't look at ELF notes in the dump on ppc64. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
		
							parent
							
								
									bb6b684363
								
							
						
					
					
						commit
						e62fbc54d4
					
				| @ -1359,6 +1359,9 @@ typedef struct elf64_shdr { | ||||
| #define NT_S390_TODPREG 0x303           /* s390 TOD programmable register */ | ||||
| #define NT_S390_TODCMP  0x302           /* s390 TOD clock comparator register */ | ||||
| #define NT_S390_TIMER   0x301           /* s390 timer register */ | ||||
| #define NT_PPC_VMX       0x100          /* PowerPC Altivec/VMX registers */ | ||||
| #define NT_PPC_SPE       0x101          /* PowerPC SPE/EVR registers */ | ||||
| #define NT_PPC_VSX       0x102          /* PowerPC VSX registers */ | ||||
| 
 | ||||
| 
 | ||||
| /* Note header in a PT_NOTE section */ | ||||
|  | ||||
| @ -2,7 +2,7 @@ obj-y += cpu-models.o | ||||
| obj-y += translate.o | ||||
| ifeq ($(CONFIG_SOFTMMU),y) | ||||
| obj-y += machine.o mmu_helper.o mmu-hash32.o | ||||
| obj-$(TARGET_PPC64) += mmu-hash64.o | ||||
| obj-$(TARGET_PPC64) += mmu-hash64.o arch_dump.o | ||||
| endif | ||||
| obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o | ||||
| obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o | ||||
|  | ||||
							
								
								
									
										253
									
								
								target-ppc/arch_dump.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								target-ppc/arch_dump.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,253 @@ | ||||
| /*
 | ||||
|  * writing ELF notes for ppc64 arch | ||||
|  * | ||||
|  * | ||||
|  * Copyright IBM, Corp. 2013 | ||||
|  * | ||||
|  * Authors: | ||||
|  * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||||
|  * | ||||
|  * This work is licensed under the terms of the GNU GPL, version 2.  See | ||||
|  * the COPYING file in the top-level directory. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "cpu.h" | ||||
| #include "elf.h" | ||||
| #include "exec/cpu-all.h" | ||||
| #include "sysemu/dump.h" | ||||
| #include "sysemu/kvm.h" | ||||
| 
 | ||||
| struct PPC64UserRegStruct { | ||||
|     uint64_t gpr[32]; | ||||
|     uint64_t nip; | ||||
|     uint64_t msr; | ||||
|     uint64_t orig_gpr3; | ||||
|     uint64_t ctr; | ||||
|     uint64_t link; | ||||
|     uint64_t xer; | ||||
|     uint64_t ccr; | ||||
|     uint64_t softe; | ||||
|     uint64_t trap; | ||||
|     uint64_t dar; | ||||
|     uint64_t dsisr; | ||||
|     uint64_t result; | ||||
| } QEMU_PACKED; | ||||
| 
 | ||||
| struct PPC64ElfPrstatus { | ||||
|     char pad1[112]; | ||||
|     struct PPC64UserRegStruct pr_reg; | ||||
|     uint64_t pad2[4]; | ||||
| } QEMU_PACKED; | ||||
| 
 | ||||
| 
 | ||||
| struct PPC64ElfFpregset { | ||||
|     uint64_t fpr[32]; | ||||
|     uint64_t fpscr; | ||||
| }  QEMU_PACKED; | ||||
| 
 | ||||
| 
 | ||||
| struct PPC64ElfVmxregset { | ||||
|     ppc_avr_t avr[32]; | ||||
|     ppc_avr_t vscr; | ||||
|     union { | ||||
|         ppc_avr_t unused; | ||||
|         uint32_t value; | ||||
|     } vrsave; | ||||
| }  QEMU_PACKED; | ||||
| 
 | ||||
| struct PPC64ElfVsxregset { | ||||
|     uint64_t vsr[32]; | ||||
| }  QEMU_PACKED; | ||||
| 
 | ||||
| struct PPC64ElfSperegset { | ||||
|     uint32_t evr[32]; | ||||
|     uint64_t spe_acc; | ||||
|     uint32_t spe_fscr; | ||||
| }  QEMU_PACKED; | ||||
| 
 | ||||
| typedef struct noteStruct { | ||||
|     Elf64_Nhdr hdr; | ||||
|     char name[5]; | ||||
|     char pad3[3]; | ||||
|     union { | ||||
|         struct PPC64ElfPrstatus  prstatus; | ||||
|         struct PPC64ElfFpregset  fpregset; | ||||
|         struct PPC64ElfVmxregset vmxregset; | ||||
|         struct PPC64ElfVsxregset vsxregset; | ||||
|         struct PPC64ElfSperegset speregset; | ||||
|     } contents; | ||||
| } QEMU_PACKED Note; | ||||
| 
 | ||||
| 
 | ||||
| static void ppc64_write_elf64_prstatus(Note *note, PowerPCCPU *cpu) | ||||
| { | ||||
|     int i; | ||||
|     uint64_t cr; | ||||
|     struct PPC64ElfPrstatus *prstatus; | ||||
|     struct PPC64UserRegStruct *reg; | ||||
| 
 | ||||
|     note->hdr.n_type = cpu_to_be32(NT_PRSTATUS); | ||||
| 
 | ||||
|     prstatus = ¬e->contents.prstatus; | ||||
|     memset(prstatus, 0, sizeof(*prstatus)); | ||||
|     reg = &prstatus->pr_reg; | ||||
| 
 | ||||
|     for (i = 0; i < 32; i++) { | ||||
|         reg->gpr[i] = cpu_to_be64(cpu->env.gpr[i]); | ||||
|     } | ||||
|     reg->nip = cpu_to_be64(cpu->env.nip); | ||||
|     reg->msr = cpu_to_be64(cpu->env.msr); | ||||
|     reg->ctr = cpu_to_be64(cpu->env.ctr); | ||||
|     reg->link = cpu_to_be64(cpu->env.lr); | ||||
|     reg->xer = cpu_to_be64(cpu_read_xer(&cpu->env)); | ||||
| 
 | ||||
|     cr = 0; | ||||
|     for (i = 0; i < 8; i++) { | ||||
|         cr |= (cpu->env.crf[i] & 15) << (4 * (7 - i)); | ||||
|     } | ||||
|     reg->ccr = cpu_to_be64(cr); | ||||
| } | ||||
| 
 | ||||
| static void ppc64_write_elf64_fpregset(Note *note, PowerPCCPU *cpu) | ||||
| { | ||||
|     int i; | ||||
|     struct PPC64ElfFpregset  *fpregset; | ||||
| 
 | ||||
|     note->hdr.n_type = cpu_to_be32(NT_PRFPREG); | ||||
| 
 | ||||
|     fpregset = ¬e->contents.fpregset; | ||||
|     memset(fpregset, 0, sizeof(*fpregset)); | ||||
| 
 | ||||
|     for (i = 0; i < 32; i++) { | ||||
|         fpregset->fpr[i] = cpu_to_be64(cpu->env.fpr[i]); | ||||
|     } | ||||
|     fpregset->fpscr = cpu_to_be64(cpu->env.fpscr); | ||||
| } | ||||
| 
 | ||||
| static void ppc64_write_elf64_vmxregset(Note *note, PowerPCCPU *cpu) | ||||
| { | ||||
|     int i; | ||||
|     struct PPC64ElfVmxregset *vmxregset; | ||||
| 
 | ||||
|     note->hdr.n_type = cpu_to_be32(NT_PPC_VMX); | ||||
|     vmxregset = ¬e->contents.vmxregset; | ||||
|     memset(vmxregset, 0, sizeof(*vmxregset)); | ||||
| 
 | ||||
|     for (i = 0; i < 32; i++) { | ||||
|         vmxregset->avr[i].u64[0] = cpu_to_be64(cpu->env.avr[i].u64[0]); | ||||
|         vmxregset->avr[i].u64[1] = cpu_to_be64(cpu->env.avr[i].u64[1]); | ||||
|     } | ||||
|     vmxregset->vscr.u32[3] = cpu_to_be32(cpu->env.vscr); | ||||
| } | ||||
| static void ppc64_write_elf64_vsxregset(Note *note, PowerPCCPU *cpu) | ||||
| { | ||||
|     int i; | ||||
|     struct PPC64ElfVsxregset *vsxregset; | ||||
| 
 | ||||
|     note->hdr.n_type = cpu_to_be32(NT_PPC_VSX); | ||||
|     vsxregset = ¬e->contents.vsxregset; | ||||
|     memset(vsxregset, 0, sizeof(*vsxregset)); | ||||
| 
 | ||||
|     for (i = 0; i < 32; i++) { | ||||
|         vsxregset->vsr[i] = cpu_to_be64(cpu->env.vsr[i]); | ||||
|     } | ||||
| } | ||||
| static void ppc64_write_elf64_speregset(Note *note, PowerPCCPU *cpu) | ||||
| { | ||||
|     struct PPC64ElfSperegset *speregset; | ||||
|     note->hdr.n_type = cpu_to_be32(NT_PPC_SPE); | ||||
|     speregset = ¬e->contents.speregset; | ||||
|     memset(speregset, 0, sizeof(*speregset)); | ||||
| 
 | ||||
|     speregset->spe_acc = cpu_to_be64(cpu->env.spe_acc); | ||||
|     speregset->spe_fscr = cpu_to_be32(cpu->env.spe_fscr); | ||||
| } | ||||
| 
 | ||||
| struct NoteFuncDescStruct { | ||||
|     int contents_size; | ||||
|     void (*note_contents_func)(Note *note, PowerPCCPU *cpu); | ||||
| } note_func[] = { | ||||
|     {sizeof(((Note *)0)->contents.prstatus),  ppc64_write_elf64_prstatus}, | ||||
|     {sizeof(((Note *)0)->contents.fpregset),  ppc64_write_elf64_fpregset}, | ||||
|     {sizeof(((Note *)0)->contents.vmxregset), ppc64_write_elf64_vmxregset}, | ||||
|     {sizeof(((Note *)0)->contents.vsxregset), ppc64_write_elf64_vsxregset}, | ||||
|     {sizeof(((Note *)0)->contents.speregset), ppc64_write_elf64_speregset}, | ||||
|     { 0, NULL} | ||||
| }; | ||||
| 
 | ||||
| typedef struct NoteFuncDescStruct NoteFuncDesc; | ||||
| 
 | ||||
| int cpu_get_dump_info(ArchDumpInfo *info, | ||||
|                       const struct GuestPhysBlockList *guest_phys_blocks) | ||||
| { | ||||
|     /*
 | ||||
|      * Currently only handling PPC64 big endian. | ||||
|      */ | ||||
|     info->d_machine = EM_PPC64; | ||||
|     info->d_endian = ELFDATA2MSB; | ||||
|     info->d_class = ELFCLASS64; | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) | ||||
| { | ||||
|     int name_size = 8; /* "CORE" or "QEMU" rounded */ | ||||
|     size_t elf_note_size = 0; | ||||
|     int note_head_size; | ||||
|     NoteFuncDesc *nf; | ||||
| 
 | ||||
|     if (class != ELFCLASS64) { | ||||
|         return -1; | ||||
|     } | ||||
|     assert(machine == EM_PPC64); | ||||
| 
 | ||||
|     note_head_size = sizeof(Elf64_Nhdr); | ||||
| 
 | ||||
|     for (nf = note_func; nf->note_contents_func; nf++) { | ||||
|         elf_note_size = elf_note_size + note_head_size + name_size + | ||||
|                         nf->contents_size; | ||||
|     } | ||||
| 
 | ||||
|     return (elf_note_size) * nr_cpus; | ||||
| } | ||||
| 
 | ||||
| static int ppc64_write_all_elf64_notes(const char *note_name, | ||||
|                                        WriteCoreDumpFunction f, | ||||
|                                        PowerPCCPU *cpu, int id, | ||||
|                                        void *opaque) | ||||
| { | ||||
|     Note note; | ||||
|     int ret = -1; | ||||
|     int note_size; | ||||
|     NoteFuncDesc *nf; | ||||
| 
 | ||||
|     for (nf = note_func; nf->note_contents_func; nf++) { | ||||
|         note.hdr.n_namesz = cpu_to_be32(sizeof(note.name)); | ||||
|         note.hdr.n_descsz = cpu_to_be32(nf->contents_size); | ||||
|         strncpy(note.name, note_name, sizeof(note.name)); | ||||
| 
 | ||||
|         (*nf->note_contents_func)(¬e, cpu); | ||||
| 
 | ||||
|         note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size; | ||||
|         ret = f(¬e, note_size, opaque); | ||||
|         if (ret < 0) { | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, | ||||
|                                int cpuid, void *opaque) | ||||
| { | ||||
|     PowerPCCPU *cpu = POWERPC_CPU(cs); | ||||
|     return ppc64_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque); | ||||
| } | ||||
| 
 | ||||
| int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, | ||||
|                                    CPUState *cpu, void *opaque) | ||||
| { | ||||
|     return 0; | ||||
| } | ||||
| @ -108,7 +108,10 @@ void ppc_cpu_dump_statistics(CPUState *cpu, FILE *f, | ||||
| hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); | ||||
| int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); | ||||
| int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); | ||||
| 
 | ||||
| int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, | ||||
|                                    CPUState *cpu, void *opaque); | ||||
| int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, | ||||
|                                int cpuid, void *opaque); | ||||
| #ifndef CONFIG_USER_ONLY | ||||
| extern const struct VMStateDescription vmstate_ppc_cpu; | ||||
| #endif | ||||
|  | ||||
| @ -8572,6 +8572,10 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) | ||||
| #ifndef CONFIG_USER_ONLY | ||||
|     cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug; | ||||
|     cc->vmsd = &vmstate_ppc_cpu; | ||||
| #if defined(TARGET_PPC64) | ||||
|     cc->write_elf64_note = ppc64_cpu_write_elf64_note; | ||||
|     cc->write_elf64_qemunote = ppc64_cpu_write_elf64_qemunote; | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
|     cc->gdb_num_core_regs = 71; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Aneesh Kumar K.V
						Aneesh Kumar K.V