For targets compiled as little-endian but supporting runtime big-endian
mode (e.g. RISC-V with big-endian=true), virtio_access_is_big_endian()
unconditionally returned false. This caused legacy virtio config space
values to be stored in LE byte order even when the guest runs in BE mode,
leading to byte-swapped config reads (e.g. virtio-blk block size 512
read as 131072).

Use target_big_endian() in the #else branch to detect runtime endianness.
For LE targets that are truly LE, target_big_endian() returns false so
behavior is unchanged. For bi-endian targets running in BE mode, config
values are now correctly stored in BE byte order, matching what the
guest's le32_to_cpu() conversion expects.
---
 include/hw/virtio/virtio-access.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/hw/virtio/virtio-access.h 
b/include/hw/virtio/virtio-access.h
index b58fb6ed7e..a3f1b9f5fe 100644
--- a/include/hw/virtio/virtio-access.h
+++ b/include/hw/virtio/virtio-access.h
@@ -20,6 +20,7 @@
 #include "system/memory_cached.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-bus.h"
+#include "qemu/target-info.h"
 
 #if defined(TARGET_PPC64) || defined(TARGET_ARM)
 #define LEGACY_VIRTIO_IS_BIENDIAN 1
@@ -36,7 +37,10 @@ static inline bool virtio_access_is_big_endian(VirtIODevice 
*vdev)
     }
     return true;
 #else
-    return false;
+    if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+        return false;
+    }
+    return target_big_endian();
 #endif
 }
 
-- 
2.34.1

Reply via email to