qemu-ppc
[Top][All Lists]
Advanced

[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 = &note->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 = &note->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 = &note->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 = &note->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 = &note->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)(&note, cpu);
> +
> +        note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
> +        ret = f(&note, 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]