aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/mmc/mmcsd.c8
-rw-r--r--sys/dev/nvme/nvme_ns.c14
-rw-r--r--sys/dev/thunderbolt/tb_pcib.c14
-rw-r--r--sys/dev/virtio/virtqueue.c3
-rw-r--r--sys/dev/vmm/vmm_dev.c91
-rw-r--r--sys/dev/vmm/vmm_dev.h19
-rw-r--r--sys/dev/vmm/vmm_param.h33
7 files changed, 159 insertions, 23 deletions
diff --git a/sys/dev/mmc/mmcsd.c b/sys/dev/mmc/mmcsd.c
index 5b9cb93c7b31..f2965048b285 100644
--- a/sys/dev/mmc/mmcsd.c
+++ b/sys/dev/mmc/mmcsd.c
@@ -1422,7 +1422,7 @@ mmcsd_task(void *arg)
struct mmcsd_softc *sc;
struct bio *bp;
device_t dev, mmcbus;
- int bio_error, err, sz;
+ int abio_error, err, sz;
part = arg;
sc = part->sc;
@@ -1430,7 +1430,7 @@ mmcsd_task(void *arg)
mmcbus = sc->mmcbus;
while (1) {
- bio_error = 0;
+ abio_error = 0;
MMCSD_DISK_LOCK(part);
do {
if (part->running == 0)
@@ -1475,11 +1475,11 @@ mmcsd_task(void *arg)
} else if (bp->bio_cmd == BIO_DELETE)
block = mmcsd_delete(part, bp);
else
- bio_error = EOPNOTSUPP;
+ abio_error = EOPNOTSUPP;
release:
MMCBUS_RELEASE_BUS(mmcbus, dev);
if (block < end) {
- bp->bio_error = (bio_error == 0) ? EIO : bio_error;
+ bp->bio_error = (abio_error == 0) ? EIO : abio_error;
bp->bio_resid = (end - block) * sz;
bp->bio_flags |= BIO_ERROR;
} else
diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c
index f4a588373c98..17684cc14ba2 100644
--- a/sys/dev/nvme/nvme_ns.c
+++ b/sys/dev/nvme/nvme_ns.c
@@ -45,7 +45,7 @@
#include "nvme_private.h"
#include "nvme_linux.h"
-static void nvme_bio_child_inbed(struct bio *parent, int bio_error);
+static void nvme_bio_child_inbed(struct bio *parent, int abio_error);
static void nvme_bio_child_done(void *arg,
const struct nvme_completion *cpl);
static uint32_t nvme_get_num_segments(uint64_t addr, uint64_t size,
@@ -275,14 +275,14 @@ nvme_ns_bio_done(void *arg, const struct nvme_completion *status)
}
static void
-nvme_bio_child_inbed(struct bio *parent, int bio_error)
+nvme_bio_child_inbed(struct bio *parent, int abio_error)
{
struct nvme_completion parent_cpl;
int children, inbed;
- if (bio_error != 0) {
+ if (abio_error != 0) {
parent->bio_flags |= BIO_ERROR;
- parent->bio_error = bio_error;
+ parent->bio_error = abio_error;
}
/*
@@ -309,12 +309,12 @@ nvme_bio_child_done(void *arg, const struct nvme_completion *cpl)
{
struct bio *child = arg;
struct bio *parent;
- int bio_error;
+ int abio_error;
parent = child->bio_parent;
g_destroy_bio(child);
- bio_error = nvme_completion_is_error(cpl) ? EIO : 0;
- nvme_bio_child_inbed(parent, bio_error);
+ abio_error = nvme_completion_is_error(cpl) ? EIO : 0;
+ nvme_bio_child_inbed(parent, abio_error);
}
static uint32_t
diff --git a/sys/dev/thunderbolt/tb_pcib.c b/sys/dev/thunderbolt/tb_pcib.c
index 00738984ad1c..bc4fc1ce00ec 100644
--- a/sys/dev/thunderbolt/tb_pcib.c
+++ b/sys/dev/thunderbolt/tb_pcib.c
@@ -557,8 +557,20 @@ static int
tb_pci_probe(device_t dev)
{
struct tb_pcib_ident *n;
+ device_t parent;
+ devclass_t dc;
- if ((n = tb_pcib_find_ident(device_get_parent(dev))) != NULL) {
+ /*
+ * This driver is only valid if the parent device is a PCI-PCI
+ * bridge. To determine that, check if the grandparent is a
+ * PCI bus.
+ */
+ parent = device_get_parent(dev);
+ dc = device_get_devclass(device_get_parent(parent));
+ if (strcmp(devclass_get_name(dc), "pci") != 0)
+ return (ENXIO);
+
+ if ((n = tb_pcib_find_ident(parent)) != NULL) {
switch (n->flags & TB_GEN_MASK) {
case TB_GEN_TB1:
device_set_desc(dev, "Thunderbolt 1 Link");
diff --git a/sys/dev/virtio/virtqueue.c b/sys/dev/virtio/virtqueue.c
index cc7a233d60ee..41e01549c8b2 100644
--- a/sys/dev/virtio/virtqueue.c
+++ b/sys/dev/virtio/virtqueue.c
@@ -580,7 +580,8 @@ virtqueue_dequeue(struct virtqueue *vq, uint32_t *len)
void *cookie;
uint16_t used_idx, desc_idx;
- if (vq->vq_used_cons_idx == vq_htog16(vq, vq->vq_ring.used->idx))
+ if (vq->vq_used_cons_idx ==
+ vq_htog16(vq, atomic_load_16(&vq->vq_ring.used->idx)))
return (NULL);
used_idx = vq->vq_used_cons_idx++ & (vq->vq_nentries - 1);
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
index ebbceb25b69e..d6543bf6534e 100644
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -14,9 +14,11 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mman.h>
+#include <sys/module.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/queue.h>
+#include <sys/smp.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/ucred.h>
@@ -78,6 +80,8 @@ struct vmmdev_softc {
int flags;
};
+static bool vmm_initialized = false;
+
static SLIST_HEAD(, vmmdev_softc) head;
static unsigned pr_allow_flag;
@@ -88,6 +92,10 @@ static MALLOC_DEFINE(M_VMMDEV, "vmmdev", "vmmdev");
SYSCTL_DECL(_hw_vmm);
+u_int vm_maxcpu;
+SYSCTL_UINT(_hw_vmm, OID_AUTO, maxcpu, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
+ &vm_maxcpu, 0, "Maximum number of vCPUs");
+
static void devmem_destroy(void *arg);
static int devmem_create_cdev(struct vmmdev_softc *sc, int id, char *devmem);
@@ -619,20 +627,16 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
}
error = domainset_populate(&domain, mask, mseg->ds_policy,
mseg->ds_mask_size);
- if (error) {
- free(mask, M_VMMDEV);
+ free(mask, M_VMMDEV);
+ if (error)
break;
- }
domainset = domainset_create(&domain);
if (domainset == NULL) {
error = EINVAL;
- free(mask, M_VMMDEV);
break;
}
- free(mask, M_VMMDEV);
}
error = alloc_memseg(sc, mseg, sizeof(mseg->name), domainset);
-
break;
}
case VM_GET_MEMSEG:
@@ -985,6 +989,9 @@ vmmdev_create(const char *name, struct ucred *cred)
struct vm *vm;
int error;
+ if (name == NULL || strlen(name) > VM_MAX_NAMELEN)
+ return (EINVAL);
+
sx_xlock(&vmmdev_mtx);
sc = vmmdev_lookup(name, cred);
if (sc != NULL) {
@@ -1025,6 +1032,9 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
char *buf;
int error, buflen;
+ if (!vmm_initialized)
+ return (ENXIO);
+
error = vmm_priv_check(req->td->td_ucred);
if (error != 0)
return (error);
@@ -1110,7 +1120,7 @@ static struct cdevsw vmmctlsw = {
.d_ioctl = vmmctl_ioctl,
};
-int
+static int
vmmdev_init(void)
{
int error;
@@ -1126,7 +1136,7 @@ vmmdev_init(void)
return (error);
}
-int
+static int
vmmdev_cleanup(void)
{
sx_xlock(&vmmdev_mtx);
@@ -1144,6 +1154,71 @@ vmmdev_cleanup(void)
}
static int
+vmm_handler(module_t mod, int what, void *arg)
+{
+ int error;
+
+ switch (what) {
+ case MOD_LOAD:
+ error = vmmdev_init();
+ if (error != 0)
+ break;
+
+ vm_maxcpu = mp_ncpus;
+ TUNABLE_INT_FETCH("hw.vmm.maxcpu", &vm_maxcpu);
+ if (vm_maxcpu > VM_MAXCPU) {
+ printf("vmm: vm_maxcpu clamped to %u\n", VM_MAXCPU);
+ vm_maxcpu = VM_MAXCPU;
+ }
+ if (vm_maxcpu == 0)
+ vm_maxcpu = 1;
+
+ error = vmm_modinit();
+ if (error == 0)
+ vmm_initialized = true;
+ else {
+ error = vmmdev_cleanup();
+ KASSERT(error == 0,
+ ("%s: vmmdev_cleanup failed: %d", __func__, error));
+ }
+ break;
+ case MOD_UNLOAD:
+ error = vmmdev_cleanup();
+ if (error == 0 && vmm_initialized) {
+ error = vmm_modcleanup();
+ if (error) {
+ /*
+ * Something bad happened - prevent new
+ * VMs from being created
+ */
+ vmm_initialized = false;
+ }
+ }
+ break;
+ default:
+ error = 0;
+ break;
+ }
+ return (error);
+}
+
+static moduledata_t vmm_kmod = {
+ "vmm",
+ vmm_handler,
+ NULL
+};
+
+/*
+ * vmm initialization has the following dependencies:
+ *
+ * - Initialization requires smp_rendezvous() and therefore must happen
+ * after SMP is fully functional (after SI_SUB_SMP).
+ * - vmm device initialization requires an initialized devfs.
+ */
+DECLARE_MODULE(vmm, vmm_kmod, MAX(SI_SUB_SMP, SI_SUB_DEVFS) + 1, SI_ORDER_ANY);
+MODULE_VERSION(vmm, 1);
+
+static int
devmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t len,
struct vm_object **objp, int nprot)
{
diff --git a/sys/dev/vmm/vmm_dev.h b/sys/dev/vmm/vmm_dev.h
index 2881a7063565..f14176c8afad 100644
--- a/sys/dev/vmm/vmm_dev.h
+++ b/sys/dev/vmm/vmm_dev.h
@@ -11,15 +11,19 @@
#include <sys/types.h>
#include <sys/ioccom.h>
+
#include <machine/vmm_dev.h>
+#include <dev/vmm/vmm_param.h>
+
#ifdef _KERNEL
struct thread;
struct vm;
struct vcpu;
-int vmmdev_init(void);
-int vmmdev_cleanup(void);
+int vmm_modinit(void);
+int vmm_modcleanup(void);
+
int vmmdev_machdep_ioctl(struct vm *vm, struct vcpu *vcpu, u_long cmd,
caddr_t data, int fflag, struct thread *td);
@@ -53,6 +57,17 @@ struct vmmdev_ioctl {
extern const struct vmmdev_ioctl vmmdev_machdep_ioctls[];
extern const size_t vmmdev_machdep_ioctl_count;
+/*
+ * Upper limit on vm_maxcpu. Limited by use of uint16_t types for CPU counts as
+ * well as range of vpid values for VT-x on amd64 and by the capacity of
+ * cpuset_t masks. The call to new_unrhdr() in vpid_init() in vmx.c requires
+ * 'vm_maxcpu + 1 <= 0xffff', hence the '- 1' below.
+ */
+#define VM_MAXCPU MIN(0xffff - 1, CPU_SETSIZE)
+
+/* Maximum number of vCPUs in a single VM. */
+extern u_int vm_maxcpu;
+
#endif /* _KERNEL */
struct vmmctl_vm_create {
diff --git a/sys/dev/vmm/vmm_param.h b/sys/dev/vmm/vmm_param.h
new file mode 100644
index 000000000000..a5040eb0f58c
--- /dev/null
+++ b/sys/dev/vmm/vmm_param.h
@@ -0,0 +1,33 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _DEV_VMM_PARAM_H_
+#define _DEV_VMM_PARAM_H_
+
+/*
+ * The VM name has to fit into the pathname length constraints of devfs,
+ * governed primarily by SPECNAMELEN. The length is the total number of
+ * characters in the full path, relative to the mount point and not
+ * including any leading '/' characters.
+ * A prefix and a suffix are added to the name specified by the user.
+ * The prefix is usually "vmm/" or "vmm.io/", but can be a few characters
+ * longer for future use.
+ * The suffix is a string that identifies a bootrom image or some similar
+ * image that is attached to the VM. A separator character gets added to
+ * the suffix automatically when generating the full path, so it must be
+ * accounted for, reducing the effective length by 1.
+ * The effective length of a VM name is 229 bytes for FreeBSD 13 and 37
+ * bytes for FreeBSD 12. A minimum length is set for safety and supports
+ * a SPECNAMELEN as small as 32 on old systems.
+ */
+#define VM_MAX_PREFIXLEN 10
+#define VM_MAX_SUFFIXLEN 15
+#define VM_MIN_NAMELEN 6
+#define VM_MAX_NAMELEN \
+ (SPECNAMELEN - VM_MAX_PREFIXLEN - VM_MAX_SUFFIXLEN - 1)
+
+#endif /* !_DEV_VMM_PARAM_H_ */