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