summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McDonald <danmcd@mnx.io>2022-06-15 13:44:36 -0400
committerDan McDonald <danmcd@mnx.io>2022-06-15 13:44:36 -0400
commit60c144394d29f66e3db1d244e6d0078f79c22e4f (patch)
tree817dcb6f545b07a7eafa22fc523ce50e1a1409fa
parentb66333d8fa2df710a3b017d364b027432453db40 (diff)
parent5c22bad5dcbd030d95aca36e1c2fb0f77b505e17 (diff)
downloadillumos-joyent-60c144394d29f66e3db1d244e6d0078f79c22e4f.tar.gz
[illumos-gate merge]
commit 5c22bad5dcbd030d95aca36e1c2fb0f77b505e17 14680 tem: add support for window manipulation functions commit e760f15095bdc9fa107e7c20ed2a5e4fb5865c1d 14732 split vtd out of vmm kernel module Conflicts: manifest
-rw-r--r--manifest3
-rw-r--r--usr/src/pkg/manifests/system-bhyve-tests.p5m1
-rw-r--r--usr/src/pkg/manifests/system-bhyve.p5m4
-rw-r--r--usr/src/test/bhyve-tests/tests/vmm/Makefile3
-rw-r--r--usr/src/test/bhyve-tests/tests/vmm/check_iommu.c45
-rw-r--r--usr/src/uts/common/io/conskbd.c11
-rw-r--r--usr/src/uts/common/io/tem.c3
-rw-r--r--usr/src/uts/common/io/tem_safe.c56
-rw-r--r--usr/src/uts/common/io/vcons.c2
-rw-r--r--usr/src/uts/common/sys/tem.h3
-rw-r--r--usr/src/uts/common/sys/tem_impl.h1
-rw-r--r--usr/src/uts/intel/Makefile.files5
-rw-r--r--usr/src/uts/intel/Makefile.intel1
-rw-r--r--usr/src/uts/intel/io/vmm/Makefile.vmm5
-rw-r--r--usr/src/uts/intel/io/vmm/amd/amdv.c148
-rw-r--r--usr/src/uts/intel/io/vmm/intel/vtd.c120
-rw-r--r--usr/src/uts/intel/io/vmm/intel/vtd_sol.c84
-rw-r--r--usr/src/uts/intel/io/vmm/io/iommu.c331
-rw-r--r--usr/src/uts/intel/io/vmm/io/iommu.h36
-rw-r--r--usr/src/uts/intel/io/vmm/sys/vmm_kernel.h2
-rw-r--r--usr/src/uts/intel/io/vmm/vmm.c50
-rw-r--r--usr/src/uts/intel/io/vmm/vmm.mapfile6
-rw-r--r--usr/src/uts/intel/io/vmm/vmm_sol_dev.c5
-rw-r--r--usr/src/uts/intel/io/vmm/vmm_vtd.mapfile45
-rw-r--r--usr/src/uts/intel/sys/vmm_dev.h1
-rw-r--r--usr/src/uts/intel/vmm_vtd/Makefile60
26 files changed, 552 insertions, 479 deletions
diff --git a/manifest b/manifest
index 4d2743249a..df07c985cf 100644
--- a/manifest
+++ b/manifest
@@ -5088,6 +5088,9 @@ d usr/kernel/kmdb 0755 root sys
d usr/kernel/kmdb/amd64 0755 root sys
f usr/kernel/kmdb/amd64/smbfs 0555 root sys
f usr/kernel/kmdb/amd64/smbsrv 0555 root sys
+d usr/kernel/misc 0755 root sys
+d usr/kernel/misc/amd64 0755 root sys
+f usr/kernel/misc/amd64/vmm_vtd 0755 root sys
d usr/kernel/sched 0755 root sys
d usr/kernel/sched/amd64 0755 root sys
f usr/kernel/sched/amd64/FSS 0755 root sys
diff --git a/usr/src/pkg/manifests/system-bhyve-tests.p5m b/usr/src/pkg/manifests/system-bhyve-tests.p5m
index e06f3fc817..1df6e67bd5 100644
--- a/usr/src/pkg/manifests/system-bhyve-tests.p5m
+++ b/usr/src/pkg/manifests/system-bhyve-tests.p5m
@@ -50,6 +50,7 @@ file path=opt/bhyve-tests/tests/mevent/read_requeue mode=0555
file path=opt/bhyve-tests/tests/mevent/vnode_file mode=0555
file path=opt/bhyve-tests/tests/mevent/vnode_zvol mode=0555
dir path=opt/bhyve-tests/tests/vmm
+file path=opt/bhyve-tests/tests/vmm/check_iommu mode=0555
file path=opt/bhyve-tests/tests/vmm/fpu_getset mode=0555
file path=opt/bhyve-tests/tests/vmm/interface_version mode=0555
file path=opt/bhyve-tests/tests/vmm/mem_devmem mode=0555
diff --git a/usr/src/pkg/manifests/system-bhyve.p5m b/usr/src/pkg/manifests/system-bhyve.p5m
index ae95d62061..84e74d27cb 100644
--- a/usr/src/pkg/manifests/system-bhyve.p5m
+++ b/usr/src/pkg/manifests/system-bhyve.p5m
@@ -16,6 +16,7 @@
#
# Copyright 2018 Joyent, Inc.
# Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
+# Copyright 2022 Oxide Computer Company
#
#
@@ -40,6 +41,9 @@ file path=usr/kernel/drv/$(ARCH64)/vmm
file path=usr/kernel/drv/ppt.conf
file path=usr/kernel/drv/viona.conf
file path=usr/kernel/drv/vmm.conf
+dir path=usr/kernel/misc group=sys
+dir path=usr/kernel/misc/$(ARCH64) group=sys
+file path=usr/kernel/misc/$(ARCH64)/vmm_vtd mode=0755
file path=usr/lib/rsrvrctl mode=0555
dir path=usr/sbin
file path=usr/sbin/bhyve mode=0555
diff --git a/usr/src/test/bhyve-tests/tests/vmm/Makefile b/usr/src/test/bhyve-tests/tests/vmm/Makefile
index eeca882915..e774f5f6c0 100644
--- a/usr/src/test/bhyve-tests/tests/vmm/Makefile
+++ b/usr/src/test/bhyve-tests/tests/vmm/Makefile
@@ -19,7 +19,8 @@ PROG = mem_partial \
mem_seg_map \
mem_devmem \
fpu_getset \
- interface_version
+ interface_version \
+ check_iommu
COMMON_OBJS = common.o
CLEAN_OBJS = $(PROG:%=%.o)
diff --git a/usr/src/test/bhyve-tests/tests/vmm/check_iommu.c b/usr/src/test/bhyve-tests/tests/vmm/check_iommu.c
new file mode 100644
index 0000000000..1b7ffb01a8
--- /dev/null
+++ b/usr/src/test/bhyve-tests/tests/vmm/check_iommu.c
@@ -0,0 +1,45 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2022 Oxide Computer Company
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <libgen.h>
+
+#include <sys/vmm.h>
+#include <sys/vmm_dev.h>
+
+int
+main(int argc, char *argv[])
+{
+ const char *suite_name = basename(argv[0]);
+
+ int ctl_fd = open(VMM_CTL_DEV, O_EXCL | O_RDWR);
+ if (ctl_fd < 0) {
+ perror("could not open vmmctl device");
+ return (EXIT_FAILURE);
+ }
+
+ int res = ioctl(ctl_fd, VMM_CHECK_IOMMU, 0);
+ if (res < 0) {
+ perror("VMM_CHECK_IOMMU ioctl failed");
+ return (EXIT_FAILURE);
+ }
+
+ (void) close(ctl_fd);
+ (void) printf("%s\tPASS\n", suite_name);
+ return (0);
+}
diff --git a/usr/src/uts/common/io/conskbd.c b/usr/src/uts/common/io/conskbd.c
index feaf659d33..03188b3a6c 100644
--- a/usr/src/uts/common/io/conskbd.c
+++ b/usr/src/uts/common/io/conskbd.c
@@ -149,7 +149,7 @@ static struct qinit conskbdlrinit = {
/* lower write processing procedures structures */
static struct qinit conskbdlwinit = {
putq, /* qi_putp */
- conskbdlwserv, /* qi_srvp */
+ conskbdlwserv, /* qi_srvp */
(int (*)())NULL, /* qi_qopen */
(int (*)())NULL, /* qi_qclose */
(int (*)())NULL, /* qi_qadmin */
@@ -1131,6 +1131,15 @@ conskbdlrput(queue_t *q, mblk_t *mp)
DPRINTF(PRINT_L1, PRINT_MASK_ALL, ("conskbdlrput\n"));
switch (mp->b_datap->db_type) {
+ case M_CTL:
+ mp->b_datap->db_type = M_DATA;
+ if (conskbd.conskbd_directio)
+ putnext(conskbd_regqueue, mp);
+ else if (conskbd_consqueue != NULL)
+ putnext(conskbd_consqueue, mp);
+ else
+ freemsg(mp);
+ break;
case M_FLUSH:
if (*mp->b_rptr == FLUSHR) {
diff --git a/usr/src/uts/common/io/tem.c b/usr/src/uts/common/io/tem.c
index 42b34ab37c..7c34655bd6 100644
--- a/usr/src/uts/common/io/tem.c
+++ b/usr/src/uts/common/io/tem.c
@@ -276,7 +276,7 @@ tem_initialized(tem_vt_state_t tem_arg)
}
tem_vt_state_t
-tem_init(cred_t *credp)
+tem_init(cred_t *credp, queue_t *rq)
{
struct tem_vt_state *ptem;
@@ -288,6 +288,7 @@ tem_init(cred_t *credp)
ptem->tvs_isactive = B_FALSE;
ptem->tvs_fbmode = KD_TEXT;
+ ptem->tvs_queue = rq;
/*
* A tem is regarded as initialized only after tem_internal_init(),
diff --git a/usr/src/uts/common/io/tem_safe.c b/usr/src/uts/common/io/tem_safe.c
index 41f93c42be..04e598f994 100644
--- a/usr/src/uts/common/io/tem_safe.c
+++ b/usr/src/uts/common/io/tem_safe.c
@@ -845,6 +845,57 @@ tem_safe_selgraph(struct tem_vt_state *tem)
}
/*
+ * Handle window manipulation.
+ */
+static void
+tem_safe_window(struct tem_vt_state *tem, enum called_from called_from)
+{
+ int curparam;
+ int param;
+ int index = 0;
+ mblk_t *bp;
+ size_t len;
+ char buf[27];
+
+ tem->tvs_state = A_STATE_START;
+ curparam = tem->tvs_curparam;
+ do {
+ param = tem->tvs_params[index];
+
+ switch (param) {
+ case 8: /* Resize window to Ps2 lines and Ps3 columns. */
+ /* We ignore this */
+ index += 2;
+ curparam -= 2;
+ break;
+
+ case 18: /* Reports terminal size in characters. */
+ if (called_from == CALLED_FROM_STANDALONE)
+ break;
+ if (!canputnext(tem->tvs_queue))
+ break;
+
+ /* Response: CSI 8 ; lines ; columns t */
+ len = snprintf(buf, sizeof (buf), "%c[8;%u;%ut",
+ 0x1b, tems.ts_c_dimension.height,
+ tems.ts_c_dimension.width);
+
+ bp = allocb(len, BPRI_HI);
+ if (bp != NULL) {
+ bp->b_datap->db_type = M_CTL;
+ bcopy(buf, bp->b_wptr, len);
+ bp->b_wptr += len;
+ (void) putnext(tem->tvs_queue, bp);
+ }
+ break;
+ }
+
+ index++;
+ curparam--;
+ } while (curparam > 0);
+}
+
+/*
* perform the appropriate action for the escape sequence
*
* General rule: This code does not validate the arguments passed.
@@ -1080,6 +1131,11 @@ tem_safe_chkparam(struct tem_vt_state *tem, tem_char_t ch, cred_t *credp,
credp, called_from);
break;
+ case 't':
+ tem_safe_send_data(tem, credp, called_from);
+ tem_safe_window(tem, called_from);
+ break;
+
case 'X': /* erase char */
tem_safe_setparam(tem, 1, 1);
tem_safe_clear_chars(tem,
diff --git a/usr/src/uts/common/io/vcons.c b/usr/src/uts/common/io/vcons.c
index 5d7a1c67d0..54d0b76b1c 100644
--- a/usr/src/uts/common/io/vcons.c
+++ b/usr/src/uts/common/io/vcons.c
@@ -351,7 +351,7 @@ vt_open(minor_t minor, queue_t *rq, cred_t *crp)
* vc_tem might not be intialized if !tems.ts_initialized,
* and this only happens during console configuration.
*/
- pvc->vc_tem = tem_init(crp);
+ pvc->vc_tem = tem_init(crp, rq);
}
if (!(pvc->vc_flags & WCS_INIT))
diff --git a/usr/src/uts/common/sys/tem.h b/usr/src/uts/common/sys/tem.h
index 6fa3ca01a3..549c2c4deb 100644
--- a/usr/src/uts/common/sys/tem.h
+++ b/usr/src/uts/common/sys/tem.h
@@ -33,6 +33,7 @@ extern "C" {
#ifdef _KERNEL
+#include <sys/stream.h>
#include <sys/visual_io.h>
#include <sys/cred.h>
#include <sys/beep.h>
@@ -44,7 +45,7 @@ typedef struct __tem_vt_state *tem_vt_state_t;
boolean_t tem_initialized(tem_vt_state_t);
-tem_vt_state_t tem_init(cred_t *);
+tem_vt_state_t tem_init(cred_t *, queue_t *);
void tem_destroy(tem_vt_state_t, cred_t *);
diff --git a/usr/src/uts/common/sys/tem_impl.h b/usr/src/uts/common/sys/tem_impl.h
index 8af55ab75f..202eebb45b 100644
--- a/usr/src/uts/common/sys/tem_impl.h
+++ b/usr/src/uts/common/sys/tem_impl.h
@@ -187,6 +187,7 @@ typedef struct term_char {
* State structure for each virtual terminal emulator
*/
struct tem_vt_state {
+ queue_t *tvs_queue; /* read queue for console */
kmutex_t tvs_lock;
uchar_t tvs_fbmode; /* framebuffer mode */
uchar_t tvs_alpha; /* rgb alpha channel */
diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files
index c062f7400f..4df166d8ef 100644
--- a/usr/src/uts/intel/Makefile.files
+++ b/usr/src/uts/intel/Makefile.files
@@ -475,3 +475,8 @@ VIONA_OBJS = \
# bhyve PCI-passthru
#
PPT_OBJS = ppt.o
+
+#
+# bhyve VT-d
+#
+VMM_VTD_OBJS = vtd.o
diff --git a/usr/src/uts/intel/Makefile.intel b/usr/src/uts/intel/Makefile.intel
index 8a5adf6f19..79f4c3f26b 100644
--- a/usr/src/uts/intel/Makefile.intel
+++ b/usr/src/uts/intel/Makefile.intel
@@ -770,3 +770,4 @@ DRV_KMODS += viona
# bhyve PCI-passthru
#
DRV_KMODS += ppt
+DRV_KMODS += vmm_vtd
diff --git a/usr/src/uts/intel/io/vmm/Makefile.vmm b/usr/src/uts/intel/io/vmm/Makefile.vmm
index 84ef0548d9..d7c26183fc 100644
--- a/usr/src/uts/intel/io/vmm/Makefile.vmm
+++ b/usr/src/uts/intel/io/vmm/Makefile.vmm
@@ -29,7 +29,7 @@ AS_INC_PATH += -I$(UTSBASE)/intel/io/vmm -I$(OBJS_DIR)
# enable collection of VMM statistics
CFLAGS += -DVMM_KEEP_STATS
-LDFLAGS += -N misc/acpica -N misc/pcie -N fs/dev
+LDFLAGS += -N misc/pcie -N fs/dev
LDFLAGS += -M $(MAPFILE)
# devmem span calculations currently run afoul of overflow checks
@@ -66,13 +66,10 @@ VMM_OBJS = \
vmx_msr.o \
vmx.o \
vmx_support.o \
- vtd.o \
- vtd_sol.o \
svm.o \
svm_msr.o \
vmcb.o \
svm_support.o \
- amdv.o \
vmm_gpt.o \
seg_vmm.o \
vmm_reservoir.o \
diff --git a/usr/src/uts/intel/io/vmm/amd/amdv.c b/usr/src/uts/intel/io/vmm/amd/amdv.c
deleted file mode 100644
index b056ab86d2..0000000000
--- a/usr/src/uts/intel/io/vmm/amd/amdv.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * 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$
- */
-/*
- * This file and its contents are supplied under the terms of the
- * Common Development and Distribution License ("CDDL"), version 1.0.
- * You may only use this file in accordance with the terms of version
- * 1.0 of the CDDL.
- *
- * A full copy of the text of the CDDL should have accompanied this
- * source. A copy of the CDDL is also available via the Internet at
- * http://www.illumos.org/license/CDDL.
- *
- * Copyright 2014 Pluribus Networks Inc.
- * Copyright 2017 Joyent, Inc.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/errno.h>
-
-#include <machine/vmm.h>
-#include "io/iommu.h"
-
-static int
-amd_iommu_init(void)
-{
-
- printf("amd_iommu_init: not implemented\n");
- return (ENXIO);
-}
-
-static void
-amd_iommu_cleanup(void)
-{
-
- printf("amd_iommu_cleanup: not implemented\n");
-}
-
-static void
-amd_iommu_enable(void)
-{
-
- printf("amd_iommu_enable: not implemented\n");
-}
-
-static void
-amd_iommu_disable(void)
-{
-
- printf("amd_iommu_disable: not implemented\n");
-}
-
-static void *
-amd_iommu_create_domain(vm_paddr_t maxaddr)
-{
-
- printf("amd_iommu_create_domain: not implemented\n");
- return (NULL);
-}
-
-static void
-amd_iommu_destroy_domain(void *domain)
-{
-
- printf("amd_iommu_destroy_domain: not implemented\n");
-}
-
-static uint64_t
-amd_iommu_create_mapping(void *domain, vm_paddr_t gpa, vm_paddr_t hpa,
- uint64_t len)
-{
-
- printf("amd_iommu_create_mapping: not implemented\n");
- return (0);
-}
-
-static uint64_t
-amd_iommu_remove_mapping(void *domain, vm_paddr_t gpa, uint64_t len)
-{
-
- printf("amd_iommu_remove_mapping: not implemented\n");
- return (0);
-}
-
-static void
-amd_iommu_add_device(void *domain, uint16_t rid)
-{
-
- printf("amd_iommu_add_device: not implemented\n");
-}
-
-static void
-amd_iommu_remove_device(void *domain, uint16_t rid)
-{
-
- printf("amd_iommu_remove_device: not implemented\n");
-}
-
-static void
-amd_iommu_invalidate_tlb(void *domain)
-{
-
- printf("amd_iommu_invalidate_tlb: not implemented\n");
-}
-
-const struct iommu_ops iommu_ops_amd = {
- amd_iommu_init,
- amd_iommu_cleanup,
- amd_iommu_enable,
- amd_iommu_disable,
- amd_iommu_create_domain,
- amd_iommu_destroy_domain,
- amd_iommu_create_mapping,
- amd_iommu_remove_mapping,
- amd_iommu_add_device,
- amd_iommu_remove_device,
- amd_iommu_invalidate_tlb,
-};
diff --git a/usr/src/uts/intel/io/vmm/intel/vtd.c b/usr/src/uts/intel/io/vmm/intel/vtd.c
index 6f5e6626c8..d365b92163 100644
--- a/usr/src/uts/intel/io/vmm/intel/vtd.c
+++ b/usr/src/uts/intel/io/vmm/intel/vtd.c
@@ -27,6 +27,19 @@
*
* $FreeBSD$
*/
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * Copyright 2018 Joyent, Inc.
+ * Copyright 2022 Oxide Computer Company
+ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -124,9 +137,7 @@ static int drhd_num;
static struct vtdmap *vtdmaps[DRHD_MAX_UNITS];
static int max_domains;
typedef int (*drhd_ident_func_t)(void);
-#ifndef __FreeBSD__
-static dev_info_t *vtddips[DRHD_MAX_UNITS];
-#endif
+static dev_info_t *vtddips[DRHD_MAX_UNITS];
static uint64_t root_table[PAGE_SIZE / sizeof (uint64_t)] __aligned(4096);
static uint64_t ctx_tables[256][PAGE_SIZE / sizeof (uint64_t)] __aligned(4096);
@@ -342,12 +353,71 @@ vtd_unmap(dev_info_t *dip)
ddi_regs_map_free(&hdl);
}
-#ifndef __FreeBSD__
-/*
- * This lives in vtd_sol.c for license reasons.
- */
-extern dev_info_t *vtd_get_dip(ACPI_DMAR_HARDWARE_UNIT *, int);
-#endif
+static dev_info_t *
+vtd_get_dip(ACPI_DMAR_HARDWARE_UNIT *drhd, int unit)
+{
+ dev_info_t *dip;
+ struct ddi_parent_private_data *pdptr;
+ struct regspec reg;
+ int circ;
+
+ /*
+ * Try to find an existing devinfo node for this vtd unit.
+ */
+ ndi_devi_enter(ddi_root_node(), &circ);
+ dip = ddi_find_devinfo("vtd", unit, 0);
+ ndi_devi_exit(ddi_root_node(), circ);
+
+ if (dip != NULL)
+ return (dip);
+
+ /*
+ * None found, construct a devinfo node for this vtd unit.
+ */
+ dip = ddi_add_child(ddi_root_node(), "vtd",
+ DEVI_SID_NODEID, unit);
+
+ reg.regspec_bustype = 0;
+ reg.regspec_addr = drhd->Address;
+ reg.regspec_size = PAGE_SIZE;
+
+ /*
+ * update the reg properties
+ *
+ * reg property will be used for register
+ * set access
+ *
+ * refer to the bus_map of root nexus driver
+ * I/O or memory mapping:
+ *
+ * <bustype=0, addr=x, len=x>: memory
+ * <bustype=1, addr=x, len=x>: i/o
+ * <bustype>1, addr=0, len=x>: x86-compatibility i/o
+ */
+ (void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
+ dip, "reg", (int *)&reg,
+ sizeof (struct regspec) / sizeof (int));
+
+ /*
+ * This is an artificially constructed dev_info, and we
+ * need to set a few more things to be able to use it
+ * for ddi_dma_alloc_handle/free_handle.
+ */
+ ddi_set_driver(dip, ddi_get_driver(ddi_root_node()));
+ DEVI(dip)->devi_bus_dma_allochdl =
+ DEVI(ddi_get_driver((ddi_root_node())));
+
+ pdptr = kmem_zalloc(sizeof (struct ddi_parent_private_data)
+ + sizeof (struct regspec), KM_SLEEP);
+ pdptr->par_nreg = 1;
+ pdptr->par_reg = (struct regspec *)(pdptr + 1);
+ pdptr->par_reg->regspec_bustype = 0;
+ pdptr->par_reg->regspec_addr = drhd->Address;
+ pdptr->par_reg->regspec_size = PAGE_SIZE;
+ ddi_set_parent_data(dip, pdptr);
+
+ return (dip);
+}
static int
vtd_init(void)
@@ -859,7 +929,7 @@ vtd_destroy_domain(void *arg)
kmem_free(dom, sizeof (*dom));
}
-const struct iommu_ops iommu_ops_intel = {
+const struct iommu_ops vmm_iommu_ops = {
.init = vtd_init,
.cleanup = vtd_cleanup,
.enable = vtd_enable,
@@ -872,3 +942,33 @@ const struct iommu_ops iommu_ops_intel = {
.remove_device = vtd_remove_device,
.invalidate_tlb = vtd_invalidate_tlb,
};
+
+
+static struct modlmisc modlmisc = {
+ &mod_miscops,
+ "bhyve vmm vtd",
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1,
+ &modlmisc,
+ NULL
+};
+
+int
+_init(void)
+{
+ return (mod_install(&modlinkage));
+}
+
+int
+_fini(void)
+{
+ return (mod_remove(&modlinkage));
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&modlinkage, modinfop));
+}
diff --git a/usr/src/uts/intel/io/vmm/intel/vtd_sol.c b/usr/src/uts/intel/io/vmm/intel/vtd_sol.c
deleted file mode 100644
index 26c6c5b024..0000000000
--- a/usr/src/uts/intel/io/vmm/intel/vtd_sol.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * This file and its contents are supplied under the terms of the
- * Common Development and Distribution License ("CDDL"), version 1.0.
- * You may only use this file in accordance with the terms of version
- * 1.0 of the CDDL.
- *
- * A full copy of the text of the CDDL should have accompanied this
- * source. A copy of the CDDL is also available via the Internet at
- * http://www.illumos.org/license/CDDL.
- */
-/* This file is dual-licensed; see usr/src/contrib/bhyve/LICENSE */
-
-/*
- * Copyright 2018 Joyent, Inc.
- */
-
-#include <sys/sunndi.h>
-#include <contrib/dev/acpica/include/acpi.h>
-
-dev_info_t *
-vtd_get_dip(ACPI_DMAR_HARDWARE_UNIT *drhd, int unit)
-{
- dev_info_t *dip;
- struct ddi_parent_private_data *pdptr;
- struct regspec reg;
- int circ;
-
- /*
- * Try to find an existing devinfo node for this vtd unit.
- */
- ndi_devi_enter(ddi_root_node(), &circ);
- dip = ddi_find_devinfo("vtd", unit, 0);
- ndi_devi_exit(ddi_root_node(), circ);
-
- if (dip != NULL)
- return (dip);
-
- /*
- * None found, construct a devinfo node for this vtd unit.
- */
- dip = ddi_add_child(ddi_root_node(), "vtd",
- DEVI_SID_NODEID, unit);
-
- reg.regspec_bustype = 0;
- reg.regspec_addr = drhd->Address;
- reg.regspec_size = PAGE_SIZE;
-
- /*
- * update the reg properties
- *
- * reg property will be used for register
- * set access
- *
- * refer to the bus_map of root nexus driver
- * I/O or memory mapping:
- *
- * <bustype=0, addr=x, len=x>: memory
- * <bustype=1, addr=x, len=x>: i/o
- * <bustype>1, addr=0, len=x>: x86-compatibility i/o
- */
- (void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
- dip, "reg", (int *)&reg,
- sizeof (struct regspec) / sizeof (int));
-
- /*
- * This is an artificially constructed dev_info, and we
- * need to set a few more things to be able to use it
- * for ddi_dma_alloc_handle/free_handle.
- */
- ddi_set_driver(dip, ddi_get_driver(ddi_root_node()));
- DEVI(dip)->devi_bus_dma_allochdl =
- DEVI(ddi_get_driver((ddi_root_node())));
-
- pdptr = kmem_zalloc(sizeof (struct ddi_parent_private_data)
- + sizeof (struct regspec), KM_SLEEP);
- pdptr->par_nreg = 1;
- pdptr->par_reg = (struct regspec *)(pdptr + 1);
- pdptr->par_reg->regspec_bustype = 0;
- pdptr->par_reg->regspec_addr = drhd->Address;
- pdptr->par_reg->regspec_size = PAGE_SIZE;
- ddi_set_parent_data(dip, pdptr);
-
- return (dip);
-}
diff --git a/usr/src/uts/intel/io/vmm/io/iommu.c b/usr/src/uts/intel/io/vmm/io/iommu.c
index 3ebd394b99..8374a6da58 100644
--- a/usr/src/uts/intel/io/vmm/io/iommu.c
+++ b/usr/src/uts/intel/io/vmm/io/iommu.c
@@ -27,6 +27,18 @@
*
* $FreeBSD$
*/
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * Copyright 2022 Oxide Computer Company
+ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -50,132 +62,16 @@ __FBSDID("$FreeBSD$");
#include "vmm_util.h"
#include "iommu.h"
-static int iommu_avail;
-static int iommu_enable = 1;
+static kmutex_t iommu_lock;
+static uint_t iommu_refcnt;
+ddi_modhandle_t iommu_modhdl;
static const struct iommu_ops *ops;
static void *host_domain;
-#ifdef __FreeBSD__
-static eventhandler_tag add_tag, delete_tag;
-#endif
-#ifndef __FreeBSD__
static volatile uint_t iommu_initted;
-#endif
-
-static __inline int
-IOMMU_INIT(void)
-{
- if (ops != NULL)
- return ((*ops->init)());
- else
- return (ENXIO);
-}
-
-static __inline void
-IOMMU_CLEANUP(void)
-{
- if (ops != NULL && iommu_avail)
- (*ops->cleanup)();
-}
-
-static __inline void *
-IOMMU_CREATE_DOMAIN(vm_paddr_t maxaddr)
-{
-
- if (ops != NULL && iommu_avail)
- return ((*ops->create_domain)(maxaddr));
- else
- return (NULL);
-}
-
-static __inline void
-IOMMU_DESTROY_DOMAIN(void *dom)
-{
-
- if (ops != NULL && iommu_avail)
- (*ops->destroy_domain)(dom);
-}
-
-static __inline uint64_t
-IOMMU_CREATE_MAPPING(void *domain, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len)
-{
-
- if (ops != NULL && iommu_avail)
- return ((*ops->create_mapping)(domain, gpa, hpa, len));
- else
- return (len); /* XXX */
-}
-
-static __inline uint64_t
-IOMMU_REMOVE_MAPPING(void *domain, vm_paddr_t gpa, uint64_t len)
-{
-
- if (ops != NULL && iommu_avail)
- return ((*ops->remove_mapping)(domain, gpa, len));
- else
- return (len); /* XXX */
-}
-
-static __inline void
-IOMMU_ADD_DEVICE(void *domain, uint16_t rid)
-{
-
- if (ops != NULL && iommu_avail)
- (*ops->add_device)(domain, rid);
-}
-
-static __inline void
-IOMMU_REMOVE_DEVICE(void *domain, uint16_t rid)
-{
-
- if (ops != NULL && iommu_avail)
- (*ops->remove_device)(domain, rid);
-}
-
-static __inline void
-IOMMU_INVALIDATE_TLB(void *domain)
-{
-
- if (ops != NULL && iommu_avail)
- (*ops->invalidate_tlb)(domain);
-}
-
-static __inline void
-IOMMU_ENABLE(void)
-{
-
- if (ops != NULL && iommu_avail)
- (*ops->enable)();
-}
-
-static __inline void
-IOMMU_DISABLE(void)
-{
-
- if (ops != NULL && iommu_avail)
- (*ops->disable)();
-}
-#ifdef __FreeBSD__
-static void
-iommu_pci_add(void *arg, device_t dev)
-{
-
- /* Add new devices to the host domain. */
- iommu_add_device(host_domain, pci_get_rid(dev));
-}
-
-static void
-iommu_pci_delete(void *arg, device_t dev)
-{
-
- iommu_remove_device(host_domain, pci_get_rid(dev));
-}
-#endif
-
-#ifndef __FreeBSD__
static int
iommu_find_device(dev_info_t *dip, void *arg)
{
@@ -196,110 +92,153 @@ vmm_mem_maxaddr(void)
{
return (ptoa(physmax + 1));
}
-#endif
-static void
+static int
iommu_init(void)
{
- int error;
- vm_paddr_t maxaddr;
+ const char *mod_name;
+ int error = 0;
- if (!iommu_enable)
- return;
+ ASSERT(MUTEX_HELD(&iommu_lock));
- if (vmm_is_intel())
- ops = &iommu_ops_intel;
- else if (vmm_is_svm())
- ops = &iommu_ops_amd;
- else
- ops = NULL;
+ if (vmm_is_intel()) {
+ mod_name = "misc/vmm_vtd";
+ } else if (vmm_is_svm()) {
+ /* Use the expected name for if/when this is ported */
+ mod_name = "misc/vmm_amdvi";
+ } else {
+ return (ENXIO);
+ }
- error = IOMMU_INIT();
- if (error)
- return;
+ /* Load the backend driver */
+ iommu_modhdl = ddi_modopen(mod_name, KRTLD_MODE_FIRST, &error);
+ if (iommu_modhdl == NULL) {
+ return (error);
+ }
- iommu_avail = 1;
+ /* Locate the iommu_ops struct */
+ ops = ddi_modsym(iommu_modhdl, IOMMU_OPS_SYM_NAME, &error);
+ if (ops == NULL) {
+ goto bail;
+ }
- /*
- * Create a domain for the devices owned by the host
- */
- maxaddr = vmm_mem_maxaddr();
- host_domain = IOMMU_CREATE_DOMAIN(maxaddr);
+ /* Initialize the backend */
+ error = ops->init();
+ if (error != 0) {
+ goto bail;
+ }
+
+ /* Create a domain for the devices owned by the host */
+ const vm_paddr_t maxaddr = vmm_mem_maxaddr();
+ host_domain = ops->create_domain(maxaddr);
if (host_domain == NULL) {
- printf("iommu_init: unable to create a host domain");
- IOMMU_CLEANUP();
- ops = NULL;
- iommu_avail = 0;
- return;
+ goto bail;
}
- /*
- * Create 1:1 mappings from '0' to 'maxaddr' for devices assigned to
- * the host
- */
+ /* ... and populate it with 1:1 mappings for all of physical mem */
iommu_create_mapping(host_domain, 0, 0, maxaddr);
ddi_walk_devs(ddi_root_node(), iommu_find_device, (void *)B_TRUE);
- IOMMU_ENABLE();
+ ops->enable();
+
+ return (0);
+bail:
+ if (ops != NULL) {
+ ops->cleanup();
+ ops = NULL;
+ }
+ if (iommu_modhdl != NULL) {
+ (void) ddi_modclose(iommu_modhdl);
+ iommu_modhdl = NULL;
+ }
+ return (error);
}
-void
+static void
iommu_cleanup(void)
{
-#ifdef __FreeBSD__
- if (add_tag != NULL) {
- EVENTHANDLER_DEREGISTER(pci_add_device, add_tag);
- add_tag = NULL;
- }
- if (delete_tag != NULL) {
- EVENTHANDLER_DEREGISTER(pci_delete_device, delete_tag);
- delete_tag = NULL;
- }
-#else
- atomic_store_rel_int(&iommu_initted, 0);
-#endif
- IOMMU_DISABLE();
-#ifndef __FreeBSD__
+ ASSERT(MUTEX_HELD(&iommu_lock));
+ ASSERT3P(ops, !=, NULL);
+ ASSERT0(iommu_refcnt);
+
+ ops->disable();
ddi_walk_devs(ddi_root_node(), iommu_find_device, (void *)B_FALSE);
-#endif
- IOMMU_DESTROY_DOMAIN(host_domain);
- IOMMU_CLEANUP();
-#ifndef __FreeBSD__
+
+ ops->destroy_domain(host_domain);
+ host_domain = NULL;
+
+ ops->cleanup();
ops = NULL;
-#endif
+
+ (void) ddi_modclose(iommu_modhdl);
+ iommu_modhdl = NULL;
+}
+
+static bool
+iommu_ref(void)
+{
+ mutex_enter(&iommu_lock);
+ if (ops == NULL) {
+ int err = iommu_init();
+
+ if (err != 0) {
+ VERIFY3P(ops, ==, NULL);
+ mutex_exit(&iommu_lock);
+ return (false);
+ }
+ VERIFY3P(ops, !=, NULL);
+ }
+ iommu_refcnt++;
+ VERIFY3U(iommu_refcnt, <, UINT_MAX);
+ mutex_exit(&iommu_lock);
+
+ return (true);
+}
+
+static void
+iommu_unref(void)
+{
+ mutex_enter(&iommu_lock);
+ VERIFY3U(iommu_refcnt, >, 0);
+ iommu_refcnt--;
+ if (iommu_refcnt == 0) {
+ iommu_cleanup();
+ VERIFY3P(ops, ==, NULL);
+ }
+ mutex_exit(&iommu_lock);
}
void *
iommu_create_domain(vm_paddr_t maxaddr)
{
- if (iommu_initted < 2) {
- if (atomic_cmpset_int(&iommu_initted, 0, 1)) {
- iommu_init();
- atomic_store_rel_int(&iommu_initted, 2);
- } else
- while (iommu_initted == 1)
- cpu_spinwait();
+ if (iommu_ref()) {
+ return (ops->create_domain(maxaddr));
+ } else {
+ return (NULL);
}
- return (IOMMU_CREATE_DOMAIN(maxaddr));
}
void
-iommu_destroy_domain(void *dom)
+iommu_destroy_domain(void *domain)
{
+ ASSERT3P(domain, !=, NULL);
- IOMMU_DESTROY_DOMAIN(dom);
+ ops->destroy_domain(domain);
+ iommu_unref();
}
void
-iommu_create_mapping(void *dom, vm_paddr_t gpa, vm_paddr_t hpa, size_t len)
+iommu_create_mapping(void *domain, vm_paddr_t gpa, vm_paddr_t hpa, size_t len)
{
- uint64_t mapped, remaining;
+ uint64_t remaining = len;
- remaining = len;
+ ASSERT3P(domain, !=, NULL);
while (remaining > 0) {
- mapped = IOMMU_CREATE_MAPPING(dom, gpa, hpa, remaining);
+ uint64_t mapped;
+
+ mapped = ops->create_mapping(domain, gpa, hpa, remaining);
gpa += mapped;
hpa += mapped;
remaining -= mapped;
@@ -307,14 +246,16 @@ iommu_create_mapping(void *dom, vm_paddr_t gpa, vm_paddr_t hpa, size_t len)
}
void
-iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len)
+iommu_remove_mapping(void *domain, vm_paddr_t gpa, size_t len)
{
- uint64_t unmapped, remaining;
+ uint64_t remaining = len;
- remaining = len;
+ ASSERT3P(domain, !=, NULL);
while (remaining > 0) {
- unmapped = IOMMU_REMOVE_MAPPING(dom, gpa, remaining);
+ uint64_t unmapped;
+
+ unmapped = ops->remove_mapping(domain, gpa, remaining);
gpa += unmapped;
remaining -= unmapped;
}
@@ -323,27 +264,29 @@ iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len)
void *
iommu_host_domain(void)
{
-
return (host_domain);
}
void
-iommu_add_device(void *dom, uint16_t rid)
+iommu_add_device(void *domain, uint16_t rid)
{
+ ASSERT3P(domain, !=, NULL);
- IOMMU_ADD_DEVICE(dom, rid);
+ ops->add_device(domain, rid);
}
void
-iommu_remove_device(void *dom, uint16_t rid)
+iommu_remove_device(void *domain, uint16_t rid)
{
+ ASSERT3P(domain, !=, NULL);
- IOMMU_REMOVE_DEVICE(dom, rid);
+ ops->remove_device(domain, rid);
}
void
iommu_invalidate_tlb(void *domain)
{
+ ASSERT3P(domain, !=, NULL);
- IOMMU_INVALIDATE_TLB(domain);
+ ops->invalidate_tlb(domain);
}
diff --git a/usr/src/uts/intel/io/vmm/io/iommu.h b/usr/src/uts/intel/io/vmm/io/iommu.h
index 0d1c4b1ee2..a7d0214091 100644
--- a/usr/src/uts/intel/io/vmm/io/iommu.h
+++ b/usr/src/uts/intel/io/vmm/io/iommu.h
@@ -27,6 +27,18 @@
*
* $FreeBSD$
*/
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * Copyright 2022 Oxide Computer Company
+ */
#ifndef _IO_IOMMU_H_
#define _IO_IOMMU_H_
@@ -42,8 +54,8 @@ typedef uint64_t (*iommu_create_mapping_t)(void *domain, vm_paddr_t gpa,
typedef uint64_t (*iommu_remove_mapping_t)(void *domain, vm_paddr_t gpa,
uint64_t len);
typedef void (*iommu_add_device_t)(void *domain, uint16_t rid);
-typedef void (*iommu_remove_device_t)(void *dom, uint16_t rid);
-typedef void (*iommu_invalidate_tlb_t)(void *dom);
+typedef void (*iommu_remove_device_t)(void *domain, uint16_t rid);
+typedef void (*iommu_invalidate_tlb_t)(void *domain);
struct iommu_ops {
iommu_init_func_t init; /* module wide */
@@ -60,19 +72,17 @@ struct iommu_ops {
iommu_invalidate_tlb_t invalidate_tlb;
};
-extern const struct iommu_ops iommu_ops_intel;
-extern const struct iommu_ops iommu_ops_amd;
+#define IOMMU_OPS_SYM_NAME "vmm_iommu_ops"
-void iommu_cleanup(void);
-void *iommu_host_domain(void);
-void *iommu_create_domain(vm_paddr_t maxaddr);
-void iommu_destroy_domain(void *dom);
-void iommu_create_mapping(void *dom, vm_paddr_t gpa, vm_paddr_t hpa,
+void *iommu_host_domain(void);
+void *iommu_create_domain(vm_paddr_t maxaddr);
+void iommu_destroy_domain(void *domain);
+void iommu_create_mapping(void *domain, vm_paddr_t gpa, vm_paddr_t hpa,
size_t len);
-void iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len);
-void iommu_add_device(void *dom, uint16_t rid);
-void iommu_remove_device(void *dom, uint16_t rid);
-void iommu_invalidate_tlb(void *domain);
+void iommu_remove_mapping(void *domain, vm_paddr_t gpa, size_t len);
+void iommu_add_device(void *domain, uint16_t rid);
+void iommu_remove_device(void *domain, uint16_t rid);
+void iommu_invalidate_tlb(void *domain);
/* Glue functions used by iommu provider(s) */
void *vmm_ptp_alloc(void);
diff --git a/usr/src/uts/intel/io/vmm/sys/vmm_kernel.h b/usr/src/uts/intel/io/vmm/sys/vmm_kernel.h
index 29e90e3a1e..87f8e18b47 100644
--- a/usr/src/uts/intel/io/vmm/sys/vmm_kernel.h
+++ b/usr/src/uts/intel/io/vmm/sys/vmm_kernel.h
@@ -383,6 +383,8 @@ void vmm_contig_free(void *, size_t);
int vmm_mod_load(void);
int vmm_mod_unload(void);
+bool vmm_check_iommu(void);
+
void vmm_call_trap(uint64_t);
/*
diff --git a/usr/src/uts/intel/io/vmm/vmm.c b/usr/src/uts/intel/io/vmm/vmm.c
index 800ae4d8ee..0ff23e88b2 100644
--- a/usr/src/uts/intel/io/vmm/vmm.c
+++ b/usr/src/uts/intel/io/vmm/vmm.c
@@ -458,7 +458,6 @@ vmm_mod_unload()
VERIFY(vmm_initialized == 1);
- iommu_cleanup();
error = VMM_CLEANUP();
if (error)
return (error);
@@ -467,6 +466,24 @@ vmm_mod_unload()
return (0);
}
+/*
+ * Create a test IOMMU domain to see if the host system has necessary hardware
+ * and drivers to do so.
+ */
+bool
+vmm_check_iommu(void)
+{
+ void *domain;
+ const size_t arb_test_sz = (1UL << 32);
+
+ domain = iommu_create_domain(arb_test_sz);
+ if (domain == NULL) {
+ return (false);
+ }
+ iommu_destroy_domain(domain);
+ return (true);
+}
+
static void
vm_init(struct vm *vm, bool create)
{
@@ -975,15 +992,9 @@ vm_iommu_modify(struct vm *vm, bool map)
int i, sz;
vm_paddr_t gpa, hpa;
struct mem_map *mm;
-#ifdef __FreeBSD__
- void *vp, *cookie, *host_domain;
-#endif
vm_client_t *vmc;
sz = PAGE_SIZE;
-#ifdef __FreeBSD__
- host_domain = iommu_host_domain();
-#endif
vmc = vmspace_client_alloc(vm->vmspace);
for (i = 0; i < VM_MAX_MEMMAPS; i++) {
@@ -1016,16 +1027,22 @@ vm_iommu_modify(struct vm *vm, bool map)
hpa = ((uintptr_t)vmp_get_pfn(vmp) << PAGESHIFT);
(void) vmp_release(vmp);
+ /*
+ * When originally ported from FreeBSD, the logic for
+ * adding memory to the guest domain would
+ * simultaneously remove it from the host domain. The
+ * justification for that is not clear, and FreeBSD has
+ * subsequently changed the behavior to not remove the
+ * memory from the host domain.
+ *
+ * Leaving the guest memory in the host domain for the
+ * life of the VM is necessary to make it available for
+ * DMA, such as through viona in the TX path.
+ */
if (map) {
iommu_create_mapping(vm->iommu, gpa, hpa, sz);
-#ifdef __FreeBSD__
- iommu_remove_mapping(host_domain, hpa, sz);
-#endif
} else {
iommu_remove_mapping(vm->iommu, gpa, sz);
-#ifdef __FreeBSD__
- iommu_create_mapping(host_domain, hpa, hpa, sz);
-#endif
}
gpa += PAGE_SIZE;
@@ -1037,14 +1054,7 @@ vm_iommu_modify(struct vm *vm, bool map)
* Invalidate the cached translations associated with the domain
* from which pages were removed.
*/
-#ifdef __FreeBSD__
- if (map)
- iommu_invalidate_tlb(host_domain);
- else
- iommu_invalidate_tlb(vm->iommu);
-#else
iommu_invalidate_tlb(vm->iommu);
-#endif
}
int
diff --git a/usr/src/uts/intel/io/vmm/vmm.mapfile b/usr/src/uts/intel/io/vmm/vmm.mapfile
index fb1c9366de..e4d58aac6d 100644
--- a/usr/src/uts/intel/io/vmm/vmm.mapfile
+++ b/usr/src/uts/intel/io/vmm/vmm.mapfile
@@ -12,7 +12,7 @@
#
# Copyright 2019 Joyent, Inc.
-# Copyright 2021 Oxide Computer Company
+# Copyright 2022 Oxide Computer Company
#
#
@@ -64,6 +64,10 @@ SYMBOL_VERSION ILLUMOSprivate {
vm_iommu_domain;
vm_map_mmio;
vm_unmap_mmio;
+ vmm_ptp_alloc;
+ vmm_ptp_free;
+ invalidate_cache_all;
+ vtophys;
local:
*;
diff --git a/usr/src/uts/intel/io/vmm/vmm_sol_dev.c b/usr/src/uts/intel/io/vmm/vmm_sol_dev.c
index bf57cba26f..a58e9d63f9 100644
--- a/usr/src/uts/intel/io/vmm/vmm_sol_dev.c
+++ b/usr/src/uts/intel/io/vmm/vmm_sol_dev.c
@@ -2492,6 +2492,11 @@ vmm_ctl_ioctl(int cmd, intptr_t arg, int md, cred_t *cr, int *rvalp)
case VMM_INTERFACE_VERSION:
*rvalp = VMM_CURRENT_INTERFACE_VERSION;
return (0);
+ case VMM_CHECK_IOMMU:
+ if (!vmm_check_iommu()) {
+ return (ENXIO);
+ }
+ return (0);
case VMM_RESV_QUERY:
case VMM_RESV_ADD:
case VMM_RESV_REMOVE:
diff --git a/usr/src/uts/intel/io/vmm/vmm_vtd.mapfile b/usr/src/uts/intel/io/vmm/vmm_vtd.mapfile
new file mode 100644
index 0000000000..bb12b7b132
--- /dev/null
+++ b/usr/src/uts/intel/io/vmm/vmm_vtd.mapfile
@@ -0,0 +1,45 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# This file is dual-licensed; see usr/src/contrib/bhyve/LICENSE
+
+#
+# Copyright 2022 Oxide Computer Company
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+$mapfile_version 2
+
+SYMBOL_VERSION ILLUMOSprivate {
+ global:
+ # DDI Interfaces
+ _fini;
+ _init;
+ _info;
+
+ # IOMMU ops consumed by bhyve
+ vmm_iommu_ops;
+
+ local:
+ *;
+};
diff --git a/usr/src/uts/intel/sys/vmm_dev.h b/usr/src/uts/intel/sys/vmm_dev.h
index 2e4c0c6e40..5333facacf 100644
--- a/usr/src/uts/intel/sys/vmm_dev.h
+++ b/usr/src/uts/intel/sys/vmm_dev.h
@@ -379,6 +379,7 @@ struct vmm_dirty_tracker {
#define VMM_DESTROY_VM (VMMCTL_IOC_BASE | 0x02)
#define VMM_VM_SUPPORTED (VMMCTL_IOC_BASE | 0x03)
#define VMM_INTERFACE_VERSION (VMMCTL_IOC_BASE | 0x04)
+#define VMM_CHECK_IOMMU (VMMCTL_IOC_BASE | 0x05)
#define VMM_RESV_QUERY (VMMCTL_IOC_BASE | 0x10)
#define VMM_RESV_ADD (VMMCTL_IOC_BASE | 0x11)
diff --git a/usr/src/uts/intel/vmm_vtd/Makefile b/usr/src/uts/intel/vmm_vtd/Makefile
new file mode 100644
index 0000000000..f3e6acd0e2
--- /dev/null
+++ b/usr/src/uts/intel/vmm_vtd/Makefile
@@ -0,0 +1,60 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2019 Joyent, Inc.
+# Copyright 2022 Oxide Computer Company
+#
+
+UTSBASE = ../..
+
+MODULE = vmm_vtd
+OBJECTS = $(VMM_VTD_OBJS:%=$(OBJS_DIR)/%)
+ROOTMODULE = $(USR_MISC_DIR)/$(MODULE)
+CONF_SRCDIR = $(UTSBASE)/intel/io/vmm
+MAPFILE = $(UTSBASE)/intel/io/vmm/vmm_vtd.mapfile
+
+PRE_INC_PATH = \
+ -I$(COMPAT)/bhyve \
+ -I$(COMPAT)/bhyve/amd64 \
+ -I$(CONTRIB)/bhyve \
+ -I$(CONTRIB)/bhyve/amd64
+
+INC_PATH += -I$(UTSBASE)/intel/io/vmm -I$(UTSBASE)/intel/io/vmm/io
+AS_INC_PATH += -I$(UTSBASE)/intel/io/vmm -I$(OBJS_DIR)
+
+LDFLAGS += -N drv/vmm -N misc/acpica -N misc/pcie
+LDFLAGS += -M $(MAPFILE)
+
+include $(UTSBASE)/intel/Makefile.intel
+
+ALL_TARGET = $(BINARY)
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+
+ALL_BUILDS = $(ALL_BUILDSONLY64)
+DEF_BUILDS = $(DEF_BUILDSONLY64)
+
+.PARALLEL: $(OBJECTS)
+
+.KEEP_STATE:
+
+def: $(DEF_DEPS)
+
+all: $(ALL_DEPS)
+
+clean: $(CLEAN_DEPS)
+
+clobber: $(CLOBBER_DEPS)
+
+install: $(INSTALL_DEPS)
+
+include $(UTSBASE)/intel/Makefile.targ
+include $(UTSBASE)/intel/io/vmm/Makefile.rules