1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * KVM L1 hypervisor optimizations on Hyper-V for SVM. 4 */ 5 6 #ifndef __ARCH_X86_KVM_SVM_ONHYPERV_H__ 7 #define __ARCH_X86_KVM_SVM_ONHYPERV_H__ 8 9 #if IS_ENABLED(CONFIG_HYPERV) 10 #include <asm/mshyperv.h> 11 12 #include "hyperv.h" 13 #include "kvm_onhyperv.h" 14 15 static struct kvm_x86_ops svm_x86_ops; 16 17 /* 18 * Hyper-V uses the software reserved 32 bytes in VMCB 19 * control area to expose SVM enlightenments to guests. 20 */ 21 struct hv_enlightenments { 22 struct __packed hv_enlightenments_control { 23 u32 nested_flush_hypercall:1; 24 u32 msr_bitmap:1; 25 u32 enlightened_npt_tlb: 1; 26 u32 reserved:29; 27 } __packed hv_enlightenments_control; 28 u32 hv_vp_id; 29 u64 hv_vm_id; 30 u64 partition_assist_page; 31 u64 reserved; 32 } __packed; 33 34 /* 35 * Hyper-V uses the software reserved clean bit in VMCB 36 */ 37 #define VMCB_HV_NESTED_ENLIGHTENMENTS VMCB_SW 38 39 int svm_hv_enable_direct_tlbflush(struct kvm_vcpu *vcpu); 40 41 static inline void svm_hv_init_vmcb(struct vmcb *vmcb) 42 { 43 struct hv_enlightenments *hve = 44 (struct hv_enlightenments *)vmcb->control.reserved_sw; 45 46 if (npt_enabled && 47 ms_hyperv.nested_features & HV_X64_NESTED_ENLIGHTENED_TLB) 48 hve->hv_enlightenments_control.enlightened_npt_tlb = 1; 49 50 if (ms_hyperv.nested_features & HV_X64_NESTED_MSR_BITMAP) 51 hve->hv_enlightenments_control.msr_bitmap = 1; 52 } 53 54 static inline void svm_hv_hardware_setup(void) 55 { 56 if (npt_enabled && 57 ms_hyperv.nested_features & HV_X64_NESTED_ENLIGHTENED_TLB) { 58 pr_info("kvm: Hyper-V enlightened NPT TLB flush enabled\n"); 59 svm_x86_ops.tlb_remote_flush = hv_remote_flush_tlb; 60 svm_x86_ops.tlb_remote_flush_with_range = 61 hv_remote_flush_tlb_with_range; 62 } 63 64 if (ms_hyperv.nested_features & HV_X64_NESTED_DIRECT_FLUSH) { 65 int cpu; 66 67 pr_info("kvm: Hyper-V Direct TLB Flush enabled\n"); 68 for_each_online_cpu(cpu) { 69 struct hv_vp_assist_page *vp_ap = 70 hv_get_vp_assist_page(cpu); 71 72 if (!vp_ap) 73 continue; 74 75 vp_ap->nested_control.features.directhypercall = 1; 76 } 77 svm_x86_ops.enable_direct_tlbflush = 78 svm_hv_enable_direct_tlbflush; 79 } 80 } 81 82 static inline void svm_hv_vmcb_dirty_nested_enlightenments( 83 struct kvm_vcpu *vcpu) 84 { 85 struct vmcb *vmcb = to_svm(vcpu)->vmcb; 86 struct hv_enlightenments *hve = 87 (struct hv_enlightenments *)vmcb->control.reserved_sw; 88 89 if (hve->hv_enlightenments_control.msr_bitmap) 90 vmcb_mark_dirty(vmcb, VMCB_HV_NESTED_ENLIGHTENMENTS); 91 } 92 93 static inline void svm_hv_update_vp_id(struct vmcb *vmcb, 94 struct kvm_vcpu *vcpu) 95 { 96 struct hv_enlightenments *hve = 97 (struct hv_enlightenments *)vmcb->control.reserved_sw; 98 u32 vp_index = kvm_hv_get_vpindex(vcpu); 99 100 if (hve->hv_vp_id != vp_index) { 101 hve->hv_vp_id = vp_index; 102 vmcb_mark_dirty(vmcb, VMCB_HV_NESTED_ENLIGHTENMENTS); 103 } 104 } 105 #else 106 107 static inline void svm_hv_init_vmcb(struct vmcb *vmcb) 108 { 109 } 110 111 static inline void svm_hv_hardware_setup(void) 112 { 113 } 114 115 static inline void svm_hv_vmcb_dirty_nested_enlightenments( 116 struct kvm_vcpu *vcpu) 117 { 118 } 119 120 static inline void svm_hv_update_vp_id(struct vmcb *vmcb, 121 struct kvm_vcpu *vcpu) 122 { 123 } 124 #endif /* CONFIG_HYPERV */ 125 126 #endif /* __ARCH_X86_KVM_SVM_ONHYPERV_H__ */ 127