mirror of
https://gitlab.com/qemu-project/qemu.git
synced 2026-08-26 22:23:12 -04:00
Misc HW patches
Various fixes mostly related to misc hardware devices. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmpYiKcACgkQ4+MsLN6t wN75XhAAhaSICy5imrRLP39yCKHuw+YKblyzGOBE5v17io7BntQoBOrYERTETwcm R7SFUMFrvEJC21anOJ7kyc62jhrsnjWofmBp3sBV6eENboZXxuHxsIIr8mxJ+dgv 5u9UTfYQ6CMDWbM7keRpRFIKU2sogk1RUyH7Z3kedh3G6MEA4CrSkSf6B777G1lQ rm0rcJd5m6lDQ5rmrAd0jsJaI0UaOKLamcb43pm9w3KBDTHhOdJQNwqUX517R69p kjhZPAdIGRfyXsOd9S74jr+ZI+kzCi0fCcQGUwD5yges2oxAS+1N5TjYPzMz0E2v LDmuTrzRAqfl015QHbj5ayQHk/pAS/Mogoho29G4F6+nTKoo9HeIPX3bEEezJ1Nv TpQaD3fp3YBa7BubCSzij0zVZ3PFK1wTY1CrkFC8Je3gejZAafoWKWtZKGBD0nNz 2Qzwbef1g45v/GfQzdg3Fp3pgMeU7cHR60pAJsSI8ATbtXEZnWi/wc5VbhiJXXBB b8C2wefcbYP1wMKOL+cVZSG9wrwyj5/Yc9wW9nlFykOsBHVPYwvFhwA4dZlxCUXV MFWJHUdLdSOomhJqr/syH4V2EGuP9dXsz1zw9E0F06dwayjVOhX6Sd3rW6qj8+H7 a8Nt7ZthWYpF/6e47HXOzS7VaXy4mvXz8kg4QGVlTBLbS3hGXpg= =Wjnj -----END PGP SIGNATURE----- Merge tag 'hw-misc-20260714' of https://github.com/philmd/qemu into staging Misc HW patches Various fixes mostly related to misc hardware devices. # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmpYiKcACgkQ4+MsLN6t # wN75XhAAhaSICy5imrRLP39yCKHuw+YKblyzGOBE5v17io7BntQoBOrYERTETwcm # R7SFUMFrvEJC21anOJ7kyc62jhrsnjWofmBp3sBV6eENboZXxuHxsIIr8mxJ+dgv # 5u9UTfYQ6CMDWbM7keRpRFIKU2sogk1RUyH7Z3kedh3G6MEA4CrSkSf6B777G1lQ # rm0rcJd5m6lDQ5rmrAd0jsJaI0UaOKLamcb43pm9w3KBDTHhOdJQNwqUX517R69p # kjhZPAdIGRfyXsOd9S74jr+ZI+kzCi0fCcQGUwD5yges2oxAS+1N5TjYPzMz0E2v # LDmuTrzRAqfl015QHbj5ayQHk/pAS/Mogoho29G4F6+nTKoo9HeIPX3bEEezJ1Nv # TpQaD3fp3YBa7BubCSzij0zVZ3PFK1wTY1CrkFC8Je3gejZAafoWKWtZKGBD0nNz # 2Qzwbef1g45v/GfQzdg3Fp3pgMeU7cHR60pAJsSI8ATbtXEZnWi/wc5VbhiJXXBB # b8C2wefcbYP1wMKOL+cVZSG9wrwyj5/Yc9wW9nlFykOsBHVPYwvFhwA4dZlxCUXV # MFWJHUdLdSOomhJqr/syH4V2EGuP9dXsz1zw9E0F06dwayjVOhX6Sd3rW6qj8+H7 # a8Nt7ZthWYpF/6e47HXOzS7VaXy4mvXz8kg4QGVlTBLbS3hGXpg= # =Wjnj # -----END PGP SIGNATURE----- # gpg: Signature made Thu 16 Jul 2026 08:30:47 BST # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full] # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * tag 'hw-misc-20260714' of https://github.com/philmd/qemu: net: only advertise passt in netdev help when CONFIG_PASST hw/usb/hcd-xhci: Use qemu_log_mask() instead of fprintf() statement hw/usb/hcd-xhci: Remove the FIXME macro hw/usb/hcd-xhci: Turn guest-triggerable abort() into qemu_log_mask() hw/usb/hcd-ohci: Make sure that ohci_service_ed_list() cannot loop forever hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure hw/sparc64/niagara: use int64_t for vdisk size to avoid truncation hw/display/qxl: fix TOCTOU in cursor chunk data_size handling hw/scsi/vmw_pvscsi: add a comment to explain the endianness hw/scsi/vmw_pvscsi: translate data endianness docs/devel: Document SSI dummy-cycle ownership hw/misc/ivshmem: clear chardev handlers before freeing peers hw/sparc64/sun4u: Mark unusable PCI busses as full to ease device plugging Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
5ef0ecc594
13 changed files with 255 additions and 21 deletions
|
|
@ -2350,6 +2350,7 @@ T: git https://github.com/bonzini/qemu.git scsi-next
|
|||
SSI
|
||||
M: Alistair Francis <alistair@alistair23.me>
|
||||
S: Maintained
|
||||
F: docs/devel/ssi.rst
|
||||
F: hw/ssi/*
|
||||
F: hw/block/m25p80*
|
||||
F: include/hw/ssi/ssi.h
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ Details about QEMU's various subsystems including how to add features to them.
|
|||
reset
|
||||
s390-cpu-topology
|
||||
s390-dasd-ipl
|
||||
ssi
|
||||
tracing
|
||||
uefi-vars
|
||||
vfio-iommufd
|
||||
|
|
|
|||
132
docs/devel/ssi.rst
Normal file
132
docs/devel/ssi.rst
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
================================
|
||||
SSI devices and SPI flash models
|
||||
================================
|
||||
|
||||
QEMU's Synchronous Serial Interface (SSI) bus models the full-duplex transfer
|
||||
of words between a controller and one selected peripheral. Most SPI flash
|
||||
models, including ``m25p80``, are attached to controllers through this bus.
|
||||
|
||||
This page documents the expected boundary between a controller model and a
|
||||
flash model for SPI fast-read dummy cycles. The boundary is important because
|
||||
many real controllers expose dummy-cycle configuration in registers, while the
|
||||
flash model observes only the byte stream delivered through ``ssi_transfer()``.
|
||||
|
||||
SSI transfer granularity
|
||||
------------------------
|
||||
|
||||
``ssi_transfer()`` transfers one SSI word. Flash models that implement common
|
||||
SPI NOR command streams usually consume one 8-bit word at a time:
|
||||
|
||||
* command opcode;
|
||||
* address bytes;
|
||||
* optional mode or continuous-read bytes;
|
||||
* dummy bytes;
|
||||
* data bytes.
|
||||
|
||||
The SSI core does not model individual clock edges or the number of active SPI
|
||||
data lines. If a real transaction has a dummy phase expressed in clock cycles,
|
||||
the device model that generates transfers on the SSI bus must represent that
|
||||
phase as a number of dummy byte transfers.
|
||||
|
||||
Flash model responsibilities
|
||||
----------------------------
|
||||
|
||||
A SPI flash model owns the command semantics for the flash device:
|
||||
|
||||
* which opcodes are recognized;
|
||||
* how many address bytes are required;
|
||||
* whether a command has mode bytes;
|
||||
* how many dummy bytes must be consumed before data can be returned;
|
||||
* manufacturer-specific differences in fast-read command behavior.
|
||||
|
||||
For the ``m25p80`` model, ``needed_bytes`` is a byte count. It must not store
|
||||
raw dummy cycles. When a flash datasheet describes the dummy phase in cycles,
|
||||
the flash model converts the cycles to bytes using the bus width used for the
|
||||
dummy phase::
|
||||
|
||||
dummy_bytes = DIV_ROUND_UP(dummy_cycles * dummy_bus_width, 8)
|
||||
|
||||
For SPI NOR fast-read commands modeled by ``m25p80``, the dummy phase follows
|
||||
the address phase width. For example, output-only dual and quad read commands
|
||||
such as DOR and QOR use one line for command, address, and dummy phases, then
|
||||
use two or four lines only for the data phase. Dual I/O and Quad I/O commands
|
||||
such as DIOR and QIOR use the wider bus for both address and dummy phases.
|
||||
|
||||
If the exact dummy phase cannot be represented as a whole number of SSI byte
|
||||
transfers, the model should round up and log the limitation instead of silently
|
||||
treating cycles as bytes.
|
||||
|
||||
Controller model responsibilities
|
||||
---------------------------------
|
||||
|
||||
A controller model owns the behavior of the controller hardware:
|
||||
|
||||
* how guest-visible registers select command, address width, bus width, and
|
||||
dummy-cycle count;
|
||||
* whether the guest supplies dummy bytes in a transmit FIFO;
|
||||
* whether the controller itself generates the dummy phase for a memory-mapped,
|
||||
direct-read, or other automatic transfer mode;
|
||||
* how chip-select state changes around controller-generated transfers.
|
||||
|
||||
When guest software writes dummy bytes into a transmit FIFO or manual transfer
|
||||
path, the controller should pass those bytes to ``ssi_transfer()`` like any
|
||||
other guest-provided byte. It should not add more dummy transfers on behalf of
|
||||
the flash.
|
||||
|
||||
When hardware registers instruct the controller to generate a dummy phase, the
|
||||
controller must emit dummy byte transfers before data transfers reach the flash
|
||||
model. The controller should convert the configured cycle count using the bus
|
||||
width that the controller uses during the dummy phase. For example:
|
||||
|
||||
* 8 dummy cycles on a single data line become 1 dummy byte;
|
||||
* 8 dummy cycles on two data lines become 2 dummy bytes;
|
||||
* 8 dummy cycles on four data lines become 4 dummy bytes.
|
||||
|
||||
The controller should not duplicate flash-specific opcode tables merely to
|
||||
guess which commands need dummy cycles. In automatic modes the controller
|
||||
already has enough hardware configuration to know whether it must generate a
|
||||
dummy phase. In manual modes the guest-provided byte stream is authoritative.
|
||||
|
||||
Avoiding double counting
|
||||
------------------------
|
||||
|
||||
Exactly one side should generate each dummy byte transfer seen by the flash:
|
||||
|
||||
* If the guest sends dummy bytes through the controller, the controller forwards
|
||||
them and the flash consumes them.
|
||||
* If the guest programs a controller dummy-cycle register, the controller
|
||||
converts those cycles to dummy byte transfers and the flash consumes them.
|
||||
* The flash may know that a command requires dummy bytes, but it does not create
|
||||
transfers on the SSI bus.
|
||||
|
||||
Do not implement controller-side snooping that watches manual-mode opcode
|
||||
streams and injects extra dummy transfers based on flash opcodes. That mixes
|
||||
flash command semantics into the controller and is fragile when flash models
|
||||
gain correct dummy-byte accounting.
|
||||
|
||||
Examples in the tree
|
||||
--------------------
|
||||
|
||||
The following models illustrate the boundary:
|
||||
|
||||
* ``hw/block/m25p80.c`` keeps fast-read dummy requirements as byte counts in
|
||||
``needed_bytes``. Manufacturer-specific helpers convert datasheet dummy
|
||||
cycles to the byte stream expected by the model.
|
||||
* ``hw/ssi/aspeed_smc.c`` generates dummy byte transfers for direct fast-read
|
||||
mode from controller registers, but manual user-mode writes are forwarded as
|
||||
guest-provided bytes.
|
||||
* ``hw/ssi/npcm7xx_fiu.c`` converts the direct-read dummy configuration to the
|
||||
number of dummy byte transfers sent before reading data.
|
||||
|
||||
Review checklist
|
||||
----------------
|
||||
|
||||
When adding or changing a SPI flash controller or flash model, check:
|
||||
|
||||
* Are dummy counts stored in byte units when they drive flash state machines?
|
||||
* If a hardware register stores cycles, is the conversion to bytes based on the
|
||||
bus width of the dummy phase?
|
||||
* Are manual guest-provided dummy bytes forwarded without extra injection?
|
||||
* Are automatic controller-generated dummy phases modeled by the controller?
|
||||
* Is flash-specific opcode knowledge kept in the flash model rather than copied
|
||||
into controller snooping paths?
|
||||
|
|
@ -217,7 +217,8 @@ void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie)
|
|||
}
|
||||
|
||||
static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,
|
||||
QXLDataChunk *chunk, uint32_t group_id)
|
||||
QXLDataChunk *chunk, uint32_t group_id,
|
||||
uint32_t chunk_data_size)
|
||||
{
|
||||
uint32_t max_chunks = 32;
|
||||
size_t offset = 0;
|
||||
|
|
@ -225,22 +226,21 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,
|
|||
QXLPHYSICAL next_chunk_phys = 0;
|
||||
|
||||
for (;;) {
|
||||
bytes = MIN(size - offset, chunk->data_size);
|
||||
bytes = MIN(size - offset, chunk_data_size);
|
||||
memcpy(dest + offset, chunk->data, bytes);
|
||||
offset += bytes;
|
||||
if (offset == size) {
|
||||
return;
|
||||
}
|
||||
next_chunk_phys = chunk->next_chunk;
|
||||
/* fist time, only get the next chunk's data size */
|
||||
chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
|
||||
sizeof(QXLDataChunk));
|
||||
if (!chunk) {
|
||||
return;
|
||||
}
|
||||
/* second time, check data size and get data */
|
||||
chunk_data_size = chunk->data_size;
|
||||
chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
|
||||
sizeof(QXLDataChunk) + chunk->data_size);
|
||||
sizeof(QXLDataChunk) + chunk_data_size);
|
||||
if (!chunk) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -252,7 +252,7 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,
|
|||
}
|
||||
|
||||
static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
|
||||
uint32_t group_id)
|
||||
uint32_t group_id, uint32_t chunk_data_size)
|
||||
{
|
||||
QEMUCursor *c;
|
||||
uint8_t *and_mask, *xor_mask;
|
||||
|
|
@ -272,11 +272,11 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
|
|||
case SPICE_CURSOR_TYPE_MONO:
|
||||
/* Assume that the full cursor is available in a single chunk. */
|
||||
size = 2 * cursor_get_mono_bpl(c) * c->height;
|
||||
if (size != cursor->data_size || cursor->chunk.data_size < size) {
|
||||
if (size != cursor->data_size || chunk_data_size < size) {
|
||||
qxl_set_guest_bug(qxl, "%s: bad monochrome cursor %ux%u"
|
||||
" data_size %u chunk_size %u",
|
||||
__func__, c->width, c->height,
|
||||
cursor->data_size, cursor->chunk.data_size);
|
||||
cursor->data_size, chunk_data_size);
|
||||
goto fail;
|
||||
}
|
||||
and_mask = cursor->chunk.data;
|
||||
|
|
@ -288,7 +288,8 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
|
|||
break;
|
||||
case SPICE_CURSOR_TYPE_ALPHA:
|
||||
size = sizeof(uint32_t) * c->width * c->height;
|
||||
qxl_unpack_chunks(c->data, size, qxl, &cursor->chunk, group_id);
|
||||
qxl_unpack_chunks(c->data, size, qxl, &cursor->chunk, group_id,
|
||||
chunk_data_size);
|
||||
if (qxl->debug > 2) {
|
||||
cursor_print_ascii_art(c, "qxl/alpha");
|
||||
}
|
||||
|
|
@ -325,19 +326,23 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
|
|||
}
|
||||
switch (cmd->type) {
|
||||
case QXL_CURSOR_SET:
|
||||
{
|
||||
uint32_t chunk_data_size;
|
||||
|
||||
/* First read the QXLCursor to get QXLDataChunk::data_size ... */
|
||||
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id,
|
||||
sizeof(QXLCursor));
|
||||
if (!cursor) {
|
||||
return 1;
|
||||
}
|
||||
chunk_data_size = cursor->chunk.data_size;
|
||||
/* Then read including the chunked data following QXLCursor. */
|
||||
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id,
|
||||
sizeof(QXLCursor) + cursor->chunk.data_size);
|
||||
sizeof(QXLCursor) + chunk_data_size);
|
||||
if (!cursor) {
|
||||
return 1;
|
||||
}
|
||||
c = qxl_cursor(qxl, cursor, ext->group_id);
|
||||
c = qxl_cursor(qxl, cursor, ext->group_id, chunk_data_size);
|
||||
if (c == NULL) {
|
||||
c = cursor_builtin_left_ptr();
|
||||
}
|
||||
|
|
@ -351,6 +356,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
|
|||
qemu_mutex_unlock(&qxl->ssd.lock);
|
||||
qemu_bh_schedule(qxl->ssd.cursor_bh);
|
||||
break;
|
||||
}
|
||||
case QXL_CURSOR_MOVE:
|
||||
qemu_mutex_lock(&qxl->ssd.lock);
|
||||
qxl->ssd.mouse_x = cmd->u.position.x;
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
|
|||
}
|
||||
virtio_gpu_remap_udmabuf(res);
|
||||
if (!res->remapped) {
|
||||
virtio_gpu_destroy_udmabuf(res);
|
||||
return;
|
||||
}
|
||||
pdata = res->remapped;
|
||||
|
|
|
|||
|
|
@ -938,6 +938,9 @@ static void ivshmem_exit(PCIDevice *dev)
|
|||
IVShmemState *s = IVSHMEM_COMMON(dev);
|
||||
int i;
|
||||
|
||||
qemu_chr_fe_set_handlers(&s->server_chr,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, true);
|
||||
|
||||
migrate_del_blocker(&s->migration_blocker);
|
||||
|
||||
if (memory_region_is_mapped(s->ivshmem_bar2)) {
|
||||
|
|
@ -966,6 +969,8 @@ static void ivshmem_exit(PCIDevice *dev)
|
|||
close_peer_eventfds(s, i);
|
||||
}
|
||||
g_free(s->peers);
|
||||
s->peers = NULL;
|
||||
s->nb_peers = 0;
|
||||
}
|
||||
|
||||
if (ivshmem_has_feature(s, IVSHMEM_MSI)) {
|
||||
|
|
@ -973,6 +978,7 @@ static void ivshmem_exit(PCIDevice *dev)
|
|||
}
|
||||
|
||||
g_free(s->msi_vectors);
|
||||
s->msi_vectors = NULL;
|
||||
}
|
||||
|
||||
static int ivshmem_pre_load(void *opaque)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,6 +108,20 @@ enum PVSCSICommands {
|
|||
#define PVSCSI_COMMAND_PROCESSING_FAILED (-1)
|
||||
#define PVSCSI_COMMAND_NOT_ENOUGH_DATA (-2)
|
||||
|
||||
/*
|
||||
* About endianess for the below structs:
|
||||
*
|
||||
* These structs are used to describe the data that is exchanged between the
|
||||
* guest and the PVSCSI device. The endianess of the fields in these structs
|
||||
* is not defined by any standard. The current implemented drivers are designed
|
||||
* to only work on x86 architecture, so there is no endianess awareness in the
|
||||
* drivers and thus we have no idea whether the fields should be in little-
|
||||
* endian or target native endian format.
|
||||
*
|
||||
* Considering the above, we assume that PVSCSI is implicitly little-endian and
|
||||
* expect the fields in these structs to be in little-endian format.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Command descriptor for PVSCSI_CMD_RESET_DEVICE --
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ static void niagara_init(MachineState *machine)
|
|||
outside of the partition RAM */
|
||||
if (dinfo) {
|
||||
BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
|
||||
int size = blk_getlength(blk);
|
||||
int64_t size = blk_getlength(blk);
|
||||
if (size > 0) {
|
||||
memory_region_init_ram(&s->vdisk_ram, NULL, "sun4v_vdisk.ram", size,
|
||||
&error_fatal);
|
||||
|
|
|
|||
|
|
@ -719,6 +719,13 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
|||
fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth);
|
||||
|
||||
qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
|
||||
|
||||
/*
|
||||
* Mark internal PCI busses as full so that the plugging of additional
|
||||
* PCI devices happens on the right bus that still has free slots:
|
||||
*/
|
||||
qbus_mark_full(&pci_bus->qbus);
|
||||
qbus_mark_full(&pci_busA->qbus);
|
||||
}
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "hw/core/irq.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/usb/usb.h"
|
||||
|
|
@ -1129,6 +1130,8 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head)
|
|||
return 0;
|
||||
}
|
||||
for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) {
|
||||
unsigned int ed_cnt = 0;
|
||||
|
||||
if (ohci_read_ed(ohci, cur, &ed)) {
|
||||
trace_usb_ohci_ed_read_error(cur);
|
||||
ohci_die(ohci);
|
||||
|
|
@ -1172,6 +1175,13 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ed_cnt++ > ED_LINK_LIMIT) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"ohci: Too many endpoint descriptors in loop\n");
|
||||
ohci_die(ohci);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ohci_put_ed(ohci, cur, &ed)) {
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@
|
|||
#else
|
||||
#define DPRINTF(...) do {} while (0)
|
||||
#endif
|
||||
#define FIXME(_msg) do { fprintf(stderr, "FIXME %s:%d %s\n", \
|
||||
__func__, __LINE__, _msg); abort(); } while (0)
|
||||
|
||||
#define TRB_LINK_LIMIT 32
|
||||
#define COMMAND_LIMIT 256
|
||||
|
|
@ -965,11 +963,13 @@ static TRBCCode xhci_alloc_device_streams(XHCIState *xhci, unsigned int slotid,
|
|||
* together and make an usb_device_alloc_streams call per group.
|
||||
*/
|
||||
if (epctxs[i]->nr_pstreams != req_nr_streams) {
|
||||
FIXME("guest streams config not identical for all eps");
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"guest streams config not identical for all eps\n");
|
||||
return CC_RESOURCE_ERROR;
|
||||
}
|
||||
if (eps[i]->max_streams != dev_max_streams) {
|
||||
FIXME("device streams config not identical for all eps");
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"device streams config not identical for all eps\n");
|
||||
return CC_RESOURCE_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -1017,7 +1017,8 @@ static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx,
|
|||
}
|
||||
sctx = epctx->pstreams + streamid;
|
||||
} else {
|
||||
fprintf(stderr, "xhci: FIXME: secondary streams not implemented yet");
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"xhci: secondary streams not implemented yet\n");
|
||||
*cc_error = CC_INVALID_STREAM_TYPE_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1671,9 +1672,7 @@ static int xhci_try_complete_packet(XHCITransfer *xfer)
|
|||
xhci_stall_ep(xfer);
|
||||
break;
|
||||
default:
|
||||
DPRINTF("%s: FIXME: status = %d\n", __func__,
|
||||
xfer->packet.status);
|
||||
FIXME("unhandled USB_RET_*");
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1385,7 +1385,9 @@ void show_netdevs(void)
|
|||
"dgram",
|
||||
"hubport",
|
||||
"tap",
|
||||
#ifdef CONFIG_PASST
|
||||
"passt",
|
||||
#endif
|
||||
#ifdef CONFIG_SLIRP
|
||||
"user",
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue