@samitouri / QOSamiQemu / commits / 5a811329bd

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 }