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