|
|
1.1 ! root 1: /* ! 2: * i386 CPUID helper functions ! 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, see <http://www.gnu.org/licenses/>. ! 18: */ ! 19: #include <stdlib.h> ! 20: #include <stdio.h> ! 21: #include <string.h> ! 22: #include <inttypes.h> ! 23: ! 24: #include "cpu.h" ! 25: #include "kvm.h" ! 26: ! 27: #include "qemu-option.h" ! 28: #include "qemu-config.h" ! 29: ! 30: /* feature flags taken from "Intel Processor Identification and the CPUID ! 31: * Instruction" and AMD's "CPUID Specification". In cases of disagreement ! 32: * between feature naming conventions, aliases may be added. ! 33: */ ! 34: static const char *feature_name[] = { ! 35: "fpu", "vme", "de", "pse", ! 36: "tsc", "msr", "pae", "mce", ! 37: "cx8", "apic", NULL, "sep", ! 38: "mtrr", "pge", "mca", "cmov", ! 39: "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, ! 40: NULL, "ds" /* Intel dts */, "acpi", "mmx", ! 41: "fxsr", "sse", "sse2", "ss", ! 42: "ht" /* Intel htt */, "tm", "ia64", "pbe", ! 43: }; ! 44: static const char *ext_feature_name[] = { ! 45: "pni|sse3" /* Intel,AMD sse3 */, "pclmuldq", "dtes64", "monitor", ! 46: "ds_cpl", "vmx", "smx", "est", ! 47: "tm2", "ssse3", "cid", NULL, ! 48: "fma", "cx16", "xtpr", "pdcm", ! 49: NULL, NULL, "dca", "sse4.1|sse4_1", ! 50: "sse4.2|sse4_2", "x2apic", "movbe", "popcnt", ! 51: NULL, "aes", "xsave", "osxsave", ! 52: "avx", NULL, NULL, "hypervisor", ! 53: }; ! 54: static const char *ext2_feature_name[] = { ! 55: "fpu", "vme", "de", "pse", ! 56: "tsc", "msr", "pae", "mce", ! 57: "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", ! 58: "mtrr", "pge", "mca", "cmov", ! 59: "pat", "pse36", NULL, NULL /* Linux mp */, ! 60: "nx" /* Intel xd */, NULL, "mmxext", "mmx", ! 61: "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", ! 62: NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow", ! 63: }; ! 64: static const char *ext3_feature_name[] = { ! 65: "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, ! 66: "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse", ! 67: "3dnowprefetch", "osvw", "ibs", "xop", ! 68: "skinit", "wdt", NULL, NULL, ! 69: "fma4", NULL, "cvt16", "nodeid_msr", ! 70: NULL, NULL, NULL, NULL, ! 71: NULL, NULL, NULL, NULL, ! 72: NULL, NULL, NULL, NULL, ! 73: }; ! 74: ! 75: static const char *kvm_feature_name[] = { ! 76: "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, NULL, NULL, NULL, NULL, ! 77: NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ! 78: NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ! 79: NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ! 80: }; ! 81: ! 82: /* collects per-function cpuid data ! 83: */ ! 84: typedef struct model_features_t { ! 85: uint32_t *guest_feat; ! 86: uint32_t *host_feat; ! 87: uint32_t check_feat; ! 88: const char **flag_names; ! 89: uint32_t cpuid; ! 90: } model_features_t; ! 91: ! 92: int check_cpuid = 0; ! 93: int enforce_cpuid = 0; ! 94: ! 95: static void host_cpuid(uint32_t function, uint32_t count, ! 96: uint32_t *eax, uint32_t *ebx, ! 97: uint32_t *ecx, uint32_t *edx) ! 98: { ! 99: #if defined(CONFIG_KVM) ! 100: uint32_t vec[4]; ! 101: ! 102: #ifdef __x86_64__ ! 103: asm volatile("cpuid" ! 104: : "=a"(vec[0]), "=b"(vec[1]), ! 105: "=c"(vec[2]), "=d"(vec[3]) ! 106: : "0"(function), "c"(count) : "cc"); ! 107: #else ! 108: asm volatile("pusha \n\t" ! 109: "cpuid \n\t" ! 110: "mov %%eax, 0(%2) \n\t" ! 111: "mov %%ebx, 4(%2) \n\t" ! 112: "mov %%ecx, 8(%2) \n\t" ! 113: "mov %%edx, 12(%2) \n\t" ! 114: "popa" ! 115: : : "a"(function), "c"(count), "S"(vec) ! 116: : "memory", "cc"); ! 117: #endif ! 118: ! 119: if (eax) ! 120: *eax = vec[0]; ! 121: if (ebx) ! 122: *ebx = vec[1]; ! 123: if (ecx) ! 124: *ecx = vec[2]; ! 125: if (edx) ! 126: *edx = vec[3]; ! 127: #endif ! 128: } ! 129: ! 130: #define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c))) ! 131: ! 132: /* general substring compare of *[s1..e1) and *[s2..e2). sx is start of ! 133: * a substring. ex if !NULL points to the first char after a substring, ! 134: * otherwise the string is assumed to sized by a terminating nul. ! 135: * Return lexical ordering of *s1:*s2. ! 136: */ ! 137: static int sstrcmp(const char *s1, const char *e1, const char *s2, ! 138: const char *e2) ! 139: { ! 140: for (;;) { ! 141: if (!*s1 || !*s2 || *s1 != *s2) ! 142: return (*s1 - *s2); ! 143: ++s1, ++s2; ! 144: if (s1 == e1 && s2 == e2) ! 145: return (0); ! 146: else if (s1 == e1) ! 147: return (*s2); ! 148: else if (s2 == e2) ! 149: return (*s1); ! 150: } ! 151: } ! 152: ! 153: /* compare *[s..e) to *altstr. *altstr may be a simple string or multiple ! 154: * '|' delimited (possibly empty) strings in which case search for a match ! 155: * within the alternatives proceeds left to right. Return 0 for success, ! 156: * non-zero otherwise. ! 157: */ ! 158: static int altcmp(const char *s, const char *e, const char *altstr) ! 159: { ! 160: const char *p, *q; ! 161: ! 162: for (q = p = altstr; ; ) { ! 163: while (*p && *p != '|') ! 164: ++p; ! 165: if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p))) ! 166: return (0); ! 167: if (!*p) ! 168: return (1); ! 169: else ! 170: q = ++p; ! 171: } ! 172: } ! 173: ! 174: /* search featureset for flag *[s..e), if found set corresponding bit in ! 175: * *pval and return success, otherwise return zero ! 176: */ ! 177: static int lookup_feature(uint32_t *pval, const char *s, const char *e, ! 178: const char **featureset) ! 179: { ! 180: uint32_t mask; ! 181: const char **ppc; ! 182: ! 183: for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc) ! 184: if (*ppc && !altcmp(s, e, *ppc)) { ! 185: *pval |= mask; ! 186: break; ! 187: } ! 188: return (mask ? 1 : 0); ! 189: } ! 190: ! 191: static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features, ! 192: uint32_t *ext_features, ! 193: uint32_t *ext2_features, ! 194: uint32_t *ext3_features, ! 195: uint32_t *kvm_features) ! 196: { ! 197: if (!lookup_feature(features, flagname, NULL, feature_name) && ! 198: !lookup_feature(ext_features, flagname, NULL, ext_feature_name) && ! 199: !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) && ! 200: !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) && ! 201: !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name)) ! 202: fprintf(stderr, "CPU feature %s not found\n", flagname); ! 203: } ! 204: ! 205: typedef struct x86_def_t { ! 206: struct x86_def_t *next; ! 207: const char *name; ! 208: uint32_t level; ! 209: uint32_t vendor1, vendor2, vendor3; ! 210: int family; ! 211: int model; ! 212: int stepping; ! 213: uint32_t features, ext_features, ext2_features, ext3_features, kvm_features; ! 214: uint32_t xlevel; ! 215: char model_id[48]; ! 216: int vendor_override; ! 217: uint32_t flags; ! 218: } x86_def_t; ! 219: ! 220: #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) ! 221: #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \ ! 222: CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC) ! 223: #define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \ ! 224: CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \ ! 225: CPUID_PSE36 | CPUID_FXSR) ! 226: #define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE) ! 227: #define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \ ! 228: CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \ ! 229: CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \ ! 230: CPUID_PAE | CPUID_SEP | CPUID_APIC) ! 231: #define EXT2_FEATURE_MASK 0x0183F3FF ! 232: ! 233: #define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \ ! 234: CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \ ! 235: CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \ ! 236: CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \ ! 237: CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS) ! 238: /* partly implemented: ! 239: CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64) ! 240: CPUID_PSE36 (needed for Solaris) */ ! 241: /* missing: ! 242: CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */ ! 243: #define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \ ! 244: CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \ ! 245: CPUID_EXT_HYPERVISOR) ! 246: /* missing: ! 247: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST, ! 248: CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */ ! 249: #define TCG_EXT2_FEATURES ((TCG_FEATURES & EXT2_FEATURE_MASK) | \ ! 250: CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \ ! 251: CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT) ! 252: /* missing: ! 253: CPUID_EXT2_PDPE1GB */ ! 254: #define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \ ! 255: CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A) ! 256: ! 257: /* maintains list of cpu model definitions ! 258: */ ! 259: static x86_def_t *x86_defs = {NULL}; ! 260: ! 261: /* built-in cpu model definitions (deprecated) ! 262: */ ! 263: static x86_def_t builtin_x86_defs[] = { ! 264: { ! 265: .name = "qemu64", ! 266: .level = 4, ! 267: .vendor1 = CPUID_VENDOR_AMD_1, ! 268: .vendor2 = CPUID_VENDOR_AMD_2, ! 269: .vendor3 = CPUID_VENDOR_AMD_3, ! 270: .family = 6, ! 271: .model = 2, ! 272: .stepping = 3, ! 273: .features = PPRO_FEATURES | ! 274: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | ! 275: CPUID_PSE36, ! 276: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT, ! 277: .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | ! 278: CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, ! 279: .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | ! 280: CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, ! 281: .xlevel = 0x8000000A, ! 282: .model_id = "QEMU Virtual CPU version " QEMU_VERSION, ! 283: }, ! 284: { ! 285: .name = "phenom", ! 286: .level = 5, ! 287: .vendor1 = CPUID_VENDOR_AMD_1, ! 288: .vendor2 = CPUID_VENDOR_AMD_2, ! 289: .vendor3 = CPUID_VENDOR_AMD_3, ! 290: .family = 16, ! 291: .model = 2, ! 292: .stepping = 3, ! 293: .features = PPRO_FEATURES | ! 294: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | ! 295: CPUID_PSE36 | CPUID_VME | CPUID_HT, ! 296: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 | ! 297: CPUID_EXT_POPCNT, ! 298: .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | ! 299: CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | ! 300: CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT | ! 301: CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP, ! 302: /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, ! 303: CPUID_EXT3_CR8LEG, ! 304: CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, ! 305: CPUID_EXT3_OSVW, CPUID_EXT3_IBS */ ! 306: .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | ! 307: CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, ! 308: .xlevel = 0x8000001A, ! 309: .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor" ! 310: }, ! 311: { ! 312: .name = "core2duo", ! 313: .level = 10, ! 314: .family = 6, ! 315: .model = 15, ! 316: .stepping = 11, ! 317: .features = PPRO_FEATURES | ! 318: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | ! 319: CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS | ! 320: CPUID_HT | CPUID_TM | CPUID_PBE, ! 321: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | ! 322: CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST | ! 323: CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM, ! 324: .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, ! 325: .ext3_features = CPUID_EXT3_LAHF_LM, ! 326: .xlevel = 0x80000008, ! 327: .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", ! 328: }, ! 329: { ! 330: .name = "kvm64", ! 331: .level = 5, ! 332: .vendor1 = CPUID_VENDOR_INTEL_1, ! 333: .vendor2 = CPUID_VENDOR_INTEL_2, ! 334: .vendor3 = CPUID_VENDOR_INTEL_3, ! 335: .family = 15, ! 336: .model = 6, ! 337: .stepping = 1, ! 338: /* Missing: CPUID_VME, CPUID_HT */ ! 339: .features = PPRO_FEATURES | ! 340: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | ! 341: CPUID_PSE36, ! 342: /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */ ! 343: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16, ! 344: /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */ ! 345: .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | ! 346: CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, ! 347: /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC, ! 348: CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A, ! 349: CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH, ! 350: CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */ ! 351: .ext3_features = 0, ! 352: .xlevel = 0x80000008, ! 353: .model_id = "Common KVM processor" ! 354: }, ! 355: { ! 356: .name = "qemu32", ! 357: .level = 4, ! 358: .family = 6, ! 359: .model = 3, ! 360: .stepping = 3, ! 361: .features = PPRO_FEATURES, ! 362: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT, ! 363: .xlevel = 0x80000004, ! 364: .model_id = "QEMU Virtual CPU version " QEMU_VERSION, ! 365: }, ! 366: { ! 367: .name = "kvm32", ! 368: .level = 5, ! 369: .family = 15, ! 370: .model = 6, ! 371: .stepping = 1, ! 372: .features = PPRO_FEATURES | ! 373: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, ! 374: .ext_features = CPUID_EXT_SSE3, ! 375: .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK, ! 376: .ext3_features = 0, ! 377: .xlevel = 0x80000008, ! 378: .model_id = "Common 32-bit KVM processor" ! 379: }, ! 380: { ! 381: .name = "coreduo", ! 382: .level = 10, ! 383: .family = 6, ! 384: .model = 14, ! 385: .stepping = 8, ! 386: .features = PPRO_FEATURES | CPUID_VME | ! 387: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI | ! 388: CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE, ! 389: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX | ! 390: CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM, ! 391: .ext2_features = CPUID_EXT2_NX, ! 392: .xlevel = 0x80000008, ! 393: .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", ! 394: }, ! 395: { ! 396: .name = "486", ! 397: .level = 1, ! 398: .family = 4, ! 399: .model = 0, ! 400: .stepping = 0, ! 401: .features = I486_FEATURES, ! 402: .xlevel = 0, ! 403: }, ! 404: { ! 405: .name = "pentium", ! 406: .level = 1, ! 407: .family = 5, ! 408: .model = 4, ! 409: .stepping = 3, ! 410: .features = PENTIUM_FEATURES, ! 411: .xlevel = 0, ! 412: }, ! 413: { ! 414: .name = "pentium2", ! 415: .level = 2, ! 416: .family = 6, ! 417: .model = 5, ! 418: .stepping = 2, ! 419: .features = PENTIUM2_FEATURES, ! 420: .xlevel = 0, ! 421: }, ! 422: { ! 423: .name = "pentium3", ! 424: .level = 2, ! 425: .family = 6, ! 426: .model = 7, ! 427: .stepping = 3, ! 428: .features = PENTIUM3_FEATURES, ! 429: .xlevel = 0, ! 430: }, ! 431: { ! 432: .name = "athlon", ! 433: .level = 2, ! 434: .vendor1 = CPUID_VENDOR_AMD_1, ! 435: .vendor2 = CPUID_VENDOR_AMD_2, ! 436: .vendor3 = CPUID_VENDOR_AMD_3, ! 437: .family = 6, ! 438: .model = 2, ! 439: .stepping = 3, ! 440: .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA, ! 441: .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, ! 442: .xlevel = 0x80000008, ! 443: /* XXX: put another string ? */ ! 444: .model_id = "QEMU Virtual CPU version " QEMU_VERSION, ! 445: }, ! 446: { ! 447: .name = "n270", ! 448: /* original is on level 10 */ ! 449: .level = 5, ! 450: .family = 6, ! 451: .model = 28, ! 452: .stepping = 2, ! 453: .features = PPRO_FEATURES | ! 454: CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS | ! 455: CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE, ! 456: /* Some CPUs got no CPUID_SEP */ ! 457: .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | ! 458: CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR, ! 459: .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_NX, ! 460: .ext3_features = CPUID_EXT3_LAHF_LM, ! 461: .xlevel = 0x8000000A, ! 462: .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", ! 463: }, ! 464: }; ! 465: ! 466: static int cpu_x86_fill_model_id(char *str) ! 467: { ! 468: uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; ! 469: int i; ! 470: ! 471: for (i = 0; i < 3; i++) { ! 472: host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx); ! 473: memcpy(str + i * 16 + 0, &eax, 4); ! 474: memcpy(str + i * 16 + 4, &ebx, 4); ! 475: memcpy(str + i * 16 + 8, &ecx, 4); ! 476: memcpy(str + i * 16 + 12, &edx, 4); ! 477: } ! 478: return 0; ! 479: } ! 480: ! 481: static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) ! 482: { ! 483: uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; ! 484: ! 485: x86_cpu_def->name = "host"; ! 486: host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); ! 487: x86_cpu_def->level = eax; ! 488: x86_cpu_def->vendor1 = ebx; ! 489: x86_cpu_def->vendor2 = edx; ! 490: x86_cpu_def->vendor3 = ecx; ! 491: ! 492: host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); ! 493: x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); ! 494: x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12); ! 495: x86_cpu_def->stepping = eax & 0x0F; ! 496: x86_cpu_def->ext_features = ecx; ! 497: x86_cpu_def->features = edx; ! 498: ! 499: host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx); ! 500: x86_cpu_def->xlevel = eax; ! 501: ! 502: host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx); ! 503: x86_cpu_def->ext2_features = edx; ! 504: x86_cpu_def->ext3_features = ecx; ! 505: cpu_x86_fill_model_id(x86_cpu_def->model_id); ! 506: x86_cpu_def->vendor_override = 0; ! 507: ! 508: return 0; ! 509: } ! 510: ! 511: static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) ! 512: { ! 513: int i; ! 514: ! 515: for (i = 0; i < 32; ++i) ! 516: if (1 << i & mask) { ! 517: fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested" ! 518: " flag '%s' [0x%08x]\n", ! 519: f->cpuid >> 16, f->cpuid & 0xffff, ! 520: f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask); ! 521: break; ! 522: } ! 523: return 0; ! 524: } ! 525: ! 526: /* best effort attempt to inform user requested cpu flags aren't making ! 527: * their way to the guest. Note: ft[].check_feat ideally should be ! 528: * specified via a guest_def field to suppress report of extraneous flags. ! 529: */ ! 530: static int check_features_against_host(x86_def_t *guest_def) ! 531: { ! 532: x86_def_t host_def; ! 533: uint32_t mask; ! 534: int rv, i; ! 535: struct model_features_t ft[] = { ! 536: {&guest_def->features, &host_def.features, ! 537: ~0, feature_name, 0x00000000}, ! 538: {&guest_def->ext_features, &host_def.ext_features, ! 539: ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001}, ! 540: {&guest_def->ext2_features, &host_def.ext2_features, ! 541: ~PPRO_FEATURES, ext2_feature_name, 0x80000000}, ! 542: {&guest_def->ext3_features, &host_def.ext3_features, ! 543: ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}}; ! 544: ! 545: cpu_x86_fill_host(&host_def); ! 546: for (rv = 0, i = 0; i < sizeof (ft) / sizeof (ft[0]); ++i) ! 547: for (mask = 1; mask; mask <<= 1) ! 548: if (ft[i].check_feat & mask && *ft[i].guest_feat & mask && ! 549: !(*ft[i].host_feat & mask)) { ! 550: unavailable_host_feature(&ft[i], mask); ! 551: rv = 1; ! 552: } ! 553: return rv; ! 554: } ! 555: ! 556: static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) ! 557: { ! 558: unsigned int i; ! 559: x86_def_t *def; ! 560: ! 561: char *s = strdup(cpu_model); ! 562: char *featurestr, *name = strtok(s, ","); ! 563: uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0, plus_kvm_features = 0; ! 564: uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0, minus_kvm_features = 0; ! 565: uint32_t numvalue; ! 566: ! 567: for (def = x86_defs; def; def = def->next) ! 568: if (!strcmp(name, def->name)) ! 569: break; ! 570: if (kvm_enabled() && strcmp(name, "host") == 0) { ! 571: cpu_x86_fill_host(x86_cpu_def); ! 572: } else if (!def) { ! 573: goto error; ! 574: } else { ! 575: memcpy(x86_cpu_def, def, sizeof(*def)); ! 576: } ! 577: ! 578: plus_kvm_features = ~0; /* not supported bits will be filtered out later */ ! 579: ! 580: add_flagname_to_bitmaps("hypervisor", &plus_features, ! 581: &plus_ext_features, &plus_ext2_features, &plus_ext3_features, ! 582: &plus_kvm_features); ! 583: ! 584: featurestr = strtok(NULL, ","); ! 585: ! 586: while (featurestr) { ! 587: char *val; ! 588: if (featurestr[0] == '+') { ! 589: add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, &plus_kvm_features); ! 590: } else if (featurestr[0] == '-') { ! 591: add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features, &minus_kvm_features); ! 592: } else if ((val = strchr(featurestr, '='))) { ! 593: *val = 0; val++; ! 594: if (!strcmp(featurestr, "family")) { ! 595: char *err; ! 596: numvalue = strtoul(val, &err, 0); ! 597: if (!*val || *err) { ! 598: fprintf(stderr, "bad numerical value %s\n", val); ! 599: goto error; ! 600: } ! 601: x86_cpu_def->family = numvalue; ! 602: } else if (!strcmp(featurestr, "model")) { ! 603: char *err; ! 604: numvalue = strtoul(val, &err, 0); ! 605: if (!*val || *err || numvalue > 0xff) { ! 606: fprintf(stderr, "bad numerical value %s\n", val); ! 607: goto error; ! 608: } ! 609: x86_cpu_def->model = numvalue; ! 610: } else if (!strcmp(featurestr, "stepping")) { ! 611: char *err; ! 612: numvalue = strtoul(val, &err, 0); ! 613: if (!*val || *err || numvalue > 0xf) { ! 614: fprintf(stderr, "bad numerical value %s\n", val); ! 615: goto error; ! 616: } ! 617: x86_cpu_def->stepping = numvalue ; ! 618: } else if (!strcmp(featurestr, "level")) { ! 619: char *err; ! 620: numvalue = strtoul(val, &err, 0); ! 621: if (!*val || *err) { ! 622: fprintf(stderr, "bad numerical value %s\n", val); ! 623: goto error; ! 624: } ! 625: x86_cpu_def->level = numvalue; ! 626: } else if (!strcmp(featurestr, "xlevel")) { ! 627: char *err; ! 628: numvalue = strtoul(val, &err, 0); ! 629: if (!*val || *err) { ! 630: fprintf(stderr, "bad numerical value %s\n", val); ! 631: goto error; ! 632: } ! 633: if (numvalue < 0x80000000) { ! 634: numvalue += 0x80000000; ! 635: } ! 636: x86_cpu_def->xlevel = numvalue; ! 637: } else if (!strcmp(featurestr, "vendor")) { ! 638: if (strlen(val) != 12) { ! 639: fprintf(stderr, "vendor string must be 12 chars long\n"); ! 640: goto error; ! 641: } ! 642: x86_cpu_def->vendor1 = 0; ! 643: x86_cpu_def->vendor2 = 0; ! 644: x86_cpu_def->vendor3 = 0; ! 645: for(i = 0; i < 4; i++) { ! 646: x86_cpu_def->vendor1 |= ((uint8_t)val[i ]) << (8 * i); ! 647: x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i); ! 648: x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i); ! 649: } ! 650: x86_cpu_def->vendor_override = 1; ! 651: } else if (!strcmp(featurestr, "model_id")) { ! 652: pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), ! 653: val); ! 654: } else { ! 655: fprintf(stderr, "unrecognized feature %s\n", featurestr); ! 656: goto error; ! 657: } ! 658: } else if (!strcmp(featurestr, "check")) { ! 659: check_cpuid = 1; ! 660: } else if (!strcmp(featurestr, "enforce")) { ! 661: check_cpuid = enforce_cpuid = 1; ! 662: } else { ! 663: fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr); ! 664: goto error; ! 665: } ! 666: featurestr = strtok(NULL, ","); ! 667: } ! 668: x86_cpu_def->features |= plus_features; ! 669: x86_cpu_def->ext_features |= plus_ext_features; ! 670: x86_cpu_def->ext2_features |= plus_ext2_features; ! 671: x86_cpu_def->ext3_features |= plus_ext3_features; ! 672: x86_cpu_def->kvm_features |= plus_kvm_features; ! 673: x86_cpu_def->features &= ~minus_features; ! 674: x86_cpu_def->ext_features &= ~minus_ext_features; ! 675: x86_cpu_def->ext2_features &= ~minus_ext2_features; ! 676: x86_cpu_def->ext3_features &= ~minus_ext3_features; ! 677: x86_cpu_def->kvm_features &= ~minus_kvm_features; ! 678: if (check_cpuid) { ! 679: if (check_features_against_host(x86_cpu_def) && enforce_cpuid) ! 680: goto error; ! 681: } ! 682: free(s); ! 683: return 0; ! 684: ! 685: error: ! 686: free(s); ! 687: return -1; ! 688: } ! 689: ! 690: /* generate a composite string into buf of all cpuid names in featureset ! 691: * selected by fbits. indicate truncation at bufsize in the event of overflow. ! 692: * if flags, suppress names undefined in featureset. ! 693: */ ! 694: static void listflags(char *buf, int bufsize, uint32_t fbits, ! 695: const char **featureset, uint32_t flags) ! 696: { ! 697: const char **p = &featureset[31]; ! 698: char *q, *b, bit; ! 699: int nc; ! 700: ! 701: b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL; ! 702: *buf = '\0'; ! 703: for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit) ! 704: if (fbits & 1 << bit && (*p || !flags)) { ! 705: if (*p) ! 706: nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p); ! 707: else ! 708: nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit); ! 709: if (bufsize <= nc) { ! 710: if (b) { ! 711: memcpy(b, "...", sizeof("...")); ! 712: } ! 713: return; ! 714: } ! 715: q += nc; ! 716: bufsize -= nc; ! 717: } ! 718: } ! 719: ! 720: /* generate CPU information: ! 721: * -? list model names ! 722: * -?model list model names/IDs ! 723: * -?dump output all model (x86_def_t) data ! 724: * -?cpuid list all recognized cpuid flag names ! 725: */ ! 726: void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...), ! 727: const char *optarg) ! 728: { ! 729: unsigned char model = !strcmp("?model", optarg); ! 730: unsigned char dump = !strcmp("?dump", optarg); ! 731: unsigned char cpuid = !strcmp("?cpuid", optarg); ! 732: x86_def_t *def; ! 733: char buf[256]; ! 734: ! 735: if (cpuid) { ! 736: (*cpu_fprintf)(f, "Recognized CPUID flags:\n"); ! 737: listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1); ! 738: (*cpu_fprintf)(f, " f_edx: %s\n", buf); ! 739: listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1); ! 740: (*cpu_fprintf)(f, " f_ecx: %s\n", buf); ! 741: listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1); ! 742: (*cpu_fprintf)(f, " extf_edx: %s\n", buf); ! 743: listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1); ! 744: (*cpu_fprintf)(f, " extf_ecx: %s\n", buf); ! 745: return; ! 746: } ! 747: for (def = x86_defs; def; def = def->next) { ! 748: snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name); ! 749: if (model || dump) { ! 750: (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id); ! 751: } else { ! 752: (*cpu_fprintf)(f, "x86 %16s\n", buf); ! 753: } ! 754: if (dump) { ! 755: memcpy(buf, &def->vendor1, sizeof (def->vendor1)); ! 756: memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2)); ! 757: memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3)); ! 758: buf[12] = '\0'; ! 759: (*cpu_fprintf)(f, ! 760: " family %d model %d stepping %d level %d xlevel 0x%x" ! 761: " vendor \"%s\"\n", ! 762: def->family, def->model, def->stepping, def->level, ! 763: def->xlevel, buf); ! 764: listflags(buf, sizeof (buf), def->features, feature_name, 0); ! 765: (*cpu_fprintf)(f, " feature_edx %08x (%s)\n", def->features, ! 766: buf); ! 767: listflags(buf, sizeof (buf), def->ext_features, ext_feature_name, ! 768: 0); ! 769: (*cpu_fprintf)(f, " feature_ecx %08x (%s)\n", def->ext_features, ! 770: buf); ! 771: listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name, ! 772: 0); ! 773: (*cpu_fprintf)(f, " extfeature_edx %08x (%s)\n", ! 774: def->ext2_features, buf); ! 775: listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name, ! 776: 0); ! 777: (*cpu_fprintf)(f, " extfeature_ecx %08x (%s)\n", ! 778: def->ext3_features, buf); ! 779: (*cpu_fprintf)(f, "\n"); ! 780: } ! 781: } ! 782: if (kvm_enabled()) { ! 783: (*cpu_fprintf)(f, "x86 %16s\n", "[host]"); ! 784: } ! 785: } ! 786: ! 787: int cpu_x86_register (CPUX86State *env, const char *cpu_model) ! 788: { ! 789: x86_def_t def1, *def = &def1; ! 790: ! 791: if (cpu_x86_find_by_name(def, cpu_model) < 0) ! 792: return -1; ! 793: if (def->vendor1) { ! 794: env->cpuid_vendor1 = def->vendor1; ! 795: env->cpuid_vendor2 = def->vendor2; ! 796: env->cpuid_vendor3 = def->vendor3; ! 797: } else { ! 798: env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1; ! 799: env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2; ! 800: env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3; ! 801: } ! 802: env->cpuid_vendor_override = def->vendor_override; ! 803: env->cpuid_level = def->level; ! 804: if (def->family > 0x0f) ! 805: env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20); ! 806: else ! 807: env->cpuid_version = def->family << 8; ! 808: env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16); ! 809: env->cpuid_version |= def->stepping; ! 810: env->cpuid_features = def->features; ! 811: env->pat = 0x0007040600070406ULL; ! 812: env->cpuid_ext_features = def->ext_features; ! 813: env->cpuid_ext2_features = def->ext2_features; ! 814: env->cpuid_ext3_features = def->ext3_features; ! 815: env->cpuid_xlevel = def->xlevel; ! 816: env->cpuid_kvm_features = def->kvm_features; ! 817: if (!kvm_enabled()) { ! 818: env->cpuid_features &= TCG_FEATURES; ! 819: env->cpuid_ext_features &= TCG_EXT_FEATURES; ! 820: env->cpuid_ext2_features &= (TCG_EXT2_FEATURES ! 821: #ifdef TARGET_X86_64 ! 822: | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM ! 823: #endif ! 824: ); ! 825: env->cpuid_ext3_features &= TCG_EXT3_FEATURES; ! 826: } ! 827: { ! 828: const char *model_id = def->model_id; ! 829: int c, len, i; ! 830: if (!model_id) ! 831: model_id = ""; ! 832: len = strlen(model_id); ! 833: for(i = 0; i < 48; i++) { ! 834: if (i >= len) ! 835: c = '\0'; ! 836: else ! 837: c = (uint8_t)model_id[i]; ! 838: env->cpuid_model[i >> 2] |= c << (8 * (i & 3)); ! 839: } ! 840: } ! 841: return 0; ! 842: } ! 843: ! 844: #if !defined(CONFIG_USER_ONLY) ! 845: /* copy vendor id string to 32 bit register, nul pad as needed ! 846: */ ! 847: static void cpyid(const char *s, uint32_t *id) ! 848: { ! 849: char *d = (char *)id; ! 850: char i; ! 851: ! 852: for (i = sizeof (*id); i--; ) ! 853: *d++ = *s ? *s++ : '\0'; ! 854: } ! 855: ! 856: /* interpret radix and convert from string to arbitrary scalar, ! 857: * otherwise flag failure ! 858: */ ! 859: #define setscalar(pval, str, perr) \ ! 860: { \ ! 861: char *pend; \ ! 862: unsigned long ul; \ ! 863: \ ! 864: ul = strtoul(str, &pend, 0); \ ! 865: *str && !*pend ? (*pval = ul) : (*perr = 1); \ ! 866: } ! 867: ! 868: /* map cpuid options to feature bits, otherwise return failure ! 869: * (option tags in *str are delimited by whitespace) ! 870: */ ! 871: static void setfeatures(uint32_t *pval, const char *str, ! 872: const char **featureset, int *perr) ! 873: { ! 874: const char *p, *q; ! 875: ! 876: for (q = p = str; *p || *q; q = p) { ! 877: while (iswhite(*p)) ! 878: q = ++p; ! 879: while (*p && !iswhite(*p)) ! 880: ++p; ! 881: if (!*q && !*p) ! 882: return; ! 883: if (!lookup_feature(pval, q, p, featureset)) { ! 884: fprintf(stderr, "error: feature \"%.*s\" not available in set\n", ! 885: (int)(p - q), q); ! 886: *perr = 1; ! 887: return; ! 888: } ! 889: } ! 890: } ! 891: ! 892: /* map config file options to x86_def_t form ! 893: */ ! 894: static int cpudef_setfield(const char *name, const char *str, void *opaque) ! 895: { ! 896: x86_def_t *def = opaque; ! 897: int err = 0; ! 898: ! 899: if (!strcmp(name, "name")) { ! 900: def->name = strdup(str); ! 901: } else if (!strcmp(name, "model_id")) { ! 902: strncpy(def->model_id, str, sizeof (def->model_id)); ! 903: } else if (!strcmp(name, "level")) { ! 904: setscalar(&def->level, str, &err) ! 905: } else if (!strcmp(name, "vendor")) { ! 906: cpyid(&str[0], &def->vendor1); ! 907: cpyid(&str[4], &def->vendor2); ! 908: cpyid(&str[8], &def->vendor3); ! 909: } else if (!strcmp(name, "family")) { ! 910: setscalar(&def->family, str, &err) ! 911: } else if (!strcmp(name, "model")) { ! 912: setscalar(&def->model, str, &err) ! 913: } else if (!strcmp(name, "stepping")) { ! 914: setscalar(&def->stepping, str, &err) ! 915: } else if (!strcmp(name, "feature_edx")) { ! 916: setfeatures(&def->features, str, feature_name, &err); ! 917: } else if (!strcmp(name, "feature_ecx")) { ! 918: setfeatures(&def->ext_features, str, ext_feature_name, &err); ! 919: } else if (!strcmp(name, "extfeature_edx")) { ! 920: setfeatures(&def->ext2_features, str, ext2_feature_name, &err); ! 921: } else if (!strcmp(name, "extfeature_ecx")) { ! 922: setfeatures(&def->ext3_features, str, ext3_feature_name, &err); ! 923: } else if (!strcmp(name, "xlevel")) { ! 924: setscalar(&def->xlevel, str, &err) ! 925: } else { ! 926: fprintf(stderr, "error: unknown option [%s = %s]\n", name, str); ! 927: return (1); ! 928: } ! 929: if (err) { ! 930: fprintf(stderr, "error: bad option value [%s = %s]\n", name, str); ! 931: return (1); ! 932: } ! 933: return (0); ! 934: } ! 935: ! 936: /* register config file entry as x86_def_t ! 937: */ ! 938: static int cpudef_register(QemuOpts *opts, void *opaque) ! 939: { ! 940: x86_def_t *def = qemu_mallocz(sizeof (x86_def_t)); ! 941: ! 942: qemu_opt_foreach(opts, cpudef_setfield, def, 1); ! 943: def->next = x86_defs; ! 944: x86_defs = def; ! 945: return (0); ! 946: } ! 947: ! 948: void cpu_clear_apic_feature(CPUX86State *env) ! 949: { ! 950: env->cpuid_features &= ~CPUID_APIC; ! 951: } ! 952: ! 953: #endif /* !CONFIG_USER_ONLY */ ! 954: ! 955: /* register "cpudef" models defined in configuration file. Here we first ! 956: * preload any built-in definitions ! 957: */ ! 958: void x86_cpudef_setup(void) ! 959: { ! 960: int i; ! 961: ! 962: for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) { ! 963: builtin_x86_defs[i].next = x86_defs; ! 964: builtin_x86_defs[i].flags = 1; ! 965: x86_defs = &builtin_x86_defs[i]; ! 966: } ! 967: #if !defined(CONFIG_USER_ONLY) ! 968: qemu_opts_foreach(&qemu_cpudef_opts, cpudef_register, NULL, 0); ! 969: #endif ! 970: } ! 971: ! 972: static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, ! 973: uint32_t *ecx, uint32_t *edx) ! 974: { ! 975: *ebx = env->cpuid_vendor1; ! 976: *edx = env->cpuid_vendor2; ! 977: *ecx = env->cpuid_vendor3; ! 978: ! 979: /* sysenter isn't supported on compatibility mode on AMD, syscall ! 980: * isn't supported in compatibility mode on Intel. ! 981: * Normally we advertise the actual cpu vendor, but you can override ! 982: * this if you want to use KVM's sysenter/syscall emulation ! 983: * in compatibility mode and when doing cross vendor migration ! 984: */ ! 985: if (kvm_enabled() && ! env->cpuid_vendor_override) { ! 986: host_cpuid(0, 0, NULL, ebx, ecx, edx); ! 987: } ! 988: } ! 989: ! 990: void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, ! 991: uint32_t *eax, uint32_t *ebx, ! 992: uint32_t *ecx, uint32_t *edx) ! 993: { ! 994: /* test if maximum index reached */ ! 995: if (index & 0x80000000) { ! 996: if (index > env->cpuid_xlevel) ! 997: index = env->cpuid_level; ! 998: } else { ! 999: if (index > env->cpuid_level) ! 1000: index = env->cpuid_level; ! 1001: } ! 1002: ! 1003: switch(index) { ! 1004: case 0: ! 1005: *eax = env->cpuid_level; ! 1006: get_cpuid_vendor(env, ebx, ecx, edx); ! 1007: break; ! 1008: case 1: ! 1009: *eax = env->cpuid_version; ! 1010: *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */ ! 1011: *ecx = env->cpuid_ext_features; ! 1012: *edx = env->cpuid_features; ! 1013: if (env->nr_cores * env->nr_threads > 1) { ! 1014: *ebx |= (env->nr_cores * env->nr_threads) << 16; ! 1015: *edx |= 1 << 28; /* HTT bit */ ! 1016: } ! 1017: break; ! 1018: case 2: ! 1019: /* cache info: needed for Pentium Pro compatibility */ ! 1020: *eax = 1; ! 1021: *ebx = 0; ! 1022: *ecx = 0; ! 1023: *edx = 0x2c307d; ! 1024: break; ! 1025: case 4: ! 1026: /* cache info: needed for Core compatibility */ ! 1027: if (env->nr_cores > 1) { ! 1028: *eax = (env->nr_cores - 1) << 26; ! 1029: } else { ! 1030: *eax = 0; ! 1031: } ! 1032: switch (count) { ! 1033: case 0: /* L1 dcache info */ ! 1034: *eax |= 0x0000121; ! 1035: *ebx = 0x1c0003f; ! 1036: *ecx = 0x000003f; ! 1037: *edx = 0x0000001; ! 1038: break; ! 1039: case 1: /* L1 icache info */ ! 1040: *eax |= 0x0000122; ! 1041: *ebx = 0x1c0003f; ! 1042: *ecx = 0x000003f; ! 1043: *edx = 0x0000001; ! 1044: break; ! 1045: case 2: /* L2 cache info */ ! 1046: *eax |= 0x0000143; ! 1047: if (env->nr_threads > 1) { ! 1048: *eax |= (env->nr_threads - 1) << 14; ! 1049: } ! 1050: *ebx = 0x3c0003f; ! 1051: *ecx = 0x0000fff; ! 1052: *edx = 0x0000001; ! 1053: break; ! 1054: default: /* end of info */ ! 1055: *eax = 0; ! 1056: *ebx = 0; ! 1057: *ecx = 0; ! 1058: *edx = 0; ! 1059: break; ! 1060: } ! 1061: break; ! 1062: case 5: ! 1063: /* mwait info: needed for Core compatibility */ ! 1064: *eax = 0; /* Smallest monitor-line size in bytes */ ! 1065: *ebx = 0; /* Largest monitor-line size in bytes */ ! 1066: *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; ! 1067: *edx = 0; ! 1068: break; ! 1069: case 6: ! 1070: /* Thermal and Power Leaf */ ! 1071: *eax = 0; ! 1072: *ebx = 0; ! 1073: *ecx = 0; ! 1074: *edx = 0; ! 1075: break; ! 1076: case 9: ! 1077: /* Direct Cache Access Information Leaf */ ! 1078: *eax = 0; /* Bits 0-31 in DCA_CAP MSR */ ! 1079: *ebx = 0; ! 1080: *ecx = 0; ! 1081: *edx = 0; ! 1082: break; ! 1083: case 0xA: ! 1084: /* Architectural Performance Monitoring Leaf */ ! 1085: *eax = 0; ! 1086: *ebx = 0; ! 1087: *ecx = 0; ! 1088: *edx = 0; ! 1089: break; ! 1090: case 0xD: ! 1091: /* Processor Extended State */ ! 1092: if (!(env->cpuid_ext_features & CPUID_EXT_XSAVE)) { ! 1093: *eax = 0; ! 1094: *ebx = 0; ! 1095: *ecx = 0; ! 1096: *edx = 0; ! 1097: break; ! 1098: } ! 1099: if (kvm_enabled()) { ! 1100: *eax = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EAX); ! 1101: *ebx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EBX); ! 1102: *ecx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_ECX); ! 1103: *edx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EDX); ! 1104: } else { ! 1105: *eax = 0; ! 1106: *ebx = 0; ! 1107: *ecx = 0; ! 1108: *edx = 0; ! 1109: } ! 1110: break; ! 1111: case 0x80000000: ! 1112: *eax = env->cpuid_xlevel; ! 1113: *ebx = env->cpuid_vendor1; ! 1114: *edx = env->cpuid_vendor2; ! 1115: *ecx = env->cpuid_vendor3; ! 1116: break; ! 1117: case 0x80000001: ! 1118: *eax = env->cpuid_version; ! 1119: *ebx = 0; ! 1120: *ecx = env->cpuid_ext3_features; ! 1121: *edx = env->cpuid_ext2_features; ! 1122: ! 1123: /* The Linux kernel checks for the CMPLegacy bit and ! 1124: * discards multiple thread information if it is set. ! 1125: * So dont set it here for Intel to make Linux guests happy. ! 1126: */ ! 1127: if (env->nr_cores * env->nr_threads > 1) { ! 1128: uint32_t tebx, tecx, tedx; ! 1129: get_cpuid_vendor(env, &tebx, &tecx, &tedx); ! 1130: if (tebx != CPUID_VENDOR_INTEL_1 || ! 1131: tedx != CPUID_VENDOR_INTEL_2 || ! 1132: tecx != CPUID_VENDOR_INTEL_3) { ! 1133: *ecx |= 1 << 1; /* CmpLegacy bit */ ! 1134: } ! 1135: } ! 1136: ! 1137: if (kvm_enabled()) { ! 1138: /* Nested SVM not yet supported in upstream QEMU */ ! 1139: *ecx &= ~CPUID_EXT3_SVM; ! 1140: } ! 1141: break; ! 1142: case 0x80000002: ! 1143: case 0x80000003: ! 1144: case 0x80000004: ! 1145: *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0]; ! 1146: *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1]; ! 1147: *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2]; ! 1148: *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3]; ! 1149: break; ! 1150: case 0x80000005: ! 1151: /* cache info (L1 cache) */ ! 1152: *eax = 0x01ff01ff; ! 1153: *ebx = 0x01ff01ff; ! 1154: *ecx = 0x40020140; ! 1155: *edx = 0x40020140; ! 1156: break; ! 1157: case 0x80000006: ! 1158: /* cache info (L2 cache) */ ! 1159: *eax = 0; ! 1160: *ebx = 0x42004200; ! 1161: *ecx = 0x02008140; ! 1162: *edx = 0; ! 1163: break; ! 1164: case 0x80000008: ! 1165: /* virtual & phys address size in low 2 bytes. */ ! 1166: /* XXX: This value must match the one used in the MMU code. */ ! 1167: if (env->cpuid_ext2_features & CPUID_EXT2_LM) { ! 1168: /* 64 bit processor */ ! 1169: /* XXX: The physical address space is limited to 42 bits in exec.c. */ ! 1170: *eax = 0x00003028; /* 48 bits virtual, 40 bits physical */ ! 1171: } else { ! 1172: if (env->cpuid_features & CPUID_PSE36) ! 1173: *eax = 0x00000024; /* 36 bits physical */ ! 1174: else ! 1175: *eax = 0x00000020; /* 32 bits physical */ ! 1176: } ! 1177: *ebx = 0; ! 1178: *ecx = 0; ! 1179: *edx = 0; ! 1180: if (env->nr_cores * env->nr_threads > 1) { ! 1181: *ecx |= (env->nr_cores * env->nr_threads) - 1; ! 1182: } ! 1183: break; ! 1184: case 0x8000000A: ! 1185: *eax = 0x00000001; /* SVM Revision */ ! 1186: *ebx = 0x00000010; /* nr of ASIDs */ ! 1187: *ecx = 0; ! 1188: *edx = 0; /* optional features */ ! 1189: break; ! 1190: default: ! 1191: /* reserved values: zero */ ! 1192: *eax = 0; ! 1193: *ebx = 0; ! 1194: *ecx = 0; ! 1195: *edx = 0; ! 1196: break; ! 1197: } ! 1198: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.