Index: sys/dev/virtio/pci/virtio_pci_modern.c =================================================================== --- sys/dev/virtio/pci/virtio_pci_modern.c +++ sys/dev/virtio/pci/virtio_pci_modern.c @@ -146,6 +146,11 @@ static void vtpci_modern_probe_and_attach_child(struct vtpci_modern_softc *); +static void vtpci_modern_read_dev_common(device_t dev, bus_size_t offset, + void *dst, int length); +static void vtpci_modern_write_dev_common(device_t dev, bus_size_t offset, + uint64_t src, int length); + static uint64_t vtpci_modern_read_features(struct vtpci_modern_softc *); static void vtpci_modern_write_features(struct vtpci_modern_softc *, uint64_t); @@ -167,8 +172,6 @@ bus_size_t, uint16_t); static void vtpci_modern_write_common_4(struct vtpci_modern_softc *, bus_size_t, uint32_t); -static void vtpci_modern_write_common_8(struct vtpci_modern_softc *, - bus_size_t, uint64_t); static void vtpci_modern_write_notify_2(struct vtpci_modern_softc *, bus_size_t, uint16_t); static uint8_t vtpci_modern_read_isr_1(struct vtpci_modern_softc *, @@ -489,10 +492,10 @@ { uint32_t features0, features1; - vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_DFSELECT, 0); - features0 = vtpci_modern_read_common_4(sc, VIRTIO_PCI_COMMON_DF); - vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_DFSELECT, 1); - features1 = vtpci_modern_read_common_4(sc, VIRTIO_PCI_COMMON_DF); + vtpci_modern_write_dev_common(sc->vtpci_dev, VIRTIO_PCI_COMMON_DFSELECT, 0, 4); + vtpci_modern_read_dev_common(sc->vtpci_dev, VIRTIO_PCI_COMMON_DF, &features0, 4); + vtpci_modern_write_dev_common(sc->vtpci_dev, VIRTIO_PCI_COMMON_DFSELECT, 1, 4); + vtpci_modern_read_dev_common(sc->vtpci_dev, VIRTIO_PCI_COMMON_DF, &features1, 4); return (((uint64_t) features1 << 32) | features0); } @@ -505,10 +508,10 @@ features0 = features; features1 = features >> 32; - vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_GFSELECT, 0); - vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_GF, features0); - vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_GFSELECT, 1); - vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_GF, features1); + vtpci_modern_write_dev_common(sc->vtpci_dev, VIRTIO_PCI_COMMON_GFSELECT, 0, 4); + vtpci_modern_write_dev_common(sc->vtpci_dev, VIRTIO_PCI_COMMON_GF, features0, 4); + vtpci_modern_write_dev_common(sc->vtpci_dev, VIRTIO_PCI_COMMON_GFSELECT, 1, 4); + vtpci_modern_write_dev_common(sc->vtpci_dev, VIRTIO_PCI_COMMON_GF, features1, 4); } static int @@ -522,7 +525,8 @@ sc = device_get_softc(dev); cn = &sc->vtpci_common; - max_nvqs = vtpci_modern_read_common_2(sc, VIRTIO_PCI_COMMON_NUMQ); + vtpci_modern_read_dev_common(sc->vtpci_dev, VIRTIO_PCI_COMMON_NUMQ, &max_nvqs, 2); + if (nvqs > max_nvqs) { device_printf(sc->vtpci_dev, "requested virtqueue count %d " "exceeds max %d\n", nvqs, max_nvqs); @@ -650,6 +654,80 @@ return (gen); } +static void +vtpci_modern_read_dev_common(device_t dev, bus_size_t offset, void *dst, + int length) +{ + struct vtpci_modern_softc *sc; + + sc = device_get_softc(dev); + + if (sc->vtpci_common_res_map.vtrm_map.r_size == 0) { + panic("%s: attempt to read dev common but not present", + __func__); + } + + switch (length) { + case 1: + *(uint8_t *) dst = vtpci_modern_read_common_1(sc, offset); + break; + case 2: + *(uint16_t *) dst = virtio_htog16(true, + vtpci_modern_read_common_2(sc, offset)); + break; + case 4: + *(uint32_t *) dst = virtio_htog32(true, + vtpci_modern_read_common_4(sc, offset)); + break; + default: + panic("%s: device %s invalid common read length %d offset %d", + __func__, device_get_nameunit(dev), length, (int) offset); + } +} + +static void +vtpci_modern_write_dev_common(device_t dev, bus_size_t offset, uint64_t src, + int length) +{ + struct vtpci_modern_softc *sc; + + sc = device_get_softc(dev); + + if (sc->vtpci_common_res_map.vtrm_map.r_size == 0) { + panic("%s: attempt to write dev common but not present", + __func__); + } + + switch (length) { + case 1: + vtpci_modern_write_common_1(sc, offset, (uint8_t) src); + break; + case 2: { + uint16_t val = virtio_gtoh16(true, (uint16_t) src); + vtpci_modern_write_common_2(sc, offset, val); + break; + } + case 4: { + uint32_t val = virtio_gtoh32(true, (uint32_t) src); + vtpci_modern_write_common_4(sc, offset, val); + break; + } + case 8: { + uint32_t val0, val1; + val0 = src; + val1 = src >> 32; + vtpci_modern_write_common_4(sc, offset, virtio_gtoh32(true, val0)); + vtpci_modern_write_common_4(sc, offset + 4, virtio_gtoh32(true, val1)); + break; + } + default: + panic("%s: device %s invalid common write length %d offset %d", + __func__, device_get_nameunit(dev), length, (int) offset); + } +} + + + static void vtpci_modern_read_dev_config(device_t dev, bus_size_t offset, void *dst, int length) @@ -1160,7 +1238,7 @@ vtpci_modern_register_msix(struct vtpci_modern_softc *sc, int offset, struct vtpci_interrupt *intr) { - uint16_t vector; + uint16_t vector, val; if (intr != NULL) { /* Map from guest rid to host vector. */ @@ -1168,8 +1246,9 @@ } else vector = VIRTIO_MSI_NO_VECTOR; - vtpci_modern_write_common_2(sc, offset, vector); - return (vtpci_modern_read_common_2(sc, offset) == vector ? 0 : ENODEV); + vtpci_modern_write_dev_common(sc->vtpci_dev, offset, vector, 2); + vtpci_modern_read_dev_common(sc->vtpci_dev, offset, &val, 2); + return (val == vector ? 0 : ENODEV); } static int @@ -1227,7 +1306,8 @@ static void vtpci_modern_select_virtqueue(struct vtpci_modern_softc *sc, int idx) { - vtpci_modern_write_common_2(sc, VIRTIO_PCI_COMMON_Q_SELECT, idx); + vtpci_modern_write_dev_common(sc->vtpci_dev, + VIRTIO_PCI_COMMON_Q_SELECT, (uint64_t) idx, 2); } static uint8_t @@ -1240,11 +1320,12 @@ vtpci_modern_get_vq_size(device_t dev, int idx) { struct vtpci_modern_softc *sc; + uint16_t vtq_size; sc = device_get_softc(dev); - vtpci_modern_select_virtqueue(sc, idx); - return (vtpci_modern_read_common_2(sc, VIRTIO_PCI_COMMON_Q_SIZE)); + vtpci_modern_read_dev_common(dev, VIRTIO_PCI_COMMON_Q_SIZE, &vtq_size, 2); + return vtq_size; } static bus_size_t @@ -1256,7 +1337,7 @@ sc = device_get_softc(dev); vtpci_modern_select_virtqueue(sc, idx); - q_notify_off = vtpci_modern_read_common_2(sc, VIRTIO_PCI_COMMON_Q_NOFF); + vtpci_modern_read_dev_common(dev, VIRTIO_PCI_COMMON_Q_NOFF, &q_notify_off, 2); return (q_notify_off * sc->vtpci_notify_offset_multiplier); } @@ -1265,21 +1346,27 @@ vtpci_modern_set_vq(device_t dev, struct virtqueue *vq) { struct vtpci_modern_softc *sc; + uint16_t vtq_size; + uint64_t addr; sc = device_get_softc(dev); vtpci_modern_select_virtqueue(sc, virtqueue_index(vq)); /* BMV: Currently we never adjust the device's proposed VQ size. */ - vtpci_modern_write_common_2(sc, - VIRTIO_PCI_COMMON_Q_SIZE, virtqueue_size(vq)); + vtq_size = virtqueue_size(vq); + vtpci_modern_write_dev_common(sc->vtpci_dev, + VIRTIO_PCI_COMMON_Q_SIZE, vtq_size, 2); - vtpci_modern_write_common_8(sc, - VIRTIO_PCI_COMMON_Q_DESCLO, virtqueue_desc_paddr(vq)); - vtpci_modern_write_common_8(sc, - VIRTIO_PCI_COMMON_Q_AVAILLO, virtqueue_avail_paddr(vq)); - vtpci_modern_write_common_8(sc, - VIRTIO_PCI_COMMON_Q_USEDLO, virtqueue_used_paddr(vq)); + addr = virtqueue_desc_paddr(vq); + vtpci_modern_write_dev_common(sc->vtpci_dev, + VIRTIO_PCI_COMMON_Q_DESCLO, addr, 8); + addr = virtqueue_avail_paddr(vq); + vtpci_modern_write_dev_common(sc->vtpci_dev, + VIRTIO_PCI_COMMON_Q_AVAILLO, addr, 8); + addr = virtqueue_used_paddr(vq); + vtpci_modern_write_dev_common(sc->vtpci_dev, + VIRTIO_PCI_COMMON_Q_USEDLO, addr, 8); } static void @@ -1290,9 +1377,12 @@ sc = device_get_softc(dev); vtpci_modern_select_virtqueue(sc, idx); - vtpci_modern_write_common_8(sc, VIRTIO_PCI_COMMON_Q_DESCLO, 0ULL); - vtpci_modern_write_common_8(sc, VIRTIO_PCI_COMMON_Q_AVAILLO, 0ULL); - vtpci_modern_write_common_8(sc, VIRTIO_PCI_COMMON_Q_USEDLO, 0ULL); + vtpci_modern_write_dev_common(sc->vtpci_dev, + VIRTIO_PCI_COMMON_Q_DESCLO, 0ULL, 8); + vtpci_modern_write_dev_common(sc->vtpci_dev, + VIRTIO_PCI_COMMON_Q_AVAILLO, 0ULL, 8); + vtpci_modern_write_dev_common(sc->vtpci_dev, + VIRTIO_PCI_COMMON_Q_USEDLO, 0ULL, 8); } static void @@ -1302,7 +1392,8 @@ for (idx = 0; idx < sc->vtpci_common.vtpci_nvqs; idx++) { vtpci_modern_select_virtqueue(sc, idx); - vtpci_modern_write_common_2(sc, VIRTIO_PCI_COMMON_Q_ENABLE, 1); + vtpci_modern_write_dev_common(sc->vtpci_dev, + VIRTIO_PCI_COMMON_Q_ENABLE, 1, 2); } } @@ -1345,19 +1436,6 @@ bus_write_4(&sc->vtpci_common_res_map.vtrm_map, off, val); } -static void -vtpci_modern_write_common_8(struct vtpci_modern_softc *sc, bus_size_t off, - uint64_t val) -{ - uint32_t val0, val1; - - val0 = (uint32_t) val; - val1 = val >> 32; - - vtpci_modern_write_common_4(sc, off, val0); - vtpci_modern_write_common_4(sc, off + 4, val1); -} - static void vtpci_modern_write_notify_2(struct vtpci_modern_softc *sc, bus_size_t off, uint16_t val)