1 /* $OpenBSD: vmmvar.h,v 1.109 2024/10/22 21:50:02 jsg Exp $ */ 2 /* 3 * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* 19 * CPU capabilities for VMM operation 20 */ 21 #ifndef _MACHINE_VMMVAR_H_ 22 #define _MACHINE_VMMVAR_H_ 23 24 #define VMM_HV_SIGNATURE "OpenBSDVMM58" 25 26 /* VMX: Basic Exit Reasons */ 27 #define VMX_EXIT_NMI 0 28 #define VMX_EXIT_EXTINT 1 29 #define VMX_EXIT_TRIPLE_FAULT 2 30 #define VMX_EXIT_INIT 3 31 #define VMX_EXIT_SIPI 4 32 #define VMX_EXIT_IO_SMI 5 33 #define VMX_EXIT_OTHER_SMI 6 34 #define VMX_EXIT_INT_WINDOW 7 35 #define VMX_EXIT_NMI_WINDOW 8 36 #define VMX_EXIT_TASK_SWITCH 9 37 #define VMX_EXIT_CPUID 10 38 #define VMX_EXIT_GETSEC 11 39 #define VMX_EXIT_HLT 12 40 #define VMX_EXIT_INVD 13 41 #define VMX_EXIT_INVLPG 14 42 #define VMX_EXIT_RDPMC 15 43 #define VMX_EXIT_RDTSC 16 44 #define VMX_EXIT_RSM 17 45 #define VMX_EXIT_VMCALL 18 46 #define VMX_EXIT_VMCLEAR 19 47 #define VMX_EXIT_VMLAUNCH 20 48 #define VMX_EXIT_VMPTRLD 21 49 #define VMX_EXIT_VMPTRST 22 50 #define VMX_EXIT_VMREAD 23 51 #define VMX_EXIT_VMRESUME 24 52 #define VMX_EXIT_VMWRITE 25 53 #define VMX_EXIT_VMXOFF 26 54 #define VMX_EXIT_VMXON 27 55 #define VMX_EXIT_CR_ACCESS 28 56 #define VMX_EXIT_MOV_DR 29 57 #define VMX_EXIT_IO 30 58 #define VMX_EXIT_RDMSR 31 59 #define VMX_EXIT_WRMSR 32 60 #define VMX_EXIT_ENTRY_FAILED_GUEST_STATE 33 61 #define VMX_EXIT_ENTRY_FAILED_MSR_LOAD 34 62 #define VMX_EXIT_MWAIT 36 63 #define VMX_EXIT_MTF 37 64 #define VMX_EXIT_MONITOR 39 65 #define VMX_EXIT_PAUSE 40 66 #define VMX_EXIT_ENTRY_FAILED_MCE 41 67 #define VMX_EXIT_TPR_BELOW_THRESHOLD 43 68 #define VMX_EXIT_APIC_ACCESS 44 69 #define VMX_EXIT_VIRTUALIZED_EOI 45 70 #define VMX_EXIT_GDTR_IDTR 46 71 #define VMX_EXIT_LDTR_TR 47 72 #define VMX_EXIT_EPT_VIOLATION 48 73 #define VMX_EXIT_EPT_MISCONFIGURATION 49 74 #define VMX_EXIT_INVEPT 50 75 #define VMX_EXIT_RDTSCP 51 76 #define VMX_EXIT_VMX_PREEMPTION_TIMER_EXPIRED 52 77 #define VMX_EXIT_INVVPID 53 78 #define VMX_EXIT_WBINVD 54 79 #define VMX_EXIT_XSETBV 55 80 #define VMX_EXIT_APIC_WRITE 56 81 #define VMX_EXIT_RDRAND 57 82 #define VMX_EXIT_INVPCID 58 83 #define VMX_EXIT_VMFUNC 59 84 #define VMX_EXIT_RDSEED 61 85 #define VMX_EXIT_XSAVES 63 86 #define VMX_EXIT_XRSTORS 64 87 88 #define VM_EXIT_TERMINATED 0xFFFE 89 #define VM_EXIT_NONE 0xFFFF 90 91 /* 92 * VMX: Misc defines 93 */ 94 #define VMX_MAX_CR3_TARGETS 256 95 #define VMX_VMCS_PA_CLEAR 0xFFFFFFFFFFFFFFFFUL 96 97 /* 98 * SVM: Intercept codes (exit reasons) 99 */ 100 #define SVM_VMEXIT_CR0_READ 0x00 101 #define SVM_VMEXIT_CR1_READ 0x01 102 #define SVM_VMEXIT_CR2_READ 0x02 103 #define SVM_VMEXIT_CR3_READ 0x03 104 #define SVM_VMEXIT_CR4_READ 0x04 105 #define SVM_VMEXIT_CR5_READ 0x05 106 #define SVM_VMEXIT_CR6_READ 0x06 107 #define SVM_VMEXIT_CR7_READ 0x07 108 #define SVM_VMEXIT_CR8_READ 0x08 109 #define SVM_VMEXIT_CR9_READ 0x09 110 #define SVM_VMEXIT_CR10_READ 0x0A 111 #define SVM_VMEXIT_CR11_READ 0x0B 112 #define SVM_VMEXIT_CR12_READ 0x0C 113 #define SVM_VMEXIT_CR13_READ 0x0D 114 #define SVM_VMEXIT_CR14_READ 0x0E 115 #define SVM_VMEXIT_CR15_READ 0x0F 116 #define SVM_VMEXIT_CR0_WRITE 0x10 117 #define SVM_VMEXIT_CR1_WRITE 0x11 118 #define SVM_VMEXIT_CR2_WRITE 0x12 119 #define SVM_VMEXIT_CR3_WRITE 0x13 120 #define SVM_VMEXIT_CR4_WRITE 0x14 121 #define SVM_VMEXIT_CR5_WRITE 0x15 122 #define SVM_VMEXIT_CR6_WRITE 0x16 123 #define SVM_VMEXIT_CR7_WRITE 0x17 124 #define SVM_VMEXIT_CR8_WRITE 0x18 125 #define SVM_VMEXIT_CR9_WRITE 0x19 126 #define SVM_VMEXIT_CR10_WRITE 0x1A 127 #define SVM_VMEXIT_CR11_WRITE 0x1B 128 #define SVM_VMEXIT_CR12_WRITE 0x1C 129 #define SVM_VMEXIT_CR13_WRITE 0x1D 130 #define SVM_VMEXIT_CR14_WRITE 0x1E 131 #define SVM_VMEXIT_CR15_WRITE 0x1F 132 #define SVM_VMEXIT_DR0_READ 0x20 133 #define SVM_VMEXIT_DR1_READ 0x21 134 #define SVM_VMEXIT_DR2_READ 0x22 135 #define SVM_VMEXIT_DR3_READ 0x23 136 #define SVM_VMEXIT_DR4_READ 0x24 137 #define SVM_VMEXIT_DR5_READ 0x25 138 #define SVM_VMEXIT_DR6_READ 0x26 139 #define SVM_VMEXIT_DR7_READ 0x27 140 #define SVM_VMEXIT_DR8_READ 0x28 141 #define SVM_VMEXIT_DR9_READ 0x29 142 #define SVM_VMEXIT_DR10_READ 0x2A 143 #define SVM_VMEXIT_DR11_READ 0x2B 144 #define SVM_VMEXIT_DR12_READ 0x2C 145 #define SVM_VMEXIT_DR13_READ 0x2D 146 #define SVM_VMEXIT_DR14_READ 0x2E 147 #define SVM_VMEXIT_DR15_READ 0x2F 148 #define SVM_VMEXIT_DR0_WRITE 0x30 149 #define SVM_VMEXIT_DR1_WRITE 0x31 150 #define SVM_VMEXIT_DR2_WRITE 0x32 151 #define SVM_VMEXIT_DR3_WRITE 0x33 152 #define SVM_VMEXIT_DR4_WRITE 0x34 153 #define SVM_VMEXIT_DR5_WRITE 0x35 154 #define SVM_VMEXIT_DR6_WRITE 0x36 155 #define SVM_VMEXIT_DR7_WRITE 0x37 156 #define SVM_VMEXIT_DR8_WRITE 0x38 157 #define SVM_VMEXIT_DR9_WRITE 0x39 158 #define SVM_VMEXIT_DR10_WRITE 0x3A 159 #define SVM_VMEXIT_DR11_WRITE 0x3B 160 #define SVM_VMEXIT_DR12_WRITE 0x3C 161 #define SVM_VMEXIT_DR13_WRITE 0x3D 162 #define SVM_VMEXIT_DR14_WRITE 0x3E 163 #define SVM_VMEXIT_DR15_WRITE 0x3F 164 #define SVM_VMEXIT_EXCP0 0x40 165 #define SVM_VMEXIT_EXCP1 0x41 166 #define SVM_VMEXIT_EXCP2 0x42 167 #define SVM_VMEXIT_EXCP3 0x43 168 #define SVM_VMEXIT_EXCP4 0x44 169 #define SVM_VMEXIT_EXCP5 0x45 170 #define SVM_VMEXIT_EXCP6 0x46 171 #define SVM_VMEXIT_EXCP7 0x47 172 #define SVM_VMEXIT_EXCP8 0x48 173 #define SVM_VMEXIT_EXCP9 0x49 174 #define SVM_VMEXIT_EXCP10 0x4A 175 #define SVM_VMEXIT_EXCP11 0x4B 176 #define SVM_VMEXIT_EXCP12 0x4C 177 #define SVM_VMEXIT_EXCP13 0x4D 178 #define SVM_VMEXIT_EXCP14 0x4E 179 #define SVM_VMEXIT_EXCP15 0x4F 180 #define SVM_VMEXIT_EXCP16 0x50 181 #define SVM_VMEXIT_EXCP17 0x51 182 #define SVM_VMEXIT_EXCP18 0x52 183 #define SVM_VMEXIT_EXCP19 0x53 184 #define SVM_VMEXIT_EXCP20 0x54 185 #define SVM_VMEXIT_EXCP21 0x55 186 #define SVM_VMEXIT_EXCP22 0x56 187 #define SVM_VMEXIT_EXCP23 0x57 188 #define SVM_VMEXIT_EXCP24 0x58 189 #define SVM_VMEXIT_EXCP25 0x59 190 #define SVM_VMEXIT_EXCP26 0x5A 191 #define SVM_VMEXIT_EXCP27 0x5B 192 #define SVM_VMEXIT_EXCP28 0x5C 193 #define SVM_VMEXIT_EXCP29 0x5D 194 #define SVM_VMEXIT_EXCP30 0x5E 195 #define SVM_VMEXIT_EXCP31 0x5F 196 #define SVM_VMEXIT_INTR 0x60 197 #define SVM_VMEXIT_NMI 0x61 198 #define SVM_VMEXIT_SMI 0x62 199 #define SVM_VMEXIT_INIT 0x63 200 #define SVM_VMEXIT_VINTR 0x64 201 #define SVM_VMEXIT_CR0_SEL_WRITE 0x65 202 #define SVM_VMEXIT_IDTR_READ 0x66 203 #define SVM_VMEXIT_GDTR_READ 0x67 204 #define SVM_VMEXIT_LDTR_READ 0x68 205 #define SVM_VMEXIT_TR_READ 0x69 206 #define SVM_VMEXIT_IDTR_WRITE 0x6A 207 #define SVM_VMEXIT_GDTR_WRITE 0x6B 208 #define SVM_VMEXIT_LDTR_WRITE 0x6C 209 #define SVM_VMEXIT_TR_WRITE 0x6D 210 #define SVM_VMEXIT_RDTSC 0x6E 211 #define SVM_VMEXIT_RDPMC 0x6F 212 #define SVM_VMEXIT_PUSHF 0x70 213 #define SVM_VMEXIT_POPF 0x71 214 #define SVM_VMEXIT_CPUID 0x72 215 #define SVM_VMEXIT_RSM 0x73 216 #define SVM_VMEXIT_IRET 0x74 217 #define SVM_VMEXIT_SWINT 0x75 218 #define SVM_VMEXIT_INVD 0x76 219 #define SVM_VMEXIT_PAUSE 0x77 220 #define SVM_VMEXIT_HLT 0x78 221 #define SVM_VMEXIT_INVLPG 0x79 222 #define SVM_VMEXIT_INVLPGA 0x7A 223 #define SVM_VMEXIT_IOIO 0x7B 224 #define SVM_VMEXIT_MSR 0x7C 225 #define SVM_VMEXIT_TASK_SWITCH 0x7D 226 #define SVM_VMEXIT_FERR_FREEZE 0x7E 227 #define SVM_VMEXIT_SHUTDOWN 0x7F 228 #define SVM_VMEXIT_VMRUN 0x80 229 #define SVM_VMEXIT_VMMCALL 0x81 230 #define SVM_VMEXIT_VMLOAD 0x82 231 #define SVM_VMEXIT_VMSAVE 0x83 232 #define SVM_VMEXIT_STGI 0x84 233 #define SVM_VMEXIT_CLGI 0x85 234 #define SVM_VMEXIT_SKINIT 0x86 235 #define SVM_VMEXIT_RDTSCP 0x87 236 #define SVM_VMEXIT_ICEBP 0x88 237 #define SVM_VMEXIT_WBINVD 0x89 238 #define SVM_VMEXIT_MONITOR 0x8A 239 #define SVM_VMEXIT_MWAIT 0x8B 240 #define SVM_VMEXIT_MWAIT_CONDITIONAL 0x8C 241 #define SVM_VMEXIT_XSETBV 0x8D 242 #define SVM_VMEXIT_EFER_WRITE_TRAP 0x8F 243 #define SVM_VMEXIT_CR0_WRITE_TRAP 0x90 244 #define SVM_VMEXIT_CR1_WRITE_TRAP 0x91 245 #define SVM_VMEXIT_CR2_WRITE_TRAP 0x92 246 #define SVM_VMEXIT_CR3_WRITE_TRAP 0x93 247 #define SVM_VMEXIT_CR4_WRITE_TRAP 0x94 248 #define SVM_VMEXIT_CR5_WRITE_TRAP 0x95 249 #define SVM_VMEXIT_CR6_WRITE_TRAP 0x96 250 #define SVM_VMEXIT_CR7_WRITE_TRAP 0x97 251 #define SVM_VMEXIT_CR8_WRITE_TRAP 0x98 252 #define SVM_VMEXIT_CR9_WRITE_TRAP 0x99 253 #define SVM_VMEXIT_CR10_WRITE_TRAP 0x9A 254 #define SVM_VMEXIT_CR11_WRITE_TRAP 0x9B 255 #define SVM_VMEXIT_CR12_WRITE_TRAP 0x9C 256 #define SVM_VMEXIT_CR13_WRITE_TRAP 0x9D 257 #define SVM_VMEXIT_CR14_WRITE_TRAP 0x9E 258 #define SVM_VMEXIT_CR15_WRITE_TRAP 0x9F 259 #define SVM_VMEXIT_NPF 0x400 260 #define SVM_AVIC_INCOMPLETE_IPI 0x401 261 #define SVM_AVIC_NOACCEL 0x402 262 #define SVM_VMEXIT_VMGEXIT 0x403 263 #define SVM_VMEXIT_INVALID -1 264 265 /* 266 * Exception injection vectors (these correspond to the CPU exception types 267 * defined in the SDM.) 268 */ 269 #define VMM_EX_DE 0 /* Divide Error #DE */ 270 #define VMM_EX_DB 1 /* Debug Exception #DB */ 271 #define VMM_EX_NMI 2 /* NMI */ 272 #define VMM_EX_BP 3 /* Breakpoint #BP */ 273 #define VMM_EX_OF 4 /* Overflow #OF */ 274 #define VMM_EX_BR 5 /* Bound range exceeded #BR */ 275 #define VMM_EX_UD 6 /* Undefined opcode #UD */ 276 #define VMM_EX_NM 7 /* Device not available #NM */ 277 #define VMM_EX_DF 8 /* Double fault #DF */ 278 #define VMM_EX_CP 9 /* Coprocessor segment overrun (unused) */ 279 #define VMM_EX_TS 10 /* Invalid TSS #TS */ 280 #define VMM_EX_NP 11 /* Segment not present #NP */ 281 #define VMM_EX_SS 12 /* Stack segment fault #SS */ 282 #define VMM_EX_GP 13 /* General protection #GP */ 283 #define VMM_EX_PF 14 /* Page fault #PF */ 284 #define VMM_EX_MF 16 /* x87 FPU floating point error #MF */ 285 #define VMM_EX_AC 17 /* Alignment check #AC */ 286 #define VMM_EX_MC 18 /* Machine check #MC */ 287 #define VMM_EX_XM 19 /* SIMD floating point exception #XM */ 288 #define VMM_EX_VE 20 /* Virtualization exception #VE */ 289 290 enum { 291 VEI_DIR_OUT, 292 VEI_DIR_IN 293 }; 294 295 enum { 296 VEE_FAULT_INVALID = 0, 297 VEE_FAULT_HANDLED, 298 VEE_FAULT_MMIO_ASSIST, 299 VEE_FAULT_PROTECT, 300 }; 301 302 enum { 303 VMM_CPU_MODE_REAL, 304 VMM_CPU_MODE_PROT, 305 VMM_CPU_MODE_PROT32, 306 VMM_CPU_MODE_COMPAT, 307 VMM_CPU_MODE_LONG, 308 VMM_CPU_MODE_UNKNOWN, 309 }; 310 311 struct vmm_softc_md { 312 /* Capabilities */ 313 uint32_t nr_rvi_cpus; /* [I] */ 314 uint32_t nr_ept_cpus; /* [I] */ 315 uint8_t pkru_enabled; /* [I] */ 316 }; 317 318 /* 319 * vm exit data 320 * vm_exit_inout : describes an IN/OUT exit 321 */ 322 struct vm_exit_inout { 323 uint8_t vei_size; /* Size of access */ 324 uint8_t vei_dir; /* Direction */ 325 uint8_t vei_rep; /* REP prefix? */ 326 uint8_t vei_string; /* string variety? */ 327 uint8_t vei_encoding; /* operand encoding */ 328 uint16_t vei_port; /* port */ 329 uint32_t vei_data; /* data */ 330 uint8_t vei_insn_len; /* Count of instruction bytes */ 331 }; 332 333 /* 334 * vm_exit_eptviolation : describes an EPT VIOLATION exit 335 */ 336 struct vm_exit_eptviolation { 337 uint8_t vee_fault_type; /* type of vm exit */ 338 uint8_t vee_insn_info; /* bitfield */ 339 #define VEE_LEN_VALID 0x1 /* vee_insn_len is valid */ 340 #define VEE_BYTES_VALID 0x2 /* vee_insn_bytes is valid */ 341 uint8_t vee_insn_len; /* [VMX] instruction length */ 342 uint8_t vee_insn_bytes[15]; /* [SVM] bytes at {R,E,}IP */ 343 }; 344 345 /* 346 * struct vcpu_inject_event : describes an exception or interrupt to inject. 347 */ 348 struct vcpu_inject_event { 349 uint8_t vie_vector; /* Exception or interrupt vector. */ 350 uint32_t vie_errorcode; /* Optional error code. */ 351 uint8_t vie_type; 352 #define VCPU_INJECT_NONE 0 353 #define VCPU_INJECT_INTR 1 /* External hardware interrupt. */ 354 #define VCPU_INJECT_EX 2 /* HW or SW Exception */ 355 #define VCPU_INJECT_NMI 3 /* Non-maskable Interrupt */ 356 }; 357 358 /* 359 * struct vcpu_segment_info 360 * 361 * Describes a segment + selector set, used in constructing the initial vcpu 362 * register content 363 */ 364 struct vcpu_segment_info { 365 uint16_t vsi_sel; 366 uint32_t vsi_limit; 367 uint32_t vsi_ar; 368 uint64_t vsi_base; 369 }; 370 371 /* The GPRS are ordered to assist instruction decode. */ 372 #define VCPU_REGS_RAX 0 373 #define VCPU_REGS_RCX 1 374 #define VCPU_REGS_RDX 2 375 #define VCPU_REGS_RBX 3 376 #define VCPU_REGS_RSP 4 377 #define VCPU_REGS_RBP 5 378 #define VCPU_REGS_RSI 6 379 #define VCPU_REGS_RDI 7 380 #define VCPU_REGS_R8 8 381 #define VCPU_REGS_R9 9 382 #define VCPU_REGS_R10 10 383 #define VCPU_REGS_R11 11 384 #define VCPU_REGS_R12 12 385 #define VCPU_REGS_R13 13 386 #define VCPU_REGS_R14 14 387 #define VCPU_REGS_R15 15 388 #define VCPU_REGS_RIP 16 389 #define VCPU_REGS_RFLAGS 17 390 #define VCPU_REGS_NGPRS (VCPU_REGS_RFLAGS + 1) 391 392 #define VCPU_REGS_CR0 0 393 #define VCPU_REGS_CR2 1 394 #define VCPU_REGS_CR3 2 395 #define VCPU_REGS_CR4 3 396 #define VCPU_REGS_CR8 4 397 #define VCPU_REGS_XCR0 5 398 #define VCPU_REGS_PDPTE0 6 399 #define VCPU_REGS_PDPTE1 7 400 #define VCPU_REGS_PDPTE2 8 401 #define VCPU_REGS_PDPTE3 9 402 #define VCPU_REGS_NCRS (VCPU_REGS_PDPTE3 + 1) 403 404 #define VCPU_REGS_ES 0 405 #define VCPU_REGS_CS 1 406 #define VCPU_REGS_SS 2 407 #define VCPU_REGS_DS 3 408 #define VCPU_REGS_FS 4 409 #define VCPU_REGS_GS 5 410 #define VCPU_REGS_LDTR 6 411 #define VCPU_REGS_TR 7 412 #define VCPU_REGS_NSREGS (VCPU_REGS_TR + 1) 413 414 #define VCPU_REGS_EFER 0 415 #define VCPU_REGS_STAR 1 416 #define VCPU_REGS_LSTAR 2 417 #define VCPU_REGS_CSTAR 3 418 #define VCPU_REGS_SFMASK 4 419 #define VCPU_REGS_KGSBASE 5 420 #define VCPU_REGS_MISC_ENABLE 6 421 #define VCPU_REGS_NMSRS (VCPU_REGS_MISC_ENABLE + 1) 422 423 #define VCPU_REGS_DR0 0 424 #define VCPU_REGS_DR1 1 425 #define VCPU_REGS_DR2 2 426 #define VCPU_REGS_DR3 3 427 #define VCPU_REGS_DR6 4 428 #define VCPU_REGS_DR7 5 429 #define VCPU_REGS_NDRS (VCPU_REGS_DR7 + 1) 430 431 struct vcpu_reg_state { 432 uint64_t vrs_gprs[VCPU_REGS_NGPRS]; 433 uint64_t vrs_crs[VCPU_REGS_NCRS]; 434 uint64_t vrs_msrs[VCPU_REGS_NMSRS]; 435 uint64_t vrs_drs[VCPU_REGS_NDRS]; 436 struct vcpu_segment_info vrs_sregs[VCPU_REGS_NSREGS]; 437 struct vcpu_segment_info vrs_gdtr; 438 struct vcpu_segment_info vrs_idtr; 439 }; 440 441 #define VCPU_HOST_REGS_EFER 0 442 #define VCPU_HOST_REGS_STAR 1 443 #define VCPU_HOST_REGS_LSTAR 2 444 #define VCPU_HOST_REGS_CSTAR 3 445 #define VCPU_HOST_REGS_SFMASK 4 446 #define VCPU_HOST_REGS_KGSBASE 5 447 #define VCPU_HOST_REGS_MISC_ENABLE 6 448 #define VCPU_HOST_REGS_NMSRS (VCPU_HOST_REGS_MISC_ENABLE + 1) 449 450 /* 451 * struct vm_exit 452 * 453 * Contains VM exit information communicated to vmd(8). This information is 454 * gathered by vmm(4) from the CPU on each exit that requires help from vmd. 455 */ 456 struct vm_exit { 457 union { 458 struct vm_exit_inout vei; /* IN/OUT exit */ 459 struct vm_exit_eptviolation vee; /* EPT VIOLATION exit*/ 460 }; 461 462 struct vcpu_reg_state vrs; 463 int cpl; 464 }; 465 466 struct vm_intr_params { 467 /* Input parameters to VMM_IOC_INTR */ 468 uint32_t vip_vm_id; 469 uint32_t vip_vcpu_id; 470 uint16_t vip_intr; 471 }; 472 473 #define VM_RWREGS_GPRS 0x1 /* read/write GPRs */ 474 #define VM_RWREGS_SREGS 0x2 /* read/write segment registers */ 475 #define VM_RWREGS_CRS 0x4 /* read/write CRs */ 476 #define VM_RWREGS_MSRS 0x8 /* read/write MSRs */ 477 #define VM_RWREGS_DRS 0x10 /* read/write DRs */ 478 #define VM_RWREGS_ALL (VM_RWREGS_GPRS | VM_RWREGS_SREGS | VM_RWREGS_CRS | \ 479 VM_RWREGS_MSRS | VM_RWREGS_DRS) 480 481 struct vm_rwregs_params { 482 /* 483 * Input/output parameters to VMM_IOC_READREGS / 484 * VMM_IOC_WRITEREGS 485 */ 486 uint32_t vrwp_vm_id; 487 uint32_t vrwp_vcpu_id; 488 uint64_t vrwp_mask; 489 struct vcpu_reg_state vrwp_regs; 490 }; 491 492 /* IOCTL definitions */ 493 #define VMM_IOC_INTR _IOW('V', 6, struct vm_intr_params) /* Intr pending */ 494 495 /* CPUID masks */ 496 /* 497 * clone host capabilities minus: 498 * debug store (CPUIDECX_DTES64, CPUIDECX_DSCPL, CPUID_DS) 499 * monitor/mwait (CPUIDECX_MWAIT, CPUIDECX_MWAITX) 500 * vmx/svm (CPUIDECX_VMX, CPUIDECX_SVM) 501 * smx (CPUIDECX_SMX) 502 * speedstep (CPUIDECX_EST) 503 * thermal (CPUIDECX_TM2, CPUID_ACPI, CPUID_TM) 504 * context id (CPUIDECX_CNXTID) 505 * machine check (CPUID_MCE, CPUID_MCA) 506 * silicon debug (CPUIDECX_SDBG) 507 * xTPR (CPUIDECX_XTPR) 508 * perf/debug (CPUIDECX_PDCM) 509 * pcid (CPUIDECX_PCID) 510 * direct cache access (CPUIDECX_DCA) 511 * x2APIC (CPUIDECX_X2APIC) 512 * apic deadline (CPUIDECX_DEADLINE) 513 * apic (CPUID_APIC) 514 * psn (CPUID_PSN) 515 * self snoop (CPUID_SS) 516 * hyperthreading (CPUID_HTT) 517 * pending break enabled (CPUID_PBE) 518 * MTRR (CPUID_MTRR) 519 * Speculative execution control features (AMD) 520 */ 521 #define VMM_CPUIDECX_MASK ~(CPUIDECX_EST | CPUIDECX_TM2 | CPUIDECX_MWAIT | \ 522 CPUIDECX_PDCM | CPUIDECX_VMX | CPUIDECX_DTES64 | \ 523 CPUIDECX_DSCPL | CPUIDECX_SMX | CPUIDECX_CNXTID | \ 524 CPUIDECX_SDBG | CPUIDECX_XTPR | CPUIDECX_PCID | \ 525 CPUIDECX_DCA | CPUIDECX_X2APIC | CPUIDECX_DEADLINE) 526 #define VMM_ECPUIDECX_MASK ~(CPUIDECX_SVM | CPUIDECX_MWAITX) 527 #define VMM_CPUIDEDX_MASK ~(CPUID_ACPI | CPUID_TM | \ 528 CPUID_HTT | CPUID_DS | CPUID_APIC | \ 529 CPUID_PSN | CPUID_SS | CPUID_PBE | \ 530 CPUID_MTRR | CPUID_MCE | CPUID_MCA) 531 #define VMM_AMDSPEC_EBX_MASK ~(CPUIDEBX_IBPB | CPUIDEBX_IBRS | \ 532 CPUIDEBX_STIBP | CPUIDEBX_IBRS_ALWAYSON | CPUIDEBX_STIBP_ALWAYSON | \ 533 CPUIDEBX_IBRS_PREF | CPUIDEBX_SSBD | CPUIDEBX_VIRT_SSBD | \ 534 CPUIDEBX_SSBD_NOTREQ) 535 536 /* This mask is an include list for bits we want to expose */ 537 #define VMM_APMI_EDX_INCLUDE_MASK (CPUIDEDX_ITSC) 538 539 /* 540 * SEFF flags - copy from host minus: 541 * TSC_ADJUST (SEFF0EBX_TSC_ADJUST) 542 * SGX (SEFF0EBX_SGX) 543 * HLE (SEFF0EBX_HLE) 544 * INVPCID (SEFF0EBX_INVPCID) 545 * RTM (SEFF0EBX_RTM) 546 * PQM (SEFF0EBX_PQM) 547 * AVX512F (SEFF0EBX_AVX512F) 548 * AVX512DQ (SEFF0EBX_AVX512DQ) 549 * AVX512IFMA (SEFF0EBX_AVX512IFMA) 550 * AVX512PF (SEFF0EBX_AVX512PF) 551 * AVX512ER (SEFF0EBX_AVX512ER) 552 * AVX512CD (SEFF0EBX_AVX512CD) 553 * AVX512BW (SEFF0EBX_AVX512BW) 554 * AVX512VL (SEFF0EBX_AVX512VL) 555 * MPX (SEFF0EBX_MPX) 556 * PCOMMIT (SEFF0EBX_PCOMMIT) 557 * PT (SEFF0EBX_PT) 558 */ 559 #define VMM_SEFF0EBX_MASK ~(SEFF0EBX_TSC_ADJUST | SEFF0EBX_SGX | \ 560 SEFF0EBX_HLE | SEFF0EBX_INVPCID | \ 561 SEFF0EBX_RTM | SEFF0EBX_PQM | SEFF0EBX_MPX | \ 562 SEFF0EBX_PCOMMIT | SEFF0EBX_PT | \ 563 SEFF0EBX_AVX512F | SEFF0EBX_AVX512DQ | \ 564 SEFF0EBX_AVX512IFMA | SEFF0EBX_AVX512PF | \ 565 SEFF0EBX_AVX512ER | SEFF0EBX_AVX512CD | \ 566 SEFF0EBX_AVX512BW | SEFF0EBX_AVX512VL) 567 568 /* ECX mask contains the bits to include */ 569 #define VMM_SEFF0ECX_MASK (SEFF0ECX_UMIP) 570 571 /* EDX mask contains the bits to include */ 572 #define VMM_SEFF0EDX_MASK (SEFF0EDX_MD_CLEAR) 573 574 /* 575 * Extended function flags - copy from host minus: 576 * 0x80000001 EDX:RDTSCP Support 577 */ 578 #define VMM_FEAT_EFLAGS_MASK ~(CPUID_RDTSCP) 579 580 /* 581 * CPUID[0x4] deterministic cache info 582 */ 583 #define VMM_CPUID4_CACHE_TOPOLOGY_MASK 0x3FF 584 585 #ifdef _KERNEL 586 587 #define VMX_FAIL_LAUNCH_UNKNOWN 1 588 #define VMX_FAIL_LAUNCH_INVALID_VMCS 2 589 #define VMX_FAIL_LAUNCH_VALID_VMCS 3 590 591 /* MSR bitmap manipulation macros */ 592 #define VMX_MSRIDX(m) ((m) / 8) 593 #define VMX_MSRBIT(m) (1 << (m) % 8) 594 595 #define SVM_MSRIDX(m) ((m) / 4) 596 #define SVM_MSRBIT_R(m) (1 << (((m) % 4) * 2)) 597 #define SVM_MSRBIT_W(m) (1 << (((m) % 4) * 2 + 1)) 598 599 enum { 600 VMM_MODE_UNKNOWN, 601 VMM_MODE_EPT, 602 VMM_MODE_RVI 603 }; 604 605 enum { 606 VMM_MEM_TYPE_REGULAR, 607 VMM_MEM_TYPE_MMIO, 608 VMM_MEM_TYPE_UNKNOWN 609 }; 610 611 /* Forward declarations */ 612 struct vm; 613 struct vm_create_params; 614 615 /* 616 * Implementation-specific cpu state 617 */ 618 619 struct vmcb_segment { 620 uint16_t vs_sel; /* 000h */ 621 uint16_t vs_attr; /* 002h */ 622 uint32_t vs_lim; /* 004h */ 623 uint64_t vs_base; /* 008h */ 624 }; 625 626 #define SVM_ENABLE_NP (1ULL << 0) 627 #define SVM_ENABLE_SEV (1ULL << 1) 628 629 struct vmcb { 630 union { 631 struct { 632 uint32_t v_cr_rw; /* 000h */ 633 uint32_t v_dr_rw; /* 004h */ 634 uint32_t v_excp; /* 008h */ 635 uint32_t v_intercept1; /* 00Ch */ 636 uint32_t v_intercept2; /* 010h */ 637 uint8_t v_pad1[0x28]; /* 014h-03Bh */ 638 uint16_t v_pause_thr; /* 03Ch */ 639 uint16_t v_pause_ct; /* 03Eh */ 640 uint64_t v_iopm_pa; /* 040h */ 641 uint64_t v_msrpm_pa; /* 048h */ 642 uint64_t v_tsc_offset; /* 050h */ 643 uint32_t v_asid; /* 058h */ 644 uint8_t v_tlb_control; /* 05Ch */ 645 uint8_t v_pad2[0x3]; /* 05Dh-05Fh */ 646 uint8_t v_tpr; /* 060h */ 647 uint8_t v_irq; /* 061h */ 648 uint8_t v_intr_misc; /* 062h */ 649 uint8_t v_intr_masking; /* 063h */ 650 uint8_t v_intr_vector; /* 064h */ 651 uint8_t v_pad3[0x3]; /* 065h-067h */ 652 uint64_t v_intr_shadow; /* 068h */ 653 uint64_t v_exitcode; /* 070h */ 654 uint64_t v_exitinfo1; /* 078h */ 655 uint64_t v_exitinfo2; /* 080h */ 656 uint64_t v_exitintinfo; /* 088h */ 657 uint64_t v_np_enable; /* 090h */ 658 uint64_t v_avic_apic_bar; /* 098h */ 659 uint64_t v_pad4; /* 0A0h */ 660 uint64_t v_eventinj; /* 0A8h */ 661 uint64_t v_n_cr3; /* 0B0h */ 662 uint64_t v_lbr_virt_enable; /* 0B8h */ 663 uint64_t v_vmcb_clean_bits; /* 0C0h */ 664 uint64_t v_nrip; /* 0C8h */ 665 uint8_t v_n_bytes_fetched; /* 0D0h */ 666 uint8_t v_guest_ins_bytes[0xf]; /* 0D1h-0DFh */ 667 uint64_t v_avic_apic_back_page; /* 0E0h */ 668 uint64_t v_pad5; /* 0E8h-0EFh */ 669 uint64_t v_avic_logical_table; /* 0F0h */ 670 uint64_t v_avic_phys; /* 0F8h */ 671 672 }; 673 uint8_t vmcb_control[0x400]; 674 }; 675 676 union { 677 struct { 678 /* Offsets here are relative to start of VMCB SSA */ 679 struct vmcb_segment v_es; /* 000h */ 680 struct vmcb_segment v_cs; /* 010h */ 681 struct vmcb_segment v_ss; /* 020h */ 682 struct vmcb_segment v_ds; /* 030h */ 683 struct vmcb_segment v_fs; /* 040h */ 684 struct vmcb_segment v_gs; /* 050h */ 685 struct vmcb_segment v_gdtr; /* 060h */ 686 struct vmcb_segment v_ldtr; /* 070h */ 687 struct vmcb_segment v_idtr; /* 080h */ 688 struct vmcb_segment v_tr; /* 090h */ 689 uint8_t v_pad6[0x2B]; /* 0A0h-0CAh */ 690 uint8_t v_cpl; /* 0CBh */ 691 uint32_t v_pad7; /* 0CCh-0CFh */ 692 uint64_t v_efer; /* 0D0h */ 693 uint8_t v_pad8[0x70]; /* 0D8h-147h */ 694 uint64_t v_cr4; /* 148h */ 695 uint64_t v_cr3; /* 150h */ 696 uint64_t v_cr0; /* 158h */ 697 uint64_t v_dr7; /* 160h */ 698 uint64_t v_dr6; /* 168h */ 699 uint64_t v_rflags; /* 170h */ 700 uint64_t v_rip; /* 178h */ 701 uint64_t v_pad9[0xB]; /* 180h-1D7h */ 702 uint64_t v_rsp; /* 1D8h */ 703 uint64_t v_pad10[0x3]; /* 1E0h-1F7h */ 704 uint64_t v_rax; /* 1F8h */ 705 uint64_t v_star; /* 200h */ 706 uint64_t v_lstar; /* 208h */ 707 uint64_t v_cstar; /* 210h */ 708 uint64_t v_sfmask; /* 218h */ 709 uint64_t v_kgsbase; /* 220h */ 710 uint64_t v_sysenter_cs; /* 228h */ 711 uint64_t v_sysenter_esp; /* 230h */ 712 uint64_t v_sysenter_eip; /* 238h */ 713 uint64_t v_cr2; /* 240h */ 714 uint64_t v_pad11[0x4]; /* 248h-267h */ 715 uint64_t v_g_pat; /* 268h */ 716 uint64_t v_dbgctl; /* 270h */ 717 uint64_t v_br_from; /* 278h */ 718 uint64_t v_br_to; /* 280h */ 719 uint64_t v_lastexcpfrom; /* 288h */ 720 uint64_t v_lastexcpto; /* 290h */ 721 }; 722 uint8_t vmcb_layout[PAGE_SIZE - 0x400]; 723 }; 724 }; 725 726 struct vmcs { 727 uint32_t vmcs_revision; 728 }; 729 730 struct vmx_invvpid_descriptor { 731 uint64_t vid_vpid; 732 uint64_t vid_addr; 733 }; 734 735 struct vmx_invept_descriptor { 736 uint64_t vid_eptp; 737 uint64_t vid_reserved; 738 }; 739 740 struct vmx_msr_store { 741 uint64_t vms_index; 742 uint64_t vms_data; 743 }; 744 745 /* 746 * Storage for guest registers not preserved in VMCS and various exit 747 * information. 748 * 749 * Note that vmx/svm_enter_guest depend on the layout of this struct for 750 * field access. 751 */ 752 struct vcpu_gueststate { 753 /* %rsi should be first */ 754 uint64_t vg_rsi; /* 0x00 */ 755 uint64_t vg_rax; /* 0x08 */ 756 uint64_t vg_rbx; /* 0x10 */ 757 uint64_t vg_rcx; /* 0x18 */ 758 uint64_t vg_rdx; /* 0x20 */ 759 uint64_t vg_rdi; /* 0x28 */ 760 uint64_t vg_rbp; /* 0x30 */ 761 uint64_t vg_r8; /* 0x38 */ 762 uint64_t vg_r9; /* 0x40 */ 763 uint64_t vg_r10; /* 0x48 */ 764 uint64_t vg_r11; /* 0x50 */ 765 uint64_t vg_r12; /* 0x58 */ 766 uint64_t vg_r13; /* 0x60 */ 767 uint64_t vg_r14; /* 0x68 */ 768 uint64_t vg_r15; /* 0x70 */ 769 uint64_t vg_cr2; /* 0x78 */ 770 uint64_t vg_rip; /* 0x80 */ 771 uint32_t vg_exit_reason; /* 0x88 */ 772 uint64_t vg_rflags; /* 0x90 */ 773 uint64_t vg_xcr0; /* 0x98 */ 774 /* 775 * Debug registers 776 * - %dr4/%dr5 are aliased to %dr6/%dr7 (or cause #DE) 777 * - %dr7 is saved automatically in the VMCS 778 */ 779 uint64_t vg_dr0; /* 0xa0 */ 780 uint64_t vg_dr1; /* 0xa8 */ 781 uint64_t vg_dr2; /* 0xb0 */ 782 uint64_t vg_dr3; /* 0xb8 */ 783 uint64_t vg_dr6; /* 0xc0 */ 784 }; 785 786 /* 787 * Virtual CPU 788 * 789 * Methods used to vcpu struct members: 790 * a atomic operations 791 * I immutable operations 792 * K kernel lock 793 * r reference count 794 * v vcpu rwlock 795 * V vm struct's vcpu list lock (vm_vcpu_lock) 796 */ 797 struct vcpu { 798 /* 799 * Guest FPU state - this must remain as the first member of the struct 800 * to ensure 64-byte alignment (set up during vcpu_pool init) 801 */ 802 struct savefpu vc_g_fpu; /* [v] */ 803 804 /* VMCS / VMCB pointer */ 805 vaddr_t vc_control_va; /* [I] */ 806 paddr_t vc_control_pa; /* [I] */ 807 808 /* VLAPIC pointer */ 809 vaddr_t vc_vlapic_va; /* [I] */ 810 uint64_t vc_vlapic_pa; /* [I] */ 811 812 /* MSR bitmap address */ 813 vaddr_t vc_msr_bitmap_va; /* [I] */ 814 uint64_t vc_msr_bitmap_pa; /* [I] */ 815 816 struct vm *vc_parent; /* [I] */ 817 uint32_t vc_id; /* [I] */ 818 uint16_t vc_vpid; /* [I] */ 819 u_int vc_state; /* [a] */ 820 SLIST_ENTRY(vcpu) vc_vcpu_link; /* [V] */ 821 822 uint8_t vc_virt_mode; /* [I] */ 823 824 struct rwlock vc_lock; 825 826 struct cpu_info *vc_curcpu; /* [a] */ 827 struct cpu_info *vc_last_pcpu; /* [v] */ 828 struct vm_exit vc_exit; /* [v] */ 829 830 uint16_t vc_intr; /* [v] */ 831 uint8_t vc_irqready; /* [v] */ 832 833 uint8_t vc_fpuinited; /* [v] */ 834 835 uint64_t vc_h_xcr0; /* [v] */ 836 837 struct vcpu_gueststate vc_gueststate; /* [v] */ 838 struct vcpu_inject_event vc_inject; /* [v] */ 839 840 uint32_t vc_pvclock_version; /* [v] */ 841 paddr_t vc_pvclock_system_gpa; /* [v] */ 842 uint32_t vc_pvclock_system_tsc_mul; /* [v] */ 843 844 /* Shadowed MSRs */ 845 uint64_t vc_shadow_pat; /* [v] */ 846 847 /* Userland Protection Keys */ 848 uint32_t vc_pkru; /* [v] */ 849 850 /* VMX only (all requiring [v]) */ 851 uint64_t vc_vmx_basic; 852 uint64_t vc_vmx_entry_ctls; 853 uint64_t vc_vmx_true_entry_ctls; 854 uint64_t vc_vmx_exit_ctls; 855 uint64_t vc_vmx_true_exit_ctls; 856 uint64_t vc_vmx_pinbased_ctls; 857 uint64_t vc_vmx_true_pinbased_ctls; 858 uint64_t vc_vmx_procbased_ctls; 859 uint64_t vc_vmx_true_procbased_ctls; 860 uint64_t vc_vmx_procbased2_ctls; 861 vaddr_t vc_vmx_msr_exit_save_va; 862 paddr_t vc_vmx_msr_exit_save_pa; 863 vaddr_t vc_vmx_msr_exit_load_va; 864 paddr_t vc_vmx_msr_exit_load_pa; 865 #if 0 /* XXX currently use msr_exit_save for msr_entry_load too */ 866 vaddr_t vc_vmx_msr_entry_load_va; 867 paddr_t vc_vmx_msr_entry_load_pa; 868 #endif 869 uint8_t vc_vmx_vpid_enabled; 870 uint64_t vc_vmx_cr0_fixed1; 871 uint64_t vc_vmx_cr0_fixed0; 872 uint32_t vc_vmx_vmcs_state; /* [a] */ 873 #define VMCS_CLEARED 0 874 #define VMCS_LAUNCHED 1 875 876 /* SVM only (all requiring [v]) */ 877 vaddr_t vc_svm_hsa_va; 878 paddr_t vc_svm_hsa_pa; 879 vaddr_t vc_svm_ioio_va; 880 paddr_t vc_svm_ioio_pa; 881 int vc_sev; /* [I] */ 882 }; 883 884 SLIST_HEAD(vcpu_head, vcpu); 885 886 void vmm_dispatch_intr(vaddr_t); 887 int vmxon(uint64_t *); 888 int vmxoff(void); 889 int vmclear(paddr_t *); 890 int vmptrld(paddr_t *); 891 int vmptrst(paddr_t *); 892 int vmwrite(uint64_t, uint64_t); 893 int vmread(uint64_t, uint64_t *); 894 int invvpid(uint64_t, struct vmx_invvpid_descriptor *); 895 int invept(uint64_t, struct vmx_invept_descriptor *); 896 int vmx_enter_guest(paddr_t *, struct vcpu_gueststate *, int, uint8_t); 897 int svm_enter_guest(uint64_t, struct vcpu_gueststate *, 898 struct region_descriptor *); 899 void start_vmm_on_cpu(struct cpu_info *); 900 void stop_vmm_on_cpu(struct cpu_info *); 901 void vmclear_on_cpu(struct cpu_info *); 902 void vmm_attach_machdep(struct device *, struct device *, void *); 903 void vmm_activate_machdep(struct device *, int); 904 int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *); 905 int pledge_ioctl_vmm_machdep(struct proc *, long); 906 int vmm_start(void); 907 int vmm_stop(void); 908 int vm_impl_init(struct vm *, struct proc *); 909 void vm_impl_deinit(struct vm *); 910 int vcpu_init(struct vcpu *, struct vm_create_params *); 911 void vcpu_deinit(struct vcpu *); 912 int vm_rwregs(struct vm_rwregs_params *, int); 913 int vcpu_reset_regs(struct vcpu *, struct vcpu_reg_state *); 914 915 #endif /* _KERNEL */ 916 917 #endif /* ! _MACHINE_VMMVAR_H_ */ 918