The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=b9ef152bec6cff4cd82b68921f631bd6efb24ae6

commit b9ef152bec6cff4cd82b68921f631bd6efb24ae6
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2024-08-26 18:41:39 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2024-08-26 18:41:39 +0000

    vmm: Merge vmm_dev.c
    
    This file contains the vmm device file implementation.  Most of this
    code is not machine-dependent and so shouldn't be duplicated this way.
    Move most of it into a generic dev/vmm/vmm_dev.c.  This will make it
    easier to introduce a cdev-based interface for VM creation, which in
    turn makes it possible to implement support for running bhyve as an
    unprivileged user.
    
    Machine-dependent ioctls continue to be handled in machine-dependent
    code.  To make the split a bit easier to handle, introduce a pair of
    tables which define MI and MD ioctls.  Each table entry can set flags
    which determine which locks need to be held in order to execute the
    handler.  vmmdev_ioctl() now looks up the ioctl in one of the tables,
    acquires locks and either handles the ioctl directly or calls
    vmmdev_machdep_ioctl() to handle it.
    
    No functional change intended.  There is a lot of churn in this change
    but the underlying logic in the ioctl handlers is the same.  For now,
    vmm_dev.h is still mostly separate, even though some parts could be
    merged in principle.  This would involve changing include paths for
    userspace, though.
    
    Reviewed by:    corvink, jhb
    Differential Revision:  https://reviews.freebsd.org/D46431
---
 sys/amd64/include/vmm_dev.h      |    5 -
 sys/amd64/vmm/vmm.c              |    2 +-
 sys/amd64/vmm/vmm_dev.c          | 1452 --------------------------------------
 sys/amd64/vmm/vmm_dev_machdep.c  |  526 ++++++++++++++
 sys/arm64/include/vmm_dev.h      |    5 -
 sys/arm64/vmm/vmm.c              |    2 +-
 sys/arm64/vmm/vmm_dev_machdep.c  |  137 ++++
 sys/conf/files.arm64             |    1 +
 sys/{arm64 => dev}/vmm/vmm_dev.c |  443 ++++++------
 sys/dev/vmm/vmm_dev.h            |   57 ++
 sys/modules/vmm/Makefile         |    1 +
 11 files changed, 924 insertions(+), 1707 deletions(-)

diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h
index aa265315f15e..a007ce5515a5 100644
--- a/sys/amd64/include/vmm_dev.h
+++ b/sys/amd64/include/vmm_dev.h
@@ -31,11 +31,6 @@
 
 struct vm_snapshot_meta;
 
-#ifdef _KERNEL
-void   vmmdev_init(void);
-int    vmmdev_cleanup(void);
-#endif
-
 struct vm_memmap {
        vm_paddr_t      gpa;
        int             segid;          /* memory segment */
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index d0259b3b125f..20006e63cfeb 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -67,10 +67,10 @@
 #include <x86/ifunc.h>
 
 #include <machine/vmm.h>
-#include <machine/vmm_dev.h>
 #include <machine/vmm_instruction_emul.h>
 #include <machine/vmm_snapshot.h>
 
+#include <dev/vmm/vmm_dev.h>
 #include <dev/vmm/vmm_ktr.h>
 
 #include "vmm_ioport.h"
diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c
deleted file mode 100644
index 9acbfbb454e0..000000000000
--- a/sys/amd64/vmm/vmm_dev.c
+++ /dev/null
@@ -1,1452 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * 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.
- */
-
-#include "opt_bhyve_snapshot.h"
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/jail.h>
-#include <sys/queue.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/malloc.h>
-#include <sys/conf.h>
-#include <sys/sysctl.h>
-#include <sys/libkern.h>
-#include <sys/ioccom.h>
-#include <sys/mman.h>
-#include <sys/uio.h>
-#include <sys/proc.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_map.h>
-#include <vm/vm_object.h>
-
-#include <machine/vmparam.h>
-#include <machine/vmm.h>
-#include <machine/vmm_dev.h>
-#include <machine/vmm_instruction_emul.h>
-#include <machine/vmm_snapshot.h>
-#include <x86/apicreg.h>
-
-#include "vmm_lapic.h"
-#include "vmm_stat.h"
-#include "vmm_mem.h"
-#include "io/ppt.h"
-#include "io/vatpic.h"
-#include "io/vioapic.h"
-#include "io/vhpet.h"
-#include "io/vrtc.h"
-
-#ifdef COMPAT_FREEBSD13
-struct vm_stats_old {
-       int             cpuid;                          /* in */
-       int             num_entries;                    /* out */
-       struct timeval  tv;
-       uint64_t        statbuf[MAX_VM_STATS];
-};
-
-#define        VM_STATS_OLD \
-       _IOWR('v', IOCNUM_VM_STATS, struct vm_stats_old)
-
-struct vm_snapshot_meta_old {
-       void *ctx;                      /* unused */
-       void *dev_data;
-       const char *dev_name;      /* identify userspace devices */
-       enum snapshot_req dev_req; /* identify kernel structs */
-
-       struct vm_snapshot_buffer buffer;
-
-       enum vm_snapshot_op op;
-};
-
-#define VM_SNAPSHOT_REQ_OLD \
-       _IOWR('v', IOCNUM_SNAPSHOT_REQ, struct vm_snapshot_meta_old)
-
-struct vm_exit_ipi_13 {
-       uint32_t        mode;
-       uint8_t         vector;
-       __BITSET_DEFINE(, 256) dmask;
-};
-
-struct vm_exit_13 {
-       uint32_t        exitcode;
-       int32_t         inst_length;
-       uint64_t        rip;
-       uint64_t        u[120 / sizeof(uint64_t)];
-};
-
-struct vm_run_13 {
-       int             cpuid;
-       struct vm_exit_13 vm_exit;
-};
-
-#define        VM_RUN_13 \
-       _IOWR('v', IOCNUM_RUN, struct vm_run_13)
-
-#endif /* COMPAT_FREEBSD13 */
-
-struct devmem_softc {
-       int     segid;
-       char    *name;
-       struct cdev *cdev;
-       struct vmmdev_softc *sc;
-       SLIST_ENTRY(devmem_softc) link;
-};
-
-struct vmmdev_softc {
-       struct vm       *vm;            /* vm instance cookie */
-       struct cdev     *cdev;
-       struct ucred    *ucred;
-       SLIST_ENTRY(vmmdev_softc) link;
-       SLIST_HEAD(, devmem_softc) devmem;
-       int             flags;
-};
-#define        VSC_LINKED              0x01
-
-static SLIST_HEAD(, vmmdev_softc) head;
-
-static unsigned pr_allow_flag;
-static struct mtx vmmdev_mtx;
-MTX_SYSINIT(vmmdev_mtx, &vmmdev_mtx, "vmm device mutex", MTX_DEF);
-
-static MALLOC_DEFINE(M_VMMDEV, "vmmdev", "vmmdev");
-
-SYSCTL_DECL(_hw_vmm);
-
-static int vmm_priv_check(struct ucred *ucred);
-static int devmem_create_cdev(const char *vmname, int id, char *devmem);
-static void devmem_destroy(void *arg);
-
-static int
-vmm_priv_check(struct ucred *ucred)
-{
-
-       if (jailed(ucred) &&
-           !(ucred->cr_prison->pr_allow & pr_allow_flag))
-               return (EPERM);
-
-       return (0);
-}
-
-static int
-vcpu_lock_one(struct vcpu *vcpu)
-{
-       return (vcpu_set_state(vcpu, VCPU_FROZEN, true));
-}
-
-static void
-vcpu_unlock_one(struct vcpu *vcpu)
-{
-       enum vcpu_state state;
-
-       state = vcpu_get_state(vcpu, NULL);
-       if (state != VCPU_FROZEN) {
-               panic("vcpu %s(%d) has invalid state %d",
-                   vm_name(vcpu_vm(vcpu)), vcpu_vcpuid(vcpu), state);
-       }
-
-       vcpu_set_state(vcpu, VCPU_IDLE, false);
-}
-
-static int
-vcpu_lock_all(struct vmmdev_softc *sc)
-{
-       struct vcpu *vcpu;
-       int error;
-       uint16_t i, j, maxcpus;
-
-       error = 0;
-       vm_slock_vcpus(sc->vm);
-       maxcpus = vm_get_maxcpus(sc->vm);
-       for (i = 0; i < maxcpus; i++) {
-               vcpu = vm_vcpu(sc->vm, i);
-               if (vcpu == NULL)
-                       continue;
-               error = vcpu_lock_one(vcpu);
-               if (error)
-                       break;
-       }
-
-       if (error) {
-               for (j = 0; j < i; j++) {
-                       vcpu = vm_vcpu(sc->vm, j);
-                       if (vcpu == NULL)
-                               continue;
-                       vcpu_unlock_one(vcpu);
-               }
-               vm_unlock_vcpus(sc->vm);
-       }
-
-       return (error);
-}
-
-static void
-vcpu_unlock_all(struct vmmdev_softc *sc)
-{
-       struct vcpu *vcpu;
-       uint16_t i, maxcpus;
-
-       maxcpus = vm_get_maxcpus(sc->vm);
-       for (i = 0; i < maxcpus; i++) {
-               vcpu = vm_vcpu(sc->vm, i);
-               if (vcpu == NULL)
-                       continue;
-               vcpu_unlock_one(vcpu);
-       }
-       vm_unlock_vcpus(sc->vm);
-}
-
-static struct vmmdev_softc *
-vmmdev_lookup(const char *name)
-{
-       struct vmmdev_softc *sc;
-
-       mtx_assert(&vmmdev_mtx, MA_OWNED);
-
-       SLIST_FOREACH(sc, &head, link) {
-               if (strcmp(name, vm_name(sc->vm)) == 0)
-                       break;
-       }
-
-       if (sc == NULL)
-               return (NULL);
-
-       if (cr_cansee(curthread->td_ucred, sc->ucred))
-               return (NULL);
-
-       return (sc);
-}
-
-static struct vmmdev_softc *
-vmmdev_lookup2(struct cdev *cdev)
-{
-
-       return (cdev->si_drv1);
-}
-
-static int
-vmmdev_rw(struct cdev *cdev, struct uio *uio, int flags)
-{
-       int error, off, c, prot;
-       vm_paddr_t gpa, maxaddr;
-       void *hpa, *cookie;
-       struct vmmdev_softc *sc;
-
-       error = vmm_priv_check(curthread->td_ucred);
-       if (error)
-               return (error);
-
-       sc = vmmdev_lookup2(cdev);
-       if (sc == NULL)
-               return (ENXIO);
-
-       /*
-        * Get a read lock on the guest memory map.
-        */
-       vm_slock_memsegs(sc->vm);
-
-       prot = (uio->uio_rw == UIO_WRITE ? VM_PROT_WRITE : VM_PROT_READ);
-       maxaddr = vmm_sysmem_maxaddr(sc->vm);
-       while (uio->uio_resid > 0 && error == 0) {
-               gpa = uio->uio_offset;
-               off = gpa & PAGE_MASK;
-               c = min(uio->uio_resid, PAGE_SIZE - off);
-
-               /*
-                * The VM has a hole in its physical memory map. If we want to
-                * use 'dd' to inspect memory beyond the hole we need to
-                * provide bogus data for memory that lies in the hole.
-                *
-                * Since this device does not support lseek(2), dd(1) will
-                * read(2) blocks of data to simulate the lseek(2).
-                */
-               hpa = vm_gpa_hold_global(sc->vm, gpa, c, prot, &cookie);
-               if (hpa == NULL) {
-                       if (uio->uio_rw == UIO_READ && gpa < maxaddr)
-                               error = uiomove(__DECONST(void *, zero_region),
-                                   c, uio);
-                       else
-                               error = EFAULT;
-               } else {
-                       error = uiomove(hpa, c, uio);
-                       vm_gpa_release(cookie);
-               }
-       }
-       vm_unlock_memsegs(sc->vm);
-       return (error);
-}
-
-CTASSERT(sizeof(((struct vm_memseg *)0)->name) >= VM_MAX_SUFFIXLEN + 1);
-
-static int
-get_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg, size_t len)
-{
-       struct devmem_softc *dsc;
-       int error;
-       bool sysmem;
-
-       error = vm_get_memseg(sc->vm, mseg->segid, &mseg->len, &sysmem, NULL);
-       if (error || mseg->len == 0)
-               return (error);
-
-       if (!sysmem) {
-               SLIST_FOREACH(dsc, &sc->devmem, link) {
-                       if (dsc->segid == mseg->segid)
-                               break;
-               }
-               KASSERT(dsc != NULL, ("%s: devmem segment %d not found",
-                   __func__, mseg->segid));
-               error = copystr(dsc->name, mseg->name, len, NULL);
-       } else {
-               bzero(mseg->name, len);
-       }
-
-       return (error);
-}
-
-static int
-alloc_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg, size_t len)
-{
-       char *name;
-       int error;
-       bool sysmem;
-
-       error = 0;
-       name = NULL;
-       sysmem = true;
-
-       /*
-        * The allocation is lengthened by 1 to hold a terminating NUL.  It'll
-        * by stripped off when devfs processes the full string.
-        */
-       if (VM_MEMSEG_NAME(mseg)) {
-               sysmem = false;
-               name = malloc(len, M_VMMDEV, M_WAITOK);
-               error = copystr(mseg->name, name, len, NULL);
-               if (error)
-                       goto done;
-       }
-
-       error = vm_alloc_memseg(sc->vm, mseg->segid, mseg->len, sysmem);
-       if (error)
-               goto done;
-
-       if (VM_MEMSEG_NAME(mseg)) {
-               error = devmem_create_cdev(vm_name(sc->vm), mseg->segid, name);
-               if (error)
-                       vm_free_memseg(sc->vm, mseg->segid);
-               else
-                       name = NULL;    /* freed when 'cdev' is destroyed */
-       }
-done:
-       free(name, M_VMMDEV);
-       return (error);
-}
-
-static int
-vm_get_register_set(struct vcpu *vcpu, unsigned int count, int *regnum,
-    uint64_t *regval)
-{
-       int error, i;
-
-       error = 0;
-       for (i = 0; i < count; i++) {
-               error = vm_get_register(vcpu, regnum[i], &regval[i]);
-               if (error)
-                       break;
-       }
-       return (error);
-}
-
-static int
-vm_set_register_set(struct vcpu *vcpu, unsigned int count, int *regnum,
-    uint64_t *regval)
-{
-       int error, i;
-
-       error = 0;
-       for (i = 0; i < count; i++) {
-               error = vm_set_register(vcpu, regnum[i], regval[i]);
-               if (error)
-                       break;
-       }
-       return (error);
-}
-
-static int
-vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
-            struct thread *td)
-{
-       int error, vcpuid, size;
-       cpuset_t *cpuset;
-       struct vmmdev_softc *sc;
-       struct vcpu *vcpu;
-       struct vm_register *vmreg;
-       struct vm_seg_desc *vmsegdesc;
-       struct vm_register_set *vmregset;
-       struct vm_run *vmrun;
-#ifdef COMPAT_FREEBSD13
-       struct vm_run_13 *vmrun_13;
-#endif
-       struct vm_exception *vmexc;
-       struct vm_lapic_irq *vmirq;
-       struct vm_lapic_msi *vmmsi;
-       struct vm_ioapic_irq *ioapic_irq;
-       struct vm_isa_irq *isa_irq;
-       struct vm_isa_irq_trigger *isa_irq_trigger;
-       struct vm_capability *vmcap;
-       struct vm_pptdev *pptdev;
-       struct vm_pptdev_mmio *pptmmio;
-       struct vm_pptdev_msi *pptmsi;
-       struct vm_pptdev_msix *pptmsix;
-#ifdef COMPAT_FREEBSD13
-       struct vm_stats_old *vmstats_old;
-#endif
-       struct vm_stats *vmstats;
-       struct vm_stat_desc *statdesc;
-       struct vm_x2apic *x2apic;
-       struct vm_gpa_pte *gpapte;
-       struct vm_suspend *vmsuspend;
-       struct vm_gla2gpa *gg;
-       struct vm_cpuset *vm_cpuset;
-       struct vm_intinfo *vmii;
-       struct vm_rtc_time *rtctime;
-       struct vm_rtc_data *rtcdata;
-       struct vm_memmap *mm;
-       struct vm_munmap *mu;
-       struct vm_cpu_topology *topology;
-       struct vm_readwrite_kernemu_device *kernemu;
-       uint64_t *regvals;
-       int *regnums;
-       enum { NONE, SINGLE, ALL } vcpus_locked;
-       bool memsegs_locked;
-#ifdef BHYVE_SNAPSHOT
-       struct vm_snapshot_meta *snapshot_meta;
-#ifdef COMPAT_FREEBSD13
-       struct vm_snapshot_meta_old *snapshot_old;
-#endif
-#endif
-
-       error = vmm_priv_check(curthread->td_ucred);
-       if (error)
-               return (error);
-
-       sc = vmmdev_lookup2(cdev);
-       if (sc == NULL)
-               return (ENXIO);
-
-       vcpuid = -1;
-       vcpu = NULL;
-       vcpus_locked = NONE;
-       memsegs_locked = false;
-
-       /*
-        * For VMM ioctls that operate on a single vCPU, lookup the
-        * vcpu.  For VMM ioctls which require one or more vCPUs to
-        * not be running, lock necessary vCPUs.
-        *
-        * XXX fragile, handle with care
-        * Most of these assume that the first field of the ioctl data
-        * is the vcpuid.
-        */
-       switch (cmd) {
-       case VM_RUN:
-#ifdef COMPAT_FREEBSD13
-       case VM_RUN_13:
-#endif
-       case VM_GET_REGISTER:
-       case VM_SET_REGISTER:
-       case VM_GET_SEGMENT_DESCRIPTOR:
-       case VM_SET_SEGMENT_DESCRIPTOR:
-       case VM_GET_REGISTER_SET:
-       case VM_SET_REGISTER_SET:
-       case VM_INJECT_EXCEPTION:
-       case VM_GET_CAPABILITY:
-       case VM_SET_CAPABILITY:
-       case VM_SET_X2APIC_STATE:
-       case VM_GLA2GPA:
-       case VM_GLA2GPA_NOFAULT:
-       case VM_ACTIVATE_CPU:
-       case VM_SET_INTINFO:
-       case VM_GET_INTINFO:
-       case VM_RESTART_INSTRUCTION:
-       case VM_GET_KERNEMU_DEV:
-       case VM_SET_KERNEMU_DEV:
-               /*
-                * ioctls that can operate only on vcpus that are not running.
-                */
-               vcpuid = *(int *)data;
-               vcpu = vm_alloc_vcpu(sc->vm, vcpuid);
-               if (vcpu == NULL) {
-                       error = EINVAL;
-                       goto done;
-               }
-               error = vcpu_lock_one(vcpu);
-               if (error)
-                       goto done;
-               vcpus_locked = SINGLE;
-               break;
-
-#ifdef COMPAT_FREEBSD12
-       case VM_ALLOC_MEMSEG_FBSD12:
-#endif
-       case VM_ALLOC_MEMSEG:
-       case VM_BIND_PPTDEV:
-       case VM_UNBIND_PPTDEV:
-       case VM_MMAP_MEMSEG:
-       case VM_MUNMAP_MEMSEG:
-       case VM_REINIT:
-               /*
-                * ioctls that modify the memory map must lock memory
-                * segments exclusively.
-                */
-               vm_xlock_memsegs(sc->vm);
-               memsegs_locked = true;
-               /* FALLTHROUGH */
-       case VM_MAP_PPTDEV_MMIO:
-       case VM_UNMAP_PPTDEV_MMIO:
-#ifdef BHYVE_SNAPSHOT
-       case VM_SNAPSHOT_REQ:
-#ifdef COMPAT_FREEBSD13
-       case VM_SNAPSHOT_REQ_OLD:
-#endif
-       case VM_RESTORE_TIME:
-#endif
-               /*
-                * ioctls that operate on the entire virtual machine must
-                * prevent all vcpus from running.
-                */
-               error = vcpu_lock_all(sc);
-               if (error)
-                       goto done;
-               vcpus_locked = ALL;
-               break;
-
-#ifdef COMPAT_FREEBSD12
-       case VM_GET_MEMSEG_FBSD12:
-#endif
-       case VM_GET_MEMSEG:
-       case VM_MMAP_GETNEXT:
-               /*
-                * Lock the memory map while it is being inspected.
-                */
-               vm_slock_memsegs(sc->vm);
-               memsegs_locked = true;
-               break;
-
-#ifdef COMPAT_FREEBSD13
-       case VM_STATS_OLD:
-#endif
-       case VM_STATS:
-       case VM_INJECT_NMI:
-       case VM_LAPIC_IRQ:
-       case VM_GET_X2APIC_STATE:
-               /*
-                * These do not need the vCPU locked but do operate on
-                * a specific vCPU.
-                */
-               vcpuid = *(int *)data;
-               vcpu = vm_alloc_vcpu(sc->vm, vcpuid);
-               if (vcpu == NULL) {
-                       error = EINVAL;
-                       goto done;
-               }
-               break;
-
-       case VM_LAPIC_LOCAL_IRQ:
-       case VM_SUSPEND_CPU:
-       case VM_RESUME_CPU:
-               /*
-                * These can either operate on all CPUs via a vcpuid of
-                * -1 or on a specific vCPU.
-                */
-               vcpuid = *(int *)data;
-               if (vcpuid == -1)
-                       break;
-               vcpu = vm_alloc_vcpu(sc->vm, vcpuid);
-               if (vcpu == NULL) {
-                       error = EINVAL;
-                       goto done;
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       switch (cmd) {
-       case VM_RUN: {
-               struct vm_exit *vme;
-
-               vmrun = (struct vm_run *)data;
-               vme = vm_exitinfo(vcpu);
-
-               error = vm_run(vcpu);
-               if (error != 0)
-                       break;
-
-               error = copyout(vme, vmrun->vm_exit, sizeof(*vme));
-               if (error != 0)
-                       break;
-               if (vme->exitcode == VM_EXITCODE_IPI) {
-                       error = copyout(vm_exitinfo_cpuset(vcpu),
-                           vmrun->cpuset,
-                           min(vmrun->cpusetsize, sizeof(cpuset_t)));
-                       if (error != 0)
-                               break;
-                       if (sizeof(cpuset_t) < vmrun->cpusetsize) {
-                               uint8_t *p;
-
-                               p = (uint8_t *)vmrun->cpuset +
-                                   sizeof(cpuset_t);
-                               while (p < (uint8_t *)vmrun->cpuset +
-                                   vmrun->cpusetsize) {
-                                       if (subyte(p++, 0) != 0) {
-                                               error = EFAULT;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               break;
-       }
-#ifdef COMPAT_FREEBSD13
-       case VM_RUN_13: {
-               struct vm_exit *vme;
-               struct vm_exit_13 *vme_13;
-
-               vmrun_13 = (struct vm_run_13 *)data;
-               vme_13 = &vmrun_13->vm_exit;
-               vme = vm_exitinfo(vcpu);
-
-               error = vm_run(vcpu);
-               if (error == 0) {
-                       vme_13->exitcode = vme->exitcode;
-                       vme_13->inst_length = vme->inst_length;
-                       vme_13->rip = vme->rip;
-                       memcpy(vme_13->u, &vme->u, sizeof(vme_13->u));
-                       if (vme->exitcode == VM_EXITCODE_IPI) {
-                               struct vm_exit_ipi_13 *ipi;
-                               cpuset_t *dmask;
-                               int cpu;
-
-                               dmask = vm_exitinfo_cpuset(vcpu);
-                               ipi = (struct vm_exit_ipi_13 *)&vme_13->u[0];
-                               BIT_ZERO(256, &ipi->dmask);
-                               CPU_FOREACH_ISSET(cpu, dmask) {
-                                       if (cpu >= 256)
-                                               break;
-                                       BIT_SET(256, cpu, &ipi->dmask);
-                               }
-                       }
-               }
-               break;
-       }
-#endif
-       case VM_SUSPEND:
-               vmsuspend = (struct vm_suspend *)data;
-               error = vm_suspend(sc->vm, vmsuspend->how);
-               break;
-       case VM_REINIT:
-               error = vm_reinit(sc->vm);
-               break;
-       case VM_STAT_DESC: {
-               statdesc = (struct vm_stat_desc *)data;
-               error = vmm_stat_desc_copy(statdesc->index,
-                                       statdesc->desc, sizeof(statdesc->desc));
-               break;
-       }
-#ifdef COMPAT_FREEBSD13
-       case VM_STATS_OLD:
-               vmstats_old = (struct vm_stats_old *)data;
-               getmicrotime(&vmstats_old->tv);
-               error = vmm_stat_copy(vcpu, 0,
-                                     nitems(vmstats_old->statbuf),
-                                     &vmstats_old->num_entries,
-                                     vmstats_old->statbuf);
-               break;
-#endif
-       case VM_STATS: {
-               vmstats = (struct vm_stats *)data;
-               getmicrotime(&vmstats->tv);
-               error = vmm_stat_copy(vcpu, vmstats->index,
-                                     nitems(vmstats->statbuf),
-                                     &vmstats->num_entries, vmstats->statbuf);
-               break;
-       }
-       case VM_PPTDEV_MSI:
-               pptmsi = (struct vm_pptdev_msi *)data;
-               error = ppt_setup_msi(sc->vm,
-                                     pptmsi->bus, pptmsi->slot, pptmsi->func,
-                                     pptmsi->addr, pptmsi->msg,
-                                     pptmsi->numvec);
-               break;
-       case VM_PPTDEV_MSIX:
-               pptmsix = (struct vm_pptdev_msix *)data;
-               error = ppt_setup_msix(sc->vm,
-                                      pptmsix->bus, pptmsix->slot, 
-                                      pptmsix->func, pptmsix->idx,
-                                      pptmsix->addr, pptmsix->msg,
-                                      pptmsix->vector_control);
-               break;
-       case VM_PPTDEV_DISABLE_MSIX:
-               pptdev = (struct vm_pptdev *)data;
-               error = ppt_disable_msix(sc->vm, pptdev->bus, pptdev->slot,
-                                        pptdev->func);
-               break;
-       case VM_MAP_PPTDEV_MMIO:
-               pptmmio = (struct vm_pptdev_mmio *)data;
-               error = ppt_map_mmio(sc->vm, pptmmio->bus, pptmmio->slot,
-                                    pptmmio->func, pptmmio->gpa, pptmmio->len,
-                                    pptmmio->hpa);
-               break;
-       case VM_UNMAP_PPTDEV_MMIO:
-               pptmmio = (struct vm_pptdev_mmio *)data;
-               error = ppt_unmap_mmio(sc->vm, pptmmio->bus, pptmmio->slot,
-                                      pptmmio->func, pptmmio->gpa, 
pptmmio->len);
-               break;
-       case VM_BIND_PPTDEV:
-               pptdev = (struct vm_pptdev *)data;
-               error = vm_assign_pptdev(sc->vm, pptdev->bus, pptdev->slot,
-                                        pptdev->func);
-               break;
-       case VM_UNBIND_PPTDEV:
-               pptdev = (struct vm_pptdev *)data;
-               error = vm_unassign_pptdev(sc->vm, pptdev->bus, pptdev->slot,
-                                          pptdev->func);
-               break;
-       case VM_INJECT_EXCEPTION:
-               vmexc = (struct vm_exception *)data;
-               error = vm_inject_exception(vcpu,
-                   vmexc->vector, vmexc->error_code_valid, vmexc->error_code,
-                   vmexc->restart_instruction);
-               break;
-       case VM_INJECT_NMI:
-               error = vm_inject_nmi(vcpu);
-               break;
-       case VM_LAPIC_IRQ:
-               vmirq = (struct vm_lapic_irq *)data;
-               error = lapic_intr_edge(vcpu, vmirq->vector);
-               break;
-       case VM_LAPIC_LOCAL_IRQ:
-               vmirq = (struct vm_lapic_irq *)data;
-               error = lapic_set_local_intr(sc->vm, vcpu, vmirq->vector);
-               break;
-       case VM_LAPIC_MSI:
-               vmmsi = (struct vm_lapic_msi *)data;
-               error = lapic_intr_msi(sc->vm, vmmsi->addr, vmmsi->msg);
-               break;
-       case VM_IOAPIC_ASSERT_IRQ:
-               ioapic_irq = (struct vm_ioapic_irq *)data;
-               error = vioapic_assert_irq(sc->vm, ioapic_irq->irq);
-               break;
-       case VM_IOAPIC_DEASSERT_IRQ:
-               ioapic_irq = (struct vm_ioapic_irq *)data;
-               error = vioapic_deassert_irq(sc->vm, ioapic_irq->irq);
-               break;
-       case VM_IOAPIC_PULSE_IRQ:
-               ioapic_irq = (struct vm_ioapic_irq *)data;
-               error = vioapic_pulse_irq(sc->vm, ioapic_irq->irq);
-               break;
-       case VM_IOAPIC_PINCOUNT:
-               *(int *)data = vioapic_pincount(sc->vm);
-               break;
-       case VM_SET_KERNEMU_DEV:
-       case VM_GET_KERNEMU_DEV: {
-               mem_region_write_t mwrite;
-               mem_region_read_t mread;
-               bool arg;
-
-               kernemu = (void *)data;
-
-               if (kernemu->access_width > 0)
-                       size = (1u << kernemu->access_width);
-               else
-                       size = 1;
-
-               if (kernemu->gpa >= DEFAULT_APIC_BASE && kernemu->gpa < 
DEFAULT_APIC_BASE + PAGE_SIZE) {
-                       mread = lapic_mmio_read;
-                       mwrite = lapic_mmio_write;
-               } else if (kernemu->gpa >= VIOAPIC_BASE && kernemu->gpa < 
VIOAPIC_BASE + VIOAPIC_SIZE) {
-                       mread = vioapic_mmio_read;
-                       mwrite = vioapic_mmio_write;
-               } else if (kernemu->gpa >= VHPET_BASE && kernemu->gpa < 
VHPET_BASE + VHPET_SIZE) {
-                       mread = vhpet_mmio_read;
-                       mwrite = vhpet_mmio_write;
-               } else {
-                       error = EINVAL;
-                       break;
-               }
-
-               if (cmd == VM_SET_KERNEMU_DEV)
-                       error = mwrite(vcpu, kernemu->gpa,
-                           kernemu->value, size, &arg);
-               else
-                       error = mread(vcpu, kernemu->gpa,
-                           &kernemu->value, size, &arg);
-               break;
-               }
-       case VM_ISA_ASSERT_IRQ:
-               isa_irq = (struct vm_isa_irq *)data;
-               error = vatpic_assert_irq(sc->vm, isa_irq->atpic_irq);
-               if (error == 0 && isa_irq->ioapic_irq != -1)
-                       error = vioapic_assert_irq(sc->vm,
-                           isa_irq->ioapic_irq);
-               break;
-       case VM_ISA_DEASSERT_IRQ:
-               isa_irq = (struct vm_isa_irq *)data;
-               error = vatpic_deassert_irq(sc->vm, isa_irq->atpic_irq);
-               if (error == 0 && isa_irq->ioapic_irq != -1)
-                       error = vioapic_deassert_irq(sc->vm,
-                           isa_irq->ioapic_irq);
-               break;
-       case VM_ISA_PULSE_IRQ:
-               isa_irq = (struct vm_isa_irq *)data;
-               error = vatpic_pulse_irq(sc->vm, isa_irq->atpic_irq);
-               if (error == 0 && isa_irq->ioapic_irq != -1)
-                       error = vioapic_pulse_irq(sc->vm, isa_irq->ioapic_irq);
-               break;
-       case VM_ISA_SET_IRQ_TRIGGER:
-               isa_irq_trigger = (struct vm_isa_irq_trigger *)data;
-               error = vatpic_set_irq_trigger(sc->vm,
-                   isa_irq_trigger->atpic_irq, isa_irq_trigger->trigger);
-               break;
-       case VM_MMAP_GETNEXT:
-               mm = (struct vm_memmap *)data;
-               error = vm_mmap_getnext(sc->vm, &mm->gpa, &mm->segid,
-                   &mm->segoff, &mm->len, &mm->prot, &mm->flags);
-               break;
-       case VM_MMAP_MEMSEG:
-               mm = (struct vm_memmap *)data;
-               error = vm_mmap_memseg(sc->vm, mm->gpa, mm->segid, mm->segoff,
-                   mm->len, mm->prot, mm->flags);
-               break;
-       case VM_MUNMAP_MEMSEG:
-               mu = (struct vm_munmap *)data;
-               error = vm_munmap_memseg(sc->vm, mu->gpa, mu->len);
-               break;
-#ifdef COMPAT_FREEBSD12
-       case VM_ALLOC_MEMSEG_FBSD12:
-               error = alloc_memseg(sc, (struct vm_memseg *)data,
-                   sizeof(((struct vm_memseg_fbsd12 *)0)->name));
-               break;
-#endif
-       case VM_ALLOC_MEMSEG:
-               error = alloc_memseg(sc, (struct vm_memseg *)data,
-                   sizeof(((struct vm_memseg *)0)->name));
-               break;
-#ifdef COMPAT_FREEBSD12
-       case VM_GET_MEMSEG_FBSD12:
-               error = get_memseg(sc, (struct vm_memseg *)data,
-                   sizeof(((struct vm_memseg_fbsd12 *)0)->name));
-               break;
-#endif
-       case VM_GET_MEMSEG:
-               error = get_memseg(sc, (struct vm_memseg *)data,
-                   sizeof(((struct vm_memseg *)0)->name));
-               break;
-       case VM_GET_REGISTER:
-               vmreg = (struct vm_register *)data;
-               error = vm_get_register(vcpu, vmreg->regnum, &vmreg->regval);
-               break;
-       case VM_SET_REGISTER:
-               vmreg = (struct vm_register *)data;
-               error = vm_set_register(vcpu, vmreg->regnum, vmreg->regval);
-               break;
-       case VM_SET_SEGMENT_DESCRIPTOR:
-               vmsegdesc = (struct vm_seg_desc *)data;
-               error = vm_set_seg_desc(vcpu,
-                                       vmsegdesc->regnum,
-                                       &vmsegdesc->desc);
-               break;
-       case VM_GET_SEGMENT_DESCRIPTOR:
-               vmsegdesc = (struct vm_seg_desc *)data;
-               error = vm_get_seg_desc(vcpu,
-                                       vmsegdesc->regnum,
-                                       &vmsegdesc->desc);
-               break;
-       case VM_GET_REGISTER_SET:
-               vmregset = (struct vm_register_set *)data;
-               if (vmregset->count > VM_REG_LAST) {
-                       error = EINVAL;
-                       break;
-               }
*** 1979 LINES SKIPPED ***

Reply via email to