Fix warning about incompatible types
[qemu/mini2440.git] / target-i386 / helper.c
blob94c5c748bfa7e0fa4262102b770923781f270ab0
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, 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"
30 #include "svm.h"
31 #include "qemu-common.h"
33 //#define DEBUG_MMU
35 static int cpu_x86_register (CPUX86State *env, const char *cpu_model);
37 static void add_flagname_to_bitmaps(char *flagname, uint32_t *features,
38 uint32_t *ext_features,
39 uint32_t *ext2_features,
40 uint32_t *ext3_features)
42 int i;
43 /* feature flags taken from "Intel Processor Identification and the CPUID
44 * Instruction" and AMD's "CPUID Specification". In cases of disagreement
45 * about feature names, the Linux name is used. */
46 static const char *feature_name[] = {
47 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
48 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
49 "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
50 "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
52 static const char *ext_feature_name[] = {
53 "pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
54 "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
55 NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
56 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
58 static const char *ext2_feature_name[] = {
59 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
60 "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mttr", "pge", "mca", "cmov",
61 "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
62 "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
64 static const char *ext3_feature_name[] = {
65 "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
66 "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
67 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
68 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
71 for ( i = 0 ; i < 32 ; i++ )
72 if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
73 *features |= 1 << i;
74 return;
76 for ( i = 0 ; i < 32 ; i++ )
77 if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
78 *ext_features |= 1 << i;
79 return;
81 for ( i = 0 ; i < 32 ; i++ )
82 if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
83 *ext2_features |= 1 << i;
84 return;
86 for ( i = 0 ; i < 32 ; i++ )
87 if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
88 *ext3_features |= 1 << i;
89 return;
91 fprintf(stderr, "CPU feature %s not found\n", flagname);
94 CPUX86State *cpu_x86_init(const char *cpu_model)
96 CPUX86State *env;
97 static int inited;
99 env = qemu_mallocz(sizeof(CPUX86State));
100 if (!env)
101 return NULL;
102 cpu_exec_init(env);
103 env->cpu_model_str = cpu_model;
105 /* init various static tables */
106 if (!inited) {
107 inited = 1;
108 optimize_flags_init();
110 if (cpu_x86_register(env, cpu_model) < 0) {
111 cpu_x86_close(env);
112 return NULL;
114 cpu_reset(env);
115 #ifdef USE_KQEMU
116 kqemu_init(env);
117 #endif
118 return env;
121 typedef struct x86_def_t {
122 const char *name;
123 uint32_t level;
124 uint32_t vendor1, vendor2, vendor3;
125 int family;
126 int model;
127 int stepping;
128 uint32_t features, ext_features, ext2_features, ext3_features;
129 uint32_t xlevel;
130 char model_id[48];
131 } x86_def_t;
133 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
134 #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
135 CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX)
136 #define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
137 CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
138 CPUID_PSE36 | CPUID_FXSR)
139 #define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
140 #define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
141 CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
142 CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
143 CPUID_PAE | CPUID_SEP | CPUID_APIC)
144 static x86_def_t x86_defs[] = {
145 #ifdef TARGET_X86_64
147 .name = "qemu64",
148 .level = 2,
149 .vendor1 = CPUID_VENDOR_AMD_1,
150 .vendor2 = CPUID_VENDOR_AMD_2,
151 .vendor3 = CPUID_VENDOR_AMD_3,
152 .family = 6,
153 .model = 2,
154 .stepping = 3,
155 .features = PPRO_FEATURES |
156 /* these features are needed for Win64 and aren't fully implemented */
157 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
158 /* this feature is needed for Solaris and isn't fully implemented */
159 CPUID_PSE36,
160 .ext_features = CPUID_EXT_SSE3,
161 .ext2_features = (PPRO_FEATURES & 0x0183F3FF) |
162 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
163 CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
164 .ext3_features = CPUID_EXT3_SVM,
165 .xlevel = 0x8000000A,
166 .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
169 .name = "core2duo",
170 .level = 10,
171 .family = 6,
172 .model = 15,
173 .stepping = 11,
174 /* The original CPU also implements these features:
175 CPUID_VME, CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
176 CPUID_TM, CPUID_PBE */
177 .features = PPRO_FEATURES |
178 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
179 CPUID_PSE36,
180 /* The original CPU also implements these ext features:
181 CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
182 CPUID_EXT_TM2, CPUID_EXT_CX16, CPUID_EXT_XTPR, CPUID_EXT_PDCM */
183 .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3,
184 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
185 /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */
186 .xlevel = 0x8000000A,
187 .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz",
189 #endif
191 .name = "qemu32",
192 .level = 2,
193 .family = 6,
194 .model = 3,
195 .stepping = 3,
196 .features = PPRO_FEATURES,
197 .ext_features = CPUID_EXT_SSE3,
198 .xlevel = 0,
199 .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
202 .name = "486",
203 .level = 0,
204 .family = 4,
205 .model = 0,
206 .stepping = 0,
207 .features = I486_FEATURES,
208 .xlevel = 0,
211 .name = "pentium",
212 .level = 1,
213 .family = 5,
214 .model = 4,
215 .stepping = 3,
216 .features = PENTIUM_FEATURES,
217 .xlevel = 0,
220 .name = "pentium2",
221 .level = 2,
222 .family = 6,
223 .model = 5,
224 .stepping = 2,
225 .features = PENTIUM2_FEATURES,
226 .xlevel = 0,
229 .name = "pentium3",
230 .level = 2,
231 .family = 6,
232 .model = 7,
233 .stepping = 3,
234 .features = PENTIUM3_FEATURES,
235 .xlevel = 0,
238 .name = "athlon",
239 .level = 2,
240 .vendor1 = 0x68747541, /* "Auth" */
241 .vendor2 = 0x69746e65, /* "enti" */
242 .vendor3 = 0x444d4163, /* "cAMD" */
243 .family = 6,
244 .model = 2,
245 .stepping = 3,
246 .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
247 .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
248 .xlevel = 0x80000008,
249 /* XXX: put another string ? */
250 .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
253 .name = "n270",
254 /* original is on level 10 */
255 .level = 5,
256 .family = 6,
257 .model = 28,
258 .stepping = 2,
259 .features = PPRO_FEATURES |
260 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME,
261 /* Missing: CPUID_DTS | CPUID_ACPI | CPUID_SS |
262 * CPUID_HT | CPUID_TM | CPUID_PBE */
263 /* Some CPUs got no CPUID_SEP */
264 .ext_features = CPUID_EXT_MONITOR |
265 CPUID_EXT_SSE3 /* PNI */, CPUID_EXT_SSSE3,
266 /* Missing: CPUID_EXT_DSCPL | CPUID_EXT_EST |
267 * CPUID_EXT_TM2 | CPUID_EXT_XTPR */
268 .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_NX,
269 /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */
270 .xlevel = 0x8000000A,
271 .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz",
275 static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
277 unsigned int i;
278 x86_def_t *def;
280 char *s = strdup(cpu_model);
281 char *featurestr, *name = strtok(s, ",");
282 uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
283 uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
284 int family = -1, model = -1, stepping = -1;
286 def = NULL;
287 for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) {
288 if (strcmp(name, x86_defs[i].name) == 0) {
289 def = &x86_defs[i];
290 break;
293 if (!def)
294 goto error;
295 memcpy(x86_cpu_def, def, sizeof(*def));
297 featurestr = strtok(NULL, ",");
299 while (featurestr) {
300 char *val;
301 if (featurestr[0] == '+') {
302 add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
303 } else if (featurestr[0] == '-') {
304 add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features);
305 } else if ((val = strchr(featurestr, '='))) {
306 *val = 0; val++;
307 if (!strcmp(featurestr, "family")) {
308 char *err;
309 family = strtol(val, &err, 10);
310 if (!*val || *err || family < 0) {
311 fprintf(stderr, "bad numerical value %s\n", val);
312 goto error;
314 x86_cpu_def->family = family;
315 } else if (!strcmp(featurestr, "model")) {
316 char *err;
317 model = strtol(val, &err, 10);
318 if (!*val || *err || model < 0 || model > 0xf) {
319 fprintf(stderr, "bad numerical value %s\n", val);
320 goto error;
322 x86_cpu_def->model = model;
323 } else if (!strcmp(featurestr, "stepping")) {
324 char *err;
325 stepping = strtol(val, &err, 10);
326 if (!*val || *err || stepping < 0 || stepping > 0xf) {
327 fprintf(stderr, "bad numerical value %s\n", val);
328 goto error;
330 x86_cpu_def->stepping = stepping;
331 } else if (!strcmp(featurestr, "vendor")) {
332 if (strlen(val) != 12) {
333 fprintf(stderr, "vendor string must be 12 chars long\n");
334 goto error;
336 x86_cpu_def->vendor1 = 0;
337 x86_cpu_def->vendor2 = 0;
338 x86_cpu_def->vendor3 = 0;
339 for(i = 0; i < 4; i++) {
340 x86_cpu_def->vendor1 |= ((uint8_t)val[i ]) << (8 * i);
341 x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
342 x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
344 } else if (!strcmp(featurestr, "model_id")) {
345 pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
346 val);
347 } else {
348 fprintf(stderr, "unrecognized feature %s\n", featurestr);
349 goto error;
351 } else {
352 fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
353 goto error;
355 featurestr = strtok(NULL, ",");
357 x86_cpu_def->features |= plus_features;
358 x86_cpu_def->ext_features |= plus_ext_features;
359 x86_cpu_def->ext2_features |= plus_ext2_features;
360 x86_cpu_def->ext3_features |= plus_ext3_features;
361 x86_cpu_def->features &= ~minus_features;
362 x86_cpu_def->ext_features &= ~minus_ext_features;
363 x86_cpu_def->ext2_features &= ~minus_ext2_features;
364 x86_cpu_def->ext3_features &= ~minus_ext3_features;
365 free(s);
366 return 0;
368 error:
369 free(s);
370 return -1;
373 void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
375 unsigned int i;
377 for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++)
378 (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
381 static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
383 x86_def_t def1, *def = &def1;
385 if (cpu_x86_find_by_name(def, cpu_model) < 0)
386 return -1;
387 if (def->vendor1) {
388 env->cpuid_vendor1 = def->vendor1;
389 env->cpuid_vendor2 = def->vendor2;
390 env->cpuid_vendor3 = def->vendor3;
391 } else {
392 env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
393 env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
394 env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
396 env->cpuid_level = def->level;
397 env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
398 env->cpuid_features = def->features;
399 env->pat = 0x0007040600070406ULL;
400 env->cpuid_ext_features = def->ext_features;
401 env->cpuid_ext2_features = def->ext2_features;
402 env->cpuid_xlevel = def->xlevel;
403 env->cpuid_ext3_features = def->ext3_features;
405 const char *model_id = def->model_id;
406 int c, len, i;
407 if (!model_id)
408 model_id = "";
409 len = strlen(model_id);
410 for(i = 0; i < 48; i++) {
411 if (i >= len)
412 c = '\0';
413 else
414 c = (uint8_t)model_id[i];
415 env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
418 return 0;
421 /* NOTE: must be called outside the CPU execute loop */
422 void cpu_reset(CPUX86State *env)
424 int i;
426 memset(env, 0, offsetof(CPUX86State, breakpoints));
428 tlb_flush(env, 1);
430 env->old_exception = -1;
432 /* init to reset state */
434 #ifdef CONFIG_SOFTMMU
435 env->hflags |= HF_SOFTMMU_MASK;
436 #endif
437 env->hflags2 |= HF2_GIF_MASK;
439 cpu_x86_update_cr0(env, 0x60000010);
440 env->a20_mask = ~0x0;
441 env->smbase = 0x30000;
443 env->idt.limit = 0xffff;
444 env->gdt.limit = 0xffff;
445 env->ldt.limit = 0xffff;
446 env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
447 env->tr.limit = 0xffff;
448 env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
450 cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
451 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | DESC_R_MASK);
452 cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
453 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
454 cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
455 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
456 cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
457 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
458 cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
459 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
460 cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
461 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
463 env->eip = 0xfff0;
464 env->regs[R_EDX] = env->cpuid_version;
466 env->eflags = 0x2;
468 /* FPU init */
469 for(i = 0;i < 8; i++)
470 env->fptags[i] = 1;
471 env->fpuc = 0x37f;
473 env->mxcsr = 0x1f80;
476 void cpu_x86_close(CPUX86State *env)
478 qemu_free(env);
481 /***********************************************************/
482 /* x86 debug */
484 static const char *cc_op_str[] = {
485 "DYNAMIC",
486 "EFLAGS",
488 "MULB",
489 "MULW",
490 "MULL",
491 "MULQ",
493 "ADDB",
494 "ADDW",
495 "ADDL",
496 "ADDQ",
498 "ADCB",
499 "ADCW",
500 "ADCL",
501 "ADCQ",
503 "SUBB",
504 "SUBW",
505 "SUBL",
506 "SUBQ",
508 "SBBB",
509 "SBBW",
510 "SBBL",
511 "SBBQ",
513 "LOGICB",
514 "LOGICW",
515 "LOGICL",
516 "LOGICQ",
518 "INCB",
519 "INCW",
520 "INCL",
521 "INCQ",
523 "DECB",
524 "DECW",
525 "DECL",
526 "DECQ",
528 "SHLB",
529 "SHLW",
530 "SHLL",
531 "SHLQ",
533 "SARB",
534 "SARW",
535 "SARL",
536 "SARQ",
539 void cpu_dump_state(CPUState *env, FILE *f,
540 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
541 int flags)
543 int eflags, i, nb;
544 char cc_op_name[32];
545 static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
547 eflags = env->eflags;
548 #ifdef TARGET_X86_64
549 if (env->hflags & HF_CS64_MASK) {
550 cpu_fprintf(f,
551 "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
552 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
553 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
554 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
555 "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
556 env->regs[R_EAX],
557 env->regs[R_EBX],
558 env->regs[R_ECX],
559 env->regs[R_EDX],
560 env->regs[R_ESI],
561 env->regs[R_EDI],
562 env->regs[R_EBP],
563 env->regs[R_ESP],
564 env->regs[8],
565 env->regs[9],
566 env->regs[10],
567 env->regs[11],
568 env->regs[12],
569 env->regs[13],
570 env->regs[14],
571 env->regs[15],
572 env->eip, eflags,
573 eflags & DF_MASK ? 'D' : '-',
574 eflags & CC_O ? 'O' : '-',
575 eflags & CC_S ? 'S' : '-',
576 eflags & CC_Z ? 'Z' : '-',
577 eflags & CC_A ? 'A' : '-',
578 eflags & CC_P ? 'P' : '-',
579 eflags & CC_C ? 'C' : '-',
580 env->hflags & HF_CPL_MASK,
581 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
582 (int)(env->a20_mask >> 20) & 1,
583 (env->hflags >> HF_SMM_SHIFT) & 1,
584 env->halted);
585 } else
586 #endif
588 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
589 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
590 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
591 (uint32_t)env->regs[R_EAX],
592 (uint32_t)env->regs[R_EBX],
593 (uint32_t)env->regs[R_ECX],
594 (uint32_t)env->regs[R_EDX],
595 (uint32_t)env->regs[R_ESI],
596 (uint32_t)env->regs[R_EDI],
597 (uint32_t)env->regs[R_EBP],
598 (uint32_t)env->regs[R_ESP],
599 (uint32_t)env->eip, eflags,
600 eflags & DF_MASK ? 'D' : '-',
601 eflags & CC_O ? 'O' : '-',
602 eflags & CC_S ? 'S' : '-',
603 eflags & CC_Z ? 'Z' : '-',
604 eflags & CC_A ? 'A' : '-',
605 eflags & CC_P ? 'P' : '-',
606 eflags & CC_C ? 'C' : '-',
607 env->hflags & HF_CPL_MASK,
608 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
609 (int)(env->a20_mask >> 20) & 1,
610 (env->hflags >> HF_SMM_SHIFT) & 1,
611 env->halted);
614 #ifdef TARGET_X86_64
615 if (env->hflags & HF_LMA_MASK) {
616 for(i = 0; i < 6; i++) {
617 SegmentCache *sc = &env->segs[i];
618 cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
619 seg_name[i],
620 sc->selector,
621 sc->base,
622 sc->limit,
623 sc->flags);
625 cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
626 env->ldt.selector,
627 env->ldt.base,
628 env->ldt.limit,
629 env->ldt.flags);
630 cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
631 env->tr.selector,
632 env->tr.base,
633 env->tr.limit,
634 env->tr.flags);
635 cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n",
636 env->gdt.base, env->gdt.limit);
637 cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n",
638 env->idt.base, env->idt.limit);
639 cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
640 (uint32_t)env->cr[0],
641 env->cr[2],
642 env->cr[3],
643 (uint32_t)env->cr[4]);
644 } else
645 #endif
647 for(i = 0; i < 6; i++) {
648 SegmentCache *sc = &env->segs[i];
649 cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
650 seg_name[i],
651 sc->selector,
652 (uint32_t)sc->base,
653 sc->limit,
654 sc->flags);
656 cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
657 env->ldt.selector,
658 (uint32_t)env->ldt.base,
659 env->ldt.limit,
660 env->ldt.flags);
661 cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
662 env->tr.selector,
663 (uint32_t)env->tr.base,
664 env->tr.limit,
665 env->tr.flags);
666 cpu_fprintf(f, "GDT= %08x %08x\n",
667 (uint32_t)env->gdt.base, env->gdt.limit);
668 cpu_fprintf(f, "IDT= %08x %08x\n",
669 (uint32_t)env->idt.base, env->idt.limit);
670 cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
671 (uint32_t)env->cr[0],
672 (uint32_t)env->cr[2],
673 (uint32_t)env->cr[3],
674 (uint32_t)env->cr[4]);
676 if (flags & X86_DUMP_CCOP) {
677 if ((unsigned)env->cc_op < CC_OP_NB)
678 snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
679 else
680 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
681 #ifdef TARGET_X86_64
682 if (env->hflags & HF_CS64_MASK) {
683 cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
684 env->cc_src, env->cc_dst,
685 cc_op_name);
686 } else
687 #endif
689 cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
690 (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
691 cc_op_name);
694 if (flags & X86_DUMP_FPU) {
695 int fptag;
696 fptag = 0;
697 for(i = 0; i < 8; i++) {
698 fptag |= ((!env->fptags[i]) << i);
700 cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
701 env->fpuc,
702 (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
703 env->fpstt,
704 fptag,
705 env->mxcsr);
706 for(i=0;i<8;i++) {
707 #if defined(USE_X86LDOUBLE)
708 union {
709 long double d;
710 struct {
711 uint64_t lower;
712 uint16_t upper;
713 } l;
714 } tmp;
715 tmp.d = env->fpregs[i].d;
716 cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
717 i, tmp.l.lower, tmp.l.upper);
718 #else
719 cpu_fprintf(f, "FPR%d=%016" PRIx64,
720 i, env->fpregs[i].mmx.q);
721 #endif
722 if ((i & 1) == 1)
723 cpu_fprintf(f, "\n");
724 else
725 cpu_fprintf(f, " ");
727 if (env->hflags & HF_CS64_MASK)
728 nb = 16;
729 else
730 nb = 8;
731 for(i=0;i<nb;i++) {
732 cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
734 env->xmm_regs[i].XMM_L(3),
735 env->xmm_regs[i].XMM_L(2),
736 env->xmm_regs[i].XMM_L(1),
737 env->xmm_regs[i].XMM_L(0));
738 if ((i & 1) == 1)
739 cpu_fprintf(f, "\n");
740 else
741 cpu_fprintf(f, " ");
746 /***********************************************************/
747 /* x86 mmu */
748 /* XXX: add PGE support */
750 void cpu_x86_set_a20(CPUX86State *env, int a20_state)
752 a20_state = (a20_state != 0);
753 if (a20_state != ((env->a20_mask >> 20) & 1)) {
754 #if defined(DEBUG_MMU)
755 printf("A20 update: a20=%d\n", a20_state);
756 #endif
757 /* if the cpu is currently executing code, we must unlink it and
758 all the potentially executing TB */
759 cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
761 /* when a20 is changed, all the MMU mappings are invalid, so
762 we must flush everything */
763 tlb_flush(env, 1);
764 env->a20_mask = (~0x100000) | (a20_state << 20);
768 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
770 int pe_state;
772 #if defined(DEBUG_MMU)
773 printf("CR0 update: CR0=0x%08x\n", new_cr0);
774 #endif
775 if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
776 (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
777 tlb_flush(env, 1);
780 #ifdef TARGET_X86_64
781 if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
782 (env->efer & MSR_EFER_LME)) {
783 /* enter in long mode */
784 /* XXX: generate an exception */
785 if (!(env->cr[4] & CR4_PAE_MASK))
786 return;
787 env->efer |= MSR_EFER_LMA;
788 env->hflags |= HF_LMA_MASK;
789 } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
790 (env->efer & MSR_EFER_LMA)) {
791 /* exit long mode */
792 env->efer &= ~MSR_EFER_LMA;
793 env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
794 env->eip &= 0xffffffff;
796 #endif
797 env->cr[0] = new_cr0 | CR0_ET_MASK;
799 /* update PE flag in hidden flags */
800 pe_state = (env->cr[0] & CR0_PE_MASK);
801 env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
802 /* ensure that ADDSEG is always set in real mode */
803 env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
804 /* update FPU flags */
805 env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
806 ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
809 /* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
810 the PDPT */
811 void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
813 env->cr[3] = new_cr3;
814 if (env->cr[0] & CR0_PG_MASK) {
815 #if defined(DEBUG_MMU)
816 printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
817 #endif
818 tlb_flush(env, 0);
822 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
824 #if defined(DEBUG_MMU)
825 printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
826 #endif
827 if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
828 (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
829 tlb_flush(env, 1);
831 /* SSE handling */
832 if (!(env->cpuid_features & CPUID_SSE))
833 new_cr4 &= ~CR4_OSFXSR_MASK;
834 if (new_cr4 & CR4_OSFXSR_MASK)
835 env->hflags |= HF_OSFXSR_MASK;
836 else
837 env->hflags &= ~HF_OSFXSR_MASK;
839 env->cr[4] = new_cr4;
842 /* XXX: also flush 4MB pages */
843 void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
845 tlb_flush_page(env, addr);
848 #if defined(CONFIG_USER_ONLY)
850 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
851 int is_write, int mmu_idx, int is_softmmu)
853 /* user mode only emulation */
854 is_write &= 1;
855 env->cr[2] = addr;
856 env->error_code = (is_write << PG_ERROR_W_BIT);
857 env->error_code |= PG_ERROR_U_MASK;
858 env->exception_index = EXCP0E_PAGE;
859 return 1;
862 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
864 return addr;
867 #else
869 /* XXX: This value should match the one returned by CPUID
870 * and in exec.c */
871 #if defined(USE_KQEMU)
872 #define PHYS_ADDR_MASK 0xfffff000LL
873 #else
874 # if defined(TARGET_X86_64)
875 # define PHYS_ADDR_MASK 0xfffffff000LL
876 # else
877 # define PHYS_ADDR_MASK 0xffffff000LL
878 # endif
879 #endif
881 /* return value:
882 -1 = cannot handle fault
883 0 = nothing more to do
884 1 = generate PF fault
885 2 = soft MMU activation required for this block
887 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
888 int is_write1, int mmu_idx, int is_softmmu)
890 uint64_t ptep, pte;
891 target_ulong pde_addr, pte_addr;
892 int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
893 target_phys_addr_t paddr;
894 uint32_t page_offset;
895 target_ulong vaddr, virt_addr;
897 is_user = mmu_idx == MMU_USER_IDX;
898 #if defined(DEBUG_MMU)
899 printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
900 addr, is_write1, is_user, env->eip);
901 #endif
902 is_write = is_write1 & 1;
904 if (!(env->cr[0] & CR0_PG_MASK)) {
905 pte = addr;
906 virt_addr = addr & TARGET_PAGE_MASK;
907 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
908 page_size = 4096;
909 goto do_mapping;
912 if (env->cr[4] & CR4_PAE_MASK) {
913 uint64_t pde, pdpe;
914 target_ulong pdpe_addr;
916 #ifdef TARGET_X86_64
917 if (env->hflags & HF_LMA_MASK) {
918 uint64_t pml4e_addr, pml4e;
919 int32_t sext;
921 /* test virtual address sign extension */
922 sext = (int64_t)addr >> 47;
923 if (sext != 0 && sext != -1) {
924 env->error_code = 0;
925 env->exception_index = EXCP0D_GPF;
926 return 1;
929 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
930 env->a20_mask;
931 pml4e = ldq_phys(pml4e_addr);
932 if (!(pml4e & PG_PRESENT_MASK)) {
933 error_code = 0;
934 goto do_fault;
936 if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
937 error_code = PG_ERROR_RSVD_MASK;
938 goto do_fault;
940 if (!(pml4e & PG_ACCESSED_MASK)) {
941 pml4e |= PG_ACCESSED_MASK;
942 stl_phys_notdirty(pml4e_addr, pml4e);
944 ptep = pml4e ^ PG_NX_MASK;
945 pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
946 env->a20_mask;
947 pdpe = ldq_phys(pdpe_addr);
948 if (!(pdpe & PG_PRESENT_MASK)) {
949 error_code = 0;
950 goto do_fault;
952 if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
953 error_code = PG_ERROR_RSVD_MASK;
954 goto do_fault;
956 ptep &= pdpe ^ PG_NX_MASK;
957 if (!(pdpe & PG_ACCESSED_MASK)) {
958 pdpe |= PG_ACCESSED_MASK;
959 stl_phys_notdirty(pdpe_addr, pdpe);
961 } else
962 #endif
964 /* XXX: load them when cr3 is loaded ? */
965 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
966 env->a20_mask;
967 pdpe = ldq_phys(pdpe_addr);
968 if (!(pdpe & PG_PRESENT_MASK)) {
969 error_code = 0;
970 goto do_fault;
972 ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
975 pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
976 env->a20_mask;
977 pde = ldq_phys(pde_addr);
978 if (!(pde & PG_PRESENT_MASK)) {
979 error_code = 0;
980 goto do_fault;
982 if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
983 error_code = PG_ERROR_RSVD_MASK;
984 goto do_fault;
986 ptep &= pde ^ PG_NX_MASK;
987 if (pde & PG_PSE_MASK) {
988 /* 2 MB page */
989 page_size = 2048 * 1024;
990 ptep ^= PG_NX_MASK;
991 if ((ptep & PG_NX_MASK) && is_write1 == 2)
992 goto do_fault_protect;
993 if (is_user) {
994 if (!(ptep & PG_USER_MASK))
995 goto do_fault_protect;
996 if (is_write && !(ptep & PG_RW_MASK))
997 goto do_fault_protect;
998 } else {
999 if ((env->cr[0] & CR0_WP_MASK) &&
1000 is_write && !(ptep & PG_RW_MASK))
1001 goto do_fault_protect;
1003 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
1004 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
1005 pde |= PG_ACCESSED_MASK;
1006 if (is_dirty)
1007 pde |= PG_DIRTY_MASK;
1008 stl_phys_notdirty(pde_addr, pde);
1010 /* align to page_size */
1011 pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
1012 virt_addr = addr & ~(page_size - 1);
1013 } else {
1014 /* 4 KB page */
1015 if (!(pde & PG_ACCESSED_MASK)) {
1016 pde |= PG_ACCESSED_MASK;
1017 stl_phys_notdirty(pde_addr, pde);
1019 pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
1020 env->a20_mask;
1021 pte = ldq_phys(pte_addr);
1022 if (!(pte & PG_PRESENT_MASK)) {
1023 error_code = 0;
1024 goto do_fault;
1026 if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
1027 error_code = PG_ERROR_RSVD_MASK;
1028 goto do_fault;
1030 /* combine pde and pte nx, user and rw protections */
1031 ptep &= pte ^ PG_NX_MASK;
1032 ptep ^= PG_NX_MASK;
1033 if ((ptep & PG_NX_MASK) && is_write1 == 2)
1034 goto do_fault_protect;
1035 if (is_user) {
1036 if (!(ptep & PG_USER_MASK))
1037 goto do_fault_protect;
1038 if (is_write && !(ptep & PG_RW_MASK))
1039 goto do_fault_protect;
1040 } else {
1041 if ((env->cr[0] & CR0_WP_MASK) &&
1042 is_write && !(ptep & PG_RW_MASK))
1043 goto do_fault_protect;
1045 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
1046 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
1047 pte |= PG_ACCESSED_MASK;
1048 if (is_dirty)
1049 pte |= PG_DIRTY_MASK;
1050 stl_phys_notdirty(pte_addr, pte);
1052 page_size = 4096;
1053 virt_addr = addr & ~0xfff;
1054 pte = pte & (PHYS_ADDR_MASK | 0xfff);
1056 } else {
1057 uint32_t pde;
1059 /* page directory entry */
1060 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
1061 env->a20_mask;
1062 pde = ldl_phys(pde_addr);
1063 if (!(pde & PG_PRESENT_MASK)) {
1064 error_code = 0;
1065 goto do_fault;
1067 /* if PSE bit is set, then we use a 4MB page */
1068 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1069 page_size = 4096 * 1024;
1070 if (is_user) {
1071 if (!(pde & PG_USER_MASK))
1072 goto do_fault_protect;
1073 if (is_write && !(pde & PG_RW_MASK))
1074 goto do_fault_protect;
1075 } else {
1076 if ((env->cr[0] & CR0_WP_MASK) &&
1077 is_write && !(pde & PG_RW_MASK))
1078 goto do_fault_protect;
1080 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
1081 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
1082 pde |= PG_ACCESSED_MASK;
1083 if (is_dirty)
1084 pde |= PG_DIRTY_MASK;
1085 stl_phys_notdirty(pde_addr, pde);
1088 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1089 ptep = pte;
1090 virt_addr = addr & ~(page_size - 1);
1091 } else {
1092 if (!(pde & PG_ACCESSED_MASK)) {
1093 pde |= PG_ACCESSED_MASK;
1094 stl_phys_notdirty(pde_addr, pde);
1097 /* page directory entry */
1098 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
1099 env->a20_mask;
1100 pte = ldl_phys(pte_addr);
1101 if (!(pte & PG_PRESENT_MASK)) {
1102 error_code = 0;
1103 goto do_fault;
1105 /* combine pde and pte user and rw protections */
1106 ptep = pte & pde;
1107 if (is_user) {
1108 if (!(ptep & PG_USER_MASK))
1109 goto do_fault_protect;
1110 if (is_write && !(ptep & PG_RW_MASK))
1111 goto do_fault_protect;
1112 } else {
1113 if ((env->cr[0] & CR0_WP_MASK) &&
1114 is_write && !(ptep & PG_RW_MASK))
1115 goto do_fault_protect;
1117 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
1118 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
1119 pte |= PG_ACCESSED_MASK;
1120 if (is_dirty)
1121 pte |= PG_DIRTY_MASK;
1122 stl_phys_notdirty(pte_addr, pte);
1124 page_size = 4096;
1125 virt_addr = addr & ~0xfff;
1128 /* the page can be put in the TLB */
1129 prot = PAGE_READ;
1130 if (!(ptep & PG_NX_MASK))
1131 prot |= PAGE_EXEC;
1132 if (pte & PG_DIRTY_MASK) {
1133 /* only set write access if already dirty... otherwise wait
1134 for dirty access */
1135 if (is_user) {
1136 if (ptep & PG_RW_MASK)
1137 prot |= PAGE_WRITE;
1138 } else {
1139 if (!(env->cr[0] & CR0_WP_MASK) ||
1140 (ptep & PG_RW_MASK))
1141 prot |= PAGE_WRITE;
1144 do_mapping:
1145 pte = pte & env->a20_mask;
1147 /* Even if 4MB pages, we map only one 4KB page in the cache to
1148 avoid filling it too fast */
1149 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1150 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1151 vaddr = virt_addr + page_offset;
1153 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
1154 return ret;
1155 do_fault_protect:
1156 error_code = PG_ERROR_P_MASK;
1157 do_fault:
1158 error_code |= (is_write << PG_ERROR_W_BIT);
1159 if (is_user)
1160 error_code |= PG_ERROR_U_MASK;
1161 if (is_write1 == 2 &&
1162 (env->efer & MSR_EFER_NXE) &&
1163 (env->cr[4] & CR4_PAE_MASK))
1164 error_code |= PG_ERROR_I_D_MASK;
1165 if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
1166 /* cr2 is not modified in case of exceptions */
1167 stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
1168 addr);
1169 } else {
1170 env->cr[2] = addr;
1172 env->error_code = error_code;
1173 env->exception_index = EXCP0E_PAGE;
1174 return 1;
1177 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1179 target_ulong pde_addr, pte_addr;
1180 uint64_t pte;
1181 target_phys_addr_t paddr;
1182 uint32_t page_offset;
1183 int page_size;
1185 if (env->cr[4] & CR4_PAE_MASK) {
1186 target_ulong pdpe_addr;
1187 uint64_t pde, pdpe;
1189 #ifdef TARGET_X86_64
1190 if (env->hflags & HF_LMA_MASK) {
1191 uint64_t pml4e_addr, pml4e;
1192 int32_t sext;
1194 /* test virtual address sign extension */
1195 sext = (int64_t)addr >> 47;
1196 if (sext != 0 && sext != -1)
1197 return -1;
1199 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
1200 env->a20_mask;
1201 pml4e = ldq_phys(pml4e_addr);
1202 if (!(pml4e & PG_PRESENT_MASK))
1203 return -1;
1205 pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
1206 env->a20_mask;
1207 pdpe = ldq_phys(pdpe_addr);
1208 if (!(pdpe & PG_PRESENT_MASK))
1209 return -1;
1210 } else
1211 #endif
1213 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
1214 env->a20_mask;
1215 pdpe = ldq_phys(pdpe_addr);
1216 if (!(pdpe & PG_PRESENT_MASK))
1217 return -1;
1220 pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
1221 env->a20_mask;
1222 pde = ldq_phys(pde_addr);
1223 if (!(pde & PG_PRESENT_MASK)) {
1224 return -1;
1226 if (pde & PG_PSE_MASK) {
1227 /* 2 MB page */
1228 page_size = 2048 * 1024;
1229 pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1230 } else {
1231 /* 4 KB page */
1232 pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
1233 env->a20_mask;
1234 page_size = 4096;
1235 pte = ldq_phys(pte_addr);
1237 if (!(pte & PG_PRESENT_MASK))
1238 return -1;
1239 } else {
1240 uint32_t pde;
1242 if (!(env->cr[0] & CR0_PG_MASK)) {
1243 pte = addr;
1244 page_size = 4096;
1245 } else {
1246 /* page directory entry */
1247 pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
1248 pde = ldl_phys(pde_addr);
1249 if (!(pde & PG_PRESENT_MASK))
1250 return -1;
1251 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1252 pte = pde & ~0x003ff000; /* align to 4MB */
1253 page_size = 4096 * 1024;
1254 } else {
1255 /* page directory entry */
1256 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
1257 pte = ldl_phys(pte_addr);
1258 if (!(pte & PG_PRESENT_MASK))
1259 return -1;
1260 page_size = 4096;
1263 pte = pte & env->a20_mask;
1266 page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1267 paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1268 return paddr;
1270 #endif /* !CONFIG_USER_ONLY */