[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 04/13] hyperv: ensure VP index equal to QEMU cpu_inde
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 04/13] hyperv: ensure VP index equal to QEMU cpu_index |
Date: |
Tue, 17 Jul 2018 17:06:46 +0200 |
From: Roman Kagan <address@hidden>
Hyper-V identifies vCPUs by Virtual Processor (VP) index which can be
queried by the guest via HV_X64_MSR_VP_INDEX msr. It is defined by the
spec as a sequential number which can't exceed the maximum number of
vCPUs per VM.
It has to be owned by QEMU in order to preserve it across migration.
However, the initial implementation in KVM didn't allow to set this
msr, and KVM used its own notion of VP index. Fortunately, the way
vCPUs are created in QEMU/KVM makes it likely that the KVM value is
equal to QEMU cpu_index.
So choose cpu_index as the value for vp_index, and push that to KVM on
kernels that support setting the msr. On older ones that don't, query
the kernel value and assert that it's in sync with QEMU.
Besides, since handling errors from vCPU init at hotplug time is
impossible, disable vCPU hotplug.
This patch also introduces accessor functions to encapsulate the mapping
between a vCPU and its vp_index.
Signed-off-by: Roman Kagan <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
hw/i386/pc.c | 5 +++++
target/i386/hyperv.c | 10 ++++++++++
target/i386/hyperv.h | 3 +++
target/i386/kvm-stub.c | 5 +++++
target/i386/kvm.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
target/i386/kvm_i386.h | 2 ++
6 files changed, 72 insertions(+)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 50d5553..83a4444 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1999,6 +1999,11 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
}
cpu->thread_id = topo.smt_id;
+ if (cpu->hyperv_vpindex && !kvm_hv_vpindex_settable()) {
+ error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX");
+ return;
+ }
+
cs = CPU(cpu);
cs->cpu_index = idx;
diff --git a/target/i386/hyperv.c b/target/i386/hyperv.c
index 7cc0fbb..3065d76 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 eaf3df3..00c9b45 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 bda4dc2..e7a673e 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 ebb2d23..9313602 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 e5df24c..3057ba4 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
--
1.8.3.1
- [Qemu-devel] [PULL 00/13] Misc fixes for QEMU 3.0.0-rc1, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 01/13] dump: add kernel_gs_base to QEMU CPU state, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 03/13] hyperv: rename vcpu_id to vp_index, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 02/13] accel: Fix typo and grammar in comment, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 06/13] PC Chipset: Improve serial divisor calculation, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 05/13] vhost-user-test: added proper TestServer *dest initialization in test_migrate(), Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 04/13] hyperv: ensure VP index equal to QEMU cpu_index,
Paolo Bonzini <=
- [Qemu-devel] [PULL 07/13] hw/char/serial: retry write if EAGAIN, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 09/13] virtio-scsi: fix hotplug ->reset() vs event race, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 12/13] opts: remove redundant check for NULL parameter, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 08/13] qdev: add HotplugHandler->post_plug() callback, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 10/13] i386: fix regression parsing multiboot initrd modules, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 11/13] i386: only parse the initrd_filename once for multiboot modules, Paolo Bonzini, 2018/07/17
- [Qemu-devel] [PULL 13/13] Document command line options with single dash, Paolo Bonzini, 2018/07/17
- Re: [Qemu-devel] [PULL 00/13] Misc fixes for QEMU 3.0.0-rc1, Peter Maydell, 2018/07/17