diff options
-rw-r--r-- | ObsoleteFiles.inc | 3 | ||||
-rw-r--r-- | krb5/lib/gssapi/mechglue/Makefile.inc | 2 | ||||
-rw-r--r-- | krb5/util/compile_et/Makefile | 4 | ||||
-rwxr-xr-x | release/amd64/make-memstick.sh | 6 | ||||
-rw-r--r-- | release/amd64/mkisoimages.sh | 6 | ||||
-rw-r--r-- | release/packages/ucl/libutil++-all.ucl | 4 | ||||
-rw-r--r-- | sys/dev/sdio/sdiob.c | 7 | ||||
-rw-r--r-- | sys/net/if_epair.c | 35 | ||||
-rw-r--r-- | tools/build/mk/OptionalObsoleteFiles.inc | 6 | ||||
-rw-r--r-- | usr.sbin/bhyve/amd64/pci_gvt-d.c | 180 | ||||
-rw-r--r-- | usr.sbin/bhyve/pci_passthru.c | 155 | ||||
-rw-r--r-- | usr.sbin/bhyve/pci_passthru.h | 7 |
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); |