[PATCH v2 2/6] hw/virtio: Simplify virtio_access_is_big_endian()

Philippe Mathieu-Daudé posted 6 patches 1 month, 2 weeks ago
Maintainers: Christian Schoenebeck <qemu_oss@crudebyte.com>, Greg Kurz <groug@kaod.org>, Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>, Jason Wang <jasowang@redhat.com>, Fam Zheng <fam@euphon.net>, "Michael S. Tsirkin" <mst@redhat.com>, Stefano Garzarella <sgarzare@redhat.com>
[PATCH v2 2/6] hw/virtio: Simplify virtio_access_is_big_endian()
Posted by Philippe Mathieu-Daudé 1 month, 2 weeks ago
From: Pierrick Bouvier <pierrick.bouvier@linaro.org>

Thanks to previous refactoring, we can see more easily it is strictly
equivalent to always call virtio_vdev_is_big_endian.

static inline bool virtio_vdev_is_big_endian(VirtIODevice *vdev)
{
    if (virtio_vdev_is_legacy(vdev)) {
        assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
        return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG;
    }
    /* Devices conforming to VIRTIO 1.0 or later are always LE. */
    return false;
}

The key is to understand that vdev->device_endian is initialized as
expected. It always contains cpu endianness, and not
device endianness, ignoring if device is legacy or not.

By default, it's initialized to vdev->device_endian =
virtio_default_endian(), which matches target default endianness.
Then, on virtio_reset, it will be initialized with current_cpu
endianness (if there is one current_cpu).

void virtio_reset() {
    ...
    if (current_cpu) {
        /* Guest initiated reset */
        vdev->device_endian = virtio_current_cpu_endian();
    } else {
        /* System reset */
        vdev->device_endian = virtio_default_endian();
    }

Now, we can see how existing virtio_access_is_big_endian is equivalent
to virtio_vdev_is_big_endian. Let's break the existing function in its 3
variants, and compare that to virtio_vdev_is_big_endian.

static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
- #if defined(LEGACY_VIRTIO_IS_BIENDIAN)
    return virtio_vdev_is_big_endian(vdev);
  This is the exact replacement we did, so equivalent.
- #elif TARGET_BIG_ENDIAN
    if (!virtio_vdev_is_legacy(vdev)) {
        return false;
    }
    return true;

  we know target_is_big_endian(), so
  vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG.
  if (virtio_vdev_is_legacy(vdev)) {
      return VIRTIO_DEVICE_ENDIAN_BIG == VIRTIO_DEVICE_ENDIAN_BIG;
  }
  return false;
  It's written in opposite style compared to existing code (if legacy vs
  if modern), but it's strictly equivalent.
- #else
    return false;
  we know !target_is_big_endian(), so
  vdev->device_endian == VIRTIO_DEVICE_ENDIAN_LITTLE.
  if virtio_vdev_is_legacy(vdev) {
    return VIRTIO_DEVICE_ENDIAN_LITTLE == VIRTIO_DEVICE_ENDIAN_BIG;
  }
  return false;
  So it always return false, as expected.

Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 include/hw/virtio/virtio-access.h | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h
index b8aa7a520f5..e3148c23881 100644
--- a/include/hw/virtio/virtio-access.h
+++ b/include/hw/virtio/virtio-access.h
@@ -21,23 +21,9 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-bus.h"
 
-#if defined(TARGET_PPC64) || defined(TARGET_ARM)
-#define LEGACY_VIRTIO_IS_BIENDIAN 1
-#endif
-
 static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
 {
-#if defined(LEGACY_VIRTIO_IS_BIENDIAN)
     return virtio_vdev_is_big_endian(vdev);
-#elif TARGET_BIG_ENDIAN
-    if (!virtio_vdev_is_legacy(vdev)) {
-        /* Devices conforming to VIRTIO 1.0 or later are always LE. */
-        return false;
-    }
-    return true;
-#else
-    return false;
-#endif
 }
 
 static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v)
-- 
2.52.0


Re: [PATCH v2 2/6] hw/virtio: Simplify virtio_access_is_big_endian()
Posted by Richard Henderson 1 month, 2 weeks ago
On 2/25/26 15:19, Philippe Mathieu-Daudé wrote:
> From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> 
> Thanks to previous refactoring, we can see more easily it is strictly
> equivalent to always call virtio_vdev_is_big_endian.
> 
> static inline bool virtio_vdev_is_big_endian(VirtIODevice *vdev)
> {
>      if (virtio_vdev_is_legacy(vdev)) {
>          assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
>          return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG;
>      }
>      /* Devices conforming to VIRTIO 1.0 or later are always LE. */
>      return false;
> }
> 
> The key is to understand that vdev->device_endian is initialized as
> expected. It always contains cpu endianness, and not
> device endianness, ignoring if device is legacy or not.
> 
> By default, it's initialized to vdev->device_endian =
> virtio_default_endian(), which matches target default endianness.
> Then, on virtio_reset, it will be initialized with current_cpu
> endianness (if there is one current_cpu).
> 
> void virtio_reset() {
>      ...
>      if (current_cpu) {
>          /* Guest initiated reset */
>          vdev->device_endian = virtio_current_cpu_endian();
>      } else {
>          /* System reset */
>          vdev->device_endian = virtio_default_endian();
>      }
> 
> Now, we can see how existing virtio_access_is_big_endian is equivalent
> to virtio_vdev_is_big_endian. Let's break the existing function in its 3
> variants, and compare that to virtio_vdev_is_big_endian.
> 
> static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
> - #if defined(LEGACY_VIRTIO_IS_BIENDIAN)
>      return virtio_vdev_is_big_endian(vdev);
>    This is the exact replacement we did, so equivalent.
> - #elif TARGET_BIG_ENDIAN
>      if (!virtio_vdev_is_legacy(vdev)) {
>          return false;
>      }
>      return true;
> 
>    we know target_is_big_endian(), so
>    vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG.
>    if (virtio_vdev_is_legacy(vdev)) {
>        return VIRTIO_DEVICE_ENDIAN_BIG == VIRTIO_DEVICE_ENDIAN_BIG;
>    }
>    return false;
>    It's written in opposite style compared to existing code (if legacy vs
>    if modern), but it's strictly equivalent.
> - #else
>      return false;
>    we know !target_is_big_endian(), so
>    vdev->device_endian == VIRTIO_DEVICE_ENDIAN_LITTLE.
>    if virtio_vdev_is_legacy(vdev) {
>      return VIRTIO_DEVICE_ENDIAN_LITTLE == VIRTIO_DEVICE_ENDIAN_BIG;
>    }
>    return false;
>    So it always return false, as expected.
> 
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> ---
>   include/hw/virtio/virtio-access.h | 14 --------------
>   1 file changed, 14 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~

> 
> diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h
> index b8aa7a520f5..e3148c23881 100644
> --- a/include/hw/virtio/virtio-access.h
> +++ b/include/hw/virtio/virtio-access.h
> @@ -21,23 +21,9 @@
>   #include "hw/virtio/virtio.h"
>   #include "hw/virtio/virtio-bus.h"
>   
> -#if defined(TARGET_PPC64) || defined(TARGET_ARM)
> -#define LEGACY_VIRTIO_IS_BIENDIAN 1
> -#endif
> -
>   static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
>   {
> -#if defined(LEGACY_VIRTIO_IS_BIENDIAN)
>       return virtio_vdev_is_big_endian(vdev);
> -#elif TARGET_BIG_ENDIAN
> -    if (!virtio_vdev_is_legacy(vdev)) {
> -        /* Devices conforming to VIRTIO 1.0 or later are always LE. */
> -        return false;
> -    }
> -    return true;
> -#else
> -    return false;
> -#endif
>   }
>   
>   static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v)