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 51 static inline void svm_hv_hardware_setup(void) 52 { 53 if (npt_enabled && 54 ms_hyperv.nested_features & HV_X64_NESTED_ENLIGHTENED_TLB) { 55 pr_info("kvm: Hyper-V enlightened NPT TLB flush enabled\n"); 56 svm_x86_ops.tlb_remote_flush = hv_remote_flush_tlb; 57 svm_x86_ops.tlb_remote_flush_with_range = 58 hv_remote_flush_tlb_with_range; 59 } 60 61 if (ms_hyperv.nested_features & HV_X64_NESTED_DIRECT_FLUSH) { 62 int cpu; 63 64 pr_info("kvm: Hyper-V Direct TLB Flush enabled\n"); 65 for_each_online_cpu(cpu) { 66 struct hv_vp_assist_page *vp_ap = 67 hv_get_vp_assist_page(cpu); 68 69 if (!vp_ap) 70 continue; 71 72 vp_ap->nested_control.features.directhypercall = 1; 73 } 74 svm_x86_ops.enable_direct_tlbflush = 75 svm_hv_enable_direct_tlbflush; 76 } 77 } 78 79 static inline void svm_hv_vmcb_dirty_nested_enlightenments( 80 struct kvm_vcpu *vcpu) 81 { 82 struct vmcb *vmcb = to_svm(vcpu)->vmcb; 83 struct hv_enlightenments *hve = 84 (struct hv_enlightenments *)vmcb->control.reserved_sw; 85 86 /* 87 * vmcb can be NULL if called during early vcpu init. 88 * And its okay not to mark vmcb dirty during vcpu init 89 * as we mark it dirty unconditionally towards end of vcpu 90 * init phase. 91 */ 92 if (vmcb_is_clean(vmcb, VMCB_HV_NESTED_ENLIGHTENMENTS) && 93 hve->hv_enlightenments_control.msr_bitmap) 94 vmcb_mark_dirty(vmcb, VMCB_HV_NESTED_ENLIGHTENMENTS); 95 } 96 97 static inline void svm_hv_update_vp_id(struct vmcb *vmcb, 98 struct kvm_vcpu *vcpu) 99 { 100 struct hv_enlightenments *hve = 101 (struct hv_enlightenments *)vmcb->control.reserved_sw; 102 u32 vp_index = kvm_hv_get_vpindex(vcpu); 103 104 if (hve->hv_vp_id != vp_index) { 105 hve->hv_vp_id = vp_index; 106 vmcb_mark_dirty(vmcb, VMCB_HV_NESTED_ENLIGHTENMENTS); 107 } 108 } 109 #else 110 111 static inline void svm_hv_init_vmcb(struct vmcb *vmcb) 112 { 113 } 114 115 static inline void svm_hv_hardware_setup(void) 116 { 117 } 118 119 static inline void svm_hv_vmcb_dirty_nested_enlightenments( 120 struct kvm_vcpu *vcpu) 121 { 122 } 123 124 static inline void svm_hv_update_vp_id(struct vmcb *vmcb, 125 struct kvm_vcpu *vcpu) 126 { 127 } 128 #endif /* CONFIG_HYPERV */ 129 130 #endif /* __ARCH_X86_KVM_SVM_ONHYPERV_H__ */ 131