1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Copyright (C) 2021 SUSE LLC <mdoucha@suse.cz> 4 * 5 * x86-specific KVM helper functions and structures 6 */ 7 8 #ifndef KVM_X86_H_ 9 #define KVM_X86_H_ 10 11 #include "kvm_test.h" 12 13 /* Interrupts */ 14 #define X86_INTR_COUNT 256 15 16 #define INTR_ZERODIV 0 17 #define INTR_DEBUG 1 18 #define INTR_NMI 2 19 #define INTR_BREAKPOINT 3 20 #define INTR_OVERFLOW 4 21 #define INTR_BOUND_RANGE_EXC 5 22 #define INTR_BAD_OPCODE 6 23 #define INTR_DEVICE_ERROR 7 24 #define INTR_DOUBLE_FAULT 8 25 #define INTR_INVALID_TSS 10 26 #define INTR_SEGFAULT 11 27 #define INTR_STACK_FAULT 12 28 #define INTR_GPF 13 29 #define INTR_PAGE_FAULT 14 30 #define INTR_FPU_ERROR 16 31 #define INTR_ALIGNMENT_ERROR 17 32 #define INTR_MACHINE_CHECK 18 33 #define INTR_SIMD_ERROR 19 34 #define INTR_VIRT_ERROR 20 35 #define INTR_CPE 21 36 #define INTR_HV_INJECTION 28 37 #define INTR_VMM_COMM 29 38 #define INTR_SECURITY_ERROR 30 39 40 41 /* CPUID constants */ 42 #define CPUID_GET_INPUT_RANGE 0x80000000 43 #define CPUID_GET_EXT_FEATURES 0x80000001 44 45 46 /* Model-specific CPU register constants */ 47 #define MSR_EFER 0xc0000080 48 49 #define EFER_SCE (1 << 0) /* SYSCALL/SYSRET instructions enabled */ 50 #define EFER_LME (1 << 8) /* CPU is running in 64bit mode */ 51 #define EFER_LMA (1 << 10) /* CPU uses 64bit memory paging (read-only) */ 52 #define EFER_NXE (1 << 11) /* Execute disable bit active */ 53 54 55 /* Control register constants */ 56 #define CR4_VME (1 << 0) 57 #define CR4_PVI (1 << 1) 58 #define CR4_TSD (1 << 2) 59 #define CR4_DE (1 << 3) 60 #define CR4_PSE (1 << 4) 61 #define CR4_PAE (1 << 5) 62 #define CR4_MCE (1 << 6) 63 #define CR4_PGE (1 << 7) 64 #define CR4_PCE (1 << 8) 65 #define CR4_OSFXSR (1 << 9) 66 #define CR4_OSXMMEXCPT (1 << 10) 67 #define CR4_UMIP (1 << 11) 68 #define CR4_LA57 (1 << 12) 69 #define CR4_VMXE (1 << 13) 70 #define CR4_SMXE (1 << 14) 71 #define CR4_FSGSBASE (1 << 16) 72 #define CR4_PCIDE (1 << 17) 73 #define CR4_OSXSAVE (1 << 18) 74 #define CR4_KL (1 << 19) 75 #define CR4_SMEP (1 << 20) 76 #define CR4_SMAP (1 << 21) 77 #define CR4_PKE (1 << 22) 78 #define CR4_CET (1 << 23) 79 #define CR4_PKS (1 << 24) 80 81 struct intr_descriptor { 82 uint16_t offset_lo; 83 uint16_t selector; 84 uint8_t ist; 85 uint8_t flags; 86 #if defined(__x86_64__) 87 uint64_t offset_hi; /* top 16 bits must be set to 0 */ 88 uint16_t padding; 89 #else /* defined(__x86_64__) */ 90 uint16_t offset_hi; 91 #endif /* defined(__x86_64__) */ 92 } __attribute__((__packed__)); 93 94 struct page_table_entry_pae { 95 unsigned int present: 1; 96 unsigned int writable: 1; 97 unsigned int user_access: 1; 98 unsigned int write_through: 1; 99 unsigned int disable_cache: 1; 100 unsigned int accessed: 1; 101 unsigned int dirty: 1; 102 unsigned int page_type: 1; 103 unsigned int global: 1; 104 unsigned int padding: 3; 105 uint64_t address: 40; 106 unsigned int padding2: 7; 107 unsigned int prot_key: 4; 108 unsigned int noexec: 1; 109 } __attribute__((__packed__)); 110 111 struct kvm_cpuid { 112 unsigned int eax, ebx, ecx, edx; 113 }; 114 115 struct kvm_cregs { 116 unsigned long cr0, cr2, cr3, cr4; 117 }; 118 119 extern struct page_table_entry_pae kvm_pagetable[]; 120 extern struct intr_descriptor kvm_idt[X86_INTR_COUNT]; 121 122 /* Page table helper functions */ 123 uintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry); 124 125 /* Functions for querying CPU info and status */ 126 void kvm_get_cpuid(unsigned int eax, unsigned int ecx, struct kvm_cpuid *buf); 127 void kvm_read_cregs(struct kvm_cregs *buf); 128 uint64_t kvm_rdmsr(unsigned int msr); 129 void kvm_wrmsr(unsigned int msr, uint64_t value); 130 131 /* Low-level interrupt handlers, DO NOT call directly */ 132 void kvm_handle_bad_exception(void); 133 void kvm_handle_zerodiv(void); 134 void kvm_handle_debug(void); 135 void kvm_handle_nmi(void); 136 void kvm_handle_breakpoint(void); 137 void kvm_handle_overflow(void); 138 void kvm_handle_bound_range_exc(void); 139 void kvm_handle_bad_opcode(void); 140 void kvm_handle_device_error(void); 141 void kvm_handle_double_fault(void); 142 void kvm_handle_invalid_tss(void); 143 void kvm_handle_segfault(void); 144 void kvm_handle_stack_fault(void); 145 void kvm_handle_gpf(void); 146 void kvm_handle_page_fault(void); 147 void kvm_handle_fpu_error(void); 148 void kvm_handle_alignment_error(void); 149 void kvm_handle_machine_check(void); 150 void kvm_handle_simd_error(void); 151 void kvm_handle_virt_error(void); 152 void kvm_handle_cpe(void); 153 void kvm_handle_hv_injection(void); 154 void kvm_handle_vmm_comm(void); 155 void kvm_handle_security_error(void); 156 157 #endif /* KVM_X86_H_ */ 158