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

Reply via email to