X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=target%2Fi386%2Fcpu.c;h=0cf8e545c6faafb2f22ee1d94ac9162421eb727a;hb=0788a56bd1ae3ea4e118beb4aeb071a181791184;hp=aa3a1f3a4ff37087904ec0b1e77a65dc9bb5cf16;hpb=96f75b59b6595c305c79181d7a1b6423aec5de06;p=mirror_qemu.git diff --git a/target/i386/cpu.c b/target/i386/cpu.c index aa3a1f3a4f..0cf8e545c6 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -21,6 +21,7 @@ #include "qemu/units.h" #include "qemu/cutils.h" #include "qemu/bitops.h" +#include "qemu/qemu-print.h" #include "cpu.h" #include "exec/exec-all.h" @@ -31,21 +32,23 @@ #include "sev_i386.h" #include "qemu/error-report.h" +#include "qemu/module.h" #include "qemu/option.h" #include "qemu/config-file.h" #include "qapi/error.h" -#include "qapi/qapi-visit-misc.h" +#include "qapi/qapi-visit-machine.h" #include "qapi/qapi-visit-run-state.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" #include "qapi/visitor.h" #include "qom/qom-qobject.h" #include "sysemu/arch_init.h" -#include "qapi/qapi-commands-target.h" +#include "qapi/qapi-commands-machine-target.h" #include "standard-headers/asm-x86/kvm_para.h" #include "sysemu/sysemu.h" +#include "sysemu/tcg.h" #include "hw/qdev-properties.h" #include "hw/i386/topology.h" #ifndef CONFIG_USER_ONLY @@ -53,6 +56,7 @@ #include "hw/hw.h" #include "hw/xen/xen.h" #include "hw/i386/apic_internal.h" +#include "hw/boards.h" #endif #include "disas/capstone.h" @@ -729,13 +733,14 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | \ CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_POPCNT | \ CPUID_EXT_XSAVE | /* CPUID_EXT_OSXSAVE is dynamic */ \ - CPUID_EXT_MOVBE | CPUID_EXT_AES | CPUID_EXT_HYPERVISOR) + CPUID_EXT_MOVBE | CPUID_EXT_AES | CPUID_EXT_HYPERVISOR | \ + CPUID_EXT_RDRAND) /* missing: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_SMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_CID, CPUID_EXT_FMA, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_PCID, CPUID_EXT_DCA, CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_AVX, - CPUID_EXT_F16C, CPUID_EXT_RDRAND */ + CPUID_EXT_F16C */ #ifdef TARGET_X86_64 #define TCG_EXT2_X86_64_FEATURES (CPUID_EXT2_SYSCALL | CPUID_EXT2_LM) @@ -1076,12 +1081,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .feat_names = { NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, "md-clear", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "spec-ctrl", "stibp", - NULL, "arch-capabilities", NULL, "ssbd", + NULL, "arch-capabilities", "core-capability", "ssbd", }, .cpuid = { .eax = 7, @@ -1089,7 +1094,6 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .reg = R_EDX, }, .tcg_features = TCG_7_0_EDX_FEATURES, - .unmigratable_flags = CPUID_7_0_EDX_ARCH_CAPABILITIES, }, [FEAT_8000_0007_EDX] = { .type = CPUID_FEATURE_WORD, @@ -1184,7 +1188,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .type = MSR_FEATURE_WORD, .feat_names = { "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", - "ssb-no", NULL, NULL, NULL, + "ssb-no", "mds-no", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -1200,6 +1204,26 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { } }, }, + [FEAT_CORE_CAPABILITY] = { + .type = MSR_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, + NULL, "split-lock-detect", NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .msr = { + .index = MSR_IA32_CORE_CAPABILITY, + .cpuid_dep = { + FEAT_7_0_EDX, + CPUID_7_0_EDX_CORE_CAPABILITY, + }, + }, + }, }; typedef struct X86RegisterInfo32 { @@ -1409,7 +1433,18 @@ static char *x86_cpu_class_get_model_name(X86CPUClass *cc) strlen(class_name) - strlen(X86_CPU_TYPE_SUFFIX)); } -struct X86CPUDefinition { +typedef struct PropValue { + const char *prop, *value; +} PropValue; + +typedef struct X86CPUVersionDefinition { + X86CPUVersion version; + const char *alias; + PropValue *props; +} X86CPUVersionDefinition; + +/* Base definition for a CPU model */ +typedef struct X86CPUDefinition { const char *name; uint32_t level; uint32_t xlevel; @@ -1421,8 +1456,46 @@ struct X86CPUDefinition { FeatureWordArray features; const char *model_id; CPUCaches *cache_info; + /* + * Definitions for alternative versions of CPU model. + * List is terminated by item with version == 0. + * If NULL, version 1 will be registered automatically. + */ + const X86CPUVersionDefinition *versions; +} X86CPUDefinition; + +/* Reference to a specific CPU model version */ +struct X86CPUModel { + /* Base CPU definition */ + X86CPUDefinition *cpudef; + /* CPU model version */ + X86CPUVersion version; + /* + * If true, this is an alias CPU model. + * This matters only for "-cpu help" and query-cpu-definitions + */ + bool is_alias; }; +/* Get full model name for CPU version */ +static char *x86_cpu_versioned_model_name(X86CPUDefinition *cpudef, + X86CPUVersion version) +{ + assert(version > 0); + return g_strdup_printf("%s-v%d", cpudef->name, (int)version); +} + +static const X86CPUVersionDefinition *x86_cpu_def_get_versions(X86CPUDefinition *def) +{ + /* When X86CPUDefinition::versions is NULL, we register only v1 */ + static const X86CPUVersionDefinition default_version_list[] = { + { 1 }, + { /* end of list */ } + }; + + return def->versions ?: default_version_list; +} + static CPUCaches epyc_cache_info = { .l1d_cache = &(CPUCacheInfo) { .type = DATA_CACHE, @@ -1784,31 +1857,20 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_EXT3_LAHF_LM, .xlevel = 0x80000008, .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", - }, - { - .name = "Nehalem-IBRS", - .level = 11, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 26, - .stepping = 3, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | - CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, - .xlevel = 0x80000008, - .model_id = "Intel Core i7 9xx (Nehalem Core i7, IBRS update)", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .alias = "Nehalem-IBRS", + .props = (PropValue[]) { + { "spec-ctrl", "on" }, + { "model-id", + "Intel Core i7 9xx (Nehalem Core i7, IBRS update)" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, { .name = "Westmere", @@ -1835,34 +1897,20 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_6_EAX_ARAT, .xlevel = 0x80000008, .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", - }, - { - .name = "Westmere-IBRS", - .level = 11, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 44, - .stepping = 1, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Westmere E56xx/L56xx/X56xx (IBRS update)", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .alias = "Westmere-IBRS", + .props = (PropValue[]) { + { "spec-ctrl", "on" }, + { "model-id", + "Westmere E56xx/L56xx/X56xx (IBRS update)" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, { .name = "SandyBridge", @@ -1894,39 +1942,20 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_6_EAX_ARAT, .xlevel = 0x80000008, .model_id = "Intel Xeon E312xx (Sandy Bridge)", - }, - { - .name = "SandyBridge-IBRS", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 42, - .stepping = 1, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT | - CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | - CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | - CPUID_EXT_SSE3, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Xeon E312xx (Sandy Bridge, IBRS update)", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .alias = "SandyBridge-IBRS", + .props = (PropValue[]) { + { "spec-ctrl", "on" }, + { "model-id", + "Intel Xeon E312xx (Sandy Bridge, IBRS update)" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, { .name = "IvyBridge", @@ -1961,116 +1990,20 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_6_EAX_ARAT, .xlevel = 0x80000008, .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge)", - }, - { - .name = "IvyBridge-IBRS", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 58, - .stepping = 9, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT | - CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | - CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | - CPUID_EXT_SSE3 | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_ERMS, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS)", - }, - { - .name = "Haswell-noTSX", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 60, - .stepping = 1, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | - CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID, - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Haswell, no TSX)", - }, - { - .name = "Haswell-noTSX-IBRS", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 60, - .stepping = 1, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | - CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID, - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Haswell, no TSX, IBRS)", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .alias = "IvyBridge-IBRS", + .props = (PropValue[]) { + { "spec-ctrl", "on" }, + { "model-id", + "Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS)" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, { .name = "Haswell", @@ -2108,123 +2041,52 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_6_EAX_ARAT, .xlevel = 0x80000008, .model_id = "Intel Core Processor (Haswell)", - }, - { - .name = "Haswell-IBRS", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 60, - .stepping = 4, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | - CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | - CPUID_7_0_EBX_RTM, - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Haswell, IBRS)", - }, - { - .name = "Broadwell-noTSX", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 61, - .stepping = 2, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | - CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | - CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | - CPUID_7_0_EBX_SMAP, - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Broadwell, no TSX)", - }, - { - .name = "Broadwell-noTSX-IBRS", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 61, - .stepping = 2, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | - CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | - CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | - CPUID_7_0_EBX_SMAP, - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Broadwell, no TSX, IBRS)", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .alias = "Haswell-noTSX", + .props = (PropValue[]) { + { "hle", "off" }, + { "rtm", "off" }, + { "stepping", "1" }, + { "model-id", "Intel Core Processor (Haswell, no TSX)", }, + { /* end of list */ } + }, + }, + { + .version = 3, + .alias = "Haswell-IBRS", + .props = (PropValue[]) { + /* Restore TSX features removed by -v2 above */ + { "hle", "on" }, + { "rtm", "on" }, + /* + * Haswell and Haswell-IBRS had stepping=4 in + * QEMU 4.0 and older + */ + { "stepping", "4" }, + { "spec-ctrl", "on" }, + { "model-id", + "Intel Core Processor (Haswell, IBRS)" }, + { /* end of list */ } + } + }, + { + .version = 4, + .alias = "Haswell-noTSX-IBRS", + .props = (PropValue[]) { + { "hle", "off" }, + { "rtm", "off" }, + /* spec-ctrl was already enabled by -v3 above */ + { "stepping", "1" }, + { "model-id", + "Intel Core Processor (Haswell, no TSX, IBRS)" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, { .name = "Broadwell", @@ -2258,151 +2120,58 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP, .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Broadwell)", - }, - { - .name = "Broadwell-IBRS", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 61, - .stepping = 2, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | - CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | - CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | - CPUID_7_0_EBX_SMAP, - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Broadwell, IBRS)", - }, - { - .name = "Skylake-Client", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 94, - .stepping = 3, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | - CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | - CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | - CPUID_7_0_EBX_SMAP, - /* Missing: XSAVES (not supported by some Linux versions, - * including v4.1 to v4.12). - * KVM doesn't yet expose any XSAVES state save component, - * and the only one defined in Skylake (processor tracing) - * probably will block migration anyway. - */ - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | - CPUID_XSAVE_XGETBV1, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Skylake)", - }, - { - .name = "Skylake-Client-IBRS", - .level = 0xd, - .vendor = CPUID_VENDOR_INTEL, - .family = 6, - .model = 94, - .stepping = 3, - .features[FEAT_1_EDX] = - CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | - CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | - CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | - CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | - CPUID_DE | CPUID_FP87, - .features[FEAT_1_ECX] = - CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | - CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | - CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | - CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | - CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | - CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | - CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, - .features[FEAT_7_0_EBX] = - CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | - CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | - CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | - CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | - CPUID_7_0_EBX_SMAP, - /* Missing: XSAVES (not supported by some Linux versions, - * including v4.1 to v4.12). - * KVM doesn't yet expose any XSAVES state save component, - * and the only one defined in Skylake (processor tracing) - * probably will block migration anyway. - */ - .features[FEAT_XSAVE] = - CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | - CPUID_XSAVE_XGETBV1, + CPUID_XSAVE_XSAVEOPT, .features[FEAT_6_EAX] = CPUID_6_EAX_ARAT, .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Skylake, IBRS)", + .model_id = "Intel Core Processor (Broadwell)", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .alias = "Broadwell-noTSX", + .props = (PropValue[]) { + { "hle", "off" }, + { "rtm", "off" }, + { "model-id", "Intel Core Processor (Broadwell, no TSX)", }, + { /* end of list */ } + }, + }, + { + .version = 3, + .alias = "Broadwell-IBRS", + .props = (PropValue[]) { + /* Restore TSX features removed by -v2 above */ + { "hle", "on" }, + { "rtm", "on" }, + { "spec-ctrl", "on" }, + { "model-id", + "Intel Core Processor (Broadwell, IBRS)" }, + { /* end of list */ } + } + }, + { + .version = 4, + .alias = "Broadwell-noTSX-IBRS", + .props = (PropValue[]) { + { "hle", "off" }, + { "rtm", "off" }, + /* spec-ctrl was already enabled by -v3 above */ + { "model-id", + "Intel Core Processor (Broadwell, no TSX, IBRS)" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, { - .name = "Skylake-Server", + .name = "Skylake-Client", .level = 0xd, .vendor = CPUID_VENDOR_INTEL, .family = 6, - .model = 85, - .stepping = 4, + .model = 94, + .stepping = 3, .features[FEAT_1_EDX] = CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | @@ -2417,8 +2186,8 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_LM | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP | - CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | + CPUID_EXT2_SYSCALL, .features[FEAT_8000_0001_ECX] = CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, .features[FEAT_7_0_EBX] = @@ -2426,12 +2195,7 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | - CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB | - CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | - CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | - CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, - .features[FEAT_7_0_ECX] = - CPUID_7_0_ECX_PKU, + CPUID_7_0_EBX_SMAP, /* Missing: XSAVES (not supported by some Linux versions, * including v4.1 to v4.12). * KVM doesn't yet expose any XSAVES state save component, @@ -2444,10 +2208,24 @@ static X86CPUDefinition builtin_x86_defs[] = { .features[FEAT_6_EAX] = CPUID_6_EAX_ARAT, .xlevel = 0x80000008, - .model_id = "Intel Xeon Processor (Skylake)", + .model_id = "Intel Core Processor (Skylake)", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .alias = "Skylake-Client-IBRS", + .props = (PropValue[]) { + { "spec-ctrl", "on" }, + { "model-id", + "Intel Core Processor (Skylake, IBRS)" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, { - .name = "Skylake-Server-IBRS", + .name = "Skylake-Server", .level = 0xd, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -2471,8 +2249,6 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, .features[FEAT_8000_0001_ECX] = CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, - .features[FEAT_7_0_EDX] = - CPUID_7_0_EDX_SPEC_CTRL, .features[FEAT_7_0_EBX] = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | @@ -2481,7 +2257,7 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | - CPUID_7_0_EBX_AVX512VL, + CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, .features[FEAT_7_0_ECX] = CPUID_7_0_ECX_PKU, /* Missing: XSAVES (not supported by some Linux versions, @@ -2496,7 +2272,24 @@ static X86CPUDefinition builtin_x86_defs[] = { .features[FEAT_6_EAX] = CPUID_6_EAX_ARAT, .xlevel = 0x80000008, - .model_id = "Intel Xeon Processor (Skylake, IBRS)", + .model_id = "Intel Xeon Processor (Skylake)", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .alias = "Skylake-Server-IBRS", + .props = (PropValue[]) { + /* clflushopt was not added to Skylake-Server-IBRS */ + /* TODO: add -v3 including clflushopt */ + { "clflushopt", "off" }, + { "spec-ctrl", "on" }, + { "model-id", + "Intel Xeon Processor (Skylake, IBRS)" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, { .name = "Cascadelake-Server", @@ -2533,7 +2326,7 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, .features[FEAT_7_0_ECX] = - CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | + CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_AVX512VNNI, .features[FEAT_7_0_EDX] = CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, @@ -2586,7 +2379,7 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_7_0_EBX_SMAP, .features[FEAT_7_0_ECX] = CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | - CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | + CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | CPUID_7_0_ECX_AVX512_VPOPCNTDQ, @@ -2644,7 +2437,7 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, .features[FEAT_7_0_ECX] = CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | - CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | + CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57, @@ -2664,6 +2457,77 @@ static X86CPUDefinition builtin_x86_defs[] = { .xlevel = 0x80000008, .model_id = "Intel Xeon Processor (Icelake)", }, + { + .name = "SnowRidge-Server", + .level = 27, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, + .model = 134, + .stepping = 1, + .features[FEAT_1_EDX] = + /* missing: CPUID_PN CPUID_IA64 */ + /* missing: CPUID_DTS, CPUID_HT, CPUID_TM, CPUID_PBE */ + CPUID_FP87 | CPUID_VME | CPUID_DE | 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_MMX | + CPUID_FXSR | CPUID_SSE | CPUID_SSE2, + .features[FEAT_1_ECX] = + CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_MONITOR | + CPUID_EXT_VMX | + CPUID_EXT_SSSE3 | + CPUID_EXT_CX16 | + CPUID_EXT_SSE41 | + CPUID_EXT_SSE42 | CPUID_EXT_X2APIC | CPUID_EXT_MOVBE | + CPUID_EXT_POPCNT | + CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_AES | CPUID_EXT_XSAVE | + CPUID_EXT_RDRAND, + .features[FEAT_8000_0001_EDX] = + CPUID_EXT2_SYSCALL | + CPUID_EXT2_NX | + CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP | + CPUID_EXT2_LM, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM | + CPUID_EXT3_3DNOWPREFETCH, + .features[FEAT_7_0_EBX] = + CPUID_7_0_EBX_FSGSBASE | + CPUID_7_0_EBX_SMEP | + CPUID_7_0_EBX_ERMS | + CPUID_7_0_EBX_MPX | /* missing bits 13, 15 */ + CPUID_7_0_EBX_RDSEED | + CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT | + CPUID_7_0_EBX_CLWB | + CPUID_7_0_EBX_SHA_NI, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_UMIP | + /* missing bit 5 */ + CPUID_7_0_ECX_GFNI | + CPUID_7_0_ECX_MOVDIRI | CPUID_7_0_ECX_CLDEMOTE | + CPUID_7_0_ECX_MOVDIR64B, + .features[FEAT_7_0_EDX] = + CPUID_7_0_EDX_SPEC_CTRL | + CPUID_7_0_EDX_ARCH_CAPABILITIES | CPUID_7_0_EDX_SPEC_CTRL_SSBD | + CPUID_7_0_EDX_CORE_CAPABILITY, + .features[FEAT_CORE_CAPABILITY] = + MSR_CORE_CAP_SPLIT_LOCK_DETECT, + /* + * Missing: XSAVES (not supported by some Linux versions, + * including v4.1 to v4.12). + * KVM doesn't yet expose any XSAVES state save component, + * and the only one defined in Skylake (processor tracing) + * probably will block migration anyway. + */ + .features[FEAT_XSAVE] = + CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, + .xlevel = 0x80000008, + .model_id = "Intel Atom Processor (SnowRidge)", + }, { .name = "KnightsMill", .level = 0xd, @@ -2884,14 +2748,28 @@ static X86CPUDefinition builtin_x86_defs[] = { .xlevel = 0x8000001E, .model_id = "AMD EPYC Processor", .cache_info = &epyc_cache_info, + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, + { + .version = 2, + .alias = "EPYC-IBPB", + .props = (PropValue[]) { + { "ibpb", "on" }, + { "model-id", + "AMD EPYC Processor (with IBPB)" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } }, { - .name = "EPYC-IBPB", + .name = "Dhyana", .level = 0xd, - .vendor = CPUID_VENDOR_AMD, - .family = 23, - .model = 1, - .stepping = 2, + .vendor = CPUID_VENDOR_HYGON, + .family = 24, + .model = 0, + .stepping = 1, .features[FEAT_1_EDX] = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | CPUID_PGE | @@ -2900,10 +2778,10 @@ static X86CPUDefinition builtin_x86_defs[] = { CPUID_VME | CPUID_FP87, .features[FEAT_1_ECX] = CPUID_EXT_RDRAND | CPUID_EXT_F16C | CPUID_EXT_AVX | - CPUID_EXT_XSAVE | CPUID_EXT_AES | CPUID_EXT_POPCNT | + CPUID_EXT_XSAVE | CPUID_EXT_POPCNT | CPUID_EXT_MOVBE | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA | CPUID_EXT_SSSE3 | - CPUID_EXT_MONITOR | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3, + CPUID_EXT_MONITOR | CPUID_EXT_SSE3, .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_PDPE1GB | CPUID_EXT2_FFXSR | CPUID_EXT2_MMXEXT | CPUID_EXT2_NX | @@ -2918,9 +2796,9 @@ static X86CPUDefinition builtin_x86_defs[] = { .features[FEAT_7_0_EBX] = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED | - CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT | - CPUID_7_0_EBX_SHA_NI, - /* Missing: XSAVES (not supported by some Linux versions, + CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT, + /* + * Missing: XSAVES (not supported by some Linux versions, * including v4.1 to v4.12). * KVM doesn't yet expose any XSAVES state save component. */ @@ -2932,15 +2810,11 @@ static X86CPUDefinition builtin_x86_defs[] = { .features[FEAT_SVM] = CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE, .xlevel = 0x8000001E, - .model_id = "AMD EPYC Processor (with IBPB)", + .model_id = "Hygon Dhyana Processor", .cache_info = &epyc_cache_info, }, }; -typedef struct PropValue { - const char *prop, *value; -} PropValue; - /* KVM-specific features that are automatically added/removed * from all CPU models when KVM is enabled. */ @@ -2966,6 +2840,40 @@ static PropValue tcg_default_props[] = { }; +X86CPUVersion default_cpu_version = CPU_VERSION_LATEST; + +void x86_cpu_set_default_version(X86CPUVersion version) +{ + /* Translating CPU_VERSION_AUTO to CPU_VERSION_AUTO doesn't make sense */ + assert(version != CPU_VERSION_AUTO); + default_cpu_version = version; +} + +static X86CPUVersion x86_cpu_model_last_version(const X86CPUModel *model) +{ + int v = 0; + const X86CPUVersionDefinition *vdef = + x86_cpu_def_get_versions(model->cpudef); + while (vdef->version) { + v = vdef->version; + vdef++; + } + return v; +} + +/* Return the actual version being used for a specific CPU model */ +static X86CPUVersion x86_cpu_model_resolve_version(const X86CPUModel *model) +{ + X86CPUVersion v = model->version; + if (v == CPU_VERSION_AUTO) { + v = default_cpu_version; + } + if (v == CPU_VERSION_LATEST) { + return x86_cpu_model_last_version(model); + } + return v; +} + void x86_cpu_change_kvm_default(const char *prop, const char *value) { PropValue *pv; @@ -3043,8 +2951,6 @@ static void max_x86_cpu_class_init(ObjectClass *oc, void *data) dc->props = max_x86_cpu_properties; } -static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp); - static void max_x86_cpu_initfn(Object *obj) { X86CPU *cpu = X86_CPU(obj); @@ -3060,14 +2966,8 @@ static void max_x86_cpu_initfn(Object *obj) char vendor[CPUID_VENDOR_SZ + 1] = { 0 }; char model_id[CPUID_MODEL_ID_SZ + 1] = { 0 }; int family, model, stepping; - X86CPUDefinition host_cpudef = { }; - uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; - - host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_vendor_words2str(host_cpudef.vendor, ebx, edx, ecx); host_vendor_fms(vendor, &family, &model, &stepping); - cpu_x86_fill_model_id(model_id); object_property_set_str(OBJECT(cpu), vendor, "vendor", &error_abort); @@ -3444,46 +3344,6 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, visit_type_X86CPUFeatureWordInfoList(v, "feature-words", &list, errp); } -static void x86_get_hv_spinlocks(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - X86CPU *cpu = X86_CPU(obj); - int64_t value = cpu->hyperv_spinlock_attempts; - - visit_type_int(v, name, &value, errp); -} - -static void x86_set_hv_spinlocks(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - const int64_t min = 0xFFF; - const int64_t max = UINT_MAX; - X86CPU *cpu = X86_CPU(obj); - Error *err = NULL; - int64_t value; - - visit_type_int(v, name, &value, &err); - if (err) { - error_propagate(errp, err); - return; - } - - if (value < min || value > max) { - error_setg(errp, "Property %s.%s doesn't take value %" PRId64 - " (minimum: %" PRId64 ", maximum: %" PRId64 ")", - object_get_typename(obj), name ? name : "null", - value, min, max); - return; - } - cpu->hyperv_spinlock_attempts = value; -} - -static const PropertyInfo qdev_prop_spinlocks = { - .name = "int", - .get = x86_get_hv_spinlocks, - .set = x86_set_hv_spinlocks, -}; - /* Convert all '_' in a feature string option name to '-', to make feature * name conform to QOM property naming rule, which uses '-' instead of '_'. */ @@ -3620,6 +3480,38 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features, static void x86_cpu_expand_features(X86CPU *cpu, Error **errp); static int x86_cpu_filter_features(X86CPU *cpu); +/* Build a list with the name of all features on a feature word array */ +static void x86_cpu_list_feature_names(FeatureWordArray features, + strList **feat_names) +{ + FeatureWord w; + strList **next = feat_names; + + for (w = 0; w < FEATURE_WORDS; w++) { + uint32_t filtered = features[w]; + int i; + for (i = 0; i < 32; i++) { + if (filtered & (1UL << i)) { + strList *new = g_new0(strList, 1); + new->value = g_strdup(x86_cpu_feature_name(w, i)); + *next = new; + next = &new->next; + } + } + } +} + +static void x86_cpu_get_unavailable_features(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + X86CPU *xc = X86_CPU(obj); + strList *result = NULL; + + x86_cpu_list_feature_names(xc->filtered_features, &result); + visit_type_strList(v, "unavailable-features", &result, errp); +} + /* Check for missing features that may prevent the CPU class from * running using the current machine and accelerator. */ @@ -3627,7 +3519,6 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, strList **missing_feats) { X86CPU *xc; - FeatureWord w; Error *err = NULL; strList **next = missing_feats; @@ -3654,25 +3545,14 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, x86_cpu_filter_features(xc); - for (w = 0; w < FEATURE_WORDS; w++) { - uint32_t filtered = xc->filtered_features[w]; - int i; - for (i = 0; i < 32; i++) { - if (filtered & (1UL << i)) { - strList *new = g_new0(strList, 1); - new->value = g_strdup(x86_cpu_feature_name(w, i)); - *next = new; - next = &new->next; - } - } - } + x86_cpu_list_feature_names(xc->filtered_features, next); object_unref(OBJECT(xc)); } /* Print all cpuid feature names in featureset */ -static void listflags(FILE *f, fprintf_function print, GList *features) +static void listflags(GList *features) { size_t len = 0; GList *tmp; @@ -3680,13 +3560,13 @@ static void listflags(FILE *f, fprintf_function print, GList *features) for (tmp = features; tmp; tmp = tmp->next) { const char *name = tmp->data; if ((len + strlen(name) + 1) >= 75) { - print(f, "\n"); + qemu_printf("\n"); len = 0; } - print(f, "%s%s", len == 0 ? " " : " ", name); + qemu_printf("%s%s", len == 0 ? " " : " ", name); len += strlen(name) + 1; } - print(f, "\n"); + qemu_printf("\n"); } /* Sort alphabetically by type name, respecting X86CPUClass::ordering. */ @@ -3718,36 +3598,63 @@ static GSList *get_sorted_cpu_model_list(void) return list; } +static char *x86_cpu_class_get_model_id(X86CPUClass *xc) +{ + Object *obj = object_new(object_class_get_name(OBJECT_CLASS(xc))); + char *r = object_property_get_str(obj, "model-id", &error_abort); + object_unref(obj); + return r; +} + +static char *x86_cpu_class_get_alias_of(X86CPUClass *cc) +{ + X86CPUVersion version; + + if (!cc->model || !cc->model->is_alias) { + return NULL; + } + version = x86_cpu_model_resolve_version(cc->model); + if (version <= 0) { + return NULL; + } + return x86_cpu_versioned_model_name(cc->model->cpudef, version); +} + static void x86_cpu_list_entry(gpointer data, gpointer user_data) { ObjectClass *oc = data; X86CPUClass *cc = X86_CPU_CLASS(oc); - CPUListState *s = user_data; char *name = x86_cpu_class_get_model_name(cc); - const char *desc = cc->model_description; - if (!desc && cc->cpu_def) { - desc = cc->cpu_def->model_id; + char *desc = g_strdup(cc->model_description); + char *alias_of = x86_cpu_class_get_alias_of(cc); + + if (!desc && alias_of) { + if (cc->model && cc->model->version == CPU_VERSION_AUTO) { + desc = g_strdup("(alias configured by machine type)"); + } else { + desc = g_strdup_printf("(alias of %s)", alias_of); + } + } + if (!desc) { + desc = x86_cpu_class_get_model_id(cc); } - (*s->cpu_fprintf)(s->file, "x86 %-20s %-48s\n", - name, desc); + qemu_printf("x86 %-20s %-48s\n", name, desc); g_free(name); + g_free(desc); + g_free(alias_of); } /* list available CPU models and flags */ -void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) +void x86_cpu_list(void) { int i, j; - CPUListState s = { - .file = f, - .cpu_fprintf = cpu_fprintf, - }; GSList *list; GList *names = NULL; - (*cpu_fprintf)(f, "Available CPUs:\n"); + qemu_printf("Available CPUs:\n"); list = get_sorted_cpu_model_list(); - g_slist_foreach(list, x86_cpu_list_entry, &s); + g_slist_foreach(list, x86_cpu_list_entry, NULL); g_slist_free(list); names = NULL; @@ -3762,9 +3669,9 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) names = g_list_sort(names, (GCompareFunc)strcmp); - (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n"); - listflags(f, cpu_fprintf, names); - (*cpu_fprintf)(f, "\n"); + qemu_printf("\nRecognized CPUID flags:\n"); + listflags(names); + qemu_printf("\n"); g_list_free(names); } @@ -3784,6 +3691,14 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data) info->migration_safe = cc->migration_safe; info->has_migration_safe = true; info->q_static = cc->static_model; + /* + * Old machine types won't report aliases, so that alias translation + * doesn't break compatibility with previous QEMU versions. + */ + if (default_cpu_version != CPU_VERSION_LEGACY) { + info->alias_of = x86_cpu_class_get_alias_of(cc); + info->has_alias_of = !!info->alias_of; + } entry = g_malloc0(sizeof(*entry)); entry->value = info; @@ -3791,7 +3706,7 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data) *cpu_list = entry; } -CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) +CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) { CpuDefinitionInfoList *cpu_list = NULL; GSList *list = get_sorted_cpu_model_list(); @@ -3857,10 +3772,40 @@ static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props) } } +/* Apply properties for the CPU model version specified in model */ +static void x86_cpu_apply_version_props(X86CPU *cpu, X86CPUModel *model) +{ + const X86CPUVersionDefinition *vdef; + X86CPUVersion version = x86_cpu_model_resolve_version(model); + + if (version == CPU_VERSION_LEGACY) { + return; + } + + for (vdef = x86_cpu_def_get_versions(model->cpudef); vdef->version; vdef++) { + PropValue *p; + + for (p = vdef->props; p && p->prop; p++) { + object_property_parse(OBJECT(cpu), p->value, p->prop, + &error_abort); + } + + if (vdef->version == version) { + break; + } + } + + /* + * If we reached the end of the list, version number was invalid + */ + assert(vdef->version == version); +} + /* Load data from X86CPUDefinition into a X86CPU object */ -static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp) +static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model, Error **errp) { + X86CPUDefinition *def = model->cpudef; CPUX86State *env = &cpu->env; const char *vendor; char host_vendor[CPUID_VENDOR_SZ + 1]; @@ -3917,11 +3862,12 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp) object_property_set_str(OBJECT(cpu), vendor, "vendor", errp); + x86_cpu_apply_version_props(cpu, model); } #ifndef CONFIG_USER_ONLY /* Return a QDict containing keys for all properties that can be included - * in static expansion of CPU models. All properties set by x86_cpu_load_def() + * in static expansion of CPU models. All properties set by x86_cpu_load_model() * must be included in the dictionary. */ static QDict *x86_cpu_static_props(void) @@ -4135,23 +4081,33 @@ static gchar *x86_gdb_arch_name(CPUState *cs) static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data) { - X86CPUDefinition *cpudef = data; + X86CPUModel *model = data; X86CPUClass *xcc = X86_CPU_CLASS(oc); - xcc->cpu_def = cpudef; + xcc->model = model; xcc->migration_safe = true; } -static void x86_register_cpudef_type(X86CPUDefinition *def) +static void x86_register_cpu_model_type(const char *name, X86CPUModel *model) { - char *typename = x86_cpu_type_name(def->name); + char *typename = x86_cpu_type_name(name); TypeInfo ti = { .name = typename, .parent = TYPE_X86_CPU, .class_init = x86_cpu_cpudef_class_init, - .class_data = def, + .class_data = model, }; + type_register(&ti); + g_free(typename); +} + +static void x86_register_cpudef_types(X86CPUDefinition *def) +{ + X86CPUModel *m; + const X86CPUVersionDefinition *vdef; + char *name; + /* AMD aliases are handled at runtime based on CPUID vendor, so * they shouldn't be set on the CPU model table. */ @@ -4159,9 +4115,32 @@ static void x86_register_cpudef_type(X86CPUDefinition *def) /* catch mistakes instead of silently truncating model_id when too long */ assert(def->model_id && strlen(def->model_id) <= 48); + /* Unversioned model: */ + m = g_new0(X86CPUModel, 1); + m->cpudef = def; + m->version = CPU_VERSION_AUTO; + m->is_alias = true; + x86_register_cpu_model_type(def->name, m); + + /* Versioned models: */ + + for (vdef = x86_cpu_def_get_versions(def); vdef->version; vdef++) { + X86CPUModel *m = g_new0(X86CPUModel, 1); + m->cpudef = def; + m->version = vdef->version; + name = x86_cpu_versioned_model_name(def, vdef->version); + x86_register_cpu_model_type(name, m); + g_free(name); + + if (vdef->alias) { + X86CPUModel *am = g_new0(X86CPUModel, 1); + am->cpudef = def; + am->version = vdef->version; + am->is_alias = true; + x86_register_cpu_model_type(vdef->alias, am); + } + } - type_register(&ti); - g_free(typename); } #if !defined(CONFIG_USER_ONLY) @@ -4177,9 +4156,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { - X86CPU *cpu = x86_env_get_cpu(env); - CPUState *cs = CPU(cpu); - uint32_t pkg_offset; + X86CPU *cpu = env_archcpu(env); + CPUState *cs = env_cpu(env); + uint32_t die_offset; uint32_t limit; uint32_t signature[3]; @@ -4268,10 +4247,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, eax, ebx, ecx, edx); break; case 3: /* L3 cache info */ - pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads); + die_offset = apicid_die_offset(env->nr_dies, + cs->nr_cores, cs->nr_threads); if (cpu->enable_l3_cache) { encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache, - (1 << pkg_offset), cs->nr_cores, + (1 << die_offset), cs->nr_cores, eax, ebx, ecx, edx); break; } @@ -4353,12 +4333,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, switch (count) { case 0: - *eax = apicid_core_offset(cs->nr_cores, cs->nr_threads); + *eax = apicid_core_offset(env->nr_dies, + cs->nr_cores, cs->nr_threads); *ebx = cs->nr_threads; *ecx |= CPUID_TOPOLOGY_LEVEL_SMT; break; case 1: - *eax = apicid_pkg_offset(cs->nr_cores, cs->nr_threads); + *eax = apicid_pkg_offset(env->nr_dies, + cs->nr_cores, cs->nr_threads); *ebx = cs->nr_cores * cs->nr_threads; *ecx |= CPUID_TOPOLOGY_LEVEL_CORE; break; @@ -4368,6 +4350,42 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx |= CPUID_TOPOLOGY_LEVEL_INVALID; } + assert(!(*eax & ~0x1f)); + *ebx &= 0xffff; /* The count doesn't need to be reliable. */ + break; + case 0x1F: + /* V2 Extended Topology Enumeration Leaf */ + if (env->nr_dies < 2) { + *eax = *ebx = *ecx = *edx = 0; + break; + } + + *ecx = count & 0xff; + *edx = cpu->apic_id; + switch (count) { + case 0: + *eax = apicid_core_offset(env->nr_dies, cs->nr_cores, + cs->nr_threads); + *ebx = cs->nr_threads; + *ecx |= CPUID_TOPOLOGY_LEVEL_SMT; + break; + case 1: + *eax = apicid_die_offset(env->nr_dies, cs->nr_cores, + cs->nr_threads); + *ebx = cs->nr_cores * cs->nr_threads; + *ecx |= CPUID_TOPOLOGY_LEVEL_CORE; + break; + case 2: + *eax = apicid_pkg_offset(env->nr_dies, cs->nr_cores, + cs->nr_threads); + *ebx = env->nr_dies * cs->nr_cores * cs->nr_threads; + *ecx |= CPUID_TOPOLOGY_LEVEL_DIE; + break; + default: + *eax = 0; + *ebx = 0; + *ecx |= CPUID_TOPOLOGY_LEVEL_INVALID; + } assert(!(*eax & ~0x1f)); *ebx &= 0xffff; /* The count doesn't need to be reliable. */ break; @@ -4547,6 +4565,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 0x8000001D: *eax = 0; + if (cpu->cache_info_passthrough) { + host_cpuid(index, count, eax, ebx, ecx, edx); + break; + } switch (count) { case 0: /* L1 dcache info */ encode_cache_cpuid8000001d(env->cache_info_amd.l1d_cache, cs, @@ -4681,6 +4703,9 @@ static void x86_cpu_reset(CPUState *s) env->pat = 0x0007040600070406ULL; env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT; + if (env->features[FEAT_1_ECX] & CPUID_EXT_MONITOR) { + env->msr_ia32_misc_enable |= MSR_IA32_MISC_ENABLE_MWAIT; + } memset(env->dr, 0, sizeof(env->dr)); env->dr[6] = DR6_FIXED_1; @@ -4725,7 +4750,11 @@ static void x86_cpu_reset(CPUState *s) memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed)); env->interrupt_injected = -1; - env->exception_injected = -1; + env->exception_nr = -1; + env->exception_pending = 0; + env->exception_injected = 0; + env->exception_has_payload = false; + env->exception_payload = 0; env->nmi_injected = false; #if !defined(CONFIG_USER_ONLY) /* We hard-wire the BSP to the first CPU. */ @@ -4937,7 +4966,7 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) * involved in setting up CPUID data are: * * 1) Loading CPU model definition (X86CPUDefinition). This is - * implemented by x86_cpu_load_def() and should be completely + * implemented by x86_cpu_load_model() and should be completely * transparent, as it is done automatically by instance_init. * No code should need to look at X86CPUDefinition structs * outside instance_init. @@ -5031,6 +5060,18 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX); x86_cpu_adjust_feat_level(cpu, FEAT_SVM); x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE); + + /* Intel Processor Trace requires CPUID[0x14] */ + if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) && + kvm_enabled() && cpu->intel_pt_auto_level) { + x86_cpu_adjust_level(cpu, &cpu->env.cpuid_min_level, 0x14); + } + + /* CPU topology with multi-dies support requires CPUID[0x1F] */ + if (env->nr_dies > 1) { + x86_cpu_adjust_level(cpu, &env->cpuid_min_level, 0x1F); + } + /* SVM requires CPUID[0x8000000A] */ if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A); @@ -5075,8 +5116,11 @@ static int x86_cpu_filter_features(X86CPU *cpu) uint32_t host_feat = x86_cpu_get_supported_feature_word(w, false); uint32_t requested_features = env->features[w]; - env->features[w] &= host_feat; - cpu->filtered_features[w] = requested_features & ~env->features[w]; + uint32_t available_features = requested_features & host_feat; + if (!cpu->force_features) { + env->features[w] = available_features; + } + cpu->filtered_features[w] = requested_features & ~available_features; if (cpu->filtered_features[w]) { rv = 1; } @@ -5114,12 +5158,6 @@ static int x86_cpu_filter_features(X86CPU *cpu) return rv; } -#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ - (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ - (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) -#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ - (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ - (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) static void x86_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -5190,15 +5228,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) uint32_t host_phys_bits = x86_host_phys_bits(); static bool warned; - if (cpu->host_phys_bits) { - /* The user asked for us to use the host physical bits */ - cpu->phys_bits = host_phys_bits; - if (cpu->host_phys_bits_limit && - cpu->phys_bits > cpu->host_phys_bits_limit) { - cpu->phys_bits = cpu->host_phys_bits_limit; - } - } - /* Print a warning if the user set it to a value that's not the * host value. */ @@ -5210,6 +5239,15 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) warned = true; } + if (cpu->host_phys_bits) { + /* The user asked for us to use the host physical bits */ + cpu->phys_bits = host_phys_bits; + if (cpu->host_phys_bits_limit && + cpu->phys_bits > cpu->host_phys_bits_limit) { + cpu->phys_bits = cpu->host_phys_bits_limit; + } + } + if (cpu->phys_bits && (cpu->phys_bits > TARGET_PHYS_ADDR_SPACE_BITS || cpu->phys_bits < 32)) { @@ -5250,7 +5288,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) /* Cache information initialization */ if (!cpu->legacy_cache) { - if (!xcc->cpu_def || !xcc->cpu_def->cache_info) { + if (!xcc->model || !xcc->model->cpudef->cache_info) { char *name = x86_cpu_class_get_model_name(xcc); error_setg(errp, "CPU model '%s' doesn't support legacy-cache=off", name); @@ -5258,7 +5296,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) return; } env->cache_info_cpuid2 = env->cache_info_cpuid4 = env->cache_info_amd = - *xcc->cpu_def->cache_info; + *xcc->model->cpudef->cache_info; } else { /* Build legacy cache information */ env->cache_info_cpuid2.l1d_cache = &legacy_l1d_cache; @@ -5285,9 +5323,10 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) } #ifndef CONFIG_USER_ONLY + MachineState *ms = MACHINE(qdev_get_machine()); qemu_register_reset(x86_cpu_machine_reset_cb, cpu); - if (cpu->env.features[FEAT_1_EDX] & CPUID_APIC || smp_cpus > 1) { + if (cpu->env.features[FEAT_1_EDX] & CPUID_APIC || ms->smp.cpus > 1) { x86_cpu_apic_create(cpu, &local_err); if (local_err != NULL) { goto out; @@ -5533,13 +5572,13 @@ static void x86_cpu_get_crash_info_qom(Object *obj, Visitor *v, static void x86_cpu_initfn(Object *obj) { - CPUState *cs = CPU(obj); X86CPU *cpu = X86_CPU(obj); X86CPUClass *xcc = X86_CPU_GET_CLASS(obj); CPUX86State *env = &cpu->env; FeatureWord w; - cs->env_ptr = env; + env->nr_dies = 1; + cpu_set_cpustate_pointers(cpu); object_property_add(obj, "family", "int", x86_cpuid_version_get_family, @@ -5565,12 +5604,19 @@ static void x86_cpu_initfn(Object *obj) object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo", x86_cpu_get_feature_words, NULL, NULL, (void *)cpu->filtered_features, NULL); + /* + * The "unavailable-features" property has the same semantics as + * CpuDefinitionInfo.unavailable-features on the "query-cpu-definitions" + * QMP command: they list the features that would have prevented the + * CPU from running if the "enforce" flag was set. + */ + object_property_add(obj, "unavailable-features", "strList", + x86_cpu_get_unavailable_features, + NULL, NULL, NULL, &error_abort); object_property_add(obj, "crash-information", "GuestPanicInformation", x86_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL); - cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY; - for (w = 0; w < FEATURE_WORDS; w++) { int bitnr; @@ -5609,8 +5655,8 @@ static void x86_cpu_initfn(Object *obj) object_property_add_alias(obj, "sse4_1", obj, "sse4.1", &error_abort); object_property_add_alias(obj, "sse4_2", obj, "sse4.2", &error_abort); - if (xcc->cpu_def) { - x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort); + if (xcc->model) { + x86_cpu_load_model(cpu, xcc->model, &error_abort); } } @@ -5755,32 +5801,55 @@ static Property x86_cpu_properties[] = { DEFINE_PROP_UINT32("apic-id", X86CPU, apic_id, 0), DEFINE_PROP_INT32("thread-id", X86CPU, thread_id, 0), DEFINE_PROP_INT32("core-id", X86CPU, core_id, 0), + DEFINE_PROP_INT32("die-id", X86CPU, die_id, 0), DEFINE_PROP_INT32("socket-id", X86CPU, socket_id, 0), #else DEFINE_PROP_UINT32("apic-id", X86CPU, apic_id, UNASSIGNED_APIC_ID), DEFINE_PROP_INT32("thread-id", X86CPU, thread_id, -1), DEFINE_PROP_INT32("core-id", X86CPU, core_id, -1), + DEFINE_PROP_INT32("die-id", X86CPU, die_id, -1), DEFINE_PROP_INT32("socket-id", X86CPU, socket_id, -1), #endif DEFINE_PROP_INT32("node-id", X86CPU, node_id, CPU_UNSET_NUMA_NODE_ID), DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false), - { .name = "hv-spinlocks", .info = &qdev_prop_spinlocks }, - DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false), - DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false), - DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false), - DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false), - DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false), - DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false), - DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false), - DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false), - DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false), - DEFINE_PROP_BOOL("hv-frequencies", X86CPU, hyperv_frequencies, false), - DEFINE_PROP_BOOL("hv-reenlightenment", X86CPU, hyperv_reenlightenment, false), - DEFINE_PROP_BOOL("hv-tlbflush", X86CPU, hyperv_tlbflush, false), - DEFINE_PROP_BOOL("hv-evmcs", X86CPU, hyperv_evmcs, false), - DEFINE_PROP_BOOL("hv-ipi", X86CPU, hyperv_ipi, false), + + DEFINE_PROP_UINT32("hv-spinlocks", X86CPU, hyperv_spinlock_attempts, + HYPERV_SPINLOCK_NEVER_RETRY), + DEFINE_PROP_BIT64("hv-relaxed", X86CPU, hyperv_features, + HYPERV_FEAT_RELAXED, 0), + DEFINE_PROP_BIT64("hv-vapic", X86CPU, hyperv_features, + HYPERV_FEAT_VAPIC, 0), + DEFINE_PROP_BIT64("hv-time", X86CPU, hyperv_features, + HYPERV_FEAT_TIME, 0), + DEFINE_PROP_BIT64("hv-crash", X86CPU, hyperv_features, + HYPERV_FEAT_CRASH, 0), + DEFINE_PROP_BIT64("hv-reset", X86CPU, hyperv_features, + HYPERV_FEAT_RESET, 0), + DEFINE_PROP_BIT64("hv-vpindex", X86CPU, hyperv_features, + HYPERV_FEAT_VPINDEX, 0), + DEFINE_PROP_BIT64("hv-runtime", X86CPU, hyperv_features, + HYPERV_FEAT_RUNTIME, 0), + DEFINE_PROP_BIT64("hv-synic", X86CPU, hyperv_features, + HYPERV_FEAT_SYNIC, 0), + DEFINE_PROP_BIT64("hv-stimer", X86CPU, hyperv_features, + HYPERV_FEAT_STIMER, 0), + DEFINE_PROP_BIT64("hv-frequencies", X86CPU, hyperv_features, + HYPERV_FEAT_FREQUENCIES, 0), + DEFINE_PROP_BIT64("hv-reenlightenment", X86CPU, hyperv_features, + HYPERV_FEAT_REENLIGHTENMENT, 0), + DEFINE_PROP_BIT64("hv-tlbflush", X86CPU, hyperv_features, + HYPERV_FEAT_TLBFLUSH, 0), + DEFINE_PROP_BIT64("hv-evmcs", X86CPU, hyperv_features, + HYPERV_FEAT_EVMCS, 0), + DEFINE_PROP_BIT64("hv-ipi", X86CPU, hyperv_features, + HYPERV_FEAT_IPI, 0), + DEFINE_PROP_BIT64("hv-stimer-direct", X86CPU, hyperv_features, + HYPERV_FEAT_STIMER_DIRECT, 0), + DEFINE_PROP_BOOL("hv-passthrough", X86CPU, hyperv_passthrough, false), + DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true), DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), + DEFINE_PROP_BOOL("x-force-features", X86CPU, force_features, false), DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0), DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false), @@ -5824,6 +5893,8 @@ static Property x86_cpu_properties[] = { DEFINE_PROP_INT32("x-hv-max-vps", X86CPU, hv_max_vps, -1), DEFINE_PROP_BOOL("x-hv-synic-kvm-only", X86CPU, hyperv_synic_kvm_only, false), + DEFINE_PROP_BOOL("x-intel-pt-auto-level", X86CPU, intel_pt_auto_level, + true), DEFINE_PROP_END_OF_LIST() }; @@ -5858,9 +5929,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->gdb_write_register = x86_cpu_gdb_write_register; cc->get_arch_id = x86_cpu_get_arch_id; cc->get_paging_enabled = x86_cpu_get_paging_enabled; -#ifdef CONFIG_USER_ONLY - cc->handle_mmu_fault = x86_cpu_handle_mmu_fault; -#else +#ifndef CONFIG_USER_ONLY cc->asidx_from_attrs = x86_asidx_from_attrs; cc->get_memory_mapping = x86_cpu_get_memory_mapping; cc->get_phys_page_debug = x86_cpu_get_phys_page_debug; @@ -5885,6 +5954,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->cpu_exec_exit = x86_cpu_exec_exit; #ifdef CONFIG_TCG cc->tcg_initialize = tcg_x86_init; + cc->tlb_fill = x86_cpu_tlb_fill; #endif cc->disas_set_info = x86_disas_set_info; @@ -5925,7 +5995,7 @@ static void x86_cpu_register_types(void) type_register_static(&x86_cpu_type_info); for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) { - x86_register_cpudef_type(&builtin_x86_defs[i]); + x86_register_cpudef_types(&builtin_x86_defs[i]); } type_register_static(&max_x86_cpu_type_info); type_register_static(&x86_base_cpu_type_info);