2 * writing ELF notes for s390x arch
5 * Copyright IBM Corp. 2012, 2013
7 * Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
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.
14 #include "qemu/osdep.h"
18 #include "exec/cpu-all.h"
19 #include "sysemu/dump.h"
22 struct S390xUserRegsStruct
{
28 typedef struct S390xUserRegsStruct S390xUserRegs
;
30 struct S390xElfPrstatusStruct
{
38 typedef struct S390xElfPrstatusStruct S390xElfPrstatus
;
40 struct S390xElfFpregsetStruct
{
46 typedef struct S390xElfFpregsetStruct S390xElfFpregset
;
48 struct S390xElfVregsLoStruct
{
52 typedef struct S390xElfVregsLoStruct S390xElfVregsLo
;
54 struct S390xElfVregsHiStruct
{
55 uint64_t vregs
[16][2];
58 typedef struct S390xElfVregsHiStruct S390xElfVregsHi
;
60 struct S390xElfGSCBStruct
{
64 typedef struct S390xElfGSCBStruct S390xElfGSCB
;
66 typedef struct noteStruct
{
70 S390xElfPrstatus prstatus
;
71 S390xElfFpregset fpregset
;
72 S390xElfVregsLo vregslo
;
73 S390xElfVregsHi vregshi
;
83 static void s390x_write_elf64_prstatus(Note
*note
, S390CPU
*cpu
, int id
)
88 note
->hdr
.n_type
= cpu_to_be32(NT_PRSTATUS
);
90 regs
= &(note
->contents
.prstatus
.regs
);
91 regs
->psw
[0] = cpu_to_be64(cpu
->env
.psw
.mask
);
92 regs
->psw
[1] = cpu_to_be64(cpu
->env
.psw
.addr
);
93 for (i
= 0; i
<= 15; i
++) {
94 regs
->acrs
[i
] = cpu_to_be32(cpu
->env
.aregs
[i
]);
95 regs
->gprs
[i
] = cpu_to_be64(cpu
->env
.regs
[i
]);
97 note
->contents
.prstatus
.pid
= id
;
100 static void s390x_write_elf64_fpregset(Note
*note
, S390CPU
*cpu
, int id
)
103 CPUS390XState
*cs
= &cpu
->env
;
105 note
->hdr
.n_type
= cpu_to_be32(NT_FPREGSET
);
106 note
->contents
.fpregset
.fpc
= cpu_to_be32(cpu
->env
.fpc
);
107 for (i
= 0; i
<= 15; i
++) {
108 note
->contents
.fpregset
.fprs
[i
] = cpu_to_be64(get_freg(cs
, i
)->ll
);
112 static void s390x_write_elf64_vregslo(Note
*note
, S390CPU
*cpu
, int id
)
116 note
->hdr
.n_type
= cpu_to_be32(NT_S390_VXRS_LOW
);
117 for (i
= 0; i
<= 15; i
++) {
118 note
->contents
.vregslo
.vregs
[i
] = cpu_to_be64(cpu
->env
.vregs
[i
][1].ll
);
122 static void s390x_write_elf64_vregshi(Note
*note
, S390CPU
*cpu
, int id
)
125 S390xElfVregsHi
*temp_vregshi
;
127 temp_vregshi
= ¬e
->contents
.vregshi
;
129 note
->hdr
.n_type
= cpu_to_be32(NT_S390_VXRS_HIGH
);
130 for (i
= 0; i
<= 15; i
++) {
131 temp_vregshi
->vregs
[i
][0] = cpu_to_be64(cpu
->env
.vregs
[i
+ 16][0].ll
);
132 temp_vregshi
->vregs
[i
][1] = cpu_to_be64(cpu
->env
.vregs
[i
+ 16][1].ll
);
136 static void s390x_write_elf64_gscb(Note
*note
, S390CPU
*cpu
, int id
)
140 note
->hdr
.n_type
= cpu_to_be32(NT_S390_GS_CB
);
141 for (i
= 0; i
< 4; i
++) {
142 note
->contents
.gscb
.gsregs
[i
] = cpu_to_be64(cpu
->env
.gscb
[i
]);
146 static void s390x_write_elf64_timer(Note
*note
, S390CPU
*cpu
, int id
)
148 note
->hdr
.n_type
= cpu_to_be32(NT_S390_TIMER
);
149 note
->contents
.timer
= cpu_to_be64((uint64_t)(cpu
->env
.cputm
));
152 static void s390x_write_elf64_todcmp(Note
*note
, S390CPU
*cpu
, int id
)
154 note
->hdr
.n_type
= cpu_to_be32(NT_S390_TODCMP
);
155 note
->contents
.todcmp
= cpu_to_be64((uint64_t)(cpu
->env
.ckc
));
158 static void s390x_write_elf64_todpreg(Note
*note
, S390CPU
*cpu
, int id
)
160 note
->hdr
.n_type
= cpu_to_be32(NT_S390_TODPREG
);
161 note
->contents
.todpreg
= cpu_to_be32((uint32_t)(cpu
->env
.todpr
));
164 static void s390x_write_elf64_ctrs(Note
*note
, S390CPU
*cpu
, int id
)
168 note
->hdr
.n_type
= cpu_to_be32(NT_S390_CTRS
);
170 for (i
= 0; i
<= 15; i
++) {
171 note
->contents
.ctrs
[i
] = cpu_to_be64(cpu
->env
.cregs
[i
]);
175 static void s390x_write_elf64_prefix(Note
*note
, S390CPU
*cpu
, int id
)
177 note
->hdr
.n_type
= cpu_to_be32(NT_S390_PREFIX
);
178 note
->contents
.prefix
= cpu_to_be32((uint32_t)(cpu
->env
.psa
));
182 typedef struct NoteFuncDescStruct
{
184 void (*note_contents_func
)(Note
*note
, S390CPU
*cpu
, int id
);
187 static const NoteFuncDesc note_core
[] = {
188 {sizeof(((Note
*)0)->contents
.prstatus
), s390x_write_elf64_prstatus
},
189 {sizeof(((Note
*)0)->contents
.fpregset
), s390x_write_elf64_fpregset
},
193 static const NoteFuncDesc note_linux
[] = {
194 {sizeof(((Note
*)0)->contents
.prefix
), s390x_write_elf64_prefix
},
195 {sizeof(((Note
*)0)->contents
.ctrs
), s390x_write_elf64_ctrs
},
196 {sizeof(((Note
*)0)->contents
.timer
), s390x_write_elf64_timer
},
197 {sizeof(((Note
*)0)->contents
.todcmp
), s390x_write_elf64_todcmp
},
198 {sizeof(((Note
*)0)->contents
.todpreg
), s390x_write_elf64_todpreg
},
199 {sizeof(((Note
*)0)->contents
.vregslo
), s390x_write_elf64_vregslo
},
200 {sizeof(((Note
*)0)->contents
.vregshi
), s390x_write_elf64_vregshi
},
201 {sizeof(((Note
*)0)->contents
.gscb
), s390x_write_elf64_gscb
},
205 static int s390x_write_elf64_notes(const char *note_name
,
206 WriteCoreDumpFunction f
,
207 S390CPU
*cpu
, int id
,
209 const NoteFuncDesc
*funcs
)
212 const NoteFuncDesc
*nf
;
216 for (nf
= funcs
; nf
->note_contents_func
; nf
++) {
217 memset(¬e
, 0, sizeof(note
));
218 note
.hdr
.n_namesz
= cpu_to_be32(strlen(note_name
) + 1);
219 note
.hdr
.n_descsz
= cpu_to_be32(nf
->contents_size
);
220 strncpy(note
.name
, note_name
, sizeof(note
.name
));
221 (*nf
->note_contents_func
)(¬e
, cpu
, id
);
223 note_size
= sizeof(note
) - sizeof(note
.contents
) + nf
->contents_size
;
224 ret
= f(¬e
, note_size
, opaque
);
236 int s390_cpu_write_elf64_note(WriteCoreDumpFunction f
, CPUState
*cs
,
237 int cpuid
, void *opaque
)
239 S390CPU
*cpu
= S390_CPU(cs
);
242 r
= s390x_write_elf64_notes("CORE", f
, cpu
, cpuid
, opaque
, note_core
);
246 return s390x_write_elf64_notes("LINUX", f
, cpu
, cpuid
, opaque
, note_linux
);
249 int cpu_get_dump_info(ArchDumpInfo
*info
,
250 const struct GuestPhysBlockList
*guest_phys_blocks
)
252 info
->d_machine
= EM_S390
;
253 info
->d_endian
= ELFDATA2MSB
;
254 info
->d_class
= ELFCLASS64
;
259 ssize_t
cpu_get_note_size(int class, int machine
, int nr_cpus
)
261 int name_size
= 8; /* "LINUX" or "CORE" + pad */
262 size_t elf_note_size
= 0;
264 const NoteFuncDesc
*nf
;
266 assert(class == ELFCLASS64
);
267 assert(machine
== EM_S390
);
269 note_head_size
= sizeof(Elf64_Nhdr
);
271 for (nf
= note_core
; nf
->note_contents_func
; nf
++) {
272 elf_note_size
= elf_note_size
+ note_head_size
+ name_size
+
275 for (nf
= note_linux
; nf
->note_contents_func
; nf
++) {
276 elf_note_size
= elf_note_size
+ note_head_size
+ name_size
+
280 return (elf_note_size
) * nr_cpus
;