* [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).