2 * writing ELF notes for ppc64 arch
5 * Copyright IBM, Corp. 2013
8 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
10 * This work is licensed under the terms of the GNU GPL, version 2. See
11 * the COPYING file in the top-level directory.
17 #include "exec/cpu-all.h"
18 #include "sysemu/dump.h"
19 #include "sysemu/kvm.h"
21 struct PPC64UserRegStruct
{
37 struct PPC64ElfPrstatus
{
39 struct PPC64UserRegStruct pr_reg
;
44 struct PPC64ElfFpregset
{
50 struct PPC64ElfVmxregset
{
59 struct PPC64ElfVsxregset
{
63 struct PPC64ElfSperegset
{
69 typedef struct noteStruct
{
74 struct PPC64ElfPrstatus prstatus
;
75 struct PPC64ElfFpregset fpregset
;
76 struct PPC64ElfVmxregset vmxregset
;
77 struct PPC64ElfVsxregset vsxregset
;
78 struct PPC64ElfSperegset speregset
;
82 typedef struct NoteFuncArg
{
87 static void ppc64_write_elf64_prstatus(NoteFuncArg
*arg
, PowerPCCPU
*cpu
)
91 struct PPC64ElfPrstatus
*prstatus
;
92 struct PPC64UserRegStruct
*reg
;
93 Note
*note
= &arg
->note
;
94 DumpState
*s
= arg
->state
;
96 note
->hdr
.n_type
= cpu_to_dump32(s
, NT_PRSTATUS
);
98 prstatus
= ¬e
->contents
.prstatus
;
99 memset(prstatus
, 0, sizeof(*prstatus
));
100 reg
= &prstatus
->pr_reg
;
102 for (i
= 0; i
< 32; i
++) {
103 reg
->gpr
[i
] = cpu_to_dump64(s
, cpu
->env
.gpr
[i
]);
105 reg
->nip
= cpu_to_dump64(s
, cpu
->env
.nip
);
106 reg
->msr
= cpu_to_dump64(s
, cpu
->env
.msr
);
107 reg
->ctr
= cpu_to_dump64(s
, cpu
->env
.ctr
);
108 reg
->link
= cpu_to_dump64(s
, cpu
->env
.lr
);
109 reg
->xer
= cpu_to_dump64(s
, cpu_read_xer(&cpu
->env
));
112 for (i
= 0; i
< 8; i
++) {
113 cr
|= (cpu
->env
.crf
[i
] & 15) << (4 * (7 - i
));
115 reg
->ccr
= cpu_to_dump64(s
, cr
);
118 static void ppc64_write_elf64_fpregset(NoteFuncArg
*arg
, PowerPCCPU
*cpu
)
121 struct PPC64ElfFpregset
*fpregset
;
122 Note
*note
= &arg
->note
;
123 DumpState
*s
= arg
->state
;
125 note
->hdr
.n_type
= cpu_to_dump32(s
, NT_PRFPREG
);
127 fpregset
= ¬e
->contents
.fpregset
;
128 memset(fpregset
, 0, sizeof(*fpregset
));
130 for (i
= 0; i
< 32; i
++) {
131 fpregset
->fpr
[i
] = cpu_to_dump64(s
, cpu
->env
.fpr
[i
]);
133 fpregset
->fpscr
= cpu_to_dump64(s
, cpu
->env
.fpscr
);
136 static void ppc64_write_elf64_vmxregset(NoteFuncArg
*arg
, PowerPCCPU
*cpu
)
139 struct PPC64ElfVmxregset
*vmxregset
;
140 Note
*note
= &arg
->note
;
141 DumpState
*s
= arg
->state
;
143 note
->hdr
.n_type
= cpu_to_dump32(s
, NT_PPC_VMX
);
144 vmxregset
= ¬e
->contents
.vmxregset
;
145 memset(vmxregset
, 0, sizeof(*vmxregset
));
147 for (i
= 0; i
< 32; i
++) {
150 #ifdef HOST_WORDS_BIGENDIAN
151 needs_byteswap
= s
->dump_info
.d_endian
== ELFDATA2LSB
;
153 needs_byteswap
= s
->dump_info
.d_endian
== ELFDATA2MSB
;
156 if (needs_byteswap
) {
157 vmxregset
->avr
[i
].u64
[0] = bswap64(cpu
->env
.avr
[i
].u64
[1]);
158 vmxregset
->avr
[i
].u64
[1] = bswap64(cpu
->env
.avr
[i
].u64
[0]);
160 vmxregset
->avr
[i
].u64
[0] = cpu
->env
.avr
[i
].u64
[0];
161 vmxregset
->avr
[i
].u64
[1] = cpu
->env
.avr
[i
].u64
[1];
164 vmxregset
->vscr
.u32
[3] = cpu_to_dump32(s
, cpu
->env
.vscr
);
166 static void ppc64_write_elf64_vsxregset(NoteFuncArg
*arg
, PowerPCCPU
*cpu
)
169 struct PPC64ElfVsxregset
*vsxregset
;
170 Note
*note
= &arg
->note
;
171 DumpState
*s
= arg
->state
;
173 note
->hdr
.n_type
= cpu_to_dump32(s
, NT_PPC_VSX
);
174 vsxregset
= ¬e
->contents
.vsxregset
;
175 memset(vsxregset
, 0, sizeof(*vsxregset
));
177 for (i
= 0; i
< 32; i
++) {
178 vsxregset
->vsr
[i
] = cpu_to_dump64(s
, cpu
->env
.vsr
[i
]);
181 static void ppc64_write_elf64_speregset(NoteFuncArg
*arg
, PowerPCCPU
*cpu
)
183 struct PPC64ElfSperegset
*speregset
;
184 Note
*note
= &arg
->note
;
185 DumpState
*s
= arg
->state
;
187 note
->hdr
.n_type
= cpu_to_dump32(s
, NT_PPC_SPE
);
188 speregset
= ¬e
->contents
.speregset
;
189 memset(speregset
, 0, sizeof(*speregset
));
191 speregset
->spe_acc
= cpu_to_dump64(s
, cpu
->env
.spe_acc
);
192 speregset
->spe_fscr
= cpu_to_dump32(s
, cpu
->env
.spe_fscr
);
195 static const struct NoteFuncDescStruct
{
197 void (*note_contents_func
)(NoteFuncArg
*arg
, PowerPCCPU
*cpu
);
199 {sizeof(((Note
*)0)->contents
.prstatus
), ppc64_write_elf64_prstatus
},
200 {sizeof(((Note
*)0)->contents
.fpregset
), ppc64_write_elf64_fpregset
},
201 {sizeof(((Note
*)0)->contents
.vmxregset
), ppc64_write_elf64_vmxregset
},
202 {sizeof(((Note
*)0)->contents
.vsxregset
), ppc64_write_elf64_vsxregset
},
203 {sizeof(((Note
*)0)->contents
.speregset
), ppc64_write_elf64_speregset
},
207 typedef struct NoteFuncDescStruct NoteFuncDesc
;
209 int cpu_get_dump_info(ArchDumpInfo
*info
,
210 const struct GuestPhysBlockList
*guest_phys_blocks
)
212 PowerPCCPU
*cpu
= POWERPC_CPU(first_cpu
);
213 PowerPCCPUClass
*pcc
= POWERPC_CPU_GET_CLASS(cpu
);
215 info
->d_machine
= EM_PPC64
;
216 info
->d_class
= ELFCLASS64
;
217 if ((*pcc
->interrupts_big_endian
)(cpu
)) {
218 info
->d_endian
= ELFDATA2MSB
;
220 info
->d_endian
= ELFDATA2LSB
;
226 ssize_t
cpu_get_note_size(int class, int machine
, int nr_cpus
)
228 int name_size
= 8; /* "CORE" or "QEMU" rounded */
229 size_t elf_note_size
= 0;
231 const NoteFuncDesc
*nf
;
233 if (class != ELFCLASS64
) {
236 assert(machine
== EM_PPC64
);
238 note_head_size
= sizeof(Elf64_Nhdr
);
240 for (nf
= note_func
; nf
->note_contents_func
; nf
++) {
241 elf_note_size
= elf_note_size
+ note_head_size
+ name_size
+
245 return (elf_note_size
) * nr_cpus
;
248 static int ppc64_write_all_elf64_notes(const char *note_name
,
249 WriteCoreDumpFunction f
,
250 PowerPCCPU
*cpu
, int id
,
253 NoteFuncArg arg
= { .state
= opaque
};
256 const NoteFuncDesc
*nf
;
258 for (nf
= note_func
; nf
->note_contents_func
; nf
++) {
259 arg
.note
.hdr
.n_namesz
= cpu_to_dump32(opaque
, sizeof(arg
.note
.name
));
260 arg
.note
.hdr
.n_descsz
= cpu_to_dump32(opaque
, nf
->contents_size
);
261 strncpy(arg
.note
.name
, note_name
, sizeof(arg
.note
.name
));
263 (*nf
->note_contents_func
)(&arg
, cpu
);
266 sizeof(arg
.note
) - sizeof(arg
.note
.contents
) + nf
->contents_size
;
267 ret
= f(&arg
.note
, note_size
, opaque
);
275 int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f
, CPUState
*cs
,
276 int cpuid
, void *opaque
)
278 PowerPCCPU
*cpu
= POWERPC_CPU(cs
);
279 return ppc64_write_all_elf64_notes("CORE", f
, cpu
, cpuid
, opaque
);
282 int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f
,
283 CPUState
*cpu
, void *opaque
)