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]);
+ }
}
/*