VirtualBox

source: vbox/trunk/src/recompiler_new/target-i386/helper.c@ 13368

最後變更 在這個檔案從13368是 13357,由 vboxsync 提交於 16 年 前

new codegen compiles, very unlikely works

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette