|
|
1.1 root 1: /* 1.1.1.7 ! root 2: * i386 helpers (without register variable usage) 1.1.1.6 root 3: * 1.1 root 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 1.1.1.7 ! root 18: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA 1.1 root 19: */ 1.1.1.7 ! root 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> ! 27: ! 28: #include "cpu.h" ! 29: #include "exec-all.h" ! 30: #include "qemu-common.h" ! 31: #include "kvm.h" ! 32: ! 33: //#define DEBUG_MMU ! 34: ! 35: static void add_flagname_to_bitmaps(char *flagname, uint32_t *features, ! 36: uint32_t *ext_features, ! 37: uint32_t *ext2_features, ! 38: uint32_t *ext3_features) 1.1 root 39: { 1.1.1.7 ! root 40: int i; ! 41: /* feature flags taken from "Intel Processor Identification and the CPUID ! 42: * Instruction" and AMD's "CPUID Specification". In cases of disagreement ! 43: * about feature names, the Linux name is used. */ ! 44: static const char *feature_name[] = { ! 45: "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", ! 46: "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", ! 47: "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx", ! 48: "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe", ! 49: }; ! 50: static const char *ext_feature_name[] = { ! 51: "pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est", ! 52: "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, ! 53: NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt", ! 54: NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ! 55: }; ! 56: static const char *ext2_feature_name[] = { ! 57: "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", ! 58: "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mtrr", "pge", "mca", "cmov", ! 59: "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx", ! 60: "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow", ! 61: }; ! 62: static const char *ext3_feature_name[] = { ! 63: "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse", ! 64: "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL, ! 65: NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ! 66: NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ! 67: }; ! 68: ! 69: for ( i = 0 ; i < 32 ; i++ ) ! 70: if (feature_name[i] && !strcmp (flagname, feature_name[i])) { ! 71: *features |= 1 << i; 1.1 root 72: return; 73: } 1.1.1.7 ! root 74: for ( i = 0 ; i < 32 ; i++ ) ! 75: if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) { ! 76: *ext_features |= 1 << i; 1.1 root 77: return; 78: } 1.1.1.7 ! root 79: for ( i = 0 ; i < 32 ; i++ ) ! 80: if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) { ! 81: *ext2_features |= 1 << i; 1.1 root 82: return; 83: } 1.1.1.7 ! root 84: for ( i = 0 ; i < 32 ; i++ ) ! 85: if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) { ! 86: *ext3_features |= 1 << i; 1.1 root 87: return; 88: } 1.1.1.7 ! root 89: fprintf(stderr, "CPU feature %s not found\n", flagname); 1.1 root 90: } 91: 1.1.1.7 ! root 92: typedef struct x86_def_t { ! 93: const char *name; ! 94: uint32_t level; ! 95: uint32_t vendor1, vendor2, vendor3; ! 96: int family; ! 97: int model; ! 98: int stepping; ! 99: uint32_t features, ext_features, ext2_features, ext3_features; ! 100: uint32_t xlevel; ! 101: char model_id[48]; ! 102: } x86_def_t; ! 103: ! 104: #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) ! 105: #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \ ! 106: CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX) ! 107: #define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \ ! 108: CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \ ! 109: CPUID_PSE36 | CPUID_FXSR) ! 110: #define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE) ! 111: #define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \ ! 112: CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \ ! 113: CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \ ! 114: CPUID_PAE | CPUID_SEP | CPUID_APIC) ! 115: static x86_def_t x86_defs[] = { ! 116: #ifdef TARGET_X86_64 ! 117: { ! 118: .name = "qemu64", ! 119: .level = 2, ! 120: .vendor1 = CPUID_VENDOR_AMD_1, ! 121: .vendor2 = CPUID_VENDOR_AMD_2, ! 122: .vendor3 = CPUID_VENDOR_AMD_3, ! 123: .family = 6, ! 124: .model = 2, ! 125: .stepping = 3, ! 126: .features = PPRO_FEATURES | ! 127: /* these features are needed for Win64 and aren't fully implemented */ ! 128: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | ! 129: /* this feature is needed for Solaris and isn't fully implemented */ ! 130: CPUID_PSE36, ! 131: .ext_features = CPUID_EXT_SSE3, ! 132: .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | ! 133: CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | ! 134: CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, ! 135: .ext3_features = CPUID_EXT3_SVM, ! 136: .xlevel = 0x8000000A, ! 137: .model_id = "QEMU Virtual CPU version " QEMU_VERSION, ! 138: }, ! 139: { ! 140: .name = "phenom", ! 141: .level = 5, ! 142: .vendor1 = CPUID_VENDOR_AMD_1, ! 143: .vendor2 = CPUID_VENDOR_AMD_2, ! 144: .vendor3 = CPUID_VENDOR_AMD_3, ! 145: .family = 16, ! 146: .model = 2, ! 147: .stepping = 3, ! 148: /* Missing: CPUID_VME, CPUID_HT */ ! 149: .features = PPRO_FEATURES | ! 150: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | ! 151: CPUID_PSE36, ! 152: /* Missing: CPUID_EXT_CX16, CPUID_EXT_POPCNT */ ! 153: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR, ! 154: /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ ! 155: .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | ! 156: CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | ! 157: CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT | ! 158: CPUID_EXT2_FFXSR, ! 159: /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, ! 160: CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A, ! 161: CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, ! 162: CPUID_EXT3_OSVW, CPUID_EXT3_IBS */ ! 163: .ext3_features = CPUID_EXT3_SVM, ! 164: .xlevel = 0x8000001A, ! 165: .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor" ! 166: }, ! 167: { ! 168: .name = "core2duo", ! 169: .level = 10, ! 170: .family = 6, ! 171: .model = 15, ! 172: .stepping = 11, ! 173: /* The original CPU also implements these features: ! 174: CPUID_VME, CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT, ! 175: CPUID_TM, CPUID_PBE */ ! 176: .features = PPRO_FEATURES | ! 177: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | ! 178: CPUID_PSE36, ! 179: /* The original CPU also implements these ext features: ! 180: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST, ! 181: CPUID_EXT_TM2, CPUID_EXT_CX16, CPUID_EXT_XTPR, CPUID_EXT_PDCM */ ! 182: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3, ! 183: .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, ! 184: /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */ ! 185: .xlevel = 0x80000008, ! 186: .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", ! 187: }, 1.1 root 188: #endif 1.1.1.7 ! root 189: { ! 190: .name = "qemu32", ! 191: .level = 2, ! 192: .family = 6, ! 193: .model = 3, ! 194: .stepping = 3, ! 195: .features = PPRO_FEATURES, ! 196: .ext_features = CPUID_EXT_SSE3, ! 197: .xlevel = 0, ! 198: .model_id = "QEMU Virtual CPU version " QEMU_VERSION, ! 199: }, ! 200: { ! 201: .name = "coreduo", ! 202: .level = 10, ! 203: .family = 6, ! 204: .model = 14, ! 205: .stepping = 8, ! 206: /* The original CPU also implements these features: ! 207: CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT, ! 208: CPUID_TM, CPUID_PBE */ ! 209: .features = PPRO_FEATURES | CPUID_VME | ! 210: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA, ! 211: /* The original CPU also implements these ext features: ! 212: CPUID_EXT_VMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_XTPR, ! 213: CPUID_EXT_PDCM */ ! 214: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR, ! 215: .ext2_features = CPUID_EXT2_NX, ! 216: .xlevel = 0x80000008, ! 217: .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", ! 218: }, ! 219: { ! 220: .name = "486", ! 221: .level = 0, ! 222: .family = 4, ! 223: .model = 0, ! 224: .stepping = 0, ! 225: .features = I486_FEATURES, ! 226: .xlevel = 0, ! 227: }, ! 228: { ! 229: .name = "pentium", ! 230: .level = 1, ! 231: .family = 5, ! 232: .model = 4, ! 233: .stepping = 3, ! 234: .features = PENTIUM_FEATURES, ! 235: .xlevel = 0, ! 236: }, ! 237: { ! 238: .name = "pentium2", ! 239: .level = 2, ! 240: .family = 6, ! 241: .model = 5, ! 242: .stepping = 2, ! 243: .features = PENTIUM2_FEATURES, ! 244: .xlevel = 0, ! 245: }, ! 246: { ! 247: .name = "pentium3", ! 248: .level = 2, ! 249: .family = 6, ! 250: .model = 7, ! 251: .stepping = 3, ! 252: .features = PENTIUM3_FEATURES, ! 253: .xlevel = 0, ! 254: }, ! 255: { ! 256: .name = "athlon", ! 257: .level = 2, ! 258: .vendor1 = 0x68747541, /* "Auth" */ ! 259: .vendor2 = 0x69746e65, /* "enti" */ ! 260: .vendor3 = 0x444d4163, /* "cAMD" */ ! 261: .family = 6, ! 262: .model = 2, ! 263: .stepping = 3, ! 264: .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA, ! 265: .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, ! 266: .xlevel = 0x80000008, ! 267: /* XXX: put another string ? */ ! 268: .model_id = "QEMU Virtual CPU version " QEMU_VERSION, ! 269: }, ! 270: { ! 271: .name = "n270", ! 272: /* original is on level 10 */ ! 273: .level = 5, ! 274: .family = 6, ! 275: .model = 28, ! 276: .stepping = 2, ! 277: .features = PPRO_FEATURES | ! 278: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME, ! 279: /* Missing: CPUID_DTS | CPUID_ACPI | CPUID_SS | ! 280: * CPUID_HT | CPUID_TM | CPUID_PBE */ ! 281: /* Some CPUs got no CPUID_SEP */ ! 282: .ext_features = CPUID_EXT_MONITOR | ! 283: CPUID_EXT_SSE3 /* PNI */ | CPUID_EXT_SSSE3, ! 284: /* Missing: CPUID_EXT_DSCPL | CPUID_EXT_EST | ! 285: * CPUID_EXT_TM2 | CPUID_EXT_XTPR */ ! 286: .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_NX, ! 287: /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */ ! 288: .xlevel = 0x8000000A, ! 289: .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", ! 290: }, ! 291: }; 1.1 root 292: 1.1.1.7 ! root 293: static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) 1.1 root 294: { 1.1.1.7 ! root 295: unsigned int i; ! 296: x86_def_t *def; 1.1 root 297: 1.1.1.7 ! root 298: char *s = strdup(cpu_model); ! 299: char *featurestr, *name = strtok(s, ","); ! 300: uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0; ! 301: uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0; ! 302: int family = -1, model = -1, stepping = -1; ! 303: ! 304: def = NULL; ! 305: for (i = 0; i < ARRAY_SIZE(x86_defs); i++) { ! 306: if (strcmp(name, x86_defs[i].name) == 0) { ! 307: def = &x86_defs[i]; 1.1 root 308: break; 1.1.1.7 ! root 309: } 1.1.1.6 root 310: } 1.1.1.7 ! root 311: if (!def) ! 312: goto error; ! 313: memcpy(x86_cpu_def, def, sizeof(*def)); ! 314: ! 315: featurestr = strtok(NULL, ","); ! 316: ! 317: while (featurestr) { ! 318: char *val; ! 319: if (featurestr[0] == '+') { ! 320: add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features); ! 321: } else if (featurestr[0] == '-') { ! 322: add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features); ! 323: } else if ((val = strchr(featurestr, '='))) { ! 324: *val = 0; val++; ! 325: if (!strcmp(featurestr, "family")) { ! 326: char *err; ! 327: family = strtol(val, &err, 10); ! 328: if (!*val || *err || family < 0) { ! 329: fprintf(stderr, "bad numerical value %s\n", val); ! 330: goto error; ! 331: } ! 332: x86_cpu_def->family = family; ! 333: } else if (!strcmp(featurestr, "model")) { ! 334: char *err; ! 335: model = strtol(val, &err, 10); ! 336: if (!*val || *err || model < 0 || model > 0xff) { ! 337: fprintf(stderr, "bad numerical value %s\n", val); ! 338: goto error; ! 339: } ! 340: x86_cpu_def->model = model; ! 341: } else if (!strcmp(featurestr, "stepping")) { ! 342: char *err; ! 343: stepping = strtol(val, &err, 10); ! 344: if (!*val || *err || stepping < 0 || stepping > 0xf) { ! 345: fprintf(stderr, "bad numerical value %s\n", val); ! 346: goto error; ! 347: } ! 348: x86_cpu_def->stepping = stepping; ! 349: } else if (!strcmp(featurestr, "vendor")) { ! 350: if (strlen(val) != 12) { ! 351: fprintf(stderr, "vendor string must be 12 chars long\n"); ! 352: goto error; ! 353: } ! 354: x86_cpu_def->vendor1 = 0; ! 355: x86_cpu_def->vendor2 = 0; ! 356: x86_cpu_def->vendor3 = 0; ! 357: for(i = 0; i < 4; i++) { ! 358: x86_cpu_def->vendor1 |= ((uint8_t)val[i ]) << (8 * i); ! 359: x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i); ! 360: x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i); ! 361: } ! 362: } else if (!strcmp(featurestr, "model_id")) { ! 363: pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), ! 364: val); ! 365: } else { ! 366: fprintf(stderr, "unrecognized feature %s\n", featurestr); ! 367: goto error; ! 368: } ! 369: } else { ! 370: fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr); ! 371: goto error; ! 372: } ! 373: featurestr = strtok(NULL, ","); 1.1 root 374: } 1.1.1.7 ! root 375: x86_cpu_def->features |= plus_features; ! 376: x86_cpu_def->ext_features |= plus_ext_features; ! 377: x86_cpu_def->ext2_features |= plus_ext2_features; ! 378: x86_cpu_def->ext3_features |= plus_ext3_features; ! 379: x86_cpu_def->features &= ~minus_features; ! 380: x86_cpu_def->ext_features &= ~minus_ext_features; ! 381: x86_cpu_def->ext2_features &= ~minus_ext2_features; ! 382: x86_cpu_def->ext3_features &= ~minus_ext3_features; ! 383: free(s); ! 384: return 0; 1.1 root 385: 1.1.1.7 ! root 386: error: ! 387: free(s); ! 388: return -1; 1.1 root 389: } 390: 1.1.1.7 ! root 391: void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) 1.1 root 392: { 1.1.1.7 ! root 393: unsigned int i; 1.1 root 394: 1.1.1.7 ! root 395: for (i = 0; i < ARRAY_SIZE(x86_defs); i++) ! 396: (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name); 1.1 root 397: } 398: 1.1.1.7 ! root 399: static int cpu_x86_register (CPUX86State *env, const char *cpu_model) 1.1 root 400: { 1.1.1.7 ! root 401: x86_def_t def1, *def = &def1; 1.1 root 402: 1.1.1.7 ! root 403: if (cpu_x86_find_by_name(def, cpu_model) < 0) ! 404: return -1; ! 405: if (def->vendor1) { ! 406: env->cpuid_vendor1 = def->vendor1; ! 407: env->cpuid_vendor2 = def->vendor2; ! 408: env->cpuid_vendor3 = def->vendor3; ! 409: } else { ! 410: env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1; ! 411: env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2; ! 412: env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3; ! 413: } ! 414: env->cpuid_level = def->level; ! 415: if (def->family > 0x0f) ! 416: env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20); ! 417: else ! 418: env->cpuid_version = def->family << 8; ! 419: env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16); ! 420: env->cpuid_version |= def->stepping; ! 421: env->cpuid_features = def->features; ! 422: env->pat = 0x0007040600070406ULL; ! 423: env->cpuid_ext_features = def->ext_features; ! 424: env->cpuid_ext2_features = def->ext2_features; ! 425: env->cpuid_xlevel = def->xlevel; ! 426: env->cpuid_ext3_features = def->ext3_features; ! 427: { ! 428: const char *model_id = def->model_id; ! 429: int c, len, i; ! 430: if (!model_id) ! 431: model_id = ""; ! 432: len = strlen(model_id); ! 433: for(i = 0; i < 48; i++) { ! 434: if (i >= len) ! 435: c = '\0'; ! 436: else ! 437: c = (uint8_t)model_id[i]; ! 438: env->cpuid_model[i >> 2] |= c << (8 * (i & 3)); ! 439: } 1.1 root 440: } 1.1.1.7 ! root 441: return 0; 1.1 root 442: } 443: 1.1.1.7 ! root 444: /* NOTE: must be called outside the CPU execute loop */ ! 445: void cpu_reset(CPUX86State *env) 1.1 root 446: { 1.1.1.7 ! root 447: int i; 1.1 root 448: 1.1.1.7 ! root 449: if (qemu_loglevel_mask(CPU_LOG_RESET)) { ! 450: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); ! 451: log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP); 1.1 root 452: } 453: 1.1.1.7 ! root 454: memset(env, 0, offsetof(CPUX86State, breakpoints)); 1.1 root 455: 1.1.1.7 ! root 456: tlb_flush(env, 1); 1.1 root 457: 1.1.1.7 ! root 458: env->old_exception = -1; 1.1 root 459: 1.1.1.7 ! root 460: /* init to reset state */ 1.1 root 461: 1.1.1.7 ! root 462: #ifdef CONFIG_SOFTMMU ! 463: env->hflags |= HF_SOFTMMU_MASK; 1.1 root 464: #endif 1.1.1.7 ! root 465: env->hflags2 |= HF2_GIF_MASK; 1.1 root 466: 1.1.1.7 ! root 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: env->regs[R_EDX] = env->cpuid_version; ! 493: ! 494: env->eflags = 0x2; ! 495: ! 496: /* FPU init */ ! 497: for(i = 0;i < 8; i++) ! 498: env->fptags[i] = 1; 1.1 root 499: env->fpuc = 0x37f; 500: 1.1.1.7 ! root 501: env->mxcsr = 0x1f80; 1.1 root 502: 1.1.1.7 ! root 503: memset(env->dr, 0, sizeof(env->dr)); ! 504: env->dr[6] = DR6_FIXED_1; ! 505: env->dr[7] = DR7_FIXED_1; ! 506: cpu_breakpoint_remove_all(env, BP_CPU); ! 507: cpu_watchpoint_remove_all(env, BP_CPU); ! 508: } ! 509: ! 510: void cpu_x86_close(CPUX86State *env) ! 511: { ! 512: qemu_free(env); ! 513: } ! 514: ! 515: /***********************************************************/ ! 516: /* x86 debug */ ! 517: ! 518: static const char *cc_op_str[] = { ! 519: "DYNAMIC", ! 520: "EFLAGS", ! 521: ! 522: "MULB", ! 523: "MULW", ! 524: "MULL", ! 525: "MULQ", ! 526: ! 527: "ADDB", ! 528: "ADDW", ! 529: "ADDL", ! 530: "ADDQ", ! 531: ! 532: "ADCB", ! 533: "ADCW", ! 534: "ADCL", ! 535: "ADCQ", ! 536: ! 537: "SUBB", ! 538: "SUBW", ! 539: "SUBL", ! 540: "SUBQ", ! 541: ! 542: "SBBB", ! 543: "SBBW", ! 544: "SBBL", ! 545: "SBBQ", ! 546: ! 547: "LOGICB", ! 548: "LOGICW", ! 549: "LOGICL", ! 550: "LOGICQ", ! 551: ! 552: "INCB", ! 553: "INCW", ! 554: "INCL", ! 555: "INCQ", ! 556: ! 557: "DECB", ! 558: "DECW", ! 559: "DECL", ! 560: "DECQ", ! 561: ! 562: "SHLB", ! 563: "SHLW", ! 564: "SHLL", ! 565: "SHLQ", ! 566: ! 567: "SARB", ! 568: "SARW", ! 569: "SARL", ! 570: "SARQ", ! 571: }; 1.1 root 572: 1.1.1.7 ! root 573: void cpu_dump_state(CPUState *env, FILE *f, ! 574: int (*cpu_fprintf)(FILE *f, const char *fmt, ...), ! 575: int flags) ! 576: { ! 577: int eflags, i, nb; ! 578: char cc_op_name[32]; ! 579: static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" }; ! 580: ! 581: if (kvm_enabled()) ! 582: kvm_arch_get_registers(env); ! 583: ! 584: eflags = env->eflags; ! 585: #ifdef TARGET_X86_64 ! 586: if (env->hflags & HF_CS64_MASK) { ! 587: cpu_fprintf(f, ! 588: "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n" ! 589: "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n" ! 590: "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n" ! 591: "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n" ! 592: "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n", ! 593: env->regs[R_EAX], ! 594: env->regs[R_EBX], ! 595: env->regs[R_ECX], ! 596: env->regs[R_EDX], ! 597: env->regs[R_ESI], ! 598: env->regs[R_EDI], ! 599: env->regs[R_EBP], ! 600: env->regs[R_ESP], ! 601: env->regs[8], ! 602: env->regs[9], ! 603: env->regs[10], ! 604: env->regs[11], ! 605: env->regs[12], ! 606: env->regs[13], ! 607: env->regs[14], ! 608: env->regs[15], ! 609: env->eip, eflags, ! 610: eflags & DF_MASK ? 'D' : '-', ! 611: eflags & CC_O ? 'O' : '-', ! 612: eflags & CC_S ? 'S' : '-', ! 613: eflags & CC_Z ? 'Z' : '-', ! 614: eflags & CC_A ? 'A' : '-', ! 615: eflags & CC_P ? 'P' : '-', ! 616: eflags & CC_C ? 'C' : '-', ! 617: env->hflags & HF_CPL_MASK, ! 618: (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, ! 619: (int)(env->a20_mask >> 20) & 1, ! 620: (env->hflags >> HF_SMM_SHIFT) & 1, ! 621: env->halted); ! 622: } else ! 623: #endif ! 624: { ! 625: cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" ! 626: "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" ! 627: "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n", ! 628: (uint32_t)env->regs[R_EAX], ! 629: (uint32_t)env->regs[R_EBX], ! 630: (uint32_t)env->regs[R_ECX], ! 631: (uint32_t)env->regs[R_EDX], ! 632: (uint32_t)env->regs[R_ESI], ! 633: (uint32_t)env->regs[R_EDI], ! 634: (uint32_t)env->regs[R_EBP], ! 635: (uint32_t)env->regs[R_ESP], ! 636: (uint32_t)env->eip, eflags, ! 637: eflags & DF_MASK ? 'D' : '-', ! 638: eflags & CC_O ? 'O' : '-', ! 639: eflags & CC_S ? 'S' : '-', ! 640: eflags & CC_Z ? 'Z' : '-', ! 641: eflags & CC_A ? 'A' : '-', ! 642: eflags & CC_P ? 'P' : '-', ! 643: eflags & CC_C ? 'C' : '-', ! 644: env->hflags & HF_CPL_MASK, ! 645: (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, ! 646: (int)(env->a20_mask >> 20) & 1, ! 647: (env->hflags >> HF_SMM_SHIFT) & 1, ! 648: env->halted); 1.1 root 649: } 650: 1.1.1.7 ! root 651: #ifdef TARGET_X86_64 ! 652: if (env->hflags & HF_LMA_MASK) { ! 653: for(i = 0; i < 6; i++) { ! 654: SegmentCache *sc = &env->segs[i]; ! 655: cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n", ! 656: seg_name[i], ! 657: sc->selector, ! 658: sc->base, ! 659: sc->limit, ! 660: sc->flags); ! 661: } ! 662: cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n", ! 663: env->ldt.selector, ! 664: env->ldt.base, ! 665: env->ldt.limit, ! 666: env->ldt.flags); ! 667: cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n", ! 668: env->tr.selector, ! 669: env->tr.base, ! 670: env->tr.limit, ! 671: env->tr.flags); ! 672: cpu_fprintf(f, "GDT= %016" PRIx64 " %08x\n", ! 673: env->gdt.base, env->gdt.limit); ! 674: cpu_fprintf(f, "IDT= %016" PRIx64 " %08x\n", ! 675: env->idt.base, env->idt.limit); ! 676: cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n", ! 677: (uint32_t)env->cr[0], ! 678: env->cr[2], ! 679: env->cr[3], ! 680: (uint32_t)env->cr[4]); ! 681: for(i = 0; i < 4; i++) ! 682: cpu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]); ! 683: cpu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n", ! 684: env->dr[6], env->dr[7]); ! 685: } else ! 686: #endif ! 687: { ! 688: for(i = 0; i < 6; i++) { ! 689: SegmentCache *sc = &env->segs[i]; ! 690: cpu_fprintf(f, "%s =%04x %08x %08x %08x\n", ! 691: seg_name[i], ! 692: sc->selector, ! 693: (uint32_t)sc->base, ! 694: sc->limit, ! 695: sc->flags); ! 696: } ! 697: cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n", ! 698: env->ldt.selector, ! 699: (uint32_t)env->ldt.base, ! 700: env->ldt.limit, ! 701: env->ldt.flags); ! 702: cpu_fprintf(f, "TR =%04x %08x %08x %08x\n", ! 703: env->tr.selector, ! 704: (uint32_t)env->tr.base, ! 705: env->tr.limit, ! 706: env->tr.flags); ! 707: cpu_fprintf(f, "GDT= %08x %08x\n", ! 708: (uint32_t)env->gdt.base, env->gdt.limit); ! 709: cpu_fprintf(f, "IDT= %08x %08x\n", ! 710: (uint32_t)env->idt.base, env->idt.limit); ! 711: cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n", ! 712: (uint32_t)env->cr[0], ! 713: (uint32_t)env->cr[2], ! 714: (uint32_t)env->cr[3], ! 715: (uint32_t)env->cr[4]); ! 716: for(i = 0; i < 4; i++) ! 717: cpu_fprintf(f, "DR%d=%08x ", i, env->dr[i]); ! 718: cpu_fprintf(f, "\nDR6=%08x DR7=%08x\n", env->dr[6], env->dr[7]); 1.1 root 719: } 1.1.1.7 ! root 720: if (flags & X86_DUMP_CCOP) { ! 721: if ((unsigned)env->cc_op < CC_OP_NB) ! 722: snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]); ! 723: else ! 724: snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op); ! 725: #ifdef TARGET_X86_64 ! 726: if (env->hflags & HF_CS64_MASK) { ! 727: cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n", ! 728: env->cc_src, env->cc_dst, ! 729: cc_op_name); ! 730: } else 1.1 root 731: #endif 1.1.1.7 ! root 732: { ! 733: cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n", ! 734: (uint32_t)env->cc_src, (uint32_t)env->cc_dst, ! 735: cc_op_name); ! 736: } ! 737: } ! 738: if (flags & X86_DUMP_FPU) { ! 739: int fptag; ! 740: fptag = 0; ! 741: for(i = 0; i < 8; i++) { ! 742: fptag |= ((!env->fptags[i]) << i); ! 743: } ! 744: cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n", ! 745: env->fpuc, ! 746: (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11, ! 747: env->fpstt, ! 748: fptag, ! 749: env->mxcsr); ! 750: for(i=0;i<8;i++) { ! 751: #if defined(USE_X86LDOUBLE) ! 752: union { ! 753: long double d; ! 754: struct { ! 755: uint64_t lower; ! 756: uint16_t upper; ! 757: } l; ! 758: } tmp; ! 759: tmp.d = env->fpregs[i].d; ! 760: cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x", ! 761: i, tmp.l.lower, tmp.l.upper); 1.1 root 762: #else 1.1.1.7 ! root 763: cpu_fprintf(f, "FPR%d=%016" PRIx64, ! 764: i, env->fpregs[i].mmx.q); 1.1 root 765: #endif 1.1.1.7 ! root 766: if ((i & 1) == 1) ! 767: cpu_fprintf(f, "\n"); ! 768: else ! 769: cpu_fprintf(f, " "); ! 770: } ! 771: if (env->hflags & HF_CS64_MASK) ! 772: nb = 16; ! 773: else ! 774: nb = 8; ! 775: for(i=0;i<nb;i++) { ! 776: cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x", ! 777: i, ! 778: env->xmm_regs[i].XMM_L(3), ! 779: env->xmm_regs[i].XMM_L(2), ! 780: env->xmm_regs[i].XMM_L(1), ! 781: env->xmm_regs[i].XMM_L(0)); ! 782: if ((i & 1) == 1) ! 783: cpu_fprintf(f, "\n"); ! 784: else ! 785: cpu_fprintf(f, " "); 1.1 root 786: } 787: } 788: } 789: 1.1.1.7 ! root 790: /***********************************************************/ ! 791: /* x86 mmu */ ! 792: /* XXX: add PGE support */ 1.1 root 793: 1.1.1.7 ! root 794: void cpu_x86_set_a20(CPUX86State *env, int a20_state) 1.1 root 795: { 1.1.1.7 ! root 796: a20_state = (a20_state != 0); ! 797: if (a20_state != ((env->a20_mask >> 20) & 1)) { ! 798: #if defined(DEBUG_MMU) ! 799: printf("A20 update: a20=%d\n", a20_state); ! 800: #endif ! 801: /* if the cpu is currently executing code, we must unlink it and ! 802: all the potentially executing TB */ ! 803: cpu_interrupt(env, CPU_INTERRUPT_EXITTB); 1.1 root 804: 1.1.1.7 ! root 805: /* when a20 is changed, all the MMU mappings are invalid, so ! 806: we must flush everything */ ! 807: tlb_flush(env, 1); ! 808: env->a20_mask = (~0x100000) | (a20_state << 20); ! 809: } 1.1 root 810: } 811: 1.1.1.7 ! root 812: void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0) 1.1 root 813: { 1.1.1.7 ! root 814: int pe_state; 1.1 root 815: 1.1.1.7 ! root 816: #if defined(DEBUG_MMU) ! 817: printf("CR0 update: CR0=0x%08x\n", new_cr0); ! 818: #endif ! 819: if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) != ! 820: (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) { ! 821: tlb_flush(env, 1); 1.1 root 822: } 823: 1.1.1.7 ! root 824: #ifdef TARGET_X86_64 ! 825: if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) && ! 826: (env->efer & MSR_EFER_LME)) { ! 827: /* enter in long mode */ ! 828: /* XXX: generate an exception */ ! 829: if (!(env->cr[4] & CR4_PAE_MASK)) ! 830: return; ! 831: env->efer |= MSR_EFER_LMA; ! 832: env->hflags |= HF_LMA_MASK; ! 833: } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) && ! 834: (env->efer & MSR_EFER_LMA)) { ! 835: /* exit long mode */ ! 836: env->efer &= ~MSR_EFER_LMA; ! 837: env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK); ! 838: env->eip &= 0xffffffff; 1.1 root 839: } 840: #endif 1.1.1.7 ! root 841: env->cr[0] = new_cr0 | CR0_ET_MASK; 1.1 root 842: 1.1.1.7 ! root 843: /* update PE flag in hidden flags */ ! 844: pe_state = (env->cr[0] & CR0_PE_MASK); ! 845: env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT); ! 846: /* ensure that ADDSEG is always set in real mode */ ! 847: env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT); ! 848: /* update FPU flags */ ! 849: env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) | ! 850: ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)); 1.1.1.4 root 851: } 852: 1.1.1.7 ! root 853: /* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in ! 854: the PDPT */ ! 855: void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3) 1.1.1.4 root 856: { 1.1.1.7 ! root 857: env->cr[3] = new_cr3; ! 858: if (env->cr[0] & CR0_PG_MASK) { ! 859: #if defined(DEBUG_MMU) ! 860: printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3); ! 861: #endif ! 862: tlb_flush(env, 0); ! 863: } 1.1.1.4 root 864: } 865: 1.1.1.7 ! root 866: void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) 1.1.1.4 root 867: { 1.1.1.7 ! root 868: #if defined(DEBUG_MMU) ! 869: printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]); ! 870: #endif ! 871: if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) != ! 872: (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) { ! 873: tlb_flush(env, 1); 1.1.1.4 root 874: } 1.1.1.7 ! root 875: /* SSE handling */ ! 876: if (!(env->cpuid_features & CPUID_SSE)) ! 877: new_cr4 &= ~CR4_OSFXSR_MASK; ! 878: if (new_cr4 & CR4_OSFXSR_MASK) ! 879: env->hflags |= HF_OSFXSR_MASK; ! 880: else ! 881: env->hflags &= ~HF_OSFXSR_MASK; 1.1.1.4 root 882: 1.1.1.7 ! root 883: env->cr[4] = new_cr4; 1.1 root 884: } 885: 1.1.1.7 ! root 886: #if defined(CONFIG_USER_ONLY) ! 887: ! 888: int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, ! 889: int is_write, int mmu_idx, int is_softmmu) 1.1 root 890: { 1.1.1.7 ! root 891: /* user mode only emulation */ ! 892: is_write &= 1; ! 893: env->cr[2] = addr; ! 894: env->error_code = (is_write << PG_ERROR_W_BIT); ! 895: env->error_code |= PG_ERROR_U_MASK; ! 896: env->exception_index = EXCP0E_PAGE; ! 897: return 1; 1.1 root 898: } 899: 1.1.1.7 ! root 900: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) 1.1 root 901: { 1.1.1.7 ! root 902: return addr; 1.1 root 903: } 904: 1.1.1.6 root 905: #else 1.1 root 906: 1.1.1.7 ! root 907: /* XXX: This value should match the one returned by CPUID ! 908: * and in exec.c */ ! 909: #if defined(USE_KQEMU) ! 910: #define PHYS_ADDR_MASK 0xfffff000LL ! 911: #else ! 912: # if defined(TARGET_X86_64) ! 913: # define PHYS_ADDR_MASK 0xfffffff000LL ! 914: # else ! 915: # define PHYS_ADDR_MASK 0xffffff000LL ! 916: # endif ! 917: #endif ! 918: ! 919: /* return value: ! 920: -1 = cannot handle fault ! 921: 0 = nothing more to do ! 922: 1 = generate PF fault ! 923: 2 = soft MMU activation required for this block ! 924: */ ! 925: int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, ! 926: int is_write1, int mmu_idx, int is_softmmu) ! 927: { ! 928: uint64_t ptep, pte; ! 929: target_ulong pde_addr, pte_addr; ! 930: int error_code, is_dirty, prot, page_size, ret, is_write, is_user; ! 931: target_phys_addr_t paddr; ! 932: uint32_t page_offset; ! 933: target_ulong vaddr, virt_addr; ! 934: ! 935: is_user = mmu_idx == MMU_USER_IDX; ! 936: #if defined(DEBUG_MMU) ! 937: printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n", ! 938: addr, is_write1, is_user, env->eip); ! 939: #endif ! 940: is_write = is_write1 & 1; ! 941: ! 942: if (!(env->cr[0] & CR0_PG_MASK)) { ! 943: pte = addr; ! 944: virt_addr = addr & TARGET_PAGE_MASK; ! 945: prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ! 946: page_size = 4096; ! 947: goto do_mapping; ! 948: } ! 949: ! 950: if (env->cr[4] & CR4_PAE_MASK) { ! 951: uint64_t pde, pdpe; ! 952: target_ulong pdpe_addr; 1.1 root 953: 1.1.1.7 ! root 954: #ifdef TARGET_X86_64 ! 955: if (env->hflags & HF_LMA_MASK) { ! 956: uint64_t pml4e_addr, pml4e; ! 957: int32_t sext; 1.1 root 958: 1.1.1.7 ! root 959: /* test virtual address sign extension */ ! 960: sext = (int64_t)addr >> 47; ! 961: if (sext != 0 && sext != -1) { ! 962: env->error_code = 0; ! 963: env->exception_index = EXCP0D_GPF; ! 964: return 1; ! 965: } 1.1 root 966: 1.1.1.7 ! root 967: pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & ! 968: env->a20_mask; ! 969: pml4e = ldq_phys(pml4e_addr); ! 970: if (!(pml4e & PG_PRESENT_MASK)) { ! 971: error_code = 0; ! 972: goto do_fault; ! 973: } ! 974: if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) { ! 975: error_code = PG_ERROR_RSVD_MASK; ! 976: goto do_fault; ! 977: } ! 978: if (!(pml4e & PG_ACCESSED_MASK)) { ! 979: pml4e |= PG_ACCESSED_MASK; ! 980: stl_phys_notdirty(pml4e_addr, pml4e); ! 981: } ! 982: ptep = pml4e ^ PG_NX_MASK; ! 983: pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) & ! 984: env->a20_mask; ! 985: pdpe = ldq_phys(pdpe_addr); ! 986: if (!(pdpe & PG_PRESENT_MASK)) { ! 987: error_code = 0; ! 988: goto do_fault; ! 989: } ! 990: if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) { ! 991: error_code = PG_ERROR_RSVD_MASK; ! 992: goto do_fault; ! 993: } ! 994: ptep &= pdpe ^ PG_NX_MASK; ! 995: if (!(pdpe & PG_ACCESSED_MASK)) { ! 996: pdpe |= PG_ACCESSED_MASK; ! 997: stl_phys_notdirty(pdpe_addr, pdpe); ! 998: } ! 999: } else 1.1 root 1000: #endif 1.1.1.7 ! root 1001: { ! 1002: /* XXX: load them when cr3 is loaded ? */ ! 1003: pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) & ! 1004: env->a20_mask; ! 1005: pdpe = ldq_phys(pdpe_addr); ! 1006: if (!(pdpe & PG_PRESENT_MASK)) { ! 1007: error_code = 0; ! 1008: goto do_fault; 1.1 root 1009: } 1.1.1.7 ! root 1010: ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK; 1.1 root 1011: } 1.1.1.6 root 1012: 1.1.1.7 ! root 1013: pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) & ! 1014: env->a20_mask; ! 1015: pde = ldq_phys(pde_addr); ! 1016: if (!(pde & PG_PRESENT_MASK)) { ! 1017: error_code = 0; ! 1018: goto do_fault; ! 1019: } ! 1020: if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) { ! 1021: error_code = PG_ERROR_RSVD_MASK; ! 1022: goto do_fault; ! 1023: } ! 1024: ptep &= pde ^ PG_NX_MASK; ! 1025: if (pde & PG_PSE_MASK) { ! 1026: /* 2 MB page */ ! 1027: page_size = 2048 * 1024; ! 1028: ptep ^= PG_NX_MASK; ! 1029: if ((ptep & PG_NX_MASK) && is_write1 == 2) ! 1030: goto do_fault_protect; ! 1031: if (is_user) { ! 1032: if (!(ptep & PG_USER_MASK)) ! 1033: goto do_fault_protect; ! 1034: if (is_write && !(ptep & PG_RW_MASK)) ! 1035: goto do_fault_protect; ! 1036: } else { ! 1037: if ((env->cr[0] & CR0_WP_MASK) && ! 1038: is_write && !(ptep & PG_RW_MASK)) ! 1039: goto do_fault_protect; ! 1040: } ! 1041: is_dirty = is_write && !(pde & PG_DIRTY_MASK); ! 1042: if (!(pde & PG_ACCESSED_MASK) || is_dirty) { ! 1043: pde |= PG_ACCESSED_MASK; ! 1044: if (is_dirty) ! 1045: pde |= PG_DIRTY_MASK; ! 1046: stl_phys_notdirty(pde_addr, pde); ! 1047: } ! 1048: /* align to page_size */ ! 1049: pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff); ! 1050: virt_addr = addr & ~(page_size - 1); ! 1051: } else { ! 1052: /* 4 KB page */ ! 1053: if (!(pde & PG_ACCESSED_MASK)) { ! 1054: pde |= PG_ACCESSED_MASK; ! 1055: stl_phys_notdirty(pde_addr, pde); ! 1056: } ! 1057: pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) & ! 1058: env->a20_mask; ! 1059: pte = ldq_phys(pte_addr); ! 1060: if (!(pte & PG_PRESENT_MASK)) { ! 1061: error_code = 0; ! 1062: goto do_fault; ! 1063: } ! 1064: if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) { ! 1065: error_code = PG_ERROR_RSVD_MASK; ! 1066: goto do_fault; ! 1067: } ! 1068: /* combine pde and pte nx, user and rw protections */ ! 1069: ptep &= pte ^ PG_NX_MASK; ! 1070: ptep ^= PG_NX_MASK; ! 1071: if ((ptep & PG_NX_MASK) && is_write1 == 2) ! 1072: goto do_fault_protect; ! 1073: if (is_user) { ! 1074: if (!(ptep & PG_USER_MASK)) ! 1075: goto do_fault_protect; ! 1076: if (is_write && !(ptep & PG_RW_MASK)) ! 1077: goto do_fault_protect; ! 1078: } else { ! 1079: if ((env->cr[0] & CR0_WP_MASK) && ! 1080: is_write && !(ptep & PG_RW_MASK)) ! 1081: goto do_fault_protect; ! 1082: } ! 1083: is_dirty = is_write && !(pte & PG_DIRTY_MASK); ! 1084: if (!(pte & PG_ACCESSED_MASK) || is_dirty) { ! 1085: pte |= PG_ACCESSED_MASK; ! 1086: if (is_dirty) ! 1087: pte |= PG_DIRTY_MASK; ! 1088: stl_phys_notdirty(pte_addr, pte); ! 1089: } ! 1090: page_size = 4096; ! 1091: virt_addr = addr & ~0xfff; ! 1092: pte = pte & (PHYS_ADDR_MASK | 0xfff); ! 1093: } ! 1094: } else { ! 1095: uint32_t pde; ! 1096: ! 1097: /* page directory entry */ ! 1098: pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & ! 1099: env->a20_mask; ! 1100: pde = ldl_phys(pde_addr); ! 1101: if (!(pde & PG_PRESENT_MASK)) { ! 1102: error_code = 0; ! 1103: goto do_fault; ! 1104: } ! 1105: /* if PSE bit is set, then we use a 4MB page */ ! 1106: if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { ! 1107: page_size = 4096 * 1024; ! 1108: if (is_user) { ! 1109: if (!(pde & PG_USER_MASK)) ! 1110: goto do_fault_protect; ! 1111: if (is_write && !(pde & PG_RW_MASK)) ! 1112: goto do_fault_protect; ! 1113: } else { ! 1114: if ((env->cr[0] & CR0_WP_MASK) && ! 1115: is_write && !(pde & PG_RW_MASK)) ! 1116: goto do_fault_protect; ! 1117: } ! 1118: is_dirty = is_write && !(pde & PG_DIRTY_MASK); ! 1119: if (!(pde & PG_ACCESSED_MASK) || is_dirty) { ! 1120: pde |= PG_ACCESSED_MASK; ! 1121: if (is_dirty) ! 1122: pde |= PG_DIRTY_MASK; ! 1123: stl_phys_notdirty(pde_addr, pde); ! 1124: } 1.1.1.6 root 1125: 1.1.1.7 ! root 1126: pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */ ! 1127: ptep = pte; ! 1128: virt_addr = addr & ~(page_size - 1); ! 1129: } else { ! 1130: if (!(pde & PG_ACCESSED_MASK)) { ! 1131: pde |= PG_ACCESSED_MASK; ! 1132: stl_phys_notdirty(pde_addr, pde); ! 1133: } 1.1.1.6 root 1134: 1.1.1.7 ! root 1135: /* page directory entry */ ! 1136: pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & ! 1137: env->a20_mask; ! 1138: pte = ldl_phys(pte_addr); ! 1139: if (!(pte & PG_PRESENT_MASK)) { ! 1140: error_code = 0; ! 1141: goto do_fault; ! 1142: } ! 1143: /* combine pde and pte user and rw protections */ ! 1144: ptep = pte & pde; ! 1145: if (is_user) { ! 1146: if (!(ptep & PG_USER_MASK)) ! 1147: goto do_fault_protect; ! 1148: if (is_write && !(ptep & PG_RW_MASK)) ! 1149: goto do_fault_protect; ! 1150: } else { ! 1151: if ((env->cr[0] & CR0_WP_MASK) && ! 1152: is_write && !(ptep & PG_RW_MASK)) ! 1153: goto do_fault_protect; ! 1154: } ! 1155: is_dirty = is_write && !(pte & PG_DIRTY_MASK); ! 1156: if (!(pte & PG_ACCESSED_MASK) || is_dirty) { ! 1157: pte |= PG_ACCESSED_MASK; ! 1158: if (is_dirty) ! 1159: pte |= PG_DIRTY_MASK; ! 1160: stl_phys_notdirty(pte_addr, pte); ! 1161: } ! 1162: page_size = 4096; ! 1163: virt_addr = addr & ~0xfff; ! 1164: } ! 1165: } ! 1166: /* the page can be put in the TLB */ ! 1167: prot = PAGE_READ; ! 1168: if (!(ptep & PG_NX_MASK)) ! 1169: prot |= PAGE_EXEC; ! 1170: if (pte & PG_DIRTY_MASK) { ! 1171: /* only set write access if already dirty... otherwise wait ! 1172: for dirty access */ ! 1173: if (is_user) { ! 1174: if (ptep & PG_RW_MASK) ! 1175: prot |= PAGE_WRITE; ! 1176: } else { ! 1177: if (!(env->cr[0] & CR0_WP_MASK) || ! 1178: (ptep & PG_RW_MASK)) ! 1179: prot |= PAGE_WRITE; ! 1180: } ! 1181: } ! 1182: do_mapping: ! 1183: pte = pte & env->a20_mask; ! 1184: ! 1185: /* Even if 4MB pages, we map only one 4KB page in the cache to ! 1186: avoid filling it too fast */ ! 1187: page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1); ! 1188: paddr = (pte & TARGET_PAGE_MASK) + page_offset; ! 1189: vaddr = virt_addr + page_offset; ! 1190: ! 1191: ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu); ! 1192: return ret; ! 1193: do_fault_protect: ! 1194: error_code = PG_ERROR_P_MASK; ! 1195: do_fault: ! 1196: error_code |= (is_write << PG_ERROR_W_BIT); ! 1197: if (is_user) ! 1198: error_code |= PG_ERROR_U_MASK; ! 1199: if (is_write1 == 2 && ! 1200: (env->efer & MSR_EFER_NXE) && ! 1201: (env->cr[4] & CR4_PAE_MASK)) ! 1202: error_code |= PG_ERROR_I_D_MASK; ! 1203: if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) { ! 1204: /* cr2 is not modified in case of exceptions */ ! 1205: stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), ! 1206: addr); ! 1207: } else { ! 1208: env->cr[2] = addr; ! 1209: } ! 1210: env->error_code = error_code; ! 1211: env->exception_index = EXCP0E_PAGE; ! 1212: return 1; 1.1.1.6 root 1213: } 1214: 1.1.1.7 ! root 1215: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) 1.1.1.6 root 1216: { 1.1.1.7 ! root 1217: target_ulong pde_addr, pte_addr; ! 1218: uint64_t pte; ! 1219: target_phys_addr_t paddr; ! 1220: uint32_t page_offset; ! 1221: int page_size; 1.1.1.6 root 1222: 1.1.1.7 ! root 1223: if (env->cr[4] & CR4_PAE_MASK) { ! 1224: target_ulong pdpe_addr; ! 1225: uint64_t pde, pdpe; 1.1.1.6 root 1226: 1.1.1.7 ! root 1227: #ifdef TARGET_X86_64 ! 1228: if (env->hflags & HF_LMA_MASK) { ! 1229: uint64_t pml4e_addr, pml4e; ! 1230: int32_t sext; 1.1.1.6 root 1231: 1.1.1.7 ! root 1232: /* test virtual address sign extension */ ! 1233: sext = (int64_t)addr >> 47; ! 1234: if (sext != 0 && sext != -1) ! 1235: return -1; ! 1236: ! 1237: pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & ! 1238: env->a20_mask; ! 1239: pml4e = ldq_phys(pml4e_addr); ! 1240: if (!(pml4e & PG_PRESENT_MASK)) ! 1241: return -1; ! 1242: ! 1243: pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & ! 1244: env->a20_mask; ! 1245: pdpe = ldq_phys(pdpe_addr); ! 1246: if (!(pdpe & PG_PRESENT_MASK)) ! 1247: return -1; ! 1248: } else ! 1249: #endif ! 1250: { ! 1251: pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) & ! 1252: env->a20_mask; ! 1253: pdpe = ldq_phys(pdpe_addr); ! 1254: if (!(pdpe & PG_PRESENT_MASK)) ! 1255: return -1; ! 1256: } ! 1257: ! 1258: pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) & ! 1259: env->a20_mask; ! 1260: pde = ldq_phys(pde_addr); ! 1261: if (!(pde & PG_PRESENT_MASK)) { ! 1262: return -1; ! 1263: } ! 1264: if (pde & PG_PSE_MASK) { ! 1265: /* 2 MB page */ ! 1266: page_size = 2048 * 1024; ! 1267: pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */ ! 1268: } else { ! 1269: /* 4 KB page */ ! 1270: pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) & ! 1271: env->a20_mask; ! 1272: page_size = 4096; ! 1273: pte = ldq_phys(pte_addr); ! 1274: } ! 1275: if (!(pte & PG_PRESENT_MASK)) ! 1276: return -1; ! 1277: } else { ! 1278: uint32_t pde; ! 1279: ! 1280: if (!(env->cr[0] & CR0_PG_MASK)) { ! 1281: pte = addr; ! 1282: page_size = 4096; ! 1283: } else { ! 1284: /* page directory entry */ ! 1285: pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask; ! 1286: pde = ldl_phys(pde_addr); ! 1287: if (!(pde & PG_PRESENT_MASK)) ! 1288: return -1; ! 1289: if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { ! 1290: pte = pde & ~0x003ff000; /* align to 4MB */ ! 1291: page_size = 4096 * 1024; ! 1292: } else { ! 1293: /* page directory entry */ ! 1294: pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask; ! 1295: pte = ldl_phys(pte_addr); ! 1296: if (!(pte & PG_PRESENT_MASK)) ! 1297: return -1; ! 1298: page_size = 4096; ! 1299: } ! 1300: } ! 1301: pte = pte & env->a20_mask; ! 1302: } 1.1.1.6 root 1303: 1.1.1.7 ! root 1304: page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1); ! 1305: paddr = (pte & TARGET_PAGE_MASK) + page_offset; ! 1306: return paddr; 1.1.1.6 root 1307: } 1308: 1.1.1.7 ! root 1309: void hw_breakpoint_insert(CPUState *env, int index) 1.1.1.6 root 1310: { 1.1.1.7 ! root 1311: int type, err = 0; 1.1.1.6 root 1312: 1.1.1.7 ! root 1313: switch (hw_breakpoint_type(env->dr[7], index)) { ! 1314: case 0: ! 1315: if (hw_breakpoint_enabled(env->dr[7], index)) ! 1316: err = cpu_breakpoint_insert(env, env->dr[index], BP_CPU, ! 1317: &env->cpu_breakpoint[index]); ! 1318: break; ! 1319: case 1: ! 1320: type = BP_CPU | BP_MEM_WRITE; ! 1321: goto insert_wp; ! 1322: case 2: ! 1323: /* No support for I/O watchpoints yet */ ! 1324: break; ! 1325: case 3: ! 1326: type = BP_CPU | BP_MEM_ACCESS; ! 1327: insert_wp: ! 1328: err = cpu_watchpoint_insert(env, env->dr[index], ! 1329: hw_breakpoint_len(env->dr[7], index), ! 1330: type, &env->cpu_watchpoint[index]); ! 1331: break; 1.1.1.6 root 1332: } 1.1.1.7 ! root 1333: if (err) ! 1334: env->cpu_breakpoint[index] = NULL; ! 1335: } 1.1.1.6 root 1336: 1.1.1.7 ! root 1337: void hw_breakpoint_remove(CPUState *env, int index) ! 1338: { ! 1339: if (!env->cpu_breakpoint[index]) ! 1340: return; ! 1341: switch (hw_breakpoint_type(env->dr[7], index)) { ! 1342: case 0: ! 1343: if (hw_breakpoint_enabled(env->dr[7], index)) ! 1344: cpu_breakpoint_remove_by_ref(env, env->cpu_breakpoint[index]); ! 1345: break; ! 1346: case 1: ! 1347: case 3: ! 1348: cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[index]); ! 1349: break; ! 1350: case 2: ! 1351: /* No support for I/O watchpoints yet */ 1.1.1.6 root 1352: break; 1353: } 1.1.1.7 ! root 1354: } 1.1.1.6 root 1355: 1.1.1.7 ! root 1356: int check_hw_breakpoints(CPUState *env, int force_dr6_update) ! 1357: { ! 1358: target_ulong dr6; ! 1359: int reg, type; ! 1360: int hit_enabled = 0; 1.1.1.6 root 1361: 1.1.1.7 ! root 1362: dr6 = env->dr[6] & ~0xf; ! 1363: for (reg = 0; reg < 4; reg++) { ! 1364: type = hw_breakpoint_type(env->dr[7], reg); ! 1365: if ((type == 0 && env->dr[reg] == env->eip) || ! 1366: ((type & 1) && env->cpu_watchpoint[reg] && ! 1367: (env->cpu_watchpoint[reg]->flags & BP_WATCHPOINT_HIT))) { ! 1368: dr6 |= 1 << reg; ! 1369: if (hw_breakpoint_enabled(env->dr[7], reg)) ! 1370: hit_enabled = 1; 1.1.1.6 root 1371: } 1372: } 1.1.1.7 ! root 1373: if (hit_enabled || force_dr6_update) ! 1374: env->dr[6] = dr6; ! 1375: return hit_enabled; 1.1.1.6 root 1376: } 1377: 1.1.1.7 ! root 1378: static CPUDebugExcpHandler *prev_debug_excp_handler; 1.1.1.6 root 1379: 1.1.1.7 ! root 1380: void raise_exception(int exception_index); 1.1.1.6 root 1381: 1.1.1.7 ! root 1382: static void breakpoint_handler(CPUState *env) 1.1.1.6 root 1383: { 1.1.1.7 ! root 1384: CPUBreakpoint *bp; 1.1.1.6 root 1385: 1.1.1.7 ! root 1386: if (env->watchpoint_hit) { ! 1387: if (env->watchpoint_hit->flags & BP_CPU) { ! 1388: env->watchpoint_hit = NULL; ! 1389: if (check_hw_breakpoints(env, 0)) ! 1390: raise_exception(EXCP01_DB); ! 1391: else ! 1392: cpu_resume_from_signal(env, NULL); ! 1393: } ! 1394: } else { ! 1395: TAILQ_FOREACH(bp, &env->breakpoints, entry) ! 1396: if (bp->pc == env->eip) { ! 1397: if (bp->flags & BP_CPU) { ! 1398: check_hw_breakpoints(env, 1); ! 1399: raise_exception(EXCP01_DB); ! 1400: } ! 1401: break; ! 1402: } ! 1403: } ! 1404: if (prev_debug_excp_handler) ! 1405: prev_debug_excp_handler(env); 1.1.1.6 root 1406: } 1.1.1.7 ! root 1407: #endif /* !CONFIG_USER_ONLY */ 1.1.1.6 root 1408: 1.1.1.7 ! root 1409: static void host_cpuid(uint32_t function, uint32_t count, ! 1410: uint32_t *eax, uint32_t *ebx, ! 1411: uint32_t *ecx, uint32_t *edx) ! 1412: { ! 1413: #if defined(CONFIG_KVM) ! 1414: uint32_t vec[4]; ! 1415: ! 1416: #ifdef __x86_64__ ! 1417: asm volatile("cpuid" ! 1418: : "=a"(vec[0]), "=b"(vec[1]), ! 1419: "=c"(vec[2]), "=d"(vec[3]) ! 1420: : "0"(function), "c"(count) : "cc"); ! 1421: #else ! 1422: asm volatile("pusha \n\t" ! 1423: "cpuid \n\t" ! 1424: "mov %%eax, 0(%1) \n\t" ! 1425: "mov %%ebx, 4(%1) \n\t" ! 1426: "mov %%ecx, 8(%1) \n\t" ! 1427: "mov %%edx, 12(%1) \n\t" ! 1428: "popa" ! 1429: : : "a"(function), "c"(count), "S"(vec) ! 1430: : "memory", "cc"); ! 1431: #endif ! 1432: ! 1433: if (eax) ! 1434: *eax = vec[0]; ! 1435: if (ebx) ! 1436: *ebx = vec[1]; ! 1437: if (ecx) ! 1438: *ecx = vec[2]; ! 1439: if (edx) ! 1440: *edx = vec[3]; ! 1441: #endif 1.1.1.6 root 1442: } 1443: 1.1.1.7 ! root 1444: void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, ! 1445: uint32_t *eax, uint32_t *ebx, ! 1446: uint32_t *ecx, uint32_t *edx) 1.1.1.6 root 1447: { 1.1.1.7 ! root 1448: /* test if maximum index reached */ ! 1449: if (index & 0x80000000) { ! 1450: if (index > env->cpuid_xlevel) ! 1451: index = env->cpuid_level; ! 1452: } else { ! 1453: if (index > env->cpuid_level) ! 1454: index = env->cpuid_level; ! 1455: } 1.1.1.6 root 1456: 1.1.1.7 ! root 1457: switch(index) { ! 1458: case 0: ! 1459: *eax = env->cpuid_level; ! 1460: *ebx = env->cpuid_vendor1; ! 1461: *edx = env->cpuid_vendor2; ! 1462: *ecx = env->cpuid_vendor3; ! 1463: ! 1464: /* sysenter isn't supported on compatibility mode on AMD. and syscall ! 1465: * isn't supported in compatibility mode on Intel. so advertise the ! 1466: * actuall cpu, and say goodbye to migration between different vendors ! 1467: * is you use compatibility mode. */ ! 1468: if (kvm_enabled()) ! 1469: host_cpuid(0, 0, NULL, ebx, ecx, edx); 1.1.1.6 root 1470: break; 1.1.1.7 ! root 1471: case 1: ! 1472: *eax = env->cpuid_version; ! 1473: *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */ ! 1474: *ecx = env->cpuid_ext_features; ! 1475: *edx = env->cpuid_features; ! 1476: ! 1477: /* "Hypervisor present" bit required for Microsoft SVVP */ ! 1478: if (kvm_enabled()) ! 1479: *ecx |= (1 << 31); 1.1.1.6 root 1480: break; 1.1.1.7 ! root 1481: case 2: ! 1482: /* cache info: needed for Pentium Pro compatibility */ ! 1483: *eax = 1; ! 1484: *ebx = 0; ! 1485: *ecx = 0; ! 1486: *edx = 0x2c307d; 1.1.1.6 root 1487: break; 1.1.1.7 ! root 1488: case 4: ! 1489: /* cache info: needed for Core compatibility */ ! 1490: switch (count) { ! 1491: case 0: /* L1 dcache info */ ! 1492: *eax = 0x0000121; ! 1493: *ebx = 0x1c0003f; ! 1494: *ecx = 0x000003f; ! 1495: *edx = 0x0000001; ! 1496: break; ! 1497: case 1: /* L1 icache info */ ! 1498: *eax = 0x0000122; ! 1499: *ebx = 0x1c0003f; ! 1500: *ecx = 0x000003f; ! 1501: *edx = 0x0000001; ! 1502: break; ! 1503: case 2: /* L2 cache info */ ! 1504: *eax = 0x0000143; ! 1505: *ebx = 0x3c0003f; ! 1506: *ecx = 0x0000fff; ! 1507: *edx = 0x0000001; ! 1508: break; ! 1509: default: /* end of info */ ! 1510: *eax = 0; ! 1511: *ebx = 0; ! 1512: *ecx = 0; ! 1513: *edx = 0; ! 1514: break; 1.1.1.6 root 1515: } 1516: break; 1.1.1.7 ! root 1517: case 5: ! 1518: /* mwait info: needed for Core compatibility */ ! 1519: *eax = 0; /* Smallest monitor-line size in bytes */ ! 1520: *ebx = 0; /* Largest monitor-line size in bytes */ ! 1521: *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; ! 1522: *edx = 0; ! 1523: break; ! 1524: case 6: ! 1525: /* Thermal and Power Leaf */ ! 1526: *eax = 0; ! 1527: *ebx = 0; ! 1528: *ecx = 0; ! 1529: *edx = 0; ! 1530: break; ! 1531: case 9: ! 1532: /* Direct Cache Access Information Leaf */ ! 1533: *eax = 0; /* Bits 0-31 in DCA_CAP MSR */ ! 1534: *ebx = 0; ! 1535: *ecx = 0; ! 1536: *edx = 0; ! 1537: break; ! 1538: case 0xA: ! 1539: /* Architectural Performance Monitoring Leaf */ ! 1540: *eax = 0; ! 1541: *ebx = 0; ! 1542: *ecx = 0; ! 1543: *edx = 0; ! 1544: break; ! 1545: case 0x80000000: ! 1546: *eax = env->cpuid_xlevel; ! 1547: *ebx = env->cpuid_vendor1; ! 1548: *edx = env->cpuid_vendor2; ! 1549: *ecx = env->cpuid_vendor3; 1.1.1.6 root 1550: break; 1.1.1.7 ! root 1551: case 0x80000001: ! 1552: *eax = env->cpuid_features; ! 1553: *ebx = 0; ! 1554: *ecx = env->cpuid_ext3_features; ! 1555: *edx = env->cpuid_ext2_features; ! 1556: ! 1557: if (kvm_enabled()) { ! 1558: uint32_t h_eax, h_edx; ! 1559: ! 1560: host_cpuid(index, 0, &h_eax, NULL, NULL, &h_edx); ! 1561: ! 1562: /* disable CPU features that the host does not support */ ! 1563: ! 1564: /* long mode */ ! 1565: if ((h_edx & 0x20000000) == 0 /* || !lm_capable_kernel */) ! 1566: *edx &= ~0x20000000; ! 1567: /* syscall */ ! 1568: if ((h_edx & 0x00000800) == 0) ! 1569: *edx &= ~0x00000800; ! 1570: /* nx */ ! 1571: if ((h_edx & 0x00100000) == 0) ! 1572: *edx &= ~0x00100000; ! 1573: ! 1574: /* disable CPU features that KVM cannot support */ ! 1575: ! 1576: /* svm */ ! 1577: *ecx &= ~4UL; ! 1578: /* 3dnow */ ! 1579: *edx &= ~0xc0000000; 1.1.1.6 root 1580: } 1581: break; 1.1.1.7 ! root 1582: case 0x80000002: ! 1583: case 0x80000003: ! 1584: case 0x80000004: ! 1585: *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0]; ! 1586: *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1]; ! 1587: *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2]; ! 1588: *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3]; ! 1589: break; ! 1590: case 0x80000005: ! 1591: /* cache info (L1 cache) */ ! 1592: *eax = 0x01ff01ff; ! 1593: *ebx = 0x01ff01ff; ! 1594: *ecx = 0x40020140; ! 1595: *edx = 0x40020140; ! 1596: break; ! 1597: case 0x80000006: ! 1598: /* cache info (L2 cache) */ ! 1599: *eax = 0; ! 1600: *ebx = 0x42004200; ! 1601: *ecx = 0x02008140; ! 1602: *edx = 0; ! 1603: break; ! 1604: case 0x80000008: ! 1605: /* virtual & phys address size in low 2 bytes. */ ! 1606: /* XXX: This value must match the one used in the MMU code. */ ! 1607: if (env->cpuid_ext2_features & CPUID_EXT2_LM) { ! 1608: /* 64 bit processor */ ! 1609: #if defined(USE_KQEMU) ! 1610: *eax = 0x00003020; /* 48 bits virtual, 32 bits physical */ ! 1611: #else ! 1612: /* XXX: The physical address space is limited to 42 bits in exec.c. */ ! 1613: *eax = 0x00003028; /* 48 bits virtual, 40 bits physical */ ! 1614: #endif ! 1615: } else { ! 1616: #if defined(USE_KQEMU) ! 1617: *eax = 0x00000020; /* 32 bits physical */ ! 1618: #else ! 1619: if (env->cpuid_features & CPUID_PSE36) ! 1620: *eax = 0x00000024; /* 36 bits physical */ ! 1621: else ! 1622: *eax = 0x00000020; /* 32 bits physical */ ! 1623: #endif 1.1.1.6 root 1624: } 1.1.1.7 ! root 1625: *ebx = 0; ! 1626: *ecx = 0; ! 1627: *edx = 0; ! 1628: break; ! 1629: case 0x8000000A: ! 1630: *eax = 0x00000001; /* SVM Revision */ ! 1631: *ebx = 0x00000010; /* nr of ASIDs */ ! 1632: *ecx = 0; ! 1633: *edx = 0; /* optional features */ 1.1.1.6 root 1634: break; 1635: default: 1.1.1.7 ! root 1636: /* reserved values: zero */ ! 1637: *eax = 0; ! 1638: *ebx = 0; ! 1639: *ecx = 0; ! 1640: *edx = 0; 1.1.1.6 root 1641: break; 1642: } 1643: } 1644: 1.1.1.7 ! root 1645: CPUX86State *cpu_x86_init(const char *cpu_model) 1.1.1.6 root 1646: { 1.1.1.7 ! root 1647: CPUX86State *env; ! 1648: static int inited; 1.1.1.6 root 1649: 1.1.1.7 ! root 1650: env = qemu_mallocz(sizeof(CPUX86State)); ! 1651: cpu_exec_init(env); ! 1652: env->cpu_model_str = cpu_model; 1.1.1.6 root 1653: 1.1.1.7 ! root 1654: /* init various static tables */ ! 1655: if (!inited) { ! 1656: inited = 1; ! 1657: optimize_flags_init(); ! 1658: #ifndef CONFIG_USER_ONLY ! 1659: prev_debug_excp_handler = ! 1660: cpu_set_debug_excp_handler(breakpoint_handler); ! 1661: #endif 1.1.1.6 root 1662: } 1.1.1.7 ! root 1663: if (cpu_x86_register(env, cpu_model) < 0) { ! 1664: cpu_x86_close(env); ! 1665: return NULL; ! 1666: } ! 1667: cpu_reset(env); ! 1668: #ifdef USE_KQEMU ! 1669: kqemu_init(env); 1.1.1.6 root 1670: #endif 1.1.1.7 ! root 1671: if (kvm_enabled()) ! 1672: kvm_init_vcpu(env); ! 1673: return env; 1.1.1.6 root 1674: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.