Message ID | 20190809094939.76093-3-Tianyu.Lan@microsoft.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM/Hyper-V: Add Hyper-V direct tlb flush support | expand |
lantianyu1986@gmail.com writes: > From: Tianyu Lan <Tianyu.Lan@microsoft.com> > > This patch adds new KVM cap KVM_CAP_HYPERV_DIRECT_TLBFLUSH and let > user space to enable direct tlb flush function when only Hyper-V > hypervsior capability is exposed to VM. This patch also adds > enable_direct_tlbflush callback in the struct kvm_x86_ops and > platforms may use it to implement direct tlb flush support. > > Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com> > --- > Documentation/virtual/kvm/api.txt | 10 ++++++++++ > arch/x86/include/asm/kvm_host.h | 2 ++ > arch/x86/kvm/x86.c | 8 ++++++++ > include/uapi/linux/kvm.h | 1 + > 4 files changed, 21 insertions(+) > > diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt > index 2cd6250b2896..45308ed6dd75 100644 > --- a/Documentation/virtual/kvm/api.txt > +++ b/Documentation/virtual/kvm/api.txt > @@ -5289,3 +5289,13 @@ Architectures: x86 > This capability indicates that KVM supports paravirtualized Hyper-V IPI send > hypercalls: > HvCallSendSyntheticClusterIpi, HvCallSendSyntheticClusterIpiEx. > +8.21 KVM_CAP_HYPERV_DIRECT_TLBFLUSH > + > +Architecture: x86 > + > +This capability indicates that KVM supports Hyper-V direct tlb flush function. > +User space should enable this feature only when Hyper-V hypervisor capability > +is exposed to guest and KVM profile is hided. Both Hyper-V and KVM hypercalls > +use RAX and RCX registers to pass parameters. If KVM hypercall is exposed > +to L2 guest with direct tlbflush enabled, Hyper-V may mistake KVM hypercall > +for Hyper-V tlb flush Hypercall due to paremeter register overlap. First, we need to explicitly state that this is for KVM on Hyper-V and second, that this disables normal hypercall handling by KVM. My take: This capability indicates that KVM running on top of Hyper-V hypervisor enables Direct TLB flush for its guests meaning that TLB flush hypercalls are handled by Level 1 hypervisor (Hyper-V) bypassing KVM. Due to the different ABI for hypercall parameters between Hyper-V and KVM, enabling this capability effectively disables all hypercall handling by KVM (as some KVM hypercall may be mistakenly treated as TLB flush hypercalls by Hyper-C) so userspace should disable KVM identification in CPUID. I think we should also enforce this somehow leaving only Hyper-V style hypercalls handling (for Windows guests) in place. > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 0cc5b611a113..667d154e89d4 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -1205,6 +1205,8 @@ struct kvm_x86_ops { > uint16_t (*nested_get_evmcs_version)(struct kvm_vcpu *vcpu); > > bool (*need_emulation_on_page_fault)(struct kvm_vcpu *vcpu); > + > + int (*enable_direct_tlbflush)(struct kvm_vcpu *vcpu); > }; > > struct kvm_arch_async_pf { > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 9d7b9e6a0939..a9d8ee7f7bf0 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -3183,6 +3183,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) > r = kvm_x86_ops->get_nested_state ? > kvm_x86_ops->get_nested_state(NULL, NULL, 0) : 0; > break; > + case KVM_CAP_HYPERV_DIRECT_TLBFLUSH: > + r = kvm_x86_ops->enable_direct_tlbflush ? 1 : 0; > + break; > default: > break; > } > @@ -3953,6 +3956,11 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, > r = -EFAULT; > } > return r; > + case KVM_CAP_HYPERV_DIRECT_TLBFLUSH: > + if (!kvm_x86_ops->enable_direct_tlbflush) > + return -ENOTTY; > + > + return kvm_x86_ops->enable_direct_tlbflush(vcpu); > > default: > return -EINVAL; > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h > index a7c19540ce21..cb959bc925b1 100644 > --- a/include/uapi/linux/kvm.h > +++ b/include/uapi/linux/kvm.h > @@ -996,6 +996,7 @@ struct kvm_ppc_resize_hpt { > #define KVM_CAP_ARM_PTRAUTH_ADDRESS 171 > #define KVM_CAP_ARM_PTRAUTH_GENERIC 172 > #define KVM_CAP_PMU_EVENT_FILTER 173 > +#define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 174 > > #ifdef KVM_CAP_IRQ_ROUTING
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 2cd6250b2896..45308ed6dd75 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -5289,3 +5289,13 @@ Architectures: x86 This capability indicates that KVM supports paravirtualized Hyper-V IPI send hypercalls: HvCallSendSyntheticClusterIpi, HvCallSendSyntheticClusterIpiEx. +8.21 KVM_CAP_HYPERV_DIRECT_TLBFLUSH + +Architecture: x86 + +This capability indicates that KVM supports Hyper-V direct tlb flush function. +User space should enable this feature only when Hyper-V hypervisor capability +is exposed to guest and KVM profile is hided. Both Hyper-V and KVM hypercalls +use RAX and RCX registers to pass parameters. If KVM hypercall is exposed +to L2 guest with direct tlbflush enabled, Hyper-V may mistake KVM hypercall +for Hyper-V tlb flush Hypercall due to paremeter register overlap. diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 0cc5b611a113..667d154e89d4 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1205,6 +1205,8 @@ struct kvm_x86_ops { uint16_t (*nested_get_evmcs_version)(struct kvm_vcpu *vcpu); bool (*need_emulation_on_page_fault)(struct kvm_vcpu *vcpu); + + int (*enable_direct_tlbflush)(struct kvm_vcpu *vcpu); }; struct kvm_arch_async_pf { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9d7b9e6a0939..a9d8ee7f7bf0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3183,6 +3183,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = kvm_x86_ops->get_nested_state ? kvm_x86_ops->get_nested_state(NULL, NULL, 0) : 0; break; + case KVM_CAP_HYPERV_DIRECT_TLBFLUSH: + r = kvm_x86_ops->enable_direct_tlbflush ? 1 : 0; + break; default: break; } @@ -3953,6 +3956,11 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, r = -EFAULT; } return r; + case KVM_CAP_HYPERV_DIRECT_TLBFLUSH: + if (!kvm_x86_ops->enable_direct_tlbflush) + return -ENOTTY; + + return kvm_x86_ops->enable_direct_tlbflush(vcpu); default: return -EINVAL; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a7c19540ce21..cb959bc925b1 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -996,6 +996,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_ARM_PTRAUTH_ADDRESS 171 #define KVM_CAP_ARM_PTRAUTH_GENERIC 172 #define KVM_CAP_PMU_EVENT_FILTER 173 +#define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 174 #ifdef KVM_CAP_IRQ_ROUTING