From 70b50f16469543eddc3a9958b4a973bec1e41f52 Mon Sep 17 00:00:00 2001 From: grehan Date: Thu, 13 Dec 2012 01:58:11 +0000 Subject: Rename fbsdrun.* -> bhyverun.* bhyve is intended to be a generic hypervisor, and not FreeBSD-specific. (renaming internal routines will come later) Reviewed by: neel Obtained from: NetApp --- usr.sbin/bhyve/Makefile | 2 +- usr.sbin/bhyve/acpi.c | 2 +- usr.sbin/bhyve/bhyverun.c | 770 ++++++++++++++++++++++++++++++++++++++ usr.sbin/bhyve/bhyverun.h | 53 +++ usr.sbin/bhyve/fbsdrun.c | 770 -------------------------------------- usr.sbin/bhyve/fbsdrun.h | 53 --- usr.sbin/bhyve/ioapic.c | 2 +- usr.sbin/bhyve/mptbl.c | 2 +- usr.sbin/bhyve/pci_emul.c | 2 +- usr.sbin/bhyve/pci_uart.c | 2 +- usr.sbin/bhyve/pci_virtio_block.c | 2 +- usr.sbin/bhyve/pci_virtio_net.c | 2 +- usr.sbin/bhyve/pit_8254.c | 2 +- usr.sbin/bhyve/spinup_ap.c | 2 +- 14 files changed, 833 insertions(+), 833 deletions(-) create mode 100644 usr.sbin/bhyve/bhyverun.c create mode 100644 usr.sbin/bhyve/bhyverun.h delete mode 100644 usr.sbin/bhyve/fbsdrun.c delete mode 100644 usr.sbin/bhyve/fbsdrun.h (limited to 'usr.sbin') diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index c45b904..078ef9a 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -6,7 +6,7 @@ PROG= bhyve DEBUG_FLAGS= -g -O0 -SRCS= acpi.c atpic.c consport.c dbgport.c elcr.c fbsdrun.c inout.c +SRCS= acpi.c atpic.c bhyverun.c consport.c dbgport.c elcr.c inout.c SRCS+= ioapic.c mem.c mevent.c mptbl.c SRCS+= pci_emul.c pci_hostbridge.c pci_passthru.c pci_virtio_block.c SRCS+= pci_virtio_net.c pci_uart.c pit_8254.c pmtmr.c post.c rtc.c uart.c diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c index 1671550..32effdc 100644 --- a/usr.sbin/bhyve/acpi.c +++ b/usr.sbin/bhyve/acpi.c @@ -61,7 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "fbsdrun.h" +#include "bhyverun.h" #include "acpi.h" /* diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c new file mode 100644 index 0000000..fd3d8a2 --- /dev/null +++ b/usr.sbin/bhyve/bhyverun.c @@ -0,0 +1,770 @@ +/*- + * Copyright (c) 2011 NetApp, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bhyverun.h" +#include "acpi.h" +#include "inout.h" +#include "dbgport.h" +#include "mem.h" +#include "mevent.h" +#include "mptbl.h" +#include "pci_emul.h" +#include "xmsr.h" +#include "ioapic.h" +#include "spinup_ap.h" + +#define DEFAULT_GUEST_HZ 100 +#define DEFAULT_GUEST_TSLICE 200 + +#define GUEST_NIO_PORT 0x488 /* guest upcalls via i/o port */ + +#define VMEXIT_SWITCH 0 /* force vcpu switch in mux mode */ +#define VMEXIT_CONTINUE 1 /* continue from next instruction */ +#define VMEXIT_RESTART 2 /* restart current instruction */ +#define VMEXIT_ABORT 3 /* abort the vm run loop */ +#define VMEXIT_RESET 4 /* guest machine has reset */ + +#define MB (1024UL * 1024) +#define GB (1024UL * MB) + +typedef int (*vmexit_handler_t)(struct vmctx *, struct vm_exit *, int *vcpu); + +int guest_tslice = DEFAULT_GUEST_TSLICE; +int guest_hz = DEFAULT_GUEST_HZ; +char *vmname; + +u_long lomem_sz; +u_long himem_sz; + +int guest_ncpus; + +static int pincpu = -1; +static int guest_vcpu_mux; +static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic; + +static int foundcpus; + +static int strictio; + +static int acpi; + +static char *lomem_addr; +static char *himem_addr; + +static char *progname; +static const int BSP = 0; + +static int cpumask; + +static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip); + +struct vm_exit vmexit[VM_MAXCPU]; + +struct fbsdstats { + uint64_t vmexit_bogus; + uint64_t vmexit_bogus_switch; + uint64_t vmexit_hlt; + uint64_t vmexit_pause; + uint64_t vmexit_mtrap; + uint64_t vmexit_paging; + uint64_t cpu_switch_rotate; + uint64_t cpu_switch_direct; + int io_reset; +} stats; + +struct mt_vmm_info { + pthread_t mt_thr; + struct vmctx *mt_ctx; + int mt_vcpu; +} mt_vmm_info[VM_MAXCPU]; + +static void +usage(int code) +{ + + fprintf(stderr, + "Usage: %s [-aehABHIP][-g ][-z ][-s ]" + "[-S ][-p pincpu][-n ][-m lowmem][-M highmem] \n" + " -a: local apic is in XAPIC mode (default is X2APIC)\n" + " -A: create an ACPI table\n" + " -g: gdb port (default is %d and 0 means don't open)\n" + " -c: # cpus (default 1)\n" + " -p: pin vcpu 'n' to host cpu 'pincpu + n'\n" + " -B: inject breakpoint exception on vm entry\n" + " -H: vmexit from the guest on hlt\n" + " -I: present an ioapic to the guest\n" + " -P: vmexit from the guest on pause\n" + " -e: exit on unhandled i/o access\n" + " -h: help\n" + " -z: guest hz (default is %d)\n" + " -s: PCI slot config\n" + " -S: legacy PCI slot config\n" + " -m: lowmem in MB\n" + " -M: highmem in MB\n" + " -x: mux vcpus to 1 hcpu\n" + " -t: mux vcpu timeslice hz (default %d)\n", + progname, DEFAULT_GDB_PORT, DEFAULT_GUEST_HZ, + DEFAULT_GUEST_TSLICE); + exit(code); +} + +void * +paddr_guest2host(uintptr_t gaddr) +{ + if (lomem_sz == 0) + return (NULL); + + if (gaddr < lomem_sz) { + return ((void *)(lomem_addr + gaddr)); + } else if (gaddr >= 4*GB && gaddr < (4*GB + himem_sz)) { + return ((void *)(himem_addr + gaddr - 4*GB)); + } else + return (NULL); +} + +int +fbsdrun_disable_x2apic(void) +{ + + return (disable_x2apic); +} + +int +fbsdrun_vmexit_on_pause(void) +{ + + return (guest_vmexit_on_pause); +} + +int +fbsdrun_vmexit_on_hlt(void) +{ + + return (guest_vmexit_on_hlt); +} + +int +fbsdrun_muxed(void) +{ + + return (guest_vcpu_mux); +} + +static void * +fbsdrun_start_thread(void *param) +{ + char tname[MAXCOMLEN + 1]; + struct mt_vmm_info *mtp; + int vcpu; + + mtp = param; + vcpu = mtp->mt_vcpu; + + snprintf(tname, sizeof(tname), "%s vcpu %d", vmname, vcpu); + pthread_set_name_np(mtp->mt_thr, tname); + + vm_loop(mtp->mt_ctx, vcpu, vmexit[vcpu].rip); + + /* not reached */ + exit(1); + return (NULL); +} + +void +fbsdrun_addcpu(struct vmctx *ctx, int vcpu, uint64_t rip) +{ + int error; + + if (cpumask & (1 << vcpu)) { + fprintf(stderr, "addcpu: attempting to add existing cpu %d\n", + vcpu); + exit(1); + } + + cpumask |= 1 << vcpu; + foundcpus++; + + /* + * Set up the vmexit struct to allow execution to start + * at the given RIP + */ + vmexit[vcpu].rip = rip; + vmexit[vcpu].inst_length = 0; + + if (vcpu == BSP || !guest_vcpu_mux){ + mt_vmm_info[vcpu].mt_ctx = ctx; + mt_vmm_info[vcpu].mt_vcpu = vcpu; + + error = pthread_create(&mt_vmm_info[vcpu].mt_thr, NULL, + fbsdrun_start_thread, &mt_vmm_info[vcpu]); + assert(error == 0); + } +} + +static int +fbsdrun_get_next_cpu(int curcpu) +{ + + /* + * Get the next available CPU. Assumes they arrive + * in ascending order with no gaps. + */ + return ((curcpu + 1) % foundcpus); +} + +static int +vmexit_catch_reset(void) +{ + stats.io_reset++; + return (VMEXIT_RESET); +} + +static int +vmexit_catch_inout(void) +{ + return (VMEXIT_ABORT); +} + +static int +vmexit_handle_notify(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu, + uint32_t eax) +{ +#if PG_DEBUG /* put all types of debug here */ + if (eax == 0) { + pause_noswitch = 1; + } else if (eax == 1) { + pause_noswitch = 0; + } else { + pause_noswitch = 0; + if (eax == 5) { + vm_set_capability(ctx, *pvcpu, VM_CAP_MTRAP_EXIT, 1); + } + } +#endif + return (VMEXIT_CONTINUE); +} + +static int +vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) +{ + int error; + int bytes, port, in, out; + uint32_t eax; + int vcpu; + + vcpu = *pvcpu; + + port = vme->u.inout.port; + bytes = vme->u.inout.bytes; + eax = vme->u.inout.eax; + in = vme->u.inout.in; + out = !in; + + /* We don't deal with these */ + if (vme->u.inout.string || vme->u.inout.rep) + return (VMEXIT_ABORT); + + /* Special case of guest reset */ + if (out && port == 0x64 && (uint8_t)eax == 0xFE) + return (vmexit_catch_reset()); + + /* Extra-special case of host notifications */ + if (out && port == GUEST_NIO_PORT) + return (vmexit_handle_notify(ctx, vme, pvcpu, eax)); + + error = emulate_inout(ctx, vcpu, in, port, bytes, &eax, strictio); + if (error == 0 && in) + error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RAX, eax); + + if (error == 0) + return (VMEXIT_CONTINUE); + else { + fprintf(stderr, "Unhandled %s%c 0x%04x\n", + in ? "in" : "out", + bytes == 1 ? 'b' : (bytes == 2 ? 'w' : 'l'), port); + return (vmexit_catch_inout()); + } +} + +static int +vmexit_rdmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) +{ + fprintf(stderr, "vm exit rdmsr 0x%x, cpu %d\n", vme->u.msr.code, + *pvcpu); + return (VMEXIT_ABORT); +} + +static int +vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) +{ + int newcpu; + int retval = VMEXIT_CONTINUE; + + newcpu = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code,vme->u.msr.wval); + + if (guest_vcpu_mux && *pvcpu != newcpu) { + retval = VMEXIT_SWITCH; + *pvcpu = newcpu; + } + + return (retval); +} + +static int +vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) +{ + int newcpu; + int retval = VMEXIT_CONTINUE; + + newcpu = spinup_ap(ctx, *pvcpu, + vme->u.spinup_ap.vcpu, vme->u.spinup_ap.rip); + + if (guest_vcpu_mux && *pvcpu != newcpu) { + retval = VMEXIT_SWITCH; + *pvcpu = newcpu; + } + + return (retval); +} + +static int +vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) +{ + + fprintf(stderr, "vm exit[%d]\n", *pvcpu); + fprintf(stderr, "\treason\t\tVMX\n"); + fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip); + fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length); + fprintf(stderr, "\terror\t\t%d\n", vmexit->u.vmx.error); + fprintf(stderr, "\texit_reason\t%u\n", vmexit->u.vmx.exit_reason); + fprintf(stderr, "\tqualification\t0x%016lx\n", + vmexit->u.vmx.exit_qualification); + + return (VMEXIT_ABORT); +} + +static int bogus_noswitch = 1; + +static int +vmexit_bogus(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) +{ + stats.vmexit_bogus++; + + if (!guest_vcpu_mux || guest_ncpus == 1 || bogus_noswitch) { + return (VMEXIT_RESTART); + } else { + stats.vmexit_bogus_switch++; + vmexit->inst_length = 0; + *pvcpu = -1; + return (VMEXIT_SWITCH); + } +} + +static int +vmexit_hlt(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) +{ + stats.vmexit_hlt++; + if (fbsdrun_muxed()) { + *pvcpu = -1; + return (VMEXIT_SWITCH); + } else { + /* + * Just continue execution with the next instruction. We use + * the HLT VM exit as a way to be friendly with the host + * scheduler. + */ + return (VMEXIT_CONTINUE); + } +} + +static int pause_noswitch; + +static int +vmexit_pause(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) +{ + stats.vmexit_pause++; + + if (fbsdrun_muxed() && !pause_noswitch) { + *pvcpu = -1; + return (VMEXIT_SWITCH); + } else { + return (VMEXIT_CONTINUE); + } +} + +static int +vmexit_mtrap(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) +{ + stats.vmexit_mtrap++; + + return (VMEXIT_RESTART); +} + +static int +vmexit_paging(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) +{ + int err; + stats.vmexit_paging++; + + err = emulate_mem(ctx, *pvcpu, vmexit->u.paging.gpa, + &vmexit->u.paging.vie); + + if (err) { + if (err == EINVAL) { + fprintf(stderr, + "Failed to emulate instruction at 0x%lx\n", + vmexit->rip); + } else if (err == ESRCH) { + fprintf(stderr, "Unhandled memory access to 0x%lx\n", + vmexit->u.paging.gpa); + } + + return (VMEXIT_ABORT); + } + + return (VMEXIT_CONTINUE); +} + +static void +sigalrm(int sig) +{ + return; +} + +static void +setup_timeslice(void) +{ + struct sigaction sa; + struct itimerval itv; + int error; + + /* + * Setup a realtime timer to generate a SIGALRM at a + * frequency of 'guest_tslice' ticks per second. + */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = sigalrm; + + error = sigaction(SIGALRM, &sa, NULL); + assert(error == 0); + + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 1000000 / guest_tslice; + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 1000000 / guest_tslice; + + error = setitimer(ITIMER_REAL, &itv, NULL); + assert(error == 0); +} + +static vmexit_handler_t handler[VM_EXITCODE_MAX] = { + [VM_EXITCODE_INOUT] = vmexit_inout, + [VM_EXITCODE_VMX] = vmexit_vmx, + [VM_EXITCODE_BOGUS] = vmexit_bogus, + [VM_EXITCODE_RDMSR] = vmexit_rdmsr, + [VM_EXITCODE_WRMSR] = vmexit_wrmsr, + [VM_EXITCODE_MTRAP] = vmexit_mtrap, + [VM_EXITCODE_PAGING] = vmexit_paging, + [VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap, +}; + +static void +vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip) +{ + int error, rc, prevcpu; + + if (guest_vcpu_mux) + setup_timeslice(); + + if (pincpu >= 0) { + error = vm_set_pinning(ctx, vcpu, pincpu + vcpu); + assert(error == 0); + } + + while (1) { + error = vm_run(ctx, vcpu, rip, &vmexit[vcpu]); + if (error != 0) { + /* + * It is possible that 'vmmctl' or some other process + * has transitioned the vcpu to CANNOT_RUN state right + * before we tried to transition it to RUNNING. + * + * This is expected to be temporary so just retry. + */ + if (errno == EBUSY) + continue; + else + break; + } + + prevcpu = vcpu; + rc = (*handler[vmexit[vcpu].exitcode])(ctx, &vmexit[vcpu], + &vcpu); + switch (rc) { + case VMEXIT_SWITCH: + assert(guest_vcpu_mux); + if (vcpu == -1) { + stats.cpu_switch_rotate++; + vcpu = fbsdrun_get_next_cpu(prevcpu); + } else { + stats.cpu_switch_direct++; + } + /* fall through */ + case VMEXIT_CONTINUE: + rip = vmexit[vcpu].rip + vmexit[vcpu].inst_length; + break; + case VMEXIT_RESTART: + rip = vmexit[vcpu].rip; + break; + case VMEXIT_RESET: + exit(0); + default: + exit(1); + } + } + fprintf(stderr, "vm_run error %d, errno %d\n", error, errno); +} + + +int +main(int argc, char *argv[]) +{ + int c, error, gdb_port, inject_bkpt, tmp, err, ioapic, bvmcons; + struct vmctx *ctx; + uint64_t rip; + + bvmcons = 0; + inject_bkpt = 0; + progname = basename(argv[0]); + gdb_port = DEFAULT_GDB_PORT; + guest_ncpus = 1; + ioapic = 0; + + while ((c = getopt(argc, argv, "abehABHIPxp:g:c:z:s:S:n:m:M:")) != -1) { + switch (c) { + case 'a': + disable_x2apic = 1; + break; + case 'A': + acpi = 1; + break; + case 'b': + bvmcons = 1; + break; + case 'B': + inject_bkpt = 1; + break; + case 'x': + guest_vcpu_mux = 1; + break; + case 'p': + pincpu = atoi(optarg); + break; + case 'c': + guest_ncpus = atoi(optarg); + break; + case 'g': + gdb_port = atoi(optarg); + break; + case 'z': + guest_hz = atoi(optarg); + break; + case 't': + guest_tslice = atoi(optarg); + break; + case 's': + pci_parse_slot(optarg, 0); + break; + case 'S': + pci_parse_slot(optarg, 1); + break; + case 'm': + lomem_sz = strtoul(optarg, NULL, 0) * MB; + break; + case 'M': + himem_sz = strtoul(optarg, NULL, 0) * MB; + break; + case 'H': + guest_vmexit_on_hlt = 1; + break; + case 'I': + ioapic = 1; + break; + case 'P': + guest_vmexit_on_pause = 1; + break; + case 'e': + strictio = 1; + break; + case 'h': + usage(0); + default: + usage(1); + } + } + argc -= optind; + argv += optind; + + if (argc != 1) + usage(1); + + /* No need to mux if guest is uni-processor */ + if (guest_ncpus <= 1) + guest_vcpu_mux = 0; + + if (guest_ncpus > VM_MAXCPU) { + fprintf(stderr, "%d vCPUs requested, max %d\n", + guest_ncpus, VM_MAXCPU); + exit(1); + } + + /* vmexit on hlt if guest is muxed */ + if (guest_vcpu_mux) { + guest_vmexit_on_hlt = 1; + guest_vmexit_on_pause = 1; + } + + vmname = argv[0]; + + ctx = vm_open(vmname); + if (ctx == NULL) { + perror("vm_open"); + exit(1); + } + + if (fbsdrun_vmexit_on_hlt()) { + err = vm_get_capability(ctx, BSP, VM_CAP_HALT_EXIT, &tmp); + if (err < 0) { + fprintf(stderr, "VM exit on HLT not supported\n"); + exit(1); + } + vm_set_capability(ctx, BSP, VM_CAP_HALT_EXIT, 1); + handler[VM_EXITCODE_HLT] = vmexit_hlt; + } + + if (fbsdrun_vmexit_on_pause()) { + /* + * pause exit support required for this mode + */ + err = vm_get_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, &tmp); + if (err < 0) { + fprintf(stderr, + "SMP mux requested, no pause support\n"); + exit(1); + } + vm_set_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, 1); + handler[VM_EXITCODE_PAUSE] = vmexit_pause; + } + + if (fbsdrun_disable_x2apic()) + err = vm_set_x2apic_state(ctx, BSP, X2APIC_DISABLED); + else + err = vm_set_x2apic_state(ctx, BSP, X2APIC_ENABLED); + + if (err) { + fprintf(stderr, "Unable to set x2apic state (%d)\n", err); + exit(1); + } + + if (lomem_sz != 0) { + lomem_addr = vm_map_memory(ctx, 0, lomem_sz); + if (lomem_addr == (char *) MAP_FAILED) { + lomem_sz = 0; + } else if (himem_sz != 0) { + himem_addr = vm_map_memory(ctx, 4*GB, himem_sz); + if (himem_addr == (char *) MAP_FAILED) { + lomem_sz = 0; + himem_sz = 0; + } + } + } + + init_inout(); + init_pci(ctx); + if (ioapic) + ioapic_init(0); + + if (gdb_port != 0) + init_dbgport(gdb_port); + + if (bvmcons) + init_bvmcons(); + + error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip); + assert(error == 0); + + if (inject_bkpt) { + error = vm_inject_event(ctx, BSP, VM_HW_EXCEPTION, IDT_BP); + assert(error == 0); + } + + /* + * build the guest tables, MP etc. + */ + mptable_build(ctx, guest_ncpus, ioapic); + + if (acpi) { + error = acpi_build(ctx, guest_ncpus, ioapic); + assert(error == 0); + } + + /* + * Add CPU 0 + */ + fbsdrun_addcpu(ctx, BSP, rip); + + /* + * Head off to the main event dispatch loop + */ + mevent_dispatch(); + + exit(1); +} diff --git a/usr.sbin/bhyve/bhyverun.h b/usr.sbin/bhyve/bhyverun.h new file mode 100644 index 0000000..45033b8 --- /dev/null +++ b/usr.sbin/bhyve/bhyverun.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2011 NetApp, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _FBSDRUN_H_ +#define _FBSDRUN_H_ + +#ifndef CTASSERT /* Allow lint to override */ +#define CTASSERT(x) _CTASSERT(x, __LINE__) +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] +#endif + +struct vmctx; +extern int guest_hz; +extern int guest_tslice; +extern int guest_ncpus; +extern char *vmname; + +extern u_long lomem_sz, himem_sz; + +void *paddr_guest2host(uintptr_t); + +void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip); +int fbsdrun_muxed(void); +int fbsdrun_vmexit_on_hlt(void); +int fbsdrun_vmexit_on_pause(void); +int fbsdrun_disable_x2apic(void); +#endif diff --git a/usr.sbin/bhyve/fbsdrun.c b/usr.sbin/bhyve/fbsdrun.c deleted file mode 100644 index 06e043c..0000000 --- a/usr.sbin/bhyve/fbsdrun.c +++ /dev/null @@ -1,770 +0,0 @@ -/*- - * Copyright (c) 2011 NetApp, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "fbsdrun.h" -#include "acpi.h" -#include "inout.h" -#include "dbgport.h" -#include "mem.h" -#include "mevent.h" -#include "mptbl.h" -#include "pci_emul.h" -#include "xmsr.h" -#include "ioapic.h" -#include "spinup_ap.h" - -#define DEFAULT_GUEST_HZ 100 -#define DEFAULT_GUEST_TSLICE 200 - -#define GUEST_NIO_PORT 0x488 /* guest upcalls via i/o port */ - -#define VMEXIT_SWITCH 0 /* force vcpu switch in mux mode */ -#define VMEXIT_CONTINUE 1 /* continue from next instruction */ -#define VMEXIT_RESTART 2 /* restart current instruction */ -#define VMEXIT_ABORT 3 /* abort the vm run loop */ -#define VMEXIT_RESET 4 /* guest machine has reset */ - -#define MB (1024UL * 1024) -#define GB (1024UL * MB) - -typedef int (*vmexit_handler_t)(struct vmctx *, struct vm_exit *, int *vcpu); - -int guest_tslice = DEFAULT_GUEST_TSLICE; -int guest_hz = DEFAULT_GUEST_HZ; -char *vmname; - -u_long lomem_sz; -u_long himem_sz; - -int guest_ncpus; - -static int pincpu = -1; -static int guest_vcpu_mux; -static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic; - -static int foundcpus; - -static int strictio; - -static int acpi; - -static char *lomem_addr; -static char *himem_addr; - -static char *progname; -static const int BSP = 0; - -static int cpumask; - -static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip); - -struct vm_exit vmexit[VM_MAXCPU]; - -struct fbsdstats { - uint64_t vmexit_bogus; - uint64_t vmexit_bogus_switch; - uint64_t vmexit_hlt; - uint64_t vmexit_pause; - uint64_t vmexit_mtrap; - uint64_t vmexit_paging; - uint64_t cpu_switch_rotate; - uint64_t cpu_switch_direct; - int io_reset; -} stats; - -struct mt_vmm_info { - pthread_t mt_thr; - struct vmctx *mt_ctx; - int mt_vcpu; -} mt_vmm_info[VM_MAXCPU]; - -static void -usage(int code) -{ - - fprintf(stderr, - "Usage: %s [-aehABHIP][-g ][-z ][-s ]" - "[-S ][-p pincpu][-n ][-m lowmem][-M highmem] \n" - " -a: local apic is in XAPIC mode (default is X2APIC)\n" - " -A: create an ACPI table\n" - " -g: gdb port (default is %d and 0 means don't open)\n" - " -c: # cpus (default 1)\n" - " -p: pin vcpu 'n' to host cpu 'pincpu + n'\n" - " -B: inject breakpoint exception on vm entry\n" - " -H: vmexit from the guest on hlt\n" - " -I: present an ioapic to the guest\n" - " -P: vmexit from the guest on pause\n" - " -e: exit on unhandled i/o access\n" - " -h: help\n" - " -z: guest hz (default is %d)\n" - " -s: PCI slot config\n" - " -S: legacy PCI slot config\n" - " -m: lowmem in MB\n" - " -M: highmem in MB\n" - " -x: mux vcpus to 1 hcpu\n" - " -t: mux vcpu timeslice hz (default %d)\n", - progname, DEFAULT_GDB_PORT, DEFAULT_GUEST_HZ, - DEFAULT_GUEST_TSLICE); - exit(code); -} - -void * -paddr_guest2host(uintptr_t gaddr) -{ - if (lomem_sz == 0) - return (NULL); - - if (gaddr < lomem_sz) { - return ((void *)(lomem_addr + gaddr)); - } else if (gaddr >= 4*GB && gaddr < (4*GB + himem_sz)) { - return ((void *)(himem_addr + gaddr - 4*GB)); - } else - return (NULL); -} - -int -fbsdrun_disable_x2apic(void) -{ - - return (disable_x2apic); -} - -int -fbsdrun_vmexit_on_pause(void) -{ - - return (guest_vmexit_on_pause); -} - -int -fbsdrun_vmexit_on_hlt(void) -{ - - return (guest_vmexit_on_hlt); -} - -int -fbsdrun_muxed(void) -{ - - return (guest_vcpu_mux); -} - -static void * -fbsdrun_start_thread(void *param) -{ - char tname[MAXCOMLEN + 1]; - struct mt_vmm_info *mtp; - int vcpu; - - mtp = param; - vcpu = mtp->mt_vcpu; - - snprintf(tname, sizeof(tname), "%s vcpu %d", vmname, vcpu); - pthread_set_name_np(mtp->mt_thr, tname); - - vm_loop(mtp->mt_ctx, vcpu, vmexit[vcpu].rip); - - /* not reached */ - exit(1); - return (NULL); -} - -void -fbsdrun_addcpu(struct vmctx *ctx, int vcpu, uint64_t rip) -{ - int error; - - if (cpumask & (1 << vcpu)) { - fprintf(stderr, "addcpu: attempting to add existing cpu %d\n", - vcpu); - exit(1); - } - - cpumask |= 1 << vcpu; - foundcpus++; - - /* - * Set up the vmexit struct to allow execution to start - * at the given RIP - */ - vmexit[vcpu].rip = rip; - vmexit[vcpu].inst_length = 0; - - if (vcpu == BSP || !guest_vcpu_mux){ - mt_vmm_info[vcpu].mt_ctx = ctx; - mt_vmm_info[vcpu].mt_vcpu = vcpu; - - error = pthread_create(&mt_vmm_info[vcpu].mt_thr, NULL, - fbsdrun_start_thread, &mt_vmm_info[vcpu]); - assert(error == 0); - } -} - -static int -fbsdrun_get_next_cpu(int curcpu) -{ - - /* - * Get the next available CPU. Assumes they arrive - * in ascending order with no gaps. - */ - return ((curcpu + 1) % foundcpus); -} - -static int -vmexit_catch_reset(void) -{ - stats.io_reset++; - return (VMEXIT_RESET); -} - -static int -vmexit_catch_inout(void) -{ - return (VMEXIT_ABORT); -} - -static int -vmexit_handle_notify(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu, - uint32_t eax) -{ -#if PG_DEBUG /* put all types of debug here */ - if (eax == 0) { - pause_noswitch = 1; - } else if (eax == 1) { - pause_noswitch = 0; - } else { - pause_noswitch = 0; - if (eax == 5) { - vm_set_capability(ctx, *pvcpu, VM_CAP_MTRAP_EXIT, 1); - } - } -#endif - return (VMEXIT_CONTINUE); -} - -static int -vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) -{ - int error; - int bytes, port, in, out; - uint32_t eax; - int vcpu; - - vcpu = *pvcpu; - - port = vme->u.inout.port; - bytes = vme->u.inout.bytes; - eax = vme->u.inout.eax; - in = vme->u.inout.in; - out = !in; - - /* We don't deal with these */ - if (vme->u.inout.string || vme->u.inout.rep) - return (VMEXIT_ABORT); - - /* Special case of guest reset */ - if (out && port == 0x64 && (uint8_t)eax == 0xFE) - return (vmexit_catch_reset()); - - /* Extra-special case of host notifications */ - if (out && port == GUEST_NIO_PORT) - return (vmexit_handle_notify(ctx, vme, pvcpu, eax)); - - error = emulate_inout(ctx, vcpu, in, port, bytes, &eax, strictio); - if (error == 0 && in) - error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RAX, eax); - - if (error == 0) - return (VMEXIT_CONTINUE); - else { - fprintf(stderr, "Unhandled %s%c 0x%04x\n", - in ? "in" : "out", - bytes == 1 ? 'b' : (bytes == 2 ? 'w' : 'l'), port); - return (vmexit_catch_inout()); - } -} - -static int -vmexit_rdmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) -{ - fprintf(stderr, "vm exit rdmsr 0x%x, cpu %d\n", vme->u.msr.code, - *pvcpu); - return (VMEXIT_ABORT); -} - -static int -vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) -{ - int newcpu; - int retval = VMEXIT_CONTINUE; - - newcpu = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code,vme->u.msr.wval); - - if (guest_vcpu_mux && *pvcpu != newcpu) { - retval = VMEXIT_SWITCH; - *pvcpu = newcpu; - } - - return (retval); -} - -static int -vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu) -{ - int newcpu; - int retval = VMEXIT_CONTINUE; - - newcpu = spinup_ap(ctx, *pvcpu, - vme->u.spinup_ap.vcpu, vme->u.spinup_ap.rip); - - if (guest_vcpu_mux && *pvcpu != newcpu) { - retval = VMEXIT_SWITCH; - *pvcpu = newcpu; - } - - return (retval); -} - -static int -vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) -{ - - fprintf(stderr, "vm exit[%d]\n", *pvcpu); - fprintf(stderr, "\treason\t\tVMX\n"); - fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip); - fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length); - fprintf(stderr, "\terror\t\t%d\n", vmexit->u.vmx.error); - fprintf(stderr, "\texit_reason\t%u\n", vmexit->u.vmx.exit_reason); - fprintf(stderr, "\tqualification\t0x%016lx\n", - vmexit->u.vmx.exit_qualification); - - return (VMEXIT_ABORT); -} - -static int bogus_noswitch = 1; - -static int -vmexit_bogus(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) -{ - stats.vmexit_bogus++; - - if (!guest_vcpu_mux || guest_ncpus == 1 || bogus_noswitch) { - return (VMEXIT_RESTART); - } else { - stats.vmexit_bogus_switch++; - vmexit->inst_length = 0; - *pvcpu = -1; - return (VMEXIT_SWITCH); - } -} - -static int -vmexit_hlt(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) -{ - stats.vmexit_hlt++; - if (fbsdrun_muxed()) { - *pvcpu = -1; - return (VMEXIT_SWITCH); - } else { - /* - * Just continue execution with the next instruction. We use - * the HLT VM exit as a way to be friendly with the host - * scheduler. - */ - return (VMEXIT_CONTINUE); - } -} - -static int pause_noswitch; - -static int -vmexit_pause(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) -{ - stats.vmexit_pause++; - - if (fbsdrun_muxed() && !pause_noswitch) { - *pvcpu = -1; - return (VMEXIT_SWITCH); - } else { - return (VMEXIT_CONTINUE); - } -} - -static int -vmexit_mtrap(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) -{ - stats.vmexit_mtrap++; - - return (VMEXIT_RESTART); -} - -static int -vmexit_paging(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) -{ - int err; - stats.vmexit_paging++; - - err = emulate_mem(ctx, *pvcpu, vmexit->u.paging.gpa, - &vmexit->u.paging.vie); - - if (err) { - if (err == EINVAL) { - fprintf(stderr, - "Failed to emulate instruction at 0x%lx\n", - vmexit->rip); - } else if (err == ESRCH) { - fprintf(stderr, "Unhandled memory access to 0x%lx\n", - vmexit->u.paging.gpa); - } - - return (VMEXIT_ABORT); - } - - return (VMEXIT_CONTINUE); -} - -static void -sigalrm(int sig) -{ - return; -} - -static void -setup_timeslice(void) -{ - struct sigaction sa; - struct itimerval itv; - int error; - - /* - * Setup a realtime timer to generate a SIGALRM at a - * frequency of 'guest_tslice' ticks per second. - */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = sigalrm; - - error = sigaction(SIGALRM, &sa, NULL); - assert(error == 0); - - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 1000000 / guest_tslice; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 1000000 / guest_tslice; - - error = setitimer(ITIMER_REAL, &itv, NULL); - assert(error == 0); -} - -static vmexit_handler_t handler[VM_EXITCODE_MAX] = { - [VM_EXITCODE_INOUT] = vmexit_inout, - [VM_EXITCODE_VMX] = vmexit_vmx, - [VM_EXITCODE_BOGUS] = vmexit_bogus, - [VM_EXITCODE_RDMSR] = vmexit_rdmsr, - [VM_EXITCODE_WRMSR] = vmexit_wrmsr, - [VM_EXITCODE_MTRAP] = vmexit_mtrap, - [VM_EXITCODE_PAGING] = vmexit_paging, - [VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap, -}; - -static void -vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip) -{ - int error, rc, prevcpu; - - if (guest_vcpu_mux) - setup_timeslice(); - - if (pincpu >= 0) { - error = vm_set_pinning(ctx, vcpu, pincpu + vcpu); - assert(error == 0); - } - - while (1) { - error = vm_run(ctx, vcpu, rip, &vmexit[vcpu]); - if (error != 0) { - /* - * It is possible that 'vmmctl' or some other process - * has transitioned the vcpu to CANNOT_RUN state right - * before we tried to transition it to RUNNING. - * - * This is expected to be temporary so just retry. - */ - if (errno == EBUSY) - continue; - else - break; - } - - prevcpu = vcpu; - rc = (*handler[vmexit[vcpu].exitcode])(ctx, &vmexit[vcpu], - &vcpu); - switch (rc) { - case VMEXIT_SWITCH: - assert(guest_vcpu_mux); - if (vcpu == -1) { - stats.cpu_switch_rotate++; - vcpu = fbsdrun_get_next_cpu(prevcpu); - } else { - stats.cpu_switch_direct++; - } - /* fall through */ - case VMEXIT_CONTINUE: - rip = vmexit[vcpu].rip + vmexit[vcpu].inst_length; - break; - case VMEXIT_RESTART: - rip = vmexit[vcpu].rip; - break; - case VMEXIT_RESET: - exit(0); - default: - exit(1); - } - } - fprintf(stderr, "vm_run error %d, errno %d\n", error, errno); -} - - -int -main(int argc, char *argv[]) -{ - int c, error, gdb_port, inject_bkpt, tmp, err, ioapic, bvmcons; - struct vmctx *ctx; - uint64_t rip; - - bvmcons = 0; - inject_bkpt = 0; - progname = basename(argv[0]); - gdb_port = DEFAULT_GDB_PORT; - guest_ncpus = 1; - ioapic = 0; - - while ((c = getopt(argc, argv, "abehABHIPxp:g:c:z:s:S:n:m:M:")) != -1) { - switch (c) { - case 'a': - disable_x2apic = 1; - break; - case 'A': - acpi = 1; - break; - case 'b': - bvmcons = 1; - break; - case 'B': - inject_bkpt = 1; - break; - case 'x': - guest_vcpu_mux = 1; - break; - case 'p': - pincpu = atoi(optarg); - break; - case 'c': - guest_ncpus = atoi(optarg); - break; - case 'g': - gdb_port = atoi(optarg); - break; - case 'z': - guest_hz = atoi(optarg); - break; - case 't': - guest_tslice = atoi(optarg); - break; - case 's': - pci_parse_slot(optarg, 0); - break; - case 'S': - pci_parse_slot(optarg, 1); - break; - case 'm': - lomem_sz = strtoul(optarg, NULL, 0) * MB; - break; - case 'M': - himem_sz = strtoul(optarg, NULL, 0) * MB; - break; - case 'H': - guest_vmexit_on_hlt = 1; - break; - case 'I': - ioapic = 1; - break; - case 'P': - guest_vmexit_on_pause = 1; - break; - case 'e': - strictio = 1; - break; - case 'h': - usage(0); - default: - usage(1); - } - } - argc -= optind; - argv += optind; - - if (argc != 1) - usage(1); - - /* No need to mux if guest is uni-processor */ - if (guest_ncpus <= 1) - guest_vcpu_mux = 0; - - if (guest_ncpus > VM_MAXCPU) { - fprintf(stderr, "%d vCPUs requested, max %d\n", - guest_ncpus, VM_MAXCPU); - exit(1); - } - - /* vmexit on hlt if guest is muxed */ - if (guest_vcpu_mux) { - guest_vmexit_on_hlt = 1; - guest_vmexit_on_pause = 1; - } - - vmname = argv[0]; - - ctx = vm_open(vmname); - if (ctx == NULL) { - perror("vm_open"); - exit(1); - } - - if (fbsdrun_vmexit_on_hlt()) { - err = vm_get_capability(ctx, BSP, VM_CAP_HALT_EXIT, &tmp); - if (err < 0) { - fprintf(stderr, "VM exit on HLT not supported\n"); - exit(1); - } - vm_set_capability(ctx, BSP, VM_CAP_HALT_EXIT, 1); - handler[VM_EXITCODE_HLT] = vmexit_hlt; - } - - if (fbsdrun_vmexit_on_pause()) { - /* - * pause exit support required for this mode - */ - err = vm_get_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, &tmp); - if (err < 0) { - fprintf(stderr, - "SMP mux requested, no pause support\n"); - exit(1); - } - vm_set_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, 1); - handler[VM_EXITCODE_PAUSE] = vmexit_pause; - } - - if (fbsdrun_disable_x2apic()) - err = vm_set_x2apic_state(ctx, BSP, X2APIC_DISABLED); - else - err = vm_set_x2apic_state(ctx, BSP, X2APIC_ENABLED); - - if (err) { - fprintf(stderr, "Unable to set x2apic state (%d)\n", err); - exit(1); - } - - if (lomem_sz != 0) { - lomem_addr = vm_map_memory(ctx, 0, lomem_sz); - if (lomem_addr == (char *) MAP_FAILED) { - lomem_sz = 0; - } else if (himem_sz != 0) { - himem_addr = vm_map_memory(ctx, 4*GB, himem_sz); - if (himem_addr == (char *) MAP_FAILED) { - lomem_sz = 0; - himem_sz = 0; - } - } - } - - init_inout(); - init_pci(ctx); - if (ioapic) - ioapic_init(0); - - if (gdb_port != 0) - init_dbgport(gdb_port); - - if (bvmcons) - init_bvmcons(); - - error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip); - assert(error == 0); - - if (inject_bkpt) { - error = vm_inject_event(ctx, BSP, VM_HW_EXCEPTION, IDT_BP); - assert(error == 0); - } - - /* - * build the guest tables, MP etc. - */ - mptable_build(ctx, guest_ncpus, ioapic); - - if (acpi) { - error = acpi_build(ctx, guest_ncpus, ioapic); - assert(error == 0); - } - - /* - * Add CPU 0 - */ - fbsdrun_addcpu(ctx, BSP, rip); - - /* - * Head off to the main event dispatch loop - */ - mevent_dispatch(); - - exit(1); -} diff --git a/usr.sbin/bhyve/fbsdrun.h b/usr.sbin/bhyve/fbsdrun.h deleted file mode 100644 index 45033b8..0000000 --- a/usr.sbin/bhyve/fbsdrun.h +++ /dev/null @@ -1,53 +0,0 @@ -/*- - * Copyright (c) 2011 NetApp, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _FBSDRUN_H_ -#define _FBSDRUN_H_ - -#ifndef CTASSERT /* Allow lint to override */ -#define CTASSERT(x) _CTASSERT(x, __LINE__) -#define _CTASSERT(x, y) __CTASSERT(x, y) -#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] -#endif - -struct vmctx; -extern int guest_hz; -extern int guest_tslice; -extern int guest_ncpus; -extern char *vmname; - -extern u_long lomem_sz, himem_sz; - -void *paddr_guest2host(uintptr_t); - -void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip); -int fbsdrun_muxed(void); -int fbsdrun_vmexit_on_hlt(void); -int fbsdrun_vmexit_on_pause(void); -int fbsdrun_disable_x2apic(void); -#endif diff --git a/usr.sbin/bhyve/ioapic.c b/usr.sbin/bhyve/ioapic.c index 47dd833..c712692 100644 --- a/usr.sbin/bhyve/ioapic.c +++ b/usr.sbin/bhyve/ioapic.c @@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$"); #include "inout.h" #include "mem.h" -#include "fbsdrun.h" +#include "bhyverun.h" #include diff --git a/usr.sbin/bhyve/mptbl.c b/usr.sbin/bhyve/mptbl.c index 03aaaee..52790f3 100644 --- a/usr.sbin/bhyve/mptbl.c +++ b/usr.sbin/bhyve/mptbl.c @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "fbsdrun.h" +#include "bhyverun.h" #include "mptbl.h" #define MPTABLE_BASE 0xF0000 diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index 1836bc9..e086aeb 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "fbsdrun.h" +#include "bhyverun.h" #include "inout.h" #include "mem.h" #include "mptbl.h" diff --git a/usr.sbin/bhyve/pci_uart.c b/usr.sbin/bhyve/pci_uart.c index 51876f5..3f192e1 100644 --- a/usr.sbin/bhyve/pci_uart.c +++ b/usr.sbin/bhyve/pci_uart.c @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "fbsdrun.h" +#include "bhyverun.h" #include "pci_emul.h" #include "mevent.h" diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c index 8c98615..3382097 100644 --- a/usr.sbin/bhyve/pci_virtio_block.c +++ b/usr.sbin/bhyve/pci_virtio_block.c @@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "fbsdrun.h" +#include "bhyverun.h" #include "pci_emul.h" #include "virtio.h" diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c index 9e7a1c7..3f6f88a 100644 --- a/usr.sbin/bhyve/pci_virtio_net.c +++ b/usr.sbin/bhyve/pci_virtio_net.c @@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "fbsdrun.h" +#include "bhyverun.h" #include "pci_emul.h" #include "mevent.h" #include "virtio.h" diff --git a/usr.sbin/bhyve/pit_8254.c b/usr.sbin/bhyve/pit_8254.c index d9b6d55..c96596a 100644 --- a/usr.sbin/bhyve/pit_8254.c +++ b/usr.sbin/bhyve/pit_8254.c @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "fbsdrun.h" +#include "bhyverun.h" #include "inout.h" #include "pit_8254.h" diff --git a/usr.sbin/bhyve/spinup_ap.c b/usr.sbin/bhyve/spinup_ap.c index 3aa3b65..b5e553f 100644 --- a/usr.sbin/bhyve/spinup_ap.c +++ b/usr.sbin/bhyve/spinup_ap.c @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "fbsdrun.h" +#include "bhyverun.h" #include "spinup_ap.h" /* -- cgit v1.1