[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH] target-ppc: dump-guest-memory support
From: |
Aneesh Kumar K.V |
Subject: |
Re: [Qemu-ppc] [PATCH] target-ppc: dump-guest-memory support |
Date: |
Wed, 25 Sep 2013 21:10:34 +0530 |
User-agent: |
Notmuch/0.16+84~gcbbf53e (http://notmuchmail.org) Emacs/24.2.1 (x86_64-pc-linux-gnu) |
Hi Alex,
Any update on this ?
-aneesh
"Aneesh Kumar K.V" <address@hidden> writes:
> From: "Aneesh Kumar K.V" <address@hidden>
>
> 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 <address@hidden>
> ---
> include/elf.h | 3 +
> target-ppc/Makefile.objs | 2 +-
> target-ppc/arch_dump.c | 254
> ++++++++++++++++++++++++++++++++++++++++++++
> target-ppc/cpu-qom.h | 5 +-
> target-ppc/translate_init.c | 4 +
> 5 files changed, 266 insertions(+), 2 deletions(-)
> create mode 100644 target-ppc/arch_dump.c
>
> diff --git a/include/elf.h b/include/elf.h
> index 58bfbf8..b818091 100644
> --- a/include/elf.h
> +++ b/include/elf.h
> @@ -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 */
> diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
> index f72e399..ec06e50 100644
> --- a/target-ppc/Makefile.objs
> +++ b/target-ppc/Makefile.objs
> @@ -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-$(CONFIG_NO_KVM) += kvm-stub.o
> diff --git a/target-ppc/arch_dump.c b/target-ppc/arch_dump.c
> new file mode 100644
> index 0000000..751cf92
> --- /dev/null
> +++ b/target-ppc/arch_dump.c
> @@ -0,0 +1,254 @@
> +/*
> + * writing ELF notes for ppc64 arch
> + *
> + *
> + * Copyright IBM, Corp. 2013
> + *
> + * Authors:
> + * Aneesh Kumar K.V <address@hidden>
> + *
> + * 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;
> +}
> +
> diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
> index f3c710a..827e5dd 100644
> --- a/target-ppc/cpu-qom.h
> +++ b/target-ppc/cpu-qom.h
> @@ -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
> diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
> index 13b290c..180ea1a 100644
> --- a/target-ppc/translate_init.c
> +++ b/target-ppc/translate_init.c
> @@ -8569,6 +8569,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;
> --
> 1.8.1.2