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 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; 64cb1d474bSSean Christopherson bool hv_timer_armed; 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 75cb1d474bSSean Christopherson static inline bool is_exception_n(u32 intr_info, u8 vector) 76cb1d474bSSean Christopherson { 77cb1d474bSSean Christopherson return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | 78cb1d474bSSean Christopherson INTR_INFO_VALID_MASK)) == 79cb1d474bSSean Christopherson (INTR_TYPE_HARD_EXCEPTION | vector | INTR_INFO_VALID_MASK); 80cb1d474bSSean Christopherson } 81cb1d474bSSean Christopherson 82cb1d474bSSean Christopherson static inline bool is_debug(u32 intr_info) 83cb1d474bSSean Christopherson { 84cb1d474bSSean Christopherson return is_exception_n(intr_info, DB_VECTOR); 85cb1d474bSSean Christopherson } 86cb1d474bSSean Christopherson 87cb1d474bSSean Christopherson static inline bool is_breakpoint(u32 intr_info) 88cb1d474bSSean Christopherson { 89cb1d474bSSean Christopherson return is_exception_n(intr_info, BP_VECTOR); 90cb1d474bSSean Christopherson } 91cb1d474bSSean Christopherson 92cb1d474bSSean Christopherson static inline bool is_page_fault(u32 intr_info) 93cb1d474bSSean Christopherson { 94cb1d474bSSean Christopherson return is_exception_n(intr_info, PF_VECTOR); 95cb1d474bSSean Christopherson } 96cb1d474bSSean Christopherson 97cb1d474bSSean Christopherson static inline bool is_invalid_opcode(u32 intr_info) 98cb1d474bSSean Christopherson { 99cb1d474bSSean Christopherson return is_exception_n(intr_info, UD_VECTOR); 100cb1d474bSSean Christopherson } 101cb1d474bSSean Christopherson 102cb1d474bSSean Christopherson static inline bool is_gp_fault(u32 intr_info) 103cb1d474bSSean Christopherson { 104cb1d474bSSean Christopherson return is_exception_n(intr_info, GP_VECTOR); 105cb1d474bSSean Christopherson } 106cb1d474bSSean Christopherson 107cb1d474bSSean Christopherson static inline bool is_machine_check(u32 intr_info) 108cb1d474bSSean Christopherson { 109cb1d474bSSean Christopherson return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | 110cb1d474bSSean Christopherson INTR_INFO_VALID_MASK)) == 111cb1d474bSSean Christopherson (INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK); 112cb1d474bSSean Christopherson } 113cb1d474bSSean Christopherson 114cb1d474bSSean Christopherson /* Undocumented: icebp/int1 */ 115cb1d474bSSean Christopherson static inline bool is_icebp(u32 intr_info) 116cb1d474bSSean Christopherson { 117cb1d474bSSean Christopherson return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) 118cb1d474bSSean Christopherson == (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK); 119cb1d474bSSean Christopherson } 120cb1d474bSSean Christopherson 121cb1d474bSSean Christopherson static inline bool is_nmi(u32 intr_info) 122cb1d474bSSean Christopherson { 123cb1d474bSSean Christopherson return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) 124cb1d474bSSean Christopherson == (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK); 125cb1d474bSSean Christopherson } 126cb1d474bSSean Christopherson 12749def500SSean Christopherson static inline bool is_external_intr(u32 intr_info) 12849def500SSean Christopherson { 12949def500SSean Christopherson return (intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK)) 13049def500SSean Christopherson == (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR); 13149def500SSean Christopherson } 13249def500SSean Christopherson 133cb1d474bSSean Christopherson enum vmcs_field_width { 134cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U16 = 0, 135cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U64 = 1, 136cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_U32 = 2, 137cb1d474bSSean Christopherson VMCS_FIELD_WIDTH_NATURAL_WIDTH = 3 138cb1d474bSSean Christopherson }; 139cb1d474bSSean Christopherson 140cb1d474bSSean Christopherson static inline int vmcs_field_width(unsigned long field) 141cb1d474bSSean Christopherson { 142cb1d474bSSean Christopherson if (0x1 & field) /* the *_HIGH fields are all 32 bit */ 143cb1d474bSSean Christopherson return VMCS_FIELD_WIDTH_U32; 144cb1d474bSSean Christopherson return (field >> 13) & 0x3; 145cb1d474bSSean Christopherson } 146cb1d474bSSean Christopherson 147cb1d474bSSean Christopherson static inline int vmcs_field_readonly(unsigned long field) 148cb1d474bSSean Christopherson { 149cb1d474bSSean Christopherson return (((field >> 10) & 0x3) == 1); 150cb1d474bSSean Christopherson } 151cb1d474bSSean Christopherson 152cb1d474bSSean Christopherson #endif /* __KVM_X86_VMX_VMCS_H */ 153