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