Statistics
| Branch: | Revision:

root / target-i386 / helper.c @ 40f8e2fa

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