1cb1d474bSSean Christopherson /* SPDX-License-Identifier: GPL-2.0 */ 2cb1d474bSSean Christopherson #ifndef __KVM_X86_VMX_VMCS_H 3cb1d474bSSean Christopherson #define __KVM_X86_VMX_VMCS_H 4cb1d474bSSean Christopherson 5cb1d474bSSean Christopherson #include <linux/ktime.h> 6609363cfSSean Christopherson #include <linux/list.h> 7609363cfSSean Christopherson #include <linux/nospec.h> 8cb1d474bSSean Christopherson 9609363cfSSean Christopherson #include <asm/kvm.h> 10cb1d474bSSean Christopherson #include <asm/vmx.h> 11cb1d474bSSean Christopherson 12cb1d474bSSean Christopherson #include "capabilities.h" 13cb1d474bSSean Christopherson 14c1a527a1SLike Xu #define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n))))) 15c1a527a1SLike Xu 16cb1d474bSSean Christopherson struct vmcs_hdr { 17cb1d474bSSean Christopherson u32 revision_id:31; 18cb1d474bSSean Christopherson u32 shadow_vmcs:1; 19cb1d474bSSean Christopherson }; 20cb1d474bSSean Christopherson 21cb1d474bSSean Christopherson struct vmcs { 22cb1d474bSSean Christopherson struct vmcs_hdr hdr; 23cb1d474bSSean Christopherson u32 abort; 24f4a9fdd5SGustavo A. R. Silva char data[]; 25cb1d474bSSean Christopherson }; 26cb1d474bSSean Christopherson 2775edce8aSSean Christopherson DECLARE_PER_CPU(struct vmcs *, current_vmcs); 2875edce8aSSean Christopherson 29cb1d474bSSean Christopherson /* 30cb1d474bSSean Christopherson * vmcs_host_state tracks registers that are loaded from the VMCS on VMEXIT 31cb1d474bSSean Christopherson * and whose values change infrequently, but are not constant. I.e. this is 32cb1d474bSSean Christopherson * used as a write-through cache of the corresponding VMCS fields. 33cb1d474bSSean Christopherson */ 34cb1d474bSSean Christopherson struct vmcs_host_state { 35cb1d474bSSean Christopherson unsigned long cr3; /* May not match real cr3 */ 36cb1d474bSSean Christopherson unsigned long cr4; /* May not match real cr4 */ 37cb1d474bSSean Christopherson unsigned long gs_base; 38cb1d474bSSean Christopherson unsigned long fs_base; 395a878160SSean Christopherson unsigned long rsp; 40cb1d474bSSean Christopherson 41cb1d474bSSean Christopherson u16 fs_sel, gs_sel, ldt_sel; 42cb1d474bSSean Christopherson #ifdef CONFIG_X86_64 43cb1d474bSSean Christopherson u16 ds_sel, es_sel; 44cb1d474bSSean Christopherson #endif 45cb1d474bSSean Christopherson }; 46cb1d474bSSean Christopherson 4709e226cfSSean Christopherson struct vmcs_controls_shadow { 4809e226cfSSean Christopherson u32 vm_entry; 4909e226cfSSean Christopherson u32 vm_exit; 5009e226cfSSean Christopherson u32 pin; 5109e226cfSSean Christopherson u32 exec; 5209e226cfSSean Christopherson u32 secondary_exec; 5309e226cfSSean Christopherson }; 5409e226cfSSean Christopherson 55cb1d474bSSean Christopherson /* 56cb1d474bSSean Christopherson * Track a VMCS that may be loaded on a certain CPU. If it is (cpu!=-1), also 57cb1d474bSSean Christopherson * remember whether it was VMLAUNCHed, and maintain a linked list of all VMCSs 58cb1d474bSSean Christopherson * loaded on this CPU (so we can clear them if the CPU goes down). 59cb1d474bSSean Christopherson */ 60cb1d474bSSean Christopherson struct loaded_vmcs { 61cb1d474bSSean Christopherson struct vmcs *vmcs; 62cb1d474bSSean Christopherson struct vmcs *shadow_vmcs; 63cb1d474bSSean Christopherson int cpu; 64cb1d474bSSean Christopherson bool launched; 65cb1d474bSSean Christopherson bool nmi_known_unmasked; 66804939eaSSean Christopherson bool hv_timer_soft_disabled; 67cb1d474bSSean Christopherson /* Support for vnmi-less CPUs */ 68cb1d474bSSean Christopherson int soft_vnmi_blocked; 69cb1d474bSSean Christopherson ktime_t entry_time; 70cb1d474bSSean Christopherson s64 vnmi_blocked_time; 71cb1d474bSSean Christopherson unsigned long *msr_bitmap; 72cb1d474bSSean Christopherson struct list_head loaded_vmcss_on_cpu_link; 73cb1d474bSSean Christopherson struct vmcs_host_state host_state; 7409e226cfSSean Christopherson struct vmcs_controls_shadow controls_shadow; 75cb1d474bSSean Christopherson }; 76cb1d474bSSean Christopherson 7788c200d9SSean Christopherson static inline bool is_intr_type(u32 intr_info, u32 type) 7888c200d9SSean Christopherson { 7988c200d9SSean Christopherson const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK; 8088c200d9SSean Christopherson 8188c200d9SSean Christopherson return (intr_info & mask) == (INTR_INFO_VALID_MASK | type); 8288c200d9SSean Christopherson } 8388c200d9SSean Christopherson 8488c200d9SSean Christopherson static inline bool is_intr_type_n(u32 intr_info, u32 type, u8 vector) 8588c200d9SSean Christopherson { 8688c200d9SSean Christopherson const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK | 8788c200d9SSean Christopherson INTR_INFO_VECTOR_MASK; 8888c200d9SSean Christopherson 8988c200d9SSean Christopherson return (intr_info & mask) == (INTR_INFO_VALID_MASK | type | vector); 9088c200d9SSean Christopherson } 9188c200d9SSean Christopherson 92cb1d474bSSean Christopherson static inline bool is_exception_n(u32 intr_info, u8 vector) 93cb1d474bSSean Christopherson { 9488c200d9SSean Christopherson return is_intr_type_n(intr_info, INTR_TYPE_HARD_EXCEPTION, vector); 95cb1d474bSSean Christopherson } 96cb1d474bSSean Christopherson 97cb1d474bSSean Christopherson static inline bool is_debug(u32 intr_info) 98cb1d474bSSean Christopherson { 99cb1d474bSSean Christopherson return is_exception_n(intr_info, DB_VECTOR); 100cb1d474bSSean Christopherson } 101cb1d474bSSean Christopherson 102cb1d474bSSean Christopherson static inline bool is_breakpoint(u32 intr_info) 103cb1d474bSSean Christopherson { 104cb1d474bSSean Christopherson return is_exception_n(intr_info, BP_VECTOR); 105cb1d474bSSean Christopherson } 106cb1d474bSSean Christopherson 107*9bd1f0efSSean Christopherson static inline bool is_double_fault(u32 intr_info) 108*9bd1f0efSSean Christopherson { 109*9bd1f0efSSean Christopherson return is_exception_n(intr_info, DF_VECTOR); 110*9bd1f0efSSean Christopherson } 111*9bd1f0efSSean Christopherson 112cb1d474bSSean Christopherson static inline bool is_page_fault(u32 intr_info) 113cb1d474bSSean Christopherson { 114cb1d474bSSean Christopherson return is_exception_n(intr_info, PF_VECTOR); 115cb1d474bSSean Christopherson } 116cb1d474bSSean Christopherson 117cb1d474bSSean Christopherson static inline bool is_invalid_opcode(u32 intr_info) 118cb1d474bSSean Christopherson { 119cb1d474bSSean Christopherson return is_exception_n(intr_info, UD_VECTOR); 120cb1d474bSSean Christopherson } 121cb1d474bSSean Christopherson 122cb1d474bSSean Christopherson static inline bool is_gp_fault(u32 intr_info) 123cb1d474bSSean Christopherson { 124cb1d474bSSean Christopherson return is_exception_n(intr_info, GP_VECTOR); 125cb1d474bSSean Christopherson } 126cb1d474bSSean Christopherson 127b33bb78aSSean Christopherson static inline bool is_alignment_check(u32 intr_info) 128b33bb78aSSean Christopherson { 129b33bb78aSSean Christopherson return is_exception_n(intr_info, AC_VECTOR); 130b33bb78aSSean Christopherson } 131b33bb78aSSean Christopherson 132cb1d474bSSean Christopherson static inline bool is_machine_check(u32 intr_info) 133cb1d474bSSean Christopherson { 13488c200d9SSean Christopherson return is_exception_n(intr_info, MC_VECTOR); 135cb1d474bSSean Christopherson } 136cb1d474bSSean Christopherson 137ec5be88aSJing Liu static inline bool is_nm_fault(u32 intr_info) 138ec5be88aSJing Liu { 139ec5be88aSJing Liu return is_exception_n(intr_info, NM_VECTOR); 140ec5be88aSJing Liu } 141ec5be88aSJing Liu 142cb1d474bSSean Christopherson /* Undocumented: icebp/int1 */ 143cb1d474bSSean Christopherson static inline bool is_icebp(u32 intr_info) 144cb1d474bSSean Christopherson { 14588c200d9SSean Christopherson return is_intr_type(intr_info, INTR_TYPE_PRIV_SW_EXCEPTION); 146cb1d474bSSean Christopherson } 147cb1d474bSSean Christopherson 148cb1d474bSSean Christopherson static inline bool is_nmi(u32 intr_info) 149cb1d474bSSean Christopherson { 15088c200d9SSean Christopherson return is_intr_type(intr_info, INTR_TYPE_NMI_INTR); 151cb1d474bSSean Christopherson } 152cb1d474bSSean Christopherson 15349def500SSean Christopherson static inline bool is_external_intr(u32 intr_info) 15449def500SSean Christopherson { 15588c200d9SSean Christopherson return is_intr_type(intr_info, INTR_TYPE_EXT_INTR); 15649def500SSean Christopherson } 15749def500SSean Christopherson 158f315f2b1SSean Christopherson static inline bool is_exception_with_error_code(u32 intr_info) 159f315f2b1SSean Christopherson { 160f315f2b1SSean Christopherson const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK; 161f315f2b1SSean Christopherson 162f315f2b1SSean Christopherson return (intr_info & mask) == mask; 163f315f2b1SSean Christopherson } 164f315f2b1SSean Christopherson 165cb1d474bSSean Christopherson enum vmcs_field_width { 166cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U16 = 0, 167cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U64 = 1, 168cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U32 = 2, 169cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_NATURAL_WIDTH = 3 170cb1d474bSSean Christopherson }; 171cb1d474bSSean Christopherson 172cb1d474bSSean Christopherson static inline int vmcs_field_width(unsigned long field) 173cb1d474bSSean Christopherson { 174cb1d474bSSean Christopherson if (0x1 & field) /* the *_HIGH fields are all 32 bit */ 175cb1d474bSSean Christopherson return VMCS_FIELD_WIDTH_U32; 176cb1d474bSSean Christopherson return (field >> 13) & 0x3; 177cb1d474bSSean Christopherson } 178cb1d474bSSean Christopherson 179cb1d474bSSean Christopherson static inline int vmcs_field_readonly(unsigned long field) 180cb1d474bSSean Christopherson { 181cb1d474bSSean Christopherson return (((field >> 10) & 0x3) == 1); 182cb1d474bSSean Christopherson } 183cb1d474bSSean Christopherson 184ba1f8245SSean Christopherson #define VMCS_FIELD_INDEX_SHIFT (1) 185ba1f8245SSean Christopherson #define VMCS_FIELD_INDEX_MASK GENMASK(9, 1) 186ba1f8245SSean Christopherson 187ba1f8245SSean Christopherson static inline unsigned int vmcs_field_index(unsigned long field) 188ba1f8245SSean Christopherson { 189ba1f8245SSean Christopherson return (field & VMCS_FIELD_INDEX_MASK) >> VMCS_FIELD_INDEX_SHIFT; 190ba1f8245SSean Christopherson } 191ba1f8245SSean Christopherson 192cb1d474bSSean Christopherson #endif /* __KVM_X86_VMX_VMCS_H */ 193