qemu/target-s390x/arch_dump.c
<<
>>
Prefs
   1/*
   2 * writing ELF notes for s390x arch
   3 *
   4 *
   5 * Copyright IBM Corp. 2012, 2013
   6 *
   7 *     Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10 * See the COPYING file in the top-level directory.
  11 *
  12 */
  13
  14#include "qemu/osdep.h"
  15#include "cpu.h"
  16#include "elf.h"
  17#include "exec/cpu-all.h"
  18#include "sysemu/dump.h"
  19#include "sysemu/kvm.h"
  20
  21
  22struct S390xUserRegsStruct {
  23    uint64_t psw[2];
  24    uint64_t gprs[16];
  25    uint32_t acrs[16];
  26} QEMU_PACKED;
  27
  28typedef struct S390xUserRegsStruct S390xUserRegs;
  29
  30struct S390xElfPrstatusStruct {
  31    uint8_t pad1[32];
  32    uint32_t pid;
  33    uint8_t pad2[76];
  34    S390xUserRegs regs;
  35    uint8_t pad3[16];
  36} QEMU_PACKED;
  37
  38typedef struct S390xElfPrstatusStruct S390xElfPrstatus;
  39
  40struct S390xElfFpregsetStruct {
  41    uint32_t fpc;
  42    uint32_t pad;
  43    uint64_t fprs[16];
  44} QEMU_PACKED;
  45
  46typedef struct S390xElfFpregsetStruct S390xElfFpregset;
  47
  48struct S390xElfVregsLoStruct {
  49    uint64_t vregs[16];
  50} QEMU_PACKED;
  51
  52typedef struct S390xElfVregsLoStruct S390xElfVregsLo;
  53
  54struct S390xElfVregsHiStruct {
  55    uint64_t vregs[16][2];
  56} QEMU_PACKED;
  57
  58typedef struct S390xElfVregsHiStruct S390xElfVregsHi;
  59
  60typedef struct noteStruct {
  61    Elf64_Nhdr hdr;
  62    char name[5];
  63    char pad3[3];
  64    union {
  65        S390xElfPrstatus prstatus;
  66        S390xElfFpregset fpregset;
  67        S390xElfVregsLo vregslo;
  68        S390xElfVregsHi vregshi;
  69        uint32_t prefix;
  70        uint64_t timer;
  71        uint64_t todcmp;
  72        uint32_t todpreg;
  73        uint64_t ctrs[16];
  74    } contents;
  75} QEMU_PACKED Note;
  76
  77static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu)
  78{
  79    int i;
  80    S390xUserRegs *regs;
  81
  82    note->hdr.n_type = cpu_to_be32(NT_PRSTATUS);
  83
  84    regs = &(note->contents.prstatus.regs);
  85    regs->psw[0] = cpu_to_be64(cpu->env.psw.mask);
  86    regs->psw[1] = cpu_to_be64(cpu->env.psw.addr);
  87    for (i = 0; i <= 15; i++) {
  88        regs->acrs[i] = cpu_to_be32(cpu->env.aregs[i]);
  89        regs->gprs[i] = cpu_to_be64(cpu->env.regs[i]);
  90    }
  91}
  92
  93static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu)
  94{
  95    int i;
  96    CPUS390XState *cs = &cpu->env;
  97
  98    note->hdr.n_type = cpu_to_be32(NT_FPREGSET);
  99    note->contents.fpregset.fpc = cpu_to_be32(cpu->env.fpc);
 100    for (i = 0; i <= 15; i++) {
 101        note->contents.fpregset.fprs[i] = cpu_to_be64(get_freg(cs, i)->ll);
 102    }
 103}
 104
 105static void s390x_write_elf64_vregslo(Note *note, S390CPU *cpu)
 106{
 107    int i;
 108
 109    note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_LOW);
 110    for (i = 0; i <= 15; i++) {
 111        note->contents.vregslo.vregs[i] = cpu_to_be64(cpu->env.vregs[i][1].ll);
 112    }
 113}
 114
 115static void s390x_write_elf64_vregshi(Note *note, S390CPU *cpu)
 116{
 117    int i;
 118    S390xElfVregsHi *temp_vregshi;
 119
 120    temp_vregshi = &note->contents.vregshi;
 121
 122    note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_HIGH);
 123    for (i = 0; i <= 15; i++) {
 124        temp_vregshi->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i + 16][0].ll);
 125        temp_vregshi->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i + 16][1].ll);
 126    }
 127}
 128
 129static void s390x_write_elf64_timer(Note *note, S390CPU *cpu)
 130{
 131    note->hdr.n_type = cpu_to_be32(NT_S390_TIMER);
 132    note->contents.timer = cpu_to_be64((uint64_t)(cpu->env.cputm));
 133}
 134
 135static void s390x_write_elf64_todcmp(Note *note, S390CPU *cpu)
 136{
 137    note->hdr.n_type = cpu_to_be32(NT_S390_TODCMP);
 138    note->contents.todcmp = cpu_to_be64((uint64_t)(cpu->env.ckc));
 139}
 140
 141static void s390x_write_elf64_todpreg(Note *note, S390CPU *cpu)
 142{
 143    note->hdr.n_type = cpu_to_be32(NT_S390_TODPREG);
 144    note->contents.todpreg = cpu_to_be32((uint32_t)(cpu->env.todpr));
 145}
 146
 147static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu)
 148{
 149    int i;
 150
 151    note->hdr.n_type = cpu_to_be32(NT_S390_CTRS);
 152
 153    for (i = 0; i <= 15; i++) {
 154        note->contents.ctrs[i] = cpu_to_be64(cpu->env.cregs[i]);
 155    }
 156}
 157
 158static void s390x_write_elf64_prefix(Note *note, S390CPU *cpu)
 159{
 160    note->hdr.n_type = cpu_to_be32(NT_S390_PREFIX);
 161    note->contents.prefix = cpu_to_be32((uint32_t)(cpu->env.psa));
 162}
 163
 164
 165static const struct NoteFuncDescStruct {
 166    int contents_size;
 167    void (*note_contents_func)(Note *note, S390CPU *cpu);
 168} note_func[] = {
 169    {sizeof(((Note *)0)->contents.prstatus), s390x_write_elf64_prstatus},
 170    {sizeof(((Note *)0)->contents.prefix),   s390x_write_elf64_prefix},
 171    {sizeof(((Note *)0)->contents.fpregset), s390x_write_elf64_fpregset},
 172    {sizeof(((Note *)0)->contents.ctrs),     s390x_write_elf64_ctrs},
 173    {sizeof(((Note *)0)->contents.timer),    s390x_write_elf64_timer},
 174    {sizeof(((Note *)0)->contents.todcmp),   s390x_write_elf64_todcmp},
 175    {sizeof(((Note *)0)->contents.todpreg),  s390x_write_elf64_todpreg},
 176    {sizeof(((Note *)0)->contents.vregslo),  s390x_write_elf64_vregslo},
 177    {sizeof(((Note *)0)->contents.vregshi),  s390x_write_elf64_vregshi},
 178    { 0, NULL}
 179};
 180
 181typedef struct NoteFuncDescStruct NoteFuncDesc;
 182
 183
 184static int s390x_write_all_elf64_notes(const char *note_name,
 185                                       WriteCoreDumpFunction f,
 186                                       S390CPU *cpu, int id,
 187                                       void *opaque)
 188{
 189    Note note;
 190    const NoteFuncDesc *nf;
 191    int note_size;
 192    int ret = -1;
 193
 194    for (nf = note_func; nf->note_contents_func; nf++) {
 195        memset(&note, 0, sizeof(note));
 196        note.hdr.n_namesz = cpu_to_be32(sizeof(note.name));
 197        note.hdr.n_descsz = cpu_to_be32(nf->contents_size);
 198        strncpy(note.name, note_name, sizeof(note.name));
 199        (*nf->note_contents_func)(&note, cpu);
 200
 201        note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
 202        ret = f(&note, note_size, opaque);
 203
 204        if (ret < 0) {
 205            return -1;
 206        }
 207
 208    }
 209
 210    return 0;
 211}
 212
 213
 214int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
 215                              int cpuid, void *opaque)
 216{
 217    S390CPU *cpu = S390_CPU(cs);
 218    return s390x_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque);
 219}
 220
 221int cpu_get_dump_info(ArchDumpInfo *info,
 222                      const struct GuestPhysBlockList *guest_phys_blocks)
 223{
 224    info->d_machine = EM_S390;
 225    info->d_endian = ELFDATA2MSB;
 226    info->d_class = ELFCLASS64;
 227
 228    return 0;
 229}
 230
 231ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
 232{
 233    int name_size = 8; /* "CORE" or "QEMU" rounded */
 234    size_t elf_note_size = 0;
 235    int note_head_size;
 236    const NoteFuncDesc *nf;
 237
 238    assert(class == ELFCLASS64);
 239    assert(machine == EM_S390);
 240
 241    note_head_size = sizeof(Elf64_Nhdr);
 242
 243    for (nf = note_func; nf->note_contents_func; nf++) {
 244        elf_note_size = elf_note_size + note_head_size + name_size +
 245                        nf->contents_size;
 246    }
 247
 248    return (elf_note_size) * nr_cpus;
 249}
 250