hw/scsi/vmw_pvscsi: translate data endianness
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. This patch assumes, although not having found any specifications, that the pvscsi device is little-endian, since pvscsi seems to be used only on x86 platforms, which are little-endian. Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Miao Wang <shankerwangmiao@gmail.com> Message-ID: <20260710-pvscsi-endianness-v3-1-27fe1c4d1f6e@gmail.com> [PMD: Rebased on top of commit cb30b8758d4 physmem API conversion] Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Miao Wang committed
Jul 10, 2026 at 03:21 UTC
5a811329bde78fc223abc384c85b0f62e3b34f7c
1 file changed
+56
-1
hw/scsi/vmw_pvscsi.c
+56
-1
@@ -392,9 +392,18 @@ static void
392
pvscsi_cmp_ring_put(PVSCSIState *s, struct PVSCSIRingCmpDesc *cmp_desc)
393
{
394
hwaddr cmp_descr_pa;
395
+ PVSCSIRingCmpDesc cmp_desc_conv;
396
397
cmp_descr_pa = pvscsi_ring_pop_cmp_descr(&s->rings);
398
trace_pvscsi_cmp_ring_put(cmp_descr_pa);
399
+ cmp_desc_conv = (struct PVSCSIRingCmpDesc) {
400
+ .context = cpu_to_le64(cmp_desc->context),
401
+ .dataLen = cpu_to_le64(cmp_desc->dataLen),
402
+ .senseLen = cpu_to_le32(cmp_desc->senseLen),
403
+ .hostStatus = cpu_to_le16(cmp_desc->hostStatus),
404
+ .scsiStatus = cpu_to_le16(cmp_desc->scsiStatus),
405
+ };
406
+ cmp_desc = &cmp_desc_conv;
407
physical_memory_write(cmp_descr_pa, cmp_desc, sizeof(*cmp_desc));
408
}
409
@@ -402,9 +411,18 @@ static void
411
pvscsi_msg_ring_put(PVSCSIState *s, struct PVSCSIRingMsgDesc *msg_desc)
412
{
413
hwaddr msg_descr_pa;
414
+ PVSCSIRingMsgDesc msg_desc_conv;
415
+ int i;
416
417
msg_descr_pa = pvscsi_ring_pop_msg_descr(&s->rings);
418
trace_pvscsi_msg_ring_put(msg_descr_pa);
419
+ msg_desc_conv = (PVSCSIRingMsgDesc) {
420
+ .type = cpu_to_le32(msg_desc->type),
421
+ };
422
+ for (i = 0; i < ARRAY_SIZE(msg_desc->args); i++) {
423
+ msg_desc_conv.args[i] = cpu_to_le32(msg_desc->args[i]);
424
+ }
425
+ msg_desc = &msg_desc_conv;
426
physical_memory_write(msg_descr_pa, msg_desc, sizeof(*msg_desc));
427
}
428
@@ -481,6 +499,9 @@ pvscsi_get_next_sg_elem(PVSCSISGState *sg)
499
struct PVSCSISGElement elem;
500
501
physical_memory_read(sg->elemAddr, &elem, sizeof(elem));
502
+ elem.addr = le64_to_cpu(elem.addr);
503
+ elem.length = le32_to_cpu(elem.length);
504
+ elem.flags = le32_to_cpu(elem.flags);
505
if ((elem.flags & ~PVSCSI_KNOWN_FLAGS) != 0) {
506
/*
507
* There is PVSCSI_SGE_FLAG_CHAIN_ELEMENT flag described in
@@ -759,6 +780,12 @@ pvscsi_process_io(PVSCSIState *s)
780
781
trace_pvscsi_process_io(next_descr_pa);
782
physical_memory_read(next_descr_pa, &descr, sizeof(descr));
783
+ descr.context = le64_to_cpu(descr.context);
784
+ descr.dataAddr = le64_to_cpu(descr.dataAddr);
785
+ descr.dataLen = le64_to_cpu(descr.dataLen);
786
+ descr.senseAddr = le64_to_cpu(descr.senseAddr);
787
+ descr.senseLen = le32_to_cpu(descr.senseLen);
788
+ descr.flags = le32_to_cpu(descr.flags);
789
pvscsi_process_request_descriptor(s, &descr);
790
}
791
@@ -808,6 +835,17 @@ pvscsi_on_cmd_setup_rings(PVSCSIState *s)
835
{
836
PVSCSICmdDescSetupRings *rc =
837
(PVSCSICmdDescSetupRings *) s->curr_cmd_data;
838
+ PVSCSICmdDescSetupRings translated;
839
+ int i;
840
+
841
+ translated.reqRingNumPages = le32_to_cpu(rc->reqRingNumPages);
842
+ translated.cmpRingNumPages = le32_to_cpu(rc->cmpRingNumPages);
843
+ translated.ringsStatePPN = le64_to_cpu(rc->ringsStatePPN);
844
+ for (i = 0; i < PVSCSI_SETUP_RINGS_MAX_NUM_PAGES; i++) {
845
+ translated.reqRingPPNs[i] = le64_to_cpu(rc->reqRingPPNs[i]);
846
+ translated.cmpRingPPNs[i] = le64_to_cpu(rc->cmpRingPPNs[i]);
847
+ }
848
+ rc = &translated;
849
850
trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_RINGS");
851
@@ -831,6 +869,11 @@ pvscsi_on_cmd_abort(PVSCSIState *s)
869
PVSCSICmdDescAbortCmd *cmd = (PVSCSICmdDescAbortCmd *) s->curr_cmd_data;
870
PVSCSIRequest *r, *next;
871
872
+ PVSCSICmdDescAbortCmd translated = *cmd;
873
+ translated.context = le32_to_cpu(cmd->context);
874
+ translated.target = le32_to_cpu(cmd->target);
875
+ cmd = &translated;
876
+
877
trace_pvscsi_on_cmd_abort(cmd->context, cmd->target);
878
879
QTAILQ_FOREACH_SAFE(r, &s->pending_queue, next, next) {
@@ -862,6 +905,10 @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
905
(struct PVSCSICmdDescResetDevice *) s->curr_cmd_data;
906
SCSIDevice *sdev;
907
908
+ PVSCSICmdDescResetDevice translated = *cmd;
909
+ translated.target = le32_to_cpu(cmd->target);
910
+ cmd = &translated;
911
+
912
sdev = pvscsi_device_find(s, 0, cmd->target, cmd->lun, &target_lun);
913
914
trace_pvscsi_on_cmd_reset_dev(cmd->target, (int) target_lun, sdev);
@@ -892,6 +939,14 @@ pvscsi_on_cmd_setup_msg_ring(PVSCSIState *s)
939
{
940
PVSCSICmdDescSetupMsgRing *rc =
941
(PVSCSICmdDescSetupMsgRing *) s->curr_cmd_data;
942
+ PVSCSICmdDescSetupMsgRing translated = *rc;
943
+ int i;
944
+
945
+ translated.numPages = le32_to_cpu(rc->numPages);
946
+ for (i = 0; i < PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES; i++) {
947
+ translated.ringPPNs[i] = le64_to_cpu(rc->ringPPNs[i]);
948
+ }
949
+ rc = &translated;
950
951
trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_MSG_RING");
952
@@ -994,7 +1049,7 @@ pvscsi_on_command_data(PVSCSIState *s, uint32_t value)
1049
size_t bytes_arrived = s->curr_cmd_data_cntr * sizeof(uint32_t);
1050
1051
assert(bytes_arrived < sizeof(s->curr_cmd_data));
997
- s->curr_cmd_data[s->curr_cmd_data_cntr++] = value;
1052
+ s->curr_cmd_data[s->curr_cmd_data_cntr++] = cpu_to_le32(value);
1053
1054
pvscsi_do_command_processing(s);
1055
}