]> Git Repo - qemu.git/blame - target-i386/helper.c
apic: qdev conversion cleanup
[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 };
e5c15eff
SW
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]);
a3867ed2
AL
221 }
222done:
223 cpu_fprintf(f, "\n");
224}
225
eaa728ee
FB
226void 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" };
7e84c249 233
23054111 234 cpu_synchronize_state(env);
ff3c01ca 235
eaa728ee
FB
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,
5ee0ffaa 271 (env->a20_mask >> 20) & 1,
eaa728ee 272 (env->hflags >> HF_SMM_SHIFT) & 1,
ce5232c5 273 env->halted);
eaa728ee
FB
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,
5ee0ffaa 298 (env->a20_mask >> 20) & 1,
eaa728ee 299 (env->hflags >> HF_SMM_SHIFT) & 1,
ce5232c5 300 env->halted);
8145122b 301 }
3b46e624 302
a3867ed2
AL
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
eaa728ee
FB
310#ifdef TARGET_X86_64
311 if (env->hflags & HF_LMA_MASK) {
eaa728ee
FB
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]);
a59cb4e0
AL
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",
d4b55be5 324 env->dr[6], env->dr[7]);
eaa728ee
FB
325 } else
326#endif
327 {
eaa728ee
FB
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]);
a59cb4e0
AL
337 for(i = 0; i < 4; i++)
338 cpu_fprintf(f, "DR%d=%08x ", i, env->dr[i]);
d4b55be5 339 cpu_fprintf(f, "\nDR6=%08x DR7=%08x\n", env->dr[6], env->dr[7]);
eaa728ee
FB
340 }
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
352#endif
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 }
7e84c249 358 }
b5e5a934 359 cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
eaa728ee
FB
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);
384#else
385 cpu_fprintf(f, "FPR%d=%016" PRIx64,
386 i, env->fpregs[i].mmx.q);
387#endif
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, " ");
408 }
7e84c249 409 }
2c0262af 410}
7e84c249 411
eaa728ee
FB
412/***********************************************************/
413/* x86 mmu */
414/* XXX: add PGE support */
415
416void cpu_x86_set_a20(CPUX86State *env, int a20_state)
2c0262af 417{
eaa728ee
FB
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);
3b46e624 426
eaa728ee
FB
427 /* when a20 is changed, all the MMU mappings are invalid, so
428 we must flush everything */
429 tlb_flush(env, 1);
5ee0ffaa 430 env->a20_mask = ~(1 << 20) | (a20_state << 20);
7e84c249 431 }
2c0262af
FB
432}
433
eaa728ee 434void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
2c0262af 435{
eaa728ee 436 int pe_state;
2c0262af 437
eaa728ee
FB
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);
444 }
2c0262af 445
eaa728ee
FB
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;
461 }
462#endif
463 env->cr[0] = new_cr0 | CR0_ET_MASK;
7e84c249 464
eaa728ee
FB
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));
7e84c249
FB
473}
474
eaa728ee
FB
475/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
476 the PDPT */
477void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
7e84c249 478{
eaa728ee
FB
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 }
7e84c249
FB
486}
487
eaa728ee 488void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
7e84c249 489{
eaa728ee
FB
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);
496 }
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;
b8b6a50b 504
eaa728ee 505 env->cr[4] = new_cr4;
b8b6a50b
FB
506}
507
eaa728ee
FB
508#if defined(CONFIG_USER_ONLY)
509
510int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
511 int is_write, int mmu_idx, int is_softmmu)
b8b6a50b 512{
eaa728ee
FB
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;
2c0262af
FB
520}
521
8d7b0fbb 522#else
891b38e4 523
eaa728ee
FB
524/* XXX: This value should match the one returned by CPUID
525 * and in exec.c */
eaa728ee 526# if defined(TARGET_X86_64)
2c90d794 527# define PHYS_ADDR_MASK 0xfffffff000LL
eaa728ee 528# else
2c90d794 529# define PHYS_ADDR_MASK 0xffffff000LL
eaa728ee 530# endif
eaa728ee
FB
531
532/* return value:
533 -1 = cannot handle fault
534 0 = nothing more to do
535 1 = generate PF fault
eaa728ee
FB
536*/
537int 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;
d4c430a8 542 int error_code, is_dirty, prot, page_size, is_write, is_user;
c227f099 543 target_phys_addr_t paddr;
eaa728ee
FB
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;
2c0262af 565
eaa728ee
FB
566#ifdef TARGET_X86_64
567 if (env->hflags & HF_LMA_MASK) {
568 uint64_t pml4e_addr, pml4e;
569 int32_t sext;
570
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 }
0573fbfc 578
eaa728ee
FB
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
612#endif
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;
621 }
622 ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
7e84c249 623 }
7e84c249 624
eaa728ee
FB
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);
7e84c249 705 }
2c0262af 706 } else {
eaa728ee
FB
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 }
2c0262af 737
eaa728ee
FB
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 }
891b38e4 746
eaa728ee
FB
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;
8e682019 754 }
eaa728ee
FB
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;
8e682019 766 }
eaa728ee
FB
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;
2c0262af
FB
776 }
777 }
eaa728ee
FB
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;
8e682019 792 }
891b38e4 793 }
eaa728ee
FB
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
d4c430a8
PB
803 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
804 return 0;
eaa728ee
FB
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;
872929aa
FB
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);
eaa728ee
FB
819 } else {
820 env->cr[2] = addr;
2c0262af 821 }
eaa728ee
FB
822 env->error_code = error_code;
823 env->exception_index = EXCP0E_PAGE;
eaa728ee 824 return 1;
14ce26e7
FB
825}
826
c227f099 827target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
14ce26e7 828{
eaa728ee
FB
829 target_ulong pde_addr, pte_addr;
830 uint64_t pte;
c227f099 831 target_phys_addr_t paddr;
eaa728ee
FB
832 uint32_t page_offset;
833 int page_size;
14ce26e7 834
eaa728ee
FB
835 if (env->cr[4] & CR4_PAE_MASK) {
836 target_ulong pdpe_addr;
837 uint64_t pde, pdpe;
14ce26e7 838
eaa728ee
FB
839#ifdef TARGET_X86_64
840 if (env->hflags & HF_LMA_MASK) {
841 uint64_t pml4e_addr, pml4e;
842 int32_t sext;
843
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;
14ce26e7 868 }
14ce26e7 869
eaa728ee
FB
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 }
ca1c9e15
AL
887 if (!(pte & PG_PRESENT_MASK))
888 return -1;
14ce26e7 889 } else {
eaa728ee 890 uint32_t pde;
3b46e624 891
eaa728ee
FB
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;
14ce26e7 914 }
14ce26e7 915
eaa728ee
FB
916 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
917 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
918 return paddr;
3b21e03e 919}
01df040b
AL
920
921void hw_breakpoint_insert(CPUState *env, int index)
922{
923 int type, err = 0;
924
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;
944 }
945 if (err)
946 env->cpu_breakpoint[index] = NULL;
947}
948
949void 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 */
964 break;
965 }
966}
967
968int check_hw_breakpoints(CPUState *env, int force_dr6_update)
969{
970 target_ulong dr6;
971 int reg, type;
972 int hit_enabled = 0;
973
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;
983 }
984 }
985 if (hit_enabled || force_dr6_update)
986 env->dr[6] = dr6;
987 return hit_enabled;
988}
989
990static CPUDebugExcpHandler *prev_debug_excp_handler;
991
63a54736 992void raise_exception_env(int exception_index, CPUState *env);
01df040b
AL
993
994static void breakpoint_handler(CPUState *env)
995{
996 CPUBreakpoint *bp;
997
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))
63a54736 1002 raise_exception_env(EXCP01_DB, env);
01df040b
AL
1003 else
1004 cpu_resume_from_signal(env, NULL);
1005 }
1006 } else {
72cf2d4f 1007 QTAILQ_FOREACH(bp, &env->breakpoints, entry)
01df040b
AL
1008 if (bp->pc == env->eip) {
1009 if (bp->flags & BP_CPU) {
1010 check_hw_breakpoints(env, 1);
63a54736 1011 raise_exception_env(EXCP01_DB, env);
01df040b
AL
1012 }
1013 break;
1014 }
1015 }
1016 if (prev_debug_excp_handler)
1017 prev_debug_excp_handler(env);
1018}
79c4f6b0
HY
1019
1020/* This should come from sysemu.h - if we could include it here... */
1021void qemu_system_reset_request(void);
1022
1023void 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}
74ce674f 1073#endif /* !CONFIG_USER_ONLY */
6fd805e1 1074
79c4f6b0
HY
1075static 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;
ac74d0f1 1083 bank_num = MCE_BANKS_DEF;
79c4f6b0
HY
1084 for (bank = 0; bank < bank_num; bank++)
1085 cenv->mce_banks[bank*4] = ~(uint64_t)0;
1086 }
1087}
1088
84273177
JK
1089int 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
01df040b
AL
1118CPUX86State *cpu_x86_init(const char *cpu_model)
1119{
1120 CPUX86State *env;
1121 static int inited;
1122
1123 env = qemu_mallocz(sizeof(CPUX86State));
01df040b
AL
1124 cpu_exec_init(env);
1125 env->cpu_model_str = cpu_model;
1126
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
1135 }
1136 if (cpu_x86_register(env, cpu_model) < 0) {
1137 cpu_x86_close(env);
1138 return NULL;
1139 }
79c4f6b0 1140 mce_init(env);
0bf46a40
AL
1141
1142 qemu_init_vcpu(env);
1143
01df040b
AL
1144 return env;
1145}
b09ea7d5
GN
1146
1147#if !defined(CONFIG_USER_ONLY)
1148void do_cpu_init(CPUState *env)
1149{
1150 int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
1151 cpu_reset(env);
1152 env->interrupt_request = sipi;
4a942cea 1153 apic_init_reset(env->apic_state);
b09ea7d5
GN
1154}
1155
1156void do_cpu_sipi(CPUState *env)
1157{
4a942cea 1158 apic_sipi(env->apic_state);
b09ea7d5
GN
1159}
1160#else
1161void do_cpu_init(CPUState *env)
1162{
1163}
1164void do_cpu_sipi(CPUState *env)
1165{
1166}
1167#endif
This page took 0.676593 seconds and 4 git commands to generate.