xref: /qemu/target/s390x/arch_dump.c (revision 21a106904b5336b6ea60c22a95feb7d61c664d7f)
19b4f38e1SEkaterina Tumanova /*
29b4f38e1SEkaterina Tumanova  * writing ELF notes for s390x arch
39b4f38e1SEkaterina Tumanova  *
49b4f38e1SEkaterina Tumanova  *
59b4f38e1SEkaterina Tumanova  * Copyright IBM Corp. 2012, 2013
69b4f38e1SEkaterina Tumanova  *
79b4f38e1SEkaterina Tumanova  *     Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
89b4f38e1SEkaterina Tumanova  *
99b4f38e1SEkaterina Tumanova  * This work is licensed under the terms of the GNU GPL, version 2 or later.
109b4f38e1SEkaterina Tumanova  * See the COPYING file in the top-level directory.
119b4f38e1SEkaterina Tumanova  *
129b4f38e1SEkaterina Tumanova  */
139b4f38e1SEkaterina Tumanova 
149615495aSPeter Maydell #include "qemu/osdep.h"
159b4f38e1SEkaterina Tumanova #include "cpu.h"
169b4f38e1SEkaterina Tumanova #include "elf.h"
179b4f38e1SEkaterina Tumanova #include "exec/cpu-all.h"
189b4f38e1SEkaterina Tumanova #include "sysemu/dump.h"
199b4f38e1SEkaterina Tumanova #include "sysemu/kvm.h"
209b4f38e1SEkaterina Tumanova 
219b4f38e1SEkaterina Tumanova 
229b4f38e1SEkaterina Tumanova struct S390xUserRegsStruct {
239b4f38e1SEkaterina Tumanova     uint64_t psw[2];
249b4f38e1SEkaterina Tumanova     uint64_t gprs[16];
259b4f38e1SEkaterina Tumanova     uint32_t acrs[16];
269b4f38e1SEkaterina Tumanova } QEMU_PACKED;
279b4f38e1SEkaterina Tumanova 
289b4f38e1SEkaterina Tumanova typedef struct S390xUserRegsStruct S390xUserRegs;
299b4f38e1SEkaterina Tumanova 
309b4f38e1SEkaterina Tumanova struct S390xElfPrstatusStruct {
319b4f38e1SEkaterina Tumanova     uint8_t pad1[32];
329b4f38e1SEkaterina Tumanova     uint32_t pid;
339b4f38e1SEkaterina Tumanova     uint8_t pad2[76];
349b4f38e1SEkaterina Tumanova     S390xUserRegs regs;
359b4f38e1SEkaterina Tumanova     uint8_t pad3[16];
369b4f38e1SEkaterina Tumanova } QEMU_PACKED;
379b4f38e1SEkaterina Tumanova 
389b4f38e1SEkaterina Tumanova typedef struct S390xElfPrstatusStruct S390xElfPrstatus;
399b4f38e1SEkaterina Tumanova 
409b4f38e1SEkaterina Tumanova struct S390xElfFpregsetStruct {
419b4f38e1SEkaterina Tumanova     uint32_t fpc;
429b4f38e1SEkaterina Tumanova     uint32_t pad;
439b4f38e1SEkaterina Tumanova     uint64_t fprs[16];
449b4f38e1SEkaterina Tumanova } QEMU_PACKED;
459b4f38e1SEkaterina Tumanova 
469b4f38e1SEkaterina Tumanova typedef struct S390xElfFpregsetStruct S390xElfFpregset;
479b4f38e1SEkaterina Tumanova 
483ceeb293SEric Farman struct S390xElfVregsLoStruct {
493ceeb293SEric Farman     uint64_t vregs[16];
503ceeb293SEric Farman } QEMU_PACKED;
513ceeb293SEric Farman 
523ceeb293SEric Farman typedef struct S390xElfVregsLoStruct S390xElfVregsLo;
533ceeb293SEric Farman 
543ceeb293SEric Farman struct S390xElfVregsHiStruct {
553ceeb293SEric Farman     uint64_t vregs[16][2];
563ceeb293SEric Farman } QEMU_PACKED;
573ceeb293SEric Farman 
583ceeb293SEric Farman typedef struct S390xElfVregsHiStruct S390xElfVregsHi;
593ceeb293SEric Farman 
60*21a10690SChristian Borntraeger struct S390xElfGSCBStruct {
61*21a10690SChristian Borntraeger     uint64_t gsregs[4];
62*21a10690SChristian Borntraeger } QEMU_PACKED;
63*21a10690SChristian Borntraeger 
64*21a10690SChristian Borntraeger typedef struct S390xElfGSCBStruct S390xElfGSCB;
65*21a10690SChristian Borntraeger 
669b4f38e1SEkaterina Tumanova typedef struct noteStruct {
679b4f38e1SEkaterina Tumanova     Elf64_Nhdr hdr;
685f706fdcSChristian Borntraeger     char name[8];
699b4f38e1SEkaterina Tumanova     union {
709b4f38e1SEkaterina Tumanova         S390xElfPrstatus prstatus;
719b4f38e1SEkaterina Tumanova         S390xElfFpregset fpregset;
723ceeb293SEric Farman         S390xElfVregsLo vregslo;
733ceeb293SEric Farman         S390xElfVregsHi vregshi;
74*21a10690SChristian Borntraeger         S390xElfGSCB gscb;
759b4f38e1SEkaterina Tumanova         uint32_t prefix;
769b4f38e1SEkaterina Tumanova         uint64_t timer;
779b4f38e1SEkaterina Tumanova         uint64_t todcmp;
789b4f38e1SEkaterina Tumanova         uint32_t todpreg;
799b4f38e1SEkaterina Tumanova         uint64_t ctrs[16];
809b4f38e1SEkaterina Tumanova     } contents;
819b4f38e1SEkaterina Tumanova } QEMU_PACKED Note;
829b4f38e1SEkaterina Tumanova 
83f738f296SChristian Borntraeger static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu, int id)
849b4f38e1SEkaterina Tumanova {
859b4f38e1SEkaterina Tumanova     int i;
869b4f38e1SEkaterina Tumanova     S390xUserRegs *regs;
879b4f38e1SEkaterina Tumanova 
889b4f38e1SEkaterina Tumanova     note->hdr.n_type = cpu_to_be32(NT_PRSTATUS);
899b4f38e1SEkaterina Tumanova 
909b4f38e1SEkaterina Tumanova     regs = &(note->contents.prstatus.regs);
919b4f38e1SEkaterina Tumanova     regs->psw[0] = cpu_to_be64(cpu->env.psw.mask);
929b4f38e1SEkaterina Tumanova     regs->psw[1] = cpu_to_be64(cpu->env.psw.addr);
939b4f38e1SEkaterina Tumanova     for (i = 0; i <= 15; i++) {
949b4f38e1SEkaterina Tumanova         regs->acrs[i] = cpu_to_be32(cpu->env.aregs[i]);
959b4f38e1SEkaterina Tumanova         regs->gprs[i] = cpu_to_be64(cpu->env.regs[i]);
969b4f38e1SEkaterina Tumanova     }
97f738f296SChristian Borntraeger     note->contents.prstatus.pid = id;
989b4f38e1SEkaterina Tumanova }
999b4f38e1SEkaterina Tumanova 
100f738f296SChristian Borntraeger static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu, int id)
1019b4f38e1SEkaterina Tumanova {
1029b4f38e1SEkaterina Tumanova     int i;
103c498d8e3SEric Farman     CPUS390XState *cs = &cpu->env;
1049b4f38e1SEkaterina Tumanova 
1059b4f38e1SEkaterina Tumanova     note->hdr.n_type = cpu_to_be32(NT_FPREGSET);
1069b4f38e1SEkaterina Tumanova     note->contents.fpregset.fpc = cpu_to_be32(cpu->env.fpc);
1079b4f38e1SEkaterina Tumanova     for (i = 0; i <= 15; i++) {
108c498d8e3SEric Farman         note->contents.fpregset.fprs[i] = cpu_to_be64(get_freg(cs, i)->ll);
1099b4f38e1SEkaterina Tumanova     }
1109b4f38e1SEkaterina Tumanova }
1119b4f38e1SEkaterina Tumanova 
112f738f296SChristian Borntraeger static void s390x_write_elf64_vregslo(Note *note, S390CPU *cpu,  int id)
1133ceeb293SEric Farman {
1143ceeb293SEric Farman     int i;
1153ceeb293SEric Farman 
1163ceeb293SEric Farman     note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_LOW);
1173ceeb293SEric Farman     for (i = 0; i <= 15; i++) {
1183ceeb293SEric Farman         note->contents.vregslo.vregs[i] = cpu_to_be64(cpu->env.vregs[i][1].ll);
1193ceeb293SEric Farman     }
1203ceeb293SEric Farman }
1213ceeb293SEric Farman 
122f738f296SChristian Borntraeger static void s390x_write_elf64_vregshi(Note *note, S390CPU *cpu, int id)
1233ceeb293SEric Farman {
1243ceeb293SEric Farman     int i;
1253ceeb293SEric Farman     S390xElfVregsHi *temp_vregshi;
1263ceeb293SEric Farman 
1273ceeb293SEric Farman     temp_vregshi = &note->contents.vregshi;
1283ceeb293SEric Farman 
1293ceeb293SEric Farman     note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_HIGH);
1303ceeb293SEric Farman     for (i = 0; i <= 15; i++) {
1313ceeb293SEric Farman         temp_vregshi->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i + 16][0].ll);
1323ceeb293SEric Farman         temp_vregshi->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i + 16][1].ll);
1333ceeb293SEric Farman     }
1343ceeb293SEric Farman }
1359b4f38e1SEkaterina Tumanova 
136*21a10690SChristian Borntraeger static void s390x_write_elf64_gscb(Note *note, S390CPU *cpu, int id)
137*21a10690SChristian Borntraeger {
138*21a10690SChristian Borntraeger     int i;
139*21a10690SChristian Borntraeger 
140*21a10690SChristian Borntraeger     note->hdr.n_type = cpu_to_be32(NT_S390_GS_CB);
141*21a10690SChristian Borntraeger     for (i = 0; i < 4; i++) {
142*21a10690SChristian Borntraeger         note->contents.gscb.gsregs[i] = cpu_to_be64(cpu->env.gscb[i]);
143*21a10690SChristian Borntraeger     }
144*21a10690SChristian Borntraeger }
145*21a10690SChristian Borntraeger 
146f738f296SChristian Borntraeger static void s390x_write_elf64_timer(Note *note, S390CPU *cpu, int id)
1479b4f38e1SEkaterina Tumanova {
1489b4f38e1SEkaterina Tumanova     note->hdr.n_type = cpu_to_be32(NT_S390_TIMER);
1499b4f38e1SEkaterina Tumanova     note->contents.timer = cpu_to_be64((uint64_t)(cpu->env.cputm));
1509b4f38e1SEkaterina Tumanova }
1519b4f38e1SEkaterina Tumanova 
152f738f296SChristian Borntraeger static void s390x_write_elf64_todcmp(Note *note, S390CPU *cpu, int id)
1539b4f38e1SEkaterina Tumanova {
1549b4f38e1SEkaterina Tumanova     note->hdr.n_type = cpu_to_be32(NT_S390_TODCMP);
1559b4f38e1SEkaterina Tumanova     note->contents.todcmp = cpu_to_be64((uint64_t)(cpu->env.ckc));
1569b4f38e1SEkaterina Tumanova }
1579b4f38e1SEkaterina Tumanova 
158f738f296SChristian Borntraeger static void s390x_write_elf64_todpreg(Note *note, S390CPU *cpu, int id)
1599b4f38e1SEkaterina Tumanova {
1609b4f38e1SEkaterina Tumanova     note->hdr.n_type = cpu_to_be32(NT_S390_TODPREG);
1619b4f38e1SEkaterina Tumanova     note->contents.todpreg = cpu_to_be32((uint32_t)(cpu->env.todpr));
1629b4f38e1SEkaterina Tumanova }
1639b4f38e1SEkaterina Tumanova 
164f738f296SChristian Borntraeger static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu, int id)
1659b4f38e1SEkaterina Tumanova {
1669b4f38e1SEkaterina Tumanova     int i;
1679b4f38e1SEkaterina Tumanova 
1689b4f38e1SEkaterina Tumanova     note->hdr.n_type = cpu_to_be32(NT_S390_CTRS);
1699b4f38e1SEkaterina Tumanova 
1709b4f38e1SEkaterina Tumanova     for (i = 0; i <= 15; i++) {
1719b4f38e1SEkaterina Tumanova         note->contents.ctrs[i] = cpu_to_be64(cpu->env.cregs[i]);
1729b4f38e1SEkaterina Tumanova     }
1739b4f38e1SEkaterina Tumanova }
1749b4f38e1SEkaterina Tumanova 
175f738f296SChristian Borntraeger static void s390x_write_elf64_prefix(Note *note, S390CPU *cpu, int id)
1769b4f38e1SEkaterina Tumanova {
1779b4f38e1SEkaterina Tumanova     note->hdr.n_type = cpu_to_be32(NT_S390_PREFIX);
1789b4f38e1SEkaterina Tumanova     note->contents.prefix = cpu_to_be32((uint32_t)(cpu->env.psa));
1799b4f38e1SEkaterina Tumanova }
1809b4f38e1SEkaterina Tumanova 
1819b4f38e1SEkaterina Tumanova 
1825f706fdcSChristian Borntraeger typedef struct NoteFuncDescStruct {
1839b4f38e1SEkaterina Tumanova     int contents_size;
184f738f296SChristian Borntraeger     void (*note_contents_func)(Note *note, S390CPU *cpu, int id);
1855f706fdcSChristian Borntraeger } NoteFuncDesc;
1865f706fdcSChristian Borntraeger 
1875f706fdcSChristian Borntraeger static const NoteFuncDesc note_core[] = {
1889b4f38e1SEkaterina Tumanova     {sizeof(((Note *)0)->contents.prstatus), s390x_write_elf64_prstatus},
1899b4f38e1SEkaterina Tumanova     {sizeof(((Note *)0)->contents.fpregset), s390x_write_elf64_fpregset},
1905f706fdcSChristian Borntraeger     { 0, NULL}
1915f706fdcSChristian Borntraeger };
1925f706fdcSChristian Borntraeger 
1935f706fdcSChristian Borntraeger static const NoteFuncDesc note_linux[] = {
1945f706fdcSChristian Borntraeger     {sizeof(((Note *)0)->contents.prefix),   s390x_write_elf64_prefix},
1959b4f38e1SEkaterina Tumanova     {sizeof(((Note *)0)->contents.ctrs),     s390x_write_elf64_ctrs},
1969b4f38e1SEkaterina Tumanova     {sizeof(((Note *)0)->contents.timer),    s390x_write_elf64_timer},
1979b4f38e1SEkaterina Tumanova     {sizeof(((Note *)0)->contents.todcmp),   s390x_write_elf64_todcmp},
1989b4f38e1SEkaterina Tumanova     {sizeof(((Note *)0)->contents.todpreg),  s390x_write_elf64_todpreg},
1993ceeb293SEric Farman     {sizeof(((Note *)0)->contents.vregslo),  s390x_write_elf64_vregslo},
2003ceeb293SEric Farman     {sizeof(((Note *)0)->contents.vregshi),  s390x_write_elf64_vregshi},
201*21a10690SChristian Borntraeger     {sizeof(((Note *)0)->contents.gscb),     s390x_write_elf64_gscb},
2029b4f38e1SEkaterina Tumanova     { 0, NULL}
2039b4f38e1SEkaterina Tumanova };
2049b4f38e1SEkaterina Tumanova 
2055f706fdcSChristian Borntraeger static int s390x_write_elf64_notes(const char *note_name,
2069b4f38e1SEkaterina Tumanova                                        WriteCoreDumpFunction f,
2079b4f38e1SEkaterina Tumanova                                        S390CPU *cpu, int id,
2085f706fdcSChristian Borntraeger                                        void *opaque,
2095f706fdcSChristian Borntraeger                                        const NoteFuncDesc *funcs)
2109b4f38e1SEkaterina Tumanova {
2119b4f38e1SEkaterina Tumanova     Note note;
212ecb4e01eSStefan Weil     const NoteFuncDesc *nf;
2139b4f38e1SEkaterina Tumanova     int note_size;
2149b4f38e1SEkaterina Tumanova     int ret = -1;
2159b4f38e1SEkaterina Tumanova 
2165f706fdcSChristian Borntraeger     for (nf = funcs; nf->note_contents_func; nf++) {
217abd137a1SChristian Borntraeger         memset(&note, 0, sizeof(note));
2185f706fdcSChristian Borntraeger         note.hdr.n_namesz = cpu_to_be32(strlen(note_name) + 1);
2199b4f38e1SEkaterina Tumanova         note.hdr.n_descsz = cpu_to_be32(nf->contents_size);
2209b4f38e1SEkaterina Tumanova         strncpy(note.name, note_name, sizeof(note.name));
221f738f296SChristian Borntraeger         (*nf->note_contents_func)(&note, cpu, id);
2229b4f38e1SEkaterina Tumanova 
2239b4f38e1SEkaterina Tumanova         note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
2249b4f38e1SEkaterina Tumanova         ret = f(&note, note_size, opaque);
2259b4f38e1SEkaterina Tumanova 
2269b4f38e1SEkaterina Tumanova         if (ret < 0) {
2279b4f38e1SEkaterina Tumanova             return -1;
2289b4f38e1SEkaterina Tumanova         }
2299b4f38e1SEkaterina Tumanova 
2309b4f38e1SEkaterina Tumanova     }
2319b4f38e1SEkaterina Tumanova 
2329b4f38e1SEkaterina Tumanova     return 0;
2339b4f38e1SEkaterina Tumanova }
2349b4f38e1SEkaterina Tumanova 
2359b4f38e1SEkaterina Tumanova 
2369b4f38e1SEkaterina Tumanova int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
2379b4f38e1SEkaterina Tumanova                               int cpuid, void *opaque)
2389b4f38e1SEkaterina Tumanova {
2399b4f38e1SEkaterina Tumanova     S390CPU *cpu = S390_CPU(cs);
2405f706fdcSChristian Borntraeger     int r;
2415f706fdcSChristian Borntraeger 
2425f706fdcSChristian Borntraeger     r = s390x_write_elf64_notes("CORE", f, cpu, cpuid, opaque, note_core);
2435f706fdcSChristian Borntraeger     if (r) {
2445f706fdcSChristian Borntraeger         return r;
2455f706fdcSChristian Borntraeger     }
2465f706fdcSChristian Borntraeger     return s390x_write_elf64_notes("LINUX", f, cpu, cpuid, opaque, note_linux);
2479b4f38e1SEkaterina Tumanova }
2489b4f38e1SEkaterina Tumanova 
24956c4bfb3SLaszlo Ersek int cpu_get_dump_info(ArchDumpInfo *info,
25056c4bfb3SLaszlo Ersek                       const struct GuestPhysBlockList *guest_phys_blocks)
2519b4f38e1SEkaterina Tumanova {
2529b4f38e1SEkaterina Tumanova     info->d_machine = EM_S390;
2539b4f38e1SEkaterina Tumanova     info->d_endian = ELFDATA2MSB;
2549b4f38e1SEkaterina Tumanova     info->d_class = ELFCLASS64;
2559b4f38e1SEkaterina Tumanova 
2569b4f38e1SEkaterina Tumanova     return 0;
2579b4f38e1SEkaterina Tumanova }
2589b4f38e1SEkaterina Tumanova 
2599b4f38e1SEkaterina Tumanova ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
2609b4f38e1SEkaterina Tumanova {
2615f706fdcSChristian Borntraeger     int name_size = 8; /* "LINUX" or "CORE" + pad */
2629b4f38e1SEkaterina Tumanova     size_t elf_note_size = 0;
2639b4f38e1SEkaterina Tumanova     int note_head_size;
264ecb4e01eSStefan Weil     const NoteFuncDesc *nf;
2659b4f38e1SEkaterina Tumanova 
2669b4f38e1SEkaterina Tumanova     assert(class == ELFCLASS64);
2679b4f38e1SEkaterina Tumanova     assert(machine == EM_S390);
2689b4f38e1SEkaterina Tumanova 
2699b4f38e1SEkaterina Tumanova     note_head_size = sizeof(Elf64_Nhdr);
2709b4f38e1SEkaterina Tumanova 
2715f706fdcSChristian Borntraeger     for (nf = note_core; nf->note_contents_func; nf++) {
2725f706fdcSChristian Borntraeger         elf_note_size = elf_note_size + note_head_size + name_size +
2735f706fdcSChristian Borntraeger                         nf->contents_size;
2745f706fdcSChristian Borntraeger     }
2755f706fdcSChristian Borntraeger     for (nf = note_linux; nf->note_contents_func; nf++) {
2769b4f38e1SEkaterina Tumanova         elf_note_size = elf_note_size + note_head_size + name_size +
2779b4f38e1SEkaterina Tumanova                         nf->contents_size;
2789b4f38e1SEkaterina Tumanova     }
2799b4f38e1SEkaterina Tumanova 
2809b4f38e1SEkaterina Tumanova     return (elf_note_size) * nr_cpus;
2819b4f38e1SEkaterina Tumanova }
282