diff options
-rw-r--r-- | include/hw/i386/pc.h | 8 | ||||
-rw-r--r-- | target/i386/cpu.c | 2 | ||||
-rw-r--r-- | target/i386/cpu.h | 1 | ||||
-rw-r--r-- | target/i386/kvm.c | 30 |
4 files changed, 33 insertions, 8 deletions
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 6894f37df1..dfe6746692 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -294,6 +294,14 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); int e820_get_num_entries(void); bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); +#define PC_COMPAT_3_0 \ + HW_COMPAT_3_0 \ + {\ + .driver = TYPE_X86_CPU,\ + .property = "x-hv-synic-kvm-only",\ + .value = "on",\ + } + #define PC_COMPAT_2_12 \ HW_COMPAT_2_12 \ {\ diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 32ea041c06..f0d9f7cf49 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5607,6 +5607,8 @@ static Property x86_cpu_properties[] = { * to the specific Windows version being used." */ 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_END_OF_LIST() }; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index caa1544b2e..663f3a5e67 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1378,6 +1378,7 @@ struct X86CPU { bool hyperv_vpindex; bool hyperv_runtime; bool hyperv_synic; + bool hyperv_synic_kvm_only; bool hyperv_stimer; bool hyperv_frequencies; bool hyperv_reenlightenment; diff --git a/target/i386/kvm.c b/target/i386/kvm.c index cf6270ae39..7b7a56593e 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -734,8 +734,18 @@ static int hyperv_handle_properties(CPUState *cs) env->features[FEAT_HYPERV_EAX] |= HV_VP_RUNTIME_AVAILABLE; } if (cpu->hyperv_synic) { - if (!has_msr_hv_synic || - !kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_SYNIC)) { + unsigned int cap = KVM_CAP_HYPERV_SYNIC; + if (!cpu->hyperv_synic_kvm_only) { + if (!cpu->hyperv_vpindex) { + fprintf(stderr, "Hyper-V SynIC " + "(requested by 'hv-synic' cpu flag) " + "requires Hyper-V VP_INDEX ('hv-vpindex')\n"); + return -ENOSYS; + } + cap = KVM_CAP_HYPERV_SYNIC2; + } + + if (!has_msr_hv_synic || !kvm_check_extension(cs->kvm_state, cap)) { fprintf(stderr, "Hyper-V SynIC (requested by 'hv-synic' cpu flag) " "is not supported by kernel\n"); return -ENOSYS; @@ -784,18 +794,22 @@ static int hyperv_init_vcpu(X86CPU *cpu) } if (cpu->hyperv_synic) { - ret = kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0); + uint32_t synic_cap = cpu->hyperv_synic_kvm_only ? + KVM_CAP_HYPERV_SYNIC : KVM_CAP_HYPERV_SYNIC2; + ret = kvm_vcpu_enable_cap(cs, synic_cap, 0); if (ret < 0) { error_report("failed to turn on HyperV SynIC in KVM: %s", strerror(-ret)); return ret; } - ret = hyperv_x86_synic_add(cpu); - if (ret < 0) { - error_report("failed to create HyperV SynIC: %s", - strerror(-ret)); - return ret; + if (!cpu->hyperv_synic_kvm_only) { + ret = hyperv_x86_synic_add(cpu); + if (ret < 0) { + error_report("failed to create HyperV SynIC: %s", + strerror(-ret)); + return ret; + } } } |