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