diff options
Diffstat (limited to 'target')
| -rw-r--r-- | target/i386/confidential-guest.h | 2 | ||||
| -rw-r--r-- | target/i386/cpu-system.c | 11 | ||||
| -rw-r--r-- | target/i386/cpu.c | 119 | ||||
| -rw-r--r-- | target/i386/cpu.h | 31 | ||||
| -rw-r--r-- | target/i386/hvf/x86_emu.c | 3 | ||||
| -rw-r--r-- | target/i386/kvm/kvm.c | 197 | ||||
| -rw-r--r-- | target/i386/tcg/emit.c.inc | 59 | ||||
| -rw-r--r-- | target/i386/tcg/system/misc_helper.c | 3 | ||||
| -rw-r--r-- | target/i386/tcg/translate.c | 2 |
9 files changed, 232 insertions, 195 deletions
diff --git a/target/i386/confidential-guest.h b/target/i386/confidential-guest.h index 0afb8317b5..164be7633a 100644 --- a/target/i386/confidential-guest.h +++ b/target/i386/confidential-guest.h @@ -46,7 +46,7 @@ struct X86ConfidentialGuestClass { /** * x86_confidential_guest_kvm_type: * - * Calls #X86ConfidentialGuestClass.unplug callback of @plug_handler. + * Calls #X86ConfidentialGuestClass.kvm_type() callback. */ static inline int x86_confidential_guest_kvm_type(X86ConfidentialGuest *cg) { diff --git a/target/i386/cpu-system.c b/target/i386/cpu-system.c index 9d007afdab..b56a2821af 100644 --- a/target/i386/cpu-system.c +++ b/target/i386/cpu-system.c @@ -309,3 +309,14 @@ void x86_cpu_get_crash_info_qom(Object *obj, Visitor *v, errp); qapi_free_GuestPanicInformation(panic_info); } + +uint64_t cpu_x86_get_msr_core_thread_count(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + uint64_t val; + + val = x86_threads_per_pkg(&env->topo_info); /* thread count, bits 15..0 */ + val |= x86_cores_per_pkg(&env->topo_info) << 16; /* core count, bits 31..16 */ + + return val; +} diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 0b639848cd..1b9c11022c 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -312,13 +312,11 @@ static uint32_t num_threads_by_topo_level(X86CPUTopoInfo *topo_info, case CPU_TOPOLOGY_LEVEL_CORE: return topo_info->threads_per_core; case CPU_TOPOLOGY_LEVEL_MODULE: - return topo_info->threads_per_core * topo_info->cores_per_module; + return x86_threads_per_module(topo_info); case CPU_TOPOLOGY_LEVEL_DIE: - return topo_info->threads_per_core * topo_info->cores_per_module * - topo_info->modules_per_die; + return x86_threads_per_die(topo_info); case CPU_TOPOLOGY_LEVEL_SOCKET: - return topo_info->threads_per_core * topo_info->cores_per_module * - topo_info->modules_per_die * topo_info->dies_per_pkg; + return x86_threads_per_pkg(topo_info); default: g_assert_not_reached(); } @@ -6498,18 +6496,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, CPUState *cs = env_cpu(env); uint32_t limit; uint32_t signature[3]; - X86CPUTopoInfo topo_info; - uint32_t cores_per_pkg; + X86CPUTopoInfo *topo_info = &env->topo_info; uint32_t threads_per_pkg; - topo_info.dies_per_pkg = env->nr_dies; - topo_info.modules_per_die = env->nr_modules; - topo_info.cores_per_module = cs->nr_cores / env->nr_dies / env->nr_modules; - topo_info.threads_per_core = cs->nr_threads; - - cores_per_pkg = topo_info.cores_per_module * topo_info.modules_per_die * - topo_info.dies_per_pkg; - threads_per_pkg = cores_per_pkg * topo_info.threads_per_core; + threads_per_pkg = x86_threads_per_pkg(topo_info); /* Calculate & apply limits for different index ranges */ if (index >= 0xC0000000) { @@ -6548,7 +6538,6 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *edx = env->features[FEAT_1_EDX]; if (threads_per_pkg > 1) { *ebx |= threads_per_pkg << 16; - *edx |= CPUID_HT; } if (!cpu->enable_pmu) { *ecx &= ~CPUID_EXT_PDCM; @@ -6586,12 +6575,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, int host_vcpus_per_cache = 1 + ((*eax & 0x3FFC000) >> 14); *eax &= ~0xFC000000; - *eax |= max_core_ids_in_package(&topo_info) << 26; + *eax |= max_core_ids_in_package(topo_info) << 26; if (host_vcpus_per_cache > threads_per_pkg) { *eax &= ~0x3FFC000; /* Share the cache at package level. */ - *eax |= max_thread_ids_for_cache(&topo_info, + *eax |= max_thread_ids_for_cache(topo_info, CPU_TOPOLOGY_LEVEL_SOCKET) << 14; } } @@ -6603,7 +6592,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, switch (count) { case 0: /* L1 dcache info */ encode_cache_cpuid4(env->cache_info_cpuid4.l1d_cache, - &topo_info, + topo_info, eax, ebx, ecx, edx); if (!cpu->l1_cache_per_core) { *eax &= ~MAKE_64BIT_MASK(14, 12); @@ -6611,7 +6600,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 1: /* L1 icache info */ encode_cache_cpuid4(env->cache_info_cpuid4.l1i_cache, - &topo_info, + topo_info, eax, ebx, ecx, edx); if (!cpu->l1_cache_per_core) { *eax &= ~MAKE_64BIT_MASK(14, 12); @@ -6619,13 +6608,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 2: /* L2 cache info */ encode_cache_cpuid4(env->cache_info_cpuid4.l2_cache, - &topo_info, + topo_info, eax, ebx, ecx, edx); break; case 3: /* L3 cache info */ if (cpu->enable_l3_cache) { encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache, - &topo_info, + topo_info, eax, ebx, ecx, edx); break; } @@ -6708,12 +6697,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, switch (count) { case 0: - *eax = apicid_core_offset(&topo_info); - *ebx = topo_info.threads_per_core; + *eax = apicid_core_offset(topo_info); + *ebx = topo_info->threads_per_core; *ecx |= CPUID_B_ECX_TOPO_LEVEL_SMT << 8; break; case 1: - *eax = apicid_pkg_offset(&topo_info); + *eax = apicid_pkg_offset(topo_info); *ebx = threads_per_pkg; *ecx |= CPUID_B_ECX_TOPO_LEVEL_CORE << 8; break; @@ -6739,7 +6728,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; } - encode_topo_cpuid1f(env, count, &topo_info, eax, ebx, ecx, edx); + encode_topo_cpuid1f(env, count, topo_info, eax, ebx, ecx, edx); break; case 0xD: { /* Processor Extended State */ @@ -6964,17 +6953,6 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx = env->features[FEAT_8000_0001_ECX]; *edx = env->features[FEAT_8000_0001_EDX]; - /* The Linux kernel checks for the CMPLegacy bit and - * discards multiple thread information if it is set. - * So don't set it here for Intel to make Linux guests happy. - */ - if (threads_per_pkg > 1) { - if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 || - env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 || - env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) { - *ecx |= 1 << 1; /* CmpLegacy bit */ - } - } if (tcg_enabled() && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && !(env->hflags & HF_LMA_MASK)) { *edx &= ~CPUID_EXT2_SYSCALL; @@ -7042,7 +7020,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, * thread ID within a package". * Bits 7:0 is "The number of threads in the package is NC+1" */ - *ecx = (apicid_pkg_offset(&topo_info) << 12) | + *ecx = (apicid_pkg_offset(topo_info) << 12) | (threads_per_pkg - 1); } else { *ecx = 0; @@ -7071,19 +7049,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, switch (count) { case 0: /* L1 dcache info */ encode_cache_cpuid8000001d(env->cache_info_amd.l1d_cache, - &topo_info, eax, ebx, ecx, edx); + topo_info, eax, ebx, ecx, edx); break; case 1: /* L1 icache info */ encode_cache_cpuid8000001d(env->cache_info_amd.l1i_cache, - &topo_info, eax, ebx, ecx, edx); + topo_info, eax, ebx, ecx, edx); break; case 2: /* L2 cache info */ encode_cache_cpuid8000001d(env->cache_info_amd.l2_cache, - &topo_info, eax, ebx, ecx, edx); + topo_info, eax, ebx, ecx, edx); break; case 3: /* L3 cache info */ encode_cache_cpuid8000001d(env->cache_info_amd.l3_cache, - &topo_info, eax, ebx, ecx, edx); + topo_info, eax, ebx, ecx, edx); break; default: /* end of info */ *eax = *ebx = *ecx = *edx = 0; @@ -7095,7 +7073,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 0x8000001E: if (cpu->core_id <= 255) { - encode_topo_cpuid8000001e(cpu, &topo_info, eax, ebx, ecx, edx); + encode_topo_cpuid8000001e(cpu, topo_info, eax, ebx, ecx, edx); } else { *eax = 0; *ebx = 0; @@ -7539,6 +7517,19 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp) } } + if (x86_threads_per_pkg(&env->topo_info) > 1) { + env->features[FEAT_1_EDX] |= CPUID_HT; + + /* + * The Linux kernel checks for the CMPLegacy bit and + * discards multiple thread information if it is set. + * So don't set it here for Intel to make Linux guests happy. + */ + if (!IS_INTEL_CPU(env)) { + env->features[FEAT_8000_0001_ECX] |= CPUID_EXT3_CMP_LEG; + } + } + for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) { FeatureDep *d = &feature_dependencies[i]; if (!(env->features[d->from.index] & d->from.mask)) { @@ -7719,8 +7710,10 @@ static bool x86_cpu_filter_features(X86CPU *cpu, bool verbose) env->avx10_version = version; have_filtered_features = true; } - } else if (env->avx10_version && prefix) { - warn_report("%s: avx10.%d.", prefix, env->avx10_version); + } else if (env->avx10_version) { + if (prefix) { + warn_report("%s: avx10.%d.", prefix, env->avx10_version); + } have_filtered_features = true; } @@ -7891,6 +7884,21 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) */ cpu->mwait.ecx |= CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; + /* + * Most Intel and certain AMD CPUs support hyperthreading. Even though QEMU + * fixes this issue by adjusting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX + * based on inputs (sockets,cores,threads), it is still better to give + * users a warning. + */ + if (IS_AMD_CPU(env) && + !(env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_TOPOEXT) && + env->topo_info.threads_per_core > 1) { + warn_report_once("This family of AMD CPU doesn't support " + "hyperthreading(%d). Please configure -smp " + "options properly or try enabling topoext " + "feature.", env->topo_info.threads_per_core); + } + /* For 64bit systems think about the number of physical bits to present. * ideally this should be the same as the host; anything other than matching * the host can cause incorrect guest behaviour. @@ -7995,24 +8003,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) x86_cpu_gdb_init(cs); qemu_init_vcpu(cs); - /* - * Most Intel and certain AMD CPUs support hyperthreading. Even though QEMU - * fixes this issue by adjusting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX - * based on inputs (sockets,cores,threads), it is still better to give - * users a warning. - * - * NOTE: the following code has to follow qemu_init_vcpu(). Otherwise - * cs->nr_threads hasn't be populated yet and the checking is incorrect. - */ - if (IS_AMD_CPU(env) && - !(env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_TOPOEXT) && - cs->nr_threads > 1) { - warn_report_once("This family of AMD CPU doesn't support " - "hyperthreading(%d). Please configure -smp " - "options properly or try enabling topoext " - "feature.", cs->nr_threads); - } - #ifndef CONFIG_USER_ONLY x86_cpu_apic_realize(cpu, &local_err); if (local_err != NULL) { @@ -8171,8 +8161,7 @@ static void x86_cpu_init_default_topo(X86CPU *cpu) { CPUX86State *env = &cpu->env; - env->nr_modules = 1; - env->nr_dies = 1; + env->topo_info = (X86CPUTopoInfo) {1, 1, 1, 1}; /* thread, core and socket levels are set by default. */ set_bit(CPU_TOPOLOGY_LEVEL_THREAD, env->avail_cpu_topo); diff --git a/target/i386/cpu.h b/target/i386/cpu.h index dbd8f1ffc7..b26e25ba15 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -29,6 +29,7 @@ #include "qapi/qapi-types-common.h" #include "qemu/cpu-float.h" #include "qemu/timer.h" +#include "standard-headers/asm-x86/kvm_para.h" #define XEN_NR_VIRQS 24 @@ -1010,6 +1011,28 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w); #define CPUID_8000_0007_EBX_OVERFLOW_RECOV (1U << 0) #define CPUID_8000_0007_EBX_SUCCOR (1U << 1) +/* (Old) KVM paravirtualized clocksource */ +#define CPUID_KVM_CLOCK (1U << KVM_FEATURE_CLOCKSOURCE) +/* (New) KVM specific paravirtualized clocksource */ +#define CPUID_KVM_CLOCK2 (1U << KVM_FEATURE_CLOCKSOURCE2) +/* KVM asynchronous page fault */ +#define CPUID_KVM_ASYNCPF (1U << KVM_FEATURE_ASYNC_PF) +/* KVM stolen (when guest vCPU is not running) time accounting */ +#define CPUID_KVM_STEAL_TIME (1U << KVM_FEATURE_STEAL_TIME) +/* KVM paravirtualized end-of-interrupt signaling */ +#define CPUID_KVM_PV_EOI (1U << KVM_FEATURE_PV_EOI) +/* KVM paravirtualized spinlocks support */ +#define CPUID_KVM_PV_UNHALT (1U << KVM_FEATURE_PV_UNHALT) +/* KVM host-side polling on HLT control from the guest */ +#define CPUID_KVM_POLL_CONTROL (1U << KVM_FEATURE_POLL_CONTROL) +/* KVM interrupt based asynchronous page fault*/ +#define CPUID_KVM_ASYNCPF_INT (1U << KVM_FEATURE_ASYNC_PF_INT) +/* KVM 'Extended Destination ID' support for external interrupts */ +#define CPUID_KVM_MSI_EXT_DEST_ID (1U << KVM_FEATURE_MSI_EXT_DEST_ID) + +/* Hint to KVM that vCPUs expect never preempted for an unlimited time */ +#define CPUID_KVM_HINTS_REALTIME (1U << KVM_HINTS_REALTIME) + /* CLZERO instruction */ #define CPUID_8000_0008_EBX_CLZERO (1U << 0) /* Always save/restore FP error pointers */ @@ -2045,11 +2068,7 @@ typedef struct CPUArchState { TPRAccess tpr_access_type; - /* Number of dies within this CPU package. */ - unsigned nr_dies; - - /* Number of modules within one die. */ - unsigned nr_modules; + X86CPUTopoInfo topo_info; /* Bitmap of available CPU topology levels for this CPU. */ DECLARE_BITMAP(avail_cpu_topo, CPU_TOPOLOGY_LEVEL__MAX); @@ -2390,6 +2409,8 @@ static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu, cs->halted = 0; } +uint64_t cpu_x86_get_msr_core_thread_count(X86CPU *cpu); + int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector, target_ulong *base, unsigned int *limit, unsigned int *flags); diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index 015f760acb..69c61c9c07 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -765,8 +765,7 @@ void simulate_rdmsr(CPUX86State *env) val = env->mtrr_deftype; break; case MSR_CORE_THREAD_COUNT: - val = cs->nr_threads * cs->nr_cores; /* thread count, bits 15..0 */ - val |= ((uint32_t)cs->nr_cores << 16); /* core count, bits 31..16 */ + val = cpu_x86_get_msr_core_thread_count(cpu); break; default: /* fprintf(stderr, "%s: unknown msr 0x%x\n", __func__, msr); */ diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 2f66e63b88..6c749d4ee8 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -95,9 +95,6 @@ #define KVM_APIC_BUS_CYCLE_NS 1 #define KVM_APIC_BUS_FREQUENCY (1000000000ULL / KVM_APIC_BUS_CYCLE_NS) -#define MSR_KVM_WALL_CLOCK 0x11 -#define MSR_KVM_SYSTEM_TIME 0x12 - /* A 4096-byte buffer can hold the 8-byte kvm_msrs header, plus * 255 kvm_msr_entry structs */ #define MSR_BUF_SIZE 4096 @@ -111,8 +108,8 @@ typedef struct { } KVMMSRHandlers; static void kvm_init_msrs(X86CPU *cpu); -static bool kvm_filter_msr(KVMState *s, uint32_t msr, QEMURDMSRHandler *rdmsr, - QEMUWRMSRHandler *wrmsr); +static int kvm_filter_msr(KVMState *s, uint32_t msr, QEMURDMSRHandler *rdmsr, + QEMUWRMSRHandler *wrmsr); const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_INFO(SET_TSS_ADDR), @@ -564,13 +561,13 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, * be enabled without the in-kernel irqchip */ if (!kvm_irqchip_in_kernel()) { - ret &= ~(1U << KVM_FEATURE_PV_UNHALT); + ret &= ~CPUID_KVM_PV_UNHALT; } if (kvm_irqchip_is_split()) { - ret |= 1U << KVM_FEATURE_MSI_EXT_DEST_ID; + ret |= CPUID_KVM_MSI_EXT_DEST_ID; } } else if (function == KVM_CPUID_FEATURES && reg == R_EDX) { - ret |= 1U << KVM_HINTS_REALTIME; + ret |= CPUID_KVM_HINTS_REALTIME; } if (current_machine->cgs) { @@ -2617,10 +2614,7 @@ static bool kvm_rdmsr_core_thread_count(X86CPU *cpu, uint32_t msr, uint64_t *val) { - CPUState *cs = CPU(cpu); - - *val = cs->nr_threads * cs->nr_cores; /* thread count, bits 15..0 */ - *val |= ((uint32_t)cs->nr_cores << 16); /* core count, bits 31..16 */ + *val = cpu_x86_get_msr_core_thread_count(cpu); return true; } @@ -2939,7 +2933,6 @@ static int kvm_msr_energy_thread_init(KVMState *s, MachineState *ms) { MachineClass *mc = MACHINE_GET_CLASS(ms); struct KVMMsrEnergy *r = &s->msr_energy; - int ret = 0; /* * Sanity check @@ -2949,13 +2942,11 @@ static int kvm_msr_energy_thread_init(KVMState *s, MachineState *ms) if (!is_host_cpu_intel()) { error_report("The RAPL feature can only be enabled on hosts " "with Intel CPU models"); - ret = 1; - goto out; + return -1; } if (!is_rapl_enabled()) { - ret = 1; - goto out; + return -1; } /* Retrieve the virtual topology */ @@ -2977,16 +2968,14 @@ static int kvm_msr_energy_thread_init(KVMState *s, MachineState *ms) r->host_topo.maxcpus = vmsr_get_maxcpus(); if (r->host_topo.maxcpus == 0) { error_report("host max cpus = 0"); - ret = 1; - goto out; + return -1; } /* Max number of packages on the host */ r->host_topo.maxpkgs = vmsr_get_max_physical_package(r->host_topo.maxcpus); if (r->host_topo.maxpkgs == 0) { error_report("host max pkgs = 0"); - ret = 1; - goto out; + return -1; } /* Allocate memory for each package on the host */ @@ -2998,8 +2987,7 @@ static int kvm_msr_energy_thread_init(KVMState *s, MachineState *ms) for (int i = 0; i < r->host_topo.maxpkgs; i++) { if (r->host_topo.pkg_cpu_count[i] == 0) { error_report("cpu per packages = 0 on package_%d", i); - ret = 1; - goto out; + return -1; } } @@ -3016,8 +3004,7 @@ static int kvm_msr_energy_thread_init(KVMState *s, MachineState *ms) if (s->msr_energy.sioc == NULL) { error_report("vmsr socket opening failed"); - ret = 1; - goto out; + return -1; } /* Those MSR values should not change */ @@ -3029,15 +3016,13 @@ static int kvm_msr_energy_thread_init(KVMState *s, MachineState *ms) s->msr_energy.sioc); if (r->msr_unit == 0 || r->msr_limit == 0 || r->msr_info == 0) { error_report("can't read any virtual msr"); - ret = 1; - goto out; + return -1; } qemu_thread_create(&r->msr_thr, "kvm-msr", kvm_msr_energy_thread, s, QEMU_THREAD_JOINABLE); -out: - return ret; + return 0; } int kvm_arch_get_default_type(MachineState *ms) @@ -3103,10 +3088,7 @@ static int kvm_vm_set_tss_addr(KVMState *s, uint64_t tss_base) static int kvm_vm_enable_disable_exits(KVMState *s) { int disable_exits = kvm_check_extension(s, KVM_CAP_X86_DISABLE_EXITS); -/* Work around for kernel header with a typo. TODO: fix header and drop. */ -#if defined(KVM_X86_DISABLE_EXITS_HTL) && !defined(KVM_X86_DISABLE_EXITS_HLT) -#define KVM_X86_DISABLE_EXITS_HLT KVM_X86_DISABLE_EXITS_HTL -#endif + if (disable_exits) { disable_exits &= (KVM_X86_DISABLE_EXITS_MWAIT | KVM_X86_DISABLE_EXITS_HLT | @@ -3156,59 +3138,64 @@ static int kvm_vm_enable_notify_vmexit(KVMState *s) static int kvm_vm_enable_userspace_msr(KVMState *s) { - int ret = kvm_vm_enable_cap(s, KVM_CAP_X86_USER_SPACE_MSR, 0, - KVM_MSR_EXIT_REASON_FILTER); + int ret; + + ret = kvm_vm_enable_cap(s, KVM_CAP_X86_USER_SPACE_MSR, 0, + KVM_MSR_EXIT_REASON_FILTER); if (ret < 0) { error_report("Could not enable user space MSRs: %s", strerror(-ret)); exit(1); } - if (!kvm_filter_msr(s, MSR_CORE_THREAD_COUNT, - kvm_rdmsr_core_thread_count, NULL)) { - error_report("Could not install MSR_CORE_THREAD_COUNT handler!"); + ret = kvm_filter_msr(s, MSR_CORE_THREAD_COUNT, + kvm_rdmsr_core_thread_count, NULL); + if (ret < 0) { + error_report("Could not install MSR_CORE_THREAD_COUNT handler: %s", + strerror(-ret)); exit(1); } return 0; } -static void kvm_vm_enable_energy_msrs(KVMState *s) +static int kvm_vm_enable_energy_msrs(KVMState *s) { - bool r; + int ret; + if (s->msr_energy.enable == true) { - r = kvm_filter_msr(s, MSR_RAPL_POWER_UNIT, - kvm_rdmsr_rapl_power_unit, NULL); - if (!r) { - error_report("Could not install MSR_RAPL_POWER_UNIT \ - handler"); - exit(1); + ret = kvm_filter_msr(s, MSR_RAPL_POWER_UNIT, + kvm_rdmsr_rapl_power_unit, NULL); + if (ret < 0) { + error_report("Could not install MSR_RAPL_POWER_UNIT handler: %s", + strerror(-ret)); + return ret; } - r = kvm_filter_msr(s, MSR_PKG_POWER_LIMIT, - kvm_rdmsr_pkg_power_limit, NULL); - if (!r) { - error_report("Could not install MSR_PKG_POWER_LIMIT \ - handler"); - exit(1); + ret = kvm_filter_msr(s, MSR_PKG_POWER_LIMIT, + kvm_rdmsr_pkg_power_limit, NULL); + if (ret < 0) { + error_report("Could not install MSR_PKG_POWER_LIMIT handler: %s", + strerror(-ret)); + return ret; } - r = kvm_filter_msr(s, MSR_PKG_POWER_INFO, - kvm_rdmsr_pkg_power_info, NULL); - if (!r) { - error_report("Could not install MSR_PKG_POWER_INFO \ - handler"); - exit(1); + ret = kvm_filter_msr(s, MSR_PKG_POWER_INFO, + kvm_rdmsr_pkg_power_info, NULL); + if (ret < 0) { + error_report("Could not install MSR_PKG_POWER_INFO handler: %s", + strerror(-ret)); + return ret; } - r = kvm_filter_msr(s, MSR_PKG_ENERGY_STATUS, - kvm_rdmsr_pkg_energy_status, NULL); - if (!r) { - error_report("Could not install MSR_PKG_ENERGY_STATUS \ - handler"); - exit(1); + ret = kvm_filter_msr(s, MSR_PKG_ENERGY_STATUS, + kvm_rdmsr_pkg_energy_status, NULL); + if (ret < 0) { + error_report("Could not install MSR_PKG_ENERGY_STATUS handler: %s", + strerror(-ret)); + return ret; } } - return; + return 0; } int kvm_arch_init(MachineState *ms, KVMState *s) @@ -3275,7 +3262,10 @@ int kvm_arch_init(MachineState *ms, KVMState *s) return ret; } - kvm_get_supported_feature_msrs(s); + ret = kvm_get_supported_feature_msrs(s); + if (ret < 0) { + return ret; + } uname(&utsname); lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0; @@ -3311,6 +3301,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) if (ret < 0) { error_report("kvm: guest stopping CPU not supported: %s", strerror(-ret)); + return ret; } } @@ -3342,10 +3333,15 @@ int kvm_arch_init(MachineState *ms, KVMState *s) } if (s->msr_energy.enable == true) { - kvm_vm_enable_energy_msrs(s); - if (kvm_msr_energy_thread_init(s, ms)) { + ret = kvm_vm_enable_energy_msrs(s); + if (ret < 0) { + return ret; + } + + ret = kvm_msr_energy_thread_init(s, ms); + if (ret < 0) { error_report("kvm : error RAPL feature requirement not met"); - exit(1); + return ret; } } } @@ -3976,22 +3972,24 @@ static int kvm_put_msrs(X86CPU *cpu, int level) */ if (level >= KVM_PUT_RESET_STATE) { kvm_msr_entry_add(cpu, MSR_IA32_TSC, env->tsc); - kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, env->system_time_msr); - kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, env->wall_clock_msr); - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF_INT)) { + if (env->features[FEAT_KVM] & (CPUID_KVM_CLOCK | CPUID_KVM_CLOCK2)) { + kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, env->system_time_msr); + kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, env->wall_clock_msr); + } + if (env->features[FEAT_KVM] & CPUID_KVM_ASYNCPF_INT) { kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_INT, env->async_pf_int_msr); } - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) { + if (env->features[FEAT_KVM] & CPUID_KVM_ASYNCPF) { kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr); } - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_PV_EOI)) { + if (env->features[FEAT_KVM] & CPUID_KVM_PV_EOI) { kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, env->pv_eoi_en_msr); } - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_STEAL_TIME)) { + if (env->features[FEAT_KVM] & CPUID_KVM_STEAL_TIME) { kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, env->steal_time_msr); } - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_POLL_CONTROL)) { + if (env->features[FEAT_KVM] & CPUID_KVM_POLL_CONTROL) { kvm_msr_entry_add(cpu, MSR_KVM_POLL_CONTROL, env->poll_control_msr); } @@ -4454,21 +4452,23 @@ static int kvm_get_msrs(X86CPU *cpu) } } #endif - kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, 0); - kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, 0); - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF_INT)) { + if (env->features[FEAT_KVM] & (CPUID_KVM_CLOCK | CPUID_KVM_CLOCK2)) { + kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, 0); + kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, 0); + } + if (env->features[FEAT_KVM] & CPUID_KVM_ASYNCPF_INT) { kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_INT, 0); } - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_ASYNC_PF)) { + if (env->features[FEAT_KVM] & CPUID_KVM_ASYNCPF) { kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, 0); } - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_PV_EOI)) { + if (env->features[FEAT_KVM] & CPUID_KVM_PV_EOI) { kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, 0); } - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_STEAL_TIME)) { + if (env->features[FEAT_KVM] & CPUID_KVM_STEAL_TIME) { kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, 0); } - if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_POLL_CONTROL)) { + if (env->features[FEAT_KVM] & CPUID_KVM_POLL_CONTROL) { kvm_msr_entry_add(cpu, MSR_KVM_POLL_CONTROL, 1); } if (has_architectural_pmu_version > 0) { @@ -5843,15 +5843,16 @@ void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg) } } -static bool kvm_install_msr_filters(KVMState *s) +static int kvm_install_msr_filters(KVMState *s) { uint64_t zero = 0; struct kvm_msr_filter filter = { .flags = KVM_MSR_FILTER_DEFAULT_ALLOW, }; - int r, i, j = 0; + int i, j = 0; - for (i = 0; i < KVM_MSR_FILTER_MAX_RANGES; i++) { + QEMU_BUILD_BUG_ON(ARRAY_SIZE(msr_handlers) != ARRAY_SIZE(filter.ranges)); + for (i = 0; i < ARRAY_SIZE(msr_handlers); i++) { KVMMSRHandlers *handler = &msr_handlers[i]; if (handler->msr) { struct kvm_msr_filter_range *range = &filter.ranges[j++]; @@ -5873,18 +5874,13 @@ static bool kvm_install_msr_filters(KVMState *s) } } - r = kvm_vm_ioctl(s, KVM_X86_SET_MSR_FILTER, &filter); - if (r) { - return false; - } - - return true; + return kvm_vm_ioctl(s, KVM_X86_SET_MSR_FILTER, &filter); } -static bool kvm_filter_msr(KVMState *s, uint32_t msr, QEMURDMSRHandler *rdmsr, - QEMUWRMSRHandler *wrmsr) +static int kvm_filter_msr(KVMState *s, uint32_t msr, QEMURDMSRHandler *rdmsr, + QEMUWRMSRHandler *wrmsr) { - int i; + int i, ret; for (i = 0; i < ARRAY_SIZE(msr_handlers); i++) { if (!msr_handlers[i].msr) { @@ -5894,16 +5890,17 @@ static bool kvm_filter_msr(KVMState *s, uint32_t msr, QEMURDMSRHandler *rdmsr, .wrmsr = wrmsr, }; - if (!kvm_install_msr_filters(s)) { + ret = kvm_install_msr_filters(s); + if (ret) { msr_handlers[i] = (KVMMSRHandlers) { }; - return false; + return ret; } - return true; + return 0; } } - return false; + return -EINVAL; } static int kvm_handle_rdmsr(X86CPU *cpu, struct kvm_run *run) @@ -6195,7 +6192,7 @@ uint64_t kvm_swizzle_msi_ext_dest_id(uint64_t address) return address; } env = &X86_CPU(first_cpu)->env; - if (!(env->features[FEAT_KVM] & (1 << KVM_FEATURE_MSI_EXT_DEST_ID))) { + if (!(env->features[FEAT_KVM] & CPUID_KVM_MSI_EXT_DEST_ID)) { return address; } diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 785ff63f2a..c4cc5f48d8 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -286,24 +286,25 @@ static void gen_load(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv v) gen_op_ld_v(s, op->ot, v, s->A0); } - } else if (op->ot == MO_8 && byte_reg_is_xH(s, op->n)) { - if (v == s->T0 && decode->e.special == X86_SPECIAL_SExtT0) { - tcg_gen_sextract_tl(v, cpu_regs[op->n - 4], 8, 8); - } else { - tcg_gen_extract_tl(v, cpu_regs[op->n - 4], 8, 8); - } - } else if (op->ot < MO_TL && v == s->T0 && (decode->e.special == X86_SPECIAL_SExtT0 || decode->e.special == X86_SPECIAL_ZExtT0)) { - if (decode->e.special == X86_SPECIAL_SExtT0) { - tcg_gen_ext_tl(v, cpu_regs[op->n], op->ot | MO_SIGN); + if (op->ot == MO_8 && byte_reg_is_xH(s, op->n)) { + if (decode->e.special == X86_SPECIAL_SExtT0) { + tcg_gen_sextract_tl(v, cpu_regs[op->n - 4], 8, 8); + } else { + tcg_gen_extract_tl(v, cpu_regs[op->n - 4], 8, 8); + } } else { - tcg_gen_ext_tl(v, cpu_regs[op->n], op->ot); + if (decode->e.special == X86_SPECIAL_SExtT0) { + tcg_gen_ext_tl(v, cpu_regs[op->n], op->ot | MO_SIGN); + } else { + tcg_gen_ext_tl(v, cpu_regs[op->n], op->ot); + } } } else { - tcg_gen_mov_tl(v, cpu_regs[op->n]); + gen_op_mov_v_reg(s, op->ot, v, op->n); } break; case X86_OP_IMM: @@ -1443,8 +1444,9 @@ static TCGv gen_bt_mask(DisasContext *s, X86DecodedInsn *decode) return mask; } -/* Expects truncated bit index in s->T1, 1 << s->T1 in MASK. */ -static void gen_bt_flags(DisasContext *s, X86DecodedInsn *decode, TCGv src, TCGv mask) +/* Expects truncated bit index in COUNT, 1 << COUNT in MASK. */ +static void gen_bt_flags(DisasContext *s, X86DecodedInsn *decode, TCGv src, + TCGv count, TCGv mask) { TCGv cf; @@ -1467,15 +1469,34 @@ static void gen_bt_flags(DisasContext *s, X86DecodedInsn *decode, TCGv src, TCGv decode->cc_src = tcg_temp_new(); decode->cc_dst = cpu_cc_dst; decode->cc_op = CC_OP_SARB + cc_op_size(s->cc_op); - tcg_gen_shr_tl(decode->cc_src, src, s->T1); + tcg_gen_shr_tl(decode->cc_src, src, count); } } static void gen_BT(DisasContext *s, X86DecodedInsn *decode) { - TCGv mask = gen_bt_mask(s, decode); + TCGv count = s->T1; + TCGv mask; + + /* + * Try to ensure that the rhs of the TSTNE condition is a constant (and a + * power of two), as that is more readily available on most TCG backends. + * + * For immediate bit number gen_bt_mask()'s output is already a constant; + * for register bit number, shift the source right and check bit 0. + */ + if (decode->e.op2 == X86_TYPE_I) { + mask = gen_bt_mask(s, decode); + } else { + MemOp ot = decode->op[1].ot; + + tcg_gen_andi_tl(s->T1, s->T1, (8 << ot) - 1); + tcg_gen_shr_tl(s->T0, s->T0, s->T1); - gen_bt_flags(s, decode, s->T0, mask); + count = tcg_constant_tl(0); + mask = tcg_constant_tl(1); + } + gen_bt_flags(s, decode, s->T0, count, mask); } static void gen_BTC(DisasContext *s, X86DecodedInsn *decode) @@ -1491,7 +1512,7 @@ static void gen_BTC(DisasContext *s, X86DecodedInsn *decode) tcg_gen_xor_tl(s->T0, s->T0, mask); } - gen_bt_flags(s, decode, old, mask); + gen_bt_flags(s, decode, old, s->T1, mask); } static void gen_BTR(DisasContext *s, X86DecodedInsn *decode) @@ -1509,7 +1530,7 @@ static void gen_BTR(DisasContext *s, X86DecodedInsn *decode) tcg_gen_andc_tl(s->T0, s->T0, mask); } - gen_bt_flags(s, decode, old, mask); + gen_bt_flags(s, decode, old, s->T1, mask); } static void gen_BTS(DisasContext *s, X86DecodedInsn *decode) @@ -1525,7 +1546,7 @@ static void gen_BTS(DisasContext *s, X86DecodedInsn *decode) tcg_gen_or_tl(s->T0, s->T0, mask); } - gen_bt_flags(s, decode, old, mask); + gen_bt_flags(s, decode, old, s->T1, mask); } static void gen_BZHI(DisasContext *s, X86DecodedInsn *decode) diff --git a/target/i386/tcg/system/misc_helper.c b/target/i386/tcg/system/misc_helper.c index ffed8a3215..c9c4d42f84 100644 --- a/target/i386/tcg/system/misc_helper.c +++ b/target/i386/tcg/system/misc_helper.c @@ -468,8 +468,7 @@ void helper_rdmsr(CPUX86State *env) val = x86_cpu->ucode_rev; break; case MSR_CORE_THREAD_COUNT: { - CPUState *cs = CPU(x86_cpu); - val = (cs->nr_threads * cs->nr_cores) | (cs->nr_cores << 16); + val = cpu_x86_get_msr_core_thread_count(x86_cpu); break; } case MSR_APIC_START ... MSR_APIC_END: { diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 834aea1e59..dbc9d637c4 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -486,7 +486,7 @@ static inline void gen_op_mov_v_reg(DisasContext *s, MemOp ot, TCGv t0, int reg) { if (ot == MO_8 && byte_reg_is_xH(s, reg)) { - tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8); + tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8); } else { tcg_gen_mov_tl(t0, cpu_regs[reg]); } |