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 #define PAGESIZE 0x1000 14 #define KVM_GDT_SIZE 32 15 16 /* Interrupts */ 17 #define X86_INTR_COUNT 256 18 19 #define INTR_ZERODIV 0 20 #define INTR_DEBUG 1 21 #define INTR_NMI 2 22 #define INTR_BREAKPOINT 3 23 #define INTR_OVERFLOW 4 24 #define INTR_BOUND_RANGE_EXC 5 25 #define INTR_BAD_OPCODE 6 26 #define INTR_DEVICE_ERROR 7 27 #define INTR_DOUBLE_FAULT 8 28 #define INTR_INVALID_TSS 10 29 #define INTR_SEGFAULT 11 30 #define INTR_STACK_FAULT 12 31 #define INTR_GPF 13 32 #define INTR_PAGE_FAULT 14 33 #define INTR_FPU_ERROR 16 34 #define INTR_ALIGNMENT_ERROR 17 35 #define INTR_MACHINE_CHECK 18 36 #define INTR_SIMD_ERROR 19 37 #define INTR_VIRT_ERROR 20 38 #define INTR_CPE 21 39 #define INTR_HV_INJECTION 28 40 #define INTR_VMM_COMM 29 41 #define INTR_SECURITY_ERROR 30 42 43 44 /* Segment descriptor flags */ 45 #define SEGTYPE_LDT 0x02 46 #define SEGTYPE_TSS 0x09 47 #define SEGTYPE_TSS_BUSY 0x0b 48 #define SEGTYPE_CALL_GATE 0x0c 49 #define SEGTYPE_INTR_GATE 0x0e 50 #define SEGTYPE_TRAP_GATE 0x0f 51 #define SEGTYPE_RODATA 0x10 52 #define SEGTYPE_RWDATA 0x12 53 #define SEGTYPE_STACK 0x16 54 #define SEGTYPE_CODE 0x1a 55 #define SEGTYPE_MASK 0x1f 56 57 #define SEGFLAG_NSYSTEM 0x10 58 #define SEGFLAG_PRESENT 0x80 59 #define SEGFLAG_CODE64 0x200 60 #define SEGFLAG_32BIT 0x400 61 #define SEGFLAG_PAGE_LIMIT 0x800 62 63 64 /* CPUID constants */ 65 #define CPUID_GET_INPUT_RANGE 0x80000000 66 #define CPUID_GET_EXT_FEATURES 0x80000001 67 #define CPUID_GET_SVM_FEATURES 0x8000000a 68 69 70 /* Model-specific CPU register constants */ 71 #define MSR_EFER 0xc0000080 72 #define MSR_VM_CR 0xc0010114 73 #define MSR_VM_HSAVE_PA 0xc0010117 74 75 #define EFER_SCE (1 << 0) /* SYSCALL/SYSRET instructions enabled */ 76 #define EFER_LME (1 << 8) /* CPU is running in 64bit mode */ 77 #define EFER_LMA (1 << 10) /* CPU uses 64bit memory paging (read-only) */ 78 #define EFER_NXE (1 << 11) /* Execute disable bit active */ 79 #define EFER_SVME (1 << 12) /* AMD SVM instructions enabled */ 80 81 #define VM_CR_DPD (1 << 0) 82 #define VM_CR_R_INIT (1 << 1) 83 #define VM_CR_DIS_A20M (1 << 2) 84 #define VM_CR_LOCK (1 << 3) 85 #define VM_CR_SVMDIS (1 << 4) 86 87 /* Control register constants */ 88 #define CR4_VME (1 << 0) 89 #define CR4_PVI (1 << 1) 90 #define CR4_TSD (1 << 2) 91 #define CR4_DE (1 << 3) 92 #define CR4_PSE (1 << 4) 93 #define CR4_PAE (1 << 5) 94 #define CR4_MCE (1 << 6) 95 #define CR4_PGE (1 << 7) 96 #define CR4_PCE (1 << 8) 97 #define CR4_OSFXSR (1 << 9) 98 #define CR4_OSXMMEXCPT (1 << 10) 99 #define CR4_UMIP (1 << 11) 100 #define CR4_LA57 (1 << 12) 101 #define CR4_VMXE (1 << 13) 102 #define CR4_SMXE (1 << 14) 103 #define CR4_FSGSBASE (1 << 16) 104 #define CR4_PCIDE (1 << 17) 105 #define CR4_OSXSAVE (1 << 18) 106 #define CR4_KL (1 << 19) 107 #define CR4_SMEP (1 << 20) 108 #define CR4_SMAP (1 << 21) 109 #define CR4_PKE (1 << 22) 110 #define CR4_CET (1 << 23) 111 #define CR4_PKS (1 << 24) 112 113 struct intr_descriptor { 114 uint16_t offset_lo; 115 uint16_t selector; 116 uint8_t ist; 117 uint8_t flags; 118 #if defined(__x86_64__) 119 uint64_t offset_hi; /* top 16 bits must be set to 0 */ 120 uint16_t padding; 121 #else /* defined(__x86_64__) */ 122 uint16_t offset_hi; 123 #endif /* defined(__x86_64__) */ 124 } __attribute__((__packed__)); 125 126 struct segment_descriptor { 127 unsigned int limit_lo : 16; 128 unsigned int baseaddr_lo : 24; 129 unsigned int flags_lo : 8; 130 unsigned int limit_hi : 4; 131 unsigned int flags_hi : 4; 132 unsigned int baseaddr_hi : 8; 133 } __attribute__((__packed__)); 134 135 struct segment_descriptor64 { 136 unsigned int limit_lo : 16; 137 unsigned int baseaddr_lo : 24; 138 unsigned int flags_lo : 8; 139 unsigned int limit_hi : 4; 140 unsigned int flags_hi : 4; 141 uint64_t baseaddr_hi : 40; 142 uint32_t reserved; 143 } __attribute__((__packed__)); 144 145 struct page_table_entry_pae { 146 unsigned int present: 1; 147 unsigned int writable: 1; 148 unsigned int user_access: 1; 149 unsigned int write_through: 1; 150 unsigned int disable_cache: 1; 151 unsigned int accessed: 1; 152 unsigned int dirty: 1; 153 unsigned int page_type: 1; 154 unsigned int global: 1; 155 unsigned int padding: 3; 156 uint64_t address: 40; 157 unsigned int padding2: 7; 158 unsigned int prot_key: 4; 159 unsigned int noexec: 1; 160 } __attribute__((__packed__)); 161 162 struct kvm_cpuid { 163 unsigned int eax, ebx, ecx, edx; 164 }; 165 166 struct kvm_cregs { 167 unsigned long cr0, cr2, cr3, cr4; 168 }; 169 170 struct kvm_sregs { 171 uint16_t cs, ds, es, fs, gs, ss; 172 }; 173 174 struct kvm_regs64 { 175 uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, rsp; 176 uint64_t r8, r9, r10, r11, r12, r13, r14, r15; 177 }; 178 179 extern struct page_table_entry_pae kvm_pagetable[]; 180 extern struct intr_descriptor kvm_idt[X86_INTR_COUNT]; 181 extern struct segment_descriptor kvm_gdt[KVM_GDT_SIZE]; 182 183 /* Page table helper functions */ 184 uintptr_t kvm_get_page_address_pae(const struct page_table_entry_pae *entry); 185 186 /* Segment descriptor table functions */ 187 void kvm_set_segment_descriptor(struct segment_descriptor *dst, 188 uint64_t baseaddr, uint32_t limit, unsigned int flags); 189 void kvm_parse_segment_descriptor(struct segment_descriptor *src, 190 uint64_t *baseaddr, uint32_t *limit, unsigned int *flags); 191 int kvm_find_free_descriptor(const struct segment_descriptor *table, 192 size_t size); 193 unsigned int kvm_create_stack_descriptor(struct segment_descriptor *table, 194 size_t tabsize, void *stack_base); 195 196 /* Functions for querying CPU info and status */ 197 void kvm_get_cpuid(unsigned int eax, unsigned int ecx, struct kvm_cpuid *buf); 198 void kvm_read_cregs(struct kvm_cregs *buf); 199 void kvm_read_sregs(struct kvm_sregs *buf); 200 uint64_t kvm_rdmsr(unsigned int msr); 201 void kvm_wrmsr(unsigned int msr, uint64_t value); 202 203 /* Low-level interrupt handlers, DO NOT call directly */ 204 void kvm_handle_bad_exception(void); 205 void kvm_handle_zerodiv(void); 206 void kvm_handle_debug(void); 207 void kvm_handle_nmi(void); 208 void kvm_handle_breakpoint(void); 209 void kvm_handle_overflow(void); 210 void kvm_handle_bound_range_exc(void); 211 void kvm_handle_bad_opcode(void); 212 void kvm_handle_device_error(void); 213 void kvm_handle_double_fault(void); 214 void kvm_handle_invalid_tss(void); 215 void kvm_handle_segfault(void); 216 void kvm_handle_stack_fault(void); 217 void kvm_handle_gpf(void); 218 void kvm_handle_page_fault(void); 219 void kvm_handle_fpu_error(void); 220 void kvm_handle_alignment_error(void); 221 void kvm_handle_machine_check(void); 222 void kvm_handle_simd_error(void); 223 void kvm_handle_virt_error(void); 224 void kvm_handle_cpe(void); 225 void kvm_handle_hv_injection(void); 226 void kvm_handle_vmm_comm(void); 227 void kvm_handle_security_error(void); 228 229 #endif /* KVM_X86_H_ */ 230