Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Second round of cleaning up endian code. No more...



details:   https://anonhg.NetBSD.org/src/rev/cf1ccdbf7a44
branches:  trunk
changeset: 1018490:cf1ccdbf7a44
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Fri Feb 05 19:18:23 2021 +0000

description:
Second round of cleaning up endian code. No more tailored code to maintain.

diffstat:

 sys/dev/pci/virtio.c     |  79 +++++++++++++++++++++--------------------------
 sys/dev/pci/virtio_pci.c |  15 ++------
 sys/dev/pci/virtiovar.h  |   5 +--
 3 files changed, 41 insertions(+), 58 deletions(-)

diffs (185 lines):

diff -r e0a38e1aede1 -r cf1ccdbf7a44 sys/dev/pci/virtio.c
--- a/sys/dev/pci/virtio.c      Fri Feb 05 17:20:32 2021 +0000
+++ b/sys/dev/pci/virtio.c      Fri Feb 05 19:18:23 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: virtio.c,v 1.45 2021/01/28 15:43:12 reinoud Exp $      */
+/*     $NetBSD: virtio.c,v 1.46 2021/02/05 19:18:23 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.45 2021/01/28 15:43:12 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.46 2021/02/05 19:18:23 reinoud Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -201,32 +201,27 @@
        return val;
 }
 
+/*
+ * 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.
+ */
 uint64_t
 virtio_read_device_config_8(struct virtio_softc *sc, int index) {
        bus_space_tag_t    iot = sc->sc_devcfg_iot;
        bus_space_handle_t ioh = sc->sc_devcfg_ioh;
-       uint64_t val, val_0, val_1, val_l, val_h;
+       union {
+               uint64_t u64;
+               uint8_t  b[8];
+       } v;
+       uint64_t val;
 
-       val_0 = bus_space_read_4(iot, ioh, index);
-       val_1 = bus_space_read_4(iot, ioh, index + 4);
-       if (BYTE_ORDER != sc->sc_bus_endian) {
-               val_l = bswap32(val_1);
-               val_h = bswap32(val_0);
-       } else {
-               val_l = val_0;
-               val_h = val_1;
-       }
+       for (int i = 0; i < 8; i++)
+               v.b[i] = bus_space_read_1(iot, ioh, index + i);
+       val = v.u64;
 
-#ifdef AARCH64EB_PROBLEM
-       /* XXX see comment at virtio_pci.c */
-       if (sc->sc_aarch64eb_bus_problem) {
-               val_l = val_1;
-               val_h = val_0;
-       }
-#endif
-
-       val = val_h << 32;
-       val |= val_l;
+       if (BYTE_ORDER != sc->sc_struct_endian)
+               val = bswap64(val);
 
        DPRINTFR("read_8", "%08lx", val, index, 8);
        DPRINTFR2("read_8 low ", "%08x",
@@ -308,34 +303,32 @@
        bus_space_write_4(iot, ioh, index, value);
 }
 
+/*
+ * 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.
+ */
 void
 virtio_write_device_config_8(struct virtio_softc *sc, int index, uint64_t value)
 {
        bus_space_tag_t    iot = sc->sc_devcfg_iot;
        bus_space_handle_t ioh = sc->sc_devcfg_ioh;
-       uint64_t val_0, val_1, val_l, val_h;
+       union {
+               uint64_t u64;
+               uint8_t  b[8];
+       } v;
 
-       val_l = BUS_ADDR_LO32(value);
-       val_h = BUS_ADDR_HI32(value);
+       if (BYTE_ORDER != sc->sc_struct_endian)
+               value = bswap64(value);
 
-       if (BYTE_ORDER != sc->sc_bus_endian) {
-               val_0 = bswap32(val_h);
-               val_1 = bswap32(val_l);
-       } else {
-               val_0 = val_l;
-               val_1 = val_h;
-       }
-
-#ifdef AARCH64EB_PROBLEM
-       /* XXX see comment at virtio_pci.c */
-       if (sc->sc_aarch64eb_bus_problem) {
-               val_0 = val_h;
-               val_1 = val_l;
-       }
-#endif
-
-       bus_space_write_4(iot, ioh, index, val_0);
-       bus_space_write_4(iot, ioh, index + 4, val_1);
+       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]);
 }
 
 /*
diff -r e0a38e1aede1 -r cf1ccdbf7a44 sys/dev/pci/virtio_pci.c
--- a/sys/dev/pci/virtio_pci.c  Fri Feb 05 17:20:32 2021 +0000
+++ b/sys/dev/pci/virtio_pci.c  Fri Feb 05 19:18:23 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: virtio_pci.c,v 1.27 2021/01/28 15:43:12 reinoud Exp $ */
+/* $NetBSD: virtio_pci.c,v 1.28 2021/02/05 19:18:23 reinoud Exp $ */
 
 /*
  * Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: virtio_pci.c,v 1.27 2021/01/28 15:43:12 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: virtio_pci.c,v 1.28 2021/02/05 19:18:23 reinoud Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -127,15 +127,11 @@
  * suddenly read BIG_ENDIAN where it should stay LITTLE_ENDIAN. The data read
  * 1 byte at a time seem OK but reading bigger lengths result in swapped
  * endian. This is most notable on reading 8 byters since we can't use
- * bus_space_{read,write}_8() and it has to be patched there explicitly. We
- * define the AARCH64EB_PROBLEM to signal we're vulnerable to this and set the
- * accompanied sc->sc_aarch64_eb_bus_problem variable when attaching using the
- * IO space.
+ * bus_space_{read,write}_8().
  */
 
 #if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN
-       /* source of AARCH64EB_PROBLEM */
-#      define READ_ENDIAN_09   BIG_ENDIAN      /* XXX bug, should be LITTLE_ENDIAN */
+#      define READ_ENDIAN_09   BIG_ENDIAN      /* should be LITTLE_ENDIAN */
 #      define READ_ENDIAN_10   BIG_ENDIAN
 #      define STRUCT_ENDIAN_09 BIG_ENDIAN
 #      define STRUCT_ENDIAN_10 LITTLE_ENDIAN
@@ -369,9 +365,6 @@
        sc->sc_ops = &virtio_pci_ops_09;
        sc->sc_bus_endian    = READ_ENDIAN_09;
        sc->sc_struct_endian = STRUCT_ENDIAN_09;
-#if defined(__aarch64__) && BYTE_ORDER == BIG_ENDIAN
-       sc->sc_aarch64eb_bus_problem = true;
-#endif
        return 0;
 }
 
diff -r e0a38e1aede1 -r cf1ccdbf7a44 sys/dev/pci/virtiovar.h
--- a/sys/dev/pci/virtiovar.h   Fri Feb 05 17:20:32 2021 +0000
+++ b/sys/dev/pci/virtiovar.h   Fri Feb 05 19:18:23 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: virtiovar.h,v 1.19 2021/01/28 15:43:12 reinoud Exp $   */
+/*     $NetBSD: virtiovar.h,v 1.20 2021/02/05 19:18:23 reinoud Exp $   */
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -148,9 +148,6 @@
        const struct virtio_ops *sc_ops;
        bus_dma_tag_t           sc_dmat;
 
-#define AARCH64EB_PROBLEM      /* see comment in virtio_pci.c */
-       bool                    sc_aarch64eb_bus_problem;
-
        int                     sc_bus_endian;
        int                     sc_struct_endian;
 



Home | Main Index | Thread Index | Old Index