* [PATCH] x86:kvm:hyperv: make VP_INDEX managed by userspace
@ 2017-06-16 15:16 Roman Kagan
2017-06-16 16:03 ` Radim Krčmář
0 siblings, 1 reply; 2+ messages in thread
From: Roman Kagan @ 2017-06-16 15:16 UTC (permalink / raw)
To: kvm, Radim Krčmář, Paolo Bonzini
Cc: Evgeny Yakovlev, Denis V . Lunev, Eduardo Habkost, Igor Mammedov
Hyper-V identifies vCPUs by Virtual Processor Index, which can be
queried 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.
APIC ids can be sparse and thus aren't a valid replacement for VP
indices.
Current KVM uses its internal vcpu index as VP_INDEX. However, to make
it predictable and persistent across VM migrations, the userspace has to
control the value of VP_INDEX.
This patch achieves that, by storing vp_index explicitly on vcpu, and
allowing HV_X64_MSR_VP_INDEX to be set from the host side. For
compatibility it's initialized to KVM vcpu index. Also a few variables
are renamed to make clear distinction betweed this Hyper-V vp_index and
KVM vcpu_id (== APIC id).
Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
---
arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/kvm/hyperv.c | 49 +++++++++++++++++++++++++----------------
2 files changed, 31 insertions(+), 19 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 695605e..29c14d1 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -462,6 +462,7 @@ struct kvm_vcpu_hv_synic {
/* Hyper-V per vcpu emulation context */
struct kvm_vcpu_hv {
+ u32 vp_index;
u64 hv_vapic;
s64 runtime_offset;
struct kvm_vcpu_hv_synic synic;
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index ebae57a..015d54a 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -106,14 +106,27 @@ static int synic_set_sint(struct kvm_vcpu_hv_synic *synic, int sint,
return 0;
}
-static struct kvm_vcpu_hv_synic *synic_get(struct kvm *kvm, u32 vcpu_id)
+static struct kvm_vcpu *get_vcpu_by_vpidx(struct kvm *kvm, u32 vpidx)
+{
+ struct kvm_vcpu *vcpu = NULL;
+ int i;
+
+ if (vpidx < KVM_MAX_VCPUS)
+ vcpu = kvm_get_vcpu(kvm, vpidx);
+ if (vcpu && vcpu_to_hv_vcpu(vcpu)->vp_index == vpidx)
+ return vcpu;
+ kvm_for_each_vcpu(i, vcpu, kvm)
+ if (vcpu_to_hv_vcpu(vcpu)->vp_index == vpidx)
+ return vcpu;
+ return NULL;
+}
+
+static struct kvm_vcpu_hv_synic *synic_get(struct kvm *kvm, u32 vpidx)
{
struct kvm_vcpu *vcpu;
struct kvm_vcpu_hv_synic *synic;
- if (vcpu_id >= atomic_read(&kvm->online_vcpus))
- return NULL;
- vcpu = kvm_get_vcpu(kvm, vcpu_id);
+ vcpu = get_vcpu_by_vpidx(kvm, vpidx);
if (!vcpu)
return NULL;
synic = vcpu_to_synic(vcpu);
@@ -318,11 +331,11 @@ static int synic_set_irq(struct kvm_vcpu_hv_synic *synic, u32 sint)
return ret;
}
-int kvm_hv_synic_set_irq(struct kvm *kvm, u32 vcpu_id, u32 sint)
+int kvm_hv_synic_set_irq(struct kvm *kvm, u32 vpidx, u32 sint)
{
struct kvm_vcpu_hv_synic *synic;
- synic = synic_get(kvm, vcpu_id);
+ synic = synic_get(kvm, vpidx);
if (!synic)
return -EINVAL;
@@ -341,11 +354,11 @@ void kvm_hv_synic_send_eoi(struct kvm_vcpu *vcpu, int vector)
kvm_hv_notify_acked_sint(vcpu, i);
}
-static int kvm_hv_set_sint_gsi(struct kvm *kvm, u32 vcpu_id, u32 sint, int gsi)
+static int kvm_hv_set_sint_gsi(struct kvm *kvm, u32 vpidx, u32 sint, int gsi)
{
struct kvm_vcpu_hv_synic *synic;
- synic = synic_get(kvm, vcpu_id);
+ synic = synic_get(kvm, vpidx);
if (!synic)
return -EINVAL;
@@ -680,6 +693,8 @@ void kvm_hv_vcpu_init(struct kvm_vcpu *vcpu)
struct kvm_vcpu_hv *hv_vcpu = vcpu_to_hv_vcpu(vcpu);
int i;
+ hv_vcpu->vp_index = kvm_vcpu_get_idx(vcpu);
+
synic_init(&hv_vcpu->synic);
bitmap_zero(hv_vcpu->stimer_pending_bitmap, HV_SYNIC_STIMER_COUNT);
@@ -978,6 +993,11 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host)
struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv;
switch (msr) {
+ case HV_X64_MSR_VP_INDEX:
+ if (!host)
+ return 1;
+ hv->vp_index = (u32)data;
+ break;
case HV_X64_MSR_APIC_ASSIST_PAGE: {
u64 gfn;
unsigned long addr;
@@ -1089,18 +1109,9 @@ static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv;
switch (msr) {
- case HV_X64_MSR_VP_INDEX: {
- int r;
- struct kvm_vcpu *v;
-
- kvm_for_each_vcpu(r, v, vcpu->kvm) {
- if (v == vcpu) {
- data = r;
- break;
- }
- }
+ case HV_X64_MSR_VP_INDEX:
+ data = hv->vp_index;
break;
- }
case HV_X64_MSR_EOI:
return kvm_hv_vapic_msr_read(vcpu, APIC_EOI, pdata);
case HV_X64_MSR_ICR:
--
2.9.4
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] x86:kvm:hyperv: make VP_INDEX managed by userspace
2017-06-16 15:16 [PATCH] x86:kvm:hyperv: make VP_INDEX managed by userspace Roman Kagan
@ 2017-06-16 16:03 ` Radim Krčmář
0 siblings, 0 replies; 2+ messages in thread
From: Radim Krčmář @ 2017-06-16 16:03 UTC (permalink / raw)
To: Roman Kagan
Cc: kvm, Paolo Bonzini, Evgeny Yakovlev, Denis V . Lunev,
Eduardo Habkost, Igor Mammedov
2017-06-16 18:16+0300, Roman Kagan:
> Hyper-V identifies vCPUs by Virtual Processor Index, which can be
> queried 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.
> APIC ids can be sparse and thus aren't a valid replacement for VP
> indices.
>
> Current KVM uses its internal vcpu index as VP_INDEX. However, to make
> it predictable and persistent across VM migrations, the userspace has to
> control the value of VP_INDEX.
>
> This patch achieves that, by storing vp_index explicitly on vcpu, and
> allowing HV_X64_MSR_VP_INDEX to be set from the host side. For
> compatibility it's initialized to KVM vcpu index. Also a few variables
> are renamed to make clear distinction betweed this Hyper-V vp_index and
> KVM vcpu_id (== APIC id).
>
> Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
> ---
Please add a kvm capability, so userspace doesn't trigger the unhandled
wrmsr messages when detecting this feature.
Thanks.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-06-16 16:03 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-16 15:16 [PATCH] x86:kvm:hyperv: make VP_INDEX managed by userspace Roman Kagan
2017-06-16 16:03 ` Radim Krčmář
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox