diff mbox

i386/kvm: add support for Hyper-V TLB flush

Message ID 20180610184927.19309-1-vkuznets@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Vitaly Kuznetsov June 10, 2018, 6:49 p.m. UTC
Add support for Hyper-V TLB flush which recently got added to KVM.

Just like regular Hyper-V we announce HV_EX_PROCESSOR_MASKS_RECOMMENDED
regardless of how many vCPUs we have. Windows is 'smart' and uses less
expensive non-EX Hypercall whenever possible (when it wants to flush TLB
for all vCPUs or the maximum vCPU index in the vCPU set requires flushing
is less than 64).

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 linux-headers/linux/kvm.h  |  1 +
 target/i386/cpu.c          |  1 +
 target/i386/cpu.h          |  1 +
 target/i386/hyperv-proto.h |  1 +
 target/i386/kvm.c          | 15 ++++++++++++++-
 5 files changed, 18 insertions(+), 1 deletion(-)

Comments

Roman Kagan June 11, 2018, 3:45 p.m. UTC | #1
On Sun, Jun 10, 2018 at 08:49:27PM +0200, Vitaly Kuznetsov wrote:
> Add support for Hyper-V TLB flush which recently got added to KVM.
> 
> Just like regular Hyper-V we announce HV_EX_PROCESSOR_MASKS_RECOMMENDED
> regardless of how many vCPUs we have. Windows is 'smart' and uses less
> expensive non-EX Hypercall whenever possible (when it wants to flush TLB
> for all vCPUs or the maximum vCPU index in the vCPU set requires flushing
> is less than 64).

Indeed, reading the spec it sounds like this bit indicates the
availability of hypercalls accepting sparse processor sets, rather than
the recommendation to use them (dunno if we want to ajust the name).

> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
> ---
>  linux-headers/linux/kvm.h  |  1 +
>  target/i386/cpu.c          |  1 +
>  target/i386/cpu.h          |  1 +
>  target/i386/hyperv-proto.h |  1 +
>  target/i386/kvm.c          | 15 ++++++++++++++-
>  5 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
> index cdb148e959..a52a685690 100644
> --- a/linux-headers/linux/kvm.h
> +++ b/linux-headers/linux/kvm.h
> @@ -948,6 +948,7 @@ struct kvm_ppc_resize_hpt {
>  #define KVM_CAP_S390_BPB 152
>  #define KVM_CAP_GET_MSR_FEATURES 153
>  #define KVM_CAP_HYPERV_EVENTFD 154
> +#define KVM_CAP_HYPERV_TLBFLUSH 155
>  
>  #ifdef KVM_CAP_IRQ_ROUTING
>  

This header is imported from the kernel, so, to make life easier for the
maintainers, I tend to post changes to it in a separate patch,
indicating which kernel version contains it (AFAIK it's in kvm/queue
ATM).  But if they actually do want it they'll let you know ;)

Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Vitaly Kuznetsov June 29, 2018, 12:23 p.m. UTC | #2
Vitaly Kuznetsov <vkuznets@redhat.com> writes:

> Add support for Hyper-V TLB flush which recently got added to KVM.
>
> Just like regular Hyper-V we announce HV_EX_PROCESSOR_MASKS_RECOMMENDED
> regardless of how many vCPUs we have. Windows is 'smart' and uses less
> expensive non-EX Hypercall whenever possible (when it wants to flush TLB
> for all vCPUs or the maximum vCPU index in the vCPU set requires flushing
> is less than 64).
>

Ping?
Paolo Bonzini June 29, 2018, 1:55 p.m. UTC | #3
On 10/06/2018 20:49, Vitaly Kuznetsov wrote:
> Add support for Hyper-V TLB flush which recently got added to KVM.
> 
> Just like regular Hyper-V we announce HV_EX_PROCESSOR_MASKS_RECOMMENDED
> regardless of how many vCPUs we have. Windows is 'smart' and uses less
> expensive non-EX Hypercall whenever possible (when it wants to flush TLB
> for all vCPUs or the maximum vCPU index in the vCPU set requires flushing
> is less than 64).
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
> ---
>  linux-headers/linux/kvm.h  |  1 +
>  target/i386/cpu.c          |  1 +
>  target/i386/cpu.h          |  1 +
>  target/i386/hyperv-proto.h |  1 +
>  target/i386/kvm.c          | 15 ++++++++++++++-
>  5 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
> index cdb148e959..a52a685690 100644
> --- a/linux-headers/linux/kvm.h
> +++ b/linux-headers/linux/kvm.h
> @@ -948,6 +948,7 @@ struct kvm_ppc_resize_hpt {
>  #define KVM_CAP_S390_BPB 152
>  #define KVM_CAP_GET_MSR_FEATURES 153
>  #define KVM_CAP_HYPERV_EVENTFD 154
> +#define KVM_CAP_HYPERV_TLBFLUSH 155
>  
>  #ifdef KVM_CAP_IRQ_ROUTING
>  
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 94260412e2..756cc78808 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -5151,6 +5151,7 @@ static Property x86_cpu_properties[] = {
>      DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
>      DEFINE_PROP_BOOL("hv-frequencies", X86CPU, hyperv_frequencies, false),
>      DEFINE_PROP_BOOL("hv-reenlightenment", X86CPU, hyperv_reenlightenment, false),
> +    DEFINE_PROP_BOOL("hv-tlbflush", X86CPU, hyperv_tlbflush, false),
>      DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
>      DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
>      DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 664504610e..738d695331 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -1363,6 +1363,7 @@ struct X86CPU {
>      bool hyperv_stimer;
>      bool hyperv_frequencies;
>      bool hyperv_reenlightenment;
> +    bool hyperv_tlbflush;
>      bool check_cpuid;
>      bool enforce_cpuid;
>      bool expose_kvm;
> diff --git a/target/i386/hyperv-proto.h b/target/i386/hyperv-proto.h
> index 93352ebd2a..d6d5a79293 100644
> --- a/target/i386/hyperv-proto.h
> +++ b/target/i386/hyperv-proto.h
> @@ -58,6 +58,7 @@
>  #define HV_APIC_ACCESS_RECOMMENDED          (1u << 3)
>  #define HV_SYSTEM_RESET_RECOMMENDED         (1u << 4)
>  #define HV_RELAXED_TIMING_RECOMMENDED       (1u << 5)
> +#define HV_EX_PROCESSOR_MASKS_RECOMMENDED   (1u << 11)
>  
>  /*
>   * Basic virtualized MSRs
> diff --git a/target/i386/kvm.c b/target/i386/kvm.c
> index 44f70733e7..91c8e952c8 100644
> --- a/target/i386/kvm.c
> +++ b/target/i386/kvm.c
> @@ -585,7 +585,8 @@ static bool hyperv_enabled(X86CPU *cpu)
>              cpu->hyperv_runtime ||
>              cpu->hyperv_synic ||
>              cpu->hyperv_stimer ||
> -            cpu->hyperv_reenlightenment);
> +            cpu->hyperv_reenlightenment ||
> +            cpu->hyperv_tlbflush);
>  }
>  
>  static int kvm_arch_set_tsc_khz(CPUState *cs)
> @@ -823,6 +824,18 @@ int kvm_arch_init_vcpu(CPUState *cs)
>          if (cpu->hyperv_vapic) {
>              c->eax |= HV_APIC_ACCESS_RECOMMENDED;
>          }
> +        if (cpu->hyperv_tlbflush) {
> +            if (kvm_check_extension(cs->kvm_state,
> +                                    KVM_CAP_HYPERV_TLBFLUSH) <= 0) {
> +                fprintf(stderr, "Hyper-V TLB flush support "
> +                        "(requested by 'hv-tlbflush' cpu flag) "
> +                        " is not supported by kernel\n");
> +                return -ENOSYS;
> +            }
> +            c->eax |= HV_REMOTE_TLB_FLUSH_RECOMMENDED;
> +            c->eax |= HV_EX_PROCESSOR_MASKS_RECOMMENDED;
> +        }
> +
>          c->ebx = cpu->hyperv_spinlock_attempts;
>  
>          c = &cpuid_data.entries[cpuid_i++];
> 

Queued, thanks.

Paolo
diff mbox

Patch

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index cdb148e959..a52a685690 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -948,6 +948,7 @@  struct kvm_ppc_resize_hpt {
 #define KVM_CAP_S390_BPB 152
 #define KVM_CAP_GET_MSR_FEATURES 153
 #define KVM_CAP_HYPERV_EVENTFD 154
+#define KVM_CAP_HYPERV_TLBFLUSH 155
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 94260412e2..756cc78808 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5151,6 +5151,7 @@  static Property x86_cpu_properties[] = {
     DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
     DEFINE_PROP_BOOL("hv-frequencies", X86CPU, hyperv_frequencies, false),
     DEFINE_PROP_BOOL("hv-reenlightenment", X86CPU, hyperv_reenlightenment, false),
+    DEFINE_PROP_BOOL("hv-tlbflush", X86CPU, hyperv_tlbflush, false),
     DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
     DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
     DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 664504610e..738d695331 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1363,6 +1363,7 @@  struct X86CPU {
     bool hyperv_stimer;
     bool hyperv_frequencies;
     bool hyperv_reenlightenment;
+    bool hyperv_tlbflush;
     bool check_cpuid;
     bool enforce_cpuid;
     bool expose_kvm;
diff --git a/target/i386/hyperv-proto.h b/target/i386/hyperv-proto.h
index 93352ebd2a..d6d5a79293 100644
--- a/target/i386/hyperv-proto.h
+++ b/target/i386/hyperv-proto.h
@@ -58,6 +58,7 @@ 
 #define HV_APIC_ACCESS_RECOMMENDED          (1u << 3)
 #define HV_SYSTEM_RESET_RECOMMENDED         (1u << 4)
 #define HV_RELAXED_TIMING_RECOMMENDED       (1u << 5)
+#define HV_EX_PROCESSOR_MASKS_RECOMMENDED   (1u << 11)
 
 /*
  * Basic virtualized MSRs
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 44f70733e7..91c8e952c8 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -585,7 +585,8 @@  static bool hyperv_enabled(X86CPU *cpu)
             cpu->hyperv_runtime ||
             cpu->hyperv_synic ||
             cpu->hyperv_stimer ||
-            cpu->hyperv_reenlightenment);
+            cpu->hyperv_reenlightenment ||
+            cpu->hyperv_tlbflush);
 }
 
 static int kvm_arch_set_tsc_khz(CPUState *cs)
@@ -823,6 +824,18 @@  int kvm_arch_init_vcpu(CPUState *cs)
         if (cpu->hyperv_vapic) {
             c->eax |= HV_APIC_ACCESS_RECOMMENDED;
         }
+        if (cpu->hyperv_tlbflush) {
+            if (kvm_check_extension(cs->kvm_state,
+                                    KVM_CAP_HYPERV_TLBFLUSH) <= 0) {
+                fprintf(stderr, "Hyper-V TLB flush support "
+                        "(requested by 'hv-tlbflush' cpu flag) "
+                        " is not supported by kernel\n");
+                return -ENOSYS;
+            }
+            c->eax |= HV_REMOTE_TLB_FLUSH_RECOMMENDED;
+            c->eax |= HV_EX_PROCESSOR_MASKS_RECOMMENDED;
+        }
+
         c->ebx = cpu->hyperv_spinlock_attempts;
 
         c = &cpuid_data.entries[cpuid_i++];