hw/scsi/vmw_pvscsi.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-)
From: Miao Wang <shankerwangmiao@gmail.com>
This patch improves the implementation of the pvscsi device by
translating the endianness of the data sent or received from the guest.
This ensures pvscsi can work on big-endian hosts with little-endian
guests.
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
---
hw/scsi/vmw_pvscsi.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 57 insertions(+), 1 deletion(-)
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 11ae6b9b7474b9bc87621137eb7911361b5fd721..883dfe9b6b5dc687737de356da02fe5f68aea7ad 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -35,6 +35,7 @@
#include "hw/pci/msi.h"
#include "hw/core/qdev-properties.h"
#include "exec/cpu-common.h"
+#include "exec/tswap.h"
#include "vmw_pvscsi.h"
#include "trace.h"
#include "qom/object.h"
@@ -392,9 +393,18 @@ static void
pvscsi_cmp_ring_put(PVSCSIState *s, struct PVSCSIRingCmpDesc *cmp_desc)
{
hwaddr cmp_descr_pa;
+ struct PVSCSIRingCmpDesc cmp_desc_conv;
cmp_descr_pa = pvscsi_ring_pop_cmp_descr(&s->rings);
trace_pvscsi_cmp_ring_put(cmp_descr_pa);
+ cmp_desc_conv = (struct PVSCSIRingCmpDesc) {
+ .context = tswap64(cmp_desc->context),
+ .dataLen = tswap64(cmp_desc->dataLen),
+ .senseLen = tswap32(cmp_desc->senseLen),
+ .hostStatus = tswap16(cmp_desc->hostStatus),
+ .scsiStatus = tswap16(cmp_desc->scsiStatus),
+ };
+ cmp_desc = &cmp_desc_conv;
cpu_physical_memory_write(cmp_descr_pa, cmp_desc, sizeof(*cmp_desc));
}
@@ -402,9 +412,18 @@ static void
pvscsi_msg_ring_put(PVSCSIState *s, struct PVSCSIRingMsgDesc *msg_desc)
{
hwaddr msg_descr_pa;
+ struct PVSCSIRingMsgDesc msg_desc_conv;
+ int i;
msg_descr_pa = pvscsi_ring_pop_msg_descr(&s->rings);
trace_pvscsi_msg_ring_put(msg_descr_pa);
+ msg_desc_conv = (struct PVSCSIRingMsgDesc) {
+ .type = tswap32(msg_desc->type),
+ };
+ for (i = 0; i < ARRAY_SIZE(msg_desc->args); i++) {
+ msg_desc_conv.args[i] = tswap32(msg_desc->args[i]);
+ }
+ msg_desc = &msg_desc_conv;
cpu_physical_memory_write(msg_descr_pa, msg_desc, sizeof(*msg_desc));
}
@@ -481,6 +500,9 @@ pvscsi_get_next_sg_elem(PVSCSISGState *sg)
struct PVSCSISGElement elem;
cpu_physical_memory_read(sg->elemAddr, &elem, sizeof(elem));
+ elem.addr = tswap64(elem.addr);
+ elem.length = tswap32(elem.length);
+ elem.flags = tswap32(elem.flags);
if ((elem.flags & ~PVSCSI_KNOWN_FLAGS) != 0) {
/*
* There is PVSCSI_SGE_FLAG_CHAIN_ELEMENT flag described in
@@ -759,6 +781,12 @@ pvscsi_process_io(PVSCSIState *s)
trace_pvscsi_process_io(next_descr_pa);
cpu_physical_memory_read(next_descr_pa, &descr, sizeof(descr));
+ descr.context = tswap64(descr.context);
+ descr.dataAddr = tswap64(descr.dataAddr);
+ descr.dataLen = tswap64(descr.dataLen);
+ descr.senseAddr = tswap64(descr.senseAddr);
+ descr.senseLen = tswap32(descr.senseLen);
+ descr.flags = tswap32(descr.flags);
pvscsi_process_request_descriptor(s, &descr);
}
@@ -808,6 +836,17 @@ pvscsi_on_cmd_setup_rings(PVSCSIState *s)
{
PVSCSICmdDescSetupRings *rc =
(PVSCSICmdDescSetupRings *) s->curr_cmd_data;
+ PVSCSICmdDescSetupRings translated;
+ int i;
+
+ translated.reqRingNumPages = tswap32(rc->reqRingNumPages);
+ translated.cmpRingNumPages = tswap32(rc->cmpRingNumPages);
+ translated.ringsStatePPN = tswap64(rc->ringsStatePPN);
+ for (i = 0; i < PVSCSI_SETUP_RINGS_MAX_NUM_PAGES; i++) {
+ translated.reqRingPPNs[i] = tswap64(rc->reqRingPPNs[i]);
+ translated.cmpRingPPNs[i] = tswap64(rc->cmpRingPPNs[i]);
+ }
+ rc = &translated;
trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_RINGS");
@@ -831,6 +870,11 @@ pvscsi_on_cmd_abort(PVSCSIState *s)
PVSCSICmdDescAbortCmd *cmd = (PVSCSICmdDescAbortCmd *) s->curr_cmd_data;
PVSCSIRequest *r, *next;
+ PVSCSICmdDescAbortCmd translated = *cmd;
+ translated.context = tswap32(cmd->context);
+ translated.target = tswap32(cmd->target);
+ cmd = &translated;
+
trace_pvscsi_on_cmd_abort(cmd->context, cmd->target);
QTAILQ_FOREACH_SAFE(r, &s->pending_queue, next, next) {
@@ -862,6 +906,10 @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
(struct PVSCSICmdDescResetDevice *) s->curr_cmd_data;
SCSIDevice *sdev;
+ PVSCSICmdDescResetDevice translated = *cmd;
+ translated.target = tswap32(cmd->target);
+ cmd = &translated;
+
sdev = pvscsi_device_find(s, 0, cmd->target, cmd->lun, &target_lun);
trace_pvscsi_on_cmd_reset_dev(cmd->target, (int) target_lun, sdev);
@@ -892,6 +940,14 @@ pvscsi_on_cmd_setup_msg_ring(PVSCSIState *s)
{
PVSCSICmdDescSetupMsgRing *rc =
(PVSCSICmdDescSetupMsgRing *) s->curr_cmd_data;
+ PVSCSICmdDescSetupMsgRing translated = *rc;
+ int i;
+
+ translated.numPages = tswap32(rc->numPages);
+ for (i = 0; i < PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES; i++) {
+ translated.ringPPNs[i] = tswap64(rc->ringPPNs[i]);
+ }
+ rc = &translated;
trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_MSG_RING");
@@ -994,7 +1050,7 @@ pvscsi_on_command_data(PVSCSIState *s, uint32_t value)
size_t bytes_arrived = s->curr_cmd_data_cntr * sizeof(uint32_t);
assert(bytes_arrived < sizeof(s->curr_cmd_data));
- s->curr_cmd_data[s->curr_cmd_data_cntr++] = value;
+ s->curr_cmd_data[s->curr_cmd_data_cntr++] = tswap32(value);
pvscsi_do_command_processing(s);
}
---
base-commit: 29c042c6e9d4a09d4a0ac3fa54aeb7ee08ce0bdc
change-id: 20260605-pvscsi-endianness-c0d389d8274e
Best regards,
--
Miao Wang <shankerwangmiao@gmail.com>
On 05.06.2026 16:27, Miao Wang via B4 Relay wrote:
> From: Miao Wang <shankerwangmiao@gmail.com>
>
> This patch improves the implementation of the pvscsi device by
> translating the endianness of the data sent or received from the guest.
> This ensures pvscsi can work on big-endian hosts with little-endian
> guests.
Hi!
Can we pick this one up for 11.1 please?
I know right to nothing about s390x internals so can't really review
the change. But the fix seems to work, and it should be picked up for
the stable qemu series too, it loks like.
Thanks,
/mjt
> Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
> ---
> hw/scsi/vmw_pvscsi.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 57 insertions(+), 1 deletion(-)
>
> diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
> index 11ae6b9b7474b9bc87621137eb7911361b5fd721..883dfe9b6b5dc687737de356da02fe5f68aea7ad 100644
> --- a/hw/scsi/vmw_pvscsi.c
> +++ b/hw/scsi/vmw_pvscsi.c
> @@ -35,6 +35,7 @@
> #include "hw/pci/msi.h"
> #include "hw/core/qdev-properties.h"
> #include "exec/cpu-common.h"
> +#include "exec/tswap.h"
> #include "vmw_pvscsi.h"
> #include "trace.h"
> #include "qom/object.h"
> @@ -392,9 +393,18 @@ static void
> pvscsi_cmp_ring_put(PVSCSIState *s, struct PVSCSIRingCmpDesc *cmp_desc)
> {
> hwaddr cmp_descr_pa;
> + struct PVSCSIRingCmpDesc cmp_desc_conv;
>
> cmp_descr_pa = pvscsi_ring_pop_cmp_descr(&s->rings);
> trace_pvscsi_cmp_ring_put(cmp_descr_pa);
> + cmp_desc_conv = (struct PVSCSIRingCmpDesc) {
> + .context = tswap64(cmp_desc->context),
> + .dataLen = tswap64(cmp_desc->dataLen),
> + .senseLen = tswap32(cmp_desc->senseLen),
> + .hostStatus = tswap16(cmp_desc->hostStatus),
> + .scsiStatus = tswap16(cmp_desc->scsiStatus),
> + };
> + cmp_desc = &cmp_desc_conv;
> cpu_physical_memory_write(cmp_descr_pa, cmp_desc, sizeof(*cmp_desc));
> }
>
> @@ -402,9 +412,18 @@ static void
> pvscsi_msg_ring_put(PVSCSIState *s, struct PVSCSIRingMsgDesc *msg_desc)
> {
> hwaddr msg_descr_pa;
> + struct PVSCSIRingMsgDesc msg_desc_conv;
> + int i;
>
> msg_descr_pa = pvscsi_ring_pop_msg_descr(&s->rings);
> trace_pvscsi_msg_ring_put(msg_descr_pa);
> + msg_desc_conv = (struct PVSCSIRingMsgDesc) {
> + .type = tswap32(msg_desc->type),
> + };
> + for (i = 0; i < ARRAY_SIZE(msg_desc->args); i++) {
> + msg_desc_conv.args[i] = tswap32(msg_desc->args[i]);
> + }
> + msg_desc = &msg_desc_conv;
> cpu_physical_memory_write(msg_descr_pa, msg_desc, sizeof(*msg_desc));
> }
>
> @@ -481,6 +500,9 @@ pvscsi_get_next_sg_elem(PVSCSISGState *sg)
> struct PVSCSISGElement elem;
>
> cpu_physical_memory_read(sg->elemAddr, &elem, sizeof(elem));
> + elem.addr = tswap64(elem.addr);
> + elem.length = tswap32(elem.length);
> + elem.flags = tswap32(elem.flags);
> if ((elem.flags & ~PVSCSI_KNOWN_FLAGS) != 0) {
> /*
> * There is PVSCSI_SGE_FLAG_CHAIN_ELEMENT flag described in
> @@ -759,6 +781,12 @@ pvscsi_process_io(PVSCSIState *s)
>
> trace_pvscsi_process_io(next_descr_pa);
> cpu_physical_memory_read(next_descr_pa, &descr, sizeof(descr));
> + descr.context = tswap64(descr.context);
> + descr.dataAddr = tswap64(descr.dataAddr);
> + descr.dataLen = tswap64(descr.dataLen);
> + descr.senseAddr = tswap64(descr.senseAddr);
> + descr.senseLen = tswap32(descr.senseLen);
> + descr.flags = tswap32(descr.flags);
> pvscsi_process_request_descriptor(s, &descr);
> }
>
> @@ -808,6 +836,17 @@ pvscsi_on_cmd_setup_rings(PVSCSIState *s)
> {
> PVSCSICmdDescSetupRings *rc =
> (PVSCSICmdDescSetupRings *) s->curr_cmd_data;
> + PVSCSICmdDescSetupRings translated;
> + int i;
> +
> + translated.reqRingNumPages = tswap32(rc->reqRingNumPages);
> + translated.cmpRingNumPages = tswap32(rc->cmpRingNumPages);
> + translated.ringsStatePPN = tswap64(rc->ringsStatePPN);
> + for (i = 0; i < PVSCSI_SETUP_RINGS_MAX_NUM_PAGES; i++) {
> + translated.reqRingPPNs[i] = tswap64(rc->reqRingPPNs[i]);
> + translated.cmpRingPPNs[i] = tswap64(rc->cmpRingPPNs[i]);
> + }
> + rc = &translated;
>
> trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_RINGS");
>
> @@ -831,6 +870,11 @@ pvscsi_on_cmd_abort(PVSCSIState *s)
> PVSCSICmdDescAbortCmd *cmd = (PVSCSICmdDescAbortCmd *) s->curr_cmd_data;
> PVSCSIRequest *r, *next;
>
> + PVSCSICmdDescAbortCmd translated = *cmd;
> + translated.context = tswap32(cmd->context);
> + translated.target = tswap32(cmd->target);
> + cmd = &translated;
> +
> trace_pvscsi_on_cmd_abort(cmd->context, cmd->target);
>
> QTAILQ_FOREACH_SAFE(r, &s->pending_queue, next, next) {
> @@ -862,6 +906,10 @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
> (struct PVSCSICmdDescResetDevice *) s->curr_cmd_data;
> SCSIDevice *sdev;
>
> + PVSCSICmdDescResetDevice translated = *cmd;
> + translated.target = tswap32(cmd->target);
> + cmd = &translated;
> +
> sdev = pvscsi_device_find(s, 0, cmd->target, cmd->lun, &target_lun);
>
> trace_pvscsi_on_cmd_reset_dev(cmd->target, (int) target_lun, sdev);
> @@ -892,6 +940,14 @@ pvscsi_on_cmd_setup_msg_ring(PVSCSIState *s)
> {
> PVSCSICmdDescSetupMsgRing *rc =
> (PVSCSICmdDescSetupMsgRing *) s->curr_cmd_data;
> + PVSCSICmdDescSetupMsgRing translated = *rc;
> + int i;
> +
> + translated.numPages = tswap32(rc->numPages);
> + for (i = 0; i < PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES; i++) {
> + translated.ringPPNs[i] = tswap64(rc->ringPPNs[i]);
> + }
> + rc = &translated;
>
> trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_MSG_RING");
>
> @@ -994,7 +1050,7 @@ pvscsi_on_command_data(PVSCSIState *s, uint32_t value)
> size_t bytes_arrived = s->curr_cmd_data_cntr * sizeof(uint32_t);
>
> assert(bytes_arrived < sizeof(s->curr_cmd_data));
> - s->curr_cmd_data[s->curr_cmd_data_cntr++] = value;
> + s->curr_cmd_data[s->curr_cmd_data_cntr++] = tswap32(value);
>
> pvscsi_do_command_processing(s);
> }
>
> ---
> base-commit: 29c042c6e9d4a09d4a0ac3fa54aeb7ee08ce0bdc
> change-id: 20260605-pvscsi-endianness-c0d389d8274e
>
> Best regards,
On 9/7/26 08:39, Michael Tokarev wrote:
> On 05.06.2026 16:27, Miao Wang via B4 Relay wrote:
>> From: Miao Wang <shankerwangmiao@gmail.com>
>>
>> This patch improves the implementation of the pvscsi device by
>> translating the endianness of the data sent or received from the guest.
>> This ensures pvscsi can work on big-endian hosts with little-endian
>> guests.
>
> Hi!
>
> Can we pick this one up for 11.1 please?
> I know right to nothing about s390x internals so can't really review
> the change. But the fix seems to work, and it should be picked up for
> the stable qemu series too, it loks like.
I tagged this for review and forgot. Basically we shouldn't using
tswap*() anywhere in system emulation except semihosting. Here it
seems reasonable to use cpu_to_le*()/le*_to_cpu().
>> Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
>> ---
>> hw/scsi/vmw_pvscsi.c | 58 ++++++++++++++++++++++++++++++++++++++++++
>> +++++++++-
>> 1 file changed, 57 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
>> index
>> 11ae6b9b7474b9bc87621137eb7911361b5fd721..883dfe9b6b5dc687737de356da02fe5f68aea7ad 100644
>> --- a/hw/scsi/vmw_pvscsi.c
>> +++ b/hw/scsi/vmw_pvscsi.c
>> @@ -35,6 +35,7 @@
>> #include "hw/pci/msi.h"
>> #include "hw/core/qdev-properties.h"
>> #include "exec/cpu-common.h"
>> +#include "exec/tswap.h"
>> #include "vmw_pvscsi.h"
>> #include "trace.h"
>> #include "qom/object.h"
>> @@ -392,9 +393,18 @@ static void
>> pvscsi_cmp_ring_put(PVSCSIState *s, struct PVSCSIRingCmpDesc *cmp_desc)
>> {
>> hwaddr cmp_descr_pa;
>> + struct PVSCSIRingCmpDesc cmp_desc_conv;
>> cmp_descr_pa = pvscsi_ring_pop_cmp_descr(&s->rings);
>> trace_pvscsi_cmp_ring_put(cmp_descr_pa);
>> + cmp_desc_conv = (struct PVSCSIRingCmpDesc) {
>> + .context = tswap64(cmp_desc->context),
>> + .dataLen = tswap64(cmp_desc->dataLen),
>> + .senseLen = tswap32(cmp_desc->senseLen),
>> + .hostStatus = tswap16(cmp_desc->hostStatus),
>> + .scsiStatus = tswap16(cmp_desc->scsiStatus),
>> + };
>> + cmp_desc = &cmp_desc_conv;
>> cpu_physical_memory_write(cmp_descr_pa, cmp_desc,
Hi, > 2026年7月9日 22:41,Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> 写道: > > On 9/7/26 08:39, Michael Tokarev wrote: >> On 05.06.2026 16:27, Miao Wang via B4 Relay wrote: >>> From: Miao Wang <shankerwangmiao@gmail.com> >>> >>> This patch improves the implementation of the pvscsi device by >>> translating the endianness of the data sent or received from the guest. >>> This ensures pvscsi can work on big-endian hosts with little-endian >>> guests. >> Hi! >> Can we pick this one up for 11.1 please? >> I know right to nothing about s390x internals so can't really review >> the change. But the fix seems to work, and it should be picked up for >> the stable qemu series too, it loks like. > > I tagged this for review and forgot. Basically we shouldn't using > tswap*() anywhere in system emulation except semihosting. Here it > seems reasonable to use cpu_to_le*()/le*_to_cpu(). I have no idea why tswap* should not be used. Here the problem in pvscsi is that the driver on the guest side is using the native endianness of the guest CPU while for handling the values on the host size, we need to convert it to host endianness. As a result, what should be done is to convert from the target endianness to the host endianness and vice versa, instead of converting from a specific endianness to to host endianness. Cheers, Miao Wang
On Thu, 9 Jul 2026 at 15:54, Miao Wang <shankerwangmiao@gmail.com> wrote: > > Hi, > > > 2026年7月9日 22:41,Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> 写道: > > > > On 9/7/26 08:39, Michael Tokarev wrote: > >> On 05.06.2026 16:27, Miao Wang via B4 Relay wrote: > >>> From: Miao Wang <shankerwangmiao@gmail.com> > >>> > >>> This patch improves the implementation of the pvscsi device by > >>> translating the endianness of the data sent or received from the guest. > >>> This ensures pvscsi can work on big-endian hosts with little-endian > >>> guests. > >> Hi! > >> Can we pick this one up for 11.1 please? > >> I know right to nothing about s390x internals so can't really review > >> the change. But the fix seems to work, and it should be picked up for > >> the stable qemu series too, it loks like. > > > > I tagged this for review and forgot. Basically we shouldn't using > > tswap*() anywhere in system emulation except semihosting. Here it > > seems reasonable to use cpu_to_le*()/le*_to_cpu(). > > I have no idea why tswap* should not be used. Here the problem in > pvscsi is that the driver on the guest side is using the native > endianness of the guest CPU while for handling the values on the > host size, we need to convert it to host endianness. As a result, > what should be done is to convert from the target endianness to > the host endianness and vice versa, instead of converting from > a specific endianness to to host endianness. Right, but what is the spec of the device supposed to be? Generally speaking in real hardware devices don't have any way of knowing the endianness of the CPU, they're specified as "data is always little endian" or "data is always big endian". Sometimes paravirtual devices end up with "assumes guest endianness" baked into them, but this is usually a bad idea: the legacy virtio does this, but we fixed this in 1.0 virtio, which is always little endian. Do you have a pointer to the specification for this device? There's no URL in the source files. thanks -- PMM
> 2026年7月9日 23:06,Peter Maydell <peter.maydell@linaro.org> 写道: > > On Thu, 9 Jul 2026 at 15:54, Miao Wang <shankerwangmiao@gmail.com> wrote: >> >> Hi, >> >>> 2026年7月9日 22:41,Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> 写道: >>> >>> On 9/7/26 08:39, Michael Tokarev wrote: >>>> On 05.06.2026 16:27, Miao Wang via B4 Relay wrote: >>>>> From: Miao Wang <shankerwangmiao@gmail.com> >>>>> >>>>> This patch improves the implementation of the pvscsi device by >>>>> translating the endianness of the data sent or received from the guest. >>>>> This ensures pvscsi can work on big-endian hosts with little-endian >>>>> guests. >>>> Hi! >>>> Can we pick this one up for 11.1 please? >>>> I know right to nothing about s390x internals so can't really review >>>> the change. But the fix seems to work, and it should be picked up for >>>> the stable qemu series too, it loks like. >>> >>> I tagged this for review and forgot. Basically we shouldn't using >>> tswap*() anywhere in system emulation except semihosting. Here it >>> seems reasonable to use cpu_to_le*()/le*_to_cpu(). >> >> I have no idea why tswap* should not be used. Here the problem in >> pvscsi is that the driver on the guest side is using the native >> endianness of the guest CPU while for handling the values on the >> host size, we need to convert it to host endianness. As a result, >> what should be done is to convert from the target endianness to >> the host endianness and vice versa, instead of converting from >> a specific endianness to to host endianness. > > Right, but what is the spec of the device supposed to be? > Generally speaking in real hardware devices don't have any > way of knowing the endianness of the CPU, they're specified > as "data is always little endian" or "data is always big endian". > Sometimes paravirtual devices end up with "assumes guest > endianness" baked into them, but this is usually a bad idea: > the legacy virtio does this, but we fixed this in 1.0 virtio, > which is always little endian. > > Do you have a pointer to the specification for this device? > There's no URL in the source files. Sadly, I do not have such specification and I strongly suspect that neither does the designer of it, since it is designed to be used with x86. In the source code of its driver in Linux, it can be seen that the code is not endianness aware. However in the Kconfig, the driver is limited to be compiled on X86. As a result, there might be two possibilities: - pvscsi is designed to use (guest) native endianness - pvscsi is designed to use little endianness and since the linux driver limits itself to be used on X86, the author chose not to bother to ensure the correctness of the endianness Cheers, Miao Wang
On 9/7/26 17:41, Miao Wang wrote: > > >> 2026年7月9日 23:06,Peter Maydell <peter.maydell@linaro.org> 写道: >> >> On Thu, 9 Jul 2026 at 15:54, Miao Wang <shankerwangmiao@gmail.com> wrote: >>> >>> Hi, >>> >>>> 2026年7月9日 22:41,Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> 写道: >>>> >>>> On 9/7/26 08:39, Michael Tokarev wrote: >>>>> On 05.06.2026 16:27, Miao Wang via B4 Relay wrote: >>>>>> From: Miao Wang <shankerwangmiao@gmail.com> >>>>>> >>>>>> This patch improves the implementation of the pvscsi device by >>>>>> translating the endianness of the data sent or received from the guest. >>>>>> This ensures pvscsi can work on big-endian hosts with little-endian >>>>>> guests. >>>>> Hi! >>>>> Can we pick this one up for 11.1 please? >>>>> I know right to nothing about s390x internals so can't really review >>>>> the change. But the fix seems to work, and it should be picked up for >>>>> the stable qemu series too, it loks like. >>>> >>>> I tagged this for review and forgot. Basically we shouldn't using >>>> tswap*() anywhere in system emulation except semihosting. Here it >>>> seems reasonable to use cpu_to_le*()/le*_to_cpu(). >>> >>> I have no idea why tswap* should not be used. Here the problem in >>> pvscsi is that the driver on the guest side is using the native >>> endianness of the guest CPU while for handling the values on the >>> host size, we need to convert it to host endianness. As a result, >>> what should be done is to convert from the target endianness to >>> the host endianness and vice versa, instead of converting from >>> a specific endianness to to host endianness. >> >> Right, but what is the spec of the device supposed to be? >> Generally speaking in real hardware devices don't have any >> way of knowing the endianness of the CPU, they're specified >> as "data is always little endian" or "data is always big endian". >> Sometimes paravirtual devices end up with "assumes guest >> endianness" baked into them, but this is usually a bad idea: >> the legacy virtio does this, but we fixed this in 1.0 virtio, >> which is always little endian. >> >> Do you have a pointer to the specification for this device? >> There's no URL in the source files. > > Sadly, I do not have such specification and I strongly suspect > that neither does the designer of it, since it is designed to > be used with x86. In the source code of its driver in Linux, > it can be seen that the code is not endianness aware. However > in the Kconfig, the driver is limited to be compiled on X86. > As a result, there might be two possibilities: > > - pvscsi is designed to use (guest) native endianness > - pvscsi is designed to use little endianness and since the > linux driver limits itself to be used on X86, the author > chose not to bother to ensure the correctness of the > endianness Likely the 2nd possibility ;) Also known as "implicit endianness".
© 2016 - 2026 Red Hat, Inc.