Add ARM RealView Emulation Baseboard.
[qemu/mini2440.git] / target-i386 / helper2.c
blob19af159f9240565ea6472e4ab139be40bc808bbf
1 /*
2 * i386 helpers (without register variable usage)
3 *
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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <signal.h>
26 #include <assert.h>
28 #include "cpu.h"
29 #include "exec-all.h"
31 //#define DEBUG_MMU
33 #ifdef USE_CODE_COPY
34 #include <asm/ldt.h>
35 #include <linux/unistd.h>
36 #include <linux/version.h>
38 int modify_ldt(int func, void *ptr, unsigned long bytecount)
40 return syscall(__NR_modify_ldt, func, ptr, bytecount);
43 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
44 #define modify_ldt_ldt_s user_desc
45 #endif
46 #endif /* USE_CODE_COPY */
48 CPUX86State *cpu_x86_init(void)
50 CPUX86State *env;
51 static int inited;
53 env = qemu_mallocz(sizeof(CPUX86State));
54 if (!env)
55 return NULL;
56 cpu_exec_init(env);
58 /* init various static tables */
59 if (!inited) {
60 inited = 1;
61 optimize_flags_init();
63 #ifdef USE_CODE_COPY
64 /* testing code for code copy case */
66 struct modify_ldt_ldt_s ldt;
68 ldt.entry_number = 1;
69 ldt.base_addr = (unsigned long)env;
70 ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
71 ldt.seg_32bit = 1;
72 ldt.contents = MODIFY_LDT_CONTENTS_DATA;
73 ldt.read_exec_only = 0;
74 ldt.limit_in_pages = 1;
75 ldt.seg_not_present = 0;
76 ldt.useable = 1;
77 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
79 asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
81 #endif
83 int family, model, stepping;
84 #ifdef TARGET_X86_64
85 env->cpuid_vendor1 = 0x68747541; /* "Auth" */
86 env->cpuid_vendor2 = 0x69746e65; /* "enti" */
87 env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */
88 family = 6;
89 model = 2;
90 stepping = 3;
91 #else
92 env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
93 env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
94 env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
95 #if 0
96 /* pentium 75-200 */
97 family = 5;
98 model = 2;
99 stepping = 11;
100 #else
101 /* pentium pro */
102 family = 6;
103 model = 3;
104 stepping = 3;
105 #endif
106 #endif
107 env->cpuid_level = 2;
108 env->cpuid_version = (family << 8) | (model << 4) | stepping;
109 env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE |
110 CPUID_TSC | CPUID_MSR | CPUID_MCE |
111 CPUID_CX8 | CPUID_PGE | CPUID_CMOV |
112 CPUID_PAT);
113 env->pat = 0x0007040600070406ULL;
114 env->cpuid_ext_features = CPUID_EXT_SSE3;
115 env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
116 env->cpuid_features |= CPUID_APIC;
117 env->cpuid_xlevel = 0;
119 const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
120 int c, len, i;
121 len = strlen(model_id);
122 for(i = 0; i < 48; i++) {
123 if (i >= len)
124 c = '\0';
125 else
126 c = model_id[i];
127 env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
130 #ifdef TARGET_X86_64
131 /* currently not enabled for std i386 because not fully tested */
132 env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
133 env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX;
134 env->cpuid_xlevel = 0x80000008;
136 /* these features are needed for Win64 and aren't fully implemented */
137 env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;
138 #endif
140 cpu_reset(env);
141 #ifdef USE_KQEMU
142 kqemu_init(env);
143 #endif
144 return env;
147 /* NOTE: must be called outside the CPU execute loop */
148 void cpu_reset(CPUX86State *env)
150 int i;
152 memset(env, 0, offsetof(CPUX86State, breakpoints));
154 tlb_flush(env, 1);
156 /* init to reset state */
158 #ifdef CONFIG_SOFTMMU
159 env->hflags |= HF_SOFTMMU_MASK;
160 #endif
162 cpu_x86_update_cr0(env, 0x60000010);
163 env->a20_mask = 0xffffffff;
165 env->idt.limit = 0xffff;
166 env->gdt.limit = 0xffff;
167 env->ldt.limit = 0xffff;
168 env->ldt.flags = DESC_P_MASK;
169 env->tr.limit = 0xffff;
170 env->tr.flags = DESC_P_MASK;
172 cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0);
173 cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
174 cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
175 cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
176 cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
177 cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
179 env->eip = 0xfff0;
180 env->regs[R_EDX] = 0x600; /* indicate P6 processor */
182 env->eflags = 0x2;
184 /* FPU init */
185 for(i = 0;i < 8; i++)
186 env->fptags[i] = 1;
187 env->fpuc = 0x37f;
189 env->mxcsr = 0x1f80;
192 void cpu_x86_close(CPUX86State *env)
194 free(env);
197 /***********************************************************/
198 /* x86 debug */
200 static const char *cc_op_str[] = {
201 "DYNAMIC",
202 "EFLAGS",
204 "MULB",
205 "MULW",
206 "MULL",
207 "MULQ",
209 "ADDB",
210 "ADDW",
211 "ADDL",
212 "ADDQ",
214 "ADCB",
215 "ADCW",
216 "ADCL",
217 "ADCQ",
219 "SUBB",
220 "SUBW",
221 "SUBL",
222 "SUBQ",
224 "SBBB",
225 "SBBW",
226 "SBBL",
227 "SBBQ",
229 "LOGICB",
230 "LOGICW",
231 "LOGICL",
232 "LOGICQ",
234 "INCB",
235 "INCW",
236 "INCL",
237 "INCQ",
239 "DECB",
240 "DECW",
241 "DECL",
242 "DECQ",
244 "SHLB",
245 "SHLW",
246 "SHLL",
247 "SHLQ",
249 "SARB",
250 "SARW",
251 "SARL",
252 "SARQ",
255 void cpu_dump_state(CPUState *env, FILE *f,
256 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
257 int flags)
259 int eflags, i, nb;
260 char cc_op_name[32];
261 static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
263 eflags = env->eflags;
264 #ifdef TARGET_X86_64
265 if (env->hflags & HF_CS64_MASK) {
266 cpu_fprintf(f,
267 "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
268 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
269 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
270 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
271 "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d HLT=%d\n",
272 env->regs[R_EAX],
273 env->regs[R_EBX],
274 env->regs[R_ECX],
275 env->regs[R_EDX],
276 env->regs[R_ESI],
277 env->regs[R_EDI],
278 env->regs[R_EBP],
279 env->regs[R_ESP],
280 env->regs[8],
281 env->regs[9],
282 env->regs[10],
283 env->regs[11],
284 env->regs[12],
285 env->regs[13],
286 env->regs[14],
287 env->regs[15],
288 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_HALTED_SHIFT) & 1);
300 } else
301 #endif
303 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
304 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
305 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d HLT=%d\n",
306 (uint32_t)env->regs[R_EAX],
307 (uint32_t)env->regs[R_EBX],
308 (uint32_t)env->regs[R_ECX],
309 (uint32_t)env->regs[R_EDX],
310 (uint32_t)env->regs[R_ESI],
311 (uint32_t)env->regs[R_EDI],
312 (uint32_t)env->regs[R_EBP],
313 (uint32_t)env->regs[R_ESP],
314 (uint32_t)env->eip, eflags,
315 eflags & DF_MASK ? 'D' : '-',
316 eflags & CC_O ? 'O' : '-',
317 eflags & CC_S ? 'S' : '-',
318 eflags & CC_Z ? 'Z' : '-',
319 eflags & CC_A ? 'A' : '-',
320 eflags & CC_P ? 'P' : '-',
321 eflags & CC_C ? 'C' : '-',
322 env->hflags & HF_CPL_MASK,
323 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
324 (env->a20_mask >> 20) & 1,
325 (env->hflags >> HF_HALTED_SHIFT) & 1);
328 #ifdef TARGET_X86_64
329 if (env->hflags & HF_LMA_MASK) {
330 for(i = 0; i < 6; i++) {
331 SegmentCache *sc = &env->segs[i];
332 cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
333 seg_name[i],
334 sc->selector,
335 sc->base,
336 sc->limit,
337 sc->flags);
339 cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
340 env->ldt.selector,
341 env->ldt.base,
342 env->ldt.limit,
343 env->ldt.flags);
344 cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
345 env->tr.selector,
346 env->tr.base,
347 env->tr.limit,
348 env->tr.flags);
349 cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
350 env->gdt.base, env->gdt.limit);
351 cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
352 env->idt.base, env->idt.limit);
353 cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
354 (uint32_t)env->cr[0],
355 env->cr[2],
356 env->cr[3],
357 (uint32_t)env->cr[4]);
358 } else
359 #endif
361 for(i = 0; i < 6; i++) {
362 SegmentCache *sc = &env->segs[i];
363 cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
364 seg_name[i],
365 sc->selector,
366 (uint32_t)sc->base,
367 sc->limit,
368 sc->flags);
370 cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
371 env->ldt.selector,
372 (uint32_t)env->ldt.base,
373 env->ldt.limit,
374 env->ldt.flags);
375 cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
376 env->tr.selector,
377 (uint32_t)env->tr.base,
378 env->tr.limit,
379 env->tr.flags);
380 cpu_fprintf(f, "GDT= %08x %08x\n",
381 (uint32_t)env->gdt.base, env->gdt.limit);
382 cpu_fprintf(f, "IDT= %08x %08x\n",
383 (uint32_t)env->idt.base, env->idt.limit);
384 cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
385 (uint32_t)env->cr[0],
386 (uint32_t)env->cr[2],
387 (uint32_t)env->cr[3],
388 (uint32_t)env->cr[4]);
390 if (flags & X86_DUMP_CCOP) {
391 if ((unsigned)env->cc_op < CC_OP_NB)
392 snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
393 else
394 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
395 #ifdef TARGET_X86_64
396 if (env->hflags & HF_CS64_MASK) {
397 cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
398 env->cc_src, env->cc_dst,
399 cc_op_name);
400 } else
401 #endif
403 cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
404 (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
405 cc_op_name);
408 if (flags & X86_DUMP_FPU) {
409 int fptag;
410 fptag = 0;
411 for(i = 0; i < 8; i++) {
412 fptag |= ((!env->fptags[i]) << i);
414 cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
415 env->fpuc,
416 (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
417 env->fpstt,
418 fptag,
419 env->mxcsr);
420 for(i=0;i<8;i++) {
421 #if defined(USE_X86LDOUBLE)
422 union {
423 long double d;
424 struct {
425 uint64_t lower;
426 uint16_t upper;
427 } l;
428 } tmp;
429 tmp.d = env->fpregs[i].d;
430 cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
431 i, tmp.l.lower, tmp.l.upper);
432 #else
433 cpu_fprintf(f, "FPR%d=%016" PRIx64,
434 i, env->fpregs[i].mmx.q);
435 #endif
436 if ((i & 1) == 1)
437 cpu_fprintf(f, "\n");
438 else
439 cpu_fprintf(f, " ");
441 if (env->hflags & HF_CS64_MASK)
442 nb = 16;
443 else
444 nb = 8;
445 for(i=0;i<nb;i++) {
446 cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
448 env->xmm_regs[i].XMM_L(3),
449 env->xmm_regs[i].XMM_L(2),
450 env->xmm_regs[i].XMM_L(1),
451 env->xmm_regs[i].XMM_L(0));
452 if ((i & 1) == 1)
453 cpu_fprintf(f, "\n");
454 else
455 cpu_fprintf(f, " ");
460 /***********************************************************/
461 /* x86 mmu */
462 /* XXX: add PGE support */
464 void cpu_x86_set_a20(CPUX86State *env, int a20_state)
466 a20_state = (a20_state != 0);
467 if (a20_state != ((env->a20_mask >> 20) & 1)) {
468 #if defined(DEBUG_MMU)
469 printf("A20 update: a20=%d\n", a20_state);
470 #endif
471 /* if the cpu is currently executing code, we must unlink it and
472 all the potentially executing TB */
473 cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
475 /* when a20 is changed, all the MMU mappings are invalid, so
476 we must flush everything */
477 tlb_flush(env, 1);
478 env->a20_mask = 0xffefffff | (a20_state << 20);
482 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
484 int pe_state;
486 #if defined(DEBUG_MMU)
487 printf("CR0 update: CR0=0x%08x\n", new_cr0);
488 #endif
489 if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
490 (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
491 tlb_flush(env, 1);
494 #ifdef TARGET_X86_64
495 if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
496 (env->efer & MSR_EFER_LME)) {
497 /* enter in long mode */
498 /* XXX: generate an exception */
499 if (!(env->cr[4] & CR4_PAE_MASK))
500 return;
501 env->efer |= MSR_EFER_LMA;
502 env->hflags |= HF_LMA_MASK;
503 } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
504 (env->efer & MSR_EFER_LMA)) {
505 /* exit long mode */
506 env->efer &= ~MSR_EFER_LMA;
507 env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
508 env->eip &= 0xffffffff;
510 #endif
511 env->cr[0] = new_cr0 | CR0_ET_MASK;
513 /* update PE flag in hidden flags */
514 pe_state = (env->cr[0] & CR0_PE_MASK);
515 env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
516 /* ensure that ADDSEG is always set in real mode */
517 env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
518 /* update FPU flags */
519 env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
520 ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
523 /* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
524 the PDPT */
525 void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
527 env->cr[3] = new_cr3;
528 if (env->cr[0] & CR0_PG_MASK) {
529 #if defined(DEBUG_MMU)
530 printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
531 #endif
532 tlb_flush(env, 0);
536 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
538 #if defined(DEBUG_MMU)
539 printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
540 #endif
541 if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
542 (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
543 tlb_flush(env, 1);
545 /* SSE handling */
546 if (!(env->cpuid_features & CPUID_SSE))
547 new_cr4 &= ~CR4_OSFXSR_MASK;
548 if (new_cr4 & CR4_OSFXSR_MASK)
549 env->hflags |= HF_OSFXSR_MASK;
550 else
551 env->hflags &= ~HF_OSFXSR_MASK;
553 env->cr[4] = new_cr4;
556 /* XXX: also flush 4MB pages */
557 void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
559 tlb_flush_page(env, addr);
562 #if defined(CONFIG_USER_ONLY)
564 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
565 int is_write, int is_user, int is_softmmu)
567 /* user mode only emulation */
568 is_write &= 1;
569 env->cr[2] = addr;
570 env->error_code = (is_write << PG_ERROR_W_BIT);
571 env->error_code |= PG_ERROR_U_MASK;
572 env->exception_index = EXCP0E_PAGE;
573 return 1;
576 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
578 return addr;
581 #else
583 #define PHYS_ADDR_MASK 0xfffff000
585 /* return value:
586 -1 = cannot handle fault
587 0 = nothing more to do
588 1 = generate PF fault
589 2 = soft MMU activation required for this block
591 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
592 int is_write1, int is_user, int is_softmmu)
594 uint64_t ptep, pte;
595 uint32_t pdpe_addr, pde_addr, pte_addr;
596 int error_code, is_dirty, prot, page_size, ret, is_write;
597 unsigned long paddr, page_offset;
598 target_ulong vaddr, virt_addr;
600 #if defined(DEBUG_MMU)
601 printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
602 addr, is_write1, is_user, env->eip);
603 #endif
604 is_write = is_write1 & 1;
606 if (!(env->cr[0] & CR0_PG_MASK)) {
607 pte = addr;
608 virt_addr = addr & TARGET_PAGE_MASK;
609 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
610 page_size = 4096;
611 goto do_mapping;
614 if (env->cr[4] & CR4_PAE_MASK) {
615 uint64_t pde, pdpe;
617 /* XXX: we only use 32 bit physical addresses */
618 #ifdef TARGET_X86_64
619 if (env->hflags & HF_LMA_MASK) {
620 uint32_t pml4e_addr;
621 uint64_t pml4e;
622 int32_t sext;
624 /* test virtual address sign extension */
625 sext = (int64_t)addr >> 47;
626 if (sext != 0 && sext != -1) {
627 env->error_code = 0;
628 env->exception_index = EXCP0D_GPF;
629 return 1;
632 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
633 env->a20_mask;
634 pml4e = ldq_phys(pml4e_addr);
635 if (!(pml4e & PG_PRESENT_MASK)) {
636 error_code = 0;
637 goto do_fault;
639 if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
640 error_code = PG_ERROR_RSVD_MASK;
641 goto do_fault;
643 if (!(pml4e & PG_ACCESSED_MASK)) {
644 pml4e |= PG_ACCESSED_MASK;
645 stl_phys_notdirty(pml4e_addr, pml4e);
647 ptep = pml4e ^ PG_NX_MASK;
648 pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
649 env->a20_mask;
650 pdpe = ldq_phys(pdpe_addr);
651 if (!(pdpe & PG_PRESENT_MASK)) {
652 error_code = 0;
653 goto do_fault;
655 if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
656 error_code = PG_ERROR_RSVD_MASK;
657 goto do_fault;
659 ptep &= pdpe ^ PG_NX_MASK;
660 if (!(pdpe & PG_ACCESSED_MASK)) {
661 pdpe |= PG_ACCESSED_MASK;
662 stl_phys_notdirty(pdpe_addr, pdpe);
664 } else
665 #endif
667 /* XXX: load them when cr3 is loaded ? */
668 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) &
669 env->a20_mask;
670 pdpe = ldq_phys(pdpe_addr);
671 if (!(pdpe & PG_PRESENT_MASK)) {
672 error_code = 0;
673 goto do_fault;
675 ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
678 pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
679 env->a20_mask;
680 pde = ldq_phys(pde_addr);
681 if (!(pde & PG_PRESENT_MASK)) {
682 error_code = 0;
683 goto do_fault;
685 if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
686 error_code = PG_ERROR_RSVD_MASK;
687 goto do_fault;
689 ptep &= pde ^ PG_NX_MASK;
690 if (pde & PG_PSE_MASK) {
691 /* 2 MB page */
692 page_size = 2048 * 1024;
693 ptep ^= PG_NX_MASK;
694 if ((ptep & PG_NX_MASK) && is_write1 == 2)
695 goto do_fault_protect;
696 if (is_user) {
697 if (!(ptep & PG_USER_MASK))
698 goto do_fault_protect;
699 if (is_write && !(ptep & PG_RW_MASK))
700 goto do_fault_protect;
701 } else {
702 if ((env->cr[0] & CR0_WP_MASK) &&
703 is_write && !(ptep & PG_RW_MASK))
704 goto do_fault_protect;
706 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
707 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
708 pde |= PG_ACCESSED_MASK;
709 if (is_dirty)
710 pde |= PG_DIRTY_MASK;
711 stl_phys_notdirty(pde_addr, pde);
713 /* align to page_size */
714 pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
715 virt_addr = addr & ~(page_size - 1);
716 } else {
717 /* 4 KB page */
718 if (!(pde & PG_ACCESSED_MASK)) {
719 pde |= PG_ACCESSED_MASK;
720 stl_phys_notdirty(pde_addr, pde);
722 pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
723 env->a20_mask;
724 pte = ldq_phys(pte_addr);
725 if (!(pte & PG_PRESENT_MASK)) {
726 error_code = 0;
727 goto do_fault;
729 if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
730 error_code = PG_ERROR_RSVD_MASK;
731 goto do_fault;
733 /* combine pde and pte nx, user and rw protections */
734 ptep &= pte ^ PG_NX_MASK;
735 ptep ^= PG_NX_MASK;
736 if ((ptep & PG_NX_MASK) && is_write1 == 2)
737 goto do_fault_protect;
738 if (is_user) {
739 if (!(ptep & PG_USER_MASK))
740 goto do_fault_protect;
741 if (is_write && !(ptep & PG_RW_MASK))
742 goto do_fault_protect;
743 } else {
744 if ((env->cr[0] & CR0_WP_MASK) &&
745 is_write && !(ptep & PG_RW_MASK))
746 goto do_fault_protect;
748 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
749 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
750 pte |= PG_ACCESSED_MASK;
751 if (is_dirty)
752 pte |= PG_DIRTY_MASK;
753 stl_phys_notdirty(pte_addr, pte);
755 page_size = 4096;
756 virt_addr = addr & ~0xfff;
757 pte = pte & (PHYS_ADDR_MASK | 0xfff);
759 } else {
760 uint32_t pde;
762 /* page directory entry */
763 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) &
764 env->a20_mask;
765 pde = ldl_phys(pde_addr);
766 if (!(pde & PG_PRESENT_MASK)) {
767 error_code = 0;
768 goto do_fault;
770 /* if PSE bit is set, then we use a 4MB page */
771 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
772 page_size = 4096 * 1024;
773 if (is_user) {
774 if (!(pde & PG_USER_MASK))
775 goto do_fault_protect;
776 if (is_write && !(pde & PG_RW_MASK))
777 goto do_fault_protect;
778 } else {
779 if ((env->cr[0] & CR0_WP_MASK) &&
780 is_write && !(pde & PG_RW_MASK))
781 goto do_fault_protect;
783 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
784 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
785 pde |= PG_ACCESSED_MASK;
786 if (is_dirty)
787 pde |= PG_DIRTY_MASK;
788 stl_phys_notdirty(pde_addr, pde);
791 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
792 ptep = pte;
793 virt_addr = addr & ~(page_size - 1);
794 } else {
795 if (!(pde & PG_ACCESSED_MASK)) {
796 pde |= PG_ACCESSED_MASK;
797 stl_phys_notdirty(pde_addr, pde);
800 /* page directory entry */
801 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
802 env->a20_mask;
803 pte = ldl_phys(pte_addr);
804 if (!(pte & PG_PRESENT_MASK)) {
805 error_code = 0;
806 goto do_fault;
808 /* combine pde and pte user and rw protections */
809 ptep = pte & pde;
810 if (is_user) {
811 if (!(ptep & PG_USER_MASK))
812 goto do_fault_protect;
813 if (is_write && !(ptep & PG_RW_MASK))
814 goto do_fault_protect;
815 } else {
816 if ((env->cr[0] & CR0_WP_MASK) &&
817 is_write && !(ptep & PG_RW_MASK))
818 goto do_fault_protect;
820 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
821 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
822 pte |= PG_ACCESSED_MASK;
823 if (is_dirty)
824 pte |= PG_DIRTY_MASK;
825 stl_phys_notdirty(pte_addr, pte);
827 page_size = 4096;
828 virt_addr = addr & ~0xfff;
831 /* the page can be put in the TLB */
832 prot = PAGE_READ;
833 if (!(ptep & PG_NX_MASK))
834 prot |= PAGE_EXEC;
835 if (pte & PG_DIRTY_MASK) {
836 /* only set write access if already dirty... otherwise wait
837 for dirty access */
838 if (is_user) {
839 if (ptep & PG_RW_MASK)
840 prot |= PAGE_WRITE;
841 } else {
842 if (!(env->cr[0] & CR0_WP_MASK) ||
843 (ptep & PG_RW_MASK))
844 prot |= PAGE_WRITE;
847 do_mapping:
848 pte = pte & env->a20_mask;
850 /* Even if 4MB pages, we map only one 4KB page in the cache to
851 avoid filling it too fast */
852 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
853 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
854 vaddr = virt_addr + page_offset;
856 ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
857 return ret;
858 do_fault_protect:
859 error_code = PG_ERROR_P_MASK;
860 do_fault:
861 env->cr[2] = addr;
862 error_code |= (is_write << PG_ERROR_W_BIT);
863 if (is_user)
864 error_code |= PG_ERROR_U_MASK;
865 if (is_write1 == 2 &&
866 (env->efer & MSR_EFER_NXE) &&
867 (env->cr[4] & CR4_PAE_MASK))
868 error_code |= PG_ERROR_I_D_MASK;
869 env->error_code = error_code;
870 env->exception_index = EXCP0E_PAGE;
871 return 1;
874 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
876 uint32_t pde_addr, pte_addr;
877 uint32_t pde, pte, paddr, page_offset, page_size;
879 if (env->cr[4] & CR4_PAE_MASK) {
880 uint32_t pdpe_addr, pde_addr, pte_addr;
881 uint32_t pdpe;
883 /* XXX: we only use 32 bit physical addresses */
884 #ifdef TARGET_X86_64
885 if (env->hflags & HF_LMA_MASK) {
886 uint32_t pml4e_addr, pml4e;
887 int32_t sext;
889 /* test virtual address sign extension */
890 sext = (int64_t)addr >> 47;
891 if (sext != 0 && sext != -1)
892 return -1;
894 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
895 env->a20_mask;
896 pml4e = ldl_phys(pml4e_addr);
897 if (!(pml4e & PG_PRESENT_MASK))
898 return -1;
900 pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
901 env->a20_mask;
902 pdpe = ldl_phys(pdpe_addr);
903 if (!(pdpe & PG_PRESENT_MASK))
904 return -1;
905 } else
906 #endif
908 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) &
909 env->a20_mask;
910 pdpe = ldl_phys(pdpe_addr);
911 if (!(pdpe & PG_PRESENT_MASK))
912 return -1;
915 pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
916 env->a20_mask;
917 pde = ldl_phys(pde_addr);
918 if (!(pde & PG_PRESENT_MASK)) {
919 return -1;
921 if (pde & PG_PSE_MASK) {
922 /* 2 MB page */
923 page_size = 2048 * 1024;
924 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
925 } else {
926 /* 4 KB page */
927 pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
928 env->a20_mask;
929 page_size = 4096;
930 pte = ldl_phys(pte_addr);
932 } else {
933 if (!(env->cr[0] & CR0_PG_MASK)) {
934 pte = addr;
935 page_size = 4096;
936 } else {
937 /* page directory entry */
938 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask;
939 pde = ldl_phys(pde_addr);
940 if (!(pde & PG_PRESENT_MASK))
941 return -1;
942 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
943 pte = pde & ~0x003ff000; /* align to 4MB */
944 page_size = 4096 * 1024;
945 } else {
946 /* page directory entry */
947 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
948 pte = ldl_phys(pte_addr);
949 if (!(pte & PG_PRESENT_MASK))
950 return -1;
951 page_size = 4096;
954 pte = pte & env->a20_mask;
957 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
958 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
959 return paddr;
961 #endif /* !CONFIG_USER_ONLY */
963 #if defined(USE_CODE_COPY)
964 struct fpstate {
965 uint16_t fpuc;
966 uint16_t dummy1;
967 uint16_t fpus;
968 uint16_t dummy2;
969 uint16_t fptag;
970 uint16_t dummy3;
972 uint32_t fpip;
973 uint32_t fpcs;
974 uint32_t fpoo;
975 uint32_t fpos;
976 uint8_t fpregs1[8 * 10];
979 void restore_native_fp_state(CPUState *env)
981 int fptag, i, j;
982 struct fpstate fp1, *fp = &fp1;
984 fp->fpuc = env->fpuc;
985 fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
986 fptag = 0;
987 for (i=7; i>=0; i--) {
988 fptag <<= 2;
989 if (env->fptags[i]) {
990 fptag |= 3;
991 } else {
992 /* the FPU automatically computes it */
995 fp->fptag = fptag;
996 j = env->fpstt;
997 for(i = 0;i < 8; i++) {
998 memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
999 j = (j + 1) & 7;
1001 asm volatile ("frstor %0" : "=m" (*fp));
1002 env->native_fp_regs = 1;
1005 void save_native_fp_state(CPUState *env)
1007 int fptag, i, j;
1008 uint16_t fpuc;
1009 struct fpstate fp1, *fp = &fp1;
1011 asm volatile ("fsave %0" : : "m" (*fp));
1012 env->fpuc = fp->fpuc;
1013 env->fpstt = (fp->fpus >> 11) & 7;
1014 env->fpus = fp->fpus & ~0x3800;
1015 fptag = fp->fptag;
1016 for(i = 0;i < 8; i++) {
1017 env->fptags[i] = ((fptag & 3) == 3);
1018 fptag >>= 2;
1020 j = env->fpstt;
1021 for(i = 0;i < 8; i++) {
1022 memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
1023 j = (j + 1) & 7;
1025 /* we must restore the default rounding state */
1026 /* XXX: we do not restore the exception state */
1027 fpuc = 0x037f | (env->fpuc & (3 << 10));
1028 asm volatile("fldcw %0" : : "m" (fpuc));
1029 env->native_fp_regs = 0;
1031 #endif