]> git.proxmox.com Git - qemu.git/blob - target-i386/helper.c
x86: Fix INIT processing
[qemu.git] / target-i386 / helper.c
1 /*
2 * i386 helpers (without register variable usage)
3 *
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
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <signal.h>
25
26 #include "cpu.h"
27 #include "exec-all.h"
28 #include "qemu-common.h"
29 #include "kvm.h"
30
31 //#define DEBUG_MMU
32
33 /* NOTE: must be called outside the CPU execute loop */
34 void cpu_reset(CPUX86State *env)
35 {
36 int i;
37
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
43 memset(env, 0, offsetof(CPUX86State, breakpoints));
44
45 tlb_flush(env, 1);
46
47 env->old_exception = -1;
48
49 /* init to reset state */
50
51 #ifdef CONFIG_SOFTMMU
52 env->hflags |= HF_SOFTMMU_MASK;
53 #endif
54 env->hflags2 |= HF2_GIF_MASK;
55
56 cpu_x86_update_cr0(env, 0x60000010);
57 env->a20_mask = ~0x0;
58 env->smbase = 0x30000;
59
60 env->idt.limit = 0xffff;
61 env->gdt.limit = 0xffff;
62 env->ldt.limit = 0xffff;
63 env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
64 env->tr.limit = 0xffff;
65 env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
66
67 cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
68 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
69 DESC_R_MASK | DESC_A_MASK);
70 cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
71 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
72 DESC_A_MASK);
73 cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
74 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
75 DESC_A_MASK);
76 cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
77 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
78 DESC_A_MASK);
79 cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
80 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
81 DESC_A_MASK);
82 cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
83 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
84 DESC_A_MASK);
85
86 env->eip = 0xfff0;
87 env->regs[R_EDX] = env->cpuid_version;
88
89 env->eflags = 0x2;
90
91 /* FPU init */
92 for(i = 0;i < 8; i++)
93 env->fptags[i] = 1;
94 env->fpuc = 0x37f;
95
96 env->mxcsr = 0x1f80;
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);
103
104 env->mcg_status = 0;
105 }
106
107 void cpu_x86_close(CPUX86State *env)
108 {
109 qemu_free(env);
110 }
111
112 /***********************************************************/
113 /* x86 debug */
114
115 static const char *cc_op_str[] = {
116 "DYNAMIC",
117 "EFLAGS",
118
119 "MULB",
120 "MULW",
121 "MULL",
122 "MULQ",
123
124 "ADDB",
125 "ADDW",
126 "ADDL",
127 "ADDQ",
128
129 "ADCB",
130 "ADCW",
131 "ADCL",
132 "ADCQ",
133
134 "SUBB",
135 "SUBW",
136 "SUBL",
137 "SUBQ",
138
139 "SBBB",
140 "SBBW",
141 "SBBL",
142 "SBBQ",
143
144 "LOGICB",
145 "LOGICW",
146 "LOGICL",
147 "LOGICQ",
148
149 "INCB",
150 "INCW",
151 "INCL",
152 "INCQ",
153
154 "DECB",
155 "DECW",
156 "DECL",
157 "DECQ",
158
159 "SHLB",
160 "SHLW",
161 "SHLL",
162 "SHLQ",
163
164 "SARB",
165 "SARW",
166 "SARL",
167 "SARQ",
168 };
169
170 static void
171 cpu_x86_dump_seg_cache(CPUState *env, FILE *f,
172 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
173 const char *name, struct SegmentCache *sc)
174 {
175 #ifdef TARGET_X86_64
176 if (env->hflags & HF_CS64_MASK) {
177 cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
178 sc->selector, sc->base, sc->limit, sc->flags);
179 } else
180 #endif
181 {
182 cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
183 (uint32_t)sc->base, sc->limit, sc->flags);
184 }
185
186 if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
187 goto done;
188
189 cpu_fprintf(f, " DPL=%d ", (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT);
190 if (sc->flags & DESC_S_MASK) {
191 if (sc->flags & DESC_CS_MASK) {
192 cpu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" :
193 ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16"));
194 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-',
195 (sc->flags & DESC_R_MASK) ? 'R' : '-');
196 } else {
197 cpu_fprintf(f, (sc->flags & DESC_B_MASK) ? "DS " : "DS16");
198 cpu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-',
199 (sc->flags & DESC_W_MASK) ? 'W' : '-');
200 }
201 cpu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-');
202 } else {
203 static const char *sys_type_name[2][16] = {
204 { /* 32 bit mode */
205 "Reserved", "TSS16-avl", "LDT", "TSS16-busy",
206 "CallGate16", "TaskGate", "IntGate16", "TrapGate16",
207 "Reserved", "TSS32-avl", "Reserved", "TSS32-busy",
208 "CallGate32", "Reserved", "IntGate32", "TrapGate32"
209 },
210 { /* 64 bit mode */
211 "<hiword>", "Reserved", "LDT", "Reserved", "Reserved",
212 "Reserved", "Reserved", "Reserved", "Reserved",
213 "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64",
214 "Reserved", "IntGate64", "TrapGate64"
215 }
216 };
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]);
221 }
222 done:
223 cpu_fprintf(f, "\n");
224 }
225
226 void cpu_dump_state(CPUState *env, FILE *f,
227 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
228 int flags)
229 {
230 int eflags, i, nb;
231 char cc_op_name[32];
232 static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
233
234 cpu_synchronize_state(env);
235
236 eflags = env->eflags;
237 #ifdef TARGET_X86_64
238 if (env->hflags & HF_CS64_MASK) {
239 cpu_fprintf(f,
240 "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
241 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
242 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
243 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
244 "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
245 env->regs[R_EAX],
246 env->regs[R_EBX],
247 env->regs[R_ECX],
248 env->regs[R_EDX],
249 env->regs[R_ESI],
250 env->regs[R_EDI],
251 env->regs[R_EBP],
252 env->regs[R_ESP],
253 env->regs[8],
254 env->regs[9],
255 env->regs[10],
256 env->regs[11],
257 env->regs[12],
258 env->regs[13],
259 env->regs[14],
260 env->regs[15],
261 env->eip, eflags,
262 eflags & DF_MASK ? 'D' : '-',
263 eflags & CC_O ? 'O' : '-',
264 eflags & CC_S ? 'S' : '-',
265 eflags & CC_Z ? 'Z' : '-',
266 eflags & CC_A ? 'A' : '-',
267 eflags & CC_P ? 'P' : '-',
268 eflags & CC_C ? 'C' : '-',
269 env->hflags & HF_CPL_MASK,
270 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
271 (env->a20_mask >> 20) & 1,
272 (env->hflags >> HF_SMM_SHIFT) & 1,
273 env->halted);
274 } else
275 #endif
276 {
277 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
278 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
279 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
280 (uint32_t)env->regs[R_EAX],
281 (uint32_t)env->regs[R_EBX],
282 (uint32_t)env->regs[R_ECX],
283 (uint32_t)env->regs[R_EDX],
284 (uint32_t)env->regs[R_ESI],
285 (uint32_t)env->regs[R_EDI],
286 (uint32_t)env->regs[R_EBP],
287 (uint32_t)env->regs[R_ESP],
288 (uint32_t)env->eip, eflags,
289 eflags & DF_MASK ? 'D' : '-',
290 eflags & CC_O ? 'O' : '-',
291 eflags & CC_S ? 'S' : '-',
292 eflags & CC_Z ? 'Z' : '-',
293 eflags & CC_A ? 'A' : '-',
294 eflags & CC_P ? 'P' : '-',
295 eflags & CC_C ? 'C' : '-',
296 env->hflags & HF_CPL_MASK,
297 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
298 (env->a20_mask >> 20) & 1,
299 (env->hflags >> HF_SMM_SHIFT) & 1,
300 env->halted);
301 }
302
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
310 #ifdef TARGET_X86_64
311 if (env->hflags & HF_LMA_MASK) {
312 cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
313 env->gdt.base, env->gdt.limit);
314 cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
315 env->idt.base, env->idt.limit);
316 cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
317 (uint32_t)env->cr[0],
318 env->cr[2],
319 env->cr[3],
320 (uint32_t)env->cr[4]);
321 for(i = 0; i < 4; i++)
322 cpu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]);
323 cpu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n",
324 env->dr[6], env->dr[7]);
325 } else
326 #endif
327 {
328 cpu_fprintf(f, "GDT= %08x %08x\n",
329 (uint32_t)env->gdt.base, env->gdt.limit);
330 cpu_fprintf(f, "IDT= %08x %08x\n",
331 (uint32_t)env->idt.base, env->idt.limit);
332 cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
333 (uint32_t)env->cr[0],
334 (uint32_t)env->cr[2],
335 (uint32_t)env->cr[3],
336 (uint32_t)env->cr[4]);
337 for(i = 0; i < 4; i++)
338 cpu_fprintf(f, "DR%d=%08x ", i, env->dr[i]);
339 cpu_fprintf(f, "\nDR6=%08x DR7=%08x\n", env->dr[6], env->dr[7]);
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 }
358 }
359 cpu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer);
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 }
409 }
410 }
411
412 /***********************************************************/
413 /* x86 mmu */
414 /* XXX: add PGE support */
415
416 void cpu_x86_set_a20(CPUX86State *env, int a20_state)
417 {
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);
426
427 /* when a20 is changed, all the MMU mappings are invalid, so
428 we must flush everything */
429 tlb_flush(env, 1);
430 env->a20_mask = ~(1 << 20) | (a20_state << 20);
431 }
432 }
433
434 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
435 {
436 int pe_state;
437
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 }
445
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;
464
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));
473 }
474
475 /* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
476 the PDPT */
477 void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
478 {
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 }
486 }
487
488 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
489 {
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;
504
505 env->cr[4] = new_cr4;
506 }
507
508 #if defined(CONFIG_USER_ONLY)
509
510 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
511 int is_write, int mmu_idx, int is_softmmu)
512 {
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;
520 }
521
522 #else
523
524 /* XXX: This value should match the one returned by CPUID
525 * and in exec.c */
526 # if defined(TARGET_X86_64)
527 # define PHYS_ADDR_MASK 0xfffffff000LL
528 # else
529 # define PHYS_ADDR_MASK 0xffffff000LL
530 # endif
531
532 /* return value:
533 -1 = cannot handle fault
534 0 = nothing more to do
535 1 = generate PF fault
536 */
537 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
538 int is_write1, int mmu_idx, int is_softmmu)
539 {
540 uint64_t ptep, pte;
541 target_ulong pde_addr, pte_addr;
542 int error_code, is_dirty, prot, page_size, is_write, is_user;
543 target_phys_addr_t paddr;
544 uint32_t page_offset;
545 target_ulong vaddr, virt_addr;
546
547 is_user = mmu_idx == MMU_USER_IDX;
548 #if defined(DEBUG_MMU)
549 printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
550 addr, is_write1, is_user, env->eip);
551 #endif
552 is_write = is_write1 & 1;
553
554 if (!(env->cr[0] & CR0_PG_MASK)) {
555 pte = addr;
556 virt_addr = addr & TARGET_PAGE_MASK;
557 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
558 page_size = 4096;
559 goto do_mapping;
560 }
561
562 if (env->cr[4] & CR4_PAE_MASK) {
563 uint64_t pde, pdpe;
564 target_ulong pdpe_addr;
565
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 }
578
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;
623 }
624
625 pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
626 env->a20_mask;
627 pde = ldq_phys(pde_addr);
628 if (!(pde & PG_PRESENT_MASK)) {
629 error_code = 0;
630 goto do_fault;
631 }
632 if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
633 error_code = PG_ERROR_RSVD_MASK;
634 goto do_fault;
635 }
636 ptep &= pde ^ PG_NX_MASK;
637 if (pde & PG_PSE_MASK) {
638 /* 2 MB page */
639 page_size = 2048 * 1024;
640 ptep ^= PG_NX_MASK;
641 if ((ptep & PG_NX_MASK) && is_write1 == 2)
642 goto do_fault_protect;
643 if (is_user) {
644 if (!(ptep & PG_USER_MASK))
645 goto do_fault_protect;
646 if (is_write && !(ptep & PG_RW_MASK))
647 goto do_fault_protect;
648 } else {
649 if ((env->cr[0] & CR0_WP_MASK) &&
650 is_write && !(ptep & PG_RW_MASK))
651 goto do_fault_protect;
652 }
653 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
654 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
655 pde |= PG_ACCESSED_MASK;
656 if (is_dirty)
657 pde |= PG_DIRTY_MASK;
658 stl_phys_notdirty(pde_addr, pde);
659 }
660 /* align to page_size */
661 pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
662 virt_addr = addr & ~(page_size - 1);
663 } else {
664 /* 4 KB page */
665 if (!(pde & PG_ACCESSED_MASK)) {
666 pde |= PG_ACCESSED_MASK;
667 stl_phys_notdirty(pde_addr, pde);
668 }
669 pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
670 env->a20_mask;
671 pte = ldq_phys(pte_addr);
672 if (!(pte & PG_PRESENT_MASK)) {
673 error_code = 0;
674 goto do_fault;
675 }
676 if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
677 error_code = PG_ERROR_RSVD_MASK;
678 goto do_fault;
679 }
680 /* combine pde and pte nx, user and rw protections */
681 ptep &= pte ^ PG_NX_MASK;
682 ptep ^= PG_NX_MASK;
683 if ((ptep & PG_NX_MASK) && is_write1 == 2)
684 goto do_fault_protect;
685 if (is_user) {
686 if (!(ptep & PG_USER_MASK))
687 goto do_fault_protect;
688 if (is_write && !(ptep & PG_RW_MASK))
689 goto do_fault_protect;
690 } else {
691 if ((env->cr[0] & CR0_WP_MASK) &&
692 is_write && !(ptep & PG_RW_MASK))
693 goto do_fault_protect;
694 }
695 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
696 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
697 pte |= PG_ACCESSED_MASK;
698 if (is_dirty)
699 pte |= PG_DIRTY_MASK;
700 stl_phys_notdirty(pte_addr, pte);
701 }
702 page_size = 4096;
703 virt_addr = addr & ~0xfff;
704 pte = pte & (PHYS_ADDR_MASK | 0xfff);
705 }
706 } else {
707 uint32_t pde;
708
709 /* page directory entry */
710 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
711 env->a20_mask;
712 pde = ldl_phys(pde_addr);
713 if (!(pde & PG_PRESENT_MASK)) {
714 error_code = 0;
715 goto do_fault;
716 }
717 /* if PSE bit is set, then we use a 4MB page */
718 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
719 page_size = 4096 * 1024;
720 if (is_user) {
721 if (!(pde & PG_USER_MASK))
722 goto do_fault_protect;
723 if (is_write && !(pde & PG_RW_MASK))
724 goto do_fault_protect;
725 } else {
726 if ((env->cr[0] & CR0_WP_MASK) &&
727 is_write && !(pde & PG_RW_MASK))
728 goto do_fault_protect;
729 }
730 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
731 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
732 pde |= PG_ACCESSED_MASK;
733 if (is_dirty)
734 pde |= PG_DIRTY_MASK;
735 stl_phys_notdirty(pde_addr, pde);
736 }
737
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 }
746
747 /* page directory entry */
748 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
749 env->a20_mask;
750 pte = ldl_phys(pte_addr);
751 if (!(pte & PG_PRESENT_MASK)) {
752 error_code = 0;
753 goto do_fault;
754 }
755 /* combine pde and pte user and rw protections */
756 ptep = pte & pde;
757 if (is_user) {
758 if (!(ptep & PG_USER_MASK))
759 goto do_fault_protect;
760 if (is_write && !(ptep & PG_RW_MASK))
761 goto do_fault_protect;
762 } else {
763 if ((env->cr[0] & CR0_WP_MASK) &&
764 is_write && !(ptep & PG_RW_MASK))
765 goto do_fault_protect;
766 }
767 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
768 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
769 pte |= PG_ACCESSED_MASK;
770 if (is_dirty)
771 pte |= PG_DIRTY_MASK;
772 stl_phys_notdirty(pte_addr, pte);
773 }
774 page_size = 4096;
775 virt_addr = addr & ~0xfff;
776 }
777 }
778 /* the page can be put in the TLB */
779 prot = PAGE_READ;
780 if (!(ptep & PG_NX_MASK))
781 prot |= PAGE_EXEC;
782 if (pte & PG_DIRTY_MASK) {
783 /* only set write access if already dirty... otherwise wait
784 for dirty access */
785 if (is_user) {
786 if (ptep & PG_RW_MASK)
787 prot |= PAGE_WRITE;
788 } else {
789 if (!(env->cr[0] & CR0_WP_MASK) ||
790 (ptep & PG_RW_MASK))
791 prot |= PAGE_WRITE;
792 }
793 }
794 do_mapping:
795 pte = pte & env->a20_mask;
796
797 /* Even if 4MB pages, we map only one 4KB page in the cache to
798 avoid filling it too fast */
799 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
800 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
801 vaddr = virt_addr + page_offset;
802
803 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
804 return 0;
805 do_fault_protect:
806 error_code = PG_ERROR_P_MASK;
807 do_fault:
808 error_code |= (is_write << PG_ERROR_W_BIT);
809 if (is_user)
810 error_code |= PG_ERROR_U_MASK;
811 if (is_write1 == 2 &&
812 (env->efer & MSR_EFER_NXE) &&
813 (env->cr[4] & CR4_PAE_MASK))
814 error_code |= PG_ERROR_I_D_MASK;
815 if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
816 /* cr2 is not modified in case of exceptions */
817 stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
818 addr);
819 } else {
820 env->cr[2] = addr;
821 }
822 env->error_code = error_code;
823 env->exception_index = EXCP0E_PAGE;
824 return 1;
825 }
826
827 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
828 {
829 target_ulong pde_addr, pte_addr;
830 uint64_t pte;
831 target_phys_addr_t paddr;
832 uint32_t page_offset;
833 int page_size;
834
835 if (env->cr[4] & CR4_PAE_MASK) {
836 target_ulong pdpe_addr;
837 uint64_t pde, pdpe;
838
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;
868 }
869
870 pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
871 env->a20_mask;
872 pde = ldq_phys(pde_addr);
873 if (!(pde & PG_PRESENT_MASK)) {
874 return -1;
875 }
876 if (pde & PG_PSE_MASK) {
877 /* 2 MB page */
878 page_size = 2048 * 1024;
879 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
880 } else {
881 /* 4 KB page */
882 pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
883 env->a20_mask;
884 page_size = 4096;
885 pte = ldq_phys(pte_addr);
886 }
887 if (!(pte & PG_PRESENT_MASK))
888 return -1;
889 } else {
890 uint32_t pde;
891
892 if (!(env->cr[0] & CR0_PG_MASK)) {
893 pte = addr;
894 page_size = 4096;
895 } else {
896 /* page directory entry */
897 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
898 pde = ldl_phys(pde_addr);
899 if (!(pde & PG_PRESENT_MASK))
900 return -1;
901 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
902 pte = pde & ~0x003ff000; /* align to 4MB */
903 page_size = 4096 * 1024;
904 } else {
905 /* page directory entry */
906 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
907 pte = ldl_phys(pte_addr);
908 if (!(pte & PG_PRESENT_MASK))
909 return -1;
910 page_size = 4096;
911 }
912 }
913 pte = pte & env->a20_mask;
914 }
915
916 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
917 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
918 return paddr;
919 }
920
921 void 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
949 void hw_breakpoint_remove(CPUState *env, int index)
950 {
951 if (!env->cpu_breakpoint[index])
952 return;
953 switch (hw_breakpoint_type(env->dr[7], index)) {
954 case 0:
955 if (hw_breakpoint_enabled(env->dr[7], index))
956 cpu_breakpoint_remove_by_ref(env, env->cpu_breakpoint[index]);
957 break;
958 case 1:
959 case 3:
960 cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[index]);
961 break;
962 case 2:
963 /* No support for I/O watchpoints yet */
964 break;
965 }
966 }
967
968 int check_hw_breakpoints(CPUState *env, int force_dr6_update)
969 {
970 target_ulong dr6;
971 int reg, type;
972 int hit_enabled = 0;
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
990 static CPUDebugExcpHandler *prev_debug_excp_handler;
991
992 void raise_exception_env(int exception_index, CPUState *env);
993
994 static 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))
1002 raise_exception_env(EXCP01_DB, env);
1003 else
1004 cpu_resume_from_signal(env, NULL);
1005 }
1006 } else {
1007 QTAILQ_FOREACH(bp, &env->breakpoints, entry)
1008 if (bp->pc == env->eip) {
1009 if (bp->flags & BP_CPU) {
1010 check_hw_breakpoints(env, 1);
1011 raise_exception_env(EXCP01_DB, env);
1012 }
1013 break;
1014 }
1015 }
1016 if (prev_debug_excp_handler)
1017 prev_debug_excp_handler(env);
1018 }
1019
1020 /* This should come from sysemu.h - if we could include it here... */
1021 void qemu_system_reset_request(void);
1022
1023 void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
1024 uint64_t mcg_status, uint64_t addr, uint64_t misc)
1025 {
1026 uint64_t mcg_cap = cenv->mcg_cap;
1027 unsigned bank_num = mcg_cap & 0xff;
1028 uint64_t *banks = cenv->mce_banks;
1029
1030 if (bank >= bank_num || !(status & MCI_STATUS_VAL))
1031 return;
1032
1033 /*
1034 * if MSR_MCG_CTL is not all 1s, the uncorrected error
1035 * reporting is disabled
1036 */
1037 if ((status & MCI_STATUS_UC) && (mcg_cap & MCG_CTL_P) &&
1038 cenv->mcg_ctl != ~(uint64_t)0)
1039 return;
1040 banks += 4 * bank;
1041 /*
1042 * if MSR_MCi_CTL is not all 1s, the uncorrected error
1043 * reporting is disabled for the bank
1044 */
1045 if ((status & MCI_STATUS_UC) && banks[0] != ~(uint64_t)0)
1046 return;
1047 if (status & MCI_STATUS_UC) {
1048 if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
1049 !(cenv->cr[4] & CR4_MCE_MASK)) {
1050 fprintf(stderr, "injects mce exception while previous "
1051 "one is in progress!\n");
1052 qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1053 qemu_system_reset_request();
1054 return;
1055 }
1056 if (banks[1] & MCI_STATUS_VAL)
1057 status |= MCI_STATUS_OVER;
1058 banks[2] = addr;
1059 banks[3] = misc;
1060 cenv->mcg_status = mcg_status;
1061 banks[1] = status;
1062 cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
1063 } else if (!(banks[1] & MCI_STATUS_VAL)
1064 || !(banks[1] & MCI_STATUS_UC)) {
1065 if (banks[1] & MCI_STATUS_VAL)
1066 status |= MCI_STATUS_OVER;
1067 banks[2] = addr;
1068 banks[3] = misc;
1069 banks[1] = status;
1070 } else
1071 banks[1] |= MCI_STATUS_OVER;
1072 }
1073 #endif /* !CONFIG_USER_ONLY */
1074
1075 static void mce_init(CPUX86State *cenv)
1076 {
1077 unsigned int bank, bank_num;
1078
1079 if (((cenv->cpuid_version >> 8)&0xf) >= 6
1080 && (cenv->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)) {
1081 cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
1082 cenv->mcg_ctl = ~(uint64_t)0;
1083 bank_num = MCE_BANKS_DEF;
1084 for (bank = 0; bank < bank_num; bank++)
1085 cenv->mce_banks[bank*4] = ~(uint64_t)0;
1086 }
1087 }
1088
1089 int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
1090 target_ulong *base, unsigned int *limit,
1091 unsigned int *flags)
1092 {
1093 SegmentCache *dt;
1094 target_ulong ptr;
1095 uint32_t e1, e2;
1096 int index;
1097
1098 if (selector & 0x4)
1099 dt = &env->ldt;
1100 else
1101 dt = &env->gdt;
1102 index = selector & ~7;
1103 ptr = dt->base + index;
1104 if ((index + 7) > dt->limit
1105 || cpu_memory_rw_debug(env, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
1106 || cpu_memory_rw_debug(env, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
1107 return 0;
1108
1109 *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1110 *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1111 if (e2 & DESC_G_MASK)
1112 *limit = (*limit << 12) | 0xfff;
1113 *flags = e2;
1114
1115 return 1;
1116 }
1117
1118 CPUX86State *cpu_x86_init(const char *cpu_model)
1119 {
1120 CPUX86State *env;
1121 static int inited;
1122
1123 env = qemu_mallocz(sizeof(CPUX86State));
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 }
1140 mce_init(env);
1141
1142 qemu_init_vcpu(env);
1143
1144 return env;
1145 }
1146
1147 #if !defined(CONFIG_USER_ONLY)
1148 void do_cpu_init(CPUState *env)
1149 {
1150 int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
1151 cpu_reset(env);
1152 env->interrupt_request = sipi;
1153 apic_init_reset(env->apic_state);
1154 env->halted = !cpu_is_bsp(env);
1155 }
1156
1157 void do_cpu_sipi(CPUState *env)
1158 {
1159 apic_sipi(env->apic_state);
1160 }
1161 #else
1162 void do_cpu_init(CPUState *env)
1163 {
1164 }
1165 void do_cpu_sipi(CPUState *env)
1166 {
1167 }
1168 #endif