Print this page
13275 bhyve needs richer INIT/SIPI support
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Approved by: Gordon Ross <gordon.w.ross@gmail.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/i86pc/sys/vmm.h
+++ new/usr/src/uts/i86pc/sys/vmm.h
1 1 /*-
2 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 3 *
4 4 * Copyright (c) 2011 NetApp, Inc.
5 5 * All rights reserved.
6 6 *
7 7 * Redistribution and use in source and binary forms, with or without
8 8 * modification, are permitted provided that the following conditions
9 9 * are met:
10 10 * 1. Redistributions of source code must retain the above copyright
11 11 * notice, this list of conditions and the following disclaimer.
12 12 * 2. Redistributions in binary form must reproduce the above copyright
13 13 * notice, this list of conditions and the following disclaimer in the
14 14 * documentation and/or other materials provided with the distribution.
15 15 *
16 16 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 19 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 26 * SUCH DAMAGE.
27 27 *
28 28 * $FreeBSD$
29 29 */
30 30 /*
31 31 * This file and its contents are supplied under the terms of the
32 32 * Common Development and Distribution License ("CDDL"), version 1.0.
33 33 * You may only use this file in accordance with the terms of version
34 34 * 1.0 of the CDDL.
35 35 *
36 36 * A full copy of the text of the CDDL should have accompanied this
37 37 * source. A copy of the CDDL is also available via the Internet at
38 38 * http://www.illumos.org/license/CDDL.
39 39 *
40 40 * Copyright 2015 Pluribus Networks Inc.
41 41 * Copyright 2019 Joyent, Inc.
42 42 * Copyright 2020 Oxide Computer Company
43 43 */
44 44
45 45 #ifndef _VMM_H_
46 46 #define _VMM_H_
47 47
48 48 enum vm_suspend_how {
49 49 VM_SUSPEND_NONE,
50 50 VM_SUSPEND_RESET,
51 51 VM_SUSPEND_POWEROFF,
52 52 VM_SUSPEND_HALT,
53 53 VM_SUSPEND_TRIPLEFAULT,
54 54 VM_SUSPEND_LAST
55 55 };
56 56
57 57 /*
58 58 * Identifiers for architecturally defined registers.
59 59 */
60 60 enum vm_reg_name {
61 61 VM_REG_GUEST_RAX,
62 62 VM_REG_GUEST_RBX,
63 63 VM_REG_GUEST_RCX,
64 64 VM_REG_GUEST_RDX,
65 65 VM_REG_GUEST_RSI,
66 66 VM_REG_GUEST_RDI,
67 67 VM_REG_GUEST_RBP,
68 68 VM_REG_GUEST_R8,
69 69 VM_REG_GUEST_R9,
70 70 VM_REG_GUEST_R10,
71 71 VM_REG_GUEST_R11,
72 72 VM_REG_GUEST_R12,
73 73 VM_REG_GUEST_R13,
74 74 VM_REG_GUEST_R14,
75 75 VM_REG_GUEST_R15,
76 76 VM_REG_GUEST_CR0,
77 77 VM_REG_GUEST_CR3,
78 78 VM_REG_GUEST_CR4,
79 79 VM_REG_GUEST_DR7,
80 80 VM_REG_GUEST_RSP,
81 81 VM_REG_GUEST_RIP,
82 82 VM_REG_GUEST_RFLAGS,
83 83 VM_REG_GUEST_ES,
84 84 VM_REG_GUEST_CS,
85 85 VM_REG_GUEST_SS,
86 86 VM_REG_GUEST_DS,
87 87 VM_REG_GUEST_FS,
88 88 VM_REG_GUEST_GS,
89 89 VM_REG_GUEST_LDTR,
90 90 VM_REG_GUEST_TR,
91 91 VM_REG_GUEST_IDTR,
92 92 VM_REG_GUEST_GDTR,
93 93 VM_REG_GUEST_EFER,
94 94 VM_REG_GUEST_CR2,
95 95 VM_REG_GUEST_PDPTE0,
96 96 VM_REG_GUEST_PDPTE1,
97 97 VM_REG_GUEST_PDPTE2,
98 98 VM_REG_GUEST_PDPTE3,
99 99 VM_REG_GUEST_INTR_SHADOW,
100 100 VM_REG_GUEST_DR0,
101 101 VM_REG_GUEST_DR1,
102 102 VM_REG_GUEST_DR2,
103 103 VM_REG_GUEST_DR3,
104 104 VM_REG_GUEST_DR6,
105 105 VM_REG_GUEST_ENTRY_INST_LENGTH,
106 106 VM_REG_LAST
107 107 };
108 108
109 109 enum x2apic_state {
110 110 X2APIC_DISABLED,
111 111 X2APIC_ENABLED,
112 112 X2APIC_STATE_LAST
113 113 };
114 114
115 115 #define VM_INTINFO_VECTOR(info) ((info) & 0xff)
116 116 #define VM_INTINFO_DEL_ERRCODE 0x800
117 117 #define VM_INTINFO_RSVD 0x7ffff000
118 118 #define VM_INTINFO_VALID 0x80000000
119 119 #define VM_INTINFO_TYPE 0x700
120 120 #define VM_INTINFO_HWINTR (0 << 8)
121 121 #define VM_INTINFO_NMI (2 << 8)
122 122 #define VM_INTINFO_HWEXCEPTION (3 << 8)
123 123 #define VM_INTINFO_SWINTR (4 << 8)
124 124
125 125 /*
126 126 * illumos doesn't have a limitation based on SPECNAMELEN like FreeBSD does.
127 127 * Instead of picking an arbitrary value we will just rely on the same
128 128 * calculation that's made below. If this calculation ever changes we need to
129 129 * update the the VM_MAX_NAMELEN mapping in the bhyve brand's boot.c file.
130 130 */
131 131
132 132 #define VM_MAX_PREFIXLEN 10
133 133 #define VM_MAX_SUFFIXLEN 15
134 134 #define VM_MIN_NAMELEN 6
135 135 #define VM_MAX_NAMELEN \
136 136 (SPECNAMELEN - VM_MAX_PREFIXLEN - VM_MAX_SUFFIXLEN - 1)
137 137
138 138 #ifdef _KERNEL
139 139 CTASSERT(VM_MAX_NAMELEN >= VM_MIN_NAMELEN);
140 140 #endif
141 141
142 142 #define VM_MAXCPU 32 /* maximum virtual cpus */
143 143
144 144 /*
145 145 * Identifiers for optional vmm capabilities
146 146 */
147 147 enum vm_cap_type {
148 148 VM_CAP_HALT_EXIT,
149 149 VM_CAP_MTRAP_EXIT,
150 150 VM_CAP_PAUSE_EXIT,
151 151 VM_CAP_ENABLE_INVPCID,
152 152 VM_CAP_BPT_EXIT,
153 153 VM_CAP_MAX
154 154 };
155 155
156 156 enum vmx_caps {
157 157 VMX_CAP_NONE = 0,
158 158 VMX_CAP_TPR_SHADOW = (1UL << 0),
159 159 VMX_CAP_APICV = (1UL << 1),
160 160 VMX_CAP_APICV_X2APIC = (1UL << 2),
161 161 VMX_CAP_APICV_PIR = (1UL << 3),
162 162 };
163 163
164 164 enum vm_intr_trigger {
165 165 EDGE_TRIGGER,
166 166 LEVEL_TRIGGER
167 167 };
168 168
169 169 /*
170 170 * The 'access' field has the format specified in Table 21-2 of the Intel
171 171 * Architecture Manual vol 3b.
172 172 *
173 173 * XXX The contents of the 'access' field are architecturally defined except
174 174 * bit 16 - Segment Unusable.
175 175 */
176 176 struct seg_desc {
177 177 uint64_t base;
178 178 uint32_t limit;
179 179 uint32_t access;
180 180 };
181 181 #define SEG_DESC_TYPE(access) ((access) & 0x001f)
182 182 #define SEG_DESC_DPL(access) (((access) >> 5) & 0x3)
183 183 #define SEG_DESC_PRESENT(access) (((access) & 0x0080) ? 1 : 0)
184 184 #define SEG_DESC_DEF32(access) (((access) & 0x4000) ? 1 : 0)
185 185 #define SEG_DESC_GRANULARITY(access) (((access) & 0x8000) ? 1 : 0)
186 186 #define SEG_DESC_UNUSABLE(access) (((access) & 0x10000) ? 1 : 0)
187 187
188 188 enum vm_cpu_mode {
189 189 CPU_MODE_REAL,
190 190 CPU_MODE_PROTECTED,
191 191 CPU_MODE_COMPATIBILITY, /* IA-32E mode (CS.L = 0) */
192 192 CPU_MODE_64BIT, /* IA-32E mode (CS.L = 1) */
193 193 };
194 194
195 195 enum vm_paging_mode {
196 196 PAGING_MODE_FLAT,
197 197 PAGING_MODE_32,
198 198 PAGING_MODE_PAE,
199 199 PAGING_MODE_64,
200 200 };
201 201
202 202 struct vm_guest_paging {
203 203 uint64_t cr3;
204 204 int cpl;
205 205 enum vm_cpu_mode cpu_mode;
206 206 enum vm_paging_mode paging_mode;
207 207 };
208 208
209 209 enum vm_exitcode {
|
↓ open down ↓ |
209 lines elided |
↑ open up ↑ |
210 210 VM_EXITCODE_INOUT,
211 211 VM_EXITCODE_VMX,
212 212 VM_EXITCODE_BOGUS,
213 213 VM_EXITCODE_RDMSR,
214 214 VM_EXITCODE_WRMSR,
215 215 VM_EXITCODE_HLT,
216 216 VM_EXITCODE_MTRAP,
217 217 VM_EXITCODE_PAUSE,
218 218 VM_EXITCODE_PAGING,
219 219 VM_EXITCODE_INST_EMUL,
220 - VM_EXITCODE_SPINUP_AP,
220 + VM_EXITCODE_RUN_STATE,
221 221 VM_EXITCODE_MMIO_EMUL,
222 - VM_EXITCODE_RUNBLOCK,
222 + VM_EXITCODE_DEPRECATED, /* formerly RUNBLOCK */
223 223 VM_EXITCODE_IOAPIC_EOI,
224 224 VM_EXITCODE_SUSPENDED,
225 225 VM_EXITCODE_MMIO,
226 226 VM_EXITCODE_TASK_SWITCH,
227 227 VM_EXITCODE_MONITOR,
228 228 VM_EXITCODE_MWAIT,
229 229 VM_EXITCODE_SVM,
230 230 VM_EXITCODE_REQIDLE,
231 231 VM_EXITCODE_DEBUG,
232 232 VM_EXITCODE_VMINSN,
233 233 VM_EXITCODE_BPT,
234 234 #ifndef __FreeBSD__
235 235 VM_EXITCODE_HT,
236 236 #endif
237 237 VM_EXITCODE_MAX
238 238 };
239 239
240 240 enum inout_flags {
241 241 INOUT_IN = (1U << 0), /* direction: 'in' when set, else 'out' */
242 242
243 243 /*
244 244 * The following flags are used only for in-kernel emulation logic and
245 245 * are not exposed to userspace.
246 246 */
247 247 INOUT_STR = (1U << 1), /* ins/outs operation */
248 248 INOUT_REP = (1U << 2), /* 'rep' prefix present on instruction */
249 249 };
250 250
251 251 struct vm_inout {
252 252 uint32_t eax;
253 253 uint16_t port;
254 254 uint8_t bytes; /* 1 or 2 or 4 */
255 255 uint8_t flags; /* see: inout_flags */
256 256
257 257 /*
258 258 * The address size and segment are relevant to INS/OUTS operations.
259 259 * Userspace is not concerned with them since the in-kernel emulation
260 260 * handles those specific aspects.
261 261 */
262 262 uint8_t addrsize;
263 263 uint8_t segment;
264 264 };
265 265
266 266 struct vm_mmio {
267 267 uint8_t bytes; /* 1/2/4/8 bytes */
268 268 uint8_t read; /* read: 1, write: 0 */
269 269 uint16_t _pad[3];
270 270 uint64_t gpa;
271 271 uint64_t data;
272 272 };
273 273
274 274 enum task_switch_reason {
275 275 TSR_CALL,
276 276 TSR_IRET,
277 277 TSR_JMP,
278 278 TSR_IDT_GATE, /* task gate in IDT */
279 279 };
|
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
280 280
281 281 struct vm_task_switch {
282 282 uint16_t tsssel; /* new TSS selector */
283 283 int ext; /* task switch due to external event */
284 284 uint32_t errcode;
285 285 int errcode_valid; /* push 'errcode' on the new stack */
286 286 enum task_switch_reason reason;
287 287 struct vm_guest_paging paging;
288 288 };
289 289
290 +enum vcpu_run_state {
291 + VRS_HALT = 0,
292 + VRS_INIT = (1 << 0),
293 + VRS_RUN = (1 << 1),
294 +
295 + VRS_PEND_INIT = (1 << 14),
296 + VRS_PEND_SIPI = (1 << 15),
297 +};
298 +#define VRS_MASK_VALID(v) \
299 + ((v) & (VRS_INIT | VRS_RUN | VRS_PEND_SIPI | VRS_PEND_SIPI))
300 +#define VRS_IS_VALID(v) ((v) == VRS_MASK_VALID(v))
301 +
290 302 struct vm_exit {
291 303 enum vm_exitcode exitcode;
292 304 int inst_length; /* 0 means unknown */
293 305 uint64_t rip;
294 306 union {
295 307 struct vm_inout inout;
296 308 struct vm_mmio mmio;
297 309 struct {
298 310 uint64_t gpa;
299 311 int fault_type;
300 312 } paging;
301 313 /*
302 314 * Kernel-internal MMIO decoding and emulation.
303 315 * Userspace should not expect to see this, but rather a
304 316 * VM_EXITCODE_MMIO with the above 'mmio' context.
305 317 */
306 318 struct {
307 319 uint64_t gpa;
308 320 uint64_t gla;
309 321 uint64_t cs_base;
310 322 int cs_d; /* CS.D */
311 323 } mmio_emul;
312 324 struct {
313 325 uint8_t inst[15];
314 326 uint8_t num_valid;
315 327 } inst_emul;
316 328 /*
317 329 * VMX specific payload. Used when there is no "better"
318 330 * exitcode to represent the VM-exit.
319 331 */
320 332 struct {
321 333 int status; /* vmx inst status */
322 334 /*
323 335 * 'exit_reason' and 'exit_qualification' are valid
324 336 * only if 'status' is zero.
325 337 */
326 338 uint32_t exit_reason;
327 339 uint64_t exit_qualification;
328 340 /*
329 341 * 'inst_error' and 'inst_type' are valid
330 342 * only if 'status' is non-zero.
331 343 */
332 344 int inst_type;
333 345 int inst_error;
334 346 } vmx;
335 347 /*
336 348 * SVM specific payload.
337 349 */
338 350 struct {
339 351 uint64_t exitcode;
340 352 uint64_t exitinfo1;
|
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
341 353 uint64_t exitinfo2;
342 354 } svm;
343 355 struct {
344 356 int inst_length;
345 357 } bpt;
346 358 struct {
347 359 uint32_t code; /* ecx value */
348 360 uint64_t wval;
349 361 } msr;
350 362 struct {
351 - int vcpu;
352 - uint64_t rip;
353 - } spinup_ap;
354 - struct {
355 363 uint64_t rflags;
356 364 } hlt;
357 365 struct {
358 366 int vector;
359 367 } ioapic_eoi;
360 368 struct {
361 369 enum vm_suspend_how how;
362 370 } suspended;
363 371 struct vm_task_switch task_switch;
364 372 } u;
365 373 };
366 374
367 375 enum vm_entry_cmds {
368 376 VEC_DEFAULT = 0,
369 377 VEC_DISCARD_INSTR, /* discard inst emul state */
370 - VEC_COMPLETE_MMIO, /* entry includes result for mmio emul */
371 - VEC_COMPLETE_INOUT, /* entry includes result for inout emul */
378 + VEC_FULFILL_MMIO, /* entry includes result for mmio emul */
379 + VEC_FULFILL_INOUT, /* entry includes result for inout emul */
372 380 };
373 381
374 382 struct vm_entry {
375 383 int cpuid;
376 384 uint_t cmd; /* see: vm_entry_cmds */
377 385 void *exit_data;
378 386 union {
379 387 struct vm_inout inout;
380 388 struct vm_mmio mmio;
381 389 } u;
382 390 };
383 391
384 392 int vm_restart_instruction(void *vm, int vcpuid);
385 393
386 394 #endif /* _VMM_H_ */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX