On 05/07/13 14:02, Jens Freimann wrote: > With this patch dump-guest-memory on s390 produces an ELF formatted, > crash-readable dump. > In order to implement this, the arch-specific part of dump-guest-memory > was added: > target-s390x/arch_dump.c contains the whole set of function for writing > Elf note sections of all types for s390x. > > Signed-off-by: Ekaterina Tumanova <tuman...@linux.vnet.ibm.com> > Signed-off-by: Jens Freimann <jf...@linux.vnet.ibm.com> Acked-by: Christian Borntraeger <borntrae...@de.ibm.com>
I can confirm that this patch creates proper dumps readable by crash with valid memory and valid register content. Would be good to see this upstream. Meanwhile this patch no longer cleanly applies due to commit 878096eeb278a8ac1ccd6667af73e026f29b4cf5 cpu: Turn cpu_dump_{state,statistics}() into CPUState hooks The fixup is trivial. Alex, please apply. > [fixed indentation, use CamelCase, rename note_t to Note, use S390CPU] > --- > include/elf.h | 6 ++ > target-s390x/Makefile.objs | 2 +- > target-s390x/arch_dump.c | 213 > +++++++++++++++++++++++++++++++++++++++++++++ > target-s390x/cpu-qom.h | 5 ++ > target-s390x/cpu.c | 4 + > 5 files changed, 229 insertions(+), 1 deletion(-) > create mode 100644 target-s390x/arch_dump.c > > diff --git a/include/elf.h b/include/elf.h > index cf0d3e2..58bfbf8 100644 > --- a/include/elf.h > +++ b/include/elf.h > @@ -1348,11 +1348,17 @@ typedef struct elf64_shdr { > > /* Notes used in ET_CORE */ > #define NT_PRSTATUS 1 > +#define NT_FPREGSET 2 > #define NT_PRFPREG 2 > #define NT_PRPSINFO 3 > #define NT_TASKSTRUCT 4 > #define NT_AUXV 6 > #define NT_PRXFPREG 0x46e62b7f /* copied from > gdb5.1/include/elf/common.h */ > +#define NT_S390_PREFIX 0x305 /* s390 prefix register */ > +#define NT_S390_CTRS 0x304 /* s390 control registers */ > +#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 */ > > > /* Note header in a PT_NOTE section */ > diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs > index 4e63417..c34f654 100644 > --- a/target-s390x/Makefile.objs > +++ b/target-s390x/Makefile.objs > @@ -1,4 +1,4 @@ > obj-y += translate.o helper.o cpu.o interrupt.o > obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o > -obj-$(CONFIG_SOFTMMU) += ioinst.o > +obj-$(CONFIG_SOFTMMU) += ioinst.o arch_dump.o > obj-$(CONFIG_KVM) += kvm.o > diff --git a/target-s390x/arch_dump.c b/target-s390x/arch_dump.c > new file mode 100644 > index 0000000..bc8db62 > --- /dev/null > +++ b/target-s390x/arch_dump.c > @@ -0,0 +1,213 @@ > +/* > + * writing ELF notes for s390x arch > + * > + * > + * Copyright IBM Corp. 2012, 2013 > + * > + * Ekaterina Tumanova <tuman...@linux.vnet.ibm.com> > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or later. > + * See the COPYING file in the top-level directory. > + * > + */ > + > +#include "cpu.h" > +#include "cpu-qom.h" > +#include "elf.h" > +#include "exec/cpu-all.h" > +#include "sysemu/dump.h" > +#include "sysemu/kvm.h" > + > + > +struct S390xUserRegsStruct { > + uint64_t psw[2]; > + uint64_t gprs[16]; > + uint32_t acrs[16]; > +} QEMU_PACKED; > + > +typedef struct S390xUserRegsStruct S390xUserRegs; > + > +struct S390xElfPrstatusStruct { > + uint8_t pad1[32]; > + uint32_t pid; > + uint8_t pad2[76]; > + S390xUserRegs regs; > + uint8_t pad3[16]; > +} QEMU_PACKED; > + > +typedef struct S390xElfPrstatusStruct S390xElfPrstatus; > + > +struct S390xElfFpregsetStruct { > + uint32_t fpc; > + uint32_t pad; > + uint64_t fprs[16]; > +} QEMU_PACKED; > + > +typedef struct S390xElfFpregsetStruct S390xElfFpregset; > + > +typedef struct noteStruct { > + Elf64_Nhdr hdr; > + char name[5]; > + char pad3[3]; > + union { > + S390xElfPrstatus prstatus; > + S390xElfFpregset fpregset; > + uint32_t prefix; > + uint64_t timer; > + uint64_t todcmp; > + uint32_t todpreg; > + uint64_t ctrs[16]; > + } contents; > +} QEMU_PACKED Note; > + > +static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu) > +{ > + int i; > + S390xUserRegs *regs; > + > + note->hdr.n_type = cpu_to_be32(NT_PRSTATUS); > + > + regs = &(note->contents.prstatus.regs); > + regs->psw[0] = cpu_to_be64(cpu->env.psw.mask); > + regs->psw[1] = cpu_to_be64(cpu->env.psw.addr); > + for (i = 0; i <= 15; i++) { > + regs->acrs[i] = cpu_to_be32(cpu->env.aregs[i]); > + regs->gprs[i] = cpu_to_be64(cpu->env.regs[i]); > + } > +} > + > +static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu) > +{ > + int i; > + > + note->hdr.n_type = cpu_to_be32(NT_FPREGSET); > + note->contents.fpregset.fpc = cpu_to_be32(cpu->env.fpc); > + for (i = 0; i <= 15; i++) { > + note->contents.fpregset.fprs[i] = cpu_to_be64(cpu->env.fregs[i].ll); > + } > +} > + > + > +static void s390x_write_elf64_timer(Note *note, S390CPU *cpu) > +{ > + note->hdr.n_type = cpu_to_be32(NT_S390_TIMER); > + note->contents.timer = cpu_to_be64((uint64_t)(cpu->env.cputm)); > +} > + > +static void s390x_write_elf64_todcmp(Note *note, S390CPU *cpu) > +{ > + note->hdr.n_type = cpu_to_be32(NT_S390_TODCMP); > + note->contents.todcmp = cpu_to_be64((uint64_t)(cpu->env.ckc)); > +} > + > +static void s390x_write_elf64_todpreg(Note *note, S390CPU *cpu) > +{ > + note->hdr.n_type = cpu_to_be32(NT_S390_TODPREG); > + note->contents.todpreg = cpu_to_be32((uint32_t)(cpu->env.todpr)); > +} > + > +static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu) > +{ > + int i; > + > + note->hdr.n_type = cpu_to_be32(NT_S390_CTRS); > + > + for (i = 0; i <= 15; i++) { > + note->contents.ctrs[i] = cpu_to_be64(cpu->env.cregs[i]); > + } > +} > + > +static void s390x_write_elf64_prefix(Note *note, S390CPU *cpu) > +{ > + note->hdr.n_type = cpu_to_be32(NT_S390_PREFIX); > + note->contents.prefix = cpu_to_be32((uint32_t)(cpu->env.psa)); > +} > + > + > +struct NoteFuncDescStruct { > + int contents_size; > + void (*note_contents_func)(Note *note, S390CPU *cpu); > +} note_func[] = { > + {sizeof(((Note *)0)->contents.prstatus), s390x_write_elf64_prstatus}, > + {sizeof(((Note *)0)->contents.prefix), s390x_write_elf64_prefix}, > + {sizeof(((Note *)0)->contents.fpregset), s390x_write_elf64_fpregset}, > + {sizeof(((Note *)0)->contents.ctrs), s390x_write_elf64_ctrs}, > + {sizeof(((Note *)0)->contents.timer), s390x_write_elf64_timer}, > + {sizeof(((Note *)0)->contents.todcmp), s390x_write_elf64_todcmp}, > + {sizeof(((Note *)0)->contents.todpreg), s390x_write_elf64_todpreg}, > + { 0, NULL} > +}; > + > +typedef struct NoteFuncDescStruct NoteFuncDesc; > + > + > +static int s390x_write_all_elf64_notes(const char *note_name, > + WriteCoreDumpFunction f, > + S390CPU *cpu, int id, > + void *opaque) > +{ > + Note note; > + NoteFuncDesc *nf; > + int note_size; > + int ret = -1; > + > + 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 s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, > + int cpuid, void *opaque) > +{ > + S390CPU *cpu = S390_CPU(cs); > + return s390x_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque); > +} > + > +int cpu_get_dump_info(ArchDumpInfo *info) > +{ > + info->d_machine = EM_S390; > + 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; > + > + assert(class == ELFCLASS64); > + assert(machine == EM_S390); > + > + 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; > +} > + > +int s390_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, > + CPUState *cpu, void *opaque) > +{ > + return 0; > +} > diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h > index 34d45c2..1b52abb 100644 > --- a/target-s390x/cpu-qom.h > +++ b/target-s390x/cpu-qom.h > @@ -72,5 +72,10 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env) > #define ENV_OFFSET offsetof(S390CPU, env) > > void s390_cpu_do_interrupt(CPUState *cpu); > +int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, > + int cpuid, void *opaque); > + > +int s390_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, > + CPUState *cpu, void *opaque); > > #endif > diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c > index 23fe51f..9376a6c 100644 > --- a/target-s390x/cpu.c > +++ b/target-s390x/cpu.c > @@ -171,6 +171,10 @@ static void s390_cpu_class_init(ObjectClass *oc, void > *data) > > cc->do_interrupt = s390_cpu_do_interrupt; > dc->vmsd = &vmstate_s390_cpu; > +#ifndef CONFIG_USER_ONLY > + cc->write_elf64_note = s390_cpu_write_elf64_note; > + cc->write_elf64_qemunote = s390_cpu_write_elf64_qemunote; > +#endif > } > > static const TypeInfo s390_cpu_type_info = { >