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