x86/x86-64 MMU PAE fixes
[qemu] / 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 #include "svm.h"
31 #include "qemu-common.h"
32
33 //#define DEBUG_MMU
34
35 static int cpu_x86_register (CPUX86State *env, const char *cpu_model);
36
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)
41 {
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     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",
51     };
52     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,
57     };
58     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",
63     };
64     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,
69     };
70
71     for ( i = 0 ; i < 32 ; i++ ) 
72         if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
73             *features |= 1 << i;
74             return;
75         }
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;
80         }
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;
85         }
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;
90         }
91     fprintf(stderr, "CPU feature %s not found\n", flagname);
92 }
93
94 CPUX86State *cpu_x86_init(const char *cpu_model)
95 {
96     CPUX86State *env;
97     static int inited;
98
99     env = qemu_mallocz(sizeof(CPUX86State));
100     if (!env)
101         return NULL;
102     cpu_exec_init(env);
103     env->cpu_model_str = cpu_model;
104
105     /* init various static tables */
106     if (!inited) {
107         inited = 1;
108         optimize_flags_init();
109     }
110     if (cpu_x86_register(env, cpu_model) < 0) {
111         cpu_x86_close(env);
112         return NULL;
113     }
114     cpu_reset(env);
115 #ifdef USE_KQEMU
116     kqemu_init(env);
117 #endif
118     return env;
119 }
120
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 } x86_def_t;
131
132 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
133 #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
134           CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX)
135 #define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
136           CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
137           CPUID_PSE36 | CPUID_FXSR)
138 #define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
139 #define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
140           CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
141           CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
142           CPUID_PAE | CPUID_SEP | CPUID_APIC)
143 static x86_def_t x86_defs[] = {
144 #ifdef TARGET_X86_64
145     {
146         .name = "qemu64",
147         .level = 2,
148         .vendor1 = 0x68747541, /* "Auth" */
149         .vendor2 = 0x69746e65, /* "enti" */
150         .vendor3 = 0x444d4163, /* "cAMD" */
151         .family = 6,
152         .model = 2,
153         .stepping = 3,
154         .features = PPRO_FEATURES | 
155         /* these features are needed for Win64 and aren't fully implemented */
156             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
157         /* this feature is needed for Solaris and isn't fully implemented */
158             CPUID_PSE36,
159         .ext_features = CPUID_EXT_SSE3,
160         .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
161             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
162             CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
163         .ext3_features = CPUID_EXT3_SVM,
164         .xlevel = 0x8000000A,
165     },
166 #endif
167     {
168         .name = "qemu32",
169         .level = 2,
170         .family = 6,
171         .model = 3,
172         .stepping = 3,
173         .features = PPRO_FEATURES,
174         .ext_features = CPUID_EXT_SSE3,
175         .xlevel = 0,
176     },
177     {
178         .name = "486",
179         .level = 0,
180         .family = 4,
181         .model = 0,
182         .stepping = 0,
183         .features = I486_FEATURES,
184         .xlevel = 0,
185     },
186     {
187         .name = "pentium",
188         .level = 1,
189         .family = 5,
190         .model = 4,
191         .stepping = 3,
192         .features = PENTIUM_FEATURES,
193         .xlevel = 0,
194     },
195     {
196         .name = "pentium2",
197         .level = 2,
198         .family = 6,
199         .model = 5,
200         .stepping = 2,
201         .features = PENTIUM2_FEATURES,
202         .xlevel = 0,
203     },
204     {
205         .name = "pentium3",
206         .level = 2,
207         .family = 6,
208         .model = 7,
209         .stepping = 3,
210         .features = PENTIUM3_FEATURES,
211         .xlevel = 0,
212     },
213     {
214         .name = "athlon",
215         .level = 2,
216         .vendor1 = 0x68747541, /* "Auth" */
217         .vendor2 = 0x69746e65, /* "enti" */
218         .vendor3 = 0x444d4163, /* "cAMD" */
219         .family = 6,
220         .model = 2,
221         .stepping = 3,
222         .features = PPRO_FEATURES | PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
223         .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
224         .xlevel = 0x80000008,
225     },
226 };
227
228 static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
229 {
230     unsigned int i;
231     x86_def_t *def;
232
233     char *s = strdup(cpu_model);
234     char *featurestr, *name = strtok(s, ",");
235     uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
236     uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
237     int family = -1, model = -1, stepping = -1;
238
239     def = NULL;
240     for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) {
241         if (strcmp(name, x86_defs[i].name) == 0) {
242             def = &x86_defs[i];
243             break;
244         }
245     }
246     if (!def)
247         goto error;
248     memcpy(x86_cpu_def, def, sizeof(*def));
249
250     featurestr = strtok(NULL, ",");
251
252     while (featurestr) {
253         char *val;
254         if (featurestr[0] == '+') {
255             add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
256         } else if (featurestr[0] == '-') {
257             add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features);
258         } else if ((val = strchr(featurestr, '='))) {
259             *val = 0; val++;
260             if (!strcmp(featurestr, "family")) {
261                 char *err;
262                 family = strtol(val, &err, 10);
263                 if (!*val || *err || family < 0) {
264                     fprintf(stderr, "bad numerical value %s\n", val);
265                     x86_cpu_def = 0;
266                     goto error;
267                 }
268                 x86_cpu_def->family = family;
269             } else if (!strcmp(featurestr, "model")) {
270                 char *err;
271                 model = strtol(val, &err, 10);
272                 if (!*val || *err || model < 0 || model > 0xf) {
273                     fprintf(stderr, "bad numerical value %s\n", val);
274                     x86_cpu_def = 0;
275                     goto error;
276                 }
277                 x86_cpu_def->model = model;
278             } else if (!strcmp(featurestr, "stepping")) {
279                 char *err;
280                 stepping = strtol(val, &err, 10);
281                 if (!*val || *err || stepping < 0 || stepping > 0xf) {
282                     fprintf(stderr, "bad numerical value %s\n", val);
283                     x86_cpu_def = 0;
284                     goto error;
285                 }
286                 x86_cpu_def->stepping = stepping;
287             } else {
288                 fprintf(stderr, "unrecognized feature %s\n", featurestr);
289                 x86_cpu_def = 0;
290                 goto error;
291             }
292         } else {
293             fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
294             x86_cpu_def = 0;
295             goto error;
296         }
297         featurestr = strtok(NULL, ",");
298     }
299     x86_cpu_def->features |= plus_features;
300     x86_cpu_def->ext_features |= plus_ext_features;
301     x86_cpu_def->ext2_features |= plus_ext2_features;
302     x86_cpu_def->ext3_features |= plus_ext3_features;
303     x86_cpu_def->features &= ~minus_features;
304     x86_cpu_def->ext_features &= ~minus_ext_features;
305     x86_cpu_def->ext2_features &= ~minus_ext2_features;
306     x86_cpu_def->ext3_features &= ~minus_ext3_features;
307     free(s);
308     return 0;
309
310 error:
311     free(s);
312     return -1;
313 }
314
315 void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
316 {
317     unsigned int i;
318
319     for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++)
320         (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
321 }
322
323 static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
324 {
325     x86_def_t def1, *def = &def1;
326
327     if (cpu_x86_find_by_name(def, cpu_model) < 0)
328         return -1;
329     if (def->vendor1) {
330         env->cpuid_vendor1 = def->vendor1;
331         env->cpuid_vendor2 = def->vendor2;
332         env->cpuid_vendor3 = def->vendor3;
333     } else {
334         env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
335         env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
336         env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
337     }
338     env->cpuid_level = def->level;
339     env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
340     env->cpuid_features = def->features;
341     env->pat = 0x0007040600070406ULL;
342     env->cpuid_ext_features = def->ext_features;
343     env->cpuid_ext2_features = def->ext2_features;
344     env->cpuid_xlevel = def->xlevel;
345     env->cpuid_ext3_features = def->ext3_features;
346     {
347         const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
348         int c, len, i;
349         len = strlen(model_id);
350         for(i = 0; i < 48; i++) {
351             if (i >= len)
352                 c = '\0';
353             else
354                 c = model_id[i];
355             env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
356         }
357     }
358     return 0;
359 }
360
361 /* NOTE: must be called outside the CPU execute loop */
362 void cpu_reset(CPUX86State *env)
363 {
364     int i;
365
366     memset(env, 0, offsetof(CPUX86State, breakpoints));
367
368     tlb_flush(env, 1);
369
370     env->old_exception = -1;
371
372     /* init to reset state */
373
374 #ifdef CONFIG_SOFTMMU
375     env->hflags |= HF_SOFTMMU_MASK;
376 #endif
377     env->hflags |= HF_GIF_MASK;
378
379     cpu_x86_update_cr0(env, 0x60000010);
380     env->a20_mask = ~0x0;
381     env->smbase = 0x30000;
382
383     env->idt.limit = 0xffff;
384     env->gdt.limit = 0xffff;
385     env->ldt.limit = 0xffff;
386     env->ldt.flags = DESC_P_MASK;
387     env->tr.limit = 0xffff;
388     env->tr.flags = DESC_P_MASK;
389
390     cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0);
391     cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
392     cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
393     cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
394     cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
395     cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
396
397     env->eip = 0xfff0;
398     env->regs[R_EDX] = env->cpuid_version;
399
400     env->eflags = 0x2;
401
402     /* FPU init */
403     for(i = 0;i < 8; i++)
404         env->fptags[i] = 1;
405     env->fpuc = 0x37f;
406
407     env->mxcsr = 0x1f80;
408 }
409
410 void cpu_x86_close(CPUX86State *env)
411 {
412     free(env);
413 }
414
415 /***********************************************************/
416 /* x86 debug */
417
418 static const char *cc_op_str[] = {
419     "DYNAMIC",
420     "EFLAGS",
421
422     "MULB",
423     "MULW",
424     "MULL",
425     "MULQ",
426
427     "ADDB",
428     "ADDW",
429     "ADDL",
430     "ADDQ",
431
432     "ADCB",
433     "ADCW",
434     "ADCL",
435     "ADCQ",
436
437     "SUBB",
438     "SUBW",
439     "SUBL",
440     "SUBQ",
441
442     "SBBB",
443     "SBBW",
444     "SBBL",
445     "SBBQ",
446
447     "LOGICB",
448     "LOGICW",
449     "LOGICL",
450     "LOGICQ",
451
452     "INCB",
453     "INCW",
454     "INCL",
455     "INCQ",
456
457     "DECB",
458     "DECW",
459     "DECL",
460     "DECQ",
461
462     "SHLB",
463     "SHLW",
464     "SHLL",
465     "SHLQ",
466
467     "SARB",
468     "SARW",
469     "SARL",
470     "SARQ",
471 };
472
473 void cpu_dump_state(CPUState *env, FILE *f,
474                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
475                     int flags)
476 {
477     int eflags, i, nb;
478     char cc_op_name[32];
479     static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
480
481     eflags = env->eflags;
482 #ifdef TARGET_X86_64
483     if (env->hflags & HF_CS64_MASK) {
484         cpu_fprintf(f,
485                     "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
486                     "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
487                     "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
488                     "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
489                     "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
490                     env->regs[R_EAX],
491                     env->regs[R_EBX],
492                     env->regs[R_ECX],
493                     env->regs[R_EDX],
494                     env->regs[R_ESI],
495                     env->regs[R_EDI],
496                     env->regs[R_EBP],
497                     env->regs[R_ESP],
498                     env->regs[8],
499                     env->regs[9],
500                     env->regs[10],
501                     env->regs[11],
502                     env->regs[12],
503                     env->regs[13],
504                     env->regs[14],
505                     env->regs[15],
506                     env->eip, eflags,
507                     eflags & DF_MASK ? 'D' : '-',
508                     eflags & CC_O ? 'O' : '-',
509                     eflags & CC_S ? 'S' : '-',
510                     eflags & CC_Z ? 'Z' : '-',
511                     eflags & CC_A ? 'A' : '-',
512                     eflags & CC_P ? 'P' : '-',
513                     eflags & CC_C ? 'C' : '-',
514                     env->hflags & HF_CPL_MASK,
515                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
516                     (env->a20_mask >> 20) & 1,
517                     (env->hflags >> HF_SMM_SHIFT) & 1,
518                     (env->hflags >> HF_HALTED_SHIFT) & 1);
519     } else
520 #endif
521     {
522         cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
523                     "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
524                     "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
525                     (uint32_t)env->regs[R_EAX],
526                     (uint32_t)env->regs[R_EBX],
527                     (uint32_t)env->regs[R_ECX],
528                     (uint32_t)env->regs[R_EDX],
529                     (uint32_t)env->regs[R_ESI],
530                     (uint32_t)env->regs[R_EDI],
531                     (uint32_t)env->regs[R_EBP],
532                     (uint32_t)env->regs[R_ESP],
533                     (uint32_t)env->eip, eflags,
534                     eflags & DF_MASK ? 'D' : '-',
535                     eflags & CC_O ? 'O' : '-',
536                     eflags & CC_S ? 'S' : '-',
537                     eflags & CC_Z ? 'Z' : '-',
538                     eflags & CC_A ? 'A' : '-',
539                     eflags & CC_P ? 'P' : '-',
540                     eflags & CC_C ? 'C' : '-',
541                     env->hflags & HF_CPL_MASK,
542                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
543                     (env->a20_mask >> 20) & 1,
544                     (env->hflags >> HF_SMM_SHIFT) & 1,
545                     (env->hflags >> HF_HALTED_SHIFT) & 1);
546     }
547
548 #ifdef TARGET_X86_64
549     if (env->hflags & HF_LMA_MASK) {
550         for(i = 0; i < 6; i++) {
551             SegmentCache *sc = &env->segs[i];
552             cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
553                         seg_name[i],
554                         sc->selector,
555                         sc->base,
556                         sc->limit,
557                         sc->flags);
558         }
559         cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
560                     env->ldt.selector,
561                     env->ldt.base,
562                     env->ldt.limit,
563                     env->ldt.flags);
564         cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
565                     env->tr.selector,
566                     env->tr.base,
567                     env->tr.limit,
568                     env->tr.flags);
569         cpu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
570                     env->gdt.base, env->gdt.limit);
571         cpu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
572                     env->idt.base, env->idt.limit);
573         cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
574                     (uint32_t)env->cr[0],
575                     env->cr[2],
576                     env->cr[3],
577                     (uint32_t)env->cr[4]);
578     } else
579 #endif
580     {
581         for(i = 0; i < 6; i++) {
582             SegmentCache *sc = &env->segs[i];
583             cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
584                         seg_name[i],
585                         sc->selector,
586                         (uint32_t)sc->base,
587                         sc->limit,
588                         sc->flags);
589         }
590         cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
591                     env->ldt.selector,
592                     (uint32_t)env->ldt.base,
593                     env->ldt.limit,
594                     env->ldt.flags);
595         cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
596                     env->tr.selector,
597                     (uint32_t)env->tr.base,
598                     env->tr.limit,
599                     env->tr.flags);
600         cpu_fprintf(f, "GDT=     %08x %08x\n",
601                     (uint32_t)env->gdt.base, env->gdt.limit);
602         cpu_fprintf(f, "IDT=     %08x %08x\n",
603                     (uint32_t)env->idt.base, env->idt.limit);
604         cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
605                     (uint32_t)env->cr[0],
606                     (uint32_t)env->cr[2],
607                     (uint32_t)env->cr[3],
608                     (uint32_t)env->cr[4]);
609     }
610     if (flags & X86_DUMP_CCOP) {
611         if ((unsigned)env->cc_op < CC_OP_NB)
612             snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
613         else
614             snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
615 #ifdef TARGET_X86_64
616         if (env->hflags & HF_CS64_MASK) {
617             cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
618                         env->cc_src, env->cc_dst,
619                         cc_op_name);
620         } else
621 #endif
622         {
623             cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
624                         (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
625                         cc_op_name);
626         }
627     }
628     if (flags & X86_DUMP_FPU) {
629         int fptag;
630         fptag = 0;
631         for(i = 0; i < 8; i++) {
632             fptag |= ((!env->fptags[i]) << i);
633         }
634         cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
635                     env->fpuc,
636                     (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
637                     env->fpstt,
638                     fptag,
639                     env->mxcsr);
640         for(i=0;i<8;i++) {
641 #if defined(USE_X86LDOUBLE)
642             union {
643                 long double d;
644                 struct {
645                     uint64_t lower;
646                     uint16_t upper;
647                 } l;
648             } tmp;
649             tmp.d = env->fpregs[i].d;
650             cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
651                         i, tmp.l.lower, tmp.l.upper);
652 #else
653             cpu_fprintf(f, "FPR%d=%016" PRIx64,
654                         i, env->fpregs[i].mmx.q);
655 #endif
656             if ((i & 1) == 1)
657                 cpu_fprintf(f, "\n");
658             else
659                 cpu_fprintf(f, " ");
660         }
661         if (env->hflags & HF_CS64_MASK)
662             nb = 16;
663         else
664             nb = 8;
665         for(i=0;i<nb;i++) {
666             cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
667                         i,
668                         env->xmm_regs[i].XMM_L(3),
669                         env->xmm_regs[i].XMM_L(2),
670                         env->xmm_regs[i].XMM_L(1),
671                         env->xmm_regs[i].XMM_L(0));
672             if ((i & 1) == 1)
673                 cpu_fprintf(f, "\n");
674             else
675                 cpu_fprintf(f, " ");
676         }
677     }
678 }
679
680 /***********************************************************/
681 /* x86 mmu */
682 /* XXX: add PGE support */
683
684 void cpu_x86_set_a20(CPUX86State *env, int a20_state)
685 {
686     a20_state = (a20_state != 0);
687     if (a20_state != ((env->a20_mask >> 20) & 1)) {
688 #if defined(DEBUG_MMU)
689         printf("A20 update: a20=%d\n", a20_state);
690 #endif
691         /* if the cpu is currently executing code, we must unlink it and
692            all the potentially executing TB */
693         cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
694
695         /* when a20 is changed, all the MMU mappings are invalid, so
696            we must flush everything */
697         tlb_flush(env, 1);
698         env->a20_mask = (~0x100000) | (a20_state << 20);
699     }
700 }
701
702 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
703 {
704     int pe_state;
705
706 #if defined(DEBUG_MMU)
707     printf("CR0 update: CR0=0x%08x\n", new_cr0);
708 #endif
709     if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
710         (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
711         tlb_flush(env, 1);
712     }
713
714 #ifdef TARGET_X86_64
715     if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
716         (env->efer & MSR_EFER_LME)) {
717         /* enter in long mode */
718         /* XXX: generate an exception */
719         if (!(env->cr[4] & CR4_PAE_MASK))
720             return;
721         env->efer |= MSR_EFER_LMA;
722         env->hflags |= HF_LMA_MASK;
723     } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
724                (env->efer & MSR_EFER_LMA)) {
725         /* exit long mode */
726         env->efer &= ~MSR_EFER_LMA;
727         env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
728         env->eip &= 0xffffffff;
729     }
730 #endif
731     env->cr[0] = new_cr0 | CR0_ET_MASK;
732
733     /* update PE flag in hidden flags */
734     pe_state = (env->cr[0] & CR0_PE_MASK);
735     env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
736     /* ensure that ADDSEG is always set in real mode */
737     env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
738     /* update FPU flags */
739     env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
740         ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
741 }
742
743 /* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
744    the PDPT */
745 void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
746 {
747     env->cr[3] = new_cr3;
748     if (env->cr[0] & CR0_PG_MASK) {
749 #if defined(DEBUG_MMU)
750         printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
751 #endif
752         tlb_flush(env, 0);
753     }
754 }
755
756 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
757 {
758 #if defined(DEBUG_MMU)
759     printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
760 #endif
761     if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
762         (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
763         tlb_flush(env, 1);
764     }
765     /* SSE handling */
766     if (!(env->cpuid_features & CPUID_SSE))
767         new_cr4 &= ~CR4_OSFXSR_MASK;
768     if (new_cr4 & CR4_OSFXSR_MASK)
769         env->hflags |= HF_OSFXSR_MASK;
770     else
771         env->hflags &= ~HF_OSFXSR_MASK;
772
773     env->cr[4] = new_cr4;
774 }
775
776 /* XXX: also flush 4MB pages */
777 void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
778 {
779     tlb_flush_page(env, addr);
780 }
781
782 #if defined(CONFIG_USER_ONLY)
783
784 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
785                              int is_write, int mmu_idx, int is_softmmu)
786 {
787     /* user mode only emulation */
788     is_write &= 1;
789     env->cr[2] = addr;
790     env->error_code = (is_write << PG_ERROR_W_BIT);
791     env->error_code |= PG_ERROR_U_MASK;
792     env->exception_index = EXCP0E_PAGE;
793     return 1;
794 }
795
796 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
797 {
798     return addr;
799 }
800
801 #else
802
803 #define PHYS_ADDR_MASK (~0xfff)
804
805 /* return value:
806    -1 = cannot handle fault
807    0  = nothing more to do
808    1  = generate PF fault
809    2  = soft MMU activation required for this block
810 */
811 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
812                              int is_write1, int mmu_idx, int is_softmmu)
813 {
814     uint64_t ptep, pte;
815     target_ulong pde_addr, pte_addr;
816     int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
817     target_phys_addr_t paddr;
818     uint32_t page_offset;
819     target_ulong vaddr, virt_addr;
820
821     is_user = mmu_idx == MMU_USER_IDX;
822 #if defined(DEBUG_MMU)
823     printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
824            addr, is_write1, is_user, env->eip);
825 #endif
826     is_write = is_write1 & 1;
827
828     if (!(env->cr[0] & CR0_PG_MASK)) {
829         pte = addr;
830         virt_addr = addr & TARGET_PAGE_MASK;
831         prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
832         page_size = 4096;
833         goto do_mapping;
834     }
835
836     if (env->cr[4] & CR4_PAE_MASK) {
837         uint64_t pde, pdpe;
838         target_ulong pdpe_addr;
839
840 #ifdef TARGET_X86_64
841         if (env->hflags & HF_LMA_MASK) {
842             uint64_t pml4e_addr, pml4e;
843             int32_t sext;
844
845             /* test virtual address sign extension */
846             sext = (int64_t)addr >> 47;
847             if (sext != 0 && sext != -1) {
848                 env->error_code = 0;
849                 env->exception_index = EXCP0D_GPF;
850                 return 1;
851             }
852
853             pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
854                 env->a20_mask;
855             pml4e = ldq_phys(pml4e_addr);
856             if (!(pml4e & PG_PRESENT_MASK)) {
857                 error_code = 0;
858                 goto do_fault;
859             }
860             if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
861                 error_code = PG_ERROR_RSVD_MASK;
862                 goto do_fault;
863             }
864             if (!(pml4e & PG_ACCESSED_MASK)) {
865                 pml4e |= PG_ACCESSED_MASK;
866                 stl_phys_notdirty(pml4e_addr, pml4e);
867             }
868             ptep = pml4e ^ PG_NX_MASK;
869             pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
870                 env->a20_mask;
871             pdpe = ldq_phys(pdpe_addr);
872             if (!(pdpe & PG_PRESENT_MASK)) {
873                 error_code = 0;
874                 goto do_fault;
875             }
876             if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
877                 error_code = PG_ERROR_RSVD_MASK;
878                 goto do_fault;
879             }
880             ptep &= pdpe ^ PG_NX_MASK;
881             if (!(pdpe & PG_ACCESSED_MASK)) {
882                 pdpe |= PG_ACCESSED_MASK;
883                 stl_phys_notdirty(pdpe_addr, pdpe);
884             }
885         } else
886 #endif
887         {
888             /* XXX: load them when cr3 is loaded ? */
889             pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
890                 env->a20_mask;
891             pdpe = ldq_phys(pdpe_addr);
892             if (!(pdpe & PG_PRESENT_MASK)) {
893                 error_code = 0;
894                 goto do_fault;
895             }
896             ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
897         }
898
899         pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
900             env->a20_mask;
901         pde = ldq_phys(pde_addr);
902         if (!(pde & PG_PRESENT_MASK)) {
903             error_code = 0;
904             goto do_fault;
905         }
906         if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
907             error_code = PG_ERROR_RSVD_MASK;
908             goto do_fault;
909         }
910         ptep &= pde ^ PG_NX_MASK;
911         if (pde & PG_PSE_MASK) {
912             /* 2 MB page */
913             page_size = 2048 * 1024;
914             ptep ^= PG_NX_MASK;
915             if ((ptep & PG_NX_MASK) && is_write1 == 2)
916                 goto do_fault_protect;
917             if (is_user) {
918                 if (!(ptep & PG_USER_MASK))
919                     goto do_fault_protect;
920                 if (is_write && !(ptep & PG_RW_MASK))
921                     goto do_fault_protect;
922             } else {
923                 if ((env->cr[0] & CR0_WP_MASK) &&
924                     is_write && !(ptep & PG_RW_MASK))
925                     goto do_fault_protect;
926             }
927             is_dirty = is_write && !(pde & PG_DIRTY_MASK);
928             if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
929                 pde |= PG_ACCESSED_MASK;
930                 if (is_dirty)
931                     pde |= PG_DIRTY_MASK;
932                 stl_phys_notdirty(pde_addr, pde);
933             }
934             /* align to page_size */
935             pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
936             virt_addr = addr & ~(page_size - 1);
937         } else {
938             /* 4 KB page */
939             if (!(pde & PG_ACCESSED_MASK)) {
940                 pde |= PG_ACCESSED_MASK;
941                 stl_phys_notdirty(pde_addr, pde);
942             }
943             pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
944                 env->a20_mask;
945             pte = ldq_phys(pte_addr);
946             if (!(pte & PG_PRESENT_MASK)) {
947                 error_code = 0;
948                 goto do_fault;
949             }
950             if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
951                 error_code = PG_ERROR_RSVD_MASK;
952                 goto do_fault;
953             }
954             /* combine pde and pte nx, user and rw protections */
955             ptep &= pte ^ PG_NX_MASK;
956             ptep ^= PG_NX_MASK;
957             if ((ptep & PG_NX_MASK) && is_write1 == 2)
958                 goto do_fault_protect;
959             if (is_user) {
960                 if (!(ptep & PG_USER_MASK))
961                     goto do_fault_protect;
962                 if (is_write && !(ptep & PG_RW_MASK))
963                     goto do_fault_protect;
964             } else {
965                 if ((env->cr[0] & CR0_WP_MASK) &&
966                     is_write && !(ptep & PG_RW_MASK))
967                     goto do_fault_protect;
968             }
969             is_dirty = is_write && !(pte & PG_DIRTY_MASK);
970             if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
971                 pte |= PG_ACCESSED_MASK;
972                 if (is_dirty)
973                     pte |= PG_DIRTY_MASK;
974                 stl_phys_notdirty(pte_addr, pte);
975             }
976             page_size = 4096;
977             virt_addr = addr & ~0xfff;
978             pte = pte & (PHYS_ADDR_MASK | 0xfff);
979         }
980     } else {
981         uint32_t pde;
982
983         /* page directory entry */
984         pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
985             env->a20_mask;
986         pde = ldl_phys(pde_addr);
987         if (!(pde & PG_PRESENT_MASK)) {
988             error_code = 0;
989             goto do_fault;
990         }
991         /* if PSE bit is set, then we use a 4MB page */
992         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
993             page_size = 4096 * 1024;
994             if (is_user) {
995                 if (!(pde & PG_USER_MASK))
996                     goto do_fault_protect;
997                 if (is_write && !(pde & PG_RW_MASK))
998                     goto do_fault_protect;
999             } else {
1000                 if ((env->cr[0] & CR0_WP_MASK) &&
1001                     is_write && !(pde & PG_RW_MASK))
1002                     goto do_fault_protect;
1003             }
1004             is_dirty = is_write && !(pde & PG_DIRTY_MASK);
1005             if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
1006                 pde |= PG_ACCESSED_MASK;
1007                 if (is_dirty)
1008                     pde |= PG_DIRTY_MASK;
1009                 stl_phys_notdirty(pde_addr, pde);
1010             }
1011
1012             pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1013             ptep = pte;
1014             virt_addr = addr & ~(page_size - 1);
1015         } else {
1016             if (!(pde & PG_ACCESSED_MASK)) {
1017                 pde |= PG_ACCESSED_MASK;
1018                 stl_phys_notdirty(pde_addr, pde);
1019             }
1020
1021             /* page directory entry */
1022             pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
1023                 env->a20_mask;
1024             pte = ldl_phys(pte_addr);
1025             if (!(pte & PG_PRESENT_MASK)) {
1026                 error_code = 0;
1027                 goto do_fault;
1028             }
1029             /* combine pde and pte user and rw protections */
1030             ptep = pte & pde;
1031             if (is_user) {
1032                 if (!(ptep & PG_USER_MASK))
1033                     goto do_fault_protect;
1034                 if (is_write && !(ptep & PG_RW_MASK))
1035                     goto do_fault_protect;
1036             } else {
1037                 if ((env->cr[0] & CR0_WP_MASK) &&
1038                     is_write && !(ptep & PG_RW_MASK))
1039                     goto do_fault_protect;
1040             }
1041             is_dirty = is_write && !(pte & PG_DIRTY_MASK);
1042             if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
1043                 pte |= PG_ACCESSED_MASK;
1044                 if (is_dirty)
1045                     pte |= PG_DIRTY_MASK;
1046                 stl_phys_notdirty(pte_addr, pte);
1047             }
1048             page_size = 4096;
1049             virt_addr = addr & ~0xfff;
1050         }
1051     }
1052     /* the page can be put in the TLB */
1053     prot = PAGE_READ;
1054     if (!(ptep & PG_NX_MASK))
1055         prot |= PAGE_EXEC;
1056     if (pte & PG_DIRTY_MASK) {
1057         /* only set write access if already dirty... otherwise wait
1058            for dirty access */
1059         if (is_user) {
1060             if (ptep & PG_RW_MASK)
1061                 prot |= PAGE_WRITE;
1062         } else {
1063             if (!(env->cr[0] & CR0_WP_MASK) ||
1064                 (ptep & PG_RW_MASK))
1065                 prot |= PAGE_WRITE;
1066         }
1067     }
1068  do_mapping:
1069     pte = pte & env->a20_mask;
1070
1071     /* Even if 4MB pages, we map only one 4KB page in the cache to
1072        avoid filling it too fast */
1073     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1074     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1075     vaddr = virt_addr + page_offset;
1076
1077     ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
1078     return ret;
1079  do_fault_protect:
1080     error_code = PG_ERROR_P_MASK;
1081  do_fault:
1082     error_code |= (is_write << PG_ERROR_W_BIT);
1083     if (is_user)
1084         error_code |= PG_ERROR_U_MASK;
1085     if (is_write1 == 2 &&
1086         (env->efer & MSR_EFER_NXE) &&
1087         (env->cr[4] & CR4_PAE_MASK))
1088         error_code |= PG_ERROR_I_D_MASK;
1089     if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE)) {
1090         stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), addr);
1091     } else {
1092         env->cr[2] = addr;
1093     }
1094     env->error_code = error_code;
1095     env->exception_index = EXCP0E_PAGE;
1096     /* the VMM will handle this */
1097     if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE))
1098         return 2;
1099     return 1;
1100 }
1101
1102 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1103 {
1104     target_ulong pde_addr, pte_addr;
1105     uint64_t pte;
1106     target_phys_addr_t paddr;
1107     uint32_t page_offset;
1108     int page_size;
1109
1110     if (env->cr[4] & CR4_PAE_MASK) {
1111         target_ulong pdpe_addr;
1112         uint64_t pde, pdpe;
1113
1114 #ifdef TARGET_X86_64
1115         if (env->hflags & HF_LMA_MASK) {
1116             uint64_t pml4e_addr, pml4e;
1117             int32_t sext;
1118
1119             /* test virtual address sign extension */
1120             sext = (int64_t)addr >> 47;
1121             if (sext != 0 && sext != -1)
1122                 return -1;
1123
1124             pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
1125                 env->a20_mask;
1126             pml4e = ldq_phys(pml4e_addr);
1127             if (!(pml4e & PG_PRESENT_MASK))
1128                 return -1;
1129
1130             pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
1131                 env->a20_mask;
1132             pdpe = ldq_phys(pdpe_addr);
1133             if (!(pdpe & PG_PRESENT_MASK))
1134                 return -1;
1135         } else
1136 #endif
1137         {
1138             pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
1139                 env->a20_mask;
1140             pdpe = ldq_phys(pdpe_addr);
1141             if (!(pdpe & PG_PRESENT_MASK))
1142                 return -1;
1143         }
1144
1145         pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
1146             env->a20_mask;
1147         pde = ldq_phys(pde_addr);
1148         if (!(pde & PG_PRESENT_MASK)) {
1149             return -1;
1150         }
1151         if (pde & PG_PSE_MASK) {
1152             /* 2 MB page */
1153             page_size = 2048 * 1024;
1154             pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1155         } else {
1156             /* 4 KB page */
1157             pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
1158                 env->a20_mask;
1159             page_size = 4096;
1160             pte = ldq_phys(pte_addr);
1161         }
1162     } else {
1163         uint32_t pde;
1164
1165         if (!(env->cr[0] & CR0_PG_MASK)) {
1166             pte = addr;
1167             page_size = 4096;
1168         } else {
1169             /* page directory entry */
1170             pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
1171             pde = ldl_phys(pde_addr);
1172             if (!(pde & PG_PRESENT_MASK))
1173                 return -1;
1174             if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1175                 pte = pde & ~0x003ff000; /* align to 4MB */
1176                 page_size = 4096 * 1024;
1177             } else {
1178                 /* page directory entry */
1179                 pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
1180                 pte = ldl_phys(pte_addr);
1181                 if (!(pte & PG_PRESENT_MASK))
1182                     return -1;
1183                 page_size = 4096;
1184             }
1185         }
1186         pte = pte & env->a20_mask;
1187     }
1188
1189     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1190     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1191     return paddr;
1192 }
1193 #endif /* !CONFIG_USER_ONLY */