aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ObsoleteFiles.inc3
-rw-r--r--krb5/lib/gssapi/mechglue/Makefile.inc2
-rw-r--r--krb5/util/compile_et/Makefile4
-rwxr-xr-xrelease/amd64/make-memstick.sh6
-rw-r--r--release/amd64/mkisoimages.sh6
-rw-r--r--release/packages/ucl/libutil++-all.ucl4
-rw-r--r--sys/dev/sdio/sdiob.c7
-rw-r--r--sys/net/if_epair.c35
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc6
-rw-r--r--usr.sbin/bhyve/amd64/pci_gvt-d.c180
-rw-r--r--usr.sbin/bhyve/pci_passthru.c155
-rw-r--r--usr.sbin/bhyve/pci_passthru.h7
12 files changed, 374 insertions, 41 deletions
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 0a4a7a073dcf..6308e51331b0 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -59,6 +59,9 @@ OLD_FILES+=lib/libopencsd.so.0
OLD_FILES+=usr/lib/libopencsd.a
OLD_FILES+=usr/lib/libopencsd.so
+# 20250801: Move compile_et to /usr/sbin
+OLD_FILES+=usr/share/et/compile_et
+
# 20250728: zfsboot (MBR) removed
OLD_FILES+=boot/zfsboot
OLD_FILES+=usr/share/man/man8/zfsboot.8.gz
diff --git a/krb5/lib/gssapi/mechglue/Makefile.inc b/krb5/lib/gssapi/mechglue/Makefile.inc
index bb0d436e08d1..c54cdf37b55b 100644
--- a/krb5/lib/gssapi/mechglue/Makefile.inc
+++ b/krb5/lib/gssapi/mechglue/Makefile.inc
@@ -72,3 +72,5 @@ SRCS+= g_accept_sec_context.c \
g_wrap_aead.c \
g_wrap_iov.c \
gssd_pname_to_uid.c
+
+GSSAPI_INCS+= mechglue.h
diff --git a/krb5/util/compile_et/Makefile b/krb5/util/compile_et/Makefile
index 03446f2d7d1c..3d48b39cab27 100644
--- a/krb5/util/compile_et/Makefile
+++ b/krb5/util/compile_et/Makefile
@@ -19,10 +19,6 @@ BINDIR?= /usr/bin
MAN= compile_et.1
CLEANFILES= compile_et
-.if !defined(BOOTSTRAPPING)
-SCRIPTSDIR= ${SHAREDIR}/et
-.endif
-
compile_et: compile_et.sh
sh ${SRC_ETDIR}/config_script ${SRC_ETDIR}/compile_et.sh \
"${KRB5_ETDIR}" /usr/bin/awk /usr/bin/sed > ${.TARGET}
diff --git a/release/amd64/make-memstick.sh b/release/amd64/make-memstick.sh
index cec4b27b5b96..770b128fd9f9 100755
--- a/release/amd64/make-memstick.sh
+++ b/release/amd64/make-memstick.sh
@@ -62,11 +62,9 @@ fi
# Make an ESP in a file.
espfilename=$(mktemp /tmp/efiboot.XXXXXX)
if [ -f "${BASEBITSDIR}/boot/loader_ia32.efi" ]; then
- make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi bootx64 \
- ${BASEBITSDIR}/boot/loader_ia32.efi bootia32
-else
- make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi
+ extra_args="${BASEBITSDIR}/boot/loader_ia32.efi bootia32"
fi
+make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi bootx64 ${extra_args}
${MKIMG} -s mbr \
-b ${BASEBITSDIR}/boot/mbr \
diff --git a/release/amd64/mkisoimages.sh b/release/amd64/mkisoimages.sh
index 8f7163e05261..01677ae787f9 100644
--- a/release/amd64/mkisoimages.sh
+++ b/release/amd64/mkisoimages.sh
@@ -54,11 +54,9 @@ if [ "$1" = "-b" ]; then
# ESP file size in KB.
espsize="2048"
if [ -f "${BASEBITSDIR}/boot/loader_ia32.efi" ]; then
- make_esp_file ${espfilename} ${espsize} ${BASEBITSDIR}/boot/loader.efi bootx64 \
- ${BASEBITSDIR}/boot/loader_ia32.efi bootia32
- else
- make_esp_file ${espfilename} ${espsize} ${BASEBITSDIR}/boot/loader.efi
+ extra_args="${BASEBITSDIR}/boot/loader_ia32.efi bootia32"
fi
+ make_esp_file ${espfilename} ${espsize} ${BASEBITSDIR}/boot/loader.efi bootx64 ${extra_args}
bootable="$bootable -o bootimage=i386;${espfilename} -o no-emul-boot -o platformid=efi"
shift
diff --git a/release/packages/ucl/libutil++-all.ucl b/release/packages/ucl/libutil++-all.ucl
new file mode 100644
index 000000000000..dfd77215dbc5
--- /dev/null
+++ b/release/packages/ucl/libutil++-all.ucl
@@ -0,0 +1,4 @@
+comment = "C++ utility library"
+desc = <<EOD
+libutil++ contains various C++ utility classes used by the base system.
+EOD
diff --git a/sys/dev/sdio/sdiob.c b/sys/dev/sdio/sdiob.c
index 4ec2058fa2e4..cb2cc0da6b77 100644
--- a/sys/dev/sdio/sdiob.c
+++ b/sys/dev/sdio/sdiob.c
@@ -150,7 +150,7 @@ sdiob_rw_direct_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr, bool wr,
sc->ccb = xpt_alloc_ccb();
else
memset(sc->ccb, 0, sizeof(*sc->ccb));
- xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NONE);
+ xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NORMAL);
CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_TRACE,
("%s(fn=%d, addr=%#02x, wr=%d, *val=%#02x)\n", __func__,
fn, addr, wr, *val));
@@ -250,7 +250,7 @@ sdiob_rw_extended_cam(struct sdiob_softc *sc, uint8_t fn, uint32_t addr,
sc->ccb = xpt_alloc_ccb();
else
memset(sc->ccb, 0, sizeof(*sc->ccb));
- xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NONE);
+ xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NORMAL);
CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_TRACE,
("%s(fn=%d addr=%#0x wr=%d b_count=%u blksz=%u buf=%p incr=%d)\n",
__func__, fn, addr, wr, b_count, blksz, buffer, incaddr));
@@ -977,9 +977,6 @@ sdiobdiscover(void *context, int pending)
if (sc->ccb == NULL)
sc->ccb = xpt_alloc_ccb();
- else
- memset(sc->ccb, 0, sizeof(*sc->ccb));
- xpt_setup_ccb(&sc->ccb->ccb_h, periph->path, CAM_PRIORITY_NONE);
/*
* Read CCCR and FBR of each function, get manufacturer and device IDs,
diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c
index 7051e31565d4..4d35584925a1 100644
--- a/sys/net/if_epair.c
+++ b/sys/net/if_epair.c
@@ -58,6 +58,7 @@
#include <sys/smp.h>
#include <sys/socket.h>
#include <sys/sockio.h>
+#include <sys/sysctl.h>
#include <sys/taskqueue.h>
#include <net/bpf.h>
@@ -97,6 +98,15 @@ static unsigned int next_index = 0;
#define EPAIR_LOCK() mtx_lock(&epair_n_index_mtx)
#define EPAIR_UNLOCK() mtx_unlock(&epair_n_index_mtx)
+SYSCTL_DECL(_net_link);
+static SYSCTL_NODE(_net_link, OID_AUTO, epair, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
+ "Pair of virtual cross-over connected Ethernet-like interfaces");
+
+static bool use_ether_gen_addr = false;
+SYSCTL_BOOL(_net_link_epair, OID_AUTO, ether_gen_addr, CTLFLAG_RWTUN,
+ &use_ether_gen_addr, false,
+ "Generate MAC with FreeBSD OUI using ether_gen_addr(9)");
+
struct epair_softc;
struct epair_queue {
struct mtx mtx;
@@ -496,15 +506,29 @@ epair_clone_match(struct if_clone *ifc, const char *name)
}
static void
+epair_generate_mac_byname(struct epair_softc *sc, uint8_t eaddr[])
+{
+ struct ether_addr gen_eaddr;
+ int i;
+
+ ether_gen_addr_byname(if_name(sc->ifp), &gen_eaddr);
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ eaddr[i] = gen_eaddr.octet[i];
+}
+
+static void
epair_clone_add(struct if_clone *ifc, struct epair_softc *scb)
{
struct ifnet *ifp;
uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */
ifp = scb->ifp;
- /* Copy epairNa etheraddr and change the last byte. */
- memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN);
- eaddr[5] = 0x0b;
+ if (!use_ether_gen_addr) {
+ /* Copy epairNa etheraddr and change the last byte. */
+ memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN);
+ eaddr[5] = 0x0b;
+ } else
+ epair_generate_mac_byname(scb, eaddr);
ether_ifattach(ifp, eaddr);
if_clone_addif(ifc, ifp);
@@ -719,7 +743,10 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len,
/* Finish initialization of interface <n>a. */
ifp = sca->ifp;
epair_setup_ifp(sca, name, unit);
- epair_generate_mac(sca, eaddr);
+ if (!use_ether_gen_addr)
+ epair_generate_mac(sca, eaddr);
+ else
+ epair_generate_mac_byname(sca, eaddr);
ether_ifattach(ifp, eaddr);
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 580be4362a18..58ca2a49b801 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -2837,6 +2837,9 @@ OLD_FILES+=usr/lib/libgssapi_krb5.a
OLD_FILES+=usr/lib/libgssapi_krb5.so
OLD_LIBS+=usr/lib/libgssapi_krb5.so.10
OLD_FILES+=usr/lib/libgssapi_krb5_p.a
+OLD_FILES+=usr/lib/libgssapi_mech.a
+OLD_FILES+=usr/lib/libgssapi_mech.so
+OLD_LIBS+=usr/lib/libgssapi_mech.so.10
OLD_FILES+=usr/lib/libgssapi_ntlm.a
OLD_FILES+=usr/lib/libgssapi_ntlm.so
OLD_LIBS+=usr/lib/libgssapi_ntlm.so.10
@@ -4919,6 +4922,9 @@ OLD_LIBS+=usr/lib/libcom_err.so.5
OLD_FILES+=usr/lib/libcom_err_p.a
OLD_LIBS+=usr/lib/libgssapi_krb5.so.10
OLD_FILES+=usr/lib/libgssapi_krb5_p.a
+OLD_FILES+=usr/lib/libgssapi_mech.a
+OLD_FILES+=usr/lib/libgssapi_mech.so
+OLD_LIBS+=usr/lib/libgssapi_mech.so.10
OLD_FILES+=usr/lib/libgssapi_ntlm.a
OLD_FILES+=usr/lib/libgssapi_ntlm.so
OLD_LIBS+=usr/lib/libgssapi_ntlm.so.10
diff --git a/usr.sbin/bhyve/amd64/pci_gvt-d.c b/usr.sbin/bhyve/amd64/pci_gvt-d.c
index 60bf460d71ed..0ea53689f2b2 100644
--- a/usr.sbin/bhyve/amd64/pci_gvt-d.c
+++ b/usr.sbin/bhyve/amd64/pci_gvt-d.c
@@ -20,6 +20,7 @@
#include "amd64/e820.h"
#include "pci_gvt-d-opregion.h"
#include "pci_passthru.h"
+#include "pciids_intel_gpus.h"
#define KB (1024UL)
#define MB (1024 * KB)
@@ -32,15 +33,180 @@
#define PCI_VENDOR_INTEL 0x8086
#define PCIR_BDSM 0x5C /* Base of Data Stolen Memory register */
+#define PCIR_BDSM_GEN11 0xC0
#define PCIR_ASLS_CTL 0xFC /* Opregion start address register */
#define PCIM_BDSM_GSM_ALIGNMENT \
0x00100000 /* Graphics Stolen Memory is 1 MB aligned */
+#define BDSM_GEN11_MMIO_ADDRESS 0x1080C0
+
#define GVT_D_MAP_GSM 0
#define GVT_D_MAP_OPREGION 1
#define GVT_D_MAP_VBT 2
+static uint64_t
+gvt_d_dsmbase_read(struct pci_devinst *pi, int baridx __unused, uint64_t offset,
+ int size)
+{
+ switch (size) {
+ case 1:
+ return (pci_get_cfgdata8(pi, PCIR_BDSM_GEN11 + offset));
+ case 2:
+ return (pci_get_cfgdata16(pi, PCIR_BDSM_GEN11 + offset));
+ case 4:
+ return (pci_get_cfgdata32(pi, PCIR_BDSM_GEN11 + offset));
+ default:
+ return (UINT64_MAX);
+ }
+}
+
+static void
+gvt_d_dsmbase_write(struct pci_devinst *pi, int baridx __unused,
+ uint64_t offset, int size, uint64_t val)
+{
+ switch (size) {
+ case 1:
+ pci_set_cfgdata8(pi, PCIR_BDSM_GEN11 + offset, val);
+ break;
+ case 2:
+ pci_set_cfgdata16(pi, PCIR_BDSM_GEN11 + offset, val);
+ break;
+ case 4:
+ pci_set_cfgdata32(pi, PCIR_BDSM_GEN11 + offset, val);
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+set_bdsm_gen3(struct pci_devinst *const pi, vm_paddr_t bdsm_gpa)
+{
+ struct passthru_softc *sc = pi->pi_arg;
+ uint32_t bdsm;
+ int error;
+
+ bdsm = pci_host_read_config(passthru_get_sel(sc), PCIR_BDSM, 4);
+
+ /* Protect the BDSM register in PCI space. */
+ pci_set_cfgdata32(pi, PCIR_BDSM,
+ bdsm_gpa | (bdsm & (PCIM_BDSM_GSM_ALIGNMENT - 1)));
+ error = set_pcir_handler(sc, PCIR_BDSM, 4, passthru_cfgread_emulate,
+ passthru_cfgwrite_emulate);
+ if (error) {
+ warnx("%s: Failed to setup handler for BDSM register!", __func__);
+ return (error);
+ }
+
+ return (0);
+}
+
+static int
+set_bdsm_gen11(struct pci_devinst *const pi, vm_paddr_t bdsm_gpa)
+{
+ struct passthru_softc *sc = pi->pi_arg;
+ uint64_t bdsm;
+ int error;
+
+ bdsm = pci_host_read_config(passthru_get_sel(sc), PCIR_BDSM_GEN11, 8);
+
+ /* Protect the BDSM register in PCI space. */
+ pci_set_cfgdata32(pi, PCIR_BDSM_GEN11,
+ bdsm_gpa | (bdsm & (PCIM_BDSM_GSM_ALIGNMENT - 1)));
+ pci_set_cfgdata32(pi, PCIR_BDSM_GEN11 + 4, bdsm_gpa >> 32);
+ error = set_pcir_handler(sc, PCIR_BDSM_GEN11, 8, passthru_cfgread_emulate,
+ passthru_cfgwrite_emulate);
+ if (error) {
+ warnx("%s: Failed to setup handler for BDSM register!\n", __func__);
+ return (error);
+ }
+
+ /* Protect the BDSM register in MMIO space. */
+ error = passthru_set_bar_handler(sc, 0, BDSM_GEN11_MMIO_ADDRESS, sizeof(uint64_t),
+ gvt_d_dsmbase_read, gvt_d_dsmbase_write);
+ if (error) {
+ warnx("%s: Failed to setup handler for BDSM mirror!\n", __func__);
+ return (error);
+ }
+
+ return (0);
+}
+
+struct igd_ops {
+ int (*set_bdsm)(struct pci_devinst *const pi, vm_paddr_t bdsm_gpa);
+};
+
+static const struct igd_ops igd_ops_gen3 = { .set_bdsm = set_bdsm_gen3 };
+
+static const struct igd_ops igd_ops_gen11 = { .set_bdsm = set_bdsm_gen11 };
+
+struct igd_device {
+ uint32_t device_id;
+ const struct igd_ops *ops;
+};
+
+#define IGD_DEVICE(_device_id, _ops) \
+ { \
+ .device_id = (_device_id), \
+ .ops = (_ops), \
+ }
+
+static const struct igd_device igd_devices[] = {
+ INTEL_I915G_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_I915GM_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_I945G_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_I945GM_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_VLV_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_PNV_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_I965GM_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_GM45_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_G45_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_ILK_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_SNB_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_IVB_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_HSW_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_BDW_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_CHV_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_SKL_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_BXT_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_KBL_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_CFL_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_WHL_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_CML_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_GLK_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_CNL_IDS(IGD_DEVICE, &igd_ops_gen3),
+ INTEL_ICL_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_EHL_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_JSL_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_TGL_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_RKL_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_ADLS_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_ADLP_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_ADLN_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_RPLS_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_RPLU_IDS(IGD_DEVICE, &igd_ops_gen11),
+ INTEL_RPLP_IDS(IGD_DEVICE, &igd_ops_gen11),
+};
+
+static const struct igd_ops *
+get_igd_ops(struct pci_devinst *const pi)
+{
+ struct passthru_softc *sc = pi->pi_arg;
+ uint16_t device_id;
+
+ device_id = pci_host_read_config(passthru_get_sel(sc), PCIR_DEVICE,
+ 0x02);
+ for (size_t i = 0; i < nitems(igd_devices); i++) {
+ if (igd_devices[i].device_id != device_id)
+ continue;
+
+ return (igd_devices[i].ops);
+ }
+
+ return (NULL);
+}
+
static int
gvt_d_probe(struct pci_devinst *const pi)
{
@@ -108,8 +274,8 @@ gvt_d_setup_gsm(struct pci_devinst *const pi)
{
struct passthru_softc *sc;
struct passthru_mmio_mapping *gsm;
+ const struct igd_ops *igd_ops;
size_t sysctl_len;
- uint32_t bdsm;
int error;
sc = pi->pi_arg;
@@ -170,12 +336,14 @@ gvt_d_setup_gsm(struct pci_devinst *const pi)
"Warning: Unable to reuse host address of Graphics Stolen Memory. GPU passthrough might not work properly.");
}
- bdsm = pci_host_read_config(passthru_get_sel(sc), PCIR_BDSM, 4);
- pci_set_cfgdata32(pi, PCIR_BDSM,
- gsm->gpa | (bdsm & (PCIM_BDSM_GSM_ALIGNMENT - 1)));
+ igd_ops = get_igd_ops(pi);
+ if (igd_ops == NULL) {
+ warn("%s: Unknown IGD device. It's not supported yet!",
+ __func__);
+ return (-1);
+ }
- return (set_pcir_handler(sc, PCIR_BDSM, 4, passthru_cfgread_emulate,
- passthru_cfgwrite_emulate));
+ return (igd_ops->set_bdsm(pi, gsm->gpa));
}
static int
diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
index a82078f6e036..8ddcd8bd56e8 100644
--- a/usr.sbin/bhyve/pci_passthru.c
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -79,6 +79,14 @@ static int pcifd = -1;
SET_DECLARE(passthru_dev_set, struct passthru_dev);
+struct passthru_bar_handler {
+ TAILQ_ENTRY(passthru_bar_handler) chain;
+ uint64_t off;
+ uint64_t size;
+ passthru_read_handler read;
+ passthru_write_handler write;
+};
+
struct passthru_softc {
struct pci_devinst *psc_pi;
/* ROM is handled like a BAR */
@@ -96,6 +104,9 @@ struct passthru_softc {
struct passthru_mmio_mapping psc_mmio_map[PASSTHRU_MMIO_MAX];
cfgread_handler psc_pcir_rhandler[PCI_REGMAX + 1];
cfgwrite_handler psc_pcir_whandler[PCI_REGMAX + 1];
+
+ TAILQ_HEAD(,
+ passthru_bar_handler) psc_bar_handler[PCI_BARMAX_WITH_ROM + 1];
};
static int
@@ -741,6 +752,45 @@ set_pcir_handler(struct passthru_softc *sc, int reg, int len,
return (0);
}
+int
+passthru_set_bar_handler(struct passthru_softc *sc, int baridx, uint64_t off,
+ uint64_t size, passthru_read_handler rhandler,
+ passthru_write_handler whandler)
+{
+ struct passthru_bar_handler *handler_new;
+ struct passthru_bar_handler *handler;
+
+ assert(sc->psc_bar[baridx].type == PCIBAR_IO ||
+ sc->psc_bar[baridx].type == PCIBAR_MEM32 ||
+ sc->psc_bar[baridx].type == PCIBAR_MEM64);
+ assert(sc->psc_bar[baridx].size >= off + size);
+ assert(off < off + size);
+
+ handler_new = malloc(sizeof(struct passthru_bar_handler));
+ if (handler_new == NULL) {
+ return (ENOMEM);
+ }
+
+ handler_new->off = off;
+ handler_new->size = size;
+ handler_new->read = rhandler;
+ handler_new->write = whandler;
+
+ TAILQ_FOREACH(handler, &sc->psc_bar_handler[baridx], chain) {
+ if (handler->off < handler_new->off) {
+ assert(handler->off + handler->size < handler_new->off);
+ continue;
+ }
+ assert(handler->off > handler_new->off + handler_new->size);
+ TAILQ_INSERT_BEFORE(handler, handler_new, chain);
+ return (0);
+ }
+
+ TAILQ_INSERT_TAIL(&sc->psc_bar_handler[baridx], handler_new, chain);
+
+ return (0);
+}
+
static int
passthru_legacy_config(nvlist_t *nvl, const char *opts)
{
@@ -947,6 +997,9 @@ passthru_init(struct pci_devinst *pi, nvlist_t *nvl)
pi->pi_arg = sc;
sc->psc_pi = pi;
+ for (uint8_t i = 0; i < PCI_BARMAX_WITH_ROM + 1; ++i)
+ TAILQ_INIT(&sc->psc_bar_handler[i]);
+
/* initialize config space */
if ((error = cfginit(pi, bus, slot, func)) != 0)
goto done;
@@ -1166,6 +1219,7 @@ passthru_write(struct pci_devinst *pi, int baridx, uint64_t offset, int size,
uint64_t value)
{
struct passthru_softc *sc;
+ struct passthru_bar_handler *handler;
struct pci_bar_ioreq pio;
sc = pi->pi_arg;
@@ -1173,9 +1227,27 @@ passthru_write(struct pci_devinst *pi, int baridx, uint64_t offset, int size,
if (baridx == pci_msix_table_bar(pi)) {
msix_table_write(sc, offset, size, value);
} else {
- assert(pi->pi_bar[baridx].type == PCIBAR_IO);
assert(size == 1 || size == 2 || size == 4);
- assert(offset <= UINT32_MAX && offset + size <= UINT32_MAX);
+
+ TAILQ_FOREACH(handler, &sc->psc_bar_handler[baridx], chain) {
+ if (offset >= handler->off + handler->size) {
+ continue;
+ } else if (offset < handler->off) {
+ assert(offset + size < handler->off);
+ /*
+ * The list is sorted in ascending order, so all
+ * remaining handlers will have an even larger
+ * offset.
+ */
+ break;
+ }
+
+ assert(offset + size <= handler->off + handler->size);
+
+ handler->write(pi, baridx,
+ offset - handler->off, size, value);
+ return;
+ }
bzero(&pio, sizeof(pio));
pio.pbi_sel = sc->psc_sel;
@@ -1193,6 +1265,7 @@ static uint64_t
passthru_read(struct pci_devinst *pi, int baridx, uint64_t offset, int size)
{
struct passthru_softc *sc;
+ struct passthru_bar_handler *handler;
struct pci_bar_ioreq pio;
uint64_t val;
@@ -1201,9 +1274,26 @@ passthru_read(struct pci_devinst *pi, int baridx, uint64_t offset, int size)
if (baridx == pci_msix_table_bar(pi)) {
val = msix_table_read(sc, offset, size);
} else {
- assert(pi->pi_bar[baridx].type == PCIBAR_IO);
assert(size == 1 || size == 2 || size == 4);
- assert(offset <= UINT32_MAX && offset + size <= UINT32_MAX);
+
+ TAILQ_FOREACH(handler, &sc->psc_bar_handler[baridx], chain) {
+ if (offset >= handler->off + handler->size) {
+ continue;
+ } else if (offset < handler->off) {
+ assert(offset + size < handler->off);
+ /*
+ * The list is sorted in ascending order, so all
+ * remaining handlers will have an even larger
+ * offset.
+ */
+ break;
+ }
+
+ assert(offset + size <= handler->off + handler->size);
+
+ return (handler->read(pi, baridx,
+ offset - handler->off, size));
+ }
bzero(&pio, sizeof(pio));
pio.pbi_sel = sc->psc_sel;
@@ -1272,27 +1362,64 @@ passthru_msix_addr(struct pci_devinst *pi, int baridx, int enabled,
}
}
-static void
-passthru_mmio_addr(struct pci_devinst *pi, int baridx, int enabled,
- uint64_t address)
+static int
+passthru_mmio_map(struct pci_devinst *pi, int baridx, int enabled,
+ uint64_t address, uint64_t off, uint64_t size)
{
struct passthru_softc *sc;
sc = pi->pi_arg;
if (!enabled) {
if (vm_unmap_pptdev_mmio(pi->pi_vmctx, sc->psc_sel.pc_bus,
- sc->psc_sel.pc_dev,
- sc->psc_sel.pc_func, address,
- sc->psc_bar[baridx].size) != 0)
+ sc->psc_sel.pc_dev, sc->psc_sel.pc_func, address + off,
+ size) != 0) {
warnx("pci_passthru: unmap_pptdev_mmio failed");
+ return (-1);
+ }
} else {
if (vm_map_pptdev_mmio(pi->pi_vmctx, sc->psc_sel.pc_bus,
- sc->psc_sel.pc_dev,
- sc->psc_sel.pc_func, address,
- sc->psc_bar[baridx].size,
- sc->psc_bar[baridx].addr) != 0)
+ sc->psc_sel.pc_dev, sc->psc_sel.pc_func, address + off,
+ size, sc->psc_bar[baridx].addr + off) != 0) {
warnx("pci_passthru: map_pptdev_mmio failed");
+ return (-1);
+ }
}
+
+ return (0);
+}
+
+static void
+passthru_mmio_addr(struct pci_devinst *pi, int baridx, int enabled,
+ uint64_t address)
+{
+ struct passthru_softc *sc;
+ struct passthru_bar_handler *handler;
+ uint64_t off;
+
+ sc = pi->pi_arg;
+
+ off = 0;
+
+ /* The queue is sorted by offset in ascending order. */
+ TAILQ_FOREACH(handler, &sc->psc_bar_handler[baridx], chain) {
+ uint64_t handler_off = trunc_page(handler->off);
+ uint64_t handler_end = round_page(handler->off + handler->size);
+
+ /*
+ * When two handlers point to the same page, handler_off can be
+ * lower than off. That's fine because we have nothing to do in
+ * that case.
+ */
+ if (handler_off > off) {
+ passthru_mmio_map(pi, baridx, enabled, address, off,
+ handler_off - off);
+ }
+
+ off = handler_end;
+ }
+
+ passthru_mmio_map(pi, baridx, enabled, address, off,
+ sc->psc_bar[baridx].size - off);
}
static void
diff --git a/usr.sbin/bhyve/pci_passthru.h b/usr.sbin/bhyve/pci_passthru.h
index a89ad287cbc5..9e7b27d95735 100644
--- a/usr.sbin/bhyve/pci_passthru.h
+++ b/usr.sbin/bhyve/pci_passthru.h
@@ -35,6 +35,10 @@ typedef int (*cfgread_handler)(struct passthru_softc *sc,
struct pci_devinst *pi, int coff, int bytes, uint32_t *rv);
typedef int (*cfgwrite_handler)(struct passthru_softc *sc,
struct pci_devinst *pi, int coff, int bytes, uint32_t val);
+typedef uint64_t (*passthru_read_handler)(struct pci_devinst *pi, int baridx,
+ uint64_t offset, int size);
+typedef void (*passthru_write_handler)(struct pci_devinst *pi, int baridx, uint64_t offset,
+ int size, uint64_t val);
uint32_t pci_host_read_config(const struct pcisel *sel, long reg, int width);
void pci_host_write_config(const struct pcisel *sel, long reg, int width,
@@ -49,3 +53,6 @@ struct passthru_mmio_mapping *passthru_get_mmio(struct passthru_softc *sc,
struct pcisel *passthru_get_sel(struct passthru_softc *sc);
int set_pcir_handler(struct passthru_softc *sc, int reg, int len,
cfgread_handler rhandler, cfgwrite_handler whandler);
+int passthru_set_bar_handler(struct passthru_softc *sc, int baridx,
+ uint64_t off, uint64_t size, passthru_read_handler rhandler,
+ passthru_write_handler whandler);