Statistics
| Branch: | Revision:

root / target-i386 / helper.c @ 90cb786c

History | View | Annotate | Download (39.1 kB)

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