]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bhyve/bhyverun.c
MFC r339826 (by yuripv):
[FreeBSD/FreeBSD.git] / usr.sbin / bhyve / bhyverun.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2011 NetApp, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/types.h>
35 #ifndef WITHOUT_CAPSICUM
36 #include <sys/capsicum.h>
37 #endif
38 #include <sys/mman.h>
39 #include <sys/time.h>
40
41 #include <amd64/vmm/intel/vmcs.h>
42
43 #include <machine/atomic.h>
44 #include <machine/segments.h>
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <err.h>
50 #include <errno.h>
51 #include <libgen.h>
52 #include <unistd.h>
53 #include <assert.h>
54 #include <errno.h>
55 #include <pthread.h>
56 #include <pthread_np.h>
57 #include <sysexits.h>
58 #include <stdbool.h>
59 #ifndef WITHOUT_CAPSICUM
60 #include <nl_types.h>
61 #include <termios.h>
62 #endif
63
64 #include <machine/vmm.h>
65 #ifndef WITHOUT_CAPSICUM
66 #include <machine/vmm_dev.h>
67 #endif
68 #include <vmmapi.h>
69
70 #include "bhyverun.h"
71 #include "acpi.h"
72 #include "atkbdc.h"
73 #include "inout.h"
74 #include "dbgport.h"
75 #include "fwctl.h"
76 #include "ioapic.h"
77 #include "mem.h"
78 #include "mevent.h"
79 #include "mptbl.h"
80 #include "pci_emul.h"
81 #include "pci_irq.h"
82 #include "pci_lpc.h"
83 #include "smbiostbl.h"
84 #include "xmsr.h"
85 #include "spinup_ap.h"
86 #include "rtc.h"
87
88 #define GUEST_NIO_PORT          0x488   /* guest upcalls via i/o port */
89
90 #define MB              (1024UL * 1024)
91 #define GB              (1024UL * MB)
92
93 static const char * const vmx_exit_reason_desc[] = {
94         [EXIT_REASON_EXCEPTION] = "Exception or non-maskable interrupt (NMI)",
95         [EXIT_REASON_EXT_INTR] = "External interrupt",
96         [EXIT_REASON_TRIPLE_FAULT] = "Triple fault",
97         [EXIT_REASON_INIT] = "INIT signal",
98         [EXIT_REASON_SIPI] = "Start-up IPI (SIPI)",
99         [EXIT_REASON_IO_SMI] = "I/O system-management interrupt (SMI)",
100         [EXIT_REASON_SMI] = "Other SMI",
101         [EXIT_REASON_INTR_WINDOW] = "Interrupt window",
102         [EXIT_REASON_NMI_WINDOW] = "NMI window",
103         [EXIT_REASON_TASK_SWITCH] = "Task switch",
104         [EXIT_REASON_CPUID] = "CPUID",
105         [EXIT_REASON_GETSEC] = "GETSEC",
106         [EXIT_REASON_HLT] = "HLT",
107         [EXIT_REASON_INVD] = "INVD",
108         [EXIT_REASON_INVLPG] = "INVLPG",
109         [EXIT_REASON_RDPMC] = "RDPMC",
110         [EXIT_REASON_RDTSC] = "RDTSC",
111         [EXIT_REASON_RSM] = "RSM",
112         [EXIT_REASON_VMCALL] = "VMCALL",
113         [EXIT_REASON_VMCLEAR] = "VMCLEAR",
114         [EXIT_REASON_VMLAUNCH] = "VMLAUNCH",
115         [EXIT_REASON_VMPTRLD] = "VMPTRLD",
116         [EXIT_REASON_VMPTRST] = "VMPTRST",
117         [EXIT_REASON_VMREAD] = "VMREAD",
118         [EXIT_REASON_VMRESUME] = "VMRESUME",
119         [EXIT_REASON_VMWRITE] = "VMWRITE",
120         [EXIT_REASON_VMXOFF] = "VMXOFF",
121         [EXIT_REASON_VMXON] = "VMXON",
122         [EXIT_REASON_CR_ACCESS] = "Control-register accesses",
123         [EXIT_REASON_DR_ACCESS] = "MOV DR",
124         [EXIT_REASON_INOUT] = "I/O instruction",
125         [EXIT_REASON_RDMSR] = "RDMSR",
126         [EXIT_REASON_WRMSR] = "WRMSR",
127         [EXIT_REASON_INVAL_VMCS] =
128             "VM-entry failure due to invalid guest state",
129         [EXIT_REASON_INVAL_MSR] = "VM-entry failure due to MSR loading",
130         [EXIT_REASON_MWAIT] = "MWAIT",
131         [EXIT_REASON_MTF] = "Monitor trap flag",
132         [EXIT_REASON_MONITOR] = "MONITOR",
133         [EXIT_REASON_PAUSE] = "PAUSE",
134         [EXIT_REASON_MCE_DURING_ENTRY] =
135             "VM-entry failure due to machine-check event",
136         [EXIT_REASON_TPR] = "TPR below threshold",
137         [EXIT_REASON_APIC_ACCESS] = "APIC access",
138         [EXIT_REASON_VIRTUALIZED_EOI] = "Virtualized EOI",
139         [EXIT_REASON_GDTR_IDTR] = "Access to GDTR or IDTR",
140         [EXIT_REASON_LDTR_TR] = "Access to LDTR or TR",
141         [EXIT_REASON_EPT_FAULT] = "EPT violation",
142         [EXIT_REASON_EPT_MISCONFIG] = "EPT misconfiguration",
143         [EXIT_REASON_INVEPT] = "INVEPT",
144         [EXIT_REASON_RDTSCP] = "RDTSCP",
145         [EXIT_REASON_VMX_PREEMPT] = "VMX-preemption timer expired",
146         [EXIT_REASON_INVVPID] = "INVVPID",
147         [EXIT_REASON_WBINVD] = "WBINVD",
148         [EXIT_REASON_XSETBV] = "XSETBV",
149         [EXIT_REASON_APIC_WRITE] = "APIC write",
150         [EXIT_REASON_RDRAND] = "RDRAND",
151         [EXIT_REASON_INVPCID] = "INVPCID",
152         [EXIT_REASON_VMFUNC] = "VMFUNC",
153         [EXIT_REASON_ENCLS] = "ENCLS",
154         [EXIT_REASON_RDSEED] = "RDSEED",
155         [EXIT_REASON_PM_LOG_FULL] = "Page-modification log full",
156         [EXIT_REASON_XSAVES] = "XSAVES",
157         [EXIT_REASON_XRSTORS] = "XRSTORS"
158 };
159
160 typedef int (*vmexit_handler_t)(struct vmctx *, struct vm_exit *, int *vcpu);
161 extern int vmexit_task_switch(struct vmctx *, struct vm_exit *, int *vcpu);
162
163 char *vmname;
164
165 int guest_ncpus;
166 char *guest_uuid_str;
167
168 static int guest_vmexit_on_hlt, guest_vmexit_on_pause;
169 static int virtio_msix = 1;
170 static int x2apic_mode = 0;     /* default is xAPIC */
171
172 static int strictio;
173 static int strictmsr = 1;
174
175 static int acpi;
176
177 static char *progname;
178 static const int BSP = 0;
179
180 static cpuset_t cpumask;
181
182 static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip);
183
184 static struct vm_exit vmexit[VM_MAXCPU];
185
186 struct bhyvestats {
187         uint64_t        vmexit_bogus;
188         uint64_t        vmexit_reqidle;
189         uint64_t        vmexit_hlt;
190         uint64_t        vmexit_pause;
191         uint64_t        vmexit_mtrap;
192         uint64_t        vmexit_inst_emul;
193         uint64_t        cpu_switch_rotate;
194         uint64_t        cpu_switch_direct;
195 } stats;
196
197 struct mt_vmm_info {
198         pthread_t       mt_thr;
199         struct vmctx    *mt_ctx;
200         int             mt_vcpu;        
201 } mt_vmm_info[VM_MAXCPU];
202
203 static cpuset_t *vcpumap[VM_MAXCPU] = { NULL };
204
205 static void
206 usage(int code)
207 {
208
209         fprintf(stderr,
210                 "Usage: %s [-abehuwxACHPSWY] [-c vcpus] [-g <gdb port>] [-l <lpc>]\n"
211                 "       %*s [-m mem] [-p vcpu:hostcpu] [-s <pci>] [-U uuid] <vm>\n"
212                 "       -a: local apic is in xAPIC mode (deprecated)\n"
213                 "       -A: create ACPI tables\n"
214                 "       -c: # cpus (default 1)\n"
215                 "       -C: include guest memory in core file\n"
216                 "       -e: exit on unhandled I/O access\n"
217                 "       -g: gdb port\n"
218                 "       -h: help\n"
219                 "       -H: vmexit from the guest on hlt\n"
220                 "       -l: LPC device configuration\n"
221                 "       -m: memory size in MB\n"
222                 "       -p: pin 'vcpu' to 'hostcpu'\n"
223                 "       -P: vmexit from the guest on pause\n"
224                 "       -s: <slot,driver,configinfo> PCI slot config\n"
225                 "       -S: guest memory cannot be swapped\n"
226                 "       -u: RTC keeps UTC time\n"
227                 "       -U: uuid\n"
228                 "       -w: ignore unimplemented MSRs\n"
229                 "       -W: force virtio to use single-vector MSI\n"
230                 "       -x: local apic is in x2APIC mode\n"
231                 "       -Y: disable MPtable generation\n",
232                 progname, (int)strlen(progname), "");
233
234         exit(code);
235 }
236
237 #ifndef WITHOUT_CAPSICUM
238 /*
239  * 11-stable capsicum helpers
240  */
241 static void
242 bhyve_caph_cache_catpages(void)
243 {
244
245         (void)catopen("libc", NL_CAT_LOCALE);
246 }
247
248 static int
249 bhyve_caph_limit_stdoe(void)
250 {
251         cap_rights_t rights;
252         unsigned long cmds[] = { TIOCGETA, TIOCGWINSZ };
253         int i, fds[] = { STDOUT_FILENO, STDERR_FILENO };
254
255         cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL);
256         cap_rights_set(&rights, CAP_WRITE);
257
258         for (i = 0; i < nitems(fds); i++) {
259                 if (cap_rights_limit(fds[i], &rights) < 0 && errno != ENOSYS)
260                         return (-1);
261
262                 if (cap_ioctls_limit(fds[i], cmds, nitems(cmds)) < 0 && errno != ENOSYS)
263                         return (-1);
264
265                 if (cap_fcntls_limit(fds[i], CAP_FCNTL_GETFL) < 0 && errno != ENOSYS)
266                         return (-1);
267         }
268
269         return (0);
270 }
271
272 #endif
273
274 static int
275 pincpu_parse(const char *opt)
276 {
277         int vcpu, pcpu;
278
279         if (sscanf(opt, "%d:%d", &vcpu, &pcpu) != 2) {
280                 fprintf(stderr, "invalid format: %s\n", opt);
281                 return (-1);
282         }
283
284         if (vcpu < 0 || vcpu >= VM_MAXCPU) {
285                 fprintf(stderr, "vcpu '%d' outside valid range from 0 to %d\n",
286                     vcpu, VM_MAXCPU - 1);
287                 return (-1);
288         }
289
290         if (pcpu < 0 || pcpu >= CPU_SETSIZE) {
291                 fprintf(stderr, "hostcpu '%d' outside valid range from "
292                     "0 to %d\n", pcpu, CPU_SETSIZE - 1);
293                 return (-1);
294         }
295
296         if (vcpumap[vcpu] == NULL) {
297                 if ((vcpumap[vcpu] = malloc(sizeof(cpuset_t))) == NULL) {
298                         perror("malloc");
299                         return (-1);
300                 }
301                 CPU_ZERO(vcpumap[vcpu]);
302         }
303         CPU_SET(pcpu, vcpumap[vcpu]);
304         return (0);
305 }
306
307 void
308 vm_inject_fault(void *arg, int vcpu, int vector, int errcode_valid,
309     int errcode)
310 {
311         struct vmctx *ctx;
312         int error, restart_instruction;
313
314         ctx = arg;
315         restart_instruction = 1;
316
317         error = vm_inject_exception(ctx, vcpu, vector, errcode_valid, errcode,
318             restart_instruction);
319         assert(error == 0);
320 }
321
322 void *
323 paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len)
324 {
325
326         return (vm_map_gpa(ctx, gaddr, len));
327 }
328
329 int
330 fbsdrun_vmexit_on_pause(void)
331 {
332
333         return (guest_vmexit_on_pause);
334 }
335
336 int
337 fbsdrun_vmexit_on_hlt(void)
338 {
339
340         return (guest_vmexit_on_hlt);
341 }
342
343 int
344 fbsdrun_virtio_msix(void)
345 {
346
347         return (virtio_msix);
348 }
349
350 static void *
351 fbsdrun_start_thread(void *param)
352 {
353         char tname[MAXCOMLEN + 1];
354         struct mt_vmm_info *mtp;
355         int vcpu;
356
357         mtp = param;
358         vcpu = mtp->mt_vcpu;
359
360         snprintf(tname, sizeof(tname), "vcpu %d", vcpu);
361         pthread_set_name_np(mtp->mt_thr, tname);
362
363         vm_loop(mtp->mt_ctx, vcpu, vmexit[vcpu].rip);
364
365         /* not reached */
366         exit(1);
367         return (NULL);
368 }
369
370 void
371 fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip)
372 {
373         int error;
374
375         assert(fromcpu == BSP);
376
377         /*
378          * The 'newcpu' must be activated in the context of 'fromcpu'. If
379          * vm_activate_cpu() is delayed until newcpu's pthread starts running
380          * then vmm.ko is out-of-sync with bhyve and this can create a race
381          * with vm_suspend().
382          */
383         error = vm_activate_cpu(ctx, newcpu);
384         if (error != 0)
385                 err(EX_OSERR, "could not activate CPU %d", newcpu);
386
387         CPU_SET_ATOMIC(newcpu, &cpumask);
388
389         /*
390          * Set up the vmexit struct to allow execution to start
391          * at the given RIP
392          */
393         vmexit[newcpu].rip = rip;
394         vmexit[newcpu].inst_length = 0;
395
396         mt_vmm_info[newcpu].mt_ctx = ctx;
397         mt_vmm_info[newcpu].mt_vcpu = newcpu;
398
399         error = pthread_create(&mt_vmm_info[newcpu].mt_thr, NULL,
400             fbsdrun_start_thread, &mt_vmm_info[newcpu]);
401         assert(error == 0);
402 }
403
404 static int
405 fbsdrun_deletecpu(struct vmctx *ctx, int vcpu)
406 {
407
408         if (!CPU_ISSET(vcpu, &cpumask)) {
409                 fprintf(stderr, "Attempting to delete unknown cpu %d\n", vcpu);
410                 exit(4);
411         }
412
413         CPU_CLR_ATOMIC(vcpu, &cpumask);
414         return (CPU_EMPTY(&cpumask));
415 }
416
417 static int
418 vmexit_handle_notify(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu,
419                      uint32_t eax)
420 {
421 #if BHYVE_DEBUG
422         /*
423          * put guest-driven debug here
424          */
425 #endif
426         return (VMEXIT_CONTINUE);
427 }
428
429 static int
430 vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
431 {
432         int error;
433         int bytes, port, in, out;
434         int vcpu;
435
436         vcpu = *pvcpu;
437
438         port = vme->u.inout.port;
439         bytes = vme->u.inout.bytes;
440         in = vme->u.inout.in;
441         out = !in;
442
443         /* Extra-special case of host notifications */
444         if (out && port == GUEST_NIO_PORT) {
445                 error = vmexit_handle_notify(ctx, vme, pvcpu, vme->u.inout.eax);
446                 return (error);
447         }
448
449         error = emulate_inout(ctx, vcpu, vme, strictio);
450         if (error) {
451                 fprintf(stderr, "Unhandled %s%c 0x%04x at 0x%lx\n",
452                     in ? "in" : "out",
453                     bytes == 1 ? 'b' : (bytes == 2 ? 'w' : 'l'),
454                     port, vmexit->rip);
455                 return (VMEXIT_ABORT);
456         } else {
457                 return (VMEXIT_CONTINUE);
458         }
459 }
460
461 static int
462 vmexit_rdmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
463 {
464         uint64_t val;
465         uint32_t eax, edx;
466         int error;
467
468         val = 0;
469         error = emulate_rdmsr(ctx, *pvcpu, vme->u.msr.code, &val);
470         if (error != 0) {
471                 fprintf(stderr, "rdmsr to register %#x on vcpu %d\n",
472                     vme->u.msr.code, *pvcpu);
473                 if (strictmsr) {
474                         vm_inject_gp(ctx, *pvcpu);
475                         return (VMEXIT_CONTINUE);
476                 }
477         }
478
479         eax = val;
480         error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RAX, eax);
481         assert(error == 0);
482
483         edx = val >> 32;
484         error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RDX, edx);
485         assert(error == 0);
486
487         return (VMEXIT_CONTINUE);
488 }
489
490 static int
491 vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
492 {
493         int error;
494
495         error = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code, vme->u.msr.wval);
496         if (error != 0) {
497                 fprintf(stderr, "wrmsr to register %#x(%#lx) on vcpu %d\n",
498                     vme->u.msr.code, vme->u.msr.wval, *pvcpu);
499                 if (strictmsr) {
500                         vm_inject_gp(ctx, *pvcpu);
501                         return (VMEXIT_CONTINUE);
502                 }
503         }
504         return (VMEXIT_CONTINUE);
505 }
506
507 static int
508 vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
509 {
510
511         (void)spinup_ap(ctx, *pvcpu,
512                     vme->u.spinup_ap.vcpu, vme->u.spinup_ap.rip);
513
514         return (VMEXIT_CONTINUE);
515 }
516
517 #define DEBUG_EPT_MISCONFIG
518 #ifdef DEBUG_EPT_MISCONFIG
519 #define VMCS_GUEST_PHYSICAL_ADDRESS     0x00002400
520
521 static uint64_t ept_misconfig_gpa, ept_misconfig_pte[4];
522 static int ept_misconfig_ptenum;
523 #endif
524
525 static const char *
526 vmexit_vmx_desc(uint32_t exit_reason)
527 {
528
529         if (exit_reason >= nitems(vmx_exit_reason_desc) ||
530             vmx_exit_reason_desc[exit_reason] == NULL)
531                 return ("Unknown");
532         return (vmx_exit_reason_desc[exit_reason]);
533 }
534
535 static int
536 vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
537 {
538
539         fprintf(stderr, "vm exit[%d]\n", *pvcpu);
540         fprintf(stderr, "\treason\t\tVMX\n");
541         fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip);
542         fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length);
543         fprintf(stderr, "\tstatus\t\t%d\n", vmexit->u.vmx.status);
544         fprintf(stderr, "\texit_reason\t%u (%s)\n", vmexit->u.vmx.exit_reason,
545             vmexit_vmx_desc(vmexit->u.vmx.exit_reason));
546         fprintf(stderr, "\tqualification\t0x%016lx\n",
547             vmexit->u.vmx.exit_qualification);
548         fprintf(stderr, "\tinst_type\t\t%d\n", vmexit->u.vmx.inst_type);
549         fprintf(stderr, "\tinst_error\t\t%d\n", vmexit->u.vmx.inst_error);
550 #ifdef DEBUG_EPT_MISCONFIG
551         if (vmexit->u.vmx.exit_reason == EXIT_REASON_EPT_MISCONFIG) {
552                 vm_get_register(ctx, *pvcpu,
553                     VMCS_IDENT(VMCS_GUEST_PHYSICAL_ADDRESS),
554                     &ept_misconfig_gpa);
555                 vm_get_gpa_pmap(ctx, ept_misconfig_gpa, ept_misconfig_pte,
556                     &ept_misconfig_ptenum);
557                 fprintf(stderr, "\tEPT misconfiguration:\n");
558                 fprintf(stderr, "\t\tGPA: %#lx\n", ept_misconfig_gpa);
559                 fprintf(stderr, "\t\tPTE(%d): %#lx %#lx %#lx %#lx\n",
560                     ept_misconfig_ptenum, ept_misconfig_pte[0],
561                     ept_misconfig_pte[1], ept_misconfig_pte[2],
562                     ept_misconfig_pte[3]);
563         }
564 #endif  /* DEBUG_EPT_MISCONFIG */
565         return (VMEXIT_ABORT);
566 }
567
568 static int
569 vmexit_svm(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
570 {
571
572         fprintf(stderr, "vm exit[%d]\n", *pvcpu);
573         fprintf(stderr, "\treason\t\tSVM\n");
574         fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip);
575         fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length);
576         fprintf(stderr, "\texitcode\t%#lx\n", vmexit->u.svm.exitcode);
577         fprintf(stderr, "\texitinfo1\t%#lx\n", vmexit->u.svm.exitinfo1);
578         fprintf(stderr, "\texitinfo2\t%#lx\n", vmexit->u.svm.exitinfo2);
579         return (VMEXIT_ABORT);
580 }
581
582 static int
583 vmexit_bogus(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
584 {
585
586         assert(vmexit->inst_length == 0);
587
588         stats.vmexit_bogus++;
589
590         return (VMEXIT_CONTINUE);
591 }
592
593 static int
594 vmexit_reqidle(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
595 {
596
597         assert(vmexit->inst_length == 0);
598
599         stats.vmexit_reqidle++;
600
601         return (VMEXIT_CONTINUE);
602 }
603
604 static int
605 vmexit_hlt(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
606 {
607
608         stats.vmexit_hlt++;
609
610         /*
611          * Just continue execution with the next instruction. We use
612          * the HLT VM exit as a way to be friendly with the host
613          * scheduler.
614          */
615         return (VMEXIT_CONTINUE);
616 }
617
618 static int
619 vmexit_pause(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
620 {
621
622         stats.vmexit_pause++;
623
624         return (VMEXIT_CONTINUE);
625 }
626
627 static int
628 vmexit_mtrap(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
629 {
630
631         assert(vmexit->inst_length == 0);
632
633         stats.vmexit_mtrap++;
634
635         return (VMEXIT_CONTINUE);
636 }
637
638 static int
639 vmexit_inst_emul(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
640 {
641         int err, i;
642         struct vie *vie;
643
644         stats.vmexit_inst_emul++;
645
646         vie = &vmexit->u.inst_emul.vie;
647         err = emulate_mem(ctx, *pvcpu, vmexit->u.inst_emul.gpa,
648             vie, &vmexit->u.inst_emul.paging);
649
650         if (err) {
651                 if (err == ESRCH) {
652                         fprintf(stderr, "Unhandled memory access to 0x%lx\n",
653                             vmexit->u.inst_emul.gpa);
654                 }
655
656                 fprintf(stderr, "Failed to emulate instruction [");
657                 for (i = 0; i < vie->num_valid; i++) {
658                         fprintf(stderr, "0x%02x%s", vie->inst[i],
659                             i != (vie->num_valid - 1) ? " " : "");
660                 }
661                 fprintf(stderr, "] at 0x%lx\n", vmexit->rip);
662                 return (VMEXIT_ABORT);
663         }
664
665         return (VMEXIT_CONTINUE);
666 }
667
668 static pthread_mutex_t resetcpu_mtx = PTHREAD_MUTEX_INITIALIZER;
669 static pthread_cond_t resetcpu_cond = PTHREAD_COND_INITIALIZER;
670
671 static int
672 vmexit_suspend(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
673 {
674         enum vm_suspend_how how;
675
676         how = vmexit->u.suspended.how;
677
678         fbsdrun_deletecpu(ctx, *pvcpu);
679
680         if (*pvcpu != BSP) {
681                 pthread_mutex_lock(&resetcpu_mtx);
682                 pthread_cond_signal(&resetcpu_cond);
683                 pthread_mutex_unlock(&resetcpu_mtx);
684                 pthread_exit(NULL);
685         }
686
687         pthread_mutex_lock(&resetcpu_mtx);
688         while (!CPU_EMPTY(&cpumask)) {
689                 pthread_cond_wait(&resetcpu_cond, &resetcpu_mtx);
690         }
691         pthread_mutex_unlock(&resetcpu_mtx);
692
693         switch (how) {
694         case VM_SUSPEND_RESET:
695                 exit(0);
696         case VM_SUSPEND_POWEROFF:
697                 exit(1);
698         case VM_SUSPEND_HALT:
699                 exit(2);
700         case VM_SUSPEND_TRIPLEFAULT:
701                 exit(3);
702         default:
703                 fprintf(stderr, "vmexit_suspend: invalid reason %d\n", how);
704                 exit(100);
705         }
706         return (0);     /* NOTREACHED */
707 }
708
709 static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
710         [VM_EXITCODE_INOUT]  = vmexit_inout,
711         [VM_EXITCODE_INOUT_STR]  = vmexit_inout,
712         [VM_EXITCODE_VMX]    = vmexit_vmx,
713         [VM_EXITCODE_SVM]    = vmexit_svm,
714         [VM_EXITCODE_BOGUS]  = vmexit_bogus,
715         [VM_EXITCODE_REQIDLE] = vmexit_reqidle,
716         [VM_EXITCODE_RDMSR]  = vmexit_rdmsr,
717         [VM_EXITCODE_WRMSR]  = vmexit_wrmsr,
718         [VM_EXITCODE_MTRAP]  = vmexit_mtrap,
719         [VM_EXITCODE_INST_EMUL] = vmexit_inst_emul,
720         [VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap,
721         [VM_EXITCODE_SUSPENDED] = vmexit_suspend,
722         [VM_EXITCODE_TASK_SWITCH] = vmexit_task_switch,
723 };
724
725 static void
726 vm_loop(struct vmctx *ctx, int vcpu, uint64_t startrip)
727 {
728         int error, rc;
729         enum vm_exitcode exitcode;
730         cpuset_t active_cpus;
731
732         if (vcpumap[vcpu] != NULL) {
733                 error = pthread_setaffinity_np(pthread_self(),
734                     sizeof(cpuset_t), vcpumap[vcpu]);
735                 assert(error == 0);
736         }
737
738         error = vm_active_cpus(ctx, &active_cpus);
739         assert(CPU_ISSET(vcpu, &active_cpus));
740
741         error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RIP, startrip);
742         assert(error == 0);
743
744         while (1) {
745                 error = vm_run(ctx, vcpu, &vmexit[vcpu]);
746                 if (error != 0)
747                         break;
748
749                 exitcode = vmexit[vcpu].exitcode;
750                 if (exitcode >= VM_EXITCODE_MAX || handler[exitcode] == NULL) {
751                         fprintf(stderr, "vm_loop: unexpected exitcode 0x%x\n",
752                             exitcode);
753                         exit(4);
754                 }
755
756                 rc = (*handler[exitcode])(ctx, &vmexit[vcpu], &vcpu);
757
758                 switch (rc) {
759                 case VMEXIT_CONTINUE:
760                         break;
761                 case VMEXIT_ABORT:
762                         abort();
763                 default:
764                         exit(4);
765                 }
766         }
767         fprintf(stderr, "vm_run error %d, errno %d\n", error, errno);
768 }
769
770 static int
771 num_vcpus_allowed(struct vmctx *ctx)
772 {
773         int tmp, error;
774
775         error = vm_get_capability(ctx, BSP, VM_CAP_UNRESTRICTED_GUEST, &tmp);
776
777         /*
778          * The guest is allowed to spinup more than one processor only if the
779          * UNRESTRICTED_GUEST capability is available.
780          */
781         if (error == 0)
782                 return (VM_MAXCPU);
783         else
784                 return (1);
785 }
786
787 void
788 fbsdrun_set_capabilities(struct vmctx *ctx, int cpu)
789 {
790         int err, tmp;
791
792         if (fbsdrun_vmexit_on_hlt()) {
793                 err = vm_get_capability(ctx, cpu, VM_CAP_HALT_EXIT, &tmp);
794                 if (err < 0) {
795                         fprintf(stderr, "VM exit on HLT not supported\n");
796                         exit(4);
797                 }
798                 vm_set_capability(ctx, cpu, VM_CAP_HALT_EXIT, 1);
799                 if (cpu == BSP)
800                         handler[VM_EXITCODE_HLT] = vmexit_hlt;
801         }
802
803         if (fbsdrun_vmexit_on_pause()) {
804                 /*
805                  * pause exit support required for this mode
806                  */
807                 err = vm_get_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, &tmp);
808                 if (err < 0) {
809                         fprintf(stderr,
810                             "SMP mux requested, no pause support\n");
811                         exit(4);
812                 }
813                 vm_set_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, 1);
814                 if (cpu == BSP)
815                         handler[VM_EXITCODE_PAUSE] = vmexit_pause;
816         }
817
818         if (x2apic_mode)
819                 err = vm_set_x2apic_state(ctx, cpu, X2APIC_ENABLED);
820         else
821                 err = vm_set_x2apic_state(ctx, cpu, X2APIC_DISABLED);
822
823         if (err) {
824                 fprintf(stderr, "Unable to set x2apic state (%d)\n", err);
825                 exit(4);
826         }
827
828         vm_set_capability(ctx, cpu, VM_CAP_ENABLE_INVPCID, 1);
829 }
830
831 static struct vmctx *
832 do_open(const char *vmname)
833 {
834         struct vmctx *ctx;
835         int error;
836         bool reinit, romboot;
837 #ifndef WITHOUT_CAPSICUM
838         cap_rights_t rights;
839         const cap_ioctl_t *cmds;        
840         size_t ncmds;
841 #endif
842
843         reinit = romboot = false;
844
845         if (lpc_bootrom())
846                 romboot = true;
847
848         error = vm_create(vmname);
849         if (error) {
850                 if (errno == EEXIST) {
851                         if (romboot) {
852                                 reinit = true;
853                         } else {
854                                 /*
855                                  * The virtual machine has been setup by the
856                                  * userspace bootloader.
857                                  */
858                         }
859                 } else {
860                         perror("vm_create");
861                         exit(4);
862                 }
863         } else {
864                 if (!romboot) {
865                         /*
866                          * If the virtual machine was just created then a
867                          * bootrom must be configured to boot it.
868                          */
869                         fprintf(stderr, "virtual machine cannot be booted\n");
870                         exit(4);
871                 }
872         }
873
874         ctx = vm_open(vmname);
875         if (ctx == NULL) {
876                 perror("vm_open");
877                 exit(4);
878         }
879
880 #ifndef WITHOUT_CAPSICUM
881         cap_rights_init(&rights, CAP_IOCTL, CAP_MMAP_RW);
882         if (cap_rights_limit(vm_get_device_fd(ctx), &rights) == -1 &&
883             errno != ENOSYS)
884                 errx(EX_OSERR, "Unable to apply rights for sandbox");
885         vm_get_ioctls(&ncmds);
886         cmds = vm_get_ioctls(NULL);
887         if (cmds == NULL)
888                 errx(EX_OSERR, "out of memory");
889         if (cap_ioctls_limit(vm_get_device_fd(ctx), cmds, ncmds) == -1 &&
890             errno != ENOSYS)
891                 errx(EX_OSERR, "Unable to apply rights for sandbox");
892         free((cap_ioctl_t *)cmds);
893 #endif
894  
895         if (reinit) {
896                 error = vm_reinit(ctx);
897                 if (error) {
898                         perror("vm_reinit");
899                         exit(4);
900                 }
901         }
902         return (ctx);
903 }
904
905 int
906 main(int argc, char *argv[])
907 {
908         int c, error, gdb_port, err, bvmcons;
909         int max_vcpus, mptgen, memflags;
910         int rtc_localtime;
911         struct vmctx *ctx;
912         uint64_t rip;
913         size_t memsize;
914         char *optstr;
915
916         bvmcons = 0;
917         progname = basename(argv[0]);
918         gdb_port = 0;
919         guest_ncpus = 1;
920         memsize = 256 * MB;
921         mptgen = 1;
922         rtc_localtime = 1;
923         memflags = 0;
924
925         optstr = "abehuwxACHIPSWYp:g:c:s:m:l:U:";
926         while ((c = getopt(argc, argv, optstr)) != -1) {
927                 switch (c) {
928                 case 'a':
929                         x2apic_mode = 0;
930                         break;
931                 case 'A':
932                         acpi = 1;
933                         break;
934                 case 'b':
935                         bvmcons = 1;
936                         break;
937                 case 'p':
938                         if (pincpu_parse(optarg) != 0) {
939                             errx(EX_USAGE, "invalid vcpu pinning "
940                                  "configuration '%s'", optarg);
941                         }
942                         break;
943                 case 'c':
944                         guest_ncpus = atoi(optarg);
945                         break;
946                 case 'C':
947                         memflags |= VM_MEM_F_INCORE;
948                         break;
949                 case 'g':
950                         gdb_port = atoi(optarg);
951                         break;
952                 case 'l':
953                         if (lpc_device_parse(optarg) != 0) {
954                                 errx(EX_USAGE, "invalid lpc device "
955                                     "configuration '%s'", optarg);
956                         }
957                         break;
958                 case 's':
959                         if (pci_parse_slot(optarg) != 0)
960                                 exit(4);
961                         else
962                                 break;
963                 case 'S':
964                         memflags |= VM_MEM_F_WIRED;
965                         break;
966                 case 'm':
967                         error = vm_parse_memsize(optarg, &memsize);
968                         if (error)
969                                 errx(EX_USAGE, "invalid memsize '%s'", optarg);
970                         break;
971                 case 'H':
972                         guest_vmexit_on_hlt = 1;
973                         break;
974                 case 'I':
975                         /*
976                          * The "-I" option was used to add an ioapic to the
977                          * virtual machine.
978                          *
979                          * An ioapic is now provided unconditionally for each
980                          * virtual machine and this option is now deprecated.
981                          */
982                         break;
983                 case 'P':
984                         guest_vmexit_on_pause = 1;
985                         break;
986                 case 'e':
987                         strictio = 1;
988                         break;
989                 case 'u':
990                         rtc_localtime = 0;
991                         break;
992                 case 'U':
993                         guest_uuid_str = optarg;
994                         break;
995                 case 'w':
996                         strictmsr = 0;
997                         break;
998                 case 'W':
999                         virtio_msix = 0;
1000                         break;
1001                 case 'x':
1002                         x2apic_mode = 1;
1003                         break;
1004                 case 'Y':
1005                         mptgen = 0;
1006                         break;
1007                 case 'h':
1008                         usage(0);                       
1009                 default:
1010                         usage(1);
1011                 }
1012         }
1013         argc -= optind;
1014         argv += optind;
1015
1016         if (argc != 1)
1017                 usage(1);
1018
1019         vmname = argv[0];
1020         ctx = do_open(vmname);
1021
1022         if (guest_ncpus < 1) {
1023                 fprintf(stderr, "Invalid guest vCPUs (%d)\n", guest_ncpus);
1024                 exit(1);
1025         }
1026
1027         max_vcpus = num_vcpus_allowed(ctx);
1028         if (guest_ncpus > max_vcpus) {
1029                 fprintf(stderr, "%d vCPUs requested but only %d available\n",
1030                         guest_ncpus, max_vcpus);
1031                 exit(4);
1032         }
1033
1034         fbsdrun_set_capabilities(ctx, BSP);
1035
1036         vm_set_memflags(ctx, memflags);
1037         err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL);
1038         if (err) {
1039                 fprintf(stderr, "Unable to setup memory (%d)\n", errno);
1040                 exit(4);
1041         }
1042
1043         error = init_msr();
1044         if (error) {
1045                 fprintf(stderr, "init_msr error %d", error);
1046                 exit(4);
1047         }
1048
1049         init_mem();
1050         init_inout();
1051         atkbdc_init(ctx);
1052         pci_irq_init(ctx);
1053         ioapic_init(ctx);
1054
1055         rtc_init(ctx, rtc_localtime);
1056         sci_init(ctx);
1057
1058         /*
1059          * Exit if a device emulation finds an error in it's initilization
1060          */
1061         if (init_pci(ctx) != 0) {
1062                 perror("device emulation initialization error");
1063                 exit(4);
1064         }
1065
1066         if (gdb_port != 0)
1067                 init_dbgport(gdb_port);
1068
1069         if (bvmcons)
1070                 init_bvmcons();
1071
1072         if (lpc_bootrom()) {
1073                 if (vm_set_capability(ctx, BSP, VM_CAP_UNRESTRICTED_GUEST, 1)) {
1074                         fprintf(stderr, "ROM boot failed: unrestricted guest "
1075                             "capability not available\n");
1076                         exit(4);
1077                 }
1078                 error = vcpu_reset(ctx, BSP);
1079                 assert(error == 0);
1080         }
1081
1082         error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip);
1083         assert(error == 0);
1084
1085         /*
1086          * build the guest tables, MP etc.
1087          */
1088         if (mptgen) {
1089                 error = mptable_build(ctx, guest_ncpus);
1090                 if (error) {
1091                         perror("error to build the guest tables");
1092                         exit(4);
1093                 }
1094         }
1095
1096         error = smbios_build(ctx);
1097         assert(error == 0);
1098
1099         if (acpi) {
1100                 error = acpi_build(ctx, guest_ncpus);
1101                 assert(error == 0);
1102         }
1103
1104         if (lpc_bootrom())
1105                 fwctl_init();
1106
1107         /*
1108          * Change the proc title to include the VM name.
1109          */
1110         setproctitle("%s", vmname);
1111
1112 #ifndef WITHOUT_CAPSICUM
1113         bhyve_caph_cache_catpages();
1114
1115         if (bhyve_caph_limit_stdoe() == -1)
1116                 errx(EX_OSERR, "Unable to apply rights for sandbox");
1117
1118         if (cap_enter() == -1 && errno != ENOSYS)
1119                 errx(EX_OSERR, "cap_enter() failed");
1120 #endif
1121
1122         /*
1123          * Add CPU 0
1124          */
1125         fbsdrun_addcpu(ctx, BSP, BSP, rip);
1126
1127         /*
1128          * Head off to the main event dispatch loop
1129          */
1130         mevent_dispatch();
1131
1132         exit(4);
1133 }