cpu.c 60.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*
 *  i386 CPUID helper functions
 *
 *  Copyright (c) 2003 Fabrice Bellard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

#include "cpu.h"
#include "kvm.h"

#include "qemu-option.h"
#include "qemu-config.h"

30
#include "qapi/qapi-visit-core.h"
31
#include "arch_init.h"
32

33 34
#include "hyperv.h"

35
#include "hw/hw.h"
Stefan Weil's avatar
Stefan Weil committed
36
#if defined(CONFIG_KVM)
37
#include <linux/kvm_para.h>
Stefan Weil's avatar
Stefan Weil committed
38
#endif
39

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
/* feature flags taken from "Intel Processor Identification and the CPUID
 * Instruction" and AMD's "CPUID Specification".  In cases of disagreement
 * between feature naming conventions, aliases may be added.
 */
static const char *feature_name[] = {
    "fpu", "vme", "de", "pse",
    "tsc", "msr", "pae", "mce",
    "cx8", "apic", NULL, "sep",
    "mtrr", "pge", "mca", "cmov",
    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
    NULL, "ds" /* Intel dts */, "acpi", "mmx",
    "fxsr", "sse", "sse2", "ss",
    "ht" /* Intel htt */, "tm", "ia64", "pbe",
};
static const char *ext_feature_name[] = {
55
    "pni|sse3" /* Intel,AMD sse3 */, "pclmulqdq|pclmuldq", "dtes64", "monitor",
56
    "ds_cpl", "vmx", "smx", "est",
57
    "tm2", "ssse3", "cid", NULL,
58
    "fma", "cx16", "xtpr", "pdcm",
Mao, Junjie's avatar
Mao, Junjie committed
59
    NULL, "pcid", "dca", "sse4.1|sse4_1",
60
    "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
61
    "tsc-deadline", "aes", "xsave", "osxsave",
62
    "avx", NULL, NULL, "hypervisor",
63 64 65 66 67 68 69
};
static const char *ext2_feature_name[] = {
    "fpu", "vme", "de", "pse",
    "tsc", "msr", "pae", "mce",
    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall",
    "mtrr", "pge", "mca", "cmov",
    "pat", "pse36", NULL, NULL /* Linux mp */,
70
    "nx|xd", NULL, "mmxext", "mmx",
71
    "fxsr", "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp",
72
    NULL, "lm|i64", "3dnowext", "3dnow",
73 74 75 76
};
static const char *ext3_feature_name[] = {
    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
    "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
77
    "3dnowprefetch", "osvw", "ibs", "xop",
78
    "skinit", "wdt", NULL, NULL,
79
    "fma4", NULL, "cvt16", "nodeid_msr",
80 81 82 83 84 85
    NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL,
};

static const char *kvm_feature_name[] = {
86
    "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", "kvm_asyncpf", NULL, "kvm_pv_eoi", NULL,
87 88 89 90 91
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};

Joerg Roedel's avatar
Joerg Roedel committed
92 93 94 95 96 97 98 99 100 101 102
static const char *svm_feature_name[] = {
    "npt", "lbrv", "svm_lock", "nrip_save",
    "tsc_scale", "vmcb_clean",  "flushbyasid", "decodeassists",
    NULL, NULL, "pause_filter", NULL,
    "pfthreshold", NULL, NULL, NULL,
    NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, NULL,
};

103 104 105 106 107 108 109 110 111 112 113 114 115
/* collects per-function cpuid data
 */
typedef struct model_features_t {
    uint32_t *guest_feat;
    uint32_t *host_feat;
    uint32_t check_feat;
    const char **flag_names;
    uint32_t cpuid;
    } model_features_t;

int check_cpuid = 0;
int enforce_cpuid = 0;

116 117
void host_cpuid(uint32_t function, uint32_t count,
                uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
118 119
{
#if defined(CONFIG_KVM)
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
    uint32_t vec[4];

#ifdef __x86_64__
    asm volatile("cpuid"
                 : "=a"(vec[0]), "=b"(vec[1]),
                   "=c"(vec[2]), "=d"(vec[3])
                 : "0"(function), "c"(count) : "cc");
#else
    asm volatile("pusha \n\t"
                 "cpuid \n\t"
                 "mov %%eax, 0(%2) \n\t"
                 "mov %%ebx, 4(%2) \n\t"
                 "mov %%ecx, 8(%2) \n\t"
                 "mov %%edx, 12(%2) \n\t"
                 "popa"
                 : : "a"(function), "c"(count), "S"(vec)
                 : "memory", "cc");
#endif

139
    if (eax)
140
        *eax = vec[0];
141
    if (ebx)
142
        *ebx = vec[1];
143
    if (ecx)
144
        *ecx = vec[2];
145
    if (edx)
146
        *edx = vec[3];
147 148
#endif
}
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))

/* general substring compare of *[s1..e1) and *[s2..e2).  sx is start of
 * a substring.  ex if !NULL points to the first char after a substring,
 * otherwise the string is assumed to sized by a terminating nul.
 * Return lexical ordering of *s1:*s2.
 */
static int sstrcmp(const char *s1, const char *e1, const char *s2,
    const char *e2)
{
    for (;;) {
        if (!*s1 || !*s2 || *s1 != *s2)
            return (*s1 - *s2);
        ++s1, ++s2;
        if (s1 == e1 && s2 == e2)
            return (0);
        else if (s1 == e1)
            return (*s2);
        else if (s2 == e2)
            return (*s1);
    }
}

/* compare *[s..e) to *altstr.  *altstr may be a simple string or multiple
 * '|' delimited (possibly empty) strings in which case search for a match
 * within the alternatives proceeds left to right.  Return 0 for success,
 * non-zero otherwise.
 */
static int altcmp(const char *s, const char *e, const char *altstr)
{
    const char *p, *q;

    for (q = p = altstr; ; ) {
        while (*p && *p != '|')
            ++p;
        if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
            return (0);
        if (!*p)
            return (1);
        else
            q = ++p;
    }
}

/* search featureset for flag *[s..e), if found set corresponding bit in
195
 * *pval and return true, otherwise return false
196
 */
197 198
static bool lookup_feature(uint32_t *pval, const char *s, const char *e,
                           const char **featureset)
199 200 201
{
    uint32_t mask;
    const char **ppc;
202
    bool found = false;
203

204
    for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc) {
205 206
        if (*ppc && !altcmp(s, e, *ppc)) {
            *pval |= mask;
207
            found = true;
208
        }
209 210
    }
    return found;
211 212 213 214 215 216
}

static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
                                    uint32_t *ext_features,
                                    uint32_t *ext2_features,
                                    uint32_t *ext3_features,
Joerg Roedel's avatar
Joerg Roedel committed
217 218
                                    uint32_t *kvm_features,
                                    uint32_t *svm_features)
219 220 221 222 223
{
    if (!lookup_feature(features, flagname, NULL, feature_name) &&
        !lookup_feature(ext_features, flagname, NULL, ext_feature_name) &&
        !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) &&
        !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) &&
Joerg Roedel's avatar
Joerg Roedel committed
224 225
        !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name) &&
        !lookup_feature(svm_features, flagname, NULL, svm_feature_name))
226 227 228 229 230 231 232 233 234 235 236
            fprintf(stderr, "CPU feature %s not found\n", flagname);
}

typedef struct x86_def_t {
    struct x86_def_t *next;
    const char *name;
    uint32_t level;
    uint32_t vendor1, vendor2, vendor3;
    int family;
    int model;
    int stepping;
237
    int tsc_khz;
Joerg Roedel's avatar
Joerg Roedel committed
238 239
    uint32_t features, ext_features, ext2_features, ext3_features;
    uint32_t kvm_features, svm_features;
240 241 242 243
    uint32_t xlevel;
    char model_id[48];
    int vendor_override;
    uint32_t flags;
244 245 246
    /* Store the results of Centaur's CPUID instructions */
    uint32_t ext4_features;
    uint32_t xlevel2;
247 248
    /* The feature bits on CPUID[EAX=7,ECX=0].EBX */
    uint32_t cpuid_7_0_ebx_features;
249 250 251 252 253 254 255 256 257 258 259 260 261
} x86_def_t;

#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
          CPUID_PSE36 | CPUID_FXSR)
#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
          CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
          CPUID_PAE | CPUID_SEP | CPUID_APIC)
262
#define EXT2_FEATURE_MASK 0x0183F3FF
263

264 265 266 267 268
#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
          CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
          CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
          CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
269 270 271 272 273
          /* partly implemented:
          CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64)
          CPUID_PSE36 (needed for Solaris) */
          /* missing:
          CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
274
#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
Andi Kleen's avatar
Andi Kleen committed
275
          CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
276
          CPUID_EXT_HYPERVISOR)
277 278
          /* missing:
          CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
Andi Kleen's avatar
Andi Kleen committed
279
          CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */
280 281 282
#define TCG_EXT2_FEATURES ((TCG_FEATURES & EXT2_FEATURE_MASK) | \
          CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
          CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
283 284
          /* missing:
          CPUID_EXT2_PDPE1GB */
285 286
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
          CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
Joerg Roedel's avatar
Joerg Roedel committed
287
#define TCG_SVM_FEATURES 0
288

289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
/* maintains list of cpu model definitions
 */
static x86_def_t *x86_defs = {NULL};

/* built-in cpu model definitions (deprecated)
 */
static x86_def_t builtin_x86_defs[] = {
    {
        .name = "qemu64",
        .level = 4,
        .vendor1 = CPUID_VENDOR_AMD_1,
        .vendor2 = CPUID_VENDOR_AMD_2,
        .vendor3 = CPUID_VENDOR_AMD_3,
        .family = 6,
        .model = 2,
        .stepping = 3,
        .features = PPRO_FEATURES |
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
            CPUID_PSE36,
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
309
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
        .xlevel = 0x8000000A,
    },
    {
        .name = "phenom",
        .level = 5,
        .vendor1 = CPUID_VENDOR_AMD_1,
        .vendor2 = CPUID_VENDOR_AMD_2,
        .vendor3 = CPUID_VENDOR_AMD_3,
        .family = 16,
        .model = 2,
        .stepping = 3,
        .features = PPRO_FEATURES |
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
326
            CPUID_PSE36 | CPUID_VME | CPUID_HT,
327 328
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
            CPUID_EXT_POPCNT,
329
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
330 331
            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
332
            CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
333 334 335 336 337 338
        /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
                    CPUID_EXT3_CR8LEG,
                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
Joerg Roedel's avatar
Joerg Roedel committed
339
        .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV,
340 341 342 343 344 345 346 347 348 349 350
        .xlevel = 0x8000001A,
        .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
    },
    {
        .name = "core2duo",
        .level = 10,
        .family = 6,
        .model = 15,
        .stepping = 11,
        .features = PPRO_FEATURES |
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
351 352 353 354 355
            CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS |
            CPUID_HT | CPUID_TM | CPUID_PBE,
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
            CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST |
            CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
        .ext3_features = CPUID_EXT3_LAHF_LM,
        .xlevel = 0x80000008,
        .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
    },
    {
        .name = "kvm64",
        .level = 5,
        .vendor1 = CPUID_VENDOR_INTEL_1,
        .vendor2 = CPUID_VENDOR_INTEL_2,
        .vendor3 = CPUID_VENDOR_INTEL_3,
        .family = 15,
        .model = 6,
        .stepping = 1,
        /* Missing: CPUID_VME, CPUID_HT */
        .features = PPRO_FEATURES |
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
            CPUID_PSE36,
        /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16,
        /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
377
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
        /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
                    CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
        .ext3_features = 0,
        .xlevel = 0x80000008,
        .model_id = "Common KVM processor"
    },
    {
        .name = "qemu32",
        .level = 4,
        .family = 6,
        .model = 3,
        .stepping = 3,
        .features = PPRO_FEATURES,
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
Andre Przywara's avatar
Andre Przywara committed
395
        .xlevel = 0x80000004,
396
    },
397 398 399 400 401 402 403 404 405 406 407 408 409 410
    {
        .name = "kvm32",
        .level = 5,
        .family = 15,
        .model = 6,
        .stepping = 1,
        .features = PPRO_FEATURES |
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
        .ext_features = CPUID_EXT_SSE3,
        .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK,
        .ext3_features = 0,
        .xlevel = 0x80000008,
        .model_id = "Common 32-bit KVM processor"
    },
411 412 413 414 415 416 417
    {
        .name = "coreduo",
        .level = 10,
        .family = 6,
        .model = 14,
        .stepping = 8,
        .features = PPRO_FEATURES | CPUID_VME |
418 419 420 421
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI |
            CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
            CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
422 423 424 425 426 427
        .ext2_features = CPUID_EXT2_NX,
        .xlevel = 0x80000008,
        .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
    },
    {
        .name = "486",
Andre Przywara's avatar
Andre Przywara committed
428
        .level = 1,
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
        .family = 4,
        .model = 0,
        .stepping = 0,
        .features = I486_FEATURES,
        .xlevel = 0,
    },
    {
        .name = "pentium",
        .level = 1,
        .family = 5,
        .model = 4,
        .stepping = 3,
        .features = PENTIUM_FEATURES,
        .xlevel = 0,
    },
    {
        .name = "pentium2",
        .level = 2,
        .family = 6,
        .model = 5,
        .stepping = 2,
        .features = PENTIUM2_FEATURES,
        .xlevel = 0,
    },
    {
        .name = "pentium3",
        .level = 2,
        .family = 6,
        .model = 7,
        .stepping = 3,
        .features = PENTIUM3_FEATURES,
        .xlevel = 0,
    },
    {
        .name = "athlon",
        .level = 2,
        .vendor1 = CPUID_VENDOR_AMD_1,
        .vendor2 = CPUID_VENDOR_AMD_2,
        .vendor3 = CPUID_VENDOR_AMD_3,
        .family = 6,
        .model = 2,
        .stepping = 3,
        .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
472
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
473 474 475 476 477 478 479 480 481 482
        .xlevel = 0x80000008,
    },
    {
        .name = "n270",
        /* original is on level 10 */
        .level = 5,
        .family = 6,
        .model = 28,
        .stepping = 2,
        .features = PPRO_FEATURES |
483 484
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS |
            CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
485
            /* Some CPUs got no CPUID_SEP */
486 487
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
            CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR,
488
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_NX,
489
        .ext3_features = CPUID_EXT3_LAHF_LM,
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
        .xlevel = 0x8000000A,
        .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
    },
};

static int cpu_x86_fill_model_id(char *str)
{
    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
    int i;

    for (i = 0; i < 3; i++) {
        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
        memcpy(str + i * 16 +  0, &eax, 4);
        memcpy(str + i * 16 +  4, &ebx, 4);
        memcpy(str + i * 16 +  8, &ecx, 4);
        memcpy(str + i * 16 + 12, &edx, 4);
    }
    return 0;
}

static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
{
    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;

    x86_cpu_def->name = "host";
    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
    x86_cpu_def->level = eax;
    x86_cpu_def->vendor1 = ebx;
    x86_cpu_def->vendor2 = edx;
    x86_cpu_def->vendor3 = ecx;

    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
    x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
    x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
    x86_cpu_def->stepping = eax & 0x0F;
    x86_cpu_def->ext_features = ecx;
    x86_cpu_def->features = edx;

528 529 530 531 532 533
    if (kvm_enabled() && x86_cpu_def->level >= 7) {
        x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX);
    } else {
        x86_cpu_def->cpuid_7_0_ebx_features = 0;
    }

534 535 536 537 538 539 540 541 542
    host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
    x86_cpu_def->xlevel = eax;

    host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
    x86_cpu_def->ext2_features = edx;
    x86_cpu_def->ext3_features = ecx;
    cpu_x86_fill_model_id(x86_cpu_def->model_id);
    x86_cpu_def->vendor_override = 0;

543 544 545 546 547 548 549 550 551 552 553 554
    /* Call Centaur's CPUID instruction. */
    if (x86_cpu_def->vendor1 == CPUID_VENDOR_VIA_1 &&
        x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 &&
        x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) {
        host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx);
        if (eax >= 0xC0000001) {
            /* Support VIA max extended level */
            x86_cpu_def->xlevel2 = eax;
            host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx);
            x86_cpu_def->ext4_features = edx;
        }
    }
Joerg Roedel's avatar
Joerg Roedel committed
555 556 557 558 559 560 561 562 563

    /*
     * Every SVM feature requires emulation support in KVM - so we can't just
     * read the host features here. KVM might even support SVM features not
     * available on the host hardware. Just set all bits and mask out the
     * unsupported ones later.
     */
    x86_cpu_def->svm_features = -1;

564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
    return 0;
}

static int unavailable_host_feature(struct model_features_t *f, uint32_t mask)
{
    int i;

    for (i = 0; i < 32; ++i)
        if (1 << i & mask) {
            fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested"
                " flag '%s' [0x%08x]\n",
                f->cpuid >> 16, f->cpuid & 0xffff,
                f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask);
            break;
        }
    return 0;
}

/* best effort attempt to inform user requested cpu flags aren't making
 * their way to the guest.  Note: ft[].check_feat ideally should be
 * specified via a guest_def field to suppress report of extraneous flags.
 */
static int check_features_against_host(x86_def_t *guest_def)
{
    x86_def_t host_def;
    uint32_t mask;
    int rv, i;
    struct model_features_t ft[] = {
        {&guest_def->features, &host_def.features,
            ~0, feature_name, 0x00000000},
        {&guest_def->ext_features, &host_def.ext_features,
            ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001},
        {&guest_def->ext2_features, &host_def.ext2_features,
            ~PPRO_FEATURES, ext2_feature_name, 0x80000000},
        {&guest_def->ext3_features, &host_def.ext3_features,
            ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};

    cpu_x86_fill_host(&host_def);
Blue Swirl's avatar
Blue Swirl committed
602
    for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i)
603 604 605 606 607 608 609 610 611
        for (mask = 1; mask; mask <<= 1)
            if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
                !(*ft[i].host_feat & mask)) {
                    unavailable_host_feature(&ft[i], mask);
                    rv = 1;
                }
    return rv;
}

612 613 614 615 616 617 618 619 620 621 622 623 624 625
static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque,
                                         const char *name, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
    int64_t value;

    value = (env->cpuid_version >> 8) & 0xf;
    if (value == 0xf) {
        value += (env->cpuid_version >> 20) & 0xff;
    }
    visit_type_int(v, &value, name, errp);
}

626 627
static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque,
                                         const char *name, Error **errp)
628
{
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
    const int64_t min = 0;
    const int64_t max = 0xff + 0xf;
    int64_t value;

    visit_type_int(v, &value, name, errp);
    if (error_is_set(errp)) {
        return;
    }
    if (value < min || value > max) {
        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
                  name ? name : "null", value, min, max);
        return;
    }

645
    env->cpuid_version &= ~0xff00f00;
646 647
    if (value > 0x0f) {
        env->cpuid_version |= 0xf00 | ((value - 0x0f) << 20);
648
    } else {
649
        env->cpuid_version |= value << 8;
650 651 652
    }
}

653 654 655 656 657 658 659 660 661 662 663 664
static void x86_cpuid_version_get_model(Object *obj, Visitor *v, void *opaque,
                                        const char *name, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
    int64_t value;

    value = (env->cpuid_version >> 4) & 0xf;
    value |= ((env->cpuid_version >> 16) & 0xf) << 4;
    visit_type_int(v, &value, name, errp);
}

665 666
static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque,
                                        const char *name, Error **errp)
667
{
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
    const int64_t min = 0;
    const int64_t max = 0xff;
    int64_t value;

    visit_type_int(v, &value, name, errp);
    if (error_is_set(errp)) {
        return;
    }
    if (value < min || value > max) {
        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
                  name ? name : "null", value, min, max);
        return;
    }

684
    env->cpuid_version &= ~0xf00f0;
685
    env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16);
686 687
}

688 689 690 691 692 693 694 695 696 697 698 699
static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v,
                                           void *opaque, const char *name,
                                           Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
    int64_t value;

    value = env->cpuid_version & 0xf;
    visit_type_int(v, &value, name, errp);
}

700 701 702
static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
                                           void *opaque, const char *name,
                                           Error **errp)
703
{
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
    const int64_t min = 0;
    const int64_t max = 0xf;
    int64_t value;

    visit_type_int(v, &value, name, errp);
    if (error_is_set(errp)) {
        return;
    }
    if (value < min || value > max) {
        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
                  name ? name : "null", value, min, max);
        return;
    }

720
    env->cpuid_version &= ~0xf;
721
    env->cpuid_version |= value & 0xf;
722 723
}

724 725 726 727 728
static void x86_cpuid_get_level(Object *obj, Visitor *v, void *opaque,
                                const char *name, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);

729
    visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
730 731 732 733 734 735 736
}

static void x86_cpuid_set_level(Object *obj, Visitor *v, void *opaque,
                                const char *name, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);

737
    visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
738 739
}

740 741 742 743 744
static void x86_cpuid_get_xlevel(Object *obj, Visitor *v, void *opaque,
                                 const char *name, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);

745
    visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
746 747 748 749 750 751 752
}

static void x86_cpuid_set_xlevel(Object *obj, Visitor *v, void *opaque,
                                 const char *name, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);

753
    visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
754 755
}

756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
    char *value;
    int i;

    value = (char *)g_malloc(12 + 1);
    for (i = 0; i < 4; i++) {
        value[i    ] = env->cpuid_vendor1 >> (8 * i);
        value[i + 4] = env->cpuid_vendor2 >> (8 * i);
        value[i + 8] = env->cpuid_vendor3 >> (8 * i);
    }
    value[12] = '\0';
    return value;
}

static void x86_cpuid_set_vendor(Object *obj, const char *value,
                                 Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
    int i;

    if (strlen(value) != 12) {
        error_set(errp, QERR_PROPERTY_VALUE_BAD, "",
                  "vendor", value);
        return;
    }

    env->cpuid_vendor1 = 0;
    env->cpuid_vendor2 = 0;
    env->cpuid_vendor3 = 0;
    for (i = 0; i < 4; i++) {
        env->cpuid_vendor1 |= ((uint8_t)value[i    ]) << (8 * i);
        env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i);
        env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i);
    }
    env->cpuid_vendor_override = 1;
}

797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
static char *x86_cpuid_get_model_id(Object *obj, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
    char *value;
    int i;

    value = g_malloc(48 + 1);
    for (i = 0; i < 48; i++) {
        value[i] = env->cpuid_model[i >> 2] >> (8 * (i & 3));
    }
    value[48] = '\0';
    return value;
}

812 813
static void x86_cpuid_set_model_id(Object *obj, const char *model_id,
                                   Error **errp)
814
{
815 816
    X86CPU *cpu = X86_CPU(obj);
    CPUX86State *env = &cpu->env;
817 818 819 820 821 822
    int c, len, i;

    if (model_id == NULL) {
        model_id = "";
    }
    len = strlen(model_id);
823
    memset(env->cpuid_model, 0, 48);
824 825 826 827 828 829 830 831 832 833
    for (i = 0; i < 48; i++) {
        if (i >= len) {
            c = '\0';
        } else {
            c = (uint8_t)model_id[i];
        }
        env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
    }
}

834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, void *opaque,
                                   const char *name, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);
    int64_t value;

    value = cpu->env.tsc_khz * 1000;
    visit_type_int(v, &value, name, errp);
}

static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
                                   const char *name, Error **errp)
{
    X86CPU *cpu = X86_CPU(obj);
    const int64_t min = 0;
    const int64_t max = INT_MAX;
    int64_t value;

    visit_type_int(v, &value, name, errp);
    if (error_is_set(errp)) {
        return;
    }
    if (value < min || value > max) {
        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
                  name ? name : "null", value, min, max);
        return;
    }

    cpu->env.tsc_khz = value / 1000;
}

865 866 867 868 869
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
{
    unsigned int i;
    x86_def_t *def;

870
    char *s = g_strdup(cpu_model);
871
    char *featurestr, *name = strtok(s, ",");
Joerg Roedel's avatar
Joerg Roedel committed
872 873 874 875 876 877 878 879
    /* Features to be added*/
    uint32_t plus_features = 0, plus_ext_features = 0;
    uint32_t plus_ext2_features = 0, plus_ext3_features = 0;
    uint32_t plus_kvm_features = 0, plus_svm_features = 0;
    /* Features to be removed */
    uint32_t minus_features = 0, minus_ext_features = 0;
    uint32_t minus_ext2_features = 0, minus_ext3_features = 0;
    uint32_t minus_kvm_features = 0, minus_svm_features = 0;
880 881 882
    uint32_t numvalue;

    for (def = x86_defs; def; def = def->next)
883
        if (name && !strcmp(name, def->name))
884
            break;
885
    if (kvm_enabled() && name && strcmp(name, "host") == 0) {
886 887 888 889 890 891 892
        cpu_x86_fill_host(x86_cpu_def);
    } else if (!def) {
        goto error;
    } else {
        memcpy(x86_cpu_def, def, sizeof(*def));
    }

893 894 895 896 897 898 899 900 901 902 903
#if defined(CONFIG_KVM)
    plus_kvm_features = (1 << KVM_FEATURE_CLOCKSOURCE) |
        (1 << KVM_FEATURE_NOP_IO_DELAY) | 
        (1 << KVM_FEATURE_MMU_OP) |
        (1 << KVM_FEATURE_CLOCKSOURCE2) |
        (1 << KVM_FEATURE_ASYNC_PF) | 
        (1 << KVM_FEATURE_STEAL_TIME) |
        (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
#else
    plus_kvm_features = 0;
#endif
904 905 906

    add_flagname_to_bitmaps("hypervisor", &plus_features,
        &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
Joerg Roedel's avatar
Joerg Roedel committed
907
        &plus_kvm_features, &plus_svm_features);
908 909 910 911 912 913

    featurestr = strtok(NULL, ",");

    while (featurestr) {
        char *val;
        if (featurestr[0] == '+') {
Joerg Roedel's avatar
Joerg Roedel committed
914 915 916 917
            add_flagname_to_bitmaps(featurestr + 1, &plus_features,
                            &plus_ext_features, &plus_ext2_features,
                            &plus_ext3_features, &plus_kvm_features,
                            &plus_svm_features);
918
        } else if (featurestr[0] == '-') {
Joerg Roedel's avatar
Joerg Roedel committed
919 920 921 922
            add_flagname_to_bitmaps(featurestr + 1, &minus_features,
                            &minus_ext_features, &minus_ext2_features,
                            &minus_ext3_features, &minus_kvm_features,
                            &minus_svm_features);
923 924 925 926 927
        } else if ((val = strchr(featurestr, '='))) {
            *val = 0; val++;
            if (!strcmp(featurestr, "family")) {
                char *err;
                numvalue = strtoul(val, &err, 0);
928
                if (!*val || *err || numvalue > 0xff + 0xf) {
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964
                    fprintf(stderr, "bad numerical value %s\n", val);
                    goto error;
                }
                x86_cpu_def->family = numvalue;
            } else if (!strcmp(featurestr, "model")) {
                char *err;
                numvalue = strtoul(val, &err, 0);
                if (!*val || *err || numvalue > 0xff) {
                    fprintf(stderr, "bad numerical value %s\n", val);
                    goto error;
                }
                x86_cpu_def->model = numvalue;
            } else if (!strcmp(featurestr, "stepping")) {
                char *err;
                numvalue = strtoul(val, &err, 0);
                if (!*val || *err || numvalue > 0xf) {
                    fprintf(stderr, "bad numerical value %s\n", val);
                    goto error;
                }
                x86_cpu_def->stepping = numvalue ;
            } else if (!strcmp(featurestr, "level")) {
                char *err;
                numvalue = strtoul(val, &err, 0);
                if (!*val || *err) {
                    fprintf(stderr, "bad numerical value %s\n", val);
                    goto error;
                }
                x86_cpu_def->level = numvalue;
            } else if (!strcmp(featurestr, "xlevel")) {
                char *err;
                numvalue = strtoul(val, &err, 0);
                if (!*val || *err) {
                    fprintf(stderr, "bad numerical value %s\n", val);
                    goto error;
                }
                if (numvalue < 0x80000000) {
Aurelien Jarno's avatar
Aurelien Jarno committed
965
                    numvalue += 0x80000000;
966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
                }
                x86_cpu_def->xlevel = numvalue;
            } else if (!strcmp(featurestr, "vendor")) {
                if (strlen(val) != 12) {
                    fprintf(stderr, "vendor string must be 12 chars long\n");
                    goto error;
                }
                x86_cpu_def->vendor1 = 0;
                x86_cpu_def->vendor2 = 0;
                x86_cpu_def->vendor3 = 0;
                for(i = 0; i < 4; i++) {
                    x86_cpu_def->vendor1 |= ((uint8_t)val[i    ]) << (8 * i);
                    x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
                    x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
                }
                x86_cpu_def->vendor_override = 1;
            } else if (!strcmp(featurestr, "model_id")) {
                pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
                        val);
985 986 987 988 989 990
            } else if (!strcmp(featurestr, "tsc_freq")) {
                int64_t tsc_freq;
                char *err;

                tsc_freq = strtosz_suffix_unit(val, &err,
                                               STRTOSZ_DEFSUFFIX_B, 1000);
991
                if (tsc_freq < 0 || *err) {
992 993 994 995
                    fprintf(stderr, "bad numerical value %s\n", val);
                    goto error;
                }
                x86_cpu_def->tsc_khz = tsc_freq / 1000;
996 997 998 999 1000 1001 1002 1003
            } else if (!strcmp(featurestr, "hv_spinlocks")) {
                char *err;
                numvalue = strtoul(val, &err, 0);
                if (!*val || *err) {
                    fprintf(stderr, "bad numerical value %s\n", val);
                    goto error;
                }
                hyperv_set_spinlock_retries(numvalue);
1004 1005 1006 1007 1008 1009 1010 1011
            } else {
                fprintf(stderr, "unrecognized feature %s\n", featurestr);
                goto error;
            }
        } else if (!strcmp(featurestr, "check")) {
            check_cpuid = 1;
        } else if (!strcmp(featurestr, "enforce")) {
            check_cpuid = enforce_cpuid = 1;
1012 1013 1014 1015
        } else if (!strcmp(featurestr, "hv_relaxed")) {
            hyperv_enable_relaxed_timing(true);
        } else if (!strcmp(featurestr, "hv_vapic")) {
            hyperv_enable_vapic_recommended(true);
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
        } else {
            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
            goto error;
        }
        featurestr = strtok(NULL, ",");
    }
    x86_cpu_def->features |= plus_features;
    x86_cpu_def->ext_features |= plus_ext_features;
    x86_cpu_def->ext2_features |= plus_ext2_features;
    x86_cpu_def->ext3_features |= plus_ext3_features;
    x86_cpu_def->kvm_features |= plus_kvm_features;
Joerg Roedel's avatar
Joerg Roedel committed
1027
    x86_cpu_def->svm_features |= plus_svm_features;
1028 1029 1030 1031 1032
    x86_cpu_def->features &= ~minus_features;
    x86_cpu_def->ext_features &= ~minus_ext_features;
    x86_cpu_def->ext2_features &= ~minus_ext2_features;
    x86_cpu_def->ext3_features &= ~minus_ext3_features;
    x86_cpu_def->kvm_features &= ~minus_kvm_features;
Joerg Roedel's avatar
Joerg Roedel committed
1033
    x86_cpu_def->svm_features &= ~minus_svm_features;
1034 1035 1036 1037
    if (check_cpuid) {
        if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
            goto error;
    }
1038
    g_free(s);
1039 1040 1041
    return 0;

error:
1042
    g_free(s);
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
    return -1;
}

/* generate a composite string into buf of all cpuid names in featureset
 * selected by fbits.  indicate truncation at bufsize in the event of overflow.
 * if flags, suppress names undefined in featureset.
 */
static void listflags(char *buf, int bufsize, uint32_t fbits,
    const char **featureset, uint32_t flags)
{
    const char **p = &featureset[31];
    char *q, *b, bit;
    int nc;

    b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
    *buf = '\0';
    for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
        if (fbits & 1 << bit && (*p || !flags)) {
            if (*p)
                nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
            else
                nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
            if (bufsize <= nc) {
                if (b) {
                    memcpy(b, "...", sizeof("..."));
                }
                return;
            }
            q += nc;
            bufsize -= nc;
        }
}

/* generate CPU information:
 * -?        list model names
 * -?model   list model names/IDs
 * -?dump    output all model (x86_def_t) data
 * -?cpuid   list all recognized cpuid flag names
 */
1082
void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
{
    unsigned char model = !strcmp("?model", optarg);
    unsigned char dump = !strcmp("?dump", optarg);
    unsigned char cpuid = !strcmp("?cpuid", optarg);
    x86_def_t *def;
    char buf[256];

    if (cpuid) {
        (*cpu_fprintf)(f, "Recognized CPUID flags:\n");
        listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1);
        (*cpu_fprintf)(f, "  f_edx: %s\n", buf);
        listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1);
        (*cpu_fprintf)(f, "  f_ecx: %s\n", buf);
        listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1);
        (*cpu_fprintf)(f, "  extf_edx: %s\n", buf);
        listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1);
        (*cpu_fprintf)(f, "  extf_ecx: %s\n", buf);
        return;
    }
    for (def = x86_defs; def; def = def->next) {
        snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name);
        if (model || dump) {
            (*cpu_fprintf)(f, "x86 %16s  %-48s\n", buf, def->model_id);
        } else {
            (*cpu_fprintf)(f, "x86 %16s\n", buf);
        }
        if (dump) {
            memcpy(buf, &def->vendor1, sizeof (def->vendor1));
            memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2));
            memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3));
            buf[12] = '\0';
            (*cpu_fprintf)(f,
                "  family %d model %d stepping %d level %d xlevel 0x%x"
                " vendor \"%s\"\n",
                def->family, def->model, def->stepping, def->level,
                def->xlevel, buf);
            listflags(buf, sizeof (buf), def->features, feature_name, 0);
            (*cpu_fprintf)(f, "  feature_edx %08x (%s)\n", def->features,
                buf);
            listflags(buf, sizeof (buf), def->ext_features, ext_feature_name,
                0);
            (*cpu_fprintf)(f, "  feature_ecx %08x (%s)\n", def->ext_features,
                buf);
            listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name,
                0);
            (*cpu_fprintf)(f, "  extfeature_edx %08x (%s)\n",
                def->ext2_features, buf);
            listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name,
                0);
            (*cpu_fprintf)(f, "  extfeature_ecx %08x (%s)\n",
                def->ext3_features, buf);
            (*cpu_fprintf)(f, "\n");
        }
    }
1137 1138 1139
    if (kvm_enabled()) {
        (*cpu_fprintf)(f, "x86 %16s\n", "[host]");
    }
1140 1141
}

1142
CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
{
    CpuDefinitionInfoList *cpu_list = NULL;
    x86_def_t *def;

    for (def = x86_defs; def; def = def->next) {
        CpuDefinitionInfoList *entry;
        CpuDefinitionInfo *info;

        info = g_malloc0(sizeof(*info));
        info->name = g_strdup(def->name);

        entry = g_malloc0(sizeof(*entry));
        entry->value = info;
        entry->next = cpu_list;
        cpu_list = entry;
    }

    return cpu_list;
}

1163
int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
1164
{
1165
    CPUX86State *env = &cpu->env;
1166
    x86_def_t def1, *def = &def1;
1167
    Error *error = NULL;
1168

1169 1170
    memset(def, 0, sizeof(*def));

1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
    if (cpu_x86_find_by_name(def, cpu_model) < 0)
        return -1;
    if (def->vendor1) {
        env->cpuid_vendor1 = def->vendor1;
        env->cpuid_vendor2 = def->vendor2;
        env->cpuid_vendor3 = def->vendor3;
    } else {
        env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
        env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
        env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
    }
    env->cpuid_vendor_override = def->vendor_override;
1183
    object_property_set_int(OBJECT(cpu), def->level, "level", &error);
1184
    object_property_set_int(OBJECT(cpu), def->family, "family", &error);
1185
    object_property_set_int(OBJECT(cpu), def->model, "model", &error);
1186
    object_property_set_int(OBJECT(cpu), def->stepping, "stepping", &error);
1187 1188 1189
    env->cpuid_features = def->features;
    env->cpuid_ext_features = def->ext_features;
    env->cpuid_ext2_features = def->ext2_features;
1190
    env->cpuid_ext3_features = def->ext3_features;
1191
    object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", &error);
1192
    env->cpuid_kvm_features = def->kvm_features;
Joerg Roedel's avatar
Joerg Roedel committed
1193
    env->cpuid_svm_features = def->svm_features;
1194
    env->cpuid_ext4_features = def->ext4_features;
1195
    env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features;
1196
    env->cpuid_xlevel2 = def->xlevel2;
1197 1198
    object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000,
                            "tsc-frequency", &error);
1199 1200 1201 1202 1203 1204 1205 1206 1207
    if (!kvm_enabled()) {
        env->cpuid_features &= TCG_FEATURES;
        env->cpuid_ext_features &= TCG_EXT_FEATURES;
        env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
#ifdef TARGET_X86_64
            | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
#endif
            );
        env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
Joerg Roedel's avatar
Joerg Roedel committed
1208
        env->cpuid_svm_features &= TCG_SVM_FEATURES;
1209
    }
1210
    object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error);
1211 1212 1213 1214
    if (error_is_set(&error)) {
        error_free(error);
        return -1;
    }
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
    return 0;
}

#if !defined(CONFIG_USER_ONLY)
/* copy vendor id string to 32 bit register, nul pad as needed
 */
static void cpyid(const char *s, uint32_t *id)
{
    char *d = (char *)id;
    char i;

    for (i = sizeof (*id); i--; )
        *d++ = *s ? *s++ : '\0';
}

/* interpret radix and convert from string to arbitrary scalar,
 * otherwise flag failure
 */
#define setscalar(pval, str, perr)                      \
{                                                       \
    char *pend;                                         \
    unsigned long ul;                                   \
                                                        \
    ul = strtoul(str, &pend, 0);                        \
    *str && !*pend ? (*pval = ul) : (*perr = 1);        \
}

/* map cpuid options to feature bits, otherwise return failure
 * (option tags in *str are delimited by whitespace)
 */
static void setfeatures(uint32_t *pval, const char *str,
    const char **featureset, int *perr)
{
    const char *p, *q;

    for (q = p = str; *p || *q; q = p) {
        while (iswhite(*p))
            q = ++p;
        while (*p && !iswhite(*p))
            ++p;
        if (!*q && !*p)
            return;
        if (!lookup_feature(pval, q, p, featureset)) {
            fprintf(stderr, "error: feature \"%.*s\" not available in set\n",
                (int)(p - q), q);
            *perr = 1;
            return;
        }
    }
}

/* map config file options to x86_def_t form
 */
static int cpudef_setfield(const char *name, const char *str, void *opaque)
{
    x86_def_t *def = opaque;
    int err = 0;

    if (!strcmp(name, "name")) {
1274
        g_free((void *)def->name);
1275
        def->name = g_strdup(str);
1276 1277 1278 1279 1280