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 14cb1d474bSSean Christopherson struct vmcs_hdr { 15cb1d474bSSean Christopherson u32 revision_id:31; 16cb1d474bSSean Christopherson u32 shadow_vmcs:1; 17cb1d474bSSean Christopherson }; 18cb1d474bSSean Christopherson 19cb1d474bSSean Christopherson struct vmcs { 20cb1d474bSSean Christopherson struct vmcs_hdr hdr; 21cb1d474bSSean Christopherson u32 abort; 22f4a9fdd5SGustavo A. R. Silva char data[]; 23cb1d474bSSean Christopherson }; 24cb1d474bSSean Christopherson 2575edce8aSSean Christopherson DECLARE_PER_CPU(struct vmcs *, current_vmcs); 2675edce8aSSean Christopherson 27cb1d474bSSean Christopherson /* 28cb1d474bSSean Christopherson * vmcs_host_state tracks registers that are loaded from the VMCS on VMEXIT 29cb1d474bSSean Christopherson * and whose values change infrequently, but are not constant. I.e. this is 30cb1d474bSSean Christopherson * used as a write-through cache of the corresponding VMCS fields. 31cb1d474bSSean Christopherson */ 32cb1d474bSSean Christopherson struct vmcs_host_state { 33cb1d474bSSean Christopherson unsigned long cr3; /* May not match real cr3 */ 34cb1d474bSSean Christopherson unsigned long cr4; /* May not match real cr4 */ 35cb1d474bSSean Christopherson unsigned long gs_base; 36cb1d474bSSean Christopherson unsigned long fs_base; 375a878160SSean Christopherson unsigned long rsp; 38cb1d474bSSean Christopherson 39cb1d474bSSean Christopherson u16 fs_sel, gs_sel, ldt_sel; 40cb1d474bSSean Christopherson #ifdef CONFIG_X86_64 41cb1d474bSSean Christopherson u16 ds_sel, es_sel; 42cb1d474bSSean Christopherson #endif 43cb1d474bSSean Christopherson }; 44cb1d474bSSean Christopherson 4509e226cfSSean Christopherson struct vmcs_controls_shadow { 4609e226cfSSean Christopherson u32 vm_entry; 4709e226cfSSean Christopherson u32 vm_exit; 4809e226cfSSean Christopherson u32 pin; 4909e226cfSSean Christopherson u32 exec; 5009e226cfSSean Christopherson u32 secondary_exec; 5109e226cfSSean Christopherson }; 5209e226cfSSean Christopherson 53cb1d474bSSean Christopherson /* 54cb1d474bSSean Christopherson * Track a VMCS that may be loaded on a certain CPU. If it is (cpu!=-1), also 55cb1d474bSSean Christopherson * remember whether it was VMLAUNCHed, and maintain a linked list of all VMCSs 56cb1d474bSSean Christopherson * loaded on this CPU (so we can clear them if the CPU goes down). 57cb1d474bSSean Christopherson */ 58cb1d474bSSean Christopherson struct loaded_vmcs { 59cb1d474bSSean Christopherson struct vmcs *vmcs; 60cb1d474bSSean Christopherson struct vmcs *shadow_vmcs; 61cb1d474bSSean Christopherson int cpu; 62cb1d474bSSean Christopherson bool launched; 63cb1d474bSSean Christopherson bool nmi_known_unmasked; 64804939eaSSean Christopherson bool hv_timer_soft_disabled; 65cb1d474bSSean Christopherson /* Support for vnmi-less CPUs */ 66cb1d474bSSean Christopherson int soft_vnmi_blocked; 67cb1d474bSSean Christopherson ktime_t entry_time; 68cb1d474bSSean Christopherson s64 vnmi_blocked_time; 69cb1d474bSSean Christopherson unsigned long *msr_bitmap; 70cb1d474bSSean Christopherson struct list_head loaded_vmcss_on_cpu_link; 71cb1d474bSSean Christopherson struct vmcs_host_state host_state; 7209e226cfSSean Christopherson struct vmcs_controls_shadow controls_shadow; 73cb1d474bSSean Christopherson }; 74cb1d474bSSean Christopherson 7588c200d9SSean Christopherson static inline bool is_intr_type(u32 intr_info, u32 type) 7688c200d9SSean Christopherson { 7788c200d9SSean Christopherson const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK; 7888c200d9SSean Christopherson 7988c200d9SSean Christopherson return (intr_info & mask) == (INTR_INFO_VALID_MASK | type); 8088c200d9SSean Christopherson } 8188c200d9SSean Christopherson 8288c200d9SSean Christopherson static inline bool is_intr_type_n(u32 intr_info, u32 type, u8 vector) 8388c200d9SSean Christopherson { 8488c200d9SSean Christopherson const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK | 8588c200d9SSean Christopherson INTR_INFO_VECTOR_MASK; 8688c200d9SSean Christopherson 8788c200d9SSean Christopherson return (intr_info & mask) == (INTR_INFO_VALID_MASK | type | vector); 8888c200d9SSean Christopherson } 8988c200d9SSean Christopherson 90cb1d474bSSean Christopherson static inline bool is_exception_n(u32 intr_info, u8 vector) 91cb1d474bSSean Christopherson { 9288c200d9SSean Christopherson return is_intr_type_n(intr_info, INTR_TYPE_HARD_EXCEPTION, vector); 93cb1d474bSSean Christopherson } 94cb1d474bSSean Christopherson 95cb1d474bSSean Christopherson static inline bool is_debug(u32 intr_info) 96cb1d474bSSean Christopherson { 97cb1d474bSSean Christopherson return is_exception_n(intr_info, DB_VECTOR); 98cb1d474bSSean Christopherson } 99cb1d474bSSean Christopherson 100cb1d474bSSean Christopherson static inline bool is_breakpoint(u32 intr_info) 101cb1d474bSSean Christopherson { 102cb1d474bSSean Christopherson return is_exception_n(intr_info, BP_VECTOR); 103cb1d474bSSean Christopherson } 104cb1d474bSSean Christopherson 105cb1d474bSSean Christopherson static inline bool is_page_fault(u32 intr_info) 106cb1d474bSSean Christopherson { 107cb1d474bSSean Christopherson return is_exception_n(intr_info, PF_VECTOR); 108cb1d474bSSean Christopherson } 109cb1d474bSSean Christopherson 110cb1d474bSSean Christopherson static inline bool is_invalid_opcode(u32 intr_info) 111cb1d474bSSean Christopherson { 112cb1d474bSSean Christopherson return is_exception_n(intr_info, UD_VECTOR); 113cb1d474bSSean Christopherson } 114cb1d474bSSean Christopherson 115cb1d474bSSean Christopherson static inline bool is_gp_fault(u32 intr_info) 116cb1d474bSSean Christopherson { 117cb1d474bSSean Christopherson return is_exception_n(intr_info, GP_VECTOR); 118cb1d474bSSean Christopherson } 119cb1d474bSSean Christopherson 120cb1d474bSSean Christopherson static inline bool is_machine_check(u32 intr_info) 121cb1d474bSSean Christopherson { 12288c200d9SSean Christopherson return is_exception_n(intr_info, MC_VECTOR); 123cb1d474bSSean Christopherson } 124cb1d474bSSean Christopherson 125cb1d474bSSean Christopherson /* Undocumented: icebp/int1 */ 126cb1d474bSSean Christopherson static inline bool is_icebp(u32 intr_info) 127cb1d474bSSean Christopherson { 12888c200d9SSean Christopherson return is_intr_type(intr_info, INTR_TYPE_PRIV_SW_EXCEPTION); 129cb1d474bSSean Christopherson } 130cb1d474bSSean Christopherson 131cb1d474bSSean Christopherson static inline bool is_nmi(u32 intr_info) 132cb1d474bSSean Christopherson { 13388c200d9SSean Christopherson return is_intr_type(intr_info, INTR_TYPE_NMI_INTR); 134cb1d474bSSean Christopherson } 135cb1d474bSSean Christopherson 13649def500SSean Christopherson static inline bool is_external_intr(u32 intr_info) 13749def500SSean Christopherson { 13888c200d9SSean Christopherson return is_intr_type(intr_info, INTR_TYPE_EXT_INTR); 13949def500SSean Christopherson } 14049def500SSean Christopherson 141f315f2b1SSean Christopherson static inline bool is_exception_with_error_code(u32 intr_info) 142f315f2b1SSean Christopherson { 143f315f2b1SSean Christopherson const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK; 144f315f2b1SSean Christopherson 145f315f2b1SSean Christopherson return (intr_info & mask) == mask; 146f315f2b1SSean Christopherson } 147f315f2b1SSean Christopherson 148cb1d474bSSean Christopherson enum vmcs_field_width { 149cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U16 = 0, 150cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U64 = 1, 151cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U32 = 2, 152cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_NATURAL_WIDTH = 3 153cb1d474bSSean Christopherson }; 154cb1d474bSSean Christopherson 155cb1d474bSSean Christopherson static inline int vmcs_field_width(unsigned long field) 156cb1d474bSSean Christopherson { 157cb1d474bSSean Christopherson if (0x1 & field) /* the *_HIGH fields are all 32 bit */ 158cb1d474bSSean Christopherson return VMCS_FIELD_WIDTH_U32; 159cb1d474bSSean Christopherson return (field >> 13) & 0x3; 160cb1d474bSSean Christopherson } 161cb1d474bSSean Christopherson 162cb1d474bSSean Christopherson static inline int vmcs_field_readonly(unsigned long field) 163cb1d474bSSean Christopherson { 164cb1d474bSSean Christopherson return (((field >> 10) & 0x3) == 1); 165cb1d474bSSean Christopherson } 166cb1d474bSSean Christopherson 167cb1d474bSSean Christopherson #endif /* __KVM_X86_VMX_VMCS_H */ 168