Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ a35f3ec7

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