xref: /openbmc/qemu/target/i386/arch_dump.c (revision 42e1e350bffc8d4614e568a03380b2ec34a131bf)
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, &regs, 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