Vineeth Pillai <viremana@xxxxxxxxxxxxxxxxxxx> writes: > From Hyper-V TLFS: > "The hypervisor exposes hypercalls (HvFlushVirtualAddressSpace, > HvFlushVirtualAddressSpaceEx, HvFlushVirtualAddressList, and > HvFlushVirtualAddressListEx) that allow operating systems to more > efficiently manage the virtual TLB. The L1 hypervisor can choose to > allow its guest to use those hypercalls and delegate the responsibility > to handle them to the L0 hypervisor. This requires the use of a > partition assist page." > > Add the Direct Virtual Flush support for SVM. > > Related VMX changes: > commit 6f6a657c9998 ("KVM/Hyper-V/VMX: Add direct tlb flush support") > > Signed-off-by: Vineeth Pillai <viremana@xxxxxxxxxxxxxxxxxxx> > --- > arch/x86/kvm/svm/svm.c | 48 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 48 insertions(+) > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c > index 3562a247b7e8..c6d3f3a7c986 100644 > --- a/arch/x86/kvm/svm/svm.c > +++ b/arch/x86/kvm/svm/svm.c > @@ -440,6 +440,32 @@ static void svm_init_osvw(struct kvm_vcpu *vcpu) > vcpu->arch.osvw.status |= 1; > } > > +#if IS_ENABLED(CONFIG_HYPERV) > +static int hv_enable_direct_tlbflush(struct kvm_vcpu *vcpu) > +{ > + struct hv_enlightenments *hve; > + struct hv_partition_assist_pg **p_hv_pa_pg = > + &to_kvm_hv(vcpu->kvm)->hv_pa_pg; > + > + if (!*p_hv_pa_pg) > + *p_hv_pa_pg = kzalloc(PAGE_SIZE, GFP_KERNEL); > + > + if (!*p_hv_pa_pg) > + return -ENOMEM; > + > + hve = (struct hv_enlightenments *)&to_svm(vcpu)->vmcb->hv_enlightenments; > + > + hve->partition_assist_page = __pa(*p_hv_pa_pg); > + hve->hv_vm_id = (unsigned long)vcpu->kvm; > + if (!hve->hv_enlightenments_control.nested_flush_hypercall) { > + hve->hv_enlightenments_control.nested_flush_hypercall = 1; > + vmcb_mark_dirty(to_svm(vcpu)->vmcb, VMCB_HV_NESTED_ENLIGHTENMENTS); > + } > + > + return 0; > +} > +#endif > + > static int has_svm(void) > { > const char *msg; > @@ -1034,6 +1060,21 @@ static __init int svm_hardware_setup(void) > svm_x86_ops.tlb_remote_flush_with_range = > kvm_hv_remote_flush_tlb_with_range; > } > + > + if (ms_hyperv.nested_features & HV_X64_NESTED_DIRECT_FLUSH) { > + pr_info("kvm: Hyper-V Direct TLB Flush enabled\n"); > + for_each_online_cpu(cpu) { > + struct hv_vp_assist_page *vp_ap = > + hv_get_vp_assist_page(cpu); > + > + if (!vp_ap) > + continue; > + > + vp_ap->nested_control.features.directhypercall = 1; > + } > + svm_x86_ops.enable_direct_tlbflush = > + hv_enable_direct_tlbflush; > + } > #endif > > if (nrips) { > @@ -3913,6 +3954,13 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) > } > svm->vmcb->save.cr2 = vcpu->arch.cr2; > > +#if IS_ENABLED(CONFIG_HYPERV) > + if (svm->vmcb->hv_enlightenments.hv_vp_id != to_hv_vcpu(vcpu)->vp_index) { This looks wrong (see my previous comment about mixing KVM-on-Hyper-V and Windows/Hyper-V-on-KVM). 'to_hv_vcpu(vcpu)->vp_index' is 'Windows/Hyper-V-on-KVM' thingy, it does not exist when we run without any Hyper-V enlightenments exposed (e.g. when we run Linux as our guest). > + svm->vmcb->hv_enlightenments.hv_vp_id = to_hv_vcpu(vcpu)->vp_index; > + vmcb_mark_dirty(svm->vmcb, VMCB_HV_NESTED_ENLIGHTENMENTS); > + } > +#endif > + > /* > * Run with all-zero DR6 unless needed, so that we can get the exact cause > * of a #DB. -- Vitaly