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:
Stefan Hajnoczi 2026-07-17 10:01:51 +01:00
commit 5ef0ecc594
13 changed files with 255 additions and 21 deletions

View file

@ -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

View file

@ -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
View 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?

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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);
}

View file

@ -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 --
*/

View file

@ -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);

View file

@ -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 {

View file

@ -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)) {

View file

@ -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;
}

View file

@ -1385,7 +1385,9 @@ void show_netdevs(void)
"dgram",
"hubport",
"tap",
#ifdef CONFIG_PASST
"passt",
#endif
#ifdef CONFIG_SLIRP
"user",
#endif