]> git.proxmox.com Git - qemu.git/blame - target-i386/helper.c
Add "broadcast" option for mce command
[qemu.git] / target-i386 / helper.c
CommitLineData
2c0262af 1/*
eaa728ee 2 * i386 helpers (without register variable usage)
5fafdf24 3 *
2c0262af
FB
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2c0262af 18 */
eaa728ee
FB
19#include <stdarg.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <inttypes.h>
24#include <signal.h>
2c0262af 25
eaa728ee
FB
26#include "cpu.h"
27#include "exec-all.h"
eaa728ee 28#include "qemu-common.h"
7ba1e619 29#include "kvm.h"
e7701825 30#include "kvm_x86.h"
f3f2d9be 31
eaa728ee 32//#define DEBUG_MMU
b5ec5ce0 33
eaa728ee
FB
34/* NOTE: must be called outside the CPU execute loop */
35void cpu_reset(CPUX86State *env)
7e84c249 36{
eaa728ee 37 int i;
7e84c249 38
eca1bdf4
AL
39 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
40 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
41 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
42 }
43
eaa728ee 44 memset(env, 0, offsetof(CPUX86State, breakpoints));
7e84c249 45
eaa728ee 46 tlb_flush(env, 1);
7e84c249 47
eaa728ee 48 env->old_exception = -1;
7e84c249 49
eaa728ee 50 /* init to reset state */
3b46e624 51
eaa728ee
FB
52#ifdef CONFIG_SOFTMMU
53 env->hflags |= HF_SOFTMMU_MASK;
2c0262af 54#endif
db620f46 55 env->hflags2 |= HF2_GIF_MASK;
2c0262af 56
eaa728ee
FB
57 cpu_x86_update_cr0(env, 0x60000010);
58 env->a20_mask = ~0x0;
59 env->smbase = 0x30000;
7e84c249 60
eaa728ee
FB
61 env->idt.limit = 0xffff;
62 env->gdt.limit = 0xffff;
63 env->ldt.limit = 0xffff;
262ffdae 64 env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
eaa728ee 65 env->tr.limit = 0xffff;
23e6c399 66 env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
262ffdae
FB
67
68 cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
538f3686
NK
69 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
70 DESC_R_MASK | DESC_A_MASK);
262ffdae 71 cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
538f3686
NK
72 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
73 DESC_A_MASK);
262ffdae 74 cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
538f3686
NK
75 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
76 DESC_A_MASK);
262ffdae 77 cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
538f3686
NK
78 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
79 DESC_A_MASK);
262ffdae 80 cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
538f3686
NK
81 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
82 DESC_A_MASK);
262ffdae 83 cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
538f3686
NK
84 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
85 DESC_A_MASK);
7e84c249 86
eaa728ee
FB
87 env->eip = 0xfff0;
88 env->regs[R_EDX] = env->cpuid_version;
2c0262af 89
eaa728ee 90 env->eflags = 0x2;
7e84c249 91
eaa728ee
FB
92 /* FPU init */
93 for(i = 0;i < 8; i++)
94 env->fptags[i] = 1;
95 env->fpuc = 0x37f;
7e84c249 96
eaa728ee 97 env->mxcsr = 0x1f80;
01df040b
AL
98
99 memset(env->dr, 0, sizeof(env->dr));
100 env->dr[6] = DR6_FIXED_1;
101 env->dr[7] = DR7_FIXED_1;
102 cpu_breakpoint_remove_all(env, BP_CPU);
103 cpu_watchpoint_remove_all(env, BP_CPU);
af364b41
HY
104
105 env->mcg_status = 0;
eaa728ee 106}
7e84c249 107
eaa728ee
FB
108void cpu_x86_close(CPUX86State *env)
109{
bb332cb2 110 qemu_free(env);
eaa728ee 111}
7e84c249 112
eaa728ee
FB
113/***********************************************************/
114/* x86 debug */
3b46e624 115
eaa728ee
FB
116static const char *cc_op_str[] = {
117 "DYNAMIC",
118 "EFLAGS",
7e84c249 119
eaa728ee
FB
120 "MULB",
121 "MULW",
122 "MULL",
123 "MULQ",
3b46e624 124
eaa728ee
FB
125 "ADDB",
126 "ADDW",
127 "ADDL",
128 "ADDQ",
3b46e624 129
eaa728ee
FB
130 "ADCB",
131 "ADCW",
132 "ADCL",
133 "ADCQ",
3b46e624 134
eaa728ee
FB
135 "SUBB",
136 "SUBW",
137 "SUBL",
138 "SUBQ",
7e84c249 139
eaa728ee
FB
140 "SBBB",
141 "SBBW",
142 "SBBL",
143 "SBBQ",
7e84c249 144
eaa728ee
FB
145 "LOGICB",
146 "LOGICW",
147 "LOGICL",
148 "LOGICQ",
7e84c249 149
eaa728ee
FB
150 "INCB",
151 "INCW",
152 "INCL",
153 "INCQ",
3b46e624 154
eaa728ee
FB
155 "DECB",
156 "DECW",
157 "DECL",
158 "DECQ",
3b46e624 159
eaa728ee
FB
160 "SHLB",
161 "SHLW",
162 "SHLL",
163 "SHLQ",
3b46e624 164
eaa728ee
FB
165 "SARB",
166 "SARW",
167 "SARL",
168 "SARQ",
169};
7e84c249 170
a3867ed2 171static void
9a78eead 172cpu_x86_dump_seg_cache(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
a3867ed2
AL
173 const char *name, struct SegmentCache *sc)
174{
175#ifdef TARGET_X86_64
176 if (env->hflags & HF_CS64_MASK) {
177 cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
4058fd98 178 sc->selector, sc->base, sc->limit, sc->flags & 0x00ffff00);
a3867ed2
AL
179 } else
180#endif
181 {
182 cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
4058fd98 183 (uint32_t)sc->base, sc->limit, sc->flags & 0x00ffff00);
a3867ed2
AL
184 }
185
186 if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
187 goto done;
188
189 cpu_fprintf(f, " DPL=%d ", (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
190 if (sc->flags & DESC_S_MASK) {
191 if (sc->flags & DESC_CS_MASK) {
192 cpu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
193 ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
194 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
195 (sc->flags & DESC_R_MASK) ? 'R' : '-');
196 } else {
197 cpu_fprintf(f, (sc->flags & DESC_B_MASK) ? "DS " : "DS16");
198 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
199 (sc->flags & DESC_W_MASK) ? 'W' : '-');
200 }
201 cpu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
202 } else {
203 static const char *sys_type_name[2][16] = {
204 { /* 32 bit mode */
205 "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
206 "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
207 "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
208 "CallGate32", "Reserved", "IntGate32", "TrapGate32"
209 },
210 { /* 64 bit mode */
211 "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
212 "Reserved", "Reserved", "Reserved", "Reserved",
213 "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
214 "Reserved", "IntGate64", "TrapGate64"
215 }
216 };
e5c15eff
SW
217 cpu_fprintf(f, "%s",
218 sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
219 [(sc->flags & DESC_TYPE_MASK)
220 >> DESC_TYPE_SHIFT]);
a3867ed2
AL
221 }
222done:
223 cpu_fprintf(f, "\n");
224}
225
9a78eead 226void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
eaa728ee
FB
227 int flags)
228{
229 int eflags, i, nb;
230 char cc_op_name[32];
231 static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
7e84c249 232
23054111 233 cpu_synchronize_state(env);
ff3c01ca 234
eaa728ee
FB
235 eflags = env->eflags;
236#ifdef TARGET_X86_64
237 if (env->hflags & HF_CS64_MASK) {
238 cpu_fprintf(f,
239 "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
240 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
241 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
242 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
243 "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
244 env->regs[R_EAX],
245 env->regs[R_EBX],
246 env->regs[R_ECX],
247 env->regs[R_EDX],
248 env->regs[R_ESI],
249 env->regs[R_EDI],
250 env->regs[R_EBP],
251 env->regs[R_ESP],
252 env->regs[8],
253 env->regs[9],
254 env->regs[10],
255 env->regs[11],
256 env->regs[12],
257 env->regs[13],
258 env->regs[14],
259 env->regs[15],
260 env->eip, eflags,
261 eflags & DF_MASK ? 'D' : '-',
262 eflags & CC_O ? 'O' : '-',
263 eflags & CC_S ? 'S' : '-',
264 eflags & CC_Z ? 'Z' : '-',
265 eflags & CC_A ? 'A' : '-',
266 eflags & CC_P ? 'P' : '-',
267 eflags & CC_C ? 'C' : '-',
268 env->hflags & HF_CPL_MASK,
269 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
5ee0ffaa 270 (env->a20_mask >> 20) & 1,
eaa728ee 271 (env->hflags >> HF_SMM_SHIFT) & 1,
ce5232c5 272 env->halted);
eaa728ee
FB
273 } else
274#endif
275 {
276 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
277 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
278 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
279 (uint32_t)env->regs[R_EAX],
280 (uint32_t)env->regs[R_EBX],
281 (uint32_t)env->regs[R_ECX],
282 (uint32_t)env->regs[R_EDX],
283 (uint32_t)env->regs[R_ESI],
284 (uint32_t)env->regs[R_EDI],
285 (uint32_t)env->regs[R_EBP],
286 (uint32_t)env->regs[R_ESP],
287 (uint32_t)env->eip, eflags,
288 eflags & DF_MASK ? 'D' : '-',
289 eflags & CC_O ? 'O' : '-',
290 eflags & CC_S ? 'S' : '-',
291 eflags & CC_Z ? 'Z' : '-',
292 eflags & CC_A ? 'A' : '-',
293 eflags & CC_P ? 'P' : '-',
294 eflags & CC_C ? 'C' : '-',
295 env->hflags & HF_CPL_MASK,
296 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
5ee0ffaa 297 (env->a20_mask >> 20) & 1,
eaa728ee 298 (env->hflags >> HF_SMM_SHIFT) & 1,
ce5232c5 299 env->halted);
8145122b 300 }
3b46e624 301
a3867ed2
AL
302 for(i = 0; i < 6; i++) {
303 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, seg_name[i],
304 &env->segs[i]);
305 }
306 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "LDT", &env->ldt);
307 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "TR", &env->tr);
308
eaa728ee
FB
309#ifdef TARGET_X86_64
310 if (env->hflags & HF_LMA_MASK) {
eaa728ee
FB
311 cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
312 env->gdt.base, env->gdt.limit);
313 cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
314 env->idt.base, env->idt.limit);
315 cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
316 (uint32_t)env->cr[0],
317 env->cr[2],
318 env->cr[3],
319 (uint32_t)env->cr[4]);
a59cb4e0
AL
320 for(i = 0; i < 4; i++)
321 cpu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
322 cpu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
d4b55be5 323 env->dr[6], env->dr[7]);
eaa728ee
FB
324 } else
325#endif
326 {
eaa728ee
FB
327 cpu_fprintf(f, "GDT= %08x %08x\n",
328 (uint32_t)env->gdt.base, env->gdt.limit);
329 cpu_fprintf(f, "IDT= %08x %08x\n",
330 (uint32_t)env->idt.base, env->idt.limit);
331 cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
332 (uint32_t)env->cr[0],
333 (uint32_t)env->cr[2],
334 (uint32_t)env->cr[3],
335 (uint32_t)env->cr[4]);
9a78eead
SW
336 for(i = 0; i < 4; i++) {
337 cpu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
338 }
339 cpu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
340 env->dr[6], env->dr[7]);
eaa728ee
FB
341 }
342 if (flags & X86_DUMP_CCOP) {
343 if ((unsigned)env->cc_op < CC_OP_NB)
344 snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
345 else
346 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
347#ifdef TARGET_X86_64
348 if (env->hflags & HF_CS64_MASK) {
349 cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
350 env->cc_src, env->cc_dst,
351 cc_op_name);
352 } else
353#endif
354 {
355 cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
356 (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
357 cc_op_name);
358 }
7e84c249 359 }
b5e5a934 360 cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
eaa728ee
FB
361 if (flags & X86_DUMP_FPU) {
362 int fptag;
363 fptag = 0;
364 for(i = 0; i < 8; i++) {
365 fptag |= ((!env->fptags[i]) << i);
366 }
367 cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
368 env->fpuc,
369 (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
370 env->fpstt,
371 fptag,
372 env->mxcsr);
373 for(i=0;i<8;i++) {
374#if defined(USE_X86LDOUBLE)
375 union {
376 long double d;
377 struct {
378 uint64_t lower;
379 uint16_t upper;
380 } l;
381 } tmp;
382 tmp.d = env->fpregs[i].d;
383 cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
384 i, tmp.l.lower, tmp.l.upper);
385#else
386 cpu_fprintf(f, "FPR%d=%016" PRIx64,
387 i, env->fpregs[i].mmx.q);
388#endif
389 if ((i & 1) == 1)
390 cpu_fprintf(f, "\n");
391 else
392 cpu_fprintf(f, " ");
393 }
394 if (env->hflags & HF_CS64_MASK)
395 nb = 16;
396 else
397 nb = 8;
398 for(i=0;i<nb;i++) {
399 cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
400 i,
401 env->xmm_regs[i].XMM_L(3),
402 env->xmm_regs[i].XMM_L(2),
403 env->xmm_regs[i].XMM_L(1),
404 env->xmm_regs[i].XMM_L(0));
405 if ((i & 1) == 1)
406 cpu_fprintf(f, "\n");
407 else
408 cpu_fprintf(f, " ");
409 }
7e84c249 410 }
2c0262af 411}
7e84c249 412
eaa728ee
FB
413/***********************************************************/
414/* x86 mmu */
415/* XXX: add PGE support */
416
417void cpu_x86_set_a20(CPUX86State *env, int a20_state)
2c0262af 418{
eaa728ee
FB
419 a20_state = (a20_state != 0);
420 if (a20_state != ((env->a20_mask >> 20) & 1)) {
421#if defined(DEBUG_MMU)
422 printf("A20 update: a20=%d\n", a20_state);
423#endif
424 /* if the cpu is currently executing code, we must unlink it and
425 all the potentially executing TB */
426 cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
3b46e624 427
eaa728ee
FB
428 /* when a20 is changed, all the MMU mappings are invalid, so
429 we must flush everything */
430 tlb_flush(env, 1);
5ee0ffaa 431 env->a20_mask = ~(1 << 20) | (a20_state << 20);
7e84c249 432 }
2c0262af
FB
433}
434
eaa728ee 435void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
2c0262af 436{
eaa728ee 437 int pe_state;
2c0262af 438
eaa728ee
FB
439#if defined(DEBUG_MMU)
440 printf("CR0 update: CR0=0x%08x\n", new_cr0);
441#endif
442 if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
443 (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
444 tlb_flush(env, 1);
445 }
2c0262af 446
eaa728ee
FB
447#ifdef TARGET_X86_64
448 if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
449 (env->efer & MSR_EFER_LME)) {
450 /* enter in long mode */
451 /* XXX: generate an exception */
452 if (!(env->cr[4] & CR4_PAE_MASK))
453 return;
454 env->efer |= MSR_EFER_LMA;
455 env->hflags |= HF_LMA_MASK;
456 } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
457 (env->efer & MSR_EFER_LMA)) {
458 /* exit long mode */
459 env->efer &= ~MSR_EFER_LMA;
460 env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
461 env->eip &= 0xffffffff;
462 }
463#endif
464 env->cr[0] = new_cr0 | CR0_ET_MASK;
7e84c249 465
eaa728ee
FB
466 /* update PE flag in hidden flags */
467 pe_state = (env->cr[0] & CR0_PE_MASK);
468 env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
469 /* ensure that ADDSEG is always set in real mode */
470 env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
471 /* update FPU flags */
472 env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
473 ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
7e84c249
FB
474}
475
eaa728ee
FB
476/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
477 the PDPT */
478void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
7e84c249 479{
eaa728ee
FB
480 env->cr[3] = new_cr3;
481 if (env->cr[0] & CR0_PG_MASK) {
482#if defined(DEBUG_MMU)
483 printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
484#endif
485 tlb_flush(env, 0);
486 }
7e84c249
FB
487}
488
eaa728ee 489void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
7e84c249 490{
eaa728ee
FB
491#if defined(DEBUG_MMU)
492 printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
493#endif
494 if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
495 (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
496 tlb_flush(env, 1);
497 }
498 /* SSE handling */
499 if (!(env->cpuid_features & CPUID_SSE))
500 new_cr4 &= ~CR4_OSFXSR_MASK;
501 if (new_cr4 & CR4_OSFXSR_MASK)
502 env->hflags |= HF_OSFXSR_MASK;
503 else
504 env->hflags &= ~HF_OSFXSR_MASK;
b8b6a50b 505
eaa728ee 506 env->cr[4] = new_cr4;
b8b6a50b
FB
507}
508
eaa728ee
FB
509#if defined(CONFIG_USER_ONLY)
510
511int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
512 int is_write, int mmu_idx, int is_softmmu)
b8b6a50b 513{
eaa728ee
FB
514 /* user mode only emulation */
515 is_write &= 1;
516 env->cr[2] = addr;
517 env->error_code = (is_write << PG_ERROR_W_BIT);
518 env->error_code |= PG_ERROR_U_MASK;
519 env->exception_index = EXCP0E_PAGE;
520 return 1;
2c0262af
FB
521}
522
8d7b0fbb 523#else
891b38e4 524
eaa728ee
FB
525/* XXX: This value should match the one returned by CPUID
526 * and in exec.c */
eaa728ee 527# if defined(TARGET_X86_64)
2c90d794 528# define PHYS_ADDR_MASK 0xfffffff000LL
eaa728ee 529# else
2c90d794 530# define PHYS_ADDR_MASK 0xffffff000LL
eaa728ee 531# endif
eaa728ee
FB
532
533/* return value:
534 -1 = cannot handle fault
535 0 = nothing more to do
536 1 = generate PF fault
eaa728ee
FB
537*/
538int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
539 int is_write1, int mmu_idx, int is_softmmu)
540{
541 uint64_t ptep, pte;
542 target_ulong pde_addr, pte_addr;
d4c430a8 543 int error_code, is_dirty, prot, page_size, is_write, is_user;
c227f099 544 target_phys_addr_t paddr;
eaa728ee
FB
545 uint32_t page_offset;
546 target_ulong vaddr, virt_addr;
547
548 is_user = mmu_idx == MMU_USER_IDX;
549#if defined(DEBUG_MMU)
550 printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
551 addr, is_write1, is_user, env->eip);
552#endif
553 is_write = is_write1 & 1;
554
555 if (!(env->cr[0] & CR0_PG_MASK)) {
556 pte = addr;
557 virt_addr = addr & TARGET_PAGE_MASK;
558 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
559 page_size = 4096;
560 goto do_mapping;
561 }
562
563 if (env->cr[4] & CR4_PAE_MASK) {
564 uint64_t pde, pdpe;
565 target_ulong pdpe_addr;
2c0262af 566
eaa728ee
FB
567#ifdef TARGET_X86_64
568 if (env->hflags & HF_LMA_MASK) {
569 uint64_t pml4e_addr, pml4e;
570 int32_t sext;
571
572 /* test virtual address sign extension */
573 sext = (int64_t)addr >> 47;
574 if (sext != 0 && sext != -1) {
575 env->error_code = 0;
576 env->exception_index = EXCP0D_GPF;
577 return 1;
578 }
0573fbfc 579
eaa728ee
FB
580 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
581 env->a20_mask;
582 pml4e = ldq_phys(pml4e_addr);
583 if (!(pml4e & PG_PRESENT_MASK)) {
584 error_code = 0;
585 goto do_fault;
586 }
587 if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
588 error_code = PG_ERROR_RSVD_MASK;
589 goto do_fault;
590 }
591 if (!(pml4e & PG_ACCESSED_MASK)) {
592 pml4e |= PG_ACCESSED_MASK;
593 stl_phys_notdirty(pml4e_addr, pml4e);
594 }
595 ptep = pml4e ^ PG_NX_MASK;
596 pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
597 env->a20_mask;
598 pdpe = ldq_phys(pdpe_addr);
599 if (!(pdpe & PG_PRESENT_MASK)) {
600 error_code = 0;
601 goto do_fault;
602 }
603 if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
604 error_code = PG_ERROR_RSVD_MASK;
605 goto do_fault;
606 }
607 ptep &= pdpe ^ PG_NX_MASK;
608 if (!(pdpe & PG_ACCESSED_MASK)) {
609 pdpe |= PG_ACCESSED_MASK;
610 stl_phys_notdirty(pdpe_addr, pdpe);
611 }
612 } else
613#endif
614 {
615 /* XXX: load them when cr3 is loaded ? */
616 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
617 env->a20_mask;
618 pdpe = ldq_phys(pdpe_addr);
619 if (!(pdpe & PG_PRESENT_MASK)) {
620 error_code = 0;
621 goto do_fault;
622 }
623 ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
7e84c249 624 }
7e84c249 625
eaa728ee
FB
626 pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
627 env->a20_mask;
628 pde = ldq_phys(pde_addr);
629 if (!(pde & PG_PRESENT_MASK)) {
630 error_code = 0;
631 goto do_fault;
632 }
633 if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
634 error_code = PG_ERROR_RSVD_MASK;
635 goto do_fault;
636 }
637 ptep &= pde ^ PG_NX_MASK;
638 if (pde & PG_PSE_MASK) {
639 /* 2 MB page */
640 page_size = 2048 * 1024;
641 ptep ^= PG_NX_MASK;
642 if ((ptep & PG_NX_MASK) && is_write1 == 2)
643 goto do_fault_protect;
644 if (is_user) {
645 if (!(ptep & PG_USER_MASK))
646 goto do_fault_protect;
647 if (is_write && !(ptep & PG_RW_MASK))
648 goto do_fault_protect;
649 } else {
650 if ((env->cr[0] & CR0_WP_MASK) &&
651 is_write && !(ptep & PG_RW_MASK))
652 goto do_fault_protect;
653 }
654 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
655 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
656 pde |= PG_ACCESSED_MASK;
657 if (is_dirty)
658 pde |= PG_DIRTY_MASK;
659 stl_phys_notdirty(pde_addr, pde);
660 }
661 /* align to page_size */
662 pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
663 virt_addr = addr & ~(page_size - 1);
664 } else {
665 /* 4 KB page */
666 if (!(pde & PG_ACCESSED_MASK)) {
667 pde |= PG_ACCESSED_MASK;
668 stl_phys_notdirty(pde_addr, pde);
669 }
670 pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
671 env->a20_mask;
672 pte = ldq_phys(pte_addr);
673 if (!(pte & PG_PRESENT_MASK)) {
674 error_code = 0;
675 goto do_fault;
676 }
677 if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
678 error_code = PG_ERROR_RSVD_MASK;
679 goto do_fault;
680 }
681 /* combine pde and pte nx, user and rw protections */
682 ptep &= pte ^ PG_NX_MASK;
683 ptep ^= PG_NX_MASK;
684 if ((ptep & PG_NX_MASK) && is_write1 == 2)
685 goto do_fault_protect;
686 if (is_user) {
687 if (!(ptep & PG_USER_MASK))
688 goto do_fault_protect;
689 if (is_write && !(ptep & PG_RW_MASK))
690 goto do_fault_protect;
691 } else {
692 if ((env->cr[0] & CR0_WP_MASK) &&
693 is_write && !(ptep & PG_RW_MASK))
694 goto do_fault_protect;
695 }
696 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
697 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
698 pte |= PG_ACCESSED_MASK;
699 if (is_dirty)
700 pte |= PG_DIRTY_MASK;
701 stl_phys_notdirty(pte_addr, pte);
702 }
703 page_size = 4096;
704 virt_addr = addr & ~0xfff;
705 pte = pte & (PHYS_ADDR_MASK | 0xfff);
7e84c249 706 }
2c0262af 707 } else {
eaa728ee
FB
708 uint32_t pde;
709
710 /* page directory entry */
711 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
712 env->a20_mask;
713 pde = ldl_phys(pde_addr);
714 if (!(pde & PG_PRESENT_MASK)) {
715 error_code = 0;
716 goto do_fault;
717 }
718 /* if PSE bit is set, then we use a 4MB page */
719 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
720 page_size = 4096 * 1024;
721 if (is_user) {
722 if (!(pde & PG_USER_MASK))
723 goto do_fault_protect;
724 if (is_write && !(pde & PG_RW_MASK))
725 goto do_fault_protect;
726 } else {
727 if ((env->cr[0] & CR0_WP_MASK) &&
728 is_write && !(pde & PG_RW_MASK))
729 goto do_fault_protect;
730 }
731 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
732 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
733 pde |= PG_ACCESSED_MASK;
734 if (is_dirty)
735 pde |= PG_DIRTY_MASK;
736 stl_phys_notdirty(pde_addr, pde);
737 }
2c0262af 738
eaa728ee
FB
739 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
740 ptep = pte;
741 virt_addr = addr & ~(page_size - 1);
742 } else {
743 if (!(pde & PG_ACCESSED_MASK)) {
744 pde |= PG_ACCESSED_MASK;
745 stl_phys_notdirty(pde_addr, pde);
746 }
891b38e4 747
eaa728ee
FB
748 /* page directory entry */
749 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
750 env->a20_mask;
751 pte = ldl_phys(pte_addr);
752 if (!(pte & PG_PRESENT_MASK)) {
753 error_code = 0;
754 goto do_fault;
8e682019 755 }
eaa728ee
FB
756 /* combine pde and pte user and rw protections */
757 ptep = pte & pde;
758 if (is_user) {
759 if (!(ptep & PG_USER_MASK))
760 goto do_fault_protect;
761 if (is_write && !(ptep & PG_RW_MASK))
762 goto do_fault_protect;
763 } else {
764 if ((env->cr[0] & CR0_WP_MASK) &&
765 is_write && !(ptep & PG_RW_MASK))
766 goto do_fault_protect;
8e682019 767 }
eaa728ee
FB
768 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
769 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
770 pte |= PG_ACCESSED_MASK;
771 if (is_dirty)
772 pte |= PG_DIRTY_MASK;
773 stl_phys_notdirty(pte_addr, pte);
774 }
775 page_size = 4096;
776 virt_addr = addr & ~0xfff;
2c0262af
FB
777 }
778 }
eaa728ee
FB
779 /* the page can be put in the TLB */
780 prot = PAGE_READ;
781 if (!(ptep & PG_NX_MASK))
782 prot |= PAGE_EXEC;
783 if (pte & PG_DIRTY_MASK) {
784 /* only set write access if already dirty... otherwise wait
785 for dirty access */
786 if (is_user) {
787 if (ptep & PG_RW_MASK)
788 prot |= PAGE_WRITE;
789 } else {
790 if (!(env->cr[0] & CR0_WP_MASK) ||
791 (ptep & PG_RW_MASK))
792 prot |= PAGE_WRITE;
8e682019 793 }
891b38e4 794 }
eaa728ee
FB
795 do_mapping:
796 pte = pte & env->a20_mask;
797
798 /* Even if 4MB pages, we map only one 4KB page in the cache to
799 avoid filling it too fast */
800 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
801 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
802 vaddr = virt_addr + page_offset;
803
d4c430a8
PB
804 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
805 return 0;
eaa728ee
FB
806 do_fault_protect:
807 error_code = PG_ERROR_P_MASK;
808 do_fault:
809 error_code |= (is_write << PG_ERROR_W_BIT);
810 if (is_user)
811 error_code |= PG_ERROR_U_MASK;
812 if (is_write1 == 2 &&
813 (env->efer & MSR_EFER_NXE) &&
814 (env->cr[4] & CR4_PAE_MASK))
815 error_code |= PG_ERROR_I_D_MASK;
872929aa
FB
816 if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
817 /* cr2 is not modified in case of exceptions */
818 stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
819 addr);
eaa728ee
FB
820 } else {
821 env->cr[2] = addr;
2c0262af 822 }
eaa728ee
FB
823 env->error_code = error_code;
824 env->exception_index = EXCP0E_PAGE;
eaa728ee 825 return 1;
14ce26e7
FB
826}
827
c227f099 828target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
14ce26e7 829{
eaa728ee
FB
830 target_ulong pde_addr, pte_addr;
831 uint64_t pte;
c227f099 832 target_phys_addr_t paddr;
eaa728ee
FB
833 uint32_t page_offset;
834 int page_size;
14ce26e7 835
eaa728ee
FB
836 if (env->cr[4] & CR4_PAE_MASK) {
837 target_ulong pdpe_addr;
838 uint64_t pde, pdpe;
14ce26e7 839
eaa728ee
FB
840#ifdef TARGET_X86_64
841 if (env->hflags & HF_LMA_MASK) {
842 uint64_t pml4e_addr, pml4e;
843 int32_t sext;
844
845 /* test virtual address sign extension */
846 sext = (int64_t)addr >> 47;
847 if (sext != 0 && sext != -1)
848 return -1;
849
850 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
851 env->a20_mask;
852 pml4e = ldq_phys(pml4e_addr);
853 if (!(pml4e & PG_PRESENT_MASK))
854 return -1;
855
856 pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
857 env->a20_mask;
858 pdpe = ldq_phys(pdpe_addr);
859 if (!(pdpe & PG_PRESENT_MASK))
860 return -1;
861 } else
862#endif
863 {
864 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
865 env->a20_mask;
866 pdpe = ldq_phys(pdpe_addr);
867 if (!(pdpe & PG_PRESENT_MASK))
868 return -1;
14ce26e7 869 }
14ce26e7 870
eaa728ee
FB
871 pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
872 env->a20_mask;
873 pde = ldq_phys(pde_addr);
874 if (!(pde & PG_PRESENT_MASK)) {
875 return -1;
876 }
877 if (pde & PG_PSE_MASK) {
878 /* 2 MB page */
879 page_size = 2048 * 1024;
880 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
881 } else {
882 /* 4 KB page */
883 pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
884 env->a20_mask;
885 page_size = 4096;
886 pte = ldq_phys(pte_addr);
887 }
ca1c9e15
AL
888 if (!(pte & PG_PRESENT_MASK))
889 return -1;
14ce26e7 890 } else {
eaa728ee 891 uint32_t pde;
3b46e624 892
eaa728ee
FB
893 if (!(env->cr[0] & CR0_PG_MASK)) {
894 pte = addr;
895 page_size = 4096;
896 } else {
897 /* page directory entry */
898 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
899 pde = ldl_phys(pde_addr);
900 if (!(pde & PG_PRESENT_MASK))
901 return -1;
902 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
903 pte = pde & ~0x003ff000; /* align to 4MB */
904 page_size = 4096 * 1024;
905 } else {
906 /* page directory entry */
907 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
908 pte = ldl_phys(pte_addr);
909 if (!(pte & PG_PRESENT_MASK))
910 return -1;
911 page_size = 4096;
912 }
913 }
914 pte = pte & env->a20_mask;
14ce26e7 915 }
14ce26e7 916
eaa728ee
FB
917 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
918 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
919 return paddr;
3b21e03e 920}
01df040b
AL
921
922void hw_breakpoint_insert(CPUState *env, int index)
923{
924 int type, err = 0;
925
926 switch (hw_breakpoint_type(env->dr[7], index)) {
927 case 0:
928 if (hw_breakpoint_enabled(env->dr[7], index))
929 err = cpu_breakpoint_insert(env, env->dr[index], BP_CPU,
930 &env->cpu_breakpoint[index]);
931 break;
932 case 1:
933 type = BP_CPU | BP_MEM_WRITE;
934 goto insert_wp;
935 case 2:
936 /* No support for I/O watchpoints yet */
937 break;
938 case 3:
939 type = BP_CPU | BP_MEM_ACCESS;
940 insert_wp:
941 err = cpu_watchpoint_insert(env, env->dr[index],
942 hw_breakpoint_len(env->dr[7], index),
943 type, &env->cpu_watchpoint[index]);
944 break;
945 }
946 if (err)
947 env->cpu_breakpoint[index] = NULL;
948}
949
950void hw_breakpoint_remove(CPUState *env, int index)
951{
952 if (!env->cpu_breakpoint[index])
953 return;
954 switch (hw_breakpoint_type(env->dr[7], index)) {
955 case 0:
956 if (hw_breakpoint_enabled(env->dr[7], index))
957 cpu_breakpoint_remove_by_ref(env, env->cpu_breakpoint[index]);
958 break;
959 case 1:
960 case 3:
961 cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[index]);
962 break;
963 case 2:
964 /* No support for I/O watchpoints yet */
965 break;
966 }
967}
968
969int check_hw_breakpoints(CPUState *env, int force_dr6_update)
970{
971 target_ulong dr6;
972 int reg, type;
973 int hit_enabled = 0;
974
975 dr6 = env->dr[6] & ~0xf;
976 for (reg = 0; reg < 4; reg++) {
977 type = hw_breakpoint_type(env->dr[7], reg);
978 if ((type == 0 && env->dr[reg] == env->eip) ||
979 ((type & 1) && env->cpu_watchpoint[reg] &&
980 (env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT))) {
981 dr6 |= 1 << reg;
982 if (hw_breakpoint_enabled(env->dr[7], reg))
983 hit_enabled = 1;
984 }
985 }
986 if (hit_enabled || force_dr6_update)
987 env->dr[6] = dr6;
988 return hit_enabled;
989}
990
991static CPUDebugExcpHandler *prev_debug_excp_handler;
992
63a54736 993void raise_exception_env(int exception_index, CPUState *env);
01df040b
AL
994
995static void breakpoint_handler(CPUState *env)
996{
997 CPUBreakpoint *bp;
998
999 if (env->watchpoint_hit) {
1000 if (env->watchpoint_hit->flags & BP_CPU) {
1001 env->watchpoint_hit = NULL;
1002 if (check_hw_breakpoints(env, 0))
63a54736 1003 raise_exception_env(EXCP01_DB, env);
01df040b
AL
1004 else
1005 cpu_resume_from_signal(env, NULL);
1006 }
1007 } else {
72cf2d4f 1008 QTAILQ_FOREACH(bp, &env->breakpoints, entry)
01df040b
AL
1009 if (bp->pc == env->eip) {
1010 if (bp->flags & BP_CPU) {
1011 check_hw_breakpoints(env, 1);
63a54736 1012 raise_exception_env(EXCP01_DB, env);
01df040b
AL
1013 }
1014 break;
1015 }
1016 }
1017 if (prev_debug_excp_handler)
1018 prev_debug_excp_handler(env);
1019}
79c4f6b0
HY
1020
1021/* This should come from sysemu.h - if we could include it here... */
1022void qemu_system_reset_request(void);
1023
b3cd24e0 1024static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
79c4f6b0
HY
1025 uint64_t mcg_status, uint64_t addr, uint64_t misc)
1026{
1027 uint64_t mcg_cap = cenv->mcg_cap;
79c4f6b0
HY
1028 uint64_t *banks = cenv->mce_banks;
1029
79c4f6b0
HY
1030 /*
1031 * if MSR_MCG_CTL is not all 1s, the uncorrected error
1032 * reporting is disabled
1033 */
1034 if ((status & MCI_STATUS_UC) && (mcg_cap & MCG_CTL_P) &&
1035 cenv->mcg_ctl != ~(uint64_t)0)
1036 return;
1037 banks += 4 * bank;
1038 /*
1039 * if MSR_MCi_CTL is not all 1s, the uncorrected error
1040 * reporting is disabled for the bank
1041 */
1042 if ((status & MCI_STATUS_UC) && banks[0] != ~(uint64_t)0)
1043 return;
1044 if (status & MCI_STATUS_UC) {
1045 if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
1046 !(cenv->cr[4] & CR4_MCE_MASK)) {
1047 fprintf(stderr, "injects mce exception while previous "
1048 "one is in progress!\n");
1049 qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1050 qemu_system_reset_request();
1051 return;
1052 }
1053 if (banks[1] & MCI_STATUS_VAL)
1054 status |= MCI_STATUS_OVER;
1055 banks[2] = addr;
1056 banks[3] = misc;
1057 cenv->mcg_status = mcg_status;
1058 banks[1] = status;
1059 cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
1060 } else if (!(banks[1] & MCI_STATUS_VAL)
1061 || !(banks[1] & MCI_STATUS_UC)) {
1062 if (banks[1] & MCI_STATUS_VAL)
1063 status |= MCI_STATUS_OVER;
1064 banks[2] = addr;
1065 banks[3] = misc;
1066 banks[1] = status;
1067 } else
1068 banks[1] |= MCI_STATUS_OVER;
1069}
b3cd24e0
JD
1070
1071void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
31ce5e0c
JD
1072 uint64_t mcg_status, uint64_t addr, uint64_t misc,
1073 int broadcast)
b3cd24e0
JD
1074{
1075 unsigned bank_num = cenv->mcg_cap & 0xff;
31ce5e0c
JD
1076 CPUState *env;
1077 int flag = 0;
b3cd24e0
JD
1078
1079 if (bank >= bank_num || !(status & MCI_STATUS_VAL)) {
1080 return;
1081 }
1082
1083 if (kvm_enabled()) {
31ce5e0c
JD
1084 if (broadcast) {
1085 flag |= MCE_BROADCAST;
1086 }
1087
1088 kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);
b3cd24e0
JD
1089 } else {
1090 qemu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);
31ce5e0c
JD
1091 if (broadcast) {
1092 for (env = first_cpu; env != NULL; env = env->next_cpu) {
1093 if (cenv == env) {
1094 continue;
1095 }
1096
1097 qemu_inject_x86_mce(env, 1, 0xa000000000000000, 0, 0, 0);
1098 }
1099 }
b3cd24e0
JD
1100 }
1101}
74ce674f 1102#endif /* !CONFIG_USER_ONLY */
6fd805e1 1103
79c4f6b0
HY
1104static void mce_init(CPUX86State *cenv)
1105{
1106 unsigned int bank, bank_num;
1107
1108 if (((cenv->cpuid_version >> 8)&0xf) >= 6
1109 && (cenv->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)) {
1110 cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
1111 cenv->mcg_ctl = ~(uint64_t)0;
ac74d0f1 1112 bank_num = MCE_BANKS_DEF;
79c4f6b0
HY
1113 for (bank = 0; bank < bank_num; bank++)
1114 cenv->mce_banks[bank*4] = ~(uint64_t)0;
1115 }
1116}
1117
84273177
JK
1118int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
1119 target_ulong *base, unsigned int *limit,
1120 unsigned int *flags)
1121{
1122 SegmentCache *dt;
1123 target_ulong ptr;
1124 uint32_t e1, e2;
1125 int index;
1126
1127 if (selector & 0x4)
1128 dt = &env->ldt;
1129 else
1130 dt = &env->gdt;
1131 index = selector & ~7;
1132 ptr = dt->base + index;
1133 if ((index + 7) > dt->limit
1134 || cpu_memory_rw_debug(env, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
1135 || cpu_memory_rw_debug(env, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
1136 return 0;
1137
1138 *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1139 *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1140 if (e2 & DESC_G_MASK)
1141 *limit = (*limit << 12) | 0xfff;
1142 *flags = e2;
1143
1144 return 1;
1145}
1146
01df040b
AL
1147CPUX86State *cpu_x86_init(const char *cpu_model)
1148{
1149 CPUX86State *env;
1150 static int inited;
1151
1152 env = qemu_mallocz(sizeof(CPUX86State));
01df040b
AL
1153 cpu_exec_init(env);
1154 env->cpu_model_str = cpu_model;
1155
1156 /* init various static tables */
1157 if (!inited) {
1158 inited = 1;
1159 optimize_flags_init();
1160#ifndef CONFIG_USER_ONLY
1161 prev_debug_excp_handler =
1162 cpu_set_debug_excp_handler(breakpoint_handler);
1163#endif
1164 }
1165 if (cpu_x86_register(env, cpu_model) < 0) {
1166 cpu_x86_close(env);
1167 return NULL;
1168 }
79c4f6b0 1169 mce_init(env);
0bf46a40
AL
1170
1171 qemu_init_vcpu(env);
1172
01df040b
AL
1173 return env;
1174}
b09ea7d5
GN
1175
1176#if !defined(CONFIG_USER_ONLY)
1177void do_cpu_init(CPUState *env)
1178{
1179 int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
1180 cpu_reset(env);
1181 env->interrupt_request = sipi;
4a942cea 1182 apic_init_reset(env->apic_state);
052be86b 1183 env->halted = !cpu_is_bsp(env);
b09ea7d5
GN
1184}
1185
1186void do_cpu_sipi(CPUState *env)
1187{
4a942cea 1188 apic_sipi(env->apic_state);
b09ea7d5
GN
1189}
1190#else
1191void do_cpu_init(CPUState *env)
1192{
1193}
1194void do_cpu_sipi(CPUState *env)
1195{
1196}
1197#endif