Skip to content

Commit 4c33c09

Browse files
committed
Merge tag 'hw-misc-20250312' of https://github.com/philmd/qemu into staging
Misc HW patches - Set correct values for MPC8569E's eSDHC (Zoltan) - Emulate Ricoh RS5C372 RTC device (Bernhard) - Array overflow fixes in SMSC91C111 netdev (Peter) - Fix typo in Xen HVM (Philippe) - Move graphic height/width/depth globals to their own file (Philippe) - Introduce qemu_arch_available() helper (Philippe) - Check fw_cfg's ACPI availability at runtime (Philippe) - Remove virtio-mem dependency on CONFIG_DEVICES (Philippe) - Sort HyperV SYNDBG API definitions (Pierrick) - Remove need for SDHCI_VENDOR_FSL definition (Philippe) # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmfRXiMACgkQ4+MsLN6t # wN5zFhAAzSW/hZneD8hycKtr9nBlvZSD72cEt+b656OCbTyyucUi1sG4rMPMvHeW # h6HP6xt2SfQxXbec6Y0pWxWUkBOQzk72s0zpttOED3oEspkrId2D+VSsSH1E+QLh # WoG7/hVgz0bDHexWYIDdGufO4no/icwewAKmC5Kp2HbaNxIIHyWlK1+RO69/lCLN # s3qkNesMsQyEWN28ogEMRqyCIG3oJVP76U4TVcdxIiE51WI8sP8/7V2um0AXN68m # IV3INrfVJjGDp501elrUbD3qsYopRdxoMAvwiVojrLXin6xtS+SQjEe/hcNxzM70 # 0IQPp9WWwLjNkeFlAJF4wpwGJttFNHj+5gtH7/YRrP75jt9kAxPXkFw/OFfpVd30 # NYbeFlWDhRL1QPBs+WPBZTrfD7fRmpfMJRLF3/w61+WvnVrshlyDaoCWbR+L329F # uOQFsBdAD7m/lkZ0mHtskS2vkZx7Itn1av4gql7T7/6cE1R7ItKy1HY9UUCtY6Gp # 7V6XrsAE3khg2HY8IcJ73+sPLQn/GxqZFE7PqmAhgcl6RZEFQv8PNrEgFxCEYyuK # KJjx0hRMLoigp0CEclLfOqz2d3knsI8SJbgD4iTYQc02E69lx8a4XS4N8JXoLEdh # 3i/ndwKEFmzwNuqbU0nYsSJDiAO9ejra8O2BXZS/a4pkxC2jtdw= # =VVr6 # -----END PGP SIGNATURE----- # gpg: Signature made Wed 12 Mar 2025 18:12:51 HKT # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <[email protected]>" [full] # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * tag 'hw-misc-20250312' of https://github.com/philmd/qemu: hw/sd/sdhci: Remove need for SDHCI_VENDOR_IMX definition hw/hyperv/hyperv-proto: Move SYNDBG definitions from target/i386 hw/virtio/virtio-mem: Remove CONFIG_DEVICES include hw/i386/fw_cfg: Check ACPI availability with acpi_builtin() hw/acpi: Introduce acpi_builtin() helper system: Replace arch_type global by qemu_arch_available() helper system: Extract target-specific globals to their own compilation unit hw/xen/hvm: Fix Aarch64 typo hw/net/smc91c111: Don't allow data register access to overrun buffer hw/net/smc91c111: Use MAX_PACKET_SIZE instead of magic numbers hw/net/smc91c111: Sanitize packet length on tx hw/net/smc91c111: Sanitize packet numbers hw/rtc: Add Ricoh RS5C372 RTC emulation hw/sd/sdhci: Set reset value of interrupt registers Signed-off-by: Stefan Hajnoczi <[email protected]>
2 parents 74b3445 + 7f2a527 commit 4c33c09

31 files changed

+503
-82
lines changed

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,10 +827,12 @@ F: hw/arm/imx8mp-evk.c
827827
F: hw/arm/fsl-imx8mp.c
828828
F: hw/misc/imx8mp_*.c
829829
F: hw/pci-host/fsl_imx8m_phy.c
830+
F: hw/rtc/rs5c372.c
830831
F: include/hw/arm/fsl-imx8mp.h
831832
F: include/hw/misc/imx8mp_*.h
832833
F: include/hw/pci-host/fsl_imx8m_phy.h
833834
F: docs/system/arm/imx8mp-evk.rst
835+
F: tests/qtest/rs5c372-test.c
834836

835837
MPS2 / MPS3
836838
M: Peter Maydell <[email protected]>

hw/acpi/acpi-stub.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,15 @@
2121
#include "qemu/osdep.h"
2222
#include "hw/acpi/acpi.h"
2323

24+
char unsigned *acpi_tables;
25+
size_t acpi_tables_len;
26+
2427
void acpi_table_add(const QemuOpts *opts, Error **errp)
2528
{
2629
g_assert_not_reached();
2730
}
31+
32+
bool acpi_builtin(void)
33+
{
34+
return false;
35+
}

hw/acpi/core.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ static void acpi_register_config(void)
7878

7979
opts_init(acpi_register_config);
8080

81+
bool acpi_builtin(void)
82+
{
83+
return true;
84+
}
85+
8186
static int acpi_checksum(const uint8_t *data, int len)
8287
{
8388
int sum, i;

hw/arm/fsl-imx25.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,6 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
243243
&error_abort);
244244
object_property_set_uint(OBJECT(&s->esdhc[i]), "capareg",
245245
IMX25_ESDHC_CAPABILITIES, &error_abort);
246-
object_property_set_uint(OBJECT(&s->esdhc[i]), "vendor",
247-
SDHCI_VENDOR_IMX, &error_abort);
248246
if (!sysbus_realize(SYS_BUS_DEVICE(&s->esdhc[i]), errp)) {
249247
return;
250248
}

hw/arm/fsl-imx6.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,6 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
327327
&error_abort);
328328
object_property_set_uint(OBJECT(&s->esdhc[i]), "capareg",
329329
IMX6_ESDHC_CAPABILITIES, &error_abort);
330-
object_property_set_uint(OBJECT(&s->esdhc[i]), "vendor",
331-
SDHCI_VENDOR_IMX, &error_abort);
332330
if (!sysbus_realize(SYS_BUS_DEVICE(&s->esdhc[i]), errp)) {
333331
return;
334332
}

hw/arm/fsl-imx6ul.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,6 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
531531
FSL_IMX6UL_USDHC2_IRQ,
532532
};
533533

534-
object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
535-
SDHCI_VENDOR_IMX, &error_abort);
536534
sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), &error_abort);
537535

538536
sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0,

hw/arm/fsl-imx7.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,6 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
471471
FSL_IMX7_USDHC3_IRQ,
472472
};
473473

474-
object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
475-
SDHCI_VENDOR_IMX, &error_abort);
476474
sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), &error_abort);
477475

478476
sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0,

hw/arm/fsl-imx8mp.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,6 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
524524
{ fsl_imx8mp_memmap[FSL_IMX8MP_USDHC3].addr, FSL_IMX8MP_USDHC3_IRQ },
525525
};
526526

527-
object_property_set_uint(OBJECT(&s->usdhc[i]), "vendor",
528-
SDHCI_VENDOR_IMX, &error_abort);
529527
if (!sysbus_realize(SYS_BUS_DEVICE(&s->usdhc[i]), errp)) {
530528
return;
531529
}

hw/i386/fw_cfg.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,10 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms,
145145
*/
146146
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, apic_id_limit);
147147
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
148-
#ifdef CONFIG_ACPI
149-
fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
150-
acpi_tables, acpi_tables_len);
151-
#endif
148+
if (acpi_builtin()) {
149+
fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
150+
acpi_tables, acpi_tables_len);
151+
}
152152
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, 1);
153153

154154
fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_fw_cfg, sizeof(hpet_fw_cfg));

hw/net/smc91c111.c

Lines changed: 130 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "net/net.h"
1414
#include "hw/irq.h"
1515
#include "hw/net/smc91c111.h"
16+
#include "hw/registerfields.h"
1617
#include "hw/qdev-properties.h"
1718
#include "qapi/error.h"
1819
#include "qemu/log.h"
@@ -22,6 +23,13 @@
2223

2324
/* Number of 2k memory pages available. */
2425
#define NUM_PACKETS 4
26+
/*
27+
* Maximum size of a data frame, including the leading status word
28+
* and byte count fields and the trailing CRC, last data byte
29+
* and control byte (per figure 8-1 in the Microchip Technology
30+
* LAN91C111 datasheet).
31+
*/
32+
#define MAX_PACKET_SIZE 2048
2533

2634
#define TYPE_SMC91C111 "smc91c111"
2735
OBJECT_DECLARE_SIMPLE_TYPE(smc91c111_state, SMC91C111)
@@ -51,7 +59,7 @@ struct smc91c111_state {
5159
int tx_fifo_done_len;
5260
int tx_fifo_done[NUM_PACKETS];
5361
/* Packet buffer memory. */
54-
uint8_t data[NUM_PACKETS][2048];
62+
uint8_t data[NUM_PACKETS][MAX_PACKET_SIZE];
5563
uint8_t int_level;
5664
uint8_t int_mask;
5765
MemoryRegion mmio;
@@ -79,7 +87,8 @@ static const VMStateDescription vmstate_smc91c111 = {
7987
VMSTATE_INT32_ARRAY(rx_fifo, smc91c111_state, NUM_PACKETS),
8088
VMSTATE_INT32(tx_fifo_done_len, smc91c111_state),
8189
VMSTATE_INT32_ARRAY(tx_fifo_done, smc91c111_state, NUM_PACKETS),
82-
VMSTATE_BUFFER_UNSAFE(data, smc91c111_state, 0, NUM_PACKETS * 2048),
90+
VMSTATE_BUFFER_UNSAFE(data, smc91c111_state, 0,
91+
NUM_PACKETS * MAX_PACKET_SIZE),
8392
VMSTATE_UINT8(int_level, smc91c111_state),
8493
VMSTATE_UINT8(int_mask, smc91c111_state),
8594
VMSTATE_END_OF_LIST()
@@ -118,6 +127,18 @@ static const VMStateDescription vmstate_smc91c111 = {
118127
#define RS_TOOSHORT 0x0400
119128
#define RS_MULTICAST 0x0001
120129

130+
FIELD(PTR, PTR, 0, 11)
131+
FIELD(PTR, NOT_EMPTY, 11, 1)
132+
FIELD(PTR, RESERVED, 12, 1)
133+
FIELD(PTR, READ, 13, 1)
134+
FIELD(PTR, AUTOINCR, 14, 1)
135+
FIELD(PTR, RCV, 15, 1)
136+
137+
static inline bool packetnum_valid(int packet_num)
138+
{
139+
return packet_num >= 0 && packet_num < NUM_PACKETS;
140+
}
141+
121142
/* Update interrupt status. */
122143
static void smc91c111_update(smc91c111_state *s)
123144
{
@@ -218,12 +239,33 @@ static void smc91c111_pop_tx_fifo_done(smc91c111_state *s)
218239
/* Release the memory allocated to a packet. */
219240
static void smc91c111_release_packet(smc91c111_state *s, int packet)
220241
{
242+
if (!packetnum_valid(packet)) {
243+
/*
244+
* Data sheet doesn't document behaviour in this guest error
245+
* case, and there is no error status register to report it.
246+
* Log and ignore the attempt.
247+
*/
248+
qemu_log_mask(LOG_GUEST_ERROR,
249+
"smc91c111: attempt to release invalid packet %d\n",
250+
packet);
251+
return;
252+
}
221253
s->allocated &= ~(1 << packet);
222254
if (s->tx_alloc == 0x80)
223255
smc91c111_tx_alloc(s);
224256
smc91c111_flush_queued_packets(s);
225257
}
226258

259+
static void smc91c111_complete_tx_packet(smc91c111_state *s, int packetnum)
260+
{
261+
if (s->ctr & CTR_AUTO_RELEASE) {
262+
/* Race? */
263+
smc91c111_release_packet(s, packetnum);
264+
} else if (s->tx_fifo_done_len < NUM_PACKETS) {
265+
s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
266+
}
267+
}
268+
227269
/* Flush the TX FIFO. */
228270
static void smc91c111_do_tx(smc91c111_state *s)
229271
{
@@ -239,12 +281,25 @@ static void smc91c111_do_tx(smc91c111_state *s)
239281
return;
240282
for (i = 0; i < s->tx_fifo_len; i++) {
241283
packetnum = s->tx_fifo[i];
284+
/* queue_tx checked the packet number was valid */
285+
assert(packetnum_valid(packetnum));
242286
p = &s->data[packetnum][0];
243287
/* Set status word. */
244288
*(p++) = 0x01;
245289
*(p++) = 0x40;
246290
len = *(p++);
247291
len |= ((int)*(p++)) << 8;
292+
if (len > MAX_PACKET_SIZE) {
293+
/*
294+
* Datasheet doesn't say what to do here, and there is no
295+
* relevant tx error condition listed. Log, and drop the packet.
296+
*/
297+
qemu_log_mask(LOG_GUEST_ERROR,
298+
"smc91c111: tx packet with bad length %d, dropping\n",
299+
len);
300+
smc91c111_complete_tx_packet(s, packetnum);
301+
continue;
302+
}
248303
len -= 6;
249304
control = p[len + 1];
250305
if (control & 0x20)
@@ -273,11 +328,7 @@ static void smc91c111_do_tx(smc91c111_state *s)
273328
}
274329
}
275330
#endif
276-
if (s->ctr & CTR_AUTO_RELEASE)
277-
/* Race? */
278-
smc91c111_release_packet(s, packetnum);
279-
else if (s->tx_fifo_done_len < NUM_PACKETS)
280-
s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
331+
smc91c111_complete_tx_packet(s, packetnum);
281332
qemu_send_packet(qemu_get_queue(s->nic), p, len);
282333
}
283334
s->tx_fifo_len = 0;
@@ -287,6 +338,17 @@ static void smc91c111_do_tx(smc91c111_state *s)
287338
/* Add a packet to the TX FIFO. */
288339
static void smc91c111_queue_tx(smc91c111_state *s, int packet)
289340
{
341+
if (!packetnum_valid(packet)) {
342+
/*
343+
* Datasheet doesn't document behaviour in this error case, and
344+
* there's no error status register we could report it in.
345+
* Log and ignore.
346+
*/
347+
qemu_log_mask(LOG_GUEST_ERROR,
348+
"smc91c111: attempt to queue invalid packet %d\n",
349+
packet);
350+
return;
351+
}
290352
if (s->tx_fifo_len == NUM_PACKETS)
291353
return;
292354
s->tx_fifo[s->tx_fifo_len++] = packet;
@@ -318,6 +380,49 @@ static void smc91c111_reset(DeviceState *dev)
318380
#define SET_LOW(name, val) s->name = (s->name & 0xff00) | val
319381
#define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8)
320382

383+
/*
384+
* The pointer register's pointer is an 11 bit value (so it exactly
385+
* indexes a 2048-byte data frame). Add the specified offset to it,
386+
* wrapping around at the 2048 byte mark, and return the resulting
387+
* wrapped value. There are flag bits in the top part of the register,
388+
* but we can ignore them here as the mask will mask them out.
389+
*/
390+
static int ptr_reg_add(smc91c111_state *s, int offset)
391+
{
392+
return (s->ptr + offset) & R_PTR_PTR_MASK;
393+
}
394+
395+
/*
396+
* For an access to the Data Register at @offset, return the
397+
* required offset into the packet's data frame. This will
398+
* perform the pointer register autoincrement if required, and
399+
* guarantees to return an in-bounds offset.
400+
*/
401+
static int data_reg_ptr(smc91c111_state *s, int offset)
402+
{
403+
int p;
404+
405+
if (s->ptr & R_PTR_AUTOINCR_MASK) {
406+
/*
407+
* Autoincrement: use the current pointer value, and
408+
* increment the pointer register's pointer field.
409+
*/
410+
p = FIELD_EX32(s->ptr, PTR, PTR);
411+
s->ptr = FIELD_DP32(s->ptr, PTR, PTR, ptr_reg_add(s, 1));
412+
} else {
413+
/*
414+
* No autoincrement: register offset determines which
415+
* byte we're addressing. Setting the pointer to the top
416+
* of the data buffer and then using the pointer wrapping
417+
* to read the bottom byte of the buffer is not something
418+
* sensible guest software will do, but the datasheet
419+
* doesn't say what the behaviour is, so we don't forbid it.
420+
*/
421+
p = ptr_reg_add(s, offset & 3);
422+
}
423+
return p;
424+
}
425+
321426
static void smc91c111_writeb(void *opaque, hwaddr offset,
322427
uint32_t value)
323428
{
@@ -457,12 +562,14 @@ static void smc91c111_writeb(void *opaque, hwaddr offset,
457562
n = s->rx_fifo[0];
458563
else
459564
n = s->packet_num;
460-
p = s->ptr & 0x07ff;
461-
if (s->ptr & 0x4000) {
462-
s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff);
463-
} else {
464-
p += (offset & 3);
565+
if (!packetnum_valid(n)) {
566+
/* Datasheet doesn't document what to do here */
567+
qemu_log_mask(LOG_GUEST_ERROR,
568+
"smc91c111: attempt to write data to invalid packet %d\n",
569+
n);
570+
return;
465571
}
572+
p = data_reg_ptr(s, offset);
466573
s->data[n][p] = value;
467574
}
468575
return;
@@ -605,12 +712,14 @@ static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
605712
n = s->rx_fifo[0];
606713
else
607714
n = s->packet_num;
608-
p = s->ptr & 0x07ff;
609-
if (s->ptr & 0x4000) {
610-
s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x07ff);
611-
} else {
612-
p += (offset & 3);
715+
if (!packetnum_valid(n)) {
716+
/* Datasheet doesn't document what to do here */
717+
qemu_log_mask(LOG_GUEST_ERROR,
718+
"smc91c111: attempt to read data from invalid packet %d\n",
719+
n);
720+
return 0;
613721
}
722+
p = data_reg_ptr(s, offset);
614723
return s->data[n][p];
615724
}
616725
case 12: /* Interrupt status. */
@@ -706,13 +815,16 @@ static ssize_t smc91c111_receive(NetClientState *nc, const uint8_t *buf, size_t
706815
if (crc)
707816
packetsize += 4;
708817
/* TODO: Flag overrun and receive errors. */
709-
if (packetsize > 2048)
818+
if (packetsize > MAX_PACKET_SIZE) {
710819
return -1;
820+
}
711821
packetnum = smc91c111_allocate_packet(s);
712822
if (packetnum == 0x80)
713823
return -1;
714824
s->rx_fifo[s->rx_fifo_len++] = packetnum;
715825

826+
/* allocate_packet() will not hand us back an invalid packet number */
827+
assert(packetnum_valid(packetnum));
716828
p = &s->data[packetnum][0];
717829
/* ??? Multicast packets? */
718830
status = 0;

0 commit comments

Comments
 (0)