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; 22cb1d474bSSean Christopherson char data[0]; 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 45cb1d474bSSean Christopherson /* 46cb1d474bSSean Christopherson * Track a VMCS that may be loaded on a certain CPU. If it is (cpu!=-1), also 47cb1d474bSSean Christopherson * remember whether it was VMLAUNCHed, and maintain a linked list of all VMCSs 48cb1d474bSSean Christopherson * loaded on this CPU (so we can clear them if the CPU goes down). 49cb1d474bSSean Christopherson */ 50cb1d474bSSean Christopherson struct loaded_vmcs { 51cb1d474bSSean Christopherson struct vmcs *vmcs; 52cb1d474bSSean Christopherson struct vmcs *shadow_vmcs; 53cb1d474bSSean Christopherson int cpu; 54cb1d474bSSean Christopherson bool launched; 55cb1d474bSSean Christopherson bool nmi_known_unmasked; 56cb1d474bSSean Christopherson bool hv_timer_armed; 57cb1d474bSSean Christopherson /* Support for vnmi-less CPUs */ 58cb1d474bSSean Christopherson int soft_vnmi_blocked; 59cb1d474bSSean Christopherson ktime_t entry_time; 60cb1d474bSSean Christopherson s64 vnmi_blocked_time; 61cb1d474bSSean Christopherson unsigned long *msr_bitmap; 62cb1d474bSSean Christopherson struct list_head loaded_vmcss_on_cpu_link; 63cb1d474bSSean Christopherson struct vmcs_host_state host_state; 64cb1d474bSSean Christopherson }; 65cb1d474bSSean Christopherson 66cb1d474bSSean Christopherson static inline bool is_exception_n(u32 intr_info, u8 vector) 67cb1d474bSSean Christopherson { 68cb1d474bSSean Christopherson return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | 69cb1d474bSSean Christopherson INTR_INFO_VALID_MASK)) == 70cb1d474bSSean Christopherson (INTR_TYPE_HARD_EXCEPTION | vector | INTR_INFO_VALID_MASK); 71cb1d474bSSean Christopherson } 72cb1d474bSSean Christopherson 73cb1d474bSSean Christopherson static inline bool is_debug(u32 intr_info) 74cb1d474bSSean Christopherson { 75cb1d474bSSean Christopherson return is_exception_n(intr_info, DB_VECTOR); 76cb1d474bSSean Christopherson } 77cb1d474bSSean Christopherson 78cb1d474bSSean Christopherson static inline bool is_breakpoint(u32 intr_info) 79cb1d474bSSean Christopherson { 80cb1d474bSSean Christopherson return is_exception_n(intr_info, BP_VECTOR); 81cb1d474bSSean Christopherson } 82cb1d474bSSean Christopherson 83cb1d474bSSean Christopherson static inline bool is_page_fault(u32 intr_info) 84cb1d474bSSean Christopherson { 85cb1d474bSSean Christopherson return is_exception_n(intr_info, PF_VECTOR); 86cb1d474bSSean Christopherson } 87cb1d474bSSean Christopherson 88cb1d474bSSean Christopherson static inline bool is_invalid_opcode(u32 intr_info) 89cb1d474bSSean Christopherson { 90cb1d474bSSean Christopherson return is_exception_n(intr_info, UD_VECTOR); 91cb1d474bSSean Christopherson } 92cb1d474bSSean Christopherson 93cb1d474bSSean Christopherson static inline bool is_gp_fault(u32 intr_info) 94cb1d474bSSean Christopherson { 95cb1d474bSSean Christopherson return is_exception_n(intr_info, GP_VECTOR); 96cb1d474bSSean Christopherson } 97cb1d474bSSean Christopherson 98cb1d474bSSean Christopherson static inline bool is_machine_check(u32 intr_info) 99cb1d474bSSean Christopherson { 100cb1d474bSSean Christopherson return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | 101cb1d474bSSean Christopherson INTR_INFO_VALID_MASK)) == 102cb1d474bSSean Christopherson (INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK); 103cb1d474bSSean Christopherson } 104cb1d474bSSean Christopherson 105cb1d474bSSean Christopherson /* Undocumented: icebp/int1 */ 106cb1d474bSSean Christopherson static inline bool is_icebp(u32 intr_info) 107cb1d474bSSean Christopherson { 108cb1d474bSSean Christopherson return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) 109cb1d474bSSean Christopherson == (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK); 110cb1d474bSSean Christopherson } 111cb1d474bSSean Christopherson 112cb1d474bSSean Christopherson static inline bool is_nmi(u32 intr_info) 113cb1d474bSSean Christopherson { 114cb1d474bSSean Christopherson return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) 115cb1d474bSSean Christopherson == (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK); 116cb1d474bSSean Christopherson } 117cb1d474bSSean Christopherson 11849def500SSean Christopherson static inline bool is_external_intr(u32 intr_info) 11949def500SSean Christopherson { 12049def500SSean Christopherson return (intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK)) 12149def500SSean Christopherson == (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR); 12249def500SSean Christopherson } 12349def500SSean Christopherson 124cb1d474bSSean Christopherson enum vmcs_field_width { 125cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U16 = 0, 126cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U64 = 1, 127cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U32 = 2, 128cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_NATURAL_WIDTH = 3 129cb1d474bSSean Christopherson }; 130cb1d474bSSean Christopherson 131cb1d474bSSean Christopherson static inline int vmcs_field_width(unsigned long field) 132cb1d474bSSean Christopherson { 133cb1d474bSSean Christopherson if (0x1 & field) /* the *_HIGH fields are all 32 bit */ 134cb1d474bSSean Christopherson return VMCS_FIELD_WIDTH_U32; 135cb1d474bSSean Christopherson return (field >> 13) & 0x3; 136cb1d474bSSean Christopherson } 137cb1d474bSSean Christopherson 138cb1d474bSSean Christopherson static inline int vmcs_field_readonly(unsigned long field) 139cb1d474bSSean Christopherson { 140cb1d474bSSean Christopherson return (((field >> 10) & 0x3) == 1); 141cb1d474bSSean Christopherson } 142cb1d474bSSean Christopherson 143cb1d474bSSean Christopherson #endif /* __KVM_X86_VMX_VMCS_H */ 144