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