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;