X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=target%2Fi386%2Fcpu.c;h=62043fee540547287686806ab4acfee8709ab6c9;hb=0b18874bd216f3237740d5cbd64f39cf1e02addf;hp=d6bb57d2108e26166cba6d9a55c0dff9fc559098;hpb=84bdc58c06c889d94dba6cd9f023a39757f7dc41;p=mirror_qemu.git diff --git a/target/i386/cpu.c b/target/i386/cpu.c index d6bb57d210..62043fee54 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, @@ -1183,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, @@ -1199,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 { @@ -2663,6 +2688,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, @@ -2934,6 +3030,56 @@ static X86CPUDefinition builtin_x86_defs[] = { .model_id = "AMD EPYC Processor (with IBPB)", .cache_info = &epyc_cache_info, }, + { + .name = "Dhyana", + .level = 0xd, + .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 | + CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | CPUID_MCE | + CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | CPUID_DE | + CPUID_VME | CPUID_FP87, + .features[FEAT_1_ECX] = + CPUID_EXT_RDRAND | CPUID_EXT_F16C | CPUID_EXT_AVX | + 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_SSE3, + .features[FEAT_8000_0001_EDX] = + CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_PDPE1GB | + CPUID_EXT2_FFXSR | CPUID_EXT2_MMXEXT | CPUID_EXT2_NX | + CPUID_EXT2_SYSCALL, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_OSVW | CPUID_EXT3_3DNOWPREFETCH | + CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | + CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM | + CPUID_EXT3_TOPOEXT, + .features[FEAT_8000_0008_EBX] = + CPUID_8000_0008_EBX_IBPB, + .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, + /* + * Missing: XSAVES (not supported by some Linux versions, + * including v4.1 to v4.12). + * KVM doesn't yet expose any XSAVES state save component. + */ + .features[FEAT_XSAVE] = + CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, + .features[FEAT_SVM] = + CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE, + .xlevel = 0x8000001E, + .model_id = "Hygon Dhyana Processor", + .cache_info = &epyc_cache_info, + }, }; typedef struct PropValue { @@ -3059,14 +3205,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); @@ -3443,46 +3583,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 '_'. */ @@ -3619,6 +3719,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. */ @@ -3626,7 +3758,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; @@ -3653,25 +3784,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; @@ -3679,13 +3799,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. */ @@ -3721,32 +3841,26 @@ 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; } - (*s->cpu_fprintf)(s->file, "x86 %-20s %-48s\n", - name, desc); + qemu_printf("x86 %-20s %-48s\n", name, desc); g_free(name); } /* 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; @@ -3761,9 +3875,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); } @@ -4176,9 +4290,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]; @@ -4267,10 +4381,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; } @@ -4352,12 +4467,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; @@ -4367,6 +4484,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; @@ -4546,6 +4699,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, @@ -4680,6 +4837,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; @@ -4724,7 +4884,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. */ @@ -5037,6 +5201,11 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) 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); @@ -5120,12 +5289,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); @@ -5196,15 +5359,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. */ @@ -5216,6 +5370,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)) { @@ -5291,9 +5454,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; @@ -5539,13 +5703,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, @@ -5571,12 +5735,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; @@ -5761,30 +5932,52 @@ 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("kvm", X86CPU, expose_kvm, true), @@ -5866,9 +6059,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; @@ -5893,6 +6084,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;