Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 45d242b6

History | View | Annotate | Download (37.8 kB)

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