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