Module Name: src Committed By: martin Date: Sat Mar 25 13:05:09 UTC 2017
Modified Files: src/sys/dev/pci: virtio.c Log Message: PR kern/52107: for now (while we still use the legacy virtio spec) at least hack around the endianess issues with that. To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/sys/dev/pci/virtio.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/virtio.c diff -u src/sys/dev/pci/virtio.c:1.19 src/sys/dev/pci/virtio.c:1.20 --- src/sys/dev/pci/virtio.c:1.19 Tue Nov 29 22:04:42 2016 +++ src/sys/dev/pci/virtio.c Sat Mar 25 13:05:09 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: virtio.c,v 1.19 2016/11/29 22:04:42 uwe Exp $ */ +/* $NetBSD: virtio.c,v 1.20 2017/03/25 13:05:09 martin Exp $ */ /* * Copyright (c) 2010 Minoura Makoto. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.19 2016/11/29 22:04:42 uwe Exp $"); +__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.20 2017/03/25 13:05:09 martin Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -67,6 +67,45 @@ CFATTACH_DECL3_NEW(virtio, sizeof(struct virtio_match, virtio_attach, virtio_detach, NULL, virtio_rescan, NULL, DVF_DETACH_SHUTDOWN); +/* we use the legacy virtio spec, so the pci registers are host native + * byte order, not pci (i.e. LE) byte order */ +static inline uint16_t +nbo_bus_space_read_2(bus_space_tag_t space, bus_space_handle_t handle, + bus_size_t offset) +{ + return le16toh(bus_space_read_2(space, handle, offset)); +} + +static inline uint32_t +nbo_bus_space_read_4(bus_space_tag_t space, bus_space_handle_t handle, + bus_size_t offset) +{ + return le32toh(bus_space_read_4(space, handle, offset)); +} + +static void +nbo_bus_space_write_2(bus_space_tag_t space, bus_space_handle_t handle, + bus_size_t offset, uint16_t value) +{ + bus_space_write_2(space, handle, offset, htole16(value)); +} + +static void +nbo_bus_space_write_4(bus_space_tag_t space, bus_space_handle_t handle, + bus_size_t offset, uint16_t value) +{ + bus_space_write_4(space, handle, offset, htole32(value)); +} + +/* some functions access registers at 4 byte offset for little/high halves */ +#if BYTE_ORDER == BIG_ENDIAN +#define REG_HI_OFF 0 +#define REG_LO_OFF 4 +#else +#define REG_HI_OFF 4 +#define REG_LO_OFF 0 +#endif + static void virtio_set_status(struct virtio_softc *sc, int status) { @@ -126,8 +165,8 @@ virtio_setup_msix_vectors(struct virtio_ offset = VIRTIO_CONFIG_MSI_CONFIG_VECTOR; vector = VIRTIO_MSIX_CONFIG_VECTOR_INDEX; - bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, vector); - ret = bus_space_read_2(sc->sc_iot, sc->sc_ioh, offset); + nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, vector); + ret = nbo_bus_space_read_2(sc->sc_iot, sc->sc_ioh, offset); aprint_debug_dev(sc->sc_dev, "expected=%d, actual=%d\n", vector, ret); if (ret != vector) @@ -135,13 +174,13 @@ virtio_setup_msix_vectors(struct virtio_ for (qid = 0; qid < sc->sc_nvqs; qid++) { offset = VIRTIO_CONFIG_QUEUE_SELECT; - bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, qid); + nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, qid); offset = VIRTIO_CONFIG_MSI_QUEUE_VECTOR; vector = VIRTIO_MSIX_QUEUE_VECTOR_INDEX; - bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, vector); - ret = bus_space_read_2(sc->sc_iot, sc->sc_ioh, offset); + nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, vector); + ret = nbo_bus_space_read_2(sc->sc_iot, sc->sc_ioh, offset); aprint_debug_dev(sc->sc_dev, "expected=%d, actual=%d\n", vector, ret); if (ret != vector) @@ -473,10 +512,10 @@ virtio_reinit_start(struct virtio_softc for (i = 0; i < sc->sc_nvqs; i++) { int n; struct virtqueue *vq = &sc->sc_vqs[i]; - bus_space_write_2(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT, vq->vq_index); - n = bus_space_read_2(sc->sc_iot, sc->sc_ioh, + n = nbo_bus_space_read_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SIZE); if (n == 0) /* vq disappeared */ continue; @@ -486,7 +525,7 @@ virtio_reinit_start(struct virtio_softc vq->vq_index); } virtio_init_vq(sc, vq, true); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_ADDRESS, (vq->vq_dmamap->dm_segs[0].ds_addr / VIRTIO_PAGE_SIZE)); @@ -519,10 +558,10 @@ virtio_negotiate_features(struct virtio_ if (!(device_cfdata(sc->sc_dev)->cf_flags & 1) && !(device_cfdata(sc->sc_child)->cf_flags & 1)) /* XXX */ guest_features |= VIRTIO_F_RING_INDIRECT_DESC; - r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + r = nbo_bus_space_read_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_DEVICE_FEATURES); r &= guest_features; - bus_space_write_4(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_GUEST_FEATURES, r); sc->sc_features = r; if (r & VIRTIO_F_RING_INDIRECT_DESC) @@ -546,14 +585,14 @@ virtio_read_device_config_1(struct virti uint16_t virtio_read_device_config_2(struct virtio_softc *sc, int index) { - return bus_space_read_2(sc->sc_iot, sc->sc_ioh, + return nbo_bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_config_offset + index); } uint32_t virtio_read_device_config_4(struct virtio_softc *sc, int index) { - return bus_space_read_4(sc->sc_iot, sc->sc_ioh, + return nbo_bus_space_read_4(sc->sc_iot, sc->sc_ioh, sc->sc_config_offset + index); } @@ -562,11 +601,12 @@ virtio_read_device_config_8(struct virti { uint64_t r; - r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, - sc->sc_config_offset + index + sizeof(uint32_t)); + r = nbo_bus_space_read_4(sc->sc_iot, sc->sc_ioh, + sc->sc_config_offset + index + REG_HI_OFF); r <<= 32; - r += bus_space_read_4(sc->sc_iot, sc->sc_ioh, - sc->sc_config_offset + index); + r |= nbo_bus_space_read_4(sc->sc_iot, sc->sc_ioh, + sc->sc_config_offset + index + REG_LO_OFF); + return r; } @@ -582,7 +622,7 @@ void virtio_write_device_config_2(struct virtio_softc *sc, int index, uint16_t value) { - bus_space_write_2(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_config_offset + index, value); } @@ -590,7 +630,7 @@ void virtio_write_device_config_4(struct virtio_softc *sc, int index, uint32_t value) { - bus_space_write_4(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_config_offset + index, value); } @@ -598,11 +638,11 @@ void virtio_write_device_config_8(struct virtio_softc *sc, int index, uint64_t value) { - bus_space_write_4(sc->sc_iot, sc->sc_ioh, - sc->sc_config_offset + index, + nbo_bus_space_write_4(sc->sc_iot, sc->sc_ioh, + sc->sc_config_offset + index + REG_LO_OFF, value & 0xffffffff); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, - sc->sc_config_offset + index + sizeof(uint32_t), + nbo_bus_space_write_4(sc->sc_iot, sc->sc_ioh, + sc->sc_config_offset + index + REG_HI_OFF, value >> 32); } @@ -822,9 +862,9 @@ virtio_alloc_vq(struct virtio_softc *sc, memset(vq, 0, sizeof(*vq)); - bus_space_write_2(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT, index); - vq_size = bus_space_read_2(sc->sc_iot, sc->sc_ioh, + vq_size = nbo_bus_space_read_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SIZE); if (vq_size == 0) { aprint_error_dev(sc->sc_dev, @@ -880,7 +920,7 @@ virtio_alloc_vq(struct virtio_softc *sc, } /* set the vq address */ - bus_space_write_4(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_ADDRESS, (vq->vq_dmamap->dm_segs[0].ds_addr / VIRTIO_PAGE_SIZE)); @@ -924,7 +964,7 @@ virtio_alloc_vq(struct virtio_softc *sc, return 0; err: - bus_space_write_4(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_ADDRESS, 0); if (vq->vq_dmamap) bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap); @@ -955,9 +995,9 @@ virtio_free_vq(struct virtio_softc *sc, } /* tell device that there's no virtqueue any longer */ - bus_space_write_2(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_SELECT, vq->vq_index); - bus_space_write_4(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_ADDRESS, 0); kmem_free(vq->vq_entries, sizeof(*vq->vq_entries) * vq->vq_num); @@ -1207,7 +1247,7 @@ notify: vq_sync_uring(sc, vq, BUS_DMASYNC_POSTREAD); membar_consumer(); if (!(vq->vq_used->flags & VRING_USED_F_NO_NOTIFY)) - bus_space_write_2(sc->sc_iot, sc->sc_ioh, + nbo_bus_space_write_2(sc->sc_iot, sc->sc_ioh, VIRTIO_CONFIG_QUEUE_NOTIFY, vq->vq_index); }