* [PULL 01/32] hw/misc/edu: restrict dma access to dma buffer
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
@ 2026-07-07 13:11 ` Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 02/32] hw/display/ati: reset host_data.next in write handler after flush Philippe Mathieu-Daudé
` (32 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:11 UTC (permalink / raw)
To: qemu-devel
From: Torin Carey <torin@tcarey.uk>
The EDU device doesn't enforce any bound checks on the addresses provided,
allowing users of the device to perform arbitrary reads and writes to QEMU's
address space.
Signed-off-by: Torin Carey <torin@tcarey.uk>
Cc: qemu-stable@nongnu.org
Fixes: 7b608e5d6c1 ("hw: misc: edu: use qemu_log_mask instead of hw_error")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3852
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-ID: <aQtAotYvzFY0Vpft@tcarey.uk>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/misc/edu.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/hw/misc/edu.c b/hw/misc/edu.c
index cece633e113..a4b01269e8b 100644
--- a/hw/misc/edu.c
+++ b/hw/misc/edu.c
@@ -103,7 +103,7 @@ static void edu_lower_irq(EduState *edu, uint32_t val)
}
}
-static void edu_check_range(uint64_t xfer_start, uint64_t xfer_size,
+static bool edu_check_range(uint64_t xfer_start, uint64_t xfer_size,
uint64_t dma_start, uint64_t dma_size)
{
uint64_t xfer_end = xfer_start + xfer_size;
@@ -115,13 +115,15 @@ static void edu_check_range(uint64_t xfer_start, uint64_t xfer_size,
*/
if (dma_end >= dma_start && xfer_end >= xfer_start &&
xfer_start >= dma_start && xfer_end <= dma_end) {
- return;
+ return true;
}
qemu_log_mask(LOG_GUEST_ERROR,
"EDU: DMA range 0x%016"PRIx64"-0x%016"PRIx64
" out of bounds (0x%016"PRIx64"-0x%016"PRIx64")!",
xfer_start, xfer_end - 1, dma_start, dma_end - 1);
+
+ return false;
}
static dma_addr_t edu_clamp_addr(const EduState *edu, dma_addr_t addr)
@@ -148,16 +150,18 @@ static void edu_dma_timer(void *opaque)
if (EDU_DMA_DIR(edu->dma.cmd) == EDU_DMA_FROM_PCI) {
uint64_t dst = edu->dma.dst;
- edu_check_range(dst, edu->dma.cnt, DMA_START, DMA_SIZE);
- dst -= DMA_START;
- pci_dma_read(&edu->pdev, edu_clamp_addr(edu, edu->dma.src),
- edu->dma_buf + dst, edu->dma.cnt);
+ if (edu_check_range(dst, edu->dma.cnt, DMA_START, DMA_SIZE)) {
+ dst -= DMA_START;
+ pci_dma_read(&edu->pdev, edu_clamp_addr(edu, edu->dma.src),
+ edu->dma_buf + dst, edu->dma.cnt);
+ }
} else {
uint64_t src = edu->dma.src;
- edu_check_range(src, edu->dma.cnt, DMA_START, DMA_SIZE);
- src -= DMA_START;
- pci_dma_write(&edu->pdev, edu_clamp_addr(edu, edu->dma.dst),
- edu->dma_buf + src, edu->dma.cnt);
+ if (edu_check_range(src, edu->dma.cnt, DMA_START, DMA_SIZE)) {
+ src -= DMA_START;
+ pci_dma_write(&edu->pdev, edu_clamp_addr(edu, edu->dma.dst),
+ edu->dma_buf + src, edu->dma.cnt);
+ }
}
edu->dma.cmd &= ~EDU_DMA_RUN;
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 02/32] hw/display/ati: reset host_data.next in write handler after flush
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 01/32] hw/misc/edu: restrict dma access to dma buffer Philippe Mathieu-Daudé
@ 2026-07-07 13:11 ` Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 03/32] hw/display/ati: guard against zero bpp in ati_host_data_flush Philippe Mathieu-Daudé
` (31 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:11 UTC (permalink / raw)
To: qemu-devel
From: Junjie Cao <junjie.cao@intel.com>
ati_host_data_flush() resets host_data.next only on its success path.
When it returns early (unsupported bpp, direction, src_source, or
src_datatype), next remains stale at >= 4. The next HOST_DATA write
then stores a guest-controlled dword at acc[4+], overflowing the
4-element accumulator array.
Fix this by resetting next unconditionally in the write handler after
calling ati_host_data_flush() or ati_host_data_finish(), and removing
the reset from inside ati_host_data_flush(). This ensures the write
handler owns the full lifecycle of the accumulator index regardless of
flush success or failure.
Cc: qemu-stable@nongnu.org
Reported-by: Feifan Qian <bea1e@proton.me>
Resolves: https://lore.kernel.org/qemu-devel/Czyl6yVfL6sHl_o1kRk8N_LpwXMMRVhO9vgz1qCVJFagn9D4nHSKuiux39iOLty0Q3acxQq_FeovPhTQvSKus2htwjI9lTajLZmqovr0Wxs=@proton.me/
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Chad Jablonski <chad@jablonski.xyz>
Message-ID: <20260519023937.439077-2-junjie.cao@intel.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/display/ati.c | 2 ++
hw/display/ati_2d.c | 1 -
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/display/ati.c b/hw/display/ati.c
index d77589df67a..db7e08a462a 100644
--- a/hw/display/ati.c
+++ b/hw/display/ati.c
@@ -1034,8 +1034,10 @@ static void ati_mm_write(void *opaque, hwaddr addr,
s->host_data.acc[s->host_data.next++] = data;
if (addr == HOST_DATA_LAST) {
ati_host_data_finish(s);
+ s->host_data.next = 0;
} else if (s->host_data.next >= 4) {
ati_host_data_flush(s);
+ s->host_data.next = 0;
}
break;
default:
diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
index 48498677c7e..8ef82bb87fd 100644
--- a/hw/display/ati_2d.c
+++ b/hw/display/ati_2d.c
@@ -452,7 +452,6 @@ bool ati_host_data_flush(ATIVGAState *s)
}
/* Track state of the overall blit for use by the next flush */
- s->host_data.next = 0;
s->host_data.row = row;
s->host_data.col = col;
if (s->host_data.row >= ctx.dst.height) {
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 03/32] hw/display/ati: guard against zero bpp in ati_host_data_flush
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 01/32] hw/misc/edu: restrict dma access to dma buffer Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 02/32] hw/display/ati: reset host_data.next in write handler after flush Philippe Mathieu-Daudé
@ 2026-07-07 13:11 ` Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 04/32] hw/ide/ahci: cancel in-flight buffered reads on command engine restart Philippe Mathieu-Daudé
` (30 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:11 UTC (permalink / raw)
To: qemu-devel
From: Junjie Cao <junjie.cao@intel.com>
ati_bpp_from_datatype() returns 0 for unrecognized dp_datatype nibble
values (0, 1, or >= 7). ati_host_data_flush() only guards against the
bpp == 24 case but not bpp == 0, leading to:
1. Division by zero at "pix_count /= ctx.bpp" (SIGFPE) when
src_datatype is SRC_COLOR.
2. g_assert_not_reached() in stn_he_p() when bypp (= bpp/8 = 0)
hits the default case of the size switch.
Both are guest-triggerable via MMIO writes to the dp_datatype register
while a HOST_DATA blit is active.
Add an explicit bpp == 0 check with LOG_GUEST_ERROR before proceeding
with the blit, consistent with the existing check in ati_2d_do_blt().
Cc: qemu-stable@nongnu.org
Reported-by: Feifan Qian <bea1e@proton.me>
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Chad Jablonski <chad@jablonski.xyz>
Message-ID: <20260519023937.439077-3-junjie.cao@intel.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/display/ati_2d.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
index 8ef82bb87fd..22dd811bd85 100644
--- a/hw/display/ati_2d.c
+++ b/hw/display/ati_2d.c
@@ -377,6 +377,11 @@ bool ati_host_data_flush(ATIVGAState *s)
setup_2d_blt_ctx(s, &ctx);
+ if (!ctx.bpp) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "host_data_blt: invalid bpp from datatype\n");
+ return false;
+ }
if (ctx.bpp == 24) {
qemu_log_mask(LOG_UNIMP,
"host_data_blt: unsupported in 24 bits mode\n");
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 04/32] hw/ide/ahci: cancel in-flight buffered reads on command engine restart
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2026-07-07 13:11 ` [PULL 03/32] hw/display/ati: guard against zero bpp in ati_host_data_flush Philippe Mathieu-Daudé
@ 2026-07-07 13:11 ` Philippe Mathieu-Daudé
2026-07-08 8:28 ` Michael Tokarev
2026-07-07 13:11 ` [PULL 05/32] hw/display/ati: Include vga state in the blit context Philippe Mathieu-Daudé
` (29 subsequent siblings)
33 siblings, 1 reply; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:11 UTC (permalink / raw)
To: qemu-devel
From: "Denis V. Lunev" <den@openvz.org>
ATAPI CD reads are issued through ide_buffered_readv()
(cd_read_sector() and ide_atapi_cmd_read_dma_cb() in hw/ide/atapi.c).
The PIO path discards the returned aiocb; the DMA path stores it in
s->bus->dma->aiocb.
A guest can stop and restart a port's command engine
(PxCMD.ST 1 -> 0 -> 1) while such a read is still in flight. Stopping
the engine unmaps the command list (ahci_unmap_clb_address()) and
restarting it re-maps the list and clears AHCIDevice.cur_cmd to NULL,
but nothing tears down the outstanding read. This path does not run
ide_reset(), so the drive's transfer state is preserved and the read
still completes. Its callbacks then dereference the stale or NULL
cur_cmd in the AHCI transfer helpers:
PIO: cd_read_sector_cb() -> ide_atapi_cmd_reply_end() ->
ide_transfer_start_norecurse() -> ahci_pio_transfer()
DMA: ide_atapi_cmd_read_dma_cb() -> ahci_dma_rw_buf() ->
ahci_populate_sglist()
Both crash with a NULL cur_cmd; the PIO variant has been seen in the
field.
Cancel the outstanding I/O when the command list is unmapped, reusing
ide_cancel_dma_sync() as the ATAPI DEVICE RESET command does. It runs
the completion callback with -ECANCELED (which tears down
s->bus->dma->aiocb for the DMA case) and orphans the buffered request,
so the eventual asynchronous completion is a no-op. Merely setting the
orphaned flag is not enough: it would leave s->bus->dma->aiocb pointing
at a freed aiocb that a later reset would cancel.
Fixes: 1d8c11d63154 ("ide: add support for IDEBufferedRequest")
Signed-off-by: Denis V. Lunev <den@openvz.org>
Message-ID: <20260619112158.304782-2-den@openvz.org>
[PMD: Use ide_bus_active_if()]
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/ide/ahci.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index c2b4432b947..749f0efa1d0 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -740,6 +740,9 @@ static bool ahci_map_clb_address(AHCIDevice *ad)
static void ahci_unmap_clb_address(AHCIDevice *ad)
{
+ /* Cancel in-flight reads that would complete against a cleared cur_cmd. */
+ ide_cancel_dma_sync(ide_bus_active_if(&ad->port));
+
if (ad->lst == NULL) {
trace_ahci_unmap_clb_address_null(ad->hba, ad->port_no);
return;
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* Re: [PULL 04/32] hw/ide/ahci: cancel in-flight buffered reads on command engine restart
2026-07-07 13:11 ` [PULL 04/32] hw/ide/ahci: cancel in-flight buffered reads on command engine restart Philippe Mathieu-Daudé
@ 2026-07-08 8:28 ` Michael Tokarev
0 siblings, 0 replies; 36+ messages in thread
From: Michael Tokarev @ 2026-07-08 8:28 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel, Denis V. Lunev; +Cc: qemu-stable
On 07.07.2026 16:11, Philippe Mathieu-Daudé wrote:
> From: "Denis V. Lunev" <den@openvz.org>
>
> ATAPI CD reads are issued through ide_buffered_readv()
> (cd_read_sector() and ide_atapi_cmd_read_dma_cb() in hw/ide/atapi.c).
> The PIO path discards the returned aiocb; the DMA path stores it in
> s->bus->dma->aiocb.
>
> A guest can stop and restart a port's command engine
> (PxCMD.ST 1 -> 0 -> 1) while such a read is still in flight. Stopping
> the engine unmaps the command list (ahci_unmap_clb_address()) and
> restarting it re-maps the list and clears AHCIDevice.cur_cmd to NULL,
> but nothing tears down the outstanding read. This path does not run
> ide_reset(), so the drive's transfer state is preserved and the read
> still completes. Its callbacks then dereference the stale or NULL
> cur_cmd in the AHCI transfer helpers:
>
> PIO: cd_read_sector_cb() -> ide_atapi_cmd_reply_end() ->
> ide_transfer_start_norecurse() -> ahci_pio_transfer()
>
> DMA: ide_atapi_cmd_read_dma_cb() -> ahci_dma_rw_buf() ->
> ahci_populate_sglist()
>
> Both crash with a NULL cur_cmd; the PIO variant has been seen in the
> field.
>
> Cancel the outstanding I/O when the command list is unmapped, reusing
> ide_cancel_dma_sync() as the ATAPI DEVICE RESET command does. It runs
> the completion callback with -ECANCELED (which tears down
> s->bus->dma->aiocb for the DMA case) and orphans the buffered request,
> so the eventual asynchronous completion is a no-op. Merely setting the
> orphaned flag is not enough: it would leave s->bus->dma->aiocb pointing
> at a freed aiocb that a later reset would cancel.
>
> Fixes: 1d8c11d63154 ("ide: add support for IDEBufferedRequest")
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> Message-ID: <20260619112158.304782-2-den@openvz.org>
> [PMD: Use ide_bus_active_if()]
> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
I'm picking this (and the test) up for the currently active stable qemu
series. Please let me know if I shouldn't.
Thanks,
/mjt
> diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
> index c2b4432b947..749f0efa1d0 100644
> --- a/hw/ide/ahci.c
> +++ b/hw/ide/ahci.c
> @@ -740,6 +740,9 @@ static bool ahci_map_clb_address(AHCIDevice *ad)
>
> static void ahci_unmap_clb_address(AHCIDevice *ad)
> {
> + /* Cancel in-flight reads that would complete against a cleared cur_cmd. */
> + ide_cancel_dma_sync(ide_bus_active_if(&ad->port));
> +
> if (ad->lst == NULL) {
> trace_ahci_unmap_clb_address_null(ad->hba, ad->port_no);
> return;
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PULL 05/32] hw/display/ati: Include vga state in the blit context
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2026-07-07 13:11 ` [PULL 04/32] hw/ide/ahci: cancel in-flight buffered reads on command engine restart Philippe Mathieu-Daudé
@ 2026-07-07 13:11 ` Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 06/32] util/filemonitor-inotify: Use QEMU_LOCK_GUARD() Philippe Mathieu-Daudé
` (28 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:11 UTC (permalink / raw)
To: qemu-devel
From: BALATON Zoltan <balaton@eik.bme.hu>
The vga state is needed by several functions using the blit context so
just include it in the context instead of passing it separately.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Chad Jablonski <chad@jablonski.xyz>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260619140408.6CF98596948@zero.eik.bme.hu>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/display/ati_2d.c | 38 ++++++++++++++++++--------------------
1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
index 22dd811bd85..7a4a115aee2 100644
--- a/hw/display/ati_2d.c
+++ b/hw/display/ati_2d.c
@@ -45,6 +45,7 @@ static int ati_bpp_from_datatype(const ATIVGAState *s)
}
typedef struct {
+ VGACommonState *vga;
int bpp;
uint32_t rop3;
bool host_data_active;
@@ -52,8 +53,6 @@ typedef struct {
bool top_to_bottom;
bool need_swap;
uint32_t frgd_clr;
- const uint8_t *palette;
- const uint8_t *vram_end;
QemuRect scissor;
QemuRect dst;
@@ -66,8 +65,9 @@ typedef struct {
const uint8_t *src_bits;
} ATI2DCtx;
-static void ati_set_dirty(VGACommonState *vga, const ATI2DCtx *ctx)
+static void ati_set_dirty(const ATI2DCtx *ctx)
{
+ VGACommonState *vga = ctx->vga;
DisplaySurface *ds = qemu_console_surface(vga->con);
unsigned int bypp = ctx->bpp / 8;
hwaddr dirty_start = ctx->dst_offset + ctx->dst.x * bypp +
@@ -94,8 +94,9 @@ static void ati_set_dirty(VGACommonState *vga, const ATI2DCtx *ctx)
}
}
-static void setup_2d_blt_ctx(const ATIVGAState *s, ATI2DCtx *ctx)
+static void setup_2d_blt_ctx(ATIVGAState *s, ATI2DCtx *ctx)
{
+ ctx->vga = &s->vga;
ctx->bpp = ati_bpp_from_datatype(s);
ctx->rop3 = s->regs.dp_mix & GMC_ROP3_MASK;
ctx->host_data_active = s->host_data.active;
@@ -103,9 +104,7 @@ static void setup_2d_blt_ctx(const ATIVGAState *s, ATI2DCtx *ctx)
ctx->top_to_bottom = s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM;
ctx->need_swap = (HOST_BIG_ENDIAN != s->vga.big_endian_fb);
ctx->frgd_clr = s->regs.dp_brush_frgd_clr;
- ctx->palette = s->vga.palette;
ctx->dst_offset = s->regs.dst_offset;
- ctx->vram_end = s->vga.vram_ptr + s->vga.vram_size;
ctx->scissor.width = s->regs.sc_right - s->regs.sc_left + 1;
ctx->scissor.height = s->regs.sc_bottom - s->regs.sc_top + 1;
@@ -153,10 +152,11 @@ static uint32_t make_filler(int bpp, uint32_t color)
return color;
}
-static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_pixman)
+static bool ati_2d_do_blt(const ATI2DCtx *ctx, uint8_t use_pixman)
{
QemuRect vis_src, vis_dst;
unsigned int x, y, i, j, bypp = ctx->bpp / 8;
+ const uint8_t *vram_end = ctx->vga->vram_ptr + ctx->vga->vram_size;
if (!ctx->bpp) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n");
@@ -167,9 +167,8 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_pixman)
return false;
}
if (ctx->dst.x > 0x3fff || ctx->dst.y > 0x3fff ||
- ctx->dst_bits >= ctx->vram_end - bypp ||
- ctx->dst_bits + ctx->dst.x * bypp + (ctx->dst.y + ctx->dst.height) *
- ctx->dst_stride >= ctx->vram_end - bypp) {
+ ctx->dst_bits >= vram_end - bypp || ctx->dst_bits + ctx->dst.x * bypp +
+ (ctx->dst.y + ctx->dst.height) * ctx->dst_stride >= vram_end - bypp) {
qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
return false;
}
@@ -206,9 +205,9 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_pixman)
}
if (!ctx->host_data_active &&
(vis_src.x > 0x3fff || vis_src.y > 0x3fff ||
- ctx->src_bits >= ctx->vram_end - bypp ||
+ ctx->src_bits >= vram_end - bypp ||
ctx->src_bits + vis_src.x * bypp + (vis_src.y + vis_dst.height) *
- ctx->src_stride >= ctx->vram_end - bypp)) {
+ ctx->src_stride >= vram_end - bypp)) {
qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
return false;
}
@@ -275,6 +274,7 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_pixman)
case ROP3_BLACKNESS:
case ROP3_WHITENESS:
{
+ const uint8_t *palette = ctx->vga->palette;
uint32_t filler = 0;
if (ctx->bpp == 24) {
@@ -286,14 +286,12 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_pixman)
filler = make_filler(ctx->bpp, ctx->frgd_clr);
break;
case ROP3_BLACKNESS:
- filler = 0xffUL << 24 | rgb_to_pixel32(ctx->palette[0],
- ctx->palette[1],
- ctx->palette[2]);
+ filler = 0xffUL << 24 | rgb_to_pixel32(palette[0], palette[1],
+ palette[2]);
break;
case ROP3_WHITENESS:
- filler = 0xffUL << 24 | rgb_to_pixel32(ctx->palette[3],
- ctx->palette[4],
- ctx->palette[5]);
+ filler = 0xffUL << 24 | rgb_to_pixel32(palette[3], palette[4],
+ palette[5]);
break;
}
DPRINTF("pixman_fill(%p, %ld, %d, %d, %d, %d, %d, %x)\n",
@@ -347,7 +345,7 @@ void ati_2d_blt(ATIVGAState *s)
}
setup_2d_blt_ctx(s, &ctx);
if (ati_2d_do_blt(&ctx, s->use_pixman)) {
- ati_set_dirty(&s->vga, &ctx);
+ ati_set_dirty(&ctx);
}
}
@@ -446,7 +444,7 @@ bool ati_host_data_flush(ATIVGAState *s)
DPRINTF("blt %dpx span @ row: %d, col: %d to dst (%d,%d)\n",
pix_in_scanline, row, col, chunk.dst.x, chunk.dst.y);
if (ati_2d_do_blt(&chunk, s->use_pixman)) {
- ati_set_dirty(&s->vga, &chunk);
+ ati_set_dirty(&chunk);
}
idx += pix_in_scanline;
col += pix_in_scanline;
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 06/32] util/filemonitor-inotify: Use QEMU_LOCK_GUARD()
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (4 preceding siblings ...)
2026-07-07 13:11 ` [PULL 05/32] hw/display/ati: Include vga state in the blit context Philippe Mathieu-Daudé
@ 2026-07-07 13:11 ` Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 07/32] hw/gpio/pca9552: fix off-by-one in QOM led index validation Philippe Mathieu-Daudé
` (27 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:11 UTC (permalink / raw)
To: qemu-devel
From: Evgeny Kolmakov <randomjack94dev@gmail.com>
Replace manual qemu_mutex_(un)lock() calls with
QEMU_LOCK_GUARD() to remove 'goto cleanup' code
Signed-off-by: Evgeny Kolmakov <randomjack94dev@gmail.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20260622073647.3721-1-randomjack94dev@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
util/filemonitor-inotify.c | 28 ++++++++--------------------
1 file changed, 8 insertions(+), 20 deletions(-)
diff --git a/util/filemonitor-inotify.c b/util/filemonitor-inotify.c
index 7352b9fe53e..fe2057f820c 100644
--- a/util/filemonitor-inotify.c
+++ b/util/filemonitor-inotify.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qemu/filemonitor.h"
#include "qemu/main-loop.h"
+#include "qemu/lockable.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "trace.h"
@@ -59,10 +60,9 @@ static void qemu_file_monitor_watch(void *arg)
int used = 0;
int len;
- qemu_mutex_lock(&mon->lock);
+ QEMU_LOCK_GUARD(&mon->lock);
if (mon->fd == -1) {
- qemu_mutex_unlock(&mon->lock);
return;
}
@@ -72,11 +72,10 @@ static void qemu_file_monitor_watch(void *arg)
if (errno != EAGAIN) {
error_report("Failure monitoring inotify FD '%s',"
"disabling events", strerror(errno));
- goto cleanup;
}
/* no more events right now */
- goto cleanup;
+ return;
}
/* Loop over all events in the buffer */
@@ -151,9 +150,6 @@ static void qemu_file_monitor_watch(void *arg)
}
}
}
-
- cleanup:
- qemu_mutex_unlock(&mon->lock);
}
@@ -257,9 +253,8 @@ qemu_file_monitor_add_watch(QFileMonitor *mon,
{
QFileMonitorDir *dir;
QFileMonitorWatch watch;
- int64_t ret = -1;
- qemu_mutex_lock(&mon->lock);
+ QEMU_LOCK_GUARD(&mon->lock);
dir = g_hash_table_lookup(mon->dirs, dirpath);
if (!dir) {
int rv = inotify_add_watch(mon->fd, dirpath,
@@ -268,7 +263,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon,
if (rv < 0) {
error_setg_errno(errp, errno, "Unable to watch '%s'", dirpath);
- goto cleanup;
+ return -1;
}
trace_qemu_file_monitor_enable_watch(mon, dirpath, rv);
@@ -297,11 +292,7 @@ qemu_file_monitor_add_watch(QFileMonitor *mon,
filename ? filename : "<none>",
cb, opaque, watch.id);
- ret = watch.id;
-
- cleanup:
- qemu_mutex_unlock(&mon->lock);
- return ret;
+ return watch.id;
}
@@ -312,13 +303,13 @@ void qemu_file_monitor_remove_watch(QFileMonitor *mon,
QFileMonitorDir *dir;
gsize i;
- qemu_mutex_lock(&mon->lock);
+ QEMU_LOCK_GUARD(&mon->lock);
trace_qemu_file_monitor_remove_watch(mon, dirpath, id);
dir = g_hash_table_lookup(mon->dirs, dirpath);
if (!dir) {
- goto cleanup;
+ return;
}
for (i = 0; i < dir->watches->len; i++) {
@@ -342,7 +333,4 @@ void qemu_file_monitor_remove_watch(QFileMonitor *mon,
qemu_set_fd_handler(mon->fd, NULL, NULL, NULL);
}
}
-
- cleanup:
- qemu_mutex_unlock(&mon->lock);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 07/32] hw/gpio/pca9552: fix off-by-one in QOM led index validation
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (5 preceding siblings ...)
2026-07-07 13:11 ` [PULL 06/32] util/filemonitor-inotify: Use QEMU_LOCK_GUARD() Philippe Mathieu-Daudé
@ 2026-07-07 13:11 ` Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 08/32] ebpf: fix swapped toeplitz/indirection args in set_data trace Philippe Mathieu-Daudé
` (26 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:11 UTC (permalink / raw)
To: qemu-devel
From: yujun <yujun@kylinos.cn>
pca955x_get_led() and pca955x_set_led() accept led indices equal to
pin_count, but valid indices are 0..pin_count-1. For a 16-pin device,
led16 passes the current check and then accesses an LS register past
max_reg.
Use the same >= pin_count bounds check as pca9554_set_pin() and the
gpio input handler assert in this file.
Fixes: a90d8f84674 ("misc/pca9552: Add qom set and get")
Signed-off-by: yujun <yujun@kylinos.cn>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Glenn Miles <milesg@linux.ibm.com>
Message-ID: <20260629074133.187549-1-yujun@kylinos.cn>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/gpio/pca9552.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/hw/gpio/pca9552.c b/hw/gpio/pca9552.c
index 472d8ad9571..b13ac9fd9ce 100644
--- a/hw/gpio/pca9552.c
+++ b/hw/gpio/pca9552.c
@@ -311,8 +311,8 @@ static void pca955x_get_led(Object *obj, Visitor *v, const char *name,
error_setg(errp, "%s: error reading %s", __func__, name);
return;
}
- if (led < 0 || led > k->pin_count) {
- error_setg(errp, "%s invalid led %s", __func__, name);
+ if (led < 0 || led >= k->pin_count) {
+ error_setg(errp, "%s: invalid led %s", __func__, name);
return;
}
/*
@@ -352,8 +352,8 @@ static void pca955x_set_led(Object *obj, Visitor *v, const char *name,
error_setg(errp, "%s: error reading %s", __func__, name);
return;
}
- if (led < 0 || led > k->pin_count) {
- error_setg(errp, "%s invalid led %s", __func__, name);
+ if (led < 0 || led >= k->pin_count) {
+ error_setg(errp, "%s: invalid led %s", __func__, name);
return;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 08/32] ebpf: fix swapped toeplitz/indirection args in set_data trace
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (6 preceding siblings ...)
2026-07-07 13:11 ` [PULL 07/32] hw/gpio/pca9552: fix off-by-one in QOM led index validation Philippe Mathieu-Daudé
@ 2026-07-07 13:11 ` Philippe Mathieu-Daudé
2026-07-07 13:11 ` [PULL 09/32] crypto/x509-utils: fix gnutls error code in crt_init failure path Philippe Mathieu-Daudé
` (25 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:11 UTC (permalink / raw)
To: qemu-devel
From: yujun <yujun@kylinos.cn>
trace_ebpf_rss_set_data() passes its third and fourth arguments to
the toeplitz-ptr and indirection-ptr fields defined in trace-events.
ebpf_rss_set_all() passed indirections_table and toeplitz_key in the
opposite order, so tracing mislabeled the two pointers.
Match the argument order already used by trace_ebpf_rss_mmap().
Fixes: f5cae19d10 ("ebpf: improve trace event coverage to all key operations")
Signed-off-by: yujun <yujun@kylinos.cn>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260629090116.266561-1-yujun@kylinos.cn>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
| 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--git a/ebpf/ebpf_rss.c b/ebpf/ebpf_rss.c
index 926392b3c58..6650d0daef0 100644
--- a/ebpf/ebpf_rss.c
+++ b/ebpf/ebpf_rss.c
@@ -270,7 +270,7 @@ bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config,
ebpf_rss_set_toepliz_key(ctx, toeplitz_key);
- trace_ebpf_rss_set_data(ctx, config, indirections_table, toeplitz_key);
+ trace_ebpf_rss_set_data(ctx, config, toeplitz_key, indirections_table);
return true;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 09/32] crypto/x509-utils: fix gnutls error code in crt_init failure path
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (7 preceding siblings ...)
2026-07-07 13:11 ` [PULL 08/32] ebpf: fix swapped toeplitz/indirection args in set_data trace Philippe Mathieu-Daudé
@ 2026-07-07 13:11 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 10/32] hw/dma/i8257: Return zeroes for read_memory in verify mode Philippe Mathieu-Daudé
` (24 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:11 UTC (permalink / raw)
To: qemu-devel
From: yujun <yujun@kylinos.cn>
qcrypto_get_x509_cert_fingerprint() reports gnutls_strerror(ret) when
gnutls_x509_crt_init() fails, but ret is still the initial value -1.
Store the gnutls return code before formatting the error, matching
other gnutls call sites in the tree.
Fixes: 2183ab6251 ("crypto/x509-utils: Check for error from gnutls_x509_crt_init()")
Signed-off-by: yujun <yujun@kylinos.cn>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20260629111026.281185-1-yujun@kylinos.cn>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
crypto/x509-utils.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/crypto/x509-utils.c b/crypto/x509-utils.c
index 39bb6d4d8c3..1843488bca3 100644
--- a/crypto/x509-utils.c
+++ b/crypto/x509-utils.c
@@ -46,7 +46,8 @@ int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
return -1;
}
- if (gnutls_x509_crt_init(&crt) < 0) {
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0) {
error_setg(errp, "Unable to initialize certificate: %s",
gnutls_strerror(ret));
return -1;
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 10/32] hw/dma/i8257: Return zeroes for read_memory in verify mode
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (8 preceding siblings ...)
2026-07-07 13:11 ` [PULL 09/32] crypto/x509-utils: fix gnutls error code in crt_init failure path Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 11/32] hw/net: fix e1000e/igb ip_len inflation by Ethernet minimum-frame padding Philippe Mathieu-Daudé
` (23 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Peter Maydell <peter.maydell@linaro.org>
The i8257 DMA controller has a "verify" mode, which the datasheet
describes like this:
> DMA verify, which does not actually involve the transfer of data.
> When an 8257 channel is in the DMA verify mode, it will respond the
> same as described for transfer operations, except that no memory or
> I/O read/write control signals will be generated. When an 8257
> channel is in the DMA verify mode, it will respond the same as
> described for transfer operations, except that no memory or I/O read
> /write control signals will be generated, thus preventing the
> transfer of data. The 8257, however, will gain control of the system
> bus and will acknowledge the peripheral's DMA request for each DMA
> cycle. The perihperal can use these acknowledge signals to enable an
> internal access of each byte of a data block in order to execute some
> verification procedure, such as the accumulation of a CRC check word.
In practice, for QEMU's purposes the only real user of this is the
floppy controller, which can be made to perform a "read data from
floppy disk and check the checksum" by telling the fdc to do a read
and the DMA controller to do a verify. This causes the fdc to do all
the usual read actions including the checksum, but the data is never
written to memory. However, it is possible for a guest doing
something silly to program the DMA controller to do a verify
operation for a device that wants to read from memory. Currently we
simply return early from i8257_dma_read_memory() without writing to
the buffer. None of the callers (the GUS, sb16 and cs4231a sound
cards, plus the fdc) expect this, so they will take the uninitialized
data as if it were from the guest. This can cause us to leak host
data off the stack into the guest.
Make i8257_dma_read_memory() fill the buffer with zeroes rather
than leaving it untouched for a verify operation.
Cc: qemu-stable@nongnu.org
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3487
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20260629140128.1900095-1-peter.maydell@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/dma/i8257.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c
index 7d7e5434275..57715498895 100644
--- a/hw/dma/i8257.c
+++ b/hw/dma/i8257.c
@@ -408,6 +408,19 @@ static int i8257_dma_read_memory(IsaDma *obj, int nchan, void *buf, int pos,
hwaddr addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
if (i8257_is_verify_transfer(r)) {
+ /*
+ * If the device is expecting this verify operation then
+ * it won't care about the nonexistent data. But if it
+ * is expecting a real read (i.e. the guest has misprogrammed
+ * the DMA controller and the device) it's going to try to do
+ * something with the buffer contents. Give it zeroes.
+ * (It's not clear whether this is exactly what happens if
+ * you do this on real hardware. In practice no device QEMU
+ * emulates has a use for verify on a memory-read transfer,
+ * so we don't care beyond avoiding the guest being able to
+ * trigger the caller reading uninitialized data.)
+ */
+ memset(buf, 0, len);
return len;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 11/32] hw/net: fix e1000e/igb ip_len inflation by Ethernet minimum-frame padding
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (9 preceding siblings ...)
2026-07-07 13:12 ` [PULL 10/32] hw/dma/i8257: Return zeroes for read_memory in verify mode Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 12/32] hw/scsi/mptsas: Reset doorbell state on reset Philippe Mathieu-Daudé
` (22 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Sanjeeva Yerrapureddy <y.sanjeevreddy@gmail.com>
When a guest transmits a short Ethernet frame, iov_size() returns the
padded wire length including any bytes added to reach the Ethernet
minimum frame size of 60 bytes. net_tx_pkt_rebuild_payload() uses
this inflated size as payload_len. net_tx_pkt_update_ip_hdr_checksum()
then overwrites the IPv4 Total Length field with payload_len +
l3_hdr_len, inflating it by the padding. The receiver interprets
Ethernet padding as IP payload, producing a malformed packet.
Fix by removing the ip_len write from net_tx_pkt_update_ip_hdr_checksum()
so it only recomputes the checksum, and moving the ip_len assignment
into net_tx_pkt_update_ip_checksums() where it is only performed for
TSO (where ip_len must be derived from payload_len since the guest sets
ip_len=0 per Intel 82574 datasheet §7.3.4 for super-packets the host
will segment).
Both e1000e and igb already call net_tx_pkt_update_ip_hdr_checksum()
from their IXSM paths, so both are corrected by this single common-
layer change.
Signed-off-by: Sanjeeva Yerrapureddy <y.sanjeevreddy@gmail.com>
Reivewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260629-net-tx-pkt-ip-length-padding-v5-1-16760e30252e@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/net/net_tx_pkt.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index 903238dca24..b134348fe80 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -93,9 +93,6 @@ void net_tx_pkt_update_ip_hdr_checksum(struct NetTxPkt *pkt)
uint16_t csum;
assert(pkt);
- pkt->l3_hdr.ip.ip_len = cpu_to_be16(pkt->payload_len +
- pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len);
-
pkt->l3_hdr.ip.ip_sum = 0;
csum = net_raw_checksum(pkt->l3_hdr.octets,
pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len);
@@ -117,7 +114,9 @@ void net_tx_pkt_update_ip_checksums(struct NetTxPkt *pkt)
if (gso_type == VIRTIO_NET_HDR_GSO_TCPV4 ||
gso_type == VIRTIO_NET_HDR_GSO_UDP) {
- /* Calculate IP header checksum */
+ /* Set ip_len and calculate IP header checksum */
+ pkt->l3_hdr.ip.ip_len = cpu_to_be16(pkt->payload_len +
+ pkt->vec[NET_TX_PKT_L3HDR_FRAG].iov_len);
net_tx_pkt_update_ip_hdr_checksum(pkt);
/* Calculate IP pseudo header checksum */
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 12/32] hw/scsi/mptsas: Reset doorbell state on reset
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (10 preceding siblings ...)
2026-07-07 13:12 ` [PULL 11/32] hw/net: fix e1000e/igb ip_len inflation by Ethernet minimum-frame padding Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 13/32] hw/hyperv: Avoid crash if hyperv_find_cpu() passed invalid vp_index Philippe Mathieu-Daudé
` (21 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Peter Maydell <peter.maydell@linaro.org>
Currently the mptsas reset function clears intr_status, but it
doesn't reset the doorbell state machine. This means that the state
machine and the interrupt state get out of sync, and the guest can
trigger an assertion failure in mptsas_doorbell_read() where
s->doorbell_state is still DOORBELL_READ but s->intr_status does not
have MPI_HIS_DOORBELL_INTERRUPT set.
Fix this by having reset also reset the doorbell state. Strictly
speaking we don't need to also clear doorbell_reply_idx and
doorbell_reply_size, because those are only read when in
DOORBELL_READ state, and the code always sets them up before
transitioning into that state. But it's less confusing to clear them
out on reset.
Cc: qemu-stable@nongnu.org
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/304
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260629185035.2138238-1-peter.maydell@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/scsi/mptsas.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
index e4a7b2fee4a..5df124c0ce5 100644
--- a/hw/scsi/mptsas.c
+++ b/hw/scsi/mptsas.c
@@ -811,6 +811,10 @@ static void mptsas_soft_reset(MPTSASState *s)
s->intr_status = 0;
s->intr_mask = save_mask;
+ s->doorbell_state = DOORBELL_NONE;
+ s->doorbell_reply_idx = 0;
+ s->doorbell_reply_size = 0;
+
s->reply_free_tail = 0;
s->reply_free_head = 0;
s->reply_post_tail = 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 13/32] hw/hyperv: Avoid crash if hyperv_find_cpu() passed invalid vp_index
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (11 preceding siblings ...)
2026-07-07 13:12 ` [PULL 12/32] hw/scsi/mptsas: Reset doorbell state on reset Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 14/32] hw/display/qxl: Fix mono cursor validation that can read past a cursor chunk Philippe Mathieu-Daudé
` (20 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Peter Maydell <peter.maydell@linaro.org>
The hyperv_find_cpu() function finds a CPU from a CPU index; this is
basically a wrapper around qemu_get_cpu(). It is allowed to fail, in
which case it returns NULL, which its caller handles. However, it
includes an assertion check which accidentally assumes the CPU
pointer is non-NULL.
We could assert only if cs != NULL, but the assertion here is not
doing anything interesting -- hyperv_vp_index() is a trivial wrapper
returning cs->cpu_index, so this is effectively asserting that
qemu_get_cpu() did what it claims to do, i.e. returned us the CPU
matching the index we gave it. qemu_get_cpu() is a simple "iterate
through list and find matching CPU" which is unlikely to be buggy,
and we don't feel the need to sanity-check it in any of our other
many uses of it. Drop the assertion entirely.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3568
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20260630084855.2319838-1-peter.maydell@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/hyperv/hyperv.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index 4d900327857..900ff80213d 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -237,9 +237,7 @@ struct HvSintRoute {
static CPUState *hyperv_find_vcpu(uint32_t vp_index)
{
- CPUState *cs = qemu_get_cpu(vp_index);
- assert(hyperv_vp_index(cs) == vp_index);
- return cs;
+ return qemu_get_cpu(vp_index);
}
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 14/32] hw/display/qxl: Fix mono cursor validation that can read past a cursor chunk
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (12 preceding siblings ...)
2026-07-07 13:12 ` [PULL 13/32] hw/hyperv: Avoid crash if hyperv_find_cpu() passed invalid vp_index Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 15/32] utils/module: fix memleak in module_load() Philippe Mathieu-Daudé
` (19 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Thomas Huth <thuth@redhat.com>
qxl_render_cursor() maps the guest-provided QXLCursor object using the
guest-controlled cursor->chunk.data_size.
For a mono cursor, qxl_cursor() then validates the expected bitmap size
against cursor->data_size, but it does not validate that the first chunk
actually contains that many bytes.
A guest could set cursor->data_size to the correct full mono cursor size
while setting cursor->chunk.data_size to zero. In that case, cursor_set_mono()
reads the AND/XOR masks starting at cursor->chunk.data. If the cursor object
is placed at the end of the QXL RAM BAR, those reads cross the mapped RAM
region and could crash the QEMU process (e.g. under ASan).
Fix it by double-checking cursor->chunk.data_size for the correct size.
This patch is based on the suggested changes by the reporter in the bug
ticket.
Reported-by: huntr bubble
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3646
Signed-off-by: Thomas Huth <thuth@redhat.com>
Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260630101022.379057-1-thuth@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/display/qxl-render.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index 7b692d5a854..3bf634ee059 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -272,9 +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) {
- fprintf(stderr, "%s: bad monochrome cursor %ux%u with size %u\n",
- __func__, c->width, c->height, cursor->data_size);
+ if (size != cursor->data_size || cursor->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);
goto fail;
}
and_mask = cursor->chunk.data;
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 15/32] utils/module: fix memleak in module_load()
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (13 preceding siblings ...)
2026-07-07 13:12 ` [PULL 14/32] hw/display/qxl: Fix mono cursor validation that can read past a cursor chunk Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 16/32] hw/intc/loongarch_dintc: Fix OOB access in DINT MMIO write handler Philippe Mathieu-Daudé
` (18 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Dmitry Frolov <frolov@swemel.ru>
Memory for version_dir, allocated by g_strdup, is not freed
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Signed-off-by: Dmitry Frolov <frolov@swemel.ru>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260630110601.736019-1-frolov@swemel.ru>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
util/module.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/util/module.c b/util/module.c
index 09dc43f51eb..8f8e6994f11 100644
--- a/util/module.c
+++ b/util/module.c
@@ -203,7 +203,7 @@ int module_load(const char *prefix, const char *name, Error **errp)
{
int rv = -1;
#ifdef CONFIG_MODULE_UPGRADES
- char *version_dir;
+ g_autofree char *version_dir = NULL;
#endif
const char *search_dir;
char *dirs[5];
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 16/32] hw/intc/loongarch_dintc: Fix OOB access in DINT MMIO write handler
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (14 preceding siblings ...)
2026-07-07 13:12 ` [PULL 15/32] utils/module: fix memleak in module_load() Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 17/32] hw/net/can/flexcan: Wire clock control module via link property Philippe Mathieu-Daudé
` (17 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Song Gao <gaosong@loongson.cn>
Validate guest-controlled cpu_num before using it to index the cpu[] array
or pass to async_run_on_cpu(). Without this check, a malicious guest can
trigger a NULL pointer dereference in async_run_on_cpu() and an
out-of-bounds array access in qemu_set_irq(), causing host crash.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3616
Fixes: 0d148eaf5a3e ("hw/loongarch: Implement dintc set irq")
Reported-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260701065454.1976188-1-gaosong@loongson.cn>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/intc/loongarch_dintc.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/hw/intc/loongarch_dintc.c b/hw/intc/loongarch_dintc.c
index c877a8003b7..e40292887c2 100644
--- a/hw/intc/loongarch_dintc.c
+++ b/hw/intc/loongarch_dintc.c
@@ -19,6 +19,7 @@
#include "target/loongarch/cpu.h"
#include "qemu/error-report.h"
#include "system/hw_accel.h"
+#include "qemu/log.h"
/* msg addr field */
FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
@@ -52,7 +53,19 @@ static void loongarch_dintc_mem_write(void *opaque, hwaddr addr,
CPUState *cs;
cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
+
+ /* Validate cpu_num against the configured number of CPUs */
+ if (cpu_num >= s->num_cpu) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "loongarch-dintc: invalid cpu number%d\n", cpu_num);
+ return;
+ }
cs = cpu_by_arch_id(cpu_num);
+ if (!cs) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "loongarch-dintc: no CPU for arch_id %d\n", cpu_num);
+ return;
+ }
irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
async_run_on_cpu(cs, do_set_vcpu_dintc_irq,
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 17/32] hw/net/can/flexcan: Wire clock control module via link property
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (15 preceding siblings ...)
2026-07-07 13:12 ` [PULL 16/32] hw/intc/loongarch_dintc: Fix OOB access in DINT MMIO write handler Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 18/32] hw/net/can/flexcan: Subclass TYPE_CAN_FLEXCAN Philippe Mathieu-Daudé
` (16 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bernhard Beschow <shentey@gmail.com>
When wiring struct FlexcanState to the clock control module, it is
currently necessary to reach into its private data. Moreover, when
forgetting to wire the clock control module, QEMU will crash after the
guest has already started. Fix both by letting struct FlexcanState
expose a link property whose sanity is checked at realize time.
Suggested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Acked-by: Pavel Pisa <pisa@fel.cvut.cz>
Tested-by: Pavel Pisa <pisa@fel.cvut.cz>
Message-ID: <20260702184038.178196-2-shentey@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/arm/fsl-imx6.c | 3 ++-
hw/net/can/flexcan.c | 10 ++++++++--
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index bf106a90632..585c935b899 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -391,7 +391,8 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
{ FSL_IMX6_CAN2_ADDR, FSL_IMX6_FLEXCAN2_IRQ },
};
- s->flexcan[i].ccm = IMX_CCM(&s->ccm);
+ object_property_set_link(OBJECT(&s->flexcan[i]), "clock-control-module",
+ OBJECT(&s->ccm), &error_abort);
object_property_set_link(OBJECT(&s->flexcan[i]), "canbus",
OBJECT(s->canbus[i]), &error_abort);
diff --git a/hw/net/can/flexcan.c b/hw/net/can/flexcan.c
index 1ea459d9f69..8f3f066ef50 100644
--- a/hw/net/can/flexcan.c
+++ b/hw/net/can/flexcan.c
@@ -333,8 +333,6 @@ static uint32_t flexcan_get_bitrate(FlexcanState *s)
uint32_t pe_freq, s_freq, bitrate;
- assert(s->ccm);
-
/* s_freq: CAN clock from CCM divided by the prescaler */
pe_freq = imx_ccm_get_clock_frequency(s->ccm, CLK_CAN);
s_freq = pe_freq / (1 + conf_presdiv);
@@ -1346,6 +1344,12 @@ static void flexcan_realize(DeviceState *dev, Error **errp)
}
}
+ if (!s->ccm) {
+ error_setg(errp, "%s 'clock-control-module' link property not set",
+ dev->canonical_path);
+ return;
+ }
+
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
sysbus_init_irq(SYS_BUS_DEVICE(SYS_BUS_DEVICE(dev)), &s->irq);
}
@@ -1366,6 +1370,8 @@ static const VMStateDescription vmstate_can = {
static const Property flexcan_properties[] = {
DEFINE_PROP_LINK("canbus", FlexcanState, canbus, TYPE_CAN_BUS,
CanBusState *),
+ DEFINE_PROP_LINK("clock-control-module", FlexcanState, ccm, TYPE_IMX_CCM,
+ IMXCCMState *),
};
static void flexcan_class_init(ObjectClass *klass, const void *data)
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 18/32] hw/net/can/flexcan: Subclass TYPE_CAN_FLEXCAN
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (16 preceding siblings ...)
2026-07-07 13:12 ` [PULL 17/32] hw/net/can/flexcan: Wire clock control module via link property Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 19/32] hw/arm/imx8mp-evk: Open code DEFINE_MACHINE_AARCH64 Philippe Mathieu-Daudé
` (15 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bernhard Beschow <shentey@gmail.com>
Subclass TYPE_CAN_FLEXCAN, yielding TYPE_CAN_FLEXCAN2 and
TYPE_CAN_FLEXCAN3.
Since TYPE_CAN_FLEXCAN is now abstract, TYPE_FSL_IMX6 needs to use
TYPE_CAN_FLEXCAN2. TYPE_CAN_FLEXCAN3 will be used in TYPE_FSL_IMX8MP.
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Acked-by: Pavel Pisa <pisa@fel.cvut.cz>
Tested-by: Pavel Pisa <pisa@fel.cvut.cz>
Message-ID: <20260702184038.178196-3-shentey@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/net/flexcan.h | 4 +-
hw/arm/fsl-imx6.c | 2 +-
hw/net/can/flexcan.c | 80 ++++++++++++++++++++++++++++++++--------
3 files changed, 69 insertions(+), 17 deletions(-)
diff --git a/include/hw/net/flexcan.h b/include/hw/net/flexcan.h
index 153afc1e03b..32de7b904af 100644
--- a/include/hw/net/flexcan.h
+++ b/include/hw/net/flexcan.h
@@ -139,7 +139,9 @@ typedef struct FlexcanState {
} FlexcanState;
#define TYPE_CAN_FLEXCAN "flexcan"
-
OBJECT_DECLARE_SIMPLE_TYPE(FlexcanState, CAN_FLEXCAN);
+#define TYPE_CAN_FLEXCAN2 "flexcan2"
+#define TYPE_CAN_FLEXCAN3 "flexcan3"
+
#endif
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index 585c935b899..eec9673c6fb 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -92,7 +92,7 @@ static void fsl_imx6_init(Object *obj)
}
for (i = 0; i < FSL_IMX6_NUM_CANS; i++) {
snprintf(name, NAME_SIZE, "flexcan%d", i + 1);
- object_initialize_child(obj, name, &s->flexcan[i], TYPE_CAN_FLEXCAN);
+ object_initialize_child(obj, name, &s->flexcan[i], TYPE_CAN_FLEXCAN2);
}
for (i = 0; i < FSL_IMX6_NUM_WDTS; i++) {
snprintf(name, NAME_SIZE, "wdt%d", i);
diff --git a/hw/net/can/flexcan.c b/hw/net/can/flexcan.c
index 8f3f066ef50..da36d10bd33 100644
--- a/hw/net/can/flexcan.c
+++ b/hw/net/can/flexcan.c
@@ -1290,7 +1290,7 @@ static bool flexcan_mem_accepts(void *opaque, hwaddr addr,
return true;
}
-static const struct MemoryRegionOps flexcan_ops = {
+static const struct MemoryRegionOps flexcan2_ops = {
.read = flexcan_mem_read,
.write = flexcan_mem_write,
.endianness = DEVICE_LITTLE_ENDIAN,
@@ -1307,6 +1307,23 @@ static const struct MemoryRegionOps flexcan_ops = {
},
};
+static const struct MemoryRegionOps flexcan3_ops = {
+ .read = flexcan_mem_read,
+ .write = flexcan_mem_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 8,
+ .unaligned = true,
+ .accepts = flexcan_mem_accepts
+ },
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false
+ },
+};
+
static CanBusClientInfo flexcan_bus_client_info = {
.can_receive = flexcan_can_receive,
.receive = flexcan_receive,
@@ -1322,16 +1339,26 @@ static int flexcan_connect_to_bus(FlexcanState *s, CanBusState *bus)
return 0;
}
-static void flexcan_init(Object *obj)
+static void flexcan2_init(Object *obj)
{
FlexcanState *s = CAN_FLEXCAN(obj);
memory_region_init_io(
- &s->iomem, obj, &flexcan_ops, s, TYPE_CAN_FLEXCAN,
+ &s->iomem, obj, &flexcan2_ops, s, TYPE_CAN_FLEXCAN2,
offsetof(FlexcanRegs, _reserved6)
);
}
+static void flexcan3_init(Object *obj)
+{
+ FlexcanState *s = CAN_FLEXCAN(obj);
+
+ memory_region_init_io(
+ &s->iomem, obj, &flexcan3_ops, s, TYPE_CAN_FLEXCAN3,
+ sizeof(FlexcanRegs)
+ );
+}
+
static void flexcan_realize(DeviceState *dev, Error **errp)
{
FlexcanState *s = CAN_FLEXCAN(dev);
@@ -1384,19 +1411,42 @@ static void flexcan_class_init(ObjectClass *klass, const void *data)
dc->realize = flexcan_realize;
device_class_set_props(dc, flexcan_properties);
dc->vmsd = &vmstate_can;
- dc->desc = "i.MX FLEXCAN Controller";
}
-static const TypeInfo flexcan_info = {
- .name = TYPE_CAN_FLEXCAN,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(FlexcanState),
- .class_init = flexcan_class_init,
- .instance_init = flexcan_init,
+static void flexcan2_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "i.MX FlexCAN 2 Controller";
+}
+
+static void flexcan3_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "i.MX FlexCAN 3 Controller";
+}
+
+static const TypeInfo flexcan_types[] = {
+ {
+ .name = TYPE_CAN_FLEXCAN,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(FlexcanState),
+ .class_init = flexcan_class_init,
+ .abstract = true,
+ },
+ {
+ .name = TYPE_CAN_FLEXCAN2,
+ .parent = TYPE_CAN_FLEXCAN,
+ .class_init = flexcan2_class_init,
+ .instance_init = flexcan2_init,
+ },
+ {
+ .name = TYPE_CAN_FLEXCAN3,
+ .parent = TYPE_CAN_FLEXCAN,
+ .class_init = flexcan3_class_init,
+ .instance_init = flexcan3_init,
+ },
};
-static void can_register_types(void)
-{
- type_register_static(&flexcan_info);
-}
-type_init(can_register_types)
+DEFINE_TYPES(flexcan_types)
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 19/32] hw/arm/imx8mp-evk: Open code DEFINE_MACHINE_AARCH64
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (17 preceding siblings ...)
2026-07-07 13:12 ` [PULL 18/32] hw/net/can/flexcan: Subclass TYPE_CAN_FLEXCAN Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 20/32] hw/arm/imx8mp-evk: Introduce FslImx8mpEvkState Philippe Mathieu-Daudé
` (14 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bernhard Beschow <shentey@gmail.com>
Open code the DEFINE_MACHINE_AARCH64 macro in preparation of creating
FslImx8mpEvkState class, needed for FlexCAN emulation.
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Acked-by: Pavel Pisa <pisa@fel.cvut.cz>
Tested-by: Pavel Pisa <pisa@fel.cvut.cz>
Message-ID: <20260702184038.178196-4-shentey@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/arm/imx8mp-evk.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
index b84ac91a17d..4a0c9df76b7 100644
--- a/hw/arm/imx8mp-evk.c
+++ b/hw/arm/imx8mp-evk.c
@@ -113,8 +113,10 @@ static const char *imx8mp_evk_get_default_cpu_type(const MachineState *ms)
return ARM_CPU_TYPE_NAME("cortex-a53");
}
-static void imx8mp_evk_machine_init(MachineClass *mc)
+static void imx8mp_evk_machine_class_init(ObjectClass *oc, const void *data)
{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
mc->desc = "NXP i.MX 8M Plus EVK Board";
mc->init = imx8mp_evk_init;
mc->default_cpus = 4;
@@ -124,4 +126,13 @@ static void imx8mp_evk_machine_init(MachineClass *mc)
mc->get_default_cpu_type = imx8mp_evk_get_default_cpu_type;
}
-DEFINE_MACHINE_AARCH64("imx8mp-evk", imx8mp_evk_machine_init)
+static const TypeInfo imx8mp_evk_machine_types[] = {
+ {
+ .name = MACHINE_TYPE_NAME("imx8mp-evk"),
+ .parent = TYPE_MACHINE,
+ .class_init = imx8mp_evk_machine_class_init,
+ .interfaces = aarch64_machine_interfaces,
+ },
+};
+
+DEFINE_TYPES(imx8mp_evk_machine_types)
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 20/32] hw/arm/imx8mp-evk: Introduce FslImx8mpEvkState
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (18 preceding siblings ...)
2026-07-07 13:12 ` [PULL 19/32] hw/arm/imx8mp-evk: Open code DEFINE_MACHINE_AARCH64 Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 21/32] hw/arm: Add basic FlexCAN3 support to TYPE_FSL_IMX8MP and imx8mp-evk Philippe Mathieu-Daudé
` (13 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bernhard Beschow <shentey@gmail.com>
Introduce class FslImx8mpEvkState which will be needed for holding
CanBusState attributes and associated properties.
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Acked-by: Pavel Pisa <pisa@fel.cvut.cz>
Tested-by: Pavel Pisa <pisa@fel.cvut.cz>
Message-ID: <20260702184038.178196-5-shentey@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/arm/imx8mp-evk.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
index 4a0c9df76b7..ca0ee2d3f2e 100644
--- a/hw/arm/imx8mp-evk.c
+++ b/hw/arm/imx8mp-evk.c
@@ -19,6 +19,17 @@
#include "qapi/error.h"
#include <libfdt.h>
+#define TYPE_IMX8MPEVK_MACHINE MACHINE_TYPE_NAME("imx8mp-evk")
+OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpEvkState, IMX8MPEVK_MACHINE)
+
+struct FslImx8mpEvkState {
+ MachineState parent_obj;
+
+ FslImx8mpState soc;
+
+ struct arm_boot_info boot_info;
+};
+
static void imx8mp_evk_modify_dtb(const struct arm_boot_info *info, void *fdt)
{
int i, offset;
@@ -57,8 +68,7 @@ static void imx8mp_evk_modify_dtb(const struct arm_boot_info *info, void *fdt)
static void imx8mp_evk_init(MachineState *machine)
{
- static struct arm_boot_info boot_info;
- FslImx8mpState *s;
+ FslImx8mpEvkState *s = IMX8MPEVK_MACHINE(machine);
if (machine->ram_size > FSL_IMX8MP_RAM_SIZE_MAX) {
error_report("RAM size " RAM_ADDR_FMT " above max supported (%08" PRIx64 ")",
@@ -66,7 +76,7 @@ static void imx8mp_evk_init(MachineState *machine)
exit(1);
}
- boot_info = (struct arm_boot_info) {
+ s->boot_info = (struct arm_boot_info) {
.loader_start = FSL_IMX8MP_RAM_START,
.board_id = -1,
.ram_size = machine->ram_size,
@@ -74,10 +84,9 @@ static void imx8mp_evk_init(MachineState *machine)
.modify_dtb = imx8mp_evk_modify_dtb,
};
- s = FSL_IMX8MP(object_new(TYPE_FSL_IMX8MP));
- object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
- object_property_set_uint(OBJECT(s), "fec1-phy-num", 1, &error_fatal);
- sysbus_realize_and_unref(SYS_BUS_DEVICE(s), &error_fatal);
+ object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_FSL_IMX8MP);
+ object_property_set_uint(OBJECT(&s->soc), "fec1-phy-num", 1, &error_fatal);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->soc), &error_fatal);
memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
machine->ram);
@@ -93,14 +102,14 @@ static void imx8mp_evk_init(MachineState *machine)
}
blk = blk_by_legacy_dinfo(di);
- bus = qdev_get_child_bus(DEVICE(&s->usdhc[i]), "sd-bus");
+ bus = qdev_get_child_bus(DEVICE(&s->soc.usdhc[i]), "sd-bus");
carddev = qdev_new(TYPE_SD_CARD);
qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
qdev_realize_and_unref(carddev, bus, &error_fatal);
}
if (!qtest_enabled()) {
- arm_load_kernel(&s->cpu[0], machine, &boot_info);
+ arm_load_kernel(&s->soc.cpu[0], machine, &s->boot_info);
}
}
@@ -128,9 +137,10 @@ static void imx8mp_evk_machine_class_init(ObjectClass *oc, const void *data)
static const TypeInfo imx8mp_evk_machine_types[] = {
{
- .name = MACHINE_TYPE_NAME("imx8mp-evk"),
+ .name = TYPE_IMX8MPEVK_MACHINE,
.parent = TYPE_MACHINE,
.class_init = imx8mp_evk_machine_class_init,
+ .instance_size = sizeof(FslImx8mpEvkState),
.interfaces = aarch64_machine_interfaces,
},
};
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 21/32] hw/arm: Add basic FlexCAN3 support to TYPE_FSL_IMX8MP and imx8mp-evk
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (19 preceding siblings ...)
2026-07-07 13:12 ` [PULL 20/32] hw/arm/imx8mp-evk: Introduce FslImx8mpEvkState Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 22/32] hw/rtc/mc146818rtc: convert date from object prop to class prop Philippe Mathieu-Daudé
` (12 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bernhard Beschow <shentey@gmail.com>
Real hardware supports CAN FD which is missing in the emulation and is
considered future work. Still, CAN communication already works under Linux.
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Acked-by: Pavel Pisa <pisa@fel.cvut.cz>
Tested-by: Pavel Pisa <pisa@fel.cvut.cz>
Message-ID: <20260702184038.178196-6-shentey@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
docs/system/arm/imx8m.rst | 1 +
include/hw/arm/fsl-imx8mp.h | 8 ++++++++
hw/arm/fsl-imx8mp.c | 38 +++++++++++++++++++++++++++++++++++++
hw/arm/imx8mp-evk.c | 21 ++++++++++++++++++++
hw/misc/imx8mp_ccm.c | 3 +++
hw/arm/Kconfig | 1 +
6 files changed, 72 insertions(+)
diff --git a/docs/system/arm/imx8m.rst b/docs/system/arm/imx8m.rst
index afbc33b2f40..1bcb8255be5 100644
--- a/docs/system/arm/imx8m.rst
+++ b/docs/system/arm/imx8m.rst
@@ -18,6 +18,7 @@ following devices:
* 1 Designware PCI Express Controller
* 1 Ethernet Controller
* 2 Designware USB 3 Controllers
+ * 2 FlexCAN 3 CAN Controllers (``imx8mp-evk`` only)
* 5 GPIO Controllers
* 6 I2C Controllers
* 3 SPI Controllers
diff --git a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h
index 3b6183ed1d6..2be3c51af56 100644
--- a/include/hw/arm/fsl-imx8mp.h
+++ b/include/hw/arm/fsl-imx8mp.h
@@ -17,6 +17,7 @@
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx8mp_analog.h"
#include "hw/misc/imx8mp_ccm.h"
+#include "hw/net/flexcan.h"
#include "hw/net/imx_fec.h"
#include "hw/core/or-irq.h"
#include "hw/pci-host/designware.h"
@@ -37,6 +38,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState, FSL_IMX8MP)
#define FSL_IMX8MP_RAM_SIZE_MAX (8 * GiB)
enum FslImx8mpConfiguration {
+ FSL_IMX8MP_NUM_CANS = 2,
FSL_IMX8MP_NUM_CPUS = 4,
FSL_IMX8MP_NUM_ECSPIS = 3,
FSL_IMX8MP_NUM_GPIOS = 5,
@@ -68,11 +70,14 @@ struct FslImx8mpState {
USBDWC3 usb[FSL_IMX8MP_NUM_USBS];
DesignwarePCIEHost pcie;
FslImx8mPciePhyState pcie_phy;
+ FlexcanState flexcan[FSL_IMX8MP_NUM_CANS];
OrIRQState gpt5_gpt6_irq;
MemoryRegion ocram;
uint32_t phy_num;
bool phy_connected;
+
+ CanBusState *canbus[FSL_IMX8MP_NUM_CANS];
};
enum FslImx8mpMemoryRegions {
@@ -279,6 +284,9 @@ enum FslImx8mpIrqs {
FSL_IMX8MP_PCI_INTC_IRQ = 124,
FSL_IMX8MP_PCI_INTD_IRQ = 123,
FSL_IMX8MP_PCI_MSI_IRQ = 140,
+
+ FSL_IMX8MP_FLEXCAN1_IRQ = 142,
+ FSL_IMX8MP_FLEXCAN2_IRQ = 144,
};
#endif /* FSL_IMX8MP_H */
diff --git a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c
index 7c03ed3c347..bcd91739d9b 100644
--- a/hw/arm/fsl-imx8mp.c
+++ b/hw/arm/fsl-imx8mp.c
@@ -246,6 +246,11 @@ static void fsl_imx8mp_init(Object *obj)
object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
}
+ for (i = 0; i < FSL_IMX8MP_NUM_CANS; i++) {
+ g_autofree char *name = g_strdup_printf("flexcan%d", i);
+ object_initialize_child(obj, name, &s->flexcan[i], TYPE_CAN_FLEXCAN3);
+ }
+
object_initialize_child(obj, "eth0", &s->enet, TYPE_IMX_ENET);
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
@@ -669,6 +674,34 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie_phy), 0,
fsl_imx8mp_memmap[FSL_IMX8MP_PCIE_PHY1].addr);
+ /* FlexCANs */
+ for (i = 0; i < FSL_IMX8MP_NUM_CANS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } flexcan_table[FSL_IMX8MP_NUM_CANS] = {
+ {
+ fsl_imx8mp_memmap[FSL_IMX8MP_FLEXCAN1].addr,
+ FSL_IMX8MP_FLEXCAN1_IRQ
+ }, {
+ fsl_imx8mp_memmap[FSL_IMX8MP_FLEXCAN2].addr,
+ FSL_IMX8MP_FLEXCAN2_IRQ
+ },
+ };
+
+ object_property_set_link(OBJECT(&s->flexcan[i]), "clock-control-module",
+ OBJECT(&s->ccm), &error_abort);
+ object_property_set_link(OBJECT(&s->flexcan[i]), "canbus",
+ OBJECT(s->canbus[i]), &error_abort);
+
+ sysbus_realize(SYS_BUS_DEVICE(&s->flexcan[i]), &error_abort);
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->flexcan[i]), 0,
+ flexcan_table[i].addr);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->flexcan[i]), 0,
+ qdev_get_gpio_in(gicdev, flexcan_table[i].irq));
+ }
+
/* On-Chip RAM */
if (!memory_region_init_ram(&s->ocram, OBJECT(dev), "imx8mp.ocram",
fsl_imx8mp_memmap[FSL_IMX8MP_OCRAM].size,
@@ -684,6 +717,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
switch (i) {
case FSL_IMX8MP_ANA_PLL:
case FSL_IMX8MP_CCM:
+ case FSL_IMX8MP_FLEXCAN1 ... FSL_IMX8MP_FLEXCAN2:
case FSL_IMX8MP_GIC_DIST:
case FSL_IMX8MP_GIC_REDIST:
case FSL_IMX8MP_GPIO1 ... FSL_IMX8MP_GPIO5:
@@ -715,6 +749,10 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
static const Property fsl_imx8mp_properties[] = {
DEFINE_PROP_UINT32("fec1-phy-num", FslImx8mpState, phy_num, 0),
DEFINE_PROP_BOOL("fec1-phy-connected", FslImx8mpState, phy_connected, true),
+ DEFINE_PROP_LINK("canbus0", FslImx8mpState, canbus[0], TYPE_CAN_BUS,
+ CanBusState *),
+ DEFINE_PROP_LINK("canbus1", FslImx8mpState, canbus[1], TYPE_CAN_BUS,
+ CanBusState *),
};
static void fsl_imx8mp_class_init(ObjectClass *oc, const void *data)
diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c
index ca0ee2d3f2e..16e9722d146 100644
--- a/hw/arm/imx8mp-evk.c
+++ b/hw/arm/imx8mp-evk.c
@@ -26,6 +26,7 @@ struct FslImx8mpEvkState {
MachineState parent_obj;
FslImx8mpState soc;
+ CanBusState *canbus[FSL_IMX8MP_NUM_CANS];
struct arm_boot_info boot_info;
};
@@ -86,6 +87,12 @@ static void imx8mp_evk_init(MachineState *machine)
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_FSL_IMX8MP);
object_property_set_uint(OBJECT(&s->soc), "fec1-phy-num", 1, &error_fatal);
+ for (int i = 0; i < FSL_IMX8MP_NUM_CANS; i++) {
+ g_autofree char *bus_name = g_strdup_printf("canbus%d", i);
+
+ object_property_set_link(OBJECT(&s->soc), bus_name,
+ OBJECT(s->canbus[i]), &error_fatal);
+ }
sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->soc), &error_fatal);
memory_region_add_subregion(get_system_memory(), FSL_IMX8MP_RAM_START,
@@ -122,6 +129,19 @@ static const char *imx8mp_evk_get_default_cpu_type(const MachineState *ms)
return ARM_CPU_TYPE_NAME("cortex-a53");
}
+static void imx8mp_evk_machine_init(Object *obj)
+{
+ FslImx8mpEvkState *s = IMX8MPEVK_MACHINE(obj);
+
+ object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
+ (Object **)&s->canbus[0],
+ object_property_allow_set_link, 0);
+
+ object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
+ (Object **)&s->canbus[1],
+ object_property_allow_set_link, 0);
+}
+
static void imx8mp_evk_machine_class_init(ObjectClass *oc, const void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -140,6 +160,7 @@ static const TypeInfo imx8mp_evk_machine_types[] = {
.name = TYPE_IMX8MPEVK_MACHINE,
.parent = TYPE_MACHINE,
.class_init = imx8mp_evk_machine_class_init,
+ .instance_init = imx8mp_evk_machine_init,
.instance_size = sizeof(FslImx8mpEvkState),
.interfaces = aarch64_machine_interfaces,
},
diff --git a/hw/misc/imx8mp_ccm.c b/hw/misc/imx8mp_ccm.c
index 911911ed865..97d363e79d8 100644
--- a/hw/misc/imx8mp_ccm.c
+++ b/hw/misc/imx8mp_ccm.c
@@ -129,6 +129,9 @@ static uint32_t imx8mp_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
case CLK_HIGH:
freq = CKIH_FREQ;
break;
+ case CLK_CAN:
+ freq = 40000000; /* 40Mhz, taken from device tree */
+ break;
case CLK_IPG:
case CLK_IPG_HIGH:
/*
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index f9a225c19bc..82e0bc2e700 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -601,6 +601,7 @@ config FSL_IMX8MP
imply I2C_DEVICES
imply PCI_DEVICES
select ARM_GIC
+ select CAN_FLEXCAN
select FSL_IMX8MP_ANALOG
select FSL_IMX8MP_CCM
select IMX
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 22/32] hw/rtc/mc146818rtc: convert date from object prop to class prop
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (20 preceding siblings ...)
2026-07-07 13:12 ` [PULL 21/32] hw/arm: Add basic FlexCAN3 support to TYPE_FSL_IMX8MP and imx8mp-evk Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 23/32] hw/acpi/ich9: move initial property values into ich9_reset_properties() Philippe Mathieu-Daudé
` (11 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Mark Cave-Ayland <mark.caveayland@nutanix.com>
This is to allow it to be the target of a class alias property.
Signed-off-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260703090814.2993188-6-mark.caveayland@nutanix.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/rtc/mc146818rtc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index bcab018c7cd..ba396435d1a 100644
--- a/hw/rtc/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -920,8 +920,6 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
memory_region_add_subregion(&s->io, 0, &s->coalesced_io);
memory_region_add_coalescing(&s->coalesced_io, 0, 1);
- object_property_add_tm(OBJECT(s), "date", rtc_get_date);
-
qdev_init_gpio_out(dev, &s->irq, 1);
}
@@ -1020,6 +1018,8 @@ static void rtc_class_initfn(ObjectClass *klass, const void *data)
adevc->build_dev_aml = rtc_build_aml;
device_class_set_props(dc, mc146818rtc_properties);
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+
+ object_class_property_add_tm(klass, "date", rtc_get_date);
}
static const TypeInfo mc146818rtc_info = {
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 23/32] hw/acpi/ich9: move initial property values into ich9_reset_properties()
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (21 preceding siblings ...)
2026-07-07 13:12 ` [PULL 22/32] hw/rtc/mc146818rtc: convert date from object prop to class prop Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 24/32] backends/iommufd: Fix dev_id and type order in viommu trace Philippe Mathieu-Daudé
` (10 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Mark Cave-Ayland <mark.caveayland@nutanix.com>
Signed-off-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260703135512.3213964-7-mark.caveayland@nutanix.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/acpi/ich9.h | 2 ++
hw/acpi/ich9.c | 8 ++++++--
hw/isa/lpc_ich9.c | 1 +
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 019f0915c11..30990fcef53 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -81,6 +81,8 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, qemu_irq sci_irq);
void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
extern const VMStateDescription vmstate_ich9_pm;
+void ich9_pm_reset_properties(ICH9LPCPMRegs *pm);
+
void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm);
void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 5c7dfb2c69d..5e8f8a7eafa 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -388,9 +388,8 @@ static void ich9_pm_set_keep_pci_slot_hpc(Object *obj, bool value, Error **errp)
s->pm.keep_pci_slot_hpc = value;
}
-void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm)
+void ich9_pm_reset_properties(ICH9LPCPMRegs *pm)
{
- static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
pm->acpi_memory_hotplug.is_enabled = true;
pm->disable_s3 = 0;
pm->disable_s4 = 0;
@@ -398,6 +397,11 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm)
pm->acpi_pci_hotplug.use_acpi_hotplug_bridge = true;
pm->keep_pci_slot_hpc = true;
pm->enable_tco = true;
+}
+
+void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm)
+{
+ static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
&pm->pm_io_base, OBJ_PROP_FLAG_READ);
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 9cec18a378c..edf9783ec8d 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -701,6 +701,7 @@ static void ich9_lpc_initfn(Object *obj)
&lpc->smi_negotiated_features,
OBJ_PROP_FLAG_READ);
+ ich9_pm_reset_properties(&lpc->pm);
ich9_pm_add_properties(obj, &lpc->pm);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 24/32] backends/iommufd: Fix dev_id and type order in viommu trace
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (22 preceding siblings ...)
2026-07-07 13:12 ` [PULL 23/32] hw/acpi/ich9: move initial property values into ich9_reset_properties() Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 25/32] hw/block: m25p80: Fix dummy byte handling for Winbond flash Philippe Mathieu-Daudé
` (9 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Shameer Kolothum <skolothumtho@nvidia.com>
The trace event receives dev_id before type, but its format string prints
them in the wrong order. Correct the order.
Fixes: f2d31df0d925 ("backends/iommufd: Introduce iommufd_backend_alloc_viommu")
Reported-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20260706103653.84243-1-skolothumtho@nvidia.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
backends/trace-events | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/backends/trace-events b/backends/trace-events
index b63420b73ee..009a25b0be9 100644
--- a/backends/trace-events
+++ b/backends/trace-events
@@ -21,7 +21,7 @@ iommufd_backend_free_id(int iommufd, uint32_t id, int ret) " iommufd=%d id=%d (%
iommufd_backend_set_dirty(int iommufd, uint32_t hwpt_id, bool start, int ret) " iommufd=%d hwpt=%u enable=%d (%d)"
iommufd_backend_get_dirty_bitmap(int iommufd, uint32_t hwpt_id, uint64_t iova, uint64_t size, uint64_t flags, uint64_t page_size, int ret) " iommufd=%d hwpt=%u iova=0x%"PRIx64" size=0x%"PRIx64" flags=0x%"PRIx64" page_size=0x%"PRIx64" (%d)"
iommufd_backend_invalidate_cache(int iommufd, uint32_t id, uint32_t data_type, uint32_t entry_len, uint32_t entry_num, uint32_t done_num, uint64_t data_ptr, int ret) " iommufd=%d id=%u data_type=%u entry_len=%u entry_num=%u done_num=%u data_ptr=0x%"PRIx64" (%d)"
-iommufd_backend_alloc_viommu(int iommufd, uint32_t dev_id, uint32_t type, uint32_t hwpt_id, uint64_t data_ptr, uint32_t data_len, uint32_t viommu_id, int ret) " iommufd=%d type=%u dev_id=%u hwpt_id=%u data_ptr=0x%"PRIx64" data_len=0x%x viommu_id=%u (%d)"
+iommufd_backend_alloc_viommu(int iommufd, uint32_t dev_id, uint32_t type, uint32_t hwpt_id, uint64_t data_ptr, uint32_t data_len, uint32_t viommu_id, int ret) " iommufd=%d dev_id=%u type=%u hwpt_id=%u data_ptr=0x%"PRIx64" data_len=0x%x viommu_id=%u (%d)"
iommufd_backend_alloc_vdev(int iommufd, uint32_t dev_id, uint32_t viommu_id, uint64_t virt_id, uint32_t vdev_id, int ret) " iommufd=%d dev_id=%u viommu_id=%u virt_id=0x%"PRIx64" vdev_id=%u (%d)"
iommufd_viommu_alloc_eventq(int iommufd, uint32_t viommu_id, uint32_t type, uint32_t veventq_id, uint32_t veventq_fd, int ret) " iommufd=%d viommu_id=%u type=%u veventq_id=%u veventq_fd=%u (%d)"
iommufd_backend_alloc_hw_queue(int iommufd, uint32_t viommu_id, uint32_t queue_type, uint32_t index, uint64_t addr, uint64_t size, uint32_t queue_id, int ret) " iommufd=%d viommu_id=%u queue_type=%u index=%u addr=0x%"PRIx64" size=0x%"PRIx64" queue_id=%u (%d)"
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 25/32] hw/block: m25p80: Fix dummy byte handling for Winbond flash
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (23 preceding siblings ...)
2026-07-07 13:12 ` [PULL 24/32] backends/iommufd: Fix dev_id and type order in viommu trace Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 26/32] hw/block: m25p80: Fix dummy byte handling for Numonyx/Micron flash Philippe Mathieu-Daudé
` (8 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bin Meng <bin.meng@processmission.com>
The m25p80 model uses s->needed_bytes to track how many bytes a
controller must send after an opcode before the flash model can enter
the data phase. For address-bearing commands this includes the address
bytes. For fast-read commands it also includes the dummy phase.
The tricky part is that flash datasheets describe the dummy phase in
clock cycles, while the QEMU SSI interface advances the flash model one
transferred byte at a time. The dummy clock count therefore has to be
converted to the number of SSI bytes that the controller will actually
emit.
Some controllers have drivers that push these dummy bytes into a FIFO.
Other controllers are programmed with a dummy-cycle count and generate
the clocks themselves. The flash model still has to use the same byte
count that a FIFO-style controller or the Linux spi-mem layer would use,
otherwise the model waits too long and drops the first data bytes.
Let's fix the inconsistency from the flash side first. We start from an
easy one, the Winbond flashes.
Per the Windbond W25Q256JV datasheet [1] instruction set table
(chapter 8.1.2, 8.1.3, 8.1.4, 8.1.5), fix the wrong number of
dummy bytes needed for fast read commands.
[1] https://www.winbond.com/resource-files/w25q256jv%20spi%20revb%2009202016.pdf
Fixes: fe8477052831 ("m25p80: Fix QIOR/DIOR handling for Winbond")
Fixes: 3830c7a460b8 ("m25p80: Fix WINBOND fast read command handling")
Fixes: cf6f1efe0b57 ("m25p80: Fast read commands family changes")
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Tested-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20260707083431.219671-2-bin.meng@processmission.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/block/m25p80.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 4a4cda66024..59ecb32c0a2 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -1004,7 +1004,7 @@ static void decode_fast_read_cmd(Flash *s)
s->needed_bytes += 1;
break;
case MAN_WINBOND:
- s->needed_bytes += 8;
+ s->needed_bytes += 1;
break;
case MAN_NUMONYX:
s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
@@ -1099,7 +1099,7 @@ static void decode_qio_read_cmd(Flash *s)
switch (get_man(s)) {
case MAN_WINBOND:
s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
- s->needed_bytes += 4;
+ s->needed_bytes += 2;
break;
case MAN_SPANSION:
s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 26/32] hw/block: m25p80: Fix dummy byte handling for Numonyx/Micron flash
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (24 preceding siblings ...)
2026-07-07 13:12 ` [PULL 25/32] hw/block: m25p80: Fix dummy byte handling for Winbond flash Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 27/32] hw/block: m25p80: Fix dummy byte handling for Macronix flash Philippe Mathieu-Daudé
` (7 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bin Meng <bin.meng@processmission.com>
Numonyx/Micron flashes [1] do not use one fixed dummy-phase width for all
fast-read commands. The volatile configuration register stores a number
of dummy clock cycles, and QEMU must convert that value to the number of
SSI bytes consumed by the flash model.
Keep the existing default: 10 dummy clocks in Quad I/O mode and 8 dummy
clocks otherwise. In Quad I/O and Dual I/O protocol modes, all command
phases are transferred on 4 or 2 lines, so the dummy clock count still
needs to be scaled by that bus width.
Standard SPI, also called extended SPI in the Micron datasheet, is more
subtle. Quad Output Fast Read (6Bh) and Dual Output Fast Read (3Bh) keep
the opcode and address phases on DQ0; their dummy phase is just a clock
gap before data is returned on four or two output lines. Do not scale the
dummy count for those output-only commands. Only Quad I/O Fast Read
(EBh) and Dual I/O Fast Read (BBh) transfer the address and dummy phases
on the 4-bit or 2-bit bus, so keep scaling those commands.
[1] https://docs.rs-online.com/cad7/0900766b8121bd3c.pdf
Fixes: 23af26856606 ("hw/block/m25p80: Fix Numonyx fast read dummy cycle count")
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Tested-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20260707083431.219671-3-bin.meng@processmission.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/block/m25p80.c | 55 ++++++++++++++++++++++++++++++++++++-----------
1 file changed, 42 insertions(+), 13 deletions(-)
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 59ecb32c0a2..83d1ce1f956 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -971,28 +971,57 @@ static uint8_t numonyx_mode(Flash *s)
}
}
-static uint8_t numonyx_extract_cfg_num_dummies(Flash *s)
+static uint8_t numonyx_extract_cfg_dummy_bytes(Flash *s)
{
- uint8_t num_dummies;
+ uint8_t dummy_bits;
uint8_t mode;
- assert(get_man(s) == MAN_NUMONYX);
mode = numonyx_mode(s);
- num_dummies = extract32(s->volatile_cfg, 4, 4);
+ dummy_bits = extract32(s->volatile_cfg, 4, 4);
- if (num_dummies == 0x0 || num_dummies == 0xf) {
+ /*
+ * The default nubmer of dummy cycles is only related to the SPI
+ * protocol mode. For QSPI it is 10, otherwise it is 8.
+ */
+ if (dummy_bits == 0x0 || dummy_bits == 0xf) {
+ dummy_bits = (mode == MODE_QIO) ? 10 : 8;
+ }
+
+ /*
+ * Convert the number of dummy cycles to bytes.
+ *
+ * In the Dual I/O and Quad I/O protocols, all command phases use 2 or 4
+ * lines. In standard/extended SPI mode the phase width depends on the
+ * command sequence: output-only fast reads keep the dummy clocks on the
+ * single address line, while input/output fast reads use the same 2-line
+ * or 4-line phase as the address.
+ */
+
+ if (mode == MODE_QIO) {
+ dummy_bits *= 4;
+ } else if (mode == MODE_DIO) {
+ dummy_bits *= 2;
+ } else {
switch (s->cmd_in_progress) {
case QIOR:
case QIOR4:
- num_dummies = 10;
+ dummy_bits *= 4;
break;
- default:
- num_dummies = (mode == MODE_QIO) ? 10 : 8;
+ case DIOR:
+ case DIOR4:
+ dummy_bits *= 2;
break;
- }
+ }
}
- return num_dummies;
+ /*
+ * Assert that the dummy bit count is byte-aligned
+ * as SSI core can only consume whole dummy bytes.
+ */
+ assert(dummy_bits % 8 == 0);
+
+ /* return the number of dummy bytes */
+ return dummy_bits / 8;
}
static void decode_fast_read_cmd(Flash *s)
@@ -1007,7 +1036,7 @@ static void decode_fast_read_cmd(Flash *s)
s->needed_bytes += 1;
break;
case MAN_NUMONYX:
- s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
+ s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
break;
case MAN_MACRONIX:
if (extract32(s->volatile_cfg, 6, 2) == 1) {
@@ -1059,7 +1088,7 @@ static void decode_dio_read_cmd(Flash *s)
);
break;
case MAN_NUMONYX:
- s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
+ s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
break;
case MAN_MACRONIX:
switch (extract32(s->volatile_cfg, 6, 2)) {
@@ -1109,7 +1138,7 @@ static void decode_qio_read_cmd(Flash *s)
);
break;
case MAN_NUMONYX:
- s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
+ s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
break;
case MAN_MACRONIX:
switch (extract32(s->volatile_cfg, 6, 2)) {
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 27/32] hw/block: m25p80: Fix dummy byte handling for Macronix flash
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (25 preceding siblings ...)
2026-07-07 13:12 ` [PULL 26/32] hw/block: m25p80: Fix dummy byte handling for Numonyx/Micron flash Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 28/32] hw/ssi: npcm7xx_fiu: Correct the dummy cycle emulation logic Philippe Mathieu-Daudé
` (6 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bin Meng <bin.meng@processmission.com>
Macronix flashes expose DC[1:0] bits in the volatile configuration
register [1]. These bits select the number of dummy clock cycles
used by the fast-read command families.
Convert the Macronix dummy-cycle settings through per-command-family
tables and round up the non-byte-aligned cases that the byte-oriented
SSI model cannot represent exactly.
[1] https://www.macronix.com/Lists/Datasheet/Attachments/8657/MX66L51235F,%203V,%20512Mb,%20v1.1.pdf
Fixes: cf6f1efe0b57 ("m25p80: Fast read commands family changes")
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Tested-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20260707083431.219671-4-bin.meng@processmission.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/block/m25p80.c | 63 +++++++++++++++++++++++++++--------------------
1 file changed, 36 insertions(+), 27 deletions(-)
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 83d1ce1f956..d7a9d793737 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -1024,6 +1024,39 @@ static uint8_t numonyx_extract_cfg_dummy_bytes(Flash *s)
return dummy_bits / 8;
}
+static uint8_t macronix_extract_cfg_dummy_bytes(Flash *s, uint8_t bus_width)
+{
+ static const uint8_t dummy_cycles_fast[4] = { 8, 6, 8, 10 };
+ static const uint8_t dummy_cycles_dio[4] = { 4, 6, 8, 10 };
+ static const uint8_t dummy_cycles_qio[4] = { 6, 4, 8, 10 };
+ const uint8_t *dummy_cycles = dummy_cycles_fast;
+ uint8_t dummy_bits;
+
+ switch (s->cmd_in_progress) {
+ case DIOR:
+ case DIOR4:
+ dummy_cycles = dummy_cycles_dio;
+ break;
+ case QIOR:
+ case QIOR4:
+ dummy_cycles = dummy_cycles_qio;
+ break;
+ default:
+ break;
+ }
+
+ dummy_bits = dummy_cycles[extract32(s->volatile_cfg, 6, 2)];
+ dummy_bits *= bus_width;
+
+ /*
+ * Assert that the dummy bit count is byte-aligned
+ * as SSI core can only consume whole dummy bytes.
+ */
+ assert(dummy_bits % 8 == 0);
+
+ return dummy_bits / 8;
+}
+
static void decode_fast_read_cmd(Flash *s)
{
s->needed_bytes = get_addr_length(s);
@@ -1039,11 +1072,7 @@ static void decode_fast_read_cmd(Flash *s)
s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
break;
case MAN_MACRONIX:
- if (extract32(s->volatile_cfg, 6, 2) == 1) {
- s->needed_bytes += 6;
- } else {
- s->needed_bytes += 8;
- }
+ s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 1);
break;
case MAN_SPANSION:
s->needed_bytes += extract32(s->spansion_cr2v,
@@ -1091,17 +1120,7 @@ static void decode_dio_read_cmd(Flash *s)
s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
break;
case MAN_MACRONIX:
- switch (extract32(s->volatile_cfg, 6, 2)) {
- case 1:
- s->needed_bytes += 6;
- break;
- case 2:
- s->needed_bytes += 8;
- break;
- default:
- s->needed_bytes += 4;
- break;
- }
+ s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 2);
break;
case MAN_ISSI:
/*
@@ -1141,17 +1160,7 @@ static void decode_qio_read_cmd(Flash *s)
s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
break;
case MAN_MACRONIX:
- switch (extract32(s->volatile_cfg, 6, 2)) {
- case 1:
- s->needed_bytes += 4;
- break;
- case 2:
- s->needed_bytes += 8;
- break;
- default:
- s->needed_bytes += 6;
- break;
- }
+ s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 4);
break;
case MAN_ISSI:
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 28/32] hw/ssi: npcm7xx_fiu: Correct the dummy cycle emulation logic
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (26 preceding siblings ...)
2026-07-07 13:12 ` [PULL 27/32] hw/block: m25p80: Fix dummy byte handling for Macronix flash Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 29/32] hw/ssi: xilinx_spips: Fix dummy phase handling Philippe Mathieu-Daudé
` (5 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bin Meng <bin.meng@processmission.com>
Change send_dummy_bits() to send_dummy_bytes() as the FIU register
fields are programmed from spi_mem_op.dummy.nbytes, so they already
describe byte transfers.
Verified the changes by booting OpenBMC image on `gbs` machine all
the way to the Linux login shell:
$ qemu-system-arm -machine quanta-gbs-bmc -nographic \
-drive file=image.mtd,if=mtd,bus=0,unit=0,format=raw
Fixes: b821242c7b3b ("hw/ssi: NPCM7xx Flash Interface Unit device model")
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Tested-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20260707083431.219671-6-bin.meng@processmission.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/ssi/npcm7xx_fiu.c | 25 ++++++++-----------------
1 file changed, 8 insertions(+), 17 deletions(-)
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
index 2d5bed005ad..d41d877cfbe 100644
--- a/hw/ssi/npcm7xx_fiu.c
+++ b/hw/ssi/npcm7xx_fiu.c
@@ -150,7 +150,7 @@ static uint64_t npcm7xx_fiu_flash_read(void *opaque, hwaddr addr,
NPCM7xxFIUState *fiu = f->fiu;
uint64_t value = 0;
uint32_t drd_cfg;
- int dummy_cycles;
+ int dummy_bytes;
int i;
if (fiu->active_cs != -1) {
@@ -180,10 +180,8 @@ static uint64_t npcm7xx_fiu_flash_read(void *opaque, hwaddr addr,
break;
}
- /* Flash chip model expects one transfer per dummy bit, not byte */
- dummy_cycles =
- (FIU_DRD_CFG_DBW(drd_cfg) * 8) >> FIU_DRD_CFG_ACCTYPE(drd_cfg);
- for (i = 0; i < dummy_cycles; i++) {
+ dummy_bytes = FIU_DRD_CFG_DBW(drd_cfg);
+ for (i = 0; i < dummy_bytes; i++) {
ssi_transfer(fiu->spi, 0);
}
@@ -305,20 +303,13 @@ static void send_address(SSIBus *spi, unsigned int addsiz, uint32_t addr)
}
}
-/* Send the number of dummy bits specified in the UMA config register. */
-static void send_dummy_bits(SSIBus *spi, uint32_t uma_cfg, uint32_t uma_cmd)
+/* Send the number of dummy bytes specified in the UMA config register */
+static void send_dummy_bytes(SSIBus *spi, uint32_t uma_cfg)
{
- unsigned int bits_per_clock = 1U << FIU_UMA_CFG_DBPCK(uma_cfg);
unsigned int i;
for (i = 0; i < FIU_UMA_CFG_DBSIZ(uma_cfg); i++) {
- /* Use bytes 0 and 1 first, then keep repeating byte 2 */
- unsigned int field = (i < 2) ? ((i + 1) * 8) : 24;
- unsigned int j;
-
- for (j = 0; j < 8; j += bits_per_clock) {
- ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock));
- }
+ ssi_transfer(spi, 0);
}
}
@@ -354,8 +345,8 @@ static void npcm7xx_fiu_uma_transaction(NPCM7xxFIUState *s)
ssi_transfer(s->spi, extract32(s->regs[reg], field, 8));
}
- /* Send dummy bits, if present. */
- send_dummy_bits(s->spi, uma_cfg, s->regs[NPCM7XX_FIU_UMA_CMD]);
+ /* Send dummy bytes, if present */
+ send_dummy_bytes(s->spi, uma_cfg);
/* Read data, if present. */
for (i = 0; i < FIU_UMA_CFG_RDATSIZ(uma_cfg); i++) {
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 29/32] hw/ssi: xilinx_spips: Fix dummy phase handling
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (27 preceding siblings ...)
2026-07-07 13:12 ` [PULL 28/32] hw/ssi: npcm7xx_fiu: Correct the dummy cycle emulation logic Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 30/32] hw/ssi: aspeed_smc: Fix direct-read dummy bytes Philippe Mathieu-Daudé
` (4 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bin Meng <bin.meng@processmission.com>
The ZynqMP generic FIFO encodes dummy phases as a number of
dummy cycles. QEMU's SSI bus transfers whole bytes, so the
controller model must convert the programmed cycle count to the
number of SSI byte transfers needed for the selected SPI, dual SPI
or quad SPI mode.
The legacy Xilinx QSPI snoop paths had the opposite problem after
the m25p80 dummy handling was fixed. They still treated each dummy
byte queued through the FIFO as a request to generate several SSI
transfers based on the current link width. The flash model now
consumes dummy phases as byte counts, so the manual FIFO path should
forward one SSI transfer per dummy byte.
Update the Xilinx QSPI dummy accounting consistently for the generic
FIFO, manual FIFO and LQSPI direct-read paths. Also make the command
table report the dummy byte counts consumed by m25p80 for dual and
quad output reads, and account for the mode byte before LQSPI data
reads begin.
This matches the ZynqMP TRM (ug1085, v2.2 [1]) description of the
generic FIFO dummy cycle entry and keeps the controller side aligned
with the flash model's dummy byte ownership.
The description of the generic command fifo register says:
When [receive, transmit, data_xfer] = [0,0,1], the [immediate_data]
field represents the number of dummy cycle sent on the SPI interface.
[1] https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
table 24‐22, an example of Generic FIFO Contents for Quad I/O Read Command (EBh)
Fixes: ef06ca3946e2 ("xilinx_spips: Add support for RX discard and RX drain")
Fixes: c95997a39de6 ("xilinx_spips: Add support for the ZynqMP Generic QSPI")
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Tested-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20260707083431.219671-7-bin.meng@processmission.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/ssi/xilinx_spips.h | 2 +-
hw/ssi/xilinx_spips.c | 123 +++++++++++++++++++++++++---------
2 files changed, 91 insertions(+), 34 deletions(-)
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
index c8f6c5053c4..d1eefa4ba67 100644
--- a/include/hw/ssi/xilinx_spips.h
+++ b/include/hw/ssi/xilinx_spips.h
@@ -69,7 +69,7 @@ struct XilinxSPIPS {
uint8_t num_busses;
uint8_t snoop_state;
- int cmd_dummies;
+ int cmd_dummy_bytes;
uint8_t link_state;
uint8_t link_state_next;
uint8_t link_state_next_when;
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index f6e717bc019..e4fce2c1957 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -192,6 +192,10 @@
FIELD(GQSPI_GF_SNAPSHOT, EXPONENT, 9, 1)
FIELD(GQSPI_GF_SNAPSHOT, DATA_XFER, 8, 1)
FIELD(GQSPI_GF_SNAPSHOT, IMMEDIATE_DATA, 0, 8)
+#define GQSPI_GF_MODE_SPI 1
+#define GQSPI_GF_MODE_DSPI 2
+#define GQSPI_GF_MODE_QSPI 3
+
#define R_GQSPI_MOD_ID (0x1fc / 4)
#define R_GQSPI_MOD_ID_RESET (0x10a0000)
@@ -237,7 +241,7 @@ static void xilinx_spips_update_cs(XilinxSPIPS *s, int field)
}
if (!(field & ((1 << (s->num_cs * s->num_busses)) - 1))) {
s->snoop_state = SNOOP_CHECKING;
- s->cmd_dummies = 0;
+ s->cmd_dummy_bytes = 0;
s->link_state = 1;
s->link_state_next = 1;
s->link_state_next_when = 0;
@@ -382,7 +386,7 @@ static void xilinx_spips_reset(DeviceState *d)
s->link_state_next = 1;
s->link_state_next_when = 0;
s->snoop_state = SNOOP_CHECKING;
- s->cmd_dummies = 0;
+ s->cmd_dummy_bytes = 0;
s->man_start_com = false;
xilinx_spips_update_ixr(s);
xilinx_spips_update_cs_lines(s);
@@ -457,6 +461,7 @@ static void xlnx_zynqmp_qspips_flush_fifo_g(XlnxZynqMPQSPIPS *s)
int i;
if (!s->regs[R_GQSPI_DATA_STS]) {
+ uint32_t prev_gf_snapshot = s->regs[R_GQSPI_GF_SNAPSHOT];
uint8_t imm;
s->regs[R_GQSPI_GF_SNAPSHOT] = fifo32_pop(&s->fifo_g);
@@ -484,7 +489,57 @@ static void xlnx_zynqmp_qspips_flush_fifo_g(XlnxZynqMPQSPIPS *s)
}
s->regs[R_GQSPI_DATA_STS] = 1ul << imm;
} else {
- s->regs[R_GQSPI_DATA_STS] = imm;
+ /*
+ * When [receive, transmit, data_xfer] = [0,0,1], it represents
+ * the number of dummy cycle sent on the SPI interface. We need
+ * to convert the number of dummy cycles to bytes according to
+ * the SPI mode being used.
+ *
+ * Ref: ug1085 v2.2 (December 2020) table 24‐22, an example of
+ * Generic FIFO Contents for Quad I/O Read Command (EBh)
+ */
+ if (!ARRAY_FIELD_EX32(s->regs, GQSPI_GF_SNAPSHOT, TRANSMIT) &&
+ !ARRAY_FIELD_EX32(s->regs, GQSPI_GF_SNAPSHOT, RECIEVE)) {
+ uint8_t spi_mode = ARRAY_FIELD_EX32(s->regs,
+ GQSPI_GF_SNAPSHOT,
+ SPI_MODE);
+ /*
+ * Some ZynqMP GQSPI drivers, such as Linux, use the data
+ * bus width in the dummy GENFIFO entry only to configure
+ * the controller mode. The immediate value is already
+ * the number of dummy cycles for the dummy phase, which
+ * follows the address bus width. Reuse the previous TX
+ * phase mode to convert cycles to SSI bytes.
+ *
+ * This does not make the model Linux-only. U-Boot emits
+ * the dummy entry with op->dummy.buswidth, so the entry
+ * mode already matches the dummy phase. Its opcode and
+ * address phases are immediate entries, not DATA_XFER TX
+ * entries, so the override below is not taken for U-Boot.
+ */
+ if (FIELD_EX32(prev_gf_snapshot, GQSPI_GF_SNAPSHOT,
+ DATA_XFER) &&
+ FIELD_EX32(prev_gf_snapshot, GQSPI_GF_SNAPSHOT,
+ TRANSMIT) &&
+ !FIELD_EX32(prev_gf_snapshot, GQSPI_GF_SNAPSHOT,
+ RECIEVE)) {
+ spi_mode = FIELD_EX32(prev_gf_snapshot,
+ GQSPI_GF_SNAPSHOT, SPI_MODE);
+ }
+
+ if (spi_mode == GQSPI_GF_MODE_QSPI) {
+ s->regs[R_GQSPI_DATA_STS] = ROUND_UP(imm * 4, 8) / 8;
+ } else if (spi_mode == GQSPI_GF_MODE_DSPI) {
+ s->regs[R_GQSPI_DATA_STS] = ROUND_UP(imm * 2, 8) / 8;
+ } else if (spi_mode == GQSPI_GF_MODE_SPI) {
+ s->regs[R_GQSPI_DATA_STS] = ROUND_UP(imm * 1, 8) / 8;
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Unknown SPI MODE: 0x%x ", spi_mode);
+ }
+ } else {
+ s->regs[R_GQSPI_DATA_STS] = imm;
+ }
}
}
/* Zero length transfer check */
@@ -550,7 +605,7 @@ static void xlnx_zynqmp_qspips_flush_fifo_g(XlnxZynqMPQSPIPS *s)
}
}
-static int xilinx_spips_num_dummies(XilinxQSPIPS *qs, uint8_t command)
+static int xilinx_spips_num_dummy_bytes(XilinxQSPIPS *qs, uint8_t command)
{
if (!qs) {
/* The SPI device is not a QSPI device */
@@ -567,10 +622,11 @@ static int xilinx_spips_num_dummies(XilinxQSPIPS *qs, uint8_t command)
case QPP_4:
return 0;
case FAST_READ:
- case DOR:
- case QOR:
case FAST_READ_4:
+ return 1;
+ case DOR:
case DOR_4:
+ case QOR:
case QOR_4:
return 1;
case DIOR:
@@ -611,7 +667,6 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
int i;
uint8_t tx = 0;
uint8_t tx_rx[MAX_NUM_BUSSES] = { 0 };
- uint8_t dummy_cycles = 0;
uint8_t addr_length;
if (fifo8_is_empty(&s->tx_fifo)) {
@@ -631,26 +686,18 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
tx_rx[i] = tx;
}
} else {
- /*
- * Extract a dummy byte and generate dummy cycles according to the
- * link state
- */
tx = fifo8_pop(&s->tx_fifo);
- dummy_cycles = 8 / s->link_state;
+ for (i = 0; i < num_effective_busses(s); ++i) {
+ tx_rx[i] = tx;
+ }
}
for (i = 0; i < num_effective_busses(s); ++i) {
int bus = num_effective_busses(s) - 1 - i;
- if (dummy_cycles) {
- int d;
- for (d = 0; d < dummy_cycles; ++d) {
- tx_rx[0] = ssi_transfer(s->spi[bus], (uint32_t)tx_rx[0]);
- }
- } else {
- DB_PRINT_L(debug_level, "tx = %02x\n", tx_rx[i]);
- tx_rx[i] = ssi_transfer(s->spi[bus], (uint32_t)tx_rx[i]);
- DB_PRINT_L(debug_level, "rx = %02x\n", tx_rx[i]);
- }
+
+ DB_PRINT_L(debug_level, "tx = %02x\n", tx_rx[i]);
+ tx_rx[i] = ssi_transfer(s->spi[bus], (uint32_t)tx_rx[i]);
+ DB_PRINT_L(debug_level, "rx = %02x\n", tx_rx[i]);
}
if (s->regs[R_CMND] & R_CMND_RXFIFO_DRAIN) {
@@ -685,9 +732,9 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
switch (s->snoop_state) {
case (SNOOP_CHECKING):
/* Store the count of dummy bytes in the txfifo */
- s->cmd_dummies = xilinx_spips_num_dummies(q, tx);
+ s->cmd_dummy_bytes = xilinx_spips_num_dummy_bytes(q, tx);
addr_length = get_addr_length(s, tx);
- if (s->cmd_dummies < 0) {
+ if (s->cmd_dummy_bytes < 0) {
s->snoop_state = SNOOP_NONE;
} else {
s->snoop_state = SNOOP_ADDR + addr_length - 1;
@@ -697,14 +744,14 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
case DOR:
case DOR_4:
s->link_state_next = 2;
- s->link_state_next_when = addr_length + s->cmd_dummies;
+ s->link_state_next_when = addr_length + s->cmd_dummy_bytes;
break;
case QPP:
case QPP_4:
case QOR:
case QOR_4:
s->link_state_next = 4;
- s->link_state_next_when = addr_length + s->cmd_dummies;
+ s->link_state_next_when = addr_length + s->cmd_dummy_bytes;
break;
case DIOR:
case DIOR_4:
@@ -720,10 +767,10 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
/*
* Address has been transmitted, transmit dummy cycles now if needed
*/
- if (s->cmd_dummies < 0) {
+ if (s->cmd_dummy_bytes < 0) {
s->snoop_state = SNOOP_NONE;
} else {
- s->snoop_state = s->cmd_dummies;
+ s->snoop_state = s->cmd_dummy_bytes;
}
break;
case (SNOOP_STRIPING):
@@ -1152,11 +1199,13 @@ static void lqspi_load_cache(void *opaque, hwaddr addr)
XilinxQSPIPS *q = opaque;
XilinxSPIPS *s = opaque;
int i;
+ int dummy_bytes;
int flash_addr = ((addr & ~(LQSPI_CACHE_SIZE - 1))
/ num_effective_busses(s));
int peripheral = flash_addr >> LQSPI_ADDRESS_BITS;
int cache_entry = 0;
uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
+ uint8_t command;
if (addr < q->lqspi_cached_addr ||
addr > q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
@@ -1170,10 +1219,10 @@ static void lqspi_load_cache(void *opaque, hwaddr addr)
fifo8_reset(&s->rx_fifo);
/* instruction */
+ command = s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE;
DB_PRINT_L(0, "pushing read instruction: %02x\n",
- (unsigned)(uint8_t)(s->regs[R_LQSPI_CFG] &
- LQSPI_CFG_INST_CODE));
- fifo8_push(&s->tx_fifo, s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE);
+ (unsigned)command);
+ fifo8_push(&s->tx_fifo, command);
/* read address */
DB_PRINT_L(0, "pushing read address %06x\n", flash_addr);
if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_ADDR4) {
@@ -1183,14 +1232,22 @@ static void lqspi_load_cache(void *opaque, hwaddr addr)
fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 8));
fifo8_push(&s->tx_fifo, (uint8_t)flash_addr);
/* mode bits */
+ dummy_bytes = xilinx_spips_num_dummy_bytes(q, command);
if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_MODE_EN) {
fifo8_push(&s->tx_fifo, extract32(s->regs[R_LQSPI_CFG],
LQSPI_CFG_MODE_SHIFT,
LQSPI_CFG_MODE_WIDTH));
+ if (dummy_bytes > 0) {
+ dummy_bytes--;
+ }
+ }
+ if (dummy_bytes < 0) {
+ dummy_bytes = extract32(s->regs[R_LQSPI_CFG],
+ LQSPI_CFG_DUMMY_SHIFT,
+ LQSPI_CFG_DUMMY_WIDTH);
}
/* dummy bytes */
- for (i = 0; i < (extract32(s->regs[R_LQSPI_CFG], LQSPI_CFG_DUMMY_SHIFT,
- LQSPI_CFG_DUMMY_WIDTH)); ++i) {
+ for (i = 0; i < dummy_bytes; ++i) {
DB_PRINT_L(0, "pushing dummy byte\n");
fifo8_push(&s->tx_fifo, 0);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 30/32] hw/ssi: aspeed_smc: Fix direct-read dummy bytes
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (28 preceding siblings ...)
2026-07-07 13:12 ` [PULL 29/32] hw/ssi: xilinx_spips: Fix dummy phase handling Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 31/32] Revert "aspeed/smc: Fix number of dummy cycles for FAST_READ_4 command" Philippe Mathieu-Daudé
` (3 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bin Meng <bin.meng@processmission.com>
m25p80 now consumes fast-read dummy phases as byte counts. The
ASPEED SMC direct-read path still treated the CEx dummy field as
raw cycles and emitted field * 8 SSI transfers. Convert the
ASPEED dummy field to SSI byte transfers using the selected
direct-read data width.
Fixes: ac2810defa9d ("aspeed/smc: handle dummy bytes when doing fast reads in command mode")
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20260707083431.219671-8-bin.meng@processmission.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/ssi/aspeed_smc.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index d87fbd798c6..3f957d153f8 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -449,19 +449,28 @@ static uint32_t aspeed_smc_check_segment_addr(const AspeedSMCFlash *fl,
return addr;
}
-static int aspeed_smc_flash_dummies(const AspeedSMCFlash *fl)
+static int aspeed_smc_flash_dummy_bytes(const AspeedSMCFlash *fl)
{
const AspeedSMCState *s = fl->controller;
uint32_t r_ctrl0 = s->regs[s->r_ctrl0 + fl->cs];
uint32_t dummy_high = (r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1;
uint32_t dummy_low = (r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3;
- uint32_t dummies = ((dummy_high << 2) | dummy_low) * 8;
+ uint32_t dummy_bytes = (dummy_high << 2) | dummy_low;
- if (r_ctrl0 & CTRL_IO_DUAL_ADDR_DATA) {
- dummies /= 2;
+ /*
+ * Scale the controller dummy field to SSI byte transfers using the
+ * direct-read dummy/address bus width.
+ */
+ if ((r_ctrl0 & CTRL_IO_QPI) ||
+ ((r_ctrl0 & CTRL_IO_QUAD_DATA) &&
+ (r_ctrl0 & CTRL_IO_QUAD_ADDR_DATA))) {
+ dummy_bytes *= 4;
+ } else if ((r_ctrl0 & CTRL_IO_DUAL_DATA) &&
+ (r_ctrl0 & CTRL_IO_DUAL_ADDR_DATA)) {
+ dummy_bytes *= 2;
}
- return dummies;
+ return dummy_bytes;
}
static void aspeed_smc_flash_setup(AspeedSMCFlash *fl, uint32_t addr)
@@ -487,7 +496,7 @@ static void aspeed_smc_flash_setup(AspeedSMCFlash *fl, uint32_t addr)
* settings, let's check for fast read mode.
*/
if (aspeed_smc_flash_mode(fl) == CTRL_FREADMODE) {
- for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
+ for (i = 0; i < aspeed_smc_flash_dummy_bytes(fl); i++) {
ssi_transfer(fl->controller->spi, s->regs[R_DUMMY_DATA] & 0xff);
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 31/32] Revert "aspeed/smc: Fix number of dummy cycles for FAST_READ_4 command"
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (29 preceding siblings ...)
2026-07-07 13:12 ` [PULL 30/32] hw/ssi: aspeed_smc: Fix direct-read dummy bytes Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 13:12 ` [PULL 32/32] Revert "aspeed/smc: snoop SPI transfers to fake dummy cycles" Philippe Mathieu-Daudé
` (2 subsequent siblings)
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bin Meng <bin.meng@processmission.com>
This reverts commit 7faf6f1790dddf9f3acf6ddd95f7bbc1b4a755d0.
The incorrect implementation of dummy cycles in m25p80 model is now
corrected. Revert this commit.
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20260707083431.219671-9-bin.meng@processmission.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
hw/ssi/aspeed_smc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 3f957d153f8..58e5087b570 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -568,11 +568,11 @@ static int aspeed_smc_num_dummies(uint8_t command)
case FAST_READ:
case DOR:
case QOR:
- case FAST_READ_4:
case DOR_4:
case QOR_4:
return 1;
case DIOR:
+ case FAST_READ_4:
case DIOR_4:
return 2;
case QIOR:
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PULL 32/32] Revert "aspeed/smc: snoop SPI transfers to fake dummy cycles"
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (30 preceding siblings ...)
2026-07-07 13:12 ` [PULL 31/32] Revert "aspeed/smc: Fix number of dummy cycles for FAST_READ_4 command" Philippe Mathieu-Daudé
@ 2026-07-07 13:12 ` Philippe Mathieu-Daudé
2026-07-07 17:27 ` [PULL 00/32] Misc HW patches for 2026-07-07 Bernhard Beschow
2026-07-10 4:48 ` Stefan Hajnoczi
33 siblings, 0 replies; 36+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-07 13:12 UTC (permalink / raw)
To: qemu-devel
From: Bin Meng <bin.meng@processmission.com>
This reverts commit f95c4bffdc4c53b29f89762cab4adc5a43f95daf.
The m25p80 model now accounts for fast-read dummy bytes in its
command decoder. In ASPEED SMC model user mode, guest software
already sends the complete byte stream, including any dummy
bytes needed by the flash. Hence the model should just forward
exactly the bytes supplied by the guest without the need of
decoding guest-supplied flash op codes to inject extra dummy
transfers.
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Tested-by: Cédric Le Goater <clg@redhat.com>
Message-ID: <20260707083431.219671-10-bin.meng@processmission.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
include/hw/ssi/aspeed_smc.h | 2 -
hw/ssi/aspeed_smc.c | 114 +-----------------------------------
hw/ssi/trace-events | 1 -
3 files changed, 2 insertions(+), 115 deletions(-)
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index 76831422c6f..a273365689e 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -80,8 +80,6 @@ struct AspeedSMCState {
AspeedSMCFlash flashes[ASPEED_SMC_CS_MAX];
- uint8_t snoop_index;
- uint8_t snoop_dummies;
bool unselect;
};
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 58e5087b570..c8cc6cfa56e 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -197,9 +197,6 @@
/* Flash opcodes. */
#define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
-#define SNOOP_OFF 0xFF
-#define SNOOP_START 0x0
-
/*
* Default segments mapping addresses and size for each peripheral per
* controller. These can be changed when board is initialized with the
@@ -537,104 +534,6 @@ static MemTxResult aspeed_smc_flash_read(void *opaque, hwaddr addr,
return MEMTX_OK;
}
-/*
- * TODO (clg@kaod.org): stolen from xilinx_spips.c. Should move to a
- * common include header.
- */
-typedef enum {
- READ = 0x3, READ_4 = 0x13,
- FAST_READ = 0xb, FAST_READ_4 = 0x0c,
- DOR = 0x3b, DOR_4 = 0x3c,
- QOR = 0x6b, QOR_4 = 0x6c,
- DIOR = 0xbb, DIOR_4 = 0xbc,
- QIOR = 0xeb, QIOR_4 = 0xec,
-
- PP = 0x2, PP_4 = 0x12,
- DPP = 0xa2,
- QPP = 0x32, QPP_4 = 0x34,
-} FlashCMD;
-
-static int aspeed_smc_num_dummies(uint8_t command)
-{
- switch (command) { /* check for dummies */
- case READ: /* no dummy bytes/cycles */
- case PP:
- case DPP:
- case QPP:
- case READ_4:
- case PP_4:
- case QPP_4:
- return 0;
- case FAST_READ:
- case DOR:
- case QOR:
- case DOR_4:
- case QOR_4:
- return 1;
- case DIOR:
- case FAST_READ_4:
- case DIOR_4:
- return 2;
- case QIOR:
- case QIOR_4:
- return 4;
- default:
- return -1;
- }
-}
-
-static bool aspeed_smc_do_snoop(AspeedSMCFlash *fl, uint64_t data,
- unsigned size)
-{
- AspeedSMCState *s = fl->controller;
- uint8_t addr_width = aspeed_smc_flash_addr_width(fl);
-
- trace_aspeed_smc_do_snoop(fl->cs, s->snoop_index, s->snoop_dummies,
- (uint8_t) data & 0xff);
-
- if (s->snoop_index == SNOOP_OFF) {
- return false; /* Do nothing */
-
- } else if (s->snoop_index == SNOOP_START) {
- uint8_t cmd = data & 0xff;
- int ndummies = aspeed_smc_num_dummies(cmd);
-
- /*
- * No dummy cycles are expected with the current command. Turn
- * off snooping and let the transfer proceed normally.
- */
- if (ndummies <= 0) {
- s->snoop_index = SNOOP_OFF;
- return false;
- }
-
- s->snoop_dummies = ndummies * 8;
-
- } else if (s->snoop_index >= addr_width + 1) {
-
- /* The SPI transfer has reached the dummy cycles sequence */
- for (; s->snoop_dummies; s->snoop_dummies--) {
- ssi_transfer(s->spi, s->regs[R_DUMMY_DATA] & 0xff);
- }
-
- /* If no more dummy cycles are expected, turn off snooping */
- if (!s->snoop_dummies) {
- s->snoop_index = SNOOP_OFF;
- } else {
- s->snoop_index += size;
- }
-
- /*
- * Dummy cycles have been faked already. Ignore the current
- * SPI transfer
- */
- return true;
- }
-
- s->snoop_index += size;
- return false;
-}
-
static MemTxResult aspeed_smc_flash_write(void *opaque, hwaddr addr,
uint64_t data, unsigned size, MemTxAttrs attrs)
{
@@ -652,10 +551,6 @@ static MemTxResult aspeed_smc_flash_write(void *opaque, hwaddr addr,
switch (aspeed_smc_flash_mode(fl)) {
case CTRL_USERMODE:
- if (aspeed_smc_do_snoop(fl, data, size)) {
- break;
- }
-
for (i = 0; i < size; i++) {
ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
}
@@ -717,7 +612,6 @@ static void aspeed_smc_flash_update_ctrl(AspeedSMCFlash *fl, uint32_t value)
s->regs[s->r_ctrl0 + fl->cs] = value;
if (unselect != s->unselect) {
- s->snoop_index = unselect ? SNOOP_OFF : SNOOP_START;
aspeed_smc_flash_do_select(fl, unselect);
}
}
@@ -763,9 +657,6 @@ static void aspeed_smc_reset_hold(Object *obj, ResetType type)
aspeed_smc_flash_set_segment_region(s, i,
asc->segment_to_reg(s, &asc->segments[i]));
}
-
- s->snoop_index = SNOOP_OFF;
- s->snoop_dummies = 0;
}
static MemTxResult aspeed_smc_read(void *opaque, hwaddr addr, uint64_t *data,
@@ -1293,11 +1184,10 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
static const VMStateDescription vmstate_aspeed_smc = {
.name = "aspeed.smc",
.version_id = 3,
- .minimum_version_id = 2,
+ .minimum_version_id = 1,
.fields = (const VMStateField[]) {
VMSTATE_UINT32_ARRAY(regs, AspeedSMCState, ASPEED_SMC_R_MAX),
- VMSTATE_UINT8(snoop_index, AspeedSMCState),
- VMSTATE_UINT8(snoop_dummies, AspeedSMCState),
+ VMSTATE_UNUSED_V(2, 2), /* was snoop_index/snoop_dummies */
VMSTATE_BOOL_V(unselect, AspeedSMCState, 3),
VMSTATE_END_OF_LIST()
}
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
index 2f36cf96b8b..b9d86482974 100644
--- a/hw/ssi/trace-events
+++ b/hw/ssi/trace-events
@@ -2,7 +2,6 @@
aspeed_smc_flash_set_segment(int cs, uint64_t reg, uint64_t start, uint64_t end) "CS%d segreg=0x%"PRIx64" [ 0x%"PRIx64" - 0x%"PRIx64" ]"
aspeed_smc_flash_read(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
-aspeed_smc_do_snoop(int cs, int index, int dummies, int data) "CS%d index:0x%x dummies:%d data:0x%x"
aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
--
2.53.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* Re: [PULL 00/32] Misc HW patches for 2026-07-07
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (31 preceding siblings ...)
2026-07-07 13:12 ` [PULL 32/32] Revert "aspeed/smc: snoop SPI transfers to fake dummy cycles" Philippe Mathieu-Daudé
@ 2026-07-07 17:27 ` Bernhard Beschow
2026-07-10 4:48 ` Stefan Hajnoczi
33 siblings, 0 replies; 36+ messages in thread
From: Bernhard Beschow @ 2026-07-07 17:27 UTC (permalink / raw)
To: qemu-devel, Philippe Mathieu-Daudé
Am 7. Juli 2026 13:11:50 UTC schrieb "Philippe Mathieu-Daudé" <philmd@oss.qualcomm.com>:
>The following changes since commit 94826ec1370328375c3b6d1e80fdc94c8f46c348:
>
> Merge tag 'accel-20260706' of https://github.com/philmd/qemu into staging (2026-07-06 18:38:14 +0200)
>
>are available in the Git repository at:
>
> https://github.com/philmd/qemu.git tags/hw-misc-20260707
>
>for you to fetch changes up to 04584a27dd59741bc20272c6faab96c08bcbb926:
>
> Revert "aspeed/smc: snoop SPI transfers to fake dummy cycles" (2026-07-07 15:08:41 +0200)
>
>----------------------------------------------------------------
>Misc HW patches
>
>- Fix in few trace event formats
>- A pair of improvements in util/
>- FlexCAN3 to imx8mp-evk board
>- Various fixes in hw/
> (EDU, ATI VGA, IDE AHCI, PCA9552, i8257 DMA,
> e1000e/igb, MPT SAS, Hyper-V, QXL, M25P80)
>----------------------------------------------------------------
>
>BALATON Zoltan (1):
> hw/display/ati: Include vga state in the blit context
>
>Bernhard Beschow (5):
> hw/net/can/flexcan: Wire clock control module via link property
> hw/net/can/flexcan: Subclass TYPE_CAN_FLEXCAN
> hw/arm/imx8mp-evk: Open code DEFINE_MACHINE_AARCH64
> hw/arm/imx8mp-evk: Introduce FslImx8mpEvkState
> hw/arm: Add basic FlexCAN3 support to TYPE_FSL_IMX8MP and imx8mp-evk
Thanks Phil! I owe you two beer (another one for the rs5c372). Or whatever liquid you like.
Best,
Bernhard
>
>Bin Meng (8):
> hw/block: m25p80: Fix dummy byte handling for Winbond flash
> hw/block: m25p80: Fix dummy byte handling for Numonyx/Micron flash
> hw/block: m25p80: Fix dummy byte handling for Macronix flash
> hw/ssi: npcm7xx_fiu: Correct the dummy cycle emulation logic
> hw/ssi: xilinx_spips: Fix dummy phase handling
> hw/ssi: aspeed_smc: Fix direct-read dummy bytes
> Revert "aspeed/smc: Fix number of dummy cycles for FAST_READ_4
> command"
> Revert "aspeed/smc: snoop SPI transfers to fake dummy cycles"
>
>Denis V. Lunev (1):
> hw/ide/ahci: cancel in-flight buffered reads on command engine restart
>
>Dmitry Frolov (1):
> utils/module: fix memleak in module_load()
>
>Evgeny Kolmakov (1):
> util/filemonitor-inotify: Use QEMU_LOCK_GUARD()
>
>Junjie Cao (2):
> hw/display/ati: reset host_data.next in write handler after flush
> hw/display/ati: guard against zero bpp in ati_host_data_flush
>
>Mark Cave-Ayland (2):
> hw/rtc/mc146818rtc: convert date from object prop to class prop
> hw/acpi/ich9: move initial property values into
> ich9_reset_properties()
>
>Peter Maydell (3):
> hw/dma/i8257: Return zeroes for read_memory in verify mode
> hw/scsi/mptsas: Reset doorbell state on reset
> hw/hyperv: Avoid crash if hyperv_find_cpu() passed invalid vp_index
>
>Sanjeeva Yerrapureddy (1):
> hw/net: fix e1000e/igb ip_len inflation by Ethernet minimum-frame
> padding
>
>Shameer Kolothum (1):
> backends/iommufd: Fix dev_id and type order in viommu trace
>
>Song Gao (1):
> hw/intc/loongarch_dintc: Fix OOB access in DINT MMIO write handler
>
>Thomas Huth (1):
> hw/display/qxl: Fix mono cursor validation that can read past a cursor
> chunk
>
>Torin Carey (1):
> hw/misc/edu: restrict dma access to dma buffer
>
>yujun (3):
> hw/gpio/pca9552: fix off-by-one in QOM led index validation
> ebpf: fix swapped toeplitz/indirection args in set_data trace
> crypto/x509-utils: fix gnutls error code in crt_init failure path
>
> docs/system/arm/imx8m.rst | 1 +
> include/hw/acpi/ich9.h | 2 +
> include/hw/arm/fsl-imx8mp.h | 8 ++
> include/hw/net/flexcan.h | 4 +-
> include/hw/ssi/aspeed_smc.h | 2 -
> include/hw/ssi/xilinx_spips.h | 2 +-
> crypto/x509-utils.c | 3 +-
> ebpf/ebpf_rss.c | 2 +-
> hw/acpi/ich9.c | 8 +-
> hw/arm/fsl-imx6.c | 5 +-
> hw/arm/fsl-imx8mp.c | 38 ++++++++++
> hw/arm/imx8mp-evk.c | 64 +++++++++++++---
> hw/block/m25p80.c | 122 +++++++++++++++++++-----------
> hw/display/ati.c | 2 +
> hw/display/ati_2d.c | 44 +++++------
> hw/display/qxl-render.c | 8 +-
> hw/dma/i8257.c | 13 ++++
> hw/gpio/pca9552.c | 8 +-
> hw/hyperv/hyperv.c | 4 +-
> hw/ide/ahci.c | 3 +
> hw/intc/loongarch_dintc.c | 13 ++++
> hw/isa/lpc_ich9.c | 1 +
> hw/misc/edu.c | 24 +++---
> hw/misc/imx8mp_ccm.c | 3 +
> hw/net/can/flexcan.c | 90 ++++++++++++++++++-----
> hw/net/net_tx_pkt.c | 7 +-
> hw/rtc/mc146818rtc.c | 4 +-
> hw/scsi/mptsas.c | 4 +
> hw/ssi/aspeed_smc.c | 135 +++++-----------------------------
> hw/ssi/npcm7xx_fiu.c | 25 ++-----
> hw/ssi/xilinx_spips.c | 123 ++++++++++++++++++++++---------
> util/filemonitor-inotify.c | 28 ++-----
> util/module.c | 2 +-
> backends/trace-events | 2 +-
> hw/arm/Kconfig | 1 +
> hw/ssi/trace-events | 1 -
> 36 files changed, 488 insertions(+), 318 deletions(-)
>
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PULL 00/32] Misc HW patches for 2026-07-07
2026-07-07 13:11 [PULL 00/32] Misc HW patches for 2026-07-07 Philippe Mathieu-Daudé
` (32 preceding siblings ...)
2026-07-07 17:27 ` [PULL 00/32] Misc HW patches for 2026-07-07 Bernhard Beschow
@ 2026-07-10 4:48 ` Stefan Hajnoczi
33 siblings, 0 replies; 36+ messages in thread
From: Stefan Hajnoczi @ 2026-07-10 4:48 UTC (permalink / raw)
To: Philippe Mathieu-Daudé; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/11.1 for any user-visible changes.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread