Annotation of qemu/target-i386/cpuid.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.