1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth * i386 memory mapping
3fcf5ef2aSThomas Huth *
4fcf5ef2aSThomas Huth * Copyright Fujitsu, Corp. 2011, 2012
5fcf5ef2aSThomas Huth *
6fcf5ef2aSThomas Huth * Authors:
7fcf5ef2aSThomas Huth * Wen Congyang <wency@cn.fujitsu.com>
8fcf5ef2aSThomas Huth *
9fcf5ef2aSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or later.
10fcf5ef2aSThomas Huth * See the COPYING file in the top-level directory.
11fcf5ef2aSThomas Huth *
12fcf5ef2aSThomas Huth */
13fcf5ef2aSThomas Huth
14fcf5ef2aSThomas Huth #include "qemu/osdep.h"
15fcf5ef2aSThomas Huth #include "cpu.h"
16fcf5ef2aSThomas Huth #include "sysemu/dump.h"
17fcf5ef2aSThomas Huth #include "elf.h"
18fcf5ef2aSThomas Huth #include "sysemu/memory_mapping.h"
19fcf5ef2aSThomas Huth
2018a1f0d7SMarc-André Lureau #define ELF_NOTE_SIZE(hdr_size, name_size, desc_size) \
2118a1f0d7SMarc-André Lureau ((DIV_ROUND_UP((hdr_size), 4) \
2218a1f0d7SMarc-André Lureau + DIV_ROUND_UP((name_size), 4) \
2318a1f0d7SMarc-André Lureau + DIV_ROUND_UP((desc_size), 4)) * 4)
2418a1f0d7SMarc-André Lureau
25fcf5ef2aSThomas Huth #ifdef TARGET_X86_64
26fcf5ef2aSThomas Huth typedef struct {
27fcf5ef2aSThomas Huth target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10;
28fcf5ef2aSThomas Huth target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax;
29fcf5ef2aSThomas Huth target_ulong rip, cs, eflags;
30fcf5ef2aSThomas Huth target_ulong rsp, ss;
31fcf5ef2aSThomas Huth target_ulong fs_base, gs_base;
32fcf5ef2aSThomas Huth target_ulong ds, es, fs, gs;
33fcf5ef2aSThomas Huth } x86_64_user_regs_struct;
34fcf5ef2aSThomas Huth
35fcf5ef2aSThomas Huth typedef struct {
36fcf5ef2aSThomas Huth char pad1[32];
37fcf5ef2aSThomas Huth uint32_t pid;
38fcf5ef2aSThomas Huth char pad2[76];
39fcf5ef2aSThomas Huth x86_64_user_regs_struct regs;
40fcf5ef2aSThomas Huth char pad3[8];
41fcf5ef2aSThomas Huth } x86_64_elf_prstatus;
42fcf5ef2aSThomas Huth
x86_64_write_elf64_note(WriteCoreDumpFunction f,CPUX86State * env,int id,DumpState * s)43fcf5ef2aSThomas Huth static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
44fcf5ef2aSThomas Huth CPUX86State *env, int id,
45*1af0006aSJanosch Frank DumpState *s)
46fcf5ef2aSThomas Huth {
47fcf5ef2aSThomas Huth x86_64_user_regs_struct regs;
48fcf5ef2aSThomas Huth Elf64_Nhdr *note;
49fcf5ef2aSThomas Huth char *buf;
50fcf5ef2aSThomas Huth int descsz, note_size, name_size = 5;
51fcf5ef2aSThomas Huth const char *name = "CORE";
52fcf5ef2aSThomas Huth int ret;
53fcf5ef2aSThomas Huth
54fcf5ef2aSThomas Huth regs.r15 = env->regs[15];
55fcf5ef2aSThomas Huth regs.r14 = env->regs[14];
56fcf5ef2aSThomas Huth regs.r13 = env->regs[13];
57fcf5ef2aSThomas Huth regs.r12 = env->regs[12];
58fcf5ef2aSThomas Huth regs.r11 = env->regs[11];
59fcf5ef2aSThomas Huth regs.r10 = env->regs[10];
60fcf5ef2aSThomas Huth regs.r9 = env->regs[9];
61fcf5ef2aSThomas Huth regs.r8 = env->regs[8];
62fcf5ef2aSThomas Huth regs.rbp = env->regs[R_EBP];
63fcf5ef2aSThomas Huth regs.rsp = env->regs[R_ESP];
64fcf5ef2aSThomas Huth regs.rdi = env->regs[R_EDI];
65fcf5ef2aSThomas Huth regs.rsi = env->regs[R_ESI];
66fcf5ef2aSThomas Huth regs.rdx = env->regs[R_EDX];
67fcf5ef2aSThomas Huth regs.rcx = env->regs[R_ECX];
68fcf5ef2aSThomas Huth regs.rbx = env->regs[R_EBX];
69fcf5ef2aSThomas Huth regs.rax = env->regs[R_EAX];
70fcf5ef2aSThomas Huth regs.rip = env->eip;
71fcf5ef2aSThomas Huth regs.eflags = env->eflags;
72fcf5ef2aSThomas Huth
73fcf5ef2aSThomas Huth regs.orig_rax = 0; /* FIXME */
74fcf5ef2aSThomas Huth regs.cs = env->segs[R_CS].selector;
75fcf5ef2aSThomas Huth regs.ss = env->segs[R_SS].selector;
76fcf5ef2aSThomas Huth regs.fs_base = env->segs[R_FS].base;
77fcf5ef2aSThomas Huth regs.gs_base = env->segs[R_GS].base;
78fcf5ef2aSThomas Huth regs.ds = env->segs[R_DS].selector;
79fcf5ef2aSThomas Huth regs.es = env->segs[R_ES].selector;
80fcf5ef2aSThomas Huth regs.fs = env->segs[R_FS].selector;
81fcf5ef2aSThomas Huth regs.gs = env->segs[R_GS].selector;
82fcf5ef2aSThomas Huth
83fcf5ef2aSThomas Huth descsz = sizeof(x86_64_elf_prstatus);
8418a1f0d7SMarc-André Lureau note_size = ELF_NOTE_SIZE(sizeof(Elf64_Nhdr), name_size, descsz);
85fcf5ef2aSThomas Huth note = g_malloc0(note_size);
86fcf5ef2aSThomas Huth note->n_namesz = cpu_to_le32(name_size);
87fcf5ef2aSThomas Huth note->n_descsz = cpu_to_le32(descsz);
88fcf5ef2aSThomas Huth note->n_type = cpu_to_le32(NT_PRSTATUS);
89fcf5ef2aSThomas Huth buf = (char *)note;
9017fc7e93SMarc-André Lureau buf += ROUND_UP(sizeof(Elf64_Nhdr), 4);
91fcf5ef2aSThomas Huth memcpy(buf, name, name_size);
9217fc7e93SMarc-André Lureau buf += ROUND_UP(name_size, 4);
93fcf5ef2aSThomas Huth memcpy(buf + 32, &id, 4); /* pr_pid */
94fcf5ef2aSThomas Huth buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
95fcf5ef2aSThomas Huth memcpy(buf, ®s, sizeof(x86_64_user_regs_struct));
96fcf5ef2aSThomas Huth
97*1af0006aSJanosch Frank ret = f(note, note_size, s);
98fcf5ef2aSThomas Huth g_free(note);
99fcf5ef2aSThomas Huth if (ret < 0) {
100fcf5ef2aSThomas Huth return -1;
101fcf5ef2aSThomas Huth }
102fcf5ef2aSThomas Huth
103fcf5ef2aSThomas Huth return 0;
104fcf5ef2aSThomas Huth }
105fcf5ef2aSThomas Huth #endif
106fcf5ef2aSThomas Huth
107fcf5ef2aSThomas Huth typedef struct {
108fcf5ef2aSThomas Huth uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
109fcf5ef2aSThomas Huth unsigned short ds, __ds, es, __es;
110fcf5ef2aSThomas Huth unsigned short fs, __fs, gs, __gs;
111fcf5ef2aSThomas Huth uint32_t orig_eax, eip;
112fcf5ef2aSThomas Huth unsigned short cs, __cs;
113fcf5ef2aSThomas Huth uint32_t eflags, esp;
114fcf5ef2aSThomas Huth unsigned short ss, __ss;
115fcf5ef2aSThomas Huth } x86_user_regs_struct;
116fcf5ef2aSThomas Huth
117fcf5ef2aSThomas Huth typedef struct {
118fcf5ef2aSThomas Huth char pad1[24];
119fcf5ef2aSThomas Huth uint32_t pid;
120fcf5ef2aSThomas Huth char pad2[44];
121fcf5ef2aSThomas Huth x86_user_regs_struct regs;
122fcf5ef2aSThomas Huth char pad3[4];
123fcf5ef2aSThomas Huth } x86_elf_prstatus;
124fcf5ef2aSThomas Huth
x86_fill_elf_prstatus(x86_elf_prstatus * prstatus,CPUX86State * env,int id)125fcf5ef2aSThomas Huth static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env,
126fcf5ef2aSThomas Huth int id)
127fcf5ef2aSThomas Huth {
128fcf5ef2aSThomas Huth memset(prstatus, 0, sizeof(x86_elf_prstatus));
129fcf5ef2aSThomas Huth prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff;
130fcf5ef2aSThomas Huth prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff;
131fcf5ef2aSThomas Huth prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff;
132fcf5ef2aSThomas Huth prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff;
133fcf5ef2aSThomas Huth prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff;
134fcf5ef2aSThomas Huth prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff;
135fcf5ef2aSThomas Huth prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff;
136fcf5ef2aSThomas Huth prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff;
137fcf5ef2aSThomas Huth prstatus->regs.eip = env->eip & 0xffffffff;
138fcf5ef2aSThomas Huth prstatus->regs.eflags = env->eflags & 0xffffffff;
139fcf5ef2aSThomas Huth
140fcf5ef2aSThomas Huth prstatus->regs.cs = env->segs[R_CS].selector;
141fcf5ef2aSThomas Huth prstatus->regs.ss = env->segs[R_SS].selector;
142fcf5ef2aSThomas Huth prstatus->regs.ds = env->segs[R_DS].selector;
143fcf5ef2aSThomas Huth prstatus->regs.es = env->segs[R_ES].selector;
144fcf5ef2aSThomas Huth prstatus->regs.fs = env->segs[R_FS].selector;
145fcf5ef2aSThomas Huth prstatus->regs.gs = env->segs[R_GS].selector;
146fcf5ef2aSThomas Huth
147fcf5ef2aSThomas Huth prstatus->pid = id;
148fcf5ef2aSThomas Huth }
149fcf5ef2aSThomas Huth
x86_write_elf64_note(WriteCoreDumpFunction f,CPUX86State * env,int id,DumpState * s)150fcf5ef2aSThomas Huth static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
151*1af0006aSJanosch Frank int id, DumpState *s)
152fcf5ef2aSThomas Huth {
153fcf5ef2aSThomas Huth x86_elf_prstatus prstatus;
154fcf5ef2aSThomas Huth Elf64_Nhdr *note;
155fcf5ef2aSThomas Huth char *buf;
156fcf5ef2aSThomas Huth int descsz, note_size, name_size = 5;
157fcf5ef2aSThomas Huth const char *name = "CORE";
158fcf5ef2aSThomas Huth int ret;
159fcf5ef2aSThomas Huth
160fcf5ef2aSThomas Huth x86_fill_elf_prstatus(&prstatus, env, id);
161fcf5ef2aSThomas Huth descsz = sizeof(x86_elf_prstatus);
16218a1f0d7SMarc-André Lureau note_size = ELF_NOTE_SIZE(sizeof(Elf64_Nhdr), name_size, descsz);
163fcf5ef2aSThomas Huth note = g_malloc0(note_size);
164fcf5ef2aSThomas Huth note->n_namesz = cpu_to_le32(name_size);
165fcf5ef2aSThomas Huth note->n_descsz = cpu_to_le32(descsz);
166fcf5ef2aSThomas Huth note->n_type = cpu_to_le32(NT_PRSTATUS);
167fcf5ef2aSThomas Huth buf = (char *)note;
16817fc7e93SMarc-André Lureau buf += ROUND_UP(sizeof(Elf64_Nhdr), 4);
169fcf5ef2aSThomas Huth memcpy(buf, name, name_size);
17017fc7e93SMarc-André Lureau buf += ROUND_UP(name_size, 4);
171fcf5ef2aSThomas Huth memcpy(buf, &prstatus, sizeof(prstatus));
172fcf5ef2aSThomas Huth
173*1af0006aSJanosch Frank ret = f(note, note_size, s);
174fcf5ef2aSThomas Huth g_free(note);
175fcf5ef2aSThomas Huth if (ret < 0) {
176fcf5ef2aSThomas Huth return -1;
177fcf5ef2aSThomas Huth }
178fcf5ef2aSThomas Huth
179fcf5ef2aSThomas Huth return 0;
180fcf5ef2aSThomas Huth }
181fcf5ef2aSThomas Huth
x86_cpu_write_elf64_note(WriteCoreDumpFunction f,CPUState * cs,int cpuid,DumpState * s)182fcf5ef2aSThomas Huth int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
183*1af0006aSJanosch Frank int cpuid, DumpState *s)
184fcf5ef2aSThomas Huth {
185fcf5ef2aSThomas Huth X86CPU *cpu = X86_CPU(cs);
186fcf5ef2aSThomas Huth int ret;
187fcf5ef2aSThomas Huth #ifdef TARGET_X86_64
188fcf5ef2aSThomas Huth X86CPU *first_x86_cpu = X86_CPU(first_cpu);
189fcf5ef2aSThomas Huth bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
190fcf5ef2aSThomas Huth
191fcf5ef2aSThomas Huth if (lma) {
192*1af0006aSJanosch Frank ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, s);
193fcf5ef2aSThomas Huth } else {
194fcf5ef2aSThomas Huth #endif
195*1af0006aSJanosch Frank ret = x86_write_elf64_note(f, &cpu->env, cpuid, s);
196fcf5ef2aSThomas Huth #ifdef TARGET_X86_64
197fcf5ef2aSThomas Huth }
198fcf5ef2aSThomas Huth #endif
199fcf5ef2aSThomas Huth
200fcf5ef2aSThomas Huth return ret;
201fcf5ef2aSThomas Huth }
202fcf5ef2aSThomas Huth
x86_cpu_write_elf32_note(WriteCoreDumpFunction f,CPUState * cs,int cpuid,DumpState * s)203fcf5ef2aSThomas Huth int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
204*1af0006aSJanosch Frank int cpuid, DumpState *s)
205fcf5ef2aSThomas Huth {
206fcf5ef2aSThomas Huth X86CPU *cpu = X86_CPU(cs);
207fcf5ef2aSThomas Huth x86_elf_prstatus prstatus;
208fcf5ef2aSThomas Huth Elf32_Nhdr *note;
209fcf5ef2aSThomas Huth char *buf;
210fcf5ef2aSThomas Huth int descsz, note_size, name_size = 5;
211fcf5ef2aSThomas Huth const char *name = "CORE";
212fcf5ef2aSThomas Huth int ret;
213fcf5ef2aSThomas Huth
214fcf5ef2aSThomas Huth x86_fill_elf_prstatus(&prstatus, &cpu->env, cpuid);
215fcf5ef2aSThomas Huth descsz = sizeof(x86_elf_prstatus);
21618a1f0d7SMarc-André Lureau note_size = ELF_NOTE_SIZE(sizeof(Elf32_Nhdr), name_size, descsz);
217fcf5ef2aSThomas Huth note = g_malloc0(note_size);
218fcf5ef2aSThomas Huth note->n_namesz = cpu_to_le32(name_size);
219fcf5ef2aSThomas Huth note->n_descsz = cpu_to_le32(descsz);
220fcf5ef2aSThomas Huth note->n_type = cpu_to_le32(NT_PRSTATUS);
221fcf5ef2aSThomas Huth buf = (char *)note;
22217fc7e93SMarc-André Lureau buf += ROUND_UP(sizeof(Elf32_Nhdr), 4);
223fcf5ef2aSThomas Huth memcpy(buf, name, name_size);
22417fc7e93SMarc-André Lureau buf += ROUND_UP(name_size, 4);
225fcf5ef2aSThomas Huth memcpy(buf, &prstatus, sizeof(prstatus));
226fcf5ef2aSThomas Huth
227*1af0006aSJanosch Frank ret = f(note, note_size, s);
228fcf5ef2aSThomas Huth g_free(note);
229fcf5ef2aSThomas Huth if (ret < 0) {
230fcf5ef2aSThomas Huth return -1;
231fcf5ef2aSThomas Huth }
232fcf5ef2aSThomas Huth
233fcf5ef2aSThomas Huth return 0;
234fcf5ef2aSThomas Huth }
235fcf5ef2aSThomas Huth
236fcf5ef2aSThomas Huth /*
237fcf5ef2aSThomas Huth * please count up QEMUCPUSTATE_VERSION if you have changed definition of
238fcf5ef2aSThomas Huth * QEMUCPUState, and modify the tools using this information accordingly.
239fcf5ef2aSThomas Huth */
240fcf5ef2aSThomas Huth #define QEMUCPUSTATE_VERSION (1)
241fcf5ef2aSThomas Huth
242fcf5ef2aSThomas Huth struct QEMUCPUSegment {
243fcf5ef2aSThomas Huth uint32_t selector;
244fcf5ef2aSThomas Huth uint32_t limit;
245fcf5ef2aSThomas Huth uint32_t flags;
246fcf5ef2aSThomas Huth uint32_t pad;
247fcf5ef2aSThomas Huth uint64_t base;
248fcf5ef2aSThomas Huth };
249fcf5ef2aSThomas Huth
250fcf5ef2aSThomas Huth typedef struct QEMUCPUSegment QEMUCPUSegment;
251fcf5ef2aSThomas Huth
252fcf5ef2aSThomas Huth struct QEMUCPUState {
253fcf5ef2aSThomas Huth uint32_t version;
254fcf5ef2aSThomas Huth uint32_t size;
255fcf5ef2aSThomas Huth uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
256fcf5ef2aSThomas Huth uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
257fcf5ef2aSThomas Huth uint64_t rip, rflags;
258fcf5ef2aSThomas Huth QEMUCPUSegment cs, ds, es, fs, gs, ss;
259fcf5ef2aSThomas Huth QEMUCPUSegment ldt, tr, gdt, idt;
260fcf5ef2aSThomas Huth uint64_t cr[5];
26146fac17dSViktor Prutyanov /*
26246fac17dSViktor Prutyanov * Fields below are optional and are being added at the end without
26346fac17dSViktor Prutyanov * changing the version. External tools may identify their presence
26446fac17dSViktor Prutyanov * by checking 'size' field.
26546fac17dSViktor Prutyanov */
26646fac17dSViktor Prutyanov uint64_t kernel_gs_base;
267fcf5ef2aSThomas Huth };
268fcf5ef2aSThomas Huth
269fcf5ef2aSThomas Huth typedef struct QEMUCPUState QEMUCPUState;
270fcf5ef2aSThomas Huth
copy_segment(QEMUCPUSegment * d,SegmentCache * s)271fcf5ef2aSThomas Huth static void copy_segment(QEMUCPUSegment *d, SegmentCache *s)
272fcf5ef2aSThomas Huth {
273fcf5ef2aSThomas Huth d->pad = 0;
274fcf5ef2aSThomas Huth d->selector = s->selector;
275fcf5ef2aSThomas Huth d->limit = s->limit;
276fcf5ef2aSThomas Huth d->flags = s->flags;
277fcf5ef2aSThomas Huth d->base = s->base;
278fcf5ef2aSThomas Huth }
279fcf5ef2aSThomas Huth
qemu_get_cpustate(QEMUCPUState * s,CPUX86State * env)280fcf5ef2aSThomas Huth static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env)
281fcf5ef2aSThomas Huth {
282fcf5ef2aSThomas Huth memset(s, 0, sizeof(QEMUCPUState));
283fcf5ef2aSThomas Huth
284fcf5ef2aSThomas Huth s->version = QEMUCPUSTATE_VERSION;
285fcf5ef2aSThomas Huth s->size = sizeof(QEMUCPUState);
286fcf5ef2aSThomas Huth
287fcf5ef2aSThomas Huth s->rax = env->regs[R_EAX];
288fcf5ef2aSThomas Huth s->rbx = env->regs[R_EBX];
289fcf5ef2aSThomas Huth s->rcx = env->regs[R_ECX];
290fcf5ef2aSThomas Huth s->rdx = env->regs[R_EDX];
291fcf5ef2aSThomas Huth s->rsi = env->regs[R_ESI];
292fcf5ef2aSThomas Huth s->rdi = env->regs[R_EDI];
293fcf5ef2aSThomas Huth s->rsp = env->regs[R_ESP];
294fcf5ef2aSThomas Huth s->rbp = env->regs[R_EBP];
295fcf5ef2aSThomas Huth #ifdef TARGET_X86_64
296fcf5ef2aSThomas Huth s->r8 = env->regs[8];
297fcf5ef2aSThomas Huth s->r9 = env->regs[9];
298fcf5ef2aSThomas Huth s->r10 = env->regs[10];
299fcf5ef2aSThomas Huth s->r11 = env->regs[11];
300fcf5ef2aSThomas Huth s->r12 = env->regs[12];
301fcf5ef2aSThomas Huth s->r13 = env->regs[13];
302fcf5ef2aSThomas Huth s->r14 = env->regs[14];
303fcf5ef2aSThomas Huth s->r15 = env->regs[15];
304fcf5ef2aSThomas Huth #endif
305fcf5ef2aSThomas Huth s->rip = env->eip;
306fcf5ef2aSThomas Huth s->rflags = env->eflags;
307fcf5ef2aSThomas Huth
308fcf5ef2aSThomas Huth copy_segment(&s->cs, &env->segs[R_CS]);
309fcf5ef2aSThomas Huth copy_segment(&s->ds, &env->segs[R_DS]);
310fcf5ef2aSThomas Huth copy_segment(&s->es, &env->segs[R_ES]);
311fcf5ef2aSThomas Huth copy_segment(&s->fs, &env->segs[R_FS]);
312fcf5ef2aSThomas Huth copy_segment(&s->gs, &env->segs[R_GS]);
313fcf5ef2aSThomas Huth copy_segment(&s->ss, &env->segs[R_SS]);
314fcf5ef2aSThomas Huth copy_segment(&s->ldt, &env->ldt);
315fcf5ef2aSThomas Huth copy_segment(&s->tr, &env->tr);
316fcf5ef2aSThomas Huth copy_segment(&s->gdt, &env->gdt);
317fcf5ef2aSThomas Huth copy_segment(&s->idt, &env->idt);
318fcf5ef2aSThomas Huth
319fcf5ef2aSThomas Huth s->cr[0] = env->cr[0];
320fcf5ef2aSThomas Huth s->cr[1] = env->cr[1];
321fcf5ef2aSThomas Huth s->cr[2] = env->cr[2];
322fcf5ef2aSThomas Huth s->cr[3] = env->cr[3];
323fcf5ef2aSThomas Huth s->cr[4] = env->cr[4];
32446fac17dSViktor Prutyanov
32546fac17dSViktor Prutyanov #ifdef TARGET_X86_64
32646fac17dSViktor Prutyanov s->kernel_gs_base = env->kernelgsbase;
32746fac17dSViktor Prutyanov #endif
328fcf5ef2aSThomas Huth }
329fcf5ef2aSThomas Huth
cpu_write_qemu_note(WriteCoreDumpFunction f,CPUX86State * env,DumpState * s,int type)330fcf5ef2aSThomas Huth static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
331fcf5ef2aSThomas Huth CPUX86State *env,
332*1af0006aSJanosch Frank DumpState *s,
333fcf5ef2aSThomas Huth int type)
334fcf5ef2aSThomas Huth {
335fcf5ef2aSThomas Huth QEMUCPUState state;
336fcf5ef2aSThomas Huth Elf64_Nhdr *note64;
337fcf5ef2aSThomas Huth Elf32_Nhdr *note32;
338fcf5ef2aSThomas Huth void *note;
339fcf5ef2aSThomas Huth char *buf;
340fcf5ef2aSThomas Huth int descsz, note_size, name_size = 5, note_head_size;
341fcf5ef2aSThomas Huth const char *name = "QEMU";
342fcf5ef2aSThomas Huth int ret;
343fcf5ef2aSThomas Huth
344fcf5ef2aSThomas Huth qemu_get_cpustate(&state, env);
345fcf5ef2aSThomas Huth
346fcf5ef2aSThomas Huth descsz = sizeof(state);
347fcf5ef2aSThomas Huth if (type == 0) {
348fcf5ef2aSThomas Huth note_head_size = sizeof(Elf32_Nhdr);
349fcf5ef2aSThomas Huth } else {
350fcf5ef2aSThomas Huth note_head_size = sizeof(Elf64_Nhdr);
351fcf5ef2aSThomas Huth }
352074d5afeSMarc-André Lureau note_size = (DIV_ROUND_UP(note_head_size, 4) + DIV_ROUND_UP(name_size, 4) +
353074d5afeSMarc-André Lureau DIV_ROUND_UP(descsz, 4)) * 4;
354fcf5ef2aSThomas Huth note = g_malloc0(note_size);
355fcf5ef2aSThomas Huth if (type == 0) {
356fcf5ef2aSThomas Huth note32 = note;
357fcf5ef2aSThomas Huth note32->n_namesz = cpu_to_le32(name_size);
358fcf5ef2aSThomas Huth note32->n_descsz = cpu_to_le32(descsz);
359fcf5ef2aSThomas Huth note32->n_type = 0;
360fcf5ef2aSThomas Huth } else {
361fcf5ef2aSThomas Huth note64 = note;
362fcf5ef2aSThomas Huth note64->n_namesz = cpu_to_le32(name_size);
363fcf5ef2aSThomas Huth note64->n_descsz = cpu_to_le32(descsz);
364fcf5ef2aSThomas Huth note64->n_type = 0;
365fcf5ef2aSThomas Huth }
366fcf5ef2aSThomas Huth buf = note;
36717fc7e93SMarc-André Lureau buf += ROUND_UP(note_head_size, 4);
368fcf5ef2aSThomas Huth memcpy(buf, name, name_size);
36917fc7e93SMarc-André Lureau buf += ROUND_UP(name_size, 4);
370fcf5ef2aSThomas Huth memcpy(buf, &state, sizeof(state));
371fcf5ef2aSThomas Huth
372*1af0006aSJanosch Frank ret = f(note, note_size, s);
373fcf5ef2aSThomas Huth g_free(note);
374fcf5ef2aSThomas Huth if (ret < 0) {
375fcf5ef2aSThomas Huth return -1;
376fcf5ef2aSThomas Huth }
377fcf5ef2aSThomas Huth
378fcf5ef2aSThomas Huth return 0;
379fcf5ef2aSThomas Huth }
380fcf5ef2aSThomas Huth
x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,CPUState * cs,DumpState * s)381fcf5ef2aSThomas Huth int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs,
382*1af0006aSJanosch Frank DumpState *s)
383fcf5ef2aSThomas Huth {
384fcf5ef2aSThomas Huth X86CPU *cpu = X86_CPU(cs);
385fcf5ef2aSThomas Huth
386*1af0006aSJanosch Frank return cpu_write_qemu_note(f, &cpu->env, s, 1);
387fcf5ef2aSThomas Huth }
388fcf5ef2aSThomas Huth
x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f,CPUState * cs,DumpState * s)389fcf5ef2aSThomas Huth int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
390*1af0006aSJanosch Frank DumpState *s)
391fcf5ef2aSThomas Huth {
392fcf5ef2aSThomas Huth X86CPU *cpu = X86_CPU(cs);
393fcf5ef2aSThomas Huth
394*1af0006aSJanosch Frank return cpu_write_qemu_note(f, &cpu->env, s, 0);
395fcf5ef2aSThomas Huth }
396fcf5ef2aSThomas Huth
cpu_get_dump_info(ArchDumpInfo * info,const GuestPhysBlockList * guest_phys_blocks)397fcf5ef2aSThomas Huth int cpu_get_dump_info(ArchDumpInfo *info,
398fcf5ef2aSThomas Huth const GuestPhysBlockList *guest_phys_blocks)
399fcf5ef2aSThomas Huth {
400fcf5ef2aSThomas Huth bool lma = false;
401fcf5ef2aSThomas Huth GuestPhysBlock *block;
402fcf5ef2aSThomas Huth
403fcf5ef2aSThomas Huth #ifdef TARGET_X86_64
404fcf5ef2aSThomas Huth X86CPU *first_x86_cpu = X86_CPU(first_cpu);
405fd5d23baSIwona Kotlarska lma = first_cpu && (first_x86_cpu->env.hflags & HF_LMA_MASK);
406fcf5ef2aSThomas Huth #endif
407fcf5ef2aSThomas Huth
408fcf5ef2aSThomas Huth if (lma) {
409fcf5ef2aSThomas Huth info->d_machine = EM_X86_64;
410fcf5ef2aSThomas Huth } else {
411fcf5ef2aSThomas Huth info->d_machine = EM_386;
412fcf5ef2aSThomas Huth }
413fcf5ef2aSThomas Huth info->d_endian = ELFDATA2LSB;
414fcf5ef2aSThomas Huth
415fcf5ef2aSThomas Huth if (lma) {
416fcf5ef2aSThomas Huth info->d_class = ELFCLASS64;
417fcf5ef2aSThomas Huth } else {
418fcf5ef2aSThomas Huth info->d_class = ELFCLASS32;
419fcf5ef2aSThomas Huth
420fcf5ef2aSThomas Huth QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
421fcf5ef2aSThomas Huth if (block->target_end > UINT_MAX) {
422fcf5ef2aSThomas Huth /* The memory size is greater than 4G */
423fcf5ef2aSThomas Huth info->d_class = ELFCLASS64;
424fcf5ef2aSThomas Huth break;
425fcf5ef2aSThomas Huth }
426fcf5ef2aSThomas Huth }
427fcf5ef2aSThomas Huth }
428fcf5ef2aSThomas Huth
429fcf5ef2aSThomas Huth return 0;
430fcf5ef2aSThomas Huth }
431fcf5ef2aSThomas Huth
cpu_get_note_size(int class,int machine,int nr_cpus)432fcf5ef2aSThomas Huth ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
433fcf5ef2aSThomas Huth {
434fcf5ef2aSThomas Huth int name_size = 5; /* "CORE" or "QEMU" */
435fcf5ef2aSThomas Huth size_t elf_note_size = 0;
436fcf5ef2aSThomas Huth size_t qemu_note_size = 0;
437fcf5ef2aSThomas Huth int elf_desc_size = 0;
438fcf5ef2aSThomas Huth int qemu_desc_size = 0;
439fcf5ef2aSThomas Huth int note_head_size;
440fcf5ef2aSThomas Huth
441fcf5ef2aSThomas Huth if (class == ELFCLASS32) {
442fcf5ef2aSThomas Huth note_head_size = sizeof(Elf32_Nhdr);
443fcf5ef2aSThomas Huth } else {
444fcf5ef2aSThomas Huth note_head_size = sizeof(Elf64_Nhdr);
445fcf5ef2aSThomas Huth }
446fcf5ef2aSThomas Huth
447fcf5ef2aSThomas Huth if (machine == EM_386) {
448fcf5ef2aSThomas Huth elf_desc_size = sizeof(x86_elf_prstatus);
449fcf5ef2aSThomas Huth }
450fcf5ef2aSThomas Huth #ifdef TARGET_X86_64
451fcf5ef2aSThomas Huth else {
452fcf5ef2aSThomas Huth elf_desc_size = sizeof(x86_64_elf_prstatus);
453fcf5ef2aSThomas Huth }
454fcf5ef2aSThomas Huth #endif
455fcf5ef2aSThomas Huth qemu_desc_size = sizeof(QEMUCPUState);
456fcf5ef2aSThomas Huth
45718a1f0d7SMarc-André Lureau elf_note_size = ELF_NOTE_SIZE(note_head_size, name_size, elf_desc_size);
45818a1f0d7SMarc-André Lureau qemu_note_size = ELF_NOTE_SIZE(note_head_size, name_size, qemu_desc_size);
459fcf5ef2aSThomas Huth
460fcf5ef2aSThomas Huth return (elf_note_size + qemu_note_size) * nr_cpus;
461fcf5ef2aSThomas Huth }
462