[PATCH v3 9/9] hw/virtio: Support runtime endianness in virtio access helpers

Djordje Todorovic posted 9 patches 3 weeks, 6 days ago
There is a newer version of this series
[PATCH v3 9/9] hw/virtio: Support runtime endianness in virtio access helpers
Posted by Djordje Todorovic 3 weeks, 6 days ago
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
Re: [PATCH v3 9/9] hw/virtio: Support runtime endianness in virtio access helpers
Posted by Philippe Mathieu-Daudé 3 weeks, 6 days ago
On 11/3/26 12:59, Djordje Todorovic wrote:
> 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
>   }

See commit 93b32a87377 and around, and please rebase your series on
current /master.