Merge remote-tracking branch 'stefanha/trivial-patches' into staging
[qemu.git] / target-i386 / helper.c
blobf8c8633d8bd37bc0fe97c4c762de8f8e2c60db91
1 /*
2 * i386 helpers (without register variable usage)
4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
25 #include "cpu.h"
26 #include "qemu-common.h"
27 #include "kvm.h"
28 #ifndef CONFIG_USER_ONLY
29 #include "sysemu.h"
30 #include "monitor.h"
31 #endif
33 //#define DEBUG_MMU
35 /* NOTE: must be called outside the CPU execute loop */
36 void cpu_reset(CPUX86State *env)
38 int i;
40 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
41 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
42 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
45 memset(env, 0, offsetof(CPUX86State, breakpoints));
47 tlb_flush(env, 1);
49 env->old_exception = -1;
51 /* init to reset state */
53 #ifdef CONFIG_SOFTMMU
54 env->hflags |= HF_SOFTMMU_MASK;
55 #endif
56 env->hflags2 |= HF2_GIF_MASK;
58 cpu_x86_update_cr0(env, 0x60000010);
59 env->a20_mask = ~0x0;
60 env->smbase = 0x30000;
62 env->idt.limit = 0xffff;
63 env->gdt.limit = 0xffff;
64 env->ldt.limit = 0xffff;
65 env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
66 env->tr.limit = 0xffff;
67 env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
69 cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
70 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
71 DESC_R_MASK | DESC_A_MASK);
72 cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
73 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
74 DESC_A_MASK);
75 cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
76 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
77 DESC_A_MASK);
78 cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
79 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
80 DESC_A_MASK);
81 cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
82 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
83 DESC_A_MASK);
84 cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
85 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
86 DESC_A_MASK);
88 env->eip = 0xfff0;
89 env->regs[R_EDX] = env->cpuid_version;
91 env->eflags = 0x2;
93 /* FPU init */
94 for(i = 0;i < 8; i++)
95 env->fptags[i] = 1;
96 env->fpuc = 0x37f;
98 env->mxcsr = 0x1f80;
100 env->pat = 0x0007040600070406ULL;
102 memset(env->dr, 0, sizeof(env->dr));
103 env->dr[6] = DR6_FIXED_1;
104 env->dr[7] = DR7_FIXED_1;
105 cpu_breakpoint_remove_all(env, BP_CPU);
106 cpu_watchpoint_remove_all(env, BP_CPU);
109 void cpu_x86_close(CPUX86State *env)
111 qemu_free(env);
114 static void cpu_x86_version(CPUState *env, int *family, int *model)
116 int cpuver = env->cpuid_version;
118 if (family == NULL || model == NULL) {
119 return;
122 *family = (cpuver >> 8) & 0x0f;
123 *model = ((cpuver >> 12) & 0xf0) + ((cpuver >> 4) & 0x0f);
126 /* Broadcast MCA signal for processor version 06H_EH and above */
127 int cpu_x86_support_mca_broadcast(CPUState *env)
129 int family = 0;
130 int model = 0;
132 cpu_x86_version(env, &family, &model);
133 if ((family == 6 && model >= 14) || family > 6) {
134 return 1;
137 return 0;
140 /***********************************************************/
141 /* x86 debug */
143 static const char *cc_op_str[] = {
144 "DYNAMIC",
145 "EFLAGS",
147 "MULB",
148 "MULW",
149 "MULL",
150 "MULQ",
152 "ADDB",
153 "ADDW",
154 "ADDL",
155 "ADDQ",
157 "ADCB",
158 "ADCW",
159 "ADCL",
160 "ADCQ",
162 "SUBB",
163 "SUBW",
164 "SUBL",
165 "SUBQ",
167 "SBBB",
168 "SBBW",
169 "SBBL",
170 "SBBQ",
172 "LOGICB",
173 "LOGICW",
174 "LOGICL",
175 "LOGICQ",
177 "INCB",
178 "INCW",
179 "INCL",
180 "INCQ",
182 "DECB",
183 "DECW",
184 "DECL",
185 "DECQ",
187 "SHLB",
188 "SHLW",
189 "SHLL",
190 "SHLQ",
192 "SARB",
193 "SARW",
194 "SARL",
195 "SARQ",
198 static void
199 cpu_x86_dump_seg_cache(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
200 const char *name, struct SegmentCache *sc)
202 #ifdef TARGET_X86_64
203 if (env->hflags & HF_CS64_MASK) {
204 cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
205 sc->selector, sc->base, sc->limit, sc->flags & 0x00ffff00);
206 } else
207 #endif
209 cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
210 (uint32_t)sc->base, sc->limit, sc->flags & 0x00ffff00);
213 if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
214 goto done;
216 cpu_fprintf(f, " DPL=%d ", (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
217 if (sc->flags & DESC_S_MASK) {
218 if (sc->flags & DESC_CS_MASK) {
219 cpu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
220 ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
221 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
222 (sc->flags & DESC_R_MASK) ? 'R' : '-');
223 } else {
224 cpu_fprintf(f, (sc->flags & DESC_B_MASK) ? "DS " : "DS16");
225 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
226 (sc->flags & DESC_W_MASK) ? 'W' : '-');
228 cpu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
229 } else {
230 static const char *sys_type_name[2][16] = {
231 { /* 32 bit mode */
232 "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
233 "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
234 "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
235 "CallGate32", "Reserved", "IntGate32", "TrapGate32"
237 { /* 64 bit mode */
238 "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
239 "Reserved", "Reserved", "Reserved", "Reserved",
240 "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
241 "Reserved", "IntGate64", "TrapGate64"
244 cpu_fprintf(f, "%s",
245 sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0]
246 [(sc->flags & DESC_TYPE_MASK)
247 >> DESC_TYPE_SHIFT]);
249 done:
250 cpu_fprintf(f, "\n");
253 #define DUMP_CODE_BYTES_TOTAL 50
254 #define DUMP_CODE_BYTES_BACKWARD 20
256 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
257 int flags)
259 int eflags, i, nb;
260 char cc_op_name[32];
261 static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
263 cpu_synchronize_state(env);
265 eflags = env->eflags;
266 #ifdef TARGET_X86_64
267 if (env->hflags & HF_CS64_MASK) {
268 cpu_fprintf(f,
269 "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
270 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
271 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
272 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
273 "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
274 env->regs[R_EAX],
275 env->regs[R_EBX],
276 env->regs[R_ECX],
277 env->regs[R_EDX],
278 env->regs[R_ESI],
279 env->regs[R_EDI],
280 env->regs[R_EBP],
281 env->regs[R_ESP],
282 env->regs[8],
283 env->regs[9],
284 env->regs[10],
285 env->regs[11],
286 env->regs[12],
287 env->regs[13],
288 env->regs[14],
289 env->regs[15],
290 env->eip, eflags,
291 eflags & DF_MASK ? 'D' : '-',
292 eflags & CC_O ? 'O' : '-',
293 eflags & CC_S ? 'S' : '-',
294 eflags & CC_Z ? 'Z' : '-',
295 eflags & CC_A ? 'A' : '-',
296 eflags & CC_P ? 'P' : '-',
297 eflags & CC_C ? 'C' : '-',
298 env->hflags & HF_CPL_MASK,
299 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
300 (env->a20_mask >> 20) & 1,
301 (env->hflags >> HF_SMM_SHIFT) & 1,
302 env->halted);
303 } else
304 #endif
306 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
307 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
308 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
309 (uint32_t)env->regs[R_EAX],
310 (uint32_t)env->regs[R_EBX],
311 (uint32_t)env->regs[R_ECX],
312 (uint32_t)env->regs[R_EDX],
313 (uint32_t)env->regs[R_ESI],
314 (uint32_t)env->regs[R_EDI],
315 (uint32_t)env->regs[R_EBP],
316 (uint32_t)env->regs[R_ESP],
317 (uint32_t)env->eip, eflags,
318 eflags & DF_MASK ? 'D' : '-',
319 eflags & CC_O ? 'O' : '-',
320 eflags & CC_S ? 'S' : '-',
321 eflags & CC_Z ? 'Z' : '-',
322 eflags & CC_A ? 'A' : '-',
323 eflags & CC_P ? 'P' : '-',
324 eflags & CC_C ? 'C' : '-',
325 env->hflags & HF_CPL_MASK,
326 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
327 (env->a20_mask >> 20) & 1,
328 (env->hflags >> HF_SMM_SHIFT) & 1,
329 env->halted);
332 for(i = 0; i < 6; i++) {
333 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, seg_name[i],
334 &env->segs[i]);
336 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "LDT", &env->ldt);
337 cpu_x86_dump_seg_cache(env, f, cpu_fprintf, "TR", &env->tr);
339 #ifdef TARGET_X86_64
340 if (env->hflags & HF_LMA_MASK) {
341 cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
342 env->gdt.base, env->gdt.limit);
343 cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
344 env->idt.base, env->idt.limit);
345 cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
346 (uint32_t)env->cr[0],
347 env->cr[2],
348 env->cr[3],
349 (uint32_t)env->cr[4]);
350 for(i = 0; i < 4; i++)
351 cpu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
352 cpu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
353 env->dr[6], env->dr[7]);
354 } else
355 #endif
357 cpu_fprintf(f, "GDT= %08x %08x\n",
358 (uint32_t)env->gdt.base, env->gdt.limit);
359 cpu_fprintf(f, "IDT= %08x %08x\n",
360 (uint32_t)env->idt.base, env->idt.limit);
361 cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
362 (uint32_t)env->cr[0],
363 (uint32_t)env->cr[2],
364 (uint32_t)env->cr[3],
365 (uint32_t)env->cr[4]);
366 for(i = 0; i < 4; i++) {
367 cpu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]);
369 cpu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n",
370 env->dr[6], env->dr[7]);
372 if (flags & X86_DUMP_CCOP) {
373 if ((unsigned)env->cc_op < CC_OP_NB)
374 snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
375 else
376 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
377 #ifdef TARGET_X86_64
378 if (env->hflags & HF_CS64_MASK) {
379 cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
380 env->cc_src, env->cc_dst,
381 cc_op_name);
382 } else
383 #endif
385 cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
386 (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
387 cc_op_name);
390 cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
391 if (flags & X86_DUMP_FPU) {
392 int fptag;
393 fptag = 0;
394 for(i = 0; i < 8; i++) {
395 fptag |= ((!env->fptags[i]) << i);
397 cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
398 env->fpuc,
399 (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
400 env->fpstt,
401 fptag,
402 env->mxcsr);
403 for(i=0;i<8;i++) {
404 CPU_LDoubleU u;
405 u.d = env->fpregs[i].d;
406 cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
407 i, u.l.lower, u.l.upper);
408 if ((i & 1) == 1)
409 cpu_fprintf(f, "\n");
410 else
411 cpu_fprintf(f, " ");
413 if (env->hflags & HF_CS64_MASK)
414 nb = 16;
415 else
416 nb = 8;
417 for(i=0;i<nb;i++) {
418 cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
420 env->xmm_regs[i].XMM_L(3),
421 env->xmm_regs[i].XMM_L(2),
422 env->xmm_regs[i].XMM_L(1),
423 env->xmm_regs[i].XMM_L(0));
424 if ((i & 1) == 1)
425 cpu_fprintf(f, "\n");
426 else
427 cpu_fprintf(f, " ");
430 if (flags & CPU_DUMP_CODE) {
431 target_ulong base = env->segs[R_CS].base + env->eip;
432 target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
433 uint8_t code;
434 char codestr[3];
436 cpu_fprintf(f, "Code=");
437 for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
438 if (cpu_memory_rw_debug(env, base - offs + i, &code, 1, 0) == 0) {
439 snprintf(codestr, sizeof(codestr), "%02x", code);
440 } else {
441 snprintf(codestr, sizeof(codestr), "??");
443 cpu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
444 i == offs ? "<" : "", codestr, i == offs ? ">" : "");
446 cpu_fprintf(f, "\n");
450 /***********************************************************/
451 /* x86 mmu */
452 /* XXX: add PGE support */
454 void cpu_x86_set_a20(CPUX86State *env, int a20_state)
456 a20_state = (a20_state != 0);
457 if (a20_state != ((env->a20_mask >> 20) & 1)) {
458 #if defined(DEBUG_MMU)
459 printf("A20 update: a20=%d\n", a20_state);
460 #endif
461 /* if the cpu is currently executing code, we must unlink it and
462 all the potentially executing TB */
463 cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
465 /* when a20 is changed, all the MMU mappings are invalid, so
466 we must flush everything */
467 tlb_flush(env, 1);
468 env->a20_mask = ~(1 << 20) | (a20_state << 20);
472 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
474 int pe_state;
476 #if defined(DEBUG_MMU)
477 printf("CR0 update: CR0=0x%08x\n", new_cr0);
478 #endif
479 if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
480 (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
481 tlb_flush(env, 1);
484 #ifdef TARGET_X86_64
485 if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
486 (env->efer & MSR_EFER_LME)) {
487 /* enter in long mode */
488 /* XXX: generate an exception */
489 if (!(env->cr[4] & CR4_PAE_MASK))
490 return;
491 env->efer |= MSR_EFER_LMA;
492 env->hflags |= HF_LMA_MASK;
493 } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
494 (env->efer & MSR_EFER_LMA)) {
495 /* exit long mode */
496 env->efer &= ~MSR_EFER_LMA;
497 env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
498 env->eip &= 0xffffffff;
500 #endif
501 env->cr[0] = new_cr0 | CR0_ET_MASK;
503 /* update PE flag in hidden flags */
504 pe_state = (env->cr[0] & CR0_PE_MASK);
505 env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
506 /* ensure that ADDSEG is always set in real mode */
507 env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
508 /* update FPU flags */
509 env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
510 ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
513 /* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
514 the PDPT */
515 void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
517 env->cr[3] = new_cr3;
518 if (env->cr[0] & CR0_PG_MASK) {
519 #if defined(DEBUG_MMU)
520 printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
521 #endif
522 tlb_flush(env, 0);
526 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
528 #if defined(DEBUG_MMU)
529 printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
530 #endif
531 if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
532 (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
533 tlb_flush(env, 1);
535 /* SSE handling */
536 if (!(env->cpuid_features & CPUID_SSE))
537 new_cr4 &= ~CR4_OSFXSR_MASK;
538 if (new_cr4 & CR4_OSFXSR_MASK)
539 env->hflags |= HF_OSFXSR_MASK;
540 else
541 env->hflags &= ~HF_OSFXSR_MASK;
543 env->cr[4] = new_cr4;
546 #if defined(CONFIG_USER_ONLY)
548 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
549 int is_write, int mmu_idx)
551 /* user mode only emulation */
552 is_write &= 1;
553 env->cr[2] = addr;
554 env->error_code = (is_write << PG_ERROR_W_BIT);
555 env->error_code |= PG_ERROR_U_MASK;
556 env->exception_index = EXCP0E_PAGE;
557 return 1;
560 #else
562 /* XXX: This value should match the one returned by CPUID
563 * and in exec.c */
564 # if defined(TARGET_X86_64)
565 # define PHYS_ADDR_MASK 0xfffffff000LL
566 # else
567 # define PHYS_ADDR_MASK 0xffffff000LL
568 # endif
570 /* return value:
571 -1 = cannot handle fault
572 0 = nothing more to do
573 1 = generate PF fault
575 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
576 int is_write1, int mmu_idx)
578 uint64_t ptep, pte;
579 target_ulong pde_addr, pte_addr;
580 int error_code, is_dirty, prot, page_size, is_write, is_user;
581 target_phys_addr_t paddr;
582 uint32_t page_offset;
583 target_ulong vaddr, virt_addr;
585 is_user = mmu_idx == MMU_USER_IDX;
586 #if defined(DEBUG_MMU)
587 printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
588 addr, is_write1, is_user, env->eip);
589 #endif
590 is_write = is_write1 & 1;
592 if (!(env->cr[0] & CR0_PG_MASK)) {
593 pte = addr;
594 virt_addr = addr & TARGET_PAGE_MASK;
595 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
596 page_size = 4096;
597 goto do_mapping;
600 if (env->cr[4] & CR4_PAE_MASK) {
601 uint64_t pde, pdpe;
602 target_ulong pdpe_addr;
604 #ifdef TARGET_X86_64
605 if (env->hflags & HF_LMA_MASK) {
606 uint64_t pml4e_addr, pml4e;
607 int32_t sext;
609 /* test virtual address sign extension */
610 sext = (int64_t)addr >> 47;
611 if (sext != 0 && sext != -1) {
612 env->error_code = 0;
613 env->exception_index = EXCP0D_GPF;
614 return 1;
617 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
618 env->a20_mask;
619 pml4e = ldq_phys(pml4e_addr);
620 if (!(pml4e & PG_PRESENT_MASK)) {
621 error_code = 0;
622 goto do_fault;
624 if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
625 error_code = PG_ERROR_RSVD_MASK;
626 goto do_fault;
628 if (!(pml4e & PG_ACCESSED_MASK)) {
629 pml4e |= PG_ACCESSED_MASK;
630 stl_phys_notdirty(pml4e_addr, pml4e);
632 ptep = pml4e ^ PG_NX_MASK;
633 pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
634 env->a20_mask;
635 pdpe = ldq_phys(pdpe_addr);
636 if (!(pdpe & PG_PRESENT_MASK)) {
637 error_code = 0;
638 goto do_fault;
640 if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
641 error_code = PG_ERROR_RSVD_MASK;
642 goto do_fault;
644 ptep &= pdpe ^ PG_NX_MASK;
645 if (!(pdpe & PG_ACCESSED_MASK)) {
646 pdpe |= PG_ACCESSED_MASK;
647 stl_phys_notdirty(pdpe_addr, pdpe);
649 } else
650 #endif
652 /* XXX: load them when cr3 is loaded ? */
653 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
654 env->a20_mask;
655 pdpe = ldq_phys(pdpe_addr);
656 if (!(pdpe & PG_PRESENT_MASK)) {
657 error_code = 0;
658 goto do_fault;
660 ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
663 pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
664 env->a20_mask;
665 pde = ldq_phys(pde_addr);
666 if (!(pde & PG_PRESENT_MASK)) {
667 error_code = 0;
668 goto do_fault;
670 if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
671 error_code = PG_ERROR_RSVD_MASK;
672 goto do_fault;
674 ptep &= pde ^ PG_NX_MASK;
675 if (pde & PG_PSE_MASK) {
676 /* 2 MB page */
677 page_size = 2048 * 1024;
678 ptep ^= PG_NX_MASK;
679 if ((ptep & PG_NX_MASK) && is_write1 == 2)
680 goto do_fault_protect;
681 if (is_user) {
682 if (!(ptep & PG_USER_MASK))
683 goto do_fault_protect;
684 if (is_write && !(ptep & PG_RW_MASK))
685 goto do_fault_protect;
686 } else {
687 if ((env->cr[0] & CR0_WP_MASK) &&
688 is_write && !(ptep & PG_RW_MASK))
689 goto do_fault_protect;
691 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
692 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
693 pde |= PG_ACCESSED_MASK;
694 if (is_dirty)
695 pde |= PG_DIRTY_MASK;
696 stl_phys_notdirty(pde_addr, pde);
698 /* align to page_size */
699 pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
700 virt_addr = addr & ~(page_size - 1);
701 } else {
702 /* 4 KB page */
703 if (!(pde & PG_ACCESSED_MASK)) {
704 pde |= PG_ACCESSED_MASK;
705 stl_phys_notdirty(pde_addr, pde);
707 pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
708 env->a20_mask;
709 pte = ldq_phys(pte_addr);
710 if (!(pte & PG_PRESENT_MASK)) {
711 error_code = 0;
712 goto do_fault;
714 if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
715 error_code = PG_ERROR_RSVD_MASK;
716 goto do_fault;
718 /* combine pde and pte nx, user and rw protections */
719 ptep &= pte ^ PG_NX_MASK;
720 ptep ^= PG_NX_MASK;
721 if ((ptep & PG_NX_MASK) && is_write1 == 2)
722 goto do_fault_protect;
723 if (is_user) {
724 if (!(ptep & PG_USER_MASK))
725 goto do_fault_protect;
726 if (is_write && !(ptep & PG_RW_MASK))
727 goto do_fault_protect;
728 } else {
729 if ((env->cr[0] & CR0_WP_MASK) &&
730 is_write && !(ptep & PG_RW_MASK))
731 goto do_fault_protect;
733 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
734 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
735 pte |= PG_ACCESSED_MASK;
736 if (is_dirty)
737 pte |= PG_DIRTY_MASK;
738 stl_phys_notdirty(pte_addr, pte);
740 page_size = 4096;
741 virt_addr = addr & ~0xfff;
742 pte = pte & (PHYS_ADDR_MASK | 0xfff);
744 } else {
745 uint32_t pde;
747 /* page directory entry */
748 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
749 env->a20_mask;
750 pde = ldl_phys(pde_addr);
751 if (!(pde & PG_PRESENT_MASK)) {
752 error_code = 0;
753 goto do_fault;
755 /* if PSE bit is set, then we use a 4MB page */
756 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
757 page_size = 4096 * 1024;
758 if (is_user) {
759 if (!(pde & PG_USER_MASK))
760 goto do_fault_protect;
761 if (is_write && !(pde & PG_RW_MASK))
762 goto do_fault_protect;
763 } else {
764 if ((env->cr[0] & CR0_WP_MASK) &&
765 is_write && !(pde & PG_RW_MASK))
766 goto do_fault_protect;
768 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
769 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
770 pde |= PG_ACCESSED_MASK;
771 if (is_dirty)
772 pde |= PG_DIRTY_MASK;
773 stl_phys_notdirty(pde_addr, pde);
776 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
777 ptep = pte;
778 virt_addr = addr & ~(page_size - 1);
779 } else {
780 if (!(pde & PG_ACCESSED_MASK)) {
781 pde |= PG_ACCESSED_MASK;
782 stl_phys_notdirty(pde_addr, pde);
785 /* page directory entry */
786 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
787 env->a20_mask;
788 pte = ldl_phys(pte_addr);
789 if (!(pte & PG_PRESENT_MASK)) {
790 error_code = 0;
791 goto do_fault;
793 /* combine pde and pte user and rw protections */
794 ptep = pte & pde;
795 if (is_user) {
796 if (!(ptep & PG_USER_MASK))
797 goto do_fault_protect;
798 if (is_write && !(ptep & PG_RW_MASK))
799 goto do_fault_protect;
800 } else {
801 if ((env->cr[0] & CR0_WP_MASK) &&
802 is_write && !(ptep & PG_RW_MASK))
803 goto do_fault_protect;
805 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
806 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
807 pte |= PG_ACCESSED_MASK;
808 if (is_dirty)
809 pte |= PG_DIRTY_MASK;
810 stl_phys_notdirty(pte_addr, pte);
812 page_size = 4096;
813 virt_addr = addr & ~0xfff;
816 /* the page can be put in the TLB */
817 prot = PAGE_READ;
818 if (!(ptep & PG_NX_MASK))
819 prot |= PAGE_EXEC;
820 if (pte & PG_DIRTY_MASK) {
821 /* only set write access if already dirty... otherwise wait
822 for dirty access */
823 if (is_user) {
824 if (ptep & PG_RW_MASK)
825 prot |= PAGE_WRITE;
826 } else {
827 if (!(env->cr[0] & CR0_WP_MASK) ||
828 (ptep & PG_RW_MASK))
829 prot |= PAGE_WRITE;
832 do_mapping:
833 pte = pte & env->a20_mask;
835 /* Even if 4MB pages, we map only one 4KB page in the cache to
836 avoid filling it too fast */
837 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
838 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
839 vaddr = virt_addr + page_offset;
841 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
842 return 0;
843 do_fault_protect:
844 error_code = PG_ERROR_P_MASK;
845 do_fault:
846 error_code |= (is_write << PG_ERROR_W_BIT);
847 if (is_user)
848 error_code |= PG_ERROR_U_MASK;
849 if (is_write1 == 2 &&
850 (env->efer & MSR_EFER_NXE) &&
851 (env->cr[4] & CR4_PAE_MASK))
852 error_code |= PG_ERROR_I_D_MASK;
853 if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
854 /* cr2 is not modified in case of exceptions */
855 stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
856 addr);
857 } else {
858 env->cr[2] = addr;
860 env->error_code = error_code;
861 env->exception_index = EXCP0E_PAGE;
862 return 1;
865 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
867 target_ulong pde_addr, pte_addr;
868 uint64_t pte;
869 target_phys_addr_t paddr;
870 uint32_t page_offset;
871 int page_size;
873 if (env->cr[4] & CR4_PAE_MASK) {
874 target_ulong pdpe_addr;
875 uint64_t pde, pdpe;
877 #ifdef TARGET_X86_64
878 if (env->hflags & HF_LMA_MASK) {
879 uint64_t pml4e_addr, pml4e;
880 int32_t sext;
882 /* test virtual address sign extension */
883 sext = (int64_t)addr >> 47;
884 if (sext != 0 && sext != -1)
885 return -1;
887 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
888 env->a20_mask;
889 pml4e = ldq_phys(pml4e_addr);
890 if (!(pml4e & PG_PRESENT_MASK))
891 return -1;
893 pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
894 env->a20_mask;
895 pdpe = ldq_phys(pdpe_addr);
896 if (!(pdpe & PG_PRESENT_MASK))
897 return -1;
898 } else
899 #endif
901 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
902 env->a20_mask;
903 pdpe = ldq_phys(pdpe_addr);
904 if (!(pdpe & PG_PRESENT_MASK))
905 return -1;
908 pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
909 env->a20_mask;
910 pde = ldq_phys(pde_addr);
911 if (!(pde & PG_PRESENT_MASK)) {
912 return -1;
914 if (pde & PG_PSE_MASK) {
915 /* 2 MB page */
916 page_size = 2048 * 1024;
917 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
918 } else {
919 /* 4 KB page */
920 pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
921 env->a20_mask;
922 page_size = 4096;
923 pte = ldq_phys(pte_addr);
925 if (!(pte & PG_PRESENT_MASK))
926 return -1;
927 } else {
928 uint32_t pde;
930 if (!(env->cr[0] & CR0_PG_MASK)) {
931 pte = addr;
932 page_size = 4096;
933 } else {
934 /* page directory entry */
935 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
936 pde = ldl_phys(pde_addr);
937 if (!(pde & PG_PRESENT_MASK))
938 return -1;
939 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
940 pte = pde & ~0x003ff000; /* align to 4MB */
941 page_size = 4096 * 1024;
942 } else {
943 /* page directory entry */
944 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
945 pte = ldl_phys(pte_addr);
946 if (!(pte & PG_PRESENT_MASK))
947 return -1;
948 page_size = 4096;
951 pte = pte & env->a20_mask;
954 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
955 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
956 return paddr;
959 void hw_breakpoint_insert(CPUState *env, int index)
961 int type, err = 0;
963 switch (hw_breakpoint_type(env->dr[7], index)) {
964 case 0:
965 if (hw_breakpoint_enabled(env->dr[7], index))
966 err = cpu_breakpoint_insert(env, env->dr[index], BP_CPU,
967 &env->cpu_breakpoint[index]);
968 break;
969 case 1:
970 type = BP_CPU | BP_MEM_WRITE;
971 goto insert_wp;
972 case 2:
973 /* No support for I/O watchpoints yet */
974 break;
975 case 3:
976 type = BP_CPU | BP_MEM_ACCESS;
977 insert_wp:
978 err = cpu_watchpoint_insert(env, env->dr[index],
979 hw_breakpoint_len(env->dr[7], index),
980 type, &env->cpu_watchpoint[index]);
981 break;
983 if (err)
984 env->cpu_breakpoint[index] = NULL;
987 void hw_breakpoint_remove(CPUState *env, int index)
989 if (!env->cpu_breakpoint[index])
990 return;
991 switch (hw_breakpoint_type(env->dr[7], index)) {
992 case 0:
993 if (hw_breakpoint_enabled(env->dr[7], index))
994 cpu_breakpoint_remove_by_ref(env, env->cpu_breakpoint[index]);
995 break;
996 case 1:
997 case 3:
998 cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[index]);
999 break;
1000 case 2:
1001 /* No support for I/O watchpoints yet */
1002 break;
1006 int check_hw_breakpoints(CPUState *env, int force_dr6_update)
1008 target_ulong dr6;
1009 int reg, type;
1010 int hit_enabled = 0;
1012 dr6 = env->dr[6] & ~0xf;
1013 for (reg = 0; reg < 4; reg++) {
1014 type = hw_breakpoint_type(env->dr[7], reg);
1015 if ((type == 0 && env->dr[reg] == env->eip) ||
1016 ((type & 1) && env->cpu_watchpoint[reg] &&
1017 (env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT))) {
1018 dr6 |= 1 << reg;
1019 if (hw_breakpoint_enabled(env->dr[7], reg))
1020 hit_enabled = 1;
1023 if (hit_enabled || force_dr6_update)
1024 env->dr[6] = dr6;
1025 return hit_enabled;
1028 static CPUDebugExcpHandler *prev_debug_excp_handler;
1030 static void breakpoint_handler(CPUState *env)
1032 CPUBreakpoint *bp;
1034 if (env->watchpoint_hit) {
1035 if (env->watchpoint_hit->flags & BP_CPU) {
1036 env->watchpoint_hit = NULL;
1037 if (check_hw_breakpoints(env, 0))
1038 raise_exception_env(EXCP01_DB, env);
1039 else
1040 cpu_resume_from_signal(env, NULL);
1042 } else {
1043 QTAILQ_FOREACH(bp, &env->breakpoints, entry)
1044 if (bp->pc == env->eip) {
1045 if (bp->flags & BP_CPU) {
1046 check_hw_breakpoints(env, 1);
1047 raise_exception_env(EXCP01_DB, env);
1049 break;
1052 if (prev_debug_excp_handler)
1053 prev_debug_excp_handler(env);
1056 typedef struct MCEInjectionParams {
1057 Monitor *mon;
1058 CPUState *env;
1059 int bank;
1060 uint64_t status;
1061 uint64_t mcg_status;
1062 uint64_t addr;
1063 uint64_t misc;
1064 int flags;
1065 } MCEInjectionParams;
1067 static void do_inject_x86_mce(void *data)
1069 MCEInjectionParams *params = data;
1070 CPUState *cenv = params->env;
1071 uint64_t *banks = cenv->mce_banks + 4 * params->bank;
1073 cpu_synchronize_state(cenv);
1076 * If there is an MCE exception being processed, ignore this SRAO MCE
1077 * unless unconditional injection was requested.
1079 if (!(params->flags & MCE_INJECT_UNCOND_AO)
1080 && !(params->status & MCI_STATUS_AR)
1081 && (cenv->mcg_status & MCG_STATUS_MCIP)) {
1082 return;
1085 if (params->status & MCI_STATUS_UC) {
1087 * if MSR_MCG_CTL is not all 1s, the uncorrected error
1088 * reporting is disabled
1090 if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
1091 monitor_printf(params->mon,
1092 "CPU %d: Uncorrected error reporting disabled\n",
1093 cenv->cpu_index);
1094 return;
1098 * if MSR_MCi_CTL is not all 1s, the uncorrected error
1099 * reporting is disabled for the bank
1101 if (banks[0] != ~(uint64_t)0) {
1102 monitor_printf(params->mon,
1103 "CPU %d: Uncorrected error reporting disabled for"
1104 " bank %d\n",
1105 cenv->cpu_index, params->bank);
1106 return;
1109 if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
1110 !(cenv->cr[4] & CR4_MCE_MASK)) {
1111 monitor_printf(params->mon,
1112 "CPU %d: Previous MCE still in progress, raising"
1113 " triple fault\n",
1114 cenv->cpu_index);
1115 qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1116 qemu_system_reset_request();
1117 return;
1119 if (banks[1] & MCI_STATUS_VAL) {
1120 params->status |= MCI_STATUS_OVER;
1122 banks[2] = params->addr;
1123 banks[3] = params->misc;
1124 cenv->mcg_status = params->mcg_status;
1125 banks[1] = params->status;
1126 cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
1127 } else if (!(banks[1] & MCI_STATUS_VAL)
1128 || !(banks[1] & MCI_STATUS_UC)) {
1129 if (banks[1] & MCI_STATUS_VAL) {
1130 params->status |= MCI_STATUS_OVER;
1132 banks[2] = params->addr;
1133 banks[3] = params->misc;
1134 banks[1] = params->status;
1135 } else {
1136 banks[1] |= MCI_STATUS_OVER;
1140 void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
1141 uint64_t status, uint64_t mcg_status, uint64_t addr,
1142 uint64_t misc, int flags)
1144 MCEInjectionParams params = {
1145 .mon = mon,
1146 .env = cenv,
1147 .bank = bank,
1148 .status = status,
1149 .mcg_status = mcg_status,
1150 .addr = addr,
1151 .misc = misc,
1152 .flags = flags,
1154 unsigned bank_num = cenv->mcg_cap & 0xff;
1155 CPUState *env;
1157 if (!cenv->mcg_cap) {
1158 monitor_printf(mon, "MCE injection not supported\n");
1159 return;
1161 if (bank >= bank_num) {
1162 monitor_printf(mon, "Invalid MCE bank number\n");
1163 return;
1165 if (!(status & MCI_STATUS_VAL)) {
1166 monitor_printf(mon, "Invalid MCE status code\n");
1167 return;
1169 if ((flags & MCE_INJECT_BROADCAST)
1170 && !cpu_x86_support_mca_broadcast(cenv)) {
1171 monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
1172 return;
1175 run_on_cpu(cenv, do_inject_x86_mce, &params);
1176 if (flags & MCE_INJECT_BROADCAST) {
1177 params.bank = 1;
1178 params.status = MCI_STATUS_VAL | MCI_STATUS_UC;
1179 params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
1180 params.addr = 0;
1181 params.misc = 0;
1182 for (env = first_cpu; env != NULL; env = env->next_cpu) {
1183 if (cenv == env) {
1184 continue;
1186 params.env = env;
1187 run_on_cpu(cenv, do_inject_x86_mce, &params);
1191 #endif /* !CONFIG_USER_ONLY */
1193 static void mce_init(CPUX86State *cenv)
1195 unsigned int bank;
1197 if (((cenv->cpuid_version >> 8) & 0xf) >= 6
1198 && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
1199 (CPUID_MCE | CPUID_MCA)) {
1200 cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
1201 cenv->mcg_ctl = ~(uint64_t)0;
1202 for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
1203 cenv->mce_banks[bank * 4] = ~(uint64_t)0;
1208 int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
1209 target_ulong *base, unsigned int *limit,
1210 unsigned int *flags)
1212 SegmentCache *dt;
1213 target_ulong ptr;
1214 uint32_t e1, e2;
1215 int index;
1217 if (selector & 0x4)
1218 dt = &env->ldt;
1219 else
1220 dt = &env->gdt;
1221 index = selector & ~7;
1222 ptr = dt->base + index;
1223 if ((index + 7) > dt->limit
1224 || cpu_memory_rw_debug(env, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
1225 || cpu_memory_rw_debug(env, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
1226 return 0;
1228 *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1229 *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1230 if (e2 & DESC_G_MASK)
1231 *limit = (*limit << 12) | 0xfff;
1232 *flags = e2;
1234 return 1;
1237 CPUX86State *cpu_x86_init(const char *cpu_model)
1239 CPUX86State *env;
1240 static int inited;
1242 env = qemu_mallocz(sizeof(CPUX86State));
1243 cpu_exec_init(env);
1244 env->cpu_model_str = cpu_model;
1246 /* init various static tables used in TCG mode */
1247 if (tcg_enabled() && !inited) {
1248 inited = 1;
1249 optimize_flags_init();
1250 #ifndef CONFIG_USER_ONLY
1251 prev_debug_excp_handler =
1252 cpu_set_debug_excp_handler(breakpoint_handler);
1253 #endif
1255 if (cpu_x86_register(env, cpu_model) < 0) {
1256 cpu_x86_close(env);
1257 return NULL;
1259 mce_init(env);
1261 qemu_init_vcpu(env);
1263 return env;
1266 #if !defined(CONFIG_USER_ONLY)
1267 void do_cpu_init(CPUState *env)
1269 int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
1270 uint64_t pat = env->pat;
1272 cpu_reset(env);
1273 env->interrupt_request = sipi;
1274 env->pat = pat;
1275 apic_init_reset(env->apic_state);
1276 env->halted = !cpu_is_bsp(env);
1279 void do_cpu_sipi(CPUState *env)
1281 apic_sipi(env->apic_state);
1283 #else
1284 void do_cpu_init(CPUState *env)
1287 void do_cpu_sipi(CPUState *env)
1290 #endif