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