Statistics
| Branch: | Revision:

root / target-i386 / helper.c @ 558fa836

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