1a789aebaSVitaly Kuznetsov /* SPDX-License-Identifier: GPL-2.0 */
2a789aebaSVitaly Kuznetsov #ifndef __KVM_X86_VMX_HYPERV_H
3a789aebaSVitaly Kuznetsov #define __KVM_X86_VMX_HYPERV_H
4a789aebaSVitaly Kuznetsov
5a789aebaSVitaly Kuznetsov #include <linux/jump_label.h>
6a789aebaSVitaly Kuznetsov
7a789aebaSVitaly Kuznetsov #include <asm/hyperv-tlfs.h>
8a789aebaSVitaly Kuznetsov #include <asm/mshyperv.h>
9a789aebaSVitaly Kuznetsov #include <asm/vmx.h>
10a789aebaSVitaly Kuznetsov
11a789aebaSVitaly Kuznetsov #include "../hyperv.h"
12a789aebaSVitaly Kuznetsov
13a789aebaSVitaly Kuznetsov #include "capabilities.h"
14a789aebaSVitaly Kuznetsov #include "vmcs.h"
15a789aebaSVitaly Kuznetsov #include "vmcs12.h"
16a789aebaSVitaly Kuznetsov
17a789aebaSVitaly Kuznetsov #define KVM_EVMCS_VERSION 1
18a789aebaSVitaly Kuznetsov
19*ebfed7beSVitaly Kuznetsov /*
20*ebfed7beSVitaly Kuznetsov * Enlightened VMCSv1 doesn't support these:
21*ebfed7beSVitaly Kuznetsov *
22*ebfed7beSVitaly Kuznetsov * POSTED_INTR_NV = 0x00000002,
23*ebfed7beSVitaly Kuznetsov * GUEST_INTR_STATUS = 0x00000810,
24*ebfed7beSVitaly Kuznetsov * APIC_ACCESS_ADDR = 0x00002014,
25*ebfed7beSVitaly Kuznetsov * POSTED_INTR_DESC_ADDR = 0x00002016,
26*ebfed7beSVitaly Kuznetsov * EOI_EXIT_BITMAP0 = 0x0000201c,
27*ebfed7beSVitaly Kuznetsov * EOI_EXIT_BITMAP1 = 0x0000201e,
28*ebfed7beSVitaly Kuznetsov * EOI_EXIT_BITMAP2 = 0x00002020,
29*ebfed7beSVitaly Kuznetsov * EOI_EXIT_BITMAP3 = 0x00002022,
30*ebfed7beSVitaly Kuznetsov * GUEST_PML_INDEX = 0x00000812,
31*ebfed7beSVitaly Kuznetsov * PML_ADDRESS = 0x0000200e,
32*ebfed7beSVitaly Kuznetsov * VM_FUNCTION_CONTROL = 0x00002018,
33*ebfed7beSVitaly Kuznetsov * EPTP_LIST_ADDRESS = 0x00002024,
34*ebfed7beSVitaly Kuznetsov * VMREAD_BITMAP = 0x00002026,
35*ebfed7beSVitaly Kuznetsov * VMWRITE_BITMAP = 0x00002028,
36*ebfed7beSVitaly Kuznetsov *
37*ebfed7beSVitaly Kuznetsov * TSC_MULTIPLIER = 0x00002032,
38*ebfed7beSVitaly Kuznetsov * PLE_GAP = 0x00004020,
39*ebfed7beSVitaly Kuznetsov * PLE_WINDOW = 0x00004022,
40*ebfed7beSVitaly Kuznetsov * VMX_PREEMPTION_TIMER_VALUE = 0x0000482E,
41*ebfed7beSVitaly Kuznetsov *
42*ebfed7beSVitaly Kuznetsov * Currently unsupported in KVM:
43*ebfed7beSVitaly Kuznetsov * GUEST_IA32_RTIT_CTL = 0x00002814,
44*ebfed7beSVitaly Kuznetsov */
45*ebfed7beSVitaly Kuznetsov #define EVMCS1_SUPPORTED_PINCTRL \
46*ebfed7beSVitaly Kuznetsov (PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR | \
47*ebfed7beSVitaly Kuznetsov PIN_BASED_EXT_INTR_MASK | \
48*ebfed7beSVitaly Kuznetsov PIN_BASED_NMI_EXITING | \
49*ebfed7beSVitaly Kuznetsov PIN_BASED_VIRTUAL_NMIS)
50*ebfed7beSVitaly Kuznetsov
51*ebfed7beSVitaly Kuznetsov #define EVMCS1_SUPPORTED_EXEC_CTRL \
52*ebfed7beSVitaly Kuznetsov (CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR | \
53*ebfed7beSVitaly Kuznetsov CPU_BASED_HLT_EXITING | \
54*ebfed7beSVitaly Kuznetsov CPU_BASED_CR3_LOAD_EXITING | \
55*ebfed7beSVitaly Kuznetsov CPU_BASED_CR3_STORE_EXITING | \
56*ebfed7beSVitaly Kuznetsov CPU_BASED_UNCOND_IO_EXITING | \
57*ebfed7beSVitaly Kuznetsov CPU_BASED_MOV_DR_EXITING | \
58*ebfed7beSVitaly Kuznetsov CPU_BASED_USE_TSC_OFFSETTING | \
59*ebfed7beSVitaly Kuznetsov CPU_BASED_MWAIT_EXITING | \
60*ebfed7beSVitaly Kuznetsov CPU_BASED_MONITOR_EXITING | \
61*ebfed7beSVitaly Kuznetsov CPU_BASED_INVLPG_EXITING | \
62*ebfed7beSVitaly Kuznetsov CPU_BASED_RDPMC_EXITING | \
63*ebfed7beSVitaly Kuznetsov CPU_BASED_INTR_WINDOW_EXITING | \
64*ebfed7beSVitaly Kuznetsov CPU_BASED_CR8_LOAD_EXITING | \
65*ebfed7beSVitaly Kuznetsov CPU_BASED_CR8_STORE_EXITING | \
66*ebfed7beSVitaly Kuznetsov CPU_BASED_RDTSC_EXITING | \
67*ebfed7beSVitaly Kuznetsov CPU_BASED_TPR_SHADOW | \
68*ebfed7beSVitaly Kuznetsov CPU_BASED_USE_IO_BITMAPS | \
69*ebfed7beSVitaly Kuznetsov CPU_BASED_MONITOR_TRAP_FLAG | \
70*ebfed7beSVitaly Kuznetsov CPU_BASED_USE_MSR_BITMAPS | \
71*ebfed7beSVitaly Kuznetsov CPU_BASED_NMI_WINDOW_EXITING | \
72*ebfed7beSVitaly Kuznetsov CPU_BASED_PAUSE_EXITING | \
73*ebfed7beSVitaly Kuznetsov CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
74*ebfed7beSVitaly Kuznetsov
75*ebfed7beSVitaly Kuznetsov #define EVMCS1_SUPPORTED_2NDEXEC \
76*ebfed7beSVitaly Kuznetsov (SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | \
77*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_WBINVD_EXITING | \
78*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_ENABLE_VPID | \
79*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_ENABLE_EPT | \
80*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_UNRESTRICTED_GUEST | \
81*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_DESC | \
82*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_ENABLE_RDTSCP | \
83*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_ENABLE_INVPCID | \
84*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_ENABLE_XSAVES | \
85*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_RDSEED_EXITING | \
86*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_RDRAND_EXITING | \
87*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_TSC_SCALING | \
88*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE | \
89*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_PT_USE_GPA | \
90*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_PT_CONCEAL_VMX | \
91*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_BUS_LOCK_DETECTION | \
92*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_NOTIFY_VM_EXITING | \
93*ebfed7beSVitaly Kuznetsov SECONDARY_EXEC_ENCLS_EXITING)
94*ebfed7beSVitaly Kuznetsov
95*ebfed7beSVitaly Kuznetsov #define EVMCS1_SUPPORTED_3RDEXEC (0ULL)
96*ebfed7beSVitaly Kuznetsov
97*ebfed7beSVitaly Kuznetsov #define EVMCS1_SUPPORTED_VMEXIT_CTRL \
98*ebfed7beSVitaly Kuznetsov (VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR | \
99*ebfed7beSVitaly Kuznetsov VM_EXIT_SAVE_DEBUG_CONTROLS | \
100*ebfed7beSVitaly Kuznetsov VM_EXIT_ACK_INTR_ON_EXIT | \
101*ebfed7beSVitaly Kuznetsov VM_EXIT_HOST_ADDR_SPACE_SIZE | \
102*ebfed7beSVitaly Kuznetsov VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | \
103*ebfed7beSVitaly Kuznetsov VM_EXIT_SAVE_IA32_PAT | \
104*ebfed7beSVitaly Kuznetsov VM_EXIT_LOAD_IA32_PAT | \
105*ebfed7beSVitaly Kuznetsov VM_EXIT_SAVE_IA32_EFER | \
106*ebfed7beSVitaly Kuznetsov VM_EXIT_LOAD_IA32_EFER | \
107*ebfed7beSVitaly Kuznetsov VM_EXIT_CLEAR_BNDCFGS | \
108*ebfed7beSVitaly Kuznetsov VM_EXIT_PT_CONCEAL_PIP | \
109*ebfed7beSVitaly Kuznetsov VM_EXIT_CLEAR_IA32_RTIT_CTL)
110*ebfed7beSVitaly Kuznetsov
111*ebfed7beSVitaly Kuznetsov #define EVMCS1_SUPPORTED_VMENTRY_CTRL \
112*ebfed7beSVitaly Kuznetsov (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | \
113*ebfed7beSVitaly Kuznetsov VM_ENTRY_LOAD_DEBUG_CONTROLS | \
114*ebfed7beSVitaly Kuznetsov VM_ENTRY_IA32E_MODE | \
115*ebfed7beSVitaly Kuznetsov VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | \
116*ebfed7beSVitaly Kuznetsov VM_ENTRY_LOAD_IA32_PAT | \
117*ebfed7beSVitaly Kuznetsov VM_ENTRY_LOAD_IA32_EFER | \
118*ebfed7beSVitaly Kuznetsov VM_ENTRY_LOAD_BNDCFGS | \
119*ebfed7beSVitaly Kuznetsov VM_ENTRY_PT_CONCEAL_PIP | \
120*ebfed7beSVitaly Kuznetsov VM_ENTRY_LOAD_IA32_RTIT_CTL)
121*ebfed7beSVitaly Kuznetsov
122*ebfed7beSVitaly Kuznetsov #define EVMCS1_SUPPORTED_VMFUNC (0)
123*ebfed7beSVitaly Kuznetsov
124a789aebaSVitaly Kuznetsov struct evmcs_field {
125a789aebaSVitaly Kuznetsov u16 offset;
126a789aebaSVitaly Kuznetsov u16 clean_field;
127a789aebaSVitaly Kuznetsov };
128a789aebaSVitaly Kuznetsov
129a789aebaSVitaly Kuznetsov extern const struct evmcs_field vmcs_field_to_evmcs_1[];
130a789aebaSVitaly Kuznetsov extern const unsigned int nr_evmcs_1_fields;
131a789aebaSVitaly Kuznetsov
evmcs_field_offset(unsigned long field,u16 * clean_field)132a789aebaSVitaly Kuznetsov static __always_inline int evmcs_field_offset(unsigned long field,
133a789aebaSVitaly Kuznetsov u16 *clean_field)
134a789aebaSVitaly Kuznetsov {
135a789aebaSVitaly Kuznetsov unsigned int index = ROL16(field, 6);
136a789aebaSVitaly Kuznetsov const struct evmcs_field *evmcs_field;
137a789aebaSVitaly Kuznetsov
138a789aebaSVitaly Kuznetsov if (unlikely(index >= nr_evmcs_1_fields))
139a789aebaSVitaly Kuznetsov return -ENOENT;
140a789aebaSVitaly Kuznetsov
141a789aebaSVitaly Kuznetsov evmcs_field = &vmcs_field_to_evmcs_1[index];
142a789aebaSVitaly Kuznetsov
143a789aebaSVitaly Kuznetsov /*
144a789aebaSVitaly Kuznetsov * Use offset=0 to detect holes in eVMCS. This offset belongs to
145a789aebaSVitaly Kuznetsov * 'revision_id' but this field has no encoding and is supposed to
146a789aebaSVitaly Kuznetsov * be accessed directly.
147a789aebaSVitaly Kuznetsov */
148a789aebaSVitaly Kuznetsov if (unlikely(!evmcs_field->offset))
149a789aebaSVitaly Kuznetsov return -ENOENT;
150a789aebaSVitaly Kuznetsov
151a789aebaSVitaly Kuznetsov if (clean_field)
152a789aebaSVitaly Kuznetsov *clean_field = evmcs_field->clean_field;
153a789aebaSVitaly Kuznetsov
154a789aebaSVitaly Kuznetsov return evmcs_field->offset;
155a789aebaSVitaly Kuznetsov }
156a789aebaSVitaly Kuznetsov
evmcs_read_any(struct hv_enlightened_vmcs * evmcs,unsigned long field,u16 offset)157a789aebaSVitaly Kuznetsov static inline u64 evmcs_read_any(struct hv_enlightened_vmcs *evmcs,
158a789aebaSVitaly Kuznetsov unsigned long field, u16 offset)
159a789aebaSVitaly Kuznetsov {
160a789aebaSVitaly Kuznetsov /*
161a789aebaSVitaly Kuznetsov * vmcs12_read_any() doesn't care whether the supplied structure
162a789aebaSVitaly Kuznetsov * is 'struct vmcs12' or 'struct hv_enlightened_vmcs' as it takes
163a789aebaSVitaly Kuznetsov * the exact offset of the required field, use it for convenience
164a789aebaSVitaly Kuznetsov * here.
165a789aebaSVitaly Kuznetsov */
166a789aebaSVitaly Kuznetsov return vmcs12_read_any((void *)evmcs, field, offset);
167a789aebaSVitaly Kuznetsov }
168a789aebaSVitaly Kuznetsov
169a789aebaSVitaly Kuznetsov #define EVMPTR_INVALID (-1ULL)
170a789aebaSVitaly Kuznetsov #define EVMPTR_MAP_PENDING (-2ULL)
171a789aebaSVitaly Kuznetsov
evmptr_is_valid(u64 evmptr)172a789aebaSVitaly Kuznetsov static inline bool evmptr_is_valid(u64 evmptr)
173a789aebaSVitaly Kuznetsov {
174a789aebaSVitaly Kuznetsov return evmptr != EVMPTR_INVALID && evmptr != EVMPTR_MAP_PENDING;
175a789aebaSVitaly Kuznetsov }
176a789aebaSVitaly Kuznetsov
177a789aebaSVitaly Kuznetsov enum nested_evmptrld_status {
178a789aebaSVitaly Kuznetsov EVMPTRLD_DISABLED,
179a789aebaSVitaly Kuznetsov EVMPTRLD_SUCCEEDED,
180a789aebaSVitaly Kuznetsov EVMPTRLD_VMFAIL,
181a789aebaSVitaly Kuznetsov EVMPTRLD_ERROR,
182a789aebaSVitaly Kuznetsov };
183a789aebaSVitaly Kuznetsov
184046f5756SVitaly Kuznetsov u64 nested_get_evmptr(struct kvm_vcpu *vcpu);
185a789aebaSVitaly Kuznetsov uint16_t nested_get_evmcs_version(struct kvm_vcpu *vcpu);
186a789aebaSVitaly Kuznetsov int nested_enable_evmcs(struct kvm_vcpu *vcpu,
187a789aebaSVitaly Kuznetsov uint16_t *vmcs_version);
188a789aebaSVitaly Kuznetsov void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata);
189a789aebaSVitaly Kuznetsov int nested_evmcs_check_controls(struct vmcs12 *vmcs12);
190c30e9bc8SVitaly Kuznetsov bool nested_evmcs_l2_tlb_flush_enabled(struct kvm_vcpu *vcpu);
191b0c9c25eSVitaly Kuznetsov void vmx_hv_inject_synthetic_vmexit_post_tlb_flush(struct kvm_vcpu *vcpu);
192a789aebaSVitaly Kuznetsov
193a789aebaSVitaly Kuznetsov #endif /* __KVM_X86_VMX_HYPERV_H */
194