summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Rosenfeld <hans.rosenfeld@joyent.com>2018-04-24 10:48:21 +0000
committerHans Rosenfeld <hans.rosenfeld@joyent.com>2018-04-24 13:00:13 +0200
commit7f4cce258636ed577f781c39e1dac133a2d745b2 (patch)
tree4b82948b2db627dd874c24e3fad56c5a3abead66
parent4d8ab6bf8248efd00a0524249c9faf28c7109eae (diff)
downloadillumos-joyent-7f4cce258636ed577f781c39e1dac133a2d745b2.tar.gz
OS-6738 bhyve ppt should not use /dev/mem
Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r--usr/src/cmd/bhyve/pci_passthru.c19
-rw-r--r--usr/src/uts/i86pc/io/vmm/io/ppt.c69
2 files changed, 65 insertions, 23 deletions
diff --git a/usr/src/cmd/bhyve/pci_passthru.c b/usr/src/cmd/bhyve/pci_passthru.c
index d133c61849..2ed490c71a 100644
--- a/usr/src/cmd/bhyve/pci_passthru.c
+++ b/usr/src/cmd/bhyve/pci_passthru.c
@@ -62,10 +62,6 @@ __FBSDID("$FreeBSD$");
#include "pci_emul.h"
#include "mem.h"
-#ifndef _PATH_MEM
-#define _PATH_MEM "/dev/mem"
-#endif
-
#define LEGACY_SUPPORT 1
#define MSIX_TABLE_COUNT(ctrl) (((ctrl) & PCIM_MSIXCTRL_TABLE_SIZE) + 1)
@@ -541,18 +537,6 @@ init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base)
pi->pi_msix.pba_page = NULL;
pi->pi_msix.pba_page_offset = 0;
} else {
- int memfd;
-
- /*
- * This cannot work in a zone and should be replaced
- * with a better interface offered by the ppt driver.
- */
- memfd = open(_PATH_MEM, O_RDWR, 0);
- if (memfd < 0) {
- warn("failed to open %s", _PATH_MEM);
- return (-1);
- }
-
/*
* The PBA overlaps with either the first or last
* page of the MSI-X table region. Map the
@@ -564,9 +548,8 @@ init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base)
pi->pi_msix.pba_page_offset = table_offset +
table_size - 4096;
pi->pi_msix.pba_page = mmap(NULL, 4096, PROT_READ |
- PROT_WRITE, MAP_SHARED, memfd, start +
+ PROT_WRITE, MAP_SHARED, sc->pptfd,
pi->pi_msix.pba_page_offset);
- (void) close(memfd);
if (pi->pi_msix.pba_page == MAP_FAILED) {
warn("Failed to map PBA page for MSI-X on %d",
sc->pptfd);
diff --git a/usr/src/uts/i86pc/io/vmm/io/ppt.c b/usr/src/uts/i86pc/io/vmm/io/ppt.c
index 6b808b6c5d..d36c360e03 100644
--- a/usr/src/uts/i86pc/io/vmm/io/ppt.c
+++ b/usr/src/uts/i86pc/io/vmm/io/ppt.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pci_cap.h>
#include <sys/ppt_dev.h>
#include <sys/mkdev.h>
+#include <sys/sysmacros.h>
#include "vmm_lapic.h"
#include "vmm_ktr.h"
@@ -318,6 +319,64 @@ ppt_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv)
return (0);
}
+static int
+ppt_find_pba_bar(struct pptdev *ppt)
+{
+ uint16_t base;
+ uint32_t pba_off;
+
+ if (PCI_CAP_LOCATE(ppt->pptd_cfg, PCI_CAP_ID_MSI_X, &base) !=
+ DDI_SUCCESS)
+ return (-1);
+
+ pba_off = pci_config_get32(ppt->pptd_cfg, base + PCI_MSIX_PBA_OFFSET);
+
+ if (pba_off == PCI_EINVAL32)
+ return (-1);
+
+ return (pba_off & PCI_MSIX_PBA_BIR_MASK);
+}
+
+static int
+ppt_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
+ size_t *maplen, uint_t model)
+{
+ minor_t minor;
+ struct pptdev *ppt;
+ int err;
+ int bar;
+
+ minor = getminor(dev);
+
+ if ((ppt = ddi_get_soft_state(ppt_state, minor)) == NULL)
+ return (ENXIO);
+
+#ifdef _MULTI_DATAMODEL
+ if (ddi_model_convert_from(model) != DDI_MODEL_NONE)
+ return (ENXIO);
+#endif
+
+ if (off < 0 || off != P2ALIGN(off, PAGESIZE))
+ return (EINVAL);
+
+ if ((bar = ppt_find_pba_bar(ppt)) == -1)
+ return (EINVAL);
+
+ /*
+ * Add 1 to the BAR number to get the register number used by DDI.
+ * Register 0 corresponds to PCI config space, the PCI BARs start at 1.
+ */
+ bar += 1;
+
+ err = devmap_devmem_setup(dhp, ppt->pptd_dip, NULL, bar, off, len,
+ PROT_USER | PROT_READ | PROT_WRITE, IOMEM_DATA_CACHED, &ppt_attr);
+
+ if (err == DDI_SUCCESS)
+ *maplen = len;
+
+ return (err);
+}
+
static void
ppt_bar_wipe(struct pptdev *ppt)
@@ -448,7 +507,6 @@ ppt_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
if (ppt_bar_crawl(ppt) != 0) {
goto fail;
}
-
if (ddi_create_minor_node(dip, PPT_MINOR_NAME, S_IFCHR, inst,
DDI_PSEUDO, 0) != DDI_SUCCESS) {
goto fail;
@@ -539,13 +597,14 @@ static struct cb_ops ppt_cb_ops = {
nodev, /* read */
nodev, /* write */
ppt_ioctl,
- nodev, /* devmap */
- nodev, /* mmap */
- nodev, /* segmap */
+ ppt_devmap, /* devmap */
+ NULL, /* mmap */
+ NULL, /* segmap */
nochpoll, /* poll */
ddi_prop_op,
NULL,
- D_NEW | D_MP | D_DEVMAP
+ D_NEW | D_MP | D_64BIT | D_DEVMAP,
+ CB_REV
};
static struct dev_ops ppt_ops = {