diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/i386/cpu.c | 1 | ||||
-rw-r--r-- | target/i386/cpu.h | 1 | ||||
-rw-r--r-- | target/i386/kvm.c | 56 | ||||
-rw-r--r-- | target/i386/translate.c | 6 | ||||
-rw-r--r-- | target/i386/whpx-all.c | 79 |
5 files changed, 127 insertions, 16 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 555ae79d29..1a6b082b6f 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4761,6 +4761,7 @@ static Property x86_cpu_properties[] = { 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("check", X86CPU, check_cpuid, true), DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 78db1b833a..1b219fafc4 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1296,6 +1296,7 @@ struct X86CPU { bool hyperv_runtime; bool hyperv_synic; bool hyperv_stimer; + bool hyperv_frequencies; bool check_cpuid; bool enforce_cpuid; bool expose_kvm; diff --git a/target/i386/kvm.c b/target/i386/kvm.c index d23fff12f5..6c49954e68 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -632,11 +632,6 @@ static int hyperv_handle_properties(CPUState *cs) X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; - if (cpu->hyperv_time && - kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_TIME) <= 0) { - cpu->hyperv_time = false; - } - if (cpu->hyperv_relaxed_timing) { env->features[FEAT_HYPERV_EAX] |= HV_HYPERCALL_AVAILABLE; } @@ -645,26 +640,61 @@ static int hyperv_handle_properties(CPUState *cs) env->features[FEAT_HYPERV_EAX] |= HV_APIC_ACCESS_AVAILABLE; } if (cpu->hyperv_time) { + if (kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_TIME) <= 0) { + fprintf(stderr, "Hyper-V clocksources " + "(requested by 'hv-time' cpu flag) " + "are not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EAX] |= HV_HYPERCALL_AVAILABLE; env->features[FEAT_HYPERV_EAX] |= HV_TIME_REF_COUNT_AVAILABLE; env->features[FEAT_HYPERV_EAX] |= HV_REFERENCE_TSC_AVAILABLE; - - if (has_msr_hv_frequencies && tsc_is_stable_and_known(env)) { - env->features[FEAT_HYPERV_EAX] |= HV_ACCESS_FREQUENCY_MSRS; - env->features[FEAT_HYPERV_EDX] |= HV_FREQUENCY_MSRS_AVAILABLE; + } + if (cpu->hyperv_frequencies) { + if (!has_msr_hv_frequencies) { + fprintf(stderr, "Hyper-V frequency MSRs " + "(requested by 'hv-frequencies' cpu flag) " + "are not supported by kernel\n"); + return -ENOSYS; } + env->features[FEAT_HYPERV_EAX] |= HV_ACCESS_FREQUENCY_MSRS; + env->features[FEAT_HYPERV_EDX] |= HV_FREQUENCY_MSRS_AVAILABLE; } - if (cpu->hyperv_crash && has_msr_hv_crash) { + if (cpu->hyperv_crash) { + if (!has_msr_hv_crash) { + fprintf(stderr, "Hyper-V crash MSRs " + "(requested by 'hv-crash' cpu flag) " + "are not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EDX] |= HV_GUEST_CRASH_MSR_AVAILABLE; } env->features[FEAT_HYPERV_EDX] |= HV_CPU_DYNAMIC_PARTITIONING_AVAILABLE; - if (cpu->hyperv_reset && has_msr_hv_reset) { + if (cpu->hyperv_reset) { + if (!has_msr_hv_reset) { + fprintf(stderr, "Hyper-V reset MSR " + "(requested by 'hv-reset' cpu flag) " + "is not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EAX] |= HV_RESET_AVAILABLE; } - if (cpu->hyperv_vpindex && has_msr_hv_vpindex) { + if (cpu->hyperv_vpindex) { + if (!has_msr_hv_vpindex) { + fprintf(stderr, "Hyper-V VP_INDEX MSR " + "(requested by 'hv-vpindex' cpu flag) " + "is not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EAX] |= HV_VP_INDEX_AVAILABLE; } - if (cpu->hyperv_runtime && has_msr_hv_runtime) { + if (cpu->hyperv_runtime) { + if (!has_msr_hv_runtime) { + fprintf(stderr, "Hyper-V VP_RUNTIME MSR " + "(requested by 'hv-runtime' cpu flag) " + "is not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EAX] |= HV_VP_RUNTIME_AVAILABLE; } if (cpu->hyperv_synic) { diff --git a/target/i386/translate.c b/target/i386/translate.c index 0135415d92..c9ed8dc709 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -3802,7 +3802,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - tcg_gen_andc_tl(cpu_T0, cpu_regs[s->vex_v], cpu_T0); + tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_regs[s->vex_v]); gen_op_mov_reg_v(ot, reg, cpu_T0); gen_op_update1_cc(); set_cc_op(s, CC_OP_LOGICB + ot); @@ -4563,9 +4563,11 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) #endif rex_r = (~vex2 >> 4) & 8; if (b == 0xc5) { + /* 2-byte VEX prefix: RVVVVlpp, implied 0f leading opcode byte */ vex3 = vex2; - b = x86_ldub_code(env, s); + b = x86_ldub_code(env, s) | 0x100; } else { + /* 3-byte VEX prefix: RXBmmmmm wVVVVlpp */ #ifdef TARGET_X86_64 s->rex_x = (~vex2 >> 3) & 8; s->rex_b = (~vex2 >> 2) & 8; diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index bf33d320bf..58435178a4 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -911,12 +911,62 @@ static int whpx_vcpu_run(CPUState *cpu) ret = 1; break; + case WHvRunVpExitReasonX64Cpuid: { + WHV_REGISTER_VALUE reg_values[5] = {0}; + WHV_REGISTER_NAME reg_names[5]; + UINT32 reg_count = 5; + UINT64 rip, rax, rcx, rdx, rbx; + + rip = vcpu->exit_ctx.VpContext.Rip + + vcpu->exit_ctx.VpContext.InstructionLength; + switch (vcpu->exit_ctx.CpuidAccess.Rax) { + case 1: + rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax; + /* Advertise that we are running on a hypervisor */ + rcx = + vcpu->exit_ctx.CpuidAccess.DefaultResultRcx | + CPUID_EXT_HYPERVISOR; + + rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx; + rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx; + break; + default: + rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax; + rcx = vcpu->exit_ctx.CpuidAccess.DefaultResultRcx; + rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx; + rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx; + } + + reg_names[0] = WHvX64RegisterRip; + reg_names[1] = WHvX64RegisterRax; + reg_names[2] = WHvX64RegisterRcx; + reg_names[3] = WHvX64RegisterRdx; + reg_names[4] = WHvX64RegisterRbx; + + reg_values[0].Reg64 = rip; + reg_values[1].Reg64 = rax; + reg_values[2].Reg64 = rcx; + reg_values[3].Reg64 = rdx; + reg_values[4].Reg64 = rbx; + + hr = WHvSetVirtualProcessorRegisters(whpx->partition, + cpu->cpu_index, + reg_names, + reg_count, + reg_values); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set CpuidAccess state registers," + " hr=%08lx", hr); + } + ret = 0; + break; + } case WHvRunVpExitReasonNone: case WHvRunVpExitReasonUnrecoverableException: case WHvRunVpExitReasonInvalidVpRegisterValue: case WHvRunVpExitReasonUnsupportedFeature: case WHvRunVpExitReasonX64MsrAccess: - case WHvRunVpExitReasonX64Cpuid: case WHvRunVpExitReasonException: default: error_report("WHPX: Unexpected VP exit code %d", @@ -1272,6 +1322,33 @@ static int whpx_accel_init(MachineState *ms) goto error; } + memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); + prop.ExtendedVmExits.X64CpuidExit = 1; + hr = WHvSetPartitionProperty(whpx->partition, + WHvPartitionPropertyCodeExtendedVmExits, + &prop, + sizeof(WHV_PARTITION_PROPERTY)); + + if (FAILED(hr)) { + error_report("WHPX: Failed to enable partition extended X64CpuidExit" + " hr=%08lx", hr); + ret = -EINVAL; + goto error; + } + + UINT32 cpuidExitList[] = {1}; + hr = WHvSetPartitionProperty(whpx->partition, + WHvPartitionPropertyCodeCpuidExitList, + cpuidExitList, + RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32)); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set partition CpuidExitList hr=%08lx", + hr); + ret = -EINVAL; + goto error; + } + hr = WHvSetupPartition(whpx->partition); if (FAILED(hr)) { error_report("WHPX: Failed to setup partition, hr=%08lx", hr); |