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