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 cb30b8758d physmem API conversion]
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
This commit is contained in:
committed by
Philippe Mathieu-Daudé
parent
6387fbad45
commit
5a811329bd
@@ -392,9 +392,18 @@ static void
|
||||
pvscsi_cmp_ring_put(PVSCSIState *s, struct PVSCSIRingCmpDesc *cmp_desc)
|
||||
{
|
||||
hwaddr cmp_descr_pa;
|
||||
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 = cpu_to_le64(cmp_desc->context),
|
||||
.dataLen = cpu_to_le64(cmp_desc->dataLen),
|
||||
.senseLen = cpu_to_le32(cmp_desc->senseLen),
|
||||
.hostStatus = cpu_to_le16(cmp_desc->hostStatus),
|
||||
.scsiStatus = cpu_to_le16(cmp_desc->scsiStatus),
|
||||
};
|
||||
cmp_desc = &cmp_desc_conv;
|
||||
physical_memory_write(cmp_descr_pa, cmp_desc, sizeof(*cmp_desc));
|
||||
}
|
||||
|
||||
@@ -402,9 +411,18 @@ static void
|
||||
pvscsi_msg_ring_put(PVSCSIState *s, struct PVSCSIRingMsgDesc *msg_desc)
|
||||
{
|
||||
hwaddr msg_descr_pa;
|
||||
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 = (PVSCSIRingMsgDesc) {
|
||||
.type = cpu_to_le32(msg_desc->type),
|
||||
};
|
||||
for (i = 0; i < ARRAY_SIZE(msg_desc->args); i++) {
|
||||
msg_desc_conv.args[i] = cpu_to_le32(msg_desc->args[i]);
|
||||
}
|
||||
msg_desc = &msg_desc_conv;
|
||||
physical_memory_write(msg_descr_pa, msg_desc, sizeof(*msg_desc));
|
||||
}
|
||||
|
||||
@@ -481,6 +499,9 @@ pvscsi_get_next_sg_elem(PVSCSISGState *sg)
|
||||
struct PVSCSISGElement elem;
|
||||
|
||||
physical_memory_read(sg->elemAddr, &elem, sizeof(elem));
|
||||
elem.addr = le64_to_cpu(elem.addr);
|
||||
elem.length = le32_to_cpu(elem.length);
|
||||
elem.flags = le32_to_cpu(elem.flags);
|
||||
if ((elem.flags & ~PVSCSI_KNOWN_FLAGS) != 0) {
|
||||
/*
|
||||
* There is PVSCSI_SGE_FLAG_CHAIN_ELEMENT flag described in
|
||||
@@ -759,6 +780,12 @@ pvscsi_process_io(PVSCSIState *s)
|
||||
|
||||
trace_pvscsi_process_io(next_descr_pa);
|
||||
physical_memory_read(next_descr_pa, &descr, sizeof(descr));
|
||||
descr.context = le64_to_cpu(descr.context);
|
||||
descr.dataAddr = le64_to_cpu(descr.dataAddr);
|
||||
descr.dataLen = le64_to_cpu(descr.dataLen);
|
||||
descr.senseAddr = le64_to_cpu(descr.senseAddr);
|
||||
descr.senseLen = le32_to_cpu(descr.senseLen);
|
||||
descr.flags = le32_to_cpu(descr.flags);
|
||||
pvscsi_process_request_descriptor(s, &descr);
|
||||
}
|
||||
|
||||
@@ -808,6 +835,17 @@ pvscsi_on_cmd_setup_rings(PVSCSIState *s)
|
||||
{
|
||||
PVSCSICmdDescSetupRings *rc =
|
||||
(PVSCSICmdDescSetupRings *) s->curr_cmd_data;
|
||||
PVSCSICmdDescSetupRings translated;
|
||||
int i;
|
||||
|
||||
translated.reqRingNumPages = le32_to_cpu(rc->reqRingNumPages);
|
||||
translated.cmpRingNumPages = le32_to_cpu(rc->cmpRingNumPages);
|
||||
translated.ringsStatePPN = le64_to_cpu(rc->ringsStatePPN);
|
||||
for (i = 0; i < PVSCSI_SETUP_RINGS_MAX_NUM_PAGES; i++) {
|
||||
translated.reqRingPPNs[i] = le64_to_cpu(rc->reqRingPPNs[i]);
|
||||
translated.cmpRingPPNs[i] = le64_to_cpu(rc->cmpRingPPNs[i]);
|
||||
}
|
||||
rc = &translated;
|
||||
|
||||
trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_RINGS");
|
||||
|
||||
@@ -831,6 +869,11 @@ pvscsi_on_cmd_abort(PVSCSIState *s)
|
||||
PVSCSICmdDescAbortCmd *cmd = (PVSCSICmdDescAbortCmd *) s->curr_cmd_data;
|
||||
PVSCSIRequest *r, *next;
|
||||
|
||||
PVSCSICmdDescAbortCmd translated = *cmd;
|
||||
translated.context = le32_to_cpu(cmd->context);
|
||||
translated.target = le32_to_cpu(cmd->target);
|
||||
cmd = &translated;
|
||||
|
||||
trace_pvscsi_on_cmd_abort(cmd->context, cmd->target);
|
||||
|
||||
QTAILQ_FOREACH_SAFE(r, &s->pending_queue, next, next) {
|
||||
@@ -862,6 +905,10 @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
|
||||
(struct PVSCSICmdDescResetDevice *) s->curr_cmd_data;
|
||||
SCSIDevice *sdev;
|
||||
|
||||
PVSCSICmdDescResetDevice translated = *cmd;
|
||||
translated.target = le32_to_cpu(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 +939,14 @@ pvscsi_on_cmd_setup_msg_ring(PVSCSIState *s)
|
||||
{
|
||||
PVSCSICmdDescSetupMsgRing *rc =
|
||||
(PVSCSICmdDescSetupMsgRing *) s->curr_cmd_data;
|
||||
PVSCSICmdDescSetupMsgRing translated = *rc;
|
||||
int i;
|
||||
|
||||
translated.numPages = le32_to_cpu(rc->numPages);
|
||||
for (i = 0; i < PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES; i++) {
|
||||
translated.ringPPNs[i] = le64_to_cpu(rc->ringPPNs[i]);
|
||||
}
|
||||
rc = &translated;
|
||||
|
||||
trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_MSG_RING");
|
||||
|
||||
@@ -994,7 +1049,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++] = cpu_to_le32(value);
|
||||
|
||||
pvscsi_do_command_processing(s);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user