qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] tests/qtest/libqos: Avoid double swapping when using modern virtio
@ 2025-04-30 13:28 Thomas Huth
  2025-04-30 13:50 ` Philippe Mathieu-Daudé
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Thomas Huth @ 2025-04-30 13:28 UTC (permalink / raw)
  To: Fabiano Rosas, qemu-devel, Philippe Mathieu-Daudé
  Cc: Laurent Vivier, Paolo Bonzini, Pierrick Bouvier

From: Thomas Huth <thuth@redhat.com>

The logic in the qvirtio_read/write function is rather a headache,
involving byte-swapping when the target is big endian, just to
maybe involve another byte-swapping  in the qtest_read/write
function immediately afterwards (on the QEMU side). Let's do it in
a more obvious way here: For virtio 1.0, we know that the values have
to be little endian, so let's read/write the bytes in that well known
order here.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 This also decreases our usage of qtest_big_endian() which might (or
 might not) get helpful for the universal binary one day...

 v2: Use leXX_to_cpu() / cpu_to_leXX() instead of doing it manually

 tests/qtest/libqos/virtio.c | 44 ++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 15 deletions(-)

diff --git a/tests/qtest/libqos/virtio.c b/tests/qtest/libqos/virtio.c
index 2e7979652fd..5a709d0bc59 100644
--- a/tests/qtest/libqos/virtio.c
+++ b/tests/qtest/libqos/virtio.c
@@ -25,49 +25,63 @@
  */
 static uint16_t qvirtio_readw(QVirtioDevice *d, QTestState *qts, uint64_t addr)
 {
-    uint16_t val = qtest_readw(qts, addr);
+    uint16_t val;
 
-    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
-        val = bswap16(val);
+    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
+        qtest_memread(qts, addr, &val, sizeof(val));
+        val = le16_to_cpu(val);
+    } else {
+        val = qtest_readw(qts, addr);
     }
+
     return val;
 }
 
 static uint32_t qvirtio_readl(QVirtioDevice *d, QTestState *qts, uint64_t addr)
 {
-    uint32_t val = qtest_readl(qts, addr);
+    uint32_t val;
 
-    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
-        val = bswap32(val);
+    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
+        qtest_memread(qts, addr, &val, sizeof(val));
+        val = le32_to_cpu(val);
+    } else {
+        val = qtest_readl(qts, addr);
     }
+
     return val;
 }
 
 static void qvirtio_writew(QVirtioDevice *d, QTestState *qts,
                            uint64_t addr, uint16_t val)
 {
-    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
-        val = bswap16(val);
+    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
+        val = cpu_to_le16(val);
+        qtest_memwrite(qts, addr, &val, sizeof(val));
+    } else {
+        qtest_writew(qts, addr, val);
     }
-    qtest_writew(qts, addr, val);
 }
 
 static void qvirtio_writel(QVirtioDevice *d, QTestState *qts,
                            uint64_t addr, uint32_t val)
 {
-    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
-        val = bswap32(val);
+    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
+        val = cpu_to_le32(val);
+        qtest_memwrite(qts, addr, &val, sizeof(val));
+    } else {
+        qtest_writel(qts, addr, val);
     }
-    qtest_writel(qts, addr, val);
 }
 
 static void qvirtio_writeq(QVirtioDevice *d, QTestState *qts,
                            uint64_t addr, uint64_t val)
 {
-    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
-        val = bswap64(val);
+    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
+        val = cpu_to_le64(val);
+        qtest_memwrite(qts, addr, &val, sizeof(val));
+    } else {
+        qtest_writeq(qts, addr, val);
     }
-    qtest_writeq(qts, addr, val);
 }
 
 uint8_t qvirtio_config_readb(QVirtioDevice *d, uint64_t addr)
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] tests/qtest/libqos: Avoid double swapping when using modern virtio
  2025-04-30 13:28 [PATCH v2] tests/qtest/libqos: Avoid double swapping when using modern virtio Thomas Huth
@ 2025-04-30 13:50 ` Philippe Mathieu-Daudé
  2025-04-30 14:31   ` Thomas Huth
  2025-04-30 14:54 ` Alex Bennée
  2025-05-05 14:55 ` Fabiano Rosas
  2 siblings, 1 reply; 5+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-04-30 13:50 UTC (permalink / raw)
  To: Thomas Huth, Fabiano Rosas, qemu-devel
  Cc: Laurent Vivier, Paolo Bonzini, Pierrick Bouvier

On 30/4/25 15:28, Thomas Huth wrote:
> From: Thomas Huth <thuth@redhat.com>
> 
> The logic in the qvirtio_read/write function is rather a headache,
> involving byte-swapping when the target is big endian, just to
> maybe involve another byte-swapping  in the qtest_read/write
> function immediately afterwards (on the QEMU side). Let's do it in
> a more obvious way here: For virtio 1.0, we know that the values have
> to be little endian, so let's read/write the bytes in that well known
> order here.
> 
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
>   This also decreases our usage of qtest_big_endian() which might (or
>   might not) get helpful for the universal binary one day...
> 
>   v2: Use leXX_to_cpu() / cpu_to_leXX() instead of doing it manually
> 
>   tests/qtest/libqos/virtio.c | 44 ++++++++++++++++++++++++-------------
>   1 file changed, 29 insertions(+), 15 deletions(-)

Thanks!

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

I tried this on top:

-- >8 --
diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
index 930a91dcb7d..5e01c1effc7 100644
--- a/tests/qtest/libqtest.h
+++ b/tests/qtest/libqtest.h
@@ -731,8 +730,0 @@ int64_t qtest_clock_set(QTestState *s, int64_t val);
-/**
- * qtest_big_endian:
- * @s: QTestState instance to operate on.
- *
- * Returns: True if the architecture under test has a big endian 
configuration.
- */
-bool qtest_big_endian(QTestState *s);
-
diff --git a/tests/qtest/libqos/virtio-pci.c 
b/tests/qtest/libqos/virtio-pci.c
index 002bf8b8c2d..98b35ceb9e3 100644
--- a/tests/qtest/libqos/virtio-pci.c
+++ b/tests/qtest/libqos/virtio-pci.c
@@ -389,0 +390,20 @@ void qvirtio_pci_start_hw(QOSGraphObject *obj)
+/**
+ * qvirtio_pci_query_legacy_endianness:
+ * @s: QTestState instance to operate on.
+ *
+ * Returns: True if the architecture under test has a big endian 
configuration.
+ */
+static int qvirtio_pci_query_legacy_endianness(QTestState *s)
+{
+    gchar **args;
+    int big_endian;
+
+    qtest_sendf(s, "endianness\n");
+    args = qtest_rsp_args(s, 1);
+    g_assert(strcmp(args[1], "big") == 0 || strcmp(args[1], "little") 
== 0);
+    big_endian = strcmp(args[1], "big") == 0;
+    g_strfreev(args);
+
+    return big_endian;
+}
+
@@ -391,0 +412,2 @@ static void qvirtio_pci_init_legacy(QVirtioPCIDevice 
*dev)
+    bool big_endian = 
qvirtio_pci_query_legacy_endianness(dev->pdev->bus->qts);
+
@@ -396 +418 @@ static void qvirtio_pci_init_legacy(QVirtioPCIDevice *dev)
-    dev->vdev.big_endian = qtest_big_endian(dev->pdev->bus->qts);
+    dev->vdev.big_endian = big_endian;
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index 358580361d3..4a29a8fd750 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -87 +86,0 @@ struct QTestState
-    bool big_endian;
@@ -552,2 +550,0 @@ void qtest_connect(QTestState *s)
-    /* ask endianness of the target */
-    s->big_endian = qtest_query_target_endianness(s);
@@ -779,14 +775,0 @@ static void qtest_rsp(QTestState *s)
-static int qtest_query_target_endianness(QTestState *s)
-{
-    gchar **args;
-    int big_endian;
-
-    qtest_sendf(s, "endianness\n");
-    args = qtest_rsp_args(s, 1);
-    g_assert(strcmp(args[1], "big") == 0 || strcmp(args[1], "little") 
== 0);
-    big_endian = strcmp(args[1], "big") == 0;
-    g_strfreev(args);
-
-    return big_endian;
-}
-
@@ -1561,5 +1543,0 @@ void qtest_qmp_fds_assert_success(QTestState *qts, 
int *fds, size_t nfds,
-bool qtest_big_endian(QTestState *s)
-{
-    return s->big_endian;
-}
-
@@ -2000,2 +1977,0 @@ QTestState *qtest_inproc_init(QTestState **s, bool 
log, const char* arch,
-    qts->big_endian = qtest_query_target_endianness(qts);
-
---

But it doesn't work due to qtest_sendf() and qtest_rsp_args() being
local to tests/qtest/libqtest.c:

../../tests/qtest/libqos/virtio-pci.c:401:5: error: call to undeclared 
function 'qtest_sendf'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
   401 |     qtest_sendf(s, "endianness\n");
       |     ^
../../tests/qtest/libqos/virtio-pci.c:402:12: error: call to undeclared 
function 'qtest_rsp_args'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
   402 |     args = qtest_rsp_args(s, 1);
       |            ^



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] tests/qtest/libqos: Avoid double swapping when using modern virtio
  2025-04-30 13:50 ` Philippe Mathieu-Daudé
@ 2025-04-30 14:31   ` Thomas Huth
  0 siblings, 0 replies; 5+ messages in thread
From: Thomas Huth @ 2025-04-30 14:31 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Fabiano Rosas, qemu-devel
  Cc: Laurent Vivier, Paolo Bonzini, Pierrick Bouvier

On 30/04/2025 15.50, Philippe Mathieu-Daudé wrote:
> On 30/4/25 15:28, Thomas Huth wrote:
>> From: Thomas Huth <thuth@redhat.com>
>>
>> The logic in the qvirtio_read/write function is rather a headache,
>> involving byte-swapping when the target is big endian, just to
>> maybe involve another byte-swapping  in the qtest_read/write
>> function immediately afterwards (on the QEMU side). Let's do it in
>> a more obvious way here: For virtio 1.0, we know that the values have
>> to be little endian, so let's read/write the bytes in that well known
>> order here.
>>
>> Signed-off-by: Thomas Huth <thuth@redhat.com>
>> ---
>>   This also decreases our usage of qtest_big_endian() which might (or
>>   might not) get helpful for the universal binary one day...
>>
>>   v2: Use leXX_to_cpu() / cpu_to_leXX() instead of doing it manually
>>
>>   tests/qtest/libqos/virtio.c | 44 ++++++++++++++++++++++++-------------
>>   1 file changed, 29 insertions(+), 15 deletions(-)
> 
> Thanks!
> 
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> 
> I tried this on top:
> 
> -- >8 --
> diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
> index 930a91dcb7d..5e01c1effc7 100644
> --- a/tests/qtest/libqtest.h
> +++ b/tests/qtest/libqtest.h
> @@ -731,8 +730,0 @@ int64_t qtest_clock_set(QTestState *s, int64_t val);
> -/**
> - * qtest_big_endian:
> - * @s: QTestState instance to operate on.
> - *
> - * Returns: True if the architecture under test has a big endian 
> configuration.
> - */
> -bool qtest_big_endian(QTestState *s);

I think you might be able to get rid of the big_endian stuff there 
completely if we can be sure that all tests run with VIRTIO_1.
As far as I can see, the PCI-based tests should be fine, but the MMIO-based 
tests still seem to run in legacy mode. Maybe this could be fixed by adding 
a "-global virtio-mmio.force-legacy=false" somewhere in the right spot?
Or could we set force-legacy to false by default in the QEMU binary nowadays?

  Thomas



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] tests/qtest/libqos: Avoid double swapping when using modern virtio
  2025-04-30 13:28 [PATCH v2] tests/qtest/libqos: Avoid double swapping when using modern virtio Thomas Huth
  2025-04-30 13:50 ` Philippe Mathieu-Daudé
@ 2025-04-30 14:54 ` Alex Bennée
  2025-05-05 14:55 ` Fabiano Rosas
  2 siblings, 0 replies; 5+ messages in thread
From: Alex Bennée @ 2025-04-30 14:54 UTC (permalink / raw)
  To: Thomas Huth
  Cc: Fabiano Rosas, qemu-devel, Philippe Mathieu-Daudé,
	Laurent Vivier, Paolo Bonzini, Pierrick Bouvier

Thomas Huth <thuth@redhat.com> writes:

> From: Thomas Huth <thuth@redhat.com>
>
> The logic in the qvirtio_read/write function is rather a headache,
> involving byte-swapping when the target is big endian, just to
> maybe involve another byte-swapping  in the qtest_read/write
> function immediately afterwards (on the QEMU side). Let's do it in
> a more obvious way here: For virtio 1.0, we know that the values have
> to be little endian, so let's read/write the bytes in that well known
> order here.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Alex Bennée <alex.bennee@linaro.org>


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] tests/qtest/libqos: Avoid double swapping when using modern virtio
  2025-04-30 13:28 [PATCH v2] tests/qtest/libqos: Avoid double swapping when using modern virtio Thomas Huth
  2025-04-30 13:50 ` Philippe Mathieu-Daudé
  2025-04-30 14:54 ` Alex Bennée
@ 2025-05-05 14:55 ` Fabiano Rosas
  2 siblings, 0 replies; 5+ messages in thread
From: Fabiano Rosas @ 2025-05-05 14:55 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel, Philippe Mathieu-Daudé
  Cc: Laurent Vivier, Paolo Bonzini, Pierrick Bouvier

Thomas Huth <thuth@redhat.com> writes:

> From: Thomas Huth <thuth@redhat.com>
>
> The logic in the qvirtio_read/write function is rather a headache,
> involving byte-swapping when the target is big endian, just to
> maybe involve another byte-swapping  in the qtest_read/write
> function immediately afterwards (on the QEMU side). Let's do it in
> a more obvious way here: For virtio 1.0, we know that the values have
> to be little endian, so let's read/write the bytes in that well known
> order here.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
>  This also decreases our usage of qtest_big_endian() which might (or
>  might not) get helpful for the universal binary one day...
>
>  v2: Use leXX_to_cpu() / cpu_to_leXX() instead of doing it manually
>
>  tests/qtest/libqos/virtio.c | 44 ++++++++++++++++++++++++-------------
>  1 file changed, 29 insertions(+), 15 deletions(-)
>
> diff --git a/tests/qtest/libqos/virtio.c b/tests/qtest/libqos/virtio.c
> index 2e7979652fd..5a709d0bc59 100644
> --- a/tests/qtest/libqos/virtio.c
> +++ b/tests/qtest/libqos/virtio.c
> @@ -25,49 +25,63 @@
>   */
>  static uint16_t qvirtio_readw(QVirtioDevice *d, QTestState *qts, uint64_t addr)
>  {
> -    uint16_t val = qtest_readw(qts, addr);
> +    uint16_t val;
>  
> -    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
> -        val = bswap16(val);
> +    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
> +        qtest_memread(qts, addr, &val, sizeof(val));
> +        val = le16_to_cpu(val);
> +    } else {
> +        val = qtest_readw(qts, addr);
>      }
> +
>      return val;
>  }
>  
>  static uint32_t qvirtio_readl(QVirtioDevice *d, QTestState *qts, uint64_t addr)
>  {
> -    uint32_t val = qtest_readl(qts, addr);
> +    uint32_t val;
>  
> -    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
> -        val = bswap32(val);
> +    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
> +        qtest_memread(qts, addr, &val, sizeof(val));
> +        val = le32_to_cpu(val);
> +    } else {
> +        val = qtest_readl(qts, addr);
>      }
> +
>      return val;
>  }
>  
>  static void qvirtio_writew(QVirtioDevice *d, QTestState *qts,
>                             uint64_t addr, uint16_t val)
>  {
> -    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
> -        val = bswap16(val);
> +    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
> +        val = cpu_to_le16(val);
> +        qtest_memwrite(qts, addr, &val, sizeof(val));
> +    } else {
> +        qtest_writew(qts, addr, val);
>      }
> -    qtest_writew(qts, addr, val);
>  }
>  
>  static void qvirtio_writel(QVirtioDevice *d, QTestState *qts,
>                             uint64_t addr, uint32_t val)
>  {
> -    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
> -        val = bswap32(val);
> +    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
> +        val = cpu_to_le32(val);
> +        qtest_memwrite(qts, addr, &val, sizeof(val));
> +    } else {
> +        qtest_writel(qts, addr, val);
>      }
> -    qtest_writel(qts, addr, val);
>  }
>  
>  static void qvirtio_writeq(QVirtioDevice *d, QTestState *qts,
>                             uint64_t addr, uint64_t val)
>  {
> -    if (d->features & (1ull << VIRTIO_F_VERSION_1) && qtest_big_endian(qts)) {
> -        val = bswap64(val);
> +    if (d->features & (1ull << VIRTIO_F_VERSION_1)) {
> +        val = cpu_to_le64(val);
> +        qtest_memwrite(qts, addr, &val, sizeof(val));
> +    } else {
> +        qtest_writeq(qts, addr, val);
>      }
> -    qtest_writeq(qts, addr, val);
>  }
>  
>  uint8_t qvirtio_config_readb(QVirtioDevice *d, uint64_t addr)

Queued to qtest-next, thanks!


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-05-05 14:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-30 13:28 [PATCH v2] tests/qtest/libqos: Avoid double swapping when using modern virtio Thomas Huth
2025-04-30 13:50 ` Philippe Mathieu-Daudé
2025-04-30 14:31   ` Thomas Huth
2025-04-30 14:54 ` Alex Bennée
2025-05-05 14:55 ` Fabiano Rosas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).