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