Module Name: src Committed By: reinoud Date: Fri Feb 5 20:45:38 UTC 2021
Modified Files: src/sys/dev/pci: virtio.c Log Message: Better reading of 4.1.3.1, it seems that using 32 bit reads/writes is mandatory for non-legacy devices. To generate a diff of this commit: cvs rdiff -u -r1.46 -r1.47 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.46 src/sys/dev/pci/virtio.c:1.47 --- src/sys/dev/pci/virtio.c:1.46 Fri Feb 5 19:18:23 2021 +++ src/sys/dev/pci/virtio.c Fri Feb 5 20:45:38 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: virtio.c,v 1.46 2021/02/05 19:18:23 reinoud Exp $ */ +/* $NetBSD: virtio.c,v 1.47 2021/02/05 20:45:38 reinoud Exp $ */ /* * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.46 2021/02/05 19:18:23 reinoud Exp $"); +__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.47 2021/02/05 20:45:38 reinoud Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -204,7 +204,7 @@ virtio_read_device_config_4(struct virti /* * The Virtio spec explicitly tells that reading and writing 8 bytes are not * considered atomic and no triggers may be connected to reading or writing - * it. This allows for reading byte-by-byte. + * it. We access it using two 32 reads. See virtio spec 4.1.3.1. */ uint64_t virtio_read_device_config_8(struct virtio_softc *sc, int index) { @@ -212,12 +212,16 @@ virtio_read_device_config_8(struct virti bus_space_handle_t ioh = sc->sc_devcfg_ioh; union { uint64_t u64; - uint8_t b[8]; + uint32_t l[2]; } v; uint64_t val; - for (int i = 0; i < 8; i++) - v.b[i] = bus_space_read_1(iot, ioh, index + i); + v.l[0] = bus_space_read_4(iot, ioh, index); + v.l[1] = bus_space_read_4(iot, ioh, index + 4); + if (sc->sc_bus_endian != sc->sc_struct_endian) { + v.l[0] = bswap32(v.l[0]); + v.l[1] = bswap32(v.l[1]); + } val = v.u64; if (BYTE_ORDER != sc->sc_struct_endian) @@ -306,8 +310,9 @@ virtio_write_device_config_4(struct virt /* * The Virtio spec explicitly tells that reading and writing 8 bytes are not * considered atomic and no triggers may be connected to reading or writing - * it. This allows for writing byte-by-byte. For good measure it is stated to - * always write lsb first just in case of a hypervisor bug. + * it. We access it using two 32 bit writes. For good measure it is stated to + * always write lsb first just in case of a hypervisor bug. See See virtio + * spec 4.1.3.1. */ void virtio_write_device_config_8(struct virtio_softc *sc, int index, uint64_t value) @@ -316,19 +321,25 @@ virtio_write_device_config_8(struct virt bus_space_handle_t ioh = sc->sc_devcfg_ioh; union { uint64_t u64; - uint8_t b[8]; + uint32_t l[2]; } v; if (BYTE_ORDER != sc->sc_struct_endian) value = bswap64(value); v.u64 = value; - if (sc->sc_struct_endian == LITTLE_ENDIAN) - for (int i = 0; i < 8; i++) - bus_space_write_1(iot, ioh, index + i, v.b[i]); - else - for (int i = 7; i >= 0; i--) - bus_space_write_1(iot, ioh, index + i, v.b[i]); + if (sc->sc_bus_endian != sc->sc_struct_endian) { + v.l[0] = bswap32(v.l[0]); + v.l[1] = bswap32(v.l[1]); + } + + if (sc->sc_struct_endian == LITTLE_ENDIAN) { + bus_space_write_4(iot, ioh, index, v.l[0]); + bus_space_write_4(iot, ioh, index + 4, v.l[1]); + } else { + bus_space_write_4(iot, ioh, index + 4, v.l[1]); + bus_space_write_4(iot, ioh, index, v.l[0]); + } } /*