Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ cb63669a

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