This patch adds an extra size/cookie argument to pci_add_device and pci_add_bar.
Changes required for implementing passthrough PCI.

diff --git a/usr.sbin/vmd/pci.c b/usr.sbin/vmd/pci.c
index 954235eb6..47a133b9a 100644
--- a/usr.sbin/vmd/pci.c
+++ b/usr.sbin/vmd/pci.c
@@ -39,6 +39,26 @@ extern char *__progname;
 const uint8_t pci_pic_irqs[PCI_MAX_PIC_IRQS] = {3, 5, 6, 7, 9, 10, 11, 12,
     14, 15};
 
+/*
+ * pci_mkbar
+ *
+ * Calculates BAR address is valid
+ * Returns allocated address and updates next address
+ * Returns zero if address is out of range
+ */
+static uint64_t
+pci_mkbar(uint64_t *base, uint32_t size, uint64_t maxbase)
+{
+       uint64_t mask = size - 1;
+       uint64_t cbase;
+
+       if (*base + size >= maxbase)
+               return (0);
+       cbase = *base;
+       *base = (*base + size + mask) & ~mask;
+       return cbase;
+}
+
 /*
  * pci_add_bar
  *
@@ -58,9 +78,10 @@ const uint8_t pci_pic_irqs[PCI_MAX_PIC_IRQS] = {3, 5, 6, 7, 
9, 10, 11, 12,
  * Returns 0 if the BAR was added successfully, 1 otherwise.
  */
 int
-pci_add_bar(uint8_t id, uint32_t type, void *barfn, void *cookie)
+pci_add_bar(uint8_t id, uint32_t type, uint32_t size, void *barfn, void 
*cookie)
 {
        uint8_t bar_reg_idx, bar_ct;
+       uint32_t base;
 
        /* Check id */
        if (id >= pci.pci_dev_ct)
@@ -74,34 +95,35 @@ pci_add_bar(uint8_t id, uint32_t type, void *barfn, void 
*cookie)
        /* Compute BAR address and add */
        bar_reg_idx = (PCI_MAPREG_START + (bar_ct * 4)) / 4;
        if (type == PCI_MAPREG_TYPE_MEM) {
-               if (pci.pci_next_mmio_bar >= VMM_PCI_MMIO_BAR_END)
+               base = pci_mkbar(&pci.pci_next_mmio_bar, size, 
VMM_PCI_MMIO_BAR_END);
+               if (base == 0)
                        return (1);
 
                pci.pci_devices[id].pd_cfg_space[bar_reg_idx] =
-                   PCI_MAPREG_MEM_ADDR(pci.pci_next_mmio_bar);
-               pci.pci_next_mmio_bar += VMM_PCI_MMIO_BAR_SIZE;
+                   PCI_MAPREG_MEM_ADDR(base);
                pci.pci_devices[id].pd_barfunc[bar_ct] = barfn;
                pci.pci_devices[id].pd_bar_cookie[bar_ct] = cookie;
                pci.pci_devices[id].pd_bartype[bar_ct] = PCI_BAR_TYPE_MMIO;
-               pci.pci_devices[id].pd_barsize[bar_ct] = VMM_PCI_MMIO_BAR_SIZE;
+               pci.pci_devices[id].pd_barsize[bar_ct] = size;
                pci.pci_devices[id].pd_bar_ct++;
        } else if (type == PCI_MAPREG_TYPE_IO) {
-               if (pci.pci_next_io_bar >= VMM_PCI_IO_BAR_END)
+               base = pci_mkbar(&pci.pci_next_io_bar, size, 
VMM_PCI_IO_BAR_END);
+               if (base == 0)
                        return (1);
 
                pci.pci_devices[id].pd_cfg_space[bar_reg_idx] =
-                   PCI_MAPREG_IO_ADDR(pci.pci_next_io_bar) |
+                   PCI_MAPREG_IO_ADDR(base) |
                    PCI_MAPREG_TYPE_IO;
-               pci.pci_next_io_bar += VMM_PCI_IO_BAR_SIZE;
                pci.pci_devices[id].pd_barfunc[bar_ct] = barfn;
                pci.pci_devices[id].pd_bar_cookie[bar_ct] = cookie;
-               DPRINTF("%s: adding pci bar cookie for dev %d bar %d = %p",
-                   __progname, id, bar_ct, cookie);
                pci.pci_devices[id].pd_bartype[bar_ct] = PCI_BAR_TYPE_IO;
-               pci.pci_devices[id].pd_barsize[bar_ct] = VMM_PCI_IO_BAR_SIZE;
+               pci.pci_devices[id].pd_barsize[bar_ct] = size;
                pci.pci_devices[id].pd_bar_ct++;
        }
 
+       log_info("%s: PCI_ADDBAR(%d, %d, %x, %x)", __progname,
+               bar_ct, type, pci.pci_devices[id].pd_cfg_space[bar_reg_idx], 
size);
+
        return (0);
 }
 
@@ -165,8 +187,10 @@ pci_get_dev_irq(uint8_t id)
 int
 pci_add_device(uint8_t *id, uint16_t vid, uint16_t pid, uint8_t class,
     uint8_t subclass, uint16_t subsys_vid, uint16_t subsys_id,
-    uint8_t irq_needed, pci_cs_fn_t csfunc)
+    uint8_t irq_needed, pci_cs_fn_t csfunc, void *cookie)
 {
+       log_info("%s: add_pci: %x.%x.%x", __progname, vid, pid, class);
+
        /* Exceeded max devices? */
        if (pci.pci_dev_ct >= PCI_CONFIG_MAX_DEV)
                return (1);
@@ -186,6 +210,7 @@ pci_add_device(uint8_t *id, uint16_t vid, uint16_t pid, 
uint8_t class,
        pci.pci_devices[*id].pd_subsys_id = subsys_id;
 
        pci.pci_devices[*id].pd_csfunc = csfunc;
+       pci.pci_devices[*id].pd_cookie = cookie;
 
        if (irq_needed) {
                pci.pci_devices[*id].pd_irq =
@@ -219,7 +244,7 @@ pci_init(void)
 
        if (pci_add_device(&id, PCI_VENDOR_OPENBSD, PCI_PRODUCT_OPENBSD_PCHB,
            PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_HOST,
-           PCI_VENDOR_OPENBSD, 0, 0, NULL)) {
+           PCI_VENDOR_OPENBSD, 0, 0, NULL, NULL)) {
                log_warnx("%s: can't add PCI host bridge", __progname);
                return;
        }
@@ -264,6 +289,8 @@ pci_handle_io(struct vm_run_params *vrp)
 
        for (i = 0 ; i < pci.pci_dev_ct ; i++) {
                for (j = 0 ; j < pci.pci_devices[i].pd_bar_ct; j++) {
+                       if (pci.pci_devices[i].pd_bartype[j] != PCI_BAR_TYPE_IO)
+                               continue;
                        b_lo = PCI_MAPREG_IO_ADDR(pci.pci_devices[i].pd_bar[j]);
                        b_hi = b_lo + VMM_PCI_IO_BAR_SIZE;
                        if (reg >= b_lo && reg < b_hi) {
diff --git a/usr.sbin/vmd/pci.h b/usr.sbin/vmd/pci.h
index 08fb6c650..fce1f7e45 100644
--- a/usr.sbin/vmd/pci.h
+++ b/usr.sbin/vmd/pci.h
@@ -32,6 +32,21 @@ typedef int (*pci_iobar_fn_t)(int dir, uint16_t reg, 
uint32_t *data, uint8_t *,
     void *, uint8_t);
 typedef int (*pci_mmiobar_fn_t)(int dir, uint32_t ofs, uint32_t *data);
 
+#define PTD_VALID 0x01
+
+typedef int (*iocb_t)(int, uint64_t, uint32_t, void *, void *);
+
+struct iohandler {
+       uint64_t start;
+       uint64_t end;
+       iocb_t handler;
+       void *cookie;
+       TAILQ_ENTRY(iohandler) next;
+};
+
+void register_mem(uint64_t base, uint32_t len, iocb_t handler, void *cookie);
+void unregister_mem(uint64_t base);
+int mem_handler(int dir, uint64_t addr, uint32_t size, void *data);
 
 struct pci_dev {
        union {
@@ -70,6 +85,7 @@ struct pci_dev {
        uint32_t pd_barsize[PCI_MAX_BARS];
        void *pd_barfunc[PCI_MAX_BARS];
        void *pd_bar_cookie[PCI_MAX_BARS];
+       void *pd_cookie;
 };
 
 struct pci {
@@ -88,8 +104,8 @@ void pci_handle_data_reg(struct vm_run_params *);
 uint8_t pci_handle_io(struct vm_run_params *);
 void pci_init(void);
 int pci_add_device(uint8_t *, uint16_t, uint16_t, uint8_t, uint8_t, uint16_t,
-    uint16_t, uint8_t, pci_cs_fn_t);
-int pci_add_bar(uint8_t, uint32_t, void *, void *);
+    uint16_t, uint8_t, pci_cs_fn_t, void *);
+int pci_add_bar(uint8_t, uint32_t, uint32_t, void *, void *);
 int pci_set_bar_fn(uint8_t, uint8_t, void *, void *);
 uint8_t pci_get_dev_irq(uint8_t);
 int pci_dump(int);
diff --git a/usr.sbin/vmd/virtio.c b/usr.sbin/vmd/virtio.c
index 8800594fc..430f41995 100644
--- a/usr.sbin/vmd/virtio.c
+++ b/usr.sbin/vmd/virtio.c
@@ -1797,13 +1797,13 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
            PCI_PRODUCT_QUMRANET_VIO_RNG, PCI_CLASS_SYSTEM,
            PCI_SUBCLASS_SYSTEM_MISC,
            PCI_VENDOR_OPENBSD,
-           PCI_PRODUCT_VIRTIO_ENTROPY, 1, NULL)) {
+           PCI_PRODUCT_VIRTIO_ENTROPY, 1, NULL, NULL)) {
                log_warnx("%s: can't add PCI virtio rng device",
                    __progname);
                return;
        }
 
-       if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, virtio_rnd_io, NULL)) {
+       if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, VMM_PCI_IO_BAR_SIZE, 
virtio_rnd_io, NULL)) {
                log_warnx("%s: can't add bar for virtio rng device",
                    __progname);
                return;
@@ -1835,14 +1835,14 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
                            PCI_PRODUCT_QUMRANET_VIO_NET, PCI_CLASS_SYSTEM,
                            PCI_SUBCLASS_SYSTEM_MISC,
                            PCI_VENDOR_OPENBSD,
-                           PCI_PRODUCT_VIRTIO_NETWORK, 1, NULL)) {
+                           PCI_PRODUCT_VIRTIO_NETWORK, 1, NULL, NULL)) {
                                log_warnx("%s: can't add PCI virtio net device",
                                    __progname);
                                return;
                        }
 
-                       if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, virtio_net_io,
-                           &vionet[i])) {
+                       if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, 
VMM_PCI_IO_BAR_SIZE,
+                           virtio_net_io, &vionet[i])) {
                                log_warnx("%s: can't add bar for virtio net "
                                    "device", __progname);
                                return;
@@ -1923,13 +1923,13 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
                            PCI_CLASS_MASS_STORAGE,
                            PCI_SUBCLASS_MASS_STORAGE_SCSI,
                            PCI_VENDOR_OPENBSD,
-                           PCI_PRODUCT_VIRTIO_BLOCK, 1, NULL)) {
+                           PCI_PRODUCT_VIRTIO_BLOCK, 1, NULL, NULL)) {
                                log_warnx("%s: can't add PCI virtio block "
                                    "device", __progname);
                                return;
                        }
-                       if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, virtio_blk_io,
-                           &vioblk[i])) {
+                       if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, 
VMM_PCI_IO_BAR_SIZE,
+                           virtio_blk_io, &vioblk[i])) {
                                log_warnx("%s: can't add bar for virtio block "
                                    "device", __progname);
                                return;
@@ -1971,13 +1971,14 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
                    PCI_CLASS_MASS_STORAGE,
                    PCI_SUBCLASS_MASS_STORAGE_SCSI,
                    PCI_VENDOR_OPENBSD,
-                   PCI_PRODUCT_VIRTIO_SCSI, 1, NULL)) {
+                   PCI_PRODUCT_VIRTIO_SCSI, 1, NULL, NULL)) {
                        log_warnx("%s: can't add PCI vioscsi device",
                            __progname);
                        return;
                }
 
-               if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, vioscsi_io, vioscsi)) {
+               if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, VMM_PCI_IO_BAR_SIZE,
+                   vioscsi_io, vioscsi)) {
                        log_warnx("%s: can't add bar for vioscsi device",
                            __progname);
                        return;
@@ -2013,13 +2014,13 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
            PCI_CLASS_COMMUNICATIONS,
            PCI_SUBCLASS_COMMUNICATIONS_MISC,
            PCI_VENDOR_OPENBSD,
-           PCI_PRODUCT_VIRTIO_VMMCI, 1, NULL)) {
+           PCI_PRODUCT_VIRTIO_VMMCI, 1, NULL, NULL)) {
                log_warnx("%s: can't add PCI vmm control device",
                    __progname);
                return;
        }
 
-       if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, vmmci_io, NULL)) {
+       if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, VMM_PCI_IO_BAR_SIZE, vmmci_io, 
NULL)) {
                log_warnx("%s: can't add bar for vmm control device",
                    __progname);
                return;

Reply via email to