kvm: x86: fix setting IA32_FEATURE_CONTROL with nested VMX disabled

This patch is to fix the bug https://bugs.launchpad.net/qemu-kvm/+bug/1207623

IA32_FEATURE_CONTROL is pointless if not expose VMX or SMX bits to
cpuid.1.ecx of vcpu. Current qemu-kvm will error return when kvm_put_msrs
or kvm_get_msrs.

Signed-off-by: Liu Jinsong <jinsong.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Liu Jinsong 2013-08-19 09:33:30 +08:00 committed by Paolo Bonzini
parent ca916d3729
commit df67696e97

View File

@ -65,6 +65,7 @@ static bool has_msr_star;
static bool has_msr_hsave_pa; static bool has_msr_hsave_pa;
static bool has_msr_tsc_adjust; static bool has_msr_tsc_adjust;
static bool has_msr_tsc_deadline; static bool has_msr_tsc_deadline;
static bool has_msr_feature_control;
static bool has_msr_async_pf_en; static bool has_msr_async_pf_en;
static bool has_msr_pv_eoi_en; static bool has_msr_pv_eoi_en;
static bool has_msr_misc_enable; static bool has_msr_misc_enable;
@ -666,6 +667,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
qemu_add_vm_change_state_handler(cpu_update_state, env); qemu_add_vm_change_state_handler(cpu_update_state, env);
c = cpuid_find_entry(&cpuid_data.cpuid, 1, 0);
if (c) {
has_msr_feature_control = !!(c->ecx & CPUID_EXT_VMX) ||
!!(c->ecx & CPUID_EXT_SMX);
}
cpuid_data.cpuid.padding = 0; cpuid_data.cpuid.padding = 0;
r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data); r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data);
if (r) { if (r) {
@ -1169,7 +1176,10 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
if (hyperv_vapic_recommended()) { if (hyperv_vapic_recommended()) {
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0); kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0);
} }
kvm_msr_entry_set(&msrs[n++], MSR_IA32_FEATURE_CONTROL, env->msr_ia32_feature_control); if (has_msr_feature_control) {
kvm_msr_entry_set(&msrs[n++], MSR_IA32_FEATURE_CONTROL,
env->msr_ia32_feature_control);
}
} }
if (env->mcg_cap) { if (env->mcg_cap) {
int i; int i;
@ -1394,7 +1404,9 @@ static int kvm_get_msrs(X86CPU *cpu)
if (has_msr_misc_enable) { if (has_msr_misc_enable) {
msrs[n++].index = MSR_IA32_MISC_ENABLE; msrs[n++].index = MSR_IA32_MISC_ENABLE;
} }
msrs[n++].index = MSR_IA32_FEATURE_CONTROL; if (has_msr_feature_control) {
msrs[n++].index = MSR_IA32_FEATURE_CONTROL;
}
if (!env->tsc_valid) { if (!env->tsc_valid) {
msrs[n++].index = MSR_IA32_TSC; msrs[n++].index = MSR_IA32_TSC;
@ -1509,6 +1521,7 @@ static int kvm_get_msrs(X86CPU *cpu)
break; break;
case MSR_IA32_FEATURE_CONTROL: case MSR_IA32_FEATURE_CONTROL:
env->msr_ia32_feature_control = msrs[i].data; env->msr_ia32_feature_control = msrs[i].data;
break;
default: default:
if (msrs[i].index >= MSR_MC0_CTL && if (msrs[i].index >= MSR_MC0_CTL &&
msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) { msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) {