qemu/target-ppc/arch_dump.c
<<
>>
Prefs
   1/*
   2 * writing ELF notes for ppc64 arch
   3 *
   4 *
   5 * Copyright IBM, Corp. 2013
   6 *
   7 * Authors:
   8 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
   9 *
  10 * This work is licensed under the terms of the GNU GPL, version 2.  See
  11 * the COPYING file in the top-level directory.
  12 *
  13 */
  14
  15#include "qemu/osdep.h"
  16#include "cpu.h"
  17#include "elf.h"
  18#include "exec/cpu-all.h"
  19#include "sysemu/dump.h"
  20#include "sysemu/kvm.h"
  21
  22struct PPC64UserRegStruct {
  23    uint64_t gpr[32];
  24    uint64_t nip;
  25    uint64_t msr;
  26    uint64_t orig_gpr3;
  27    uint64_t ctr;
  28    uint64_t link;
  29    uint64_t xer;
  30    uint64_t ccr;
  31    uint64_t softe;
  32    uint64_t trap;
  33    uint64_t dar;
  34    uint64_t dsisr;
  35    uint64_t result;
  36} QEMU_PACKED;
  37
  38struct PPC64ElfPrstatus {
  39    char pad1[112];
  40    struct PPC64UserRegStruct pr_reg;
  41    uint64_t pad2[4];
  42} QEMU_PACKED;
  43
  44
  45struct PPC64ElfFpregset {
  46    uint64_t fpr[32];
  47    uint64_t fpscr;
  48}  QEMU_PACKED;
  49
  50
  51struct PPC64ElfVmxregset {
  52    ppc_avr_t avr[32];
  53    ppc_avr_t vscr;
  54    union {
  55        ppc_avr_t unused;
  56        uint32_t value;
  57    } vrsave;
  58}  QEMU_PACKED;
  59
  60struct PPC64ElfVsxregset {
  61    uint64_t vsr[32];
  62}  QEMU_PACKED;
  63
  64struct PPC64ElfSperegset {
  65    uint32_t evr[32];
  66    uint64_t spe_acc;
  67    uint32_t spe_fscr;
  68}  QEMU_PACKED;
  69
  70typedef struct noteStruct {
  71    Elf64_Nhdr hdr;
  72    char name[5];
  73    char pad3[3];
  74    union {
  75        struct PPC64ElfPrstatus  prstatus;
  76        struct PPC64ElfFpregset  fpregset;
  77        struct PPC64ElfVmxregset vmxregset;
  78        struct PPC64ElfVsxregset vsxregset;
  79        struct PPC64ElfSperegset speregset;
  80    } contents;
  81} QEMU_PACKED Note;
  82
  83typedef struct NoteFuncArg {
  84    Note note;
  85    DumpState *state;
  86} NoteFuncArg;
  87
  88static void ppc64_write_elf64_prstatus(NoteFuncArg *arg, PowerPCCPU *cpu)
  89{
  90    int i;
  91    uint64_t cr;
  92    struct PPC64ElfPrstatus *prstatus;
  93    struct PPC64UserRegStruct *reg;
  94    Note *note = &arg->note;
  95    DumpState *s = arg->state;
  96
  97    note->hdr.n_type = cpu_to_dump32(s, NT_PRSTATUS);
  98
  99    prstatus = &note->contents.prstatus;
 100    memset(prstatus, 0, sizeof(*prstatus));
 101    reg = &prstatus->pr_reg;
 102
 103    for (i = 0; i < 32; i++) {
 104        reg->gpr[i] = cpu_to_dump64(s, cpu->env.gpr[i]);
 105    }
 106    reg->nip = cpu_to_dump64(s, cpu->env.nip);
 107    reg->msr = cpu_to_dump64(s, cpu->env.msr);
 108    reg->ctr = cpu_to_dump64(s, cpu->env.ctr);
 109    reg->link = cpu_to_dump64(s, cpu->env.lr);
 110    reg->xer = cpu_to_dump64(s, cpu_read_xer(&cpu->env));
 111
 112    cr = 0;
 113    for (i = 0; i < 8; i++) {
 114        cr |= (cpu->env.crf[i] & 15) << (4 * (7 - i));
 115    }
 116    reg->ccr = cpu_to_dump64(s, cr);
 117}
 118
 119static void ppc64_write_elf64_fpregset(NoteFuncArg *arg, PowerPCCPU *cpu)
 120{
 121    int i;
 122    struct PPC64ElfFpregset  *fpregset;
 123    Note *note = &arg->note;
 124    DumpState *s = arg->state;
 125
 126    note->hdr.n_type = cpu_to_dump32(s, NT_PRFPREG);
 127
 128    fpregset = &note->contents.fpregset;
 129    memset(fpregset, 0, sizeof(*fpregset));
 130
 131    for (i = 0; i < 32; i++) {
 132        fpregset->fpr[i] = cpu_to_dump64(s, cpu->env.fpr[i]);
 133    }
 134    fpregset->fpscr = cpu_to_dump64(s, cpu->env.fpscr);
 135}
 136
 137static void ppc64_write_elf64_vmxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
 138{
 139    int i;
 140    struct PPC64ElfVmxregset *vmxregset;
 141    Note *note = &arg->note;
 142    DumpState *s = arg->state;
 143
 144    note->hdr.n_type = cpu_to_dump32(s, NT_PPC_VMX);
 145    vmxregset = &note->contents.vmxregset;
 146    memset(vmxregset, 0, sizeof(*vmxregset));
 147
 148    for (i = 0; i < 32; i++) {
 149        bool needs_byteswap;
 150
 151#ifdef HOST_WORDS_BIGENDIAN
 152        needs_byteswap = s->dump_info.d_endian == ELFDATA2LSB;
 153#else
 154        needs_byteswap = s->dump_info.d_endian == ELFDATA2MSB;
 155#endif
 156
 157        if (needs_byteswap) {
 158            vmxregset->avr[i].u64[0] = bswap64(cpu->env.avr[i].u64[1]);
 159            vmxregset->avr[i].u64[1] = bswap64(cpu->env.avr[i].u64[0]);
 160        } else {
 161            vmxregset->avr[i].u64[0] = cpu->env.avr[i].u64[0];
 162            vmxregset->avr[i].u64[1] = cpu->env.avr[i].u64[1];
 163        }
 164    }
 165    vmxregset->vscr.u32[3] = cpu_to_dump32(s, cpu->env.vscr);
 166}
 167static void ppc64_write_elf64_vsxregset(NoteFuncArg *arg, PowerPCCPU *cpu)
 168{
 169    int i;
 170    struct PPC64ElfVsxregset *vsxregset;
 171    Note *note = &arg->note;
 172    DumpState *s = arg->state;
 173
 174    note->hdr.n_type = cpu_to_dump32(s, NT_PPC_VSX);
 175    vsxregset = &note->contents.vsxregset;
 176    memset(vsxregset, 0, sizeof(*vsxregset));
 177
 178    for (i = 0; i < 32; i++) {
 179        vsxregset->vsr[i] = cpu_to_dump64(s, cpu->env.vsr[i]);
 180    }
 181}
 182static void ppc64_write_elf64_speregset(NoteFuncArg *arg, PowerPCCPU *cpu)
 183{
 184    struct PPC64ElfSperegset *speregset;
 185    Note *note = &arg->note;
 186    DumpState *s = arg->state;
 187
 188    note->hdr.n_type = cpu_to_dump32(s, NT_PPC_SPE);
 189    speregset = &note->contents.speregset;
 190    memset(speregset, 0, sizeof(*speregset));
 191
 192    speregset->spe_acc = cpu_to_dump64(s, cpu->env.spe_acc);
 193    speregset->spe_fscr = cpu_to_dump32(s, cpu->env.spe_fscr);
 194}
 195
 196static const struct NoteFuncDescStruct {
 197    int contents_size;
 198    void (*note_contents_func)(NoteFuncArg *arg, PowerPCCPU *cpu);
 199} note_func[] = {
 200    {sizeof(((Note *)0)->contents.prstatus),  ppc64_write_elf64_prstatus},
 201    {sizeof(((Note *)0)->contents.fpregset),  ppc64_write_elf64_fpregset},
 202    {sizeof(((Note *)0)->contents.vmxregset), ppc64_write_elf64_vmxregset},
 203    {sizeof(((Note *)0)->contents.vsxregset), ppc64_write_elf64_vsxregset},
 204    {sizeof(((Note *)0)->contents.speregset), ppc64_write_elf64_speregset},
 205    { 0, NULL}
 206};
 207
 208typedef struct NoteFuncDescStruct NoteFuncDesc;
 209
 210int cpu_get_dump_info(ArchDumpInfo *info,
 211                      const struct GuestPhysBlockList *guest_phys_blocks)
 212{
 213    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
 214    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
 215
 216    info->d_machine = EM_PPC64;
 217    info->d_class = ELFCLASS64;
 218    if ((*pcc->interrupts_big_endian)(cpu)) {
 219        info->d_endian = ELFDATA2MSB;
 220    } else {
 221        info->d_endian = ELFDATA2LSB;
 222    }
 223
 224    return 0;
 225}
 226
 227ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 228{
 229    int name_size = 8; /* "CORE" or "QEMU" rounded */
 230    size_t elf_note_size = 0;
 231    int note_head_size;
 232    const NoteFuncDesc *nf;
 233
 234    if (class != ELFCLASS64) {
 235        return -1;
 236    }
 237    assert(machine == EM_PPC64);
 238
 239    note_head_size = sizeof(Elf64_Nhdr);
 240
 241    for (nf = note_func; nf->note_contents_func; nf++) {
 242        elf_note_size = elf_note_size + note_head_size + name_size +
 243                        nf->contents_size;
 244    }
 245
 246    return (elf_note_size) * nr_cpus;
 247}
 248
 249static int ppc64_write_all_elf64_notes(const char *note_name,
 250                                       WriteCoreDumpFunction f,
 251                                       PowerPCCPU *cpu, int id,
 252                                       void *opaque)
 253{
 254    NoteFuncArg arg = { .state = opaque };
 255    int ret = -1;
 256    int note_size;
 257    const NoteFuncDesc *nf;
 258
 259    for (nf = note_func; nf->note_contents_func; nf++) {
 260        arg.note.hdr.n_namesz = cpu_to_dump32(opaque, sizeof(arg.note.name));
 261        arg.note.hdr.n_descsz = cpu_to_dump32(opaque, nf->contents_size);
 262        strncpy(arg.note.name, note_name, sizeof(arg.note.name));
 263
 264        (*nf->note_contents_func)(&arg, cpu);
 265
 266        note_size =
 267            sizeof(arg.note) - sizeof(arg.note.contents) + nf->contents_size;
 268        ret = f(&arg.note, note_size, opaque);
 269        if (ret < 0) {
 270            return -1;
 271        }
 272    }
 273    return 0;
 274}
 275
 276int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
 277                               int cpuid, void *opaque)
 278{
 279    PowerPCCPU *cpu = POWERPC_CPU(cs);
 280    return ppc64_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque);
 281}
 282