aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/i386/hyperv.c10
-rw-r--r--target/i386/hyperv.h3
-rw-r--r--target/i386/kvm-stub.c5
-rw-r--r--target/i386/kvm.c47
-rw-r--r--target/i386/kvm_i386.h2
5 files changed, 67 insertions, 0 deletions
diff --git a/target/i386/hyperv.c b/target/i386/hyperv.c
index 7cc0fbb272..3065d765ed 100644
--- a/target/i386/hyperv.c
+++ b/target/i386/hyperv.c
@@ -16,6 +16,16 @@
#include "hyperv.h"
#include "hyperv-proto.h"
+uint32_t hyperv_vp_index(X86CPU *cpu)
+{
+ return CPU(cpu)->cpu_index;
+}
+
+X86CPU *hyperv_find_vcpu(uint32_t vp_index)
+{
+ return X86_CPU(qemu_get_cpu(vp_index));
+}
+
int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
{
CPUX86State *env = &cpu->env;
diff --git a/target/i386/hyperv.h b/target/i386/hyperv.h
index eaf3df34b0..00c9b454bb 100644
--- a/target/i386/hyperv.h
+++ b/target/i386/hyperv.h
@@ -39,4 +39,7 @@ void kvm_hv_sint_route_destroy(HvSintRoute *sint_route);
int kvm_hv_sint_route_set_sint(HvSintRoute *sint_route);
+uint32_t hyperv_vp_index(X86CPU *cpu);
+X86CPU *hyperv_find_vcpu(uint32_t vp_index);
+
#endif
diff --git a/target/i386/kvm-stub.c b/target/i386/kvm-stub.c
index bda4dc2f0c..e7a673e5db 100644
--- a/target/i386/kvm-stub.c
+++ b/target/i386/kvm-stub.c
@@ -40,3 +40,8 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
abort();
}
#endif
+
+bool kvm_hv_vpindex_settable(void)
+{
+ return false;
+}
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index ebb2d23aa4..9313602d3d 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -85,6 +85,7 @@ static bool has_msr_hv_hypercall;
static bool has_msr_hv_crash;
static bool has_msr_hv_reset;
static bool has_msr_hv_vpindex;
+static bool hv_vpindex_settable;
static bool has_msr_hv_runtime;
static bool has_msr_hv_synic;
static bool has_msr_hv_stimer;
@@ -162,6 +163,11 @@ bool kvm_enable_x2apic(void)
has_x2apic_api);
}
+bool kvm_hv_vpindex_settable(void)
+{
+ return hv_vpindex_settable;
+}
+
static int kvm_get_tsc(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
@@ -745,6 +751,37 @@ static int hyperv_handle_properties(CPUState *cs)
return 0;
}
+static int hyperv_init_vcpu(X86CPU *cpu)
+{
+ if (cpu->hyperv_vpindex && !hv_vpindex_settable) {
+ /*
+ * the kernel doesn't support setting vp_index; assert that its value
+ * is in sync
+ */
+ int ret;
+ struct {
+ struct kvm_msrs info;
+ struct kvm_msr_entry entries[1];
+ } msr_data = {
+ .info.nmsrs = 1,
+ .entries[0].index = HV_X64_MSR_VP_INDEX,
+ };
+
+ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data);
+ if (ret < 0) {
+ return ret;
+ }
+ assert(ret == 1);
+
+ if (msr_data.entries[0].data != hyperv_vp_index(cpu)) {
+ error_report("kernel's vp_index != QEMU's vp_index");
+ return -ENXIO;
+ }
+ }
+
+ return 0;
+}
+
static Error *invtsc_mig_blocker;
#define KVM_MAX_CPUID_ENTRIES 100
@@ -1160,6 +1197,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
has_msr_tsc_aux = false;
}
+ r = hyperv_init_vcpu(cpu);
+ if (r) {
+ goto fail;
+ }
+
return 0;
fail:
@@ -1351,6 +1393,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
#endif
+ hv_vpindex_settable = kvm_check_extension(s, KVM_CAP_HYPERV_VP_INDEX);
+
ret = kvm_get_supported_msrs(s);
if (ret < 0) {
return ret;
@@ -1900,6 +1944,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
if (has_msr_hv_runtime) {
kvm_msr_entry_add(cpu, HV_X64_MSR_VP_RUNTIME, env->msr_hv_runtime);
}
+ if (cpu->hyperv_vpindex && hv_vpindex_settable) {
+ kvm_msr_entry_add(cpu, HV_X64_MSR_VP_INDEX, hyperv_vp_index(cpu));
+ }
if (cpu->hyperv_synic) {
int j;
diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h
index e5df24cad1..3057ba4f7d 100644
--- a/target/i386/kvm_i386.h
+++ b/target/i386/kvm_i386.h
@@ -63,4 +63,6 @@ void kvm_put_apicbase(X86CPU *cpu, uint64_t value);
bool kvm_enable_x2apic(void);
bool kvm_has_x2apic_api(void);
+
+bool kvm_hv_vpindex_settable(void);
#endif