Commit graph

132285 commits

Author SHA1 Message Date
Richard Henderson
324bb5ef83 IDE patches
- fix the logical CHS translation a guest selects with INITIALIZE
   DEVICE PARAMETERS: reject a translation the device may not accept
   instead of dying on a division by zero, report the default
   translation in IDENTIFY DEVICE words 1, 3 and 6 and the one in
   effect in words 54 to 58, keep those words in sync when the
   translation changes, migrate both the translation and the SET
   FEATURES 0xCC revert flag, and return the power-on defaults on a
   hardware reset rather than on every reset
 - harden the IDE and AHCI state a guest or an incoming migration
   stream can reach: reject an out-of-range PIO transfer window on
   load, refuse a PIO transfer with no command header, clear cur_cmd
   when the command list is unmapped, treat a failed PRDT walk as a
   transfer failure, reject a command header with an invalid FIS
   length, and drain the ports on teardown so that a request cannot
   outlive an unplug
 - report ATAPI UDMA5 with a matching standard and cable
 - extend the IDE/AHCI qtest coverage for all of the above
 
 Signed-off-by: Denis V. Lunev <den@openvz.org>
 CC: Stefan Hajnoczi <stefanha@redhat.com>
 CC: John Snow <jsnow@redhat.com>
 CC: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQJDBAABCgAtFiEEC66qh9MCCtwRUOUfXgdxtstmbKsFAmqOyM4PHGRlbkBvcGVu
 dnoub3JnAAoJEF4HcbbLZmyrGSUP+wR5KLZXUCKwEXDM95UnUiDFQQUNO0Ko7XGv
 v8hHnTWRb3pvkIh/lJ9ECWPw0NPRKjugkSm9IGDUCndgw6+AbPOTP+tfJXFNK965
 NFisLDoJCcPrrFNCL+T6EQyPBI2GG1vl9t4bg75GeT55WTUiK4Cv0710COZMV3kc
 RlN3LzxCKLqc1wSGcqOLyObKTw97vL5pmB/xcOn/ciN1vOm4d5jgzvs1NqFcO1CF
 btlqGisG9aRlqecKRgKGeLCGXtUoYq0MBuddsMeDSLD/H4FeZ1W0qYb/e2Zv97Bn
 pdAyKb7Fs6OXV77qSUU5N1tSzALG+mn92BegHoyvuK/YRc8eDdwsiB8+OE7XHRbZ
 Atewt2CVfej+lyZH5LHe72esWrNqpcHSwvTpvP26oxJq3qwUXynKh8VqUnnIwEIa
 i1Y7ATnIGXNd1+w68Gk0TDu2zByUPVi4dw91hQR80YY2L9ZWwN5N2u3WCo81ZpAs
 8hFk44vCAtGtfRZdLPbIboMfVLExRiBIwfNxJNy7btYQLWkvI05s8K5OmyBXeCwh
 rtMQi9745BGcMVCtTIAiUjO/EHEkGtFaAs3JUdN/bdx2lzr6l8jpoofqr6rlZT2k
 R3VNa+r5iw0B/otn/2AEAN6alZpQt6RInenY6LXQlfwCKREWAbD41o3VgfWZVn3P
 VNrAjpDO
 =8aHT
 -----END PGP SIGNATURE-----

Merge tag 'pull-ide-2026-08-26' of https://gitlab.com/dlunev/qemu into staging

IDE patches

- fix the logical CHS translation a guest selects with INITIALIZE
  DEVICE PARAMETERS: reject a translation the device may not accept
  instead of dying on a division by zero, report the default
  translation in IDENTIFY DEVICE words 1, 3 and 6 and the one in
  effect in words 54 to 58, keep those words in sync when the
  translation changes, migrate both the translation and the SET
  FEATURES 0xCC revert flag, and return the power-on defaults on a
  hardware reset rather than on every reset
- harden the IDE and AHCI state a guest or an incoming migration
  stream can reach: reject an out-of-range PIO transfer window on
  load, refuse a PIO transfer with no command header, clear cur_cmd
  when the command list is unmapped, treat a failed PRDT walk as a
  transfer failure, reject a command header with an invalid FIS
  length, and drain the ports on teardown so that a request cannot
  outlive an unplug
- report ATAPI UDMA5 with a matching standard and cable
- extend the IDE/AHCI qtest coverage for all of the above

Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: John Snow <jsnow@redhat.com>
CC: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

# -----BEGIN PGP SIGNATURE-----
#
# iQJDBAABCgAtFiEEC66qh9MCCtwRUOUfXgdxtstmbKsFAmqOyM4PHGRlbkBvcGVu
# dnoub3JnAAoJEF4HcbbLZmyrGSUP+wR5KLZXUCKwEXDM95UnUiDFQQUNO0Ko7XGv
# v8hHnTWRb3pvkIh/lJ9ECWPw0NPRKjugkSm9IGDUCndgw6+AbPOTP+tfJXFNK965
# NFisLDoJCcPrrFNCL+T6EQyPBI2GG1vl9t4bg75GeT55WTUiK4Cv0710COZMV3kc
# RlN3LzxCKLqc1wSGcqOLyObKTw97vL5pmB/xcOn/ciN1vOm4d5jgzvs1NqFcO1CF
# btlqGisG9aRlqecKRgKGeLCGXtUoYq0MBuddsMeDSLD/H4FeZ1W0qYb/e2Zv97Bn
# pdAyKb7Fs6OXV77qSUU5N1tSzALG+mn92BegHoyvuK/YRc8eDdwsiB8+OE7XHRbZ
# Atewt2CVfej+lyZH5LHe72esWrNqpcHSwvTpvP26oxJq3qwUXynKh8VqUnnIwEIa
# i1Y7ATnIGXNd1+w68Gk0TDu2zByUPVi4dw91hQR80YY2L9ZWwN5N2u3WCo81ZpAs
# 8hFk44vCAtGtfRZdLPbIboMfVLExRiBIwfNxJNy7btYQLWkvI05s8K5OmyBXeCwh
# rtMQi9745BGcMVCtTIAiUjO/EHEkGtFaAs3JUdN/bdx2lzr6l8jpoofqr6rlZT2k
# R3VNa+r5iw0B/otn/2AEAN6alZpQt6RInenY6LXQlfwCKREWAbD41o3VgfWZVn3P
# VNrAjpDO
# =8aHT
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 26 Aug 2026 04:06:54 AM PDT
# gpg:                using RSA key 0BAEAA87D3020ADC1150E51F5E0771B6CB666CAB
# gpg:                issuer "den@openvz.org"
# gpg: Good signature from "Denis V. Lunev <den@openvz.org>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 0BAE AA87 D302 0ADC 1150  E51F 5E07 71B6 CB66 6CAB

* tag 'pull-ide-2026-08-26' of https://gitlab.com/dlunev/qemu: (28 commits)
  tests/qtest/ide-test: cover the UDMA5 identify words
  hw/ide: report ATAPI UDMA5 with a matching standard and cable
  tests/qtest/ahci: regression test for a request outliving an unplug
  hw/ide/ahci: drain the ports on teardown
  hw/ide/ahci: reject a command header with an invalid FIS length
  hw/ide/ahci: treat a failed PRDT walk as a PIO transfer failure
  tests/qtest/ahci: regression test for a PIO write vs. engine stop
  hw/ide/ahci: clear cur_cmd when the command list is unmapped
  hw/ide/ahci: refuse a PIO transfer with no command header
  tests/qtest/ide-test: cover the migrated PIO transfer window
  hw/ide: reject an out-of-range PIO transfer window on load
  hw/ide: drop a redundant interrupt from INITIALIZE DEVICE PARAMETERS
  tests/qtest/ide-test: cover the CHS translation across resets
  hw/ide: revert the CHS translation on a hardware reset
  tests/qtest/ide-test: cover the IDENTIFY DEVICE geometry words
  tests/qtest/ide-test: cover a rejected CHS translation in the stream
  tests/qtest/ide-test: cover the CHS translation across migration
  hw/ide: migrate the power-on defaults revert flag
  hw/ide: migrate the logical CHS translation
  hw/ide: restore the power-on device state before loading
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2026-08-26 11:26:47 -07:00
Denis V. Lunev
dd90d3cd73 tests/qtest/ide-test: cover the UDMA5 identify words
/ide/identify/udma and /ide/identify/udma_atapi check that a device
advertising UDMA mode 5 claims a standard that defines it and reports the
hardware reset result, on the disk and on the CD-ROM. The ATAPI case also
checks that the words obsolete in IDENTIFY PACKET DEVICE data stay
clear, and that the reset result reports a passed diagnostic, which
only the packet path does so far.

Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
60faaa8c3b hw/ide: report ATAPI UDMA5 with a matching standard and cable
IDENTIFY PACKET DEVICE claims UDMA mode 5 in word 88 while word 80
reports support only up to ATA/ATAPI-4. UDMA5 first appears in
ATA/ATAPI-6; ATA/ATAPI-5 stops at mode 4. Bits 3:1 of word 80 are
obsolete in IDENTIFY PACKET DEVICE data as well, so the old 001eh
claimed three standards that mean nothing for a packet device. Report
0070h, ATA/ATAPI-4 through ATA/ATAPI-6.

Word 93 was left unset, so nothing reported the 80-conductor cable that
UDMA5 needs. Fill it in, but only for a parallel attachment: ACS-3
7.13.6.41 gives word 93 of IDENTIFY PACKET DEVICE data the meaning of
word 93 of IDENTIFY DEVICE data, where "For SATA devices, word 93 shall
be set to the value 0000h". A cleared ncq_queues is how both identify
paths already tell a parallel attachment from an AHCI one.

The device 0 reset result is 0fh rather than the 01h ide_identify()
reports: bit 3 says diagnostics passed, which they did, and bits 2:1
say the device number came from some other method, the only one of the
four encodings that is not a jumper, CSEL or reserved.

Raising word 80 has a second effect. Linux decides a device is SATA in
ata_id_is_sata(), which wants word 93 clear and word 80 at ATA/ATAPI-5
or later. An AHCI CD-ROM satisfied neither condition before and was
taken for a parallel device; now it satisfies both.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4038
Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
0b7cc42531 tests/qtest/ahci: regression test for a request outliving an unplug
Add /ahci/io/{ncq,dma,pio}/unplug: arm a read against a null-co backend
whose latency keeps it in flight, then eject the controller through the
ACPI ejection register. Each of the three reaches the freed AHCIDevice
array by a different route, so covering one command class would leave
the other two untested.

That register is what a guest writes to finish a PCI unplug, and unlike
the pciehp attention button it reaches ahci_uninit() with no secondary
bus reset, so nothing cancels the request on the way. It also dictates
the machine: q35 has no ACPI hotplug on pcie.0, so the eject has no
effect there.

The latency is what holds the request; a blkdebug breakpoint cannot
stand in for it, because cancelling a suspended request waits for it and
the unplug would never return.

Unfixed, all three fail reliably under AddressSanitizer. On a plain build
the use-after-free only faults when the freed page has been returned, so
expect the odd pass there.

Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
5bdc12fed5 hw/ide/ahci: drain the ports on teardown
ahci_uninit() frees s->dev without touching the requests still in flight.
The only blk_aio_cancel() for them lives in ahci_reset_port(), which the
unplug path does not run, and the ide-hd child's own drain is deferred
through call_rcu so it happens after the free. A guest that powers the
root port slot off through SLTCTL, or writes the ACPI ejection register,
while a read is outstanding therefore leaves the completion to run
against freed memory.

A plain device_del is not affected: the pciehp attention-button flow
resets the secondary bus first, which cancels through the reset path.
Surprise removal is what skips it.

Cancelling the NCQ requests alone is not enough. IDEDMA and IDEBus are
embedded in AHCIDevice, so a plain DMA read reaches the freed array
through dma_blk_cb() and a PIO read through ide_buffered_readv_cb(),
neither of which the NCQ bookkeeping covers. ide_exit() drains nothing
and frees io_buffer, which an outstanding request may still target.

Move the NCQ cancel loop into a helper, run it from ahci_uninit() too,
and drain each port before ide_exit() so no class of request can outlive
the allocation. Delete check_bh there as well; qemu_bh_new_guarded() in
check_cmd() has no counterpart on this path either.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4069
Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
795af987ce hw/ide/ahci: reject a command header with an invalid FIS length
AHCI 1.3.1 defines CFL in the command header as the "Length of the
Command FIS", where "A length of '0' or '1' is illegal" and "The
maximum value allowed is 10h, or 16 DW". handle_cmd() never looks at
it, so an all-zero command header is executable: its zero tbl_addr maps
a command table at guest physical address 0, and a guest that has put a
valid Register H2D FIS there gets it run.

That is the reachability a guest gains by pointing PxCLB at an MMIO
region, where the CLB is a zero-filled bounce buffer rather than
anything the guest wrote.

Reject a header whose CFL falls outside the legal range. Nothing else
consults it; the command FIS is always mapped at its full 128 bytes.

The slot is dropped without reporting anything, as the unmappable
command table beside it already is. No PxIS bit describes a malformed
command header: HBFS is for a host bus error, "such as a bad software
pointer", which is why the short mapping below raises it and this does
not.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4043
Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
2713717148 hw/ide/ahci: treat a failed PRDT walk as a PIO transfer failure
ahci_dma_prepare_buf() returns -1 when it cannot build a scatter-gather
list, the PRDTL of zero case among them. ahci_pio_transfer() tests the
result for truth, so a failure sets has_sglist and the transfer goes
ahead against whatever s->sg holds. AHCI 1.3.1 is explicit about the
zero case: "If this field is '0', then no data transfer shall occur
with the command."

Test for a positive byte count instead. A successful walk that yields
nothing to transfer is already handled by the size check below.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4043
Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
d05ae87e7a tests/qtest/ahci: regression test for a PIO write vs. engine stop
Add /ahci/io/pio/engine_stop: hold the backend write of a two-sector
PIO write with a blkdebug breakpoint, clear PxCMD.ST so the command
list is unmapped underneath it, then let the write complete. The
second DRQ phase runs from that completion and reaches
ahci_pio_transfer() with no command header.

Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
a2fbf1785b hw/ide/ahci: clear cur_cmd when the command list is unmapped
ahci_unmap_clb_address() drops the CLB mapping but leaves cur_cmd
pointing into it. The cancel added by commit d9f78431d8 covers the
buffered reads, and ide_cancel_dma_sync() drains bus->dma->aiocb, but
neither reaches IDEState::pio_aiocb: a PIO write started before the
guest cleared PxCMD.ST completes afterwards and runs its second DRQ
phase against the stale header.

That is harmless while the CLB is direct RAM, because unmapping it
changes nothing. It is a use-after-free once PxCLB points at an MMIO
region, where address_space_map() hands out a bounce buffer that
dma_memory_unmap() then frees.

Clear cur_cmd after the cancel, so nothing reachable from a later
completion still refers to the freed mapping.

Reported-by: Katherine Leaver <katherine.j.leaver@gmail.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3719
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4043
Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
d7f16bad8f hw/ide/ahci: refuse a PIO transfer with no command header
ahci_map_clb_address() already clears cur_cmd, so every consumer of it
has to cope with there being no current command. ahci_pio_transfer(),
ahci_commit_buf() and ahci_populate_sglist() all dereference it
unconditionally instead.

Give the three of them a NULL check. Declaring the data transferred
anyway is not enough: ide_transfer_start() goes on to call the end
transfer function, and for a multi-sector write that is
ide_sector_write(), which commits an io_buffer the guest never
refilled. Clearing PxCMD.ST during a WRITE SECTOR(S) of two sectors
therefore writes the first sector's contents over the second, at a
sector the guest chose.

Let pio_transfer report that nothing was transferred and halt there, so
no callback acts on a buffer that was never filled. Only the AHCI HBA
implements the callback, so the signature change is local to it.

Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
e46245cd3b tests/qtest/ide-test: cover the migrated PIO transfer window
/ide/migration/pio_state_rejected leaves a drive in DRQ so the source
streams ide_drive/pio_state, rewrites cur_io_buffer_offset to the end of
the io_buffer, and expects the destination to refuse the load.

It asserts the window the source wrote before overwriting it, so a wrong
guess at the stream layout fails the test rather than passing it for the
wrong reason.

Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
1332990194 hw/ide: reject an out-of-range PIO transfer window on load
ide_drive_pio_post_load() validates end_transfer_fn_idx but takes
cur_io_buffer_offset and cur_io_buffer_len straight from the migration
stream, so data_ptr and data_end can be placed anywhere within +-2GB of
the 131076-byte io_buffer allocation. Both fields are signed 32-bit.

The subsection loader consumes every subsection present in the stream
without consulting needed(), so a crafted stream can inject
ide_drive/pio_state for a drive that was never in a DRQ state. Once
data_end is out of bounds, ide_data_writew() only compares the guest's
pointer against that same bogus data_end, and the resumed guest turns a
repeated outw to the data port into a controlled 16-bit heap write.
end_transfer_fn_idx picks the direction, so the read side of the same
code path leaks host heap instead.

Validate the window against io_buffer_total_len and fail the load. The
subtraction form avoids overflowing the addition.

Reported-by: XlabAI Team of Tencent Xuanwu Lab <xlabai@tencent.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4179
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3738
Cc: John Snow <jsnow@redhat.com>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
e8a3b42ae5 hw/ide: drop a redundant interrupt from INITIALIZE DEVICE PARAMETERS
ide_bus_exec_cmd() raises the interrupt for every command handler that
reports the command complete, which cmd_specify() does, so the request it
raised itself was the first of two. The one from ide_bus_exec_cmd() is the
one that belongs there, being raised after BSY is cleared and after
ide_cmd_done() has let the bus master post its own completion.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
d1634ae78d tests/qtest/ide-test: cover the CHS translation across resets
A translation the guest selected has to survive a software reset and not a
hardware one, and the two arrive at the same ide_reset(), so a fix for
either direction can break the other. Select a translation, put the drive
through a software reset and then through a machine reset, and name the
sector each translation picks along the way.

The marker read says which translation the device is addressing the disk
with, while IDENTIFY DEVICE words 55 and 56 say which one it reports. The
machine reset leaves the PCI command register cleared, so the device has
to be enabled again before the ports answer.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
cafb3d9625 hw/ide: revert the CHS translation on a hardware reset
A power on or hardware reset returns the device parameters to their
power-on defaults (ATA-5 9.1). A software reset keeps them unless the
guest asked with SET FEATURES 0xCC for the next reset to revert (ATA-5 9.2
and 8.16.6). ide_reset() applied the second rule to every reset, so a
translation a guest selected outlived the reset of the machine it selected
it on, and the guest that came up next addressed the disk through a
geometry it never asked for.

Neither ide_reset() nor, for AHCI, ide_bus_reset() could tell the two
apart: a guest clearing SRST in the second host to device FIS of the
software reset protocol lands in the same ahci_reset_port() as a COMRESET
or a reset of the host adapter. Pass the kind down from the callers, which
do know.

ide_drive_pre_load() stays necessary: it restores the same fields, but a
vmstate cannot depend on its device having been reset first.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Fixes: 176e4961bb ("hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command")
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
0720913323 tests/qtest/ide-test: cover the IDENTIFY DEVICE geometry words
INITIALIZE DEVICE PARAMETERS has to leave the geometry the drive came with
in words 3 and 6 and describe the translation it selected in words 54 to
58, and the data is cached, so which of the two a guest is told depends on
when it first asked. Cover both orders, as each alone leaves half of it
untested: one test has the data built while the default is in effect and
then replaces the translation, which the cached copy has to follow, the
other replaces it before the first IDENTIFY DEVICE, where the words
describing the default have to keep doing so.

Factor the reading of the data out of test_specify_zero_sectors() for the
three of them to share.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
5be90dfbc0 tests/qtest/ide-test: cover a rejected CHS translation in the stream
ide_drive_post_load() refuses a logical CHS translation that no command
could have selected, as the fields are a divisor in ide_set_sector() and a
factor in ide_get_sector(). Nothing exercised that, a fixed QEMU having no
way to produce such a stream.

Migrate a guest that selected a translation to a file, replace the number
of sectors per logical track in the subsection with a zero, and let a
destination read the result back. The load has to fail rather than take
the value, so the destination is asked not to exit on a failed incoming
migration and its migration status is what the test looks at.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
ef64d2758e tests/qtest/ide-test: cover the CHS translation across migration
Both defects here are silent: the guest addresses the disk in the
translation it selected while the device translates with another, so reads
and writes land on a sector nobody asked for. Put a marker in each of the
two candidate sectors and name the one the translation picked. CHS 0/1/1
is LBA 32 under 8 heads and 32 sectors per track and LBA 63 under the
16/63 the test drive is configured with; both markers are written by LBA,
which no translation can influence.

A translation the guest selected has to survive migration, and one it
selected after a snapshot was taken must not outlive loading that snapshot
back. The second needs a qcow2 image, so it is skipped without qemu-img.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
67a6d29c28 hw/ide: migrate the power-on defaults revert flag
SET FEATURES 0xCC asks for the next reset to revert to the power-on
defaults, and 0x66 cancels that; ide_reset() restores the default CHS
translation only when the flag is set. It was in no VMStateDescription, so
it always arrived cleared.

That was invisible while the destination had the default translation
anyway. Now that the translation is migrated, the flag decides how long it
stays in effect: without it, a reset after the migration reverts the
geometry on the source and keeps it on the destination.

Send it only alongside a translation the guest replaced. On the default
geometry it reverts to what is already in effect, so such a guest need not
lose its migration to an older QEMU over a subsection that changes
nothing.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Fixes: 176e4961bb ("hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command")
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
ba4a996631 hw/ide: migrate the logical CHS translation
INITIALIZE DEVICE PARAMETERS lets a guest replace the logical CHS
translation used to turn the CHS registers into an LBA, but s->heads and
s->sectors were in no VMStateDescription. The destination rebuilt them
from the drive configuration, so a guest that had selected one of its own
kept addressing the disk in it while the device translated with the
default, landing on sectors nobody asked for.

Add a subsection for it, sent only when the guest replaced the default, so
that migration to an older QEMU keeps working for every other guest.
s->cylinders is left out, as no command changes it.

Validate what is loaded in the existing post_load: ide_get_sector()
multiplies by these fields and ide_set_sector() divides by them.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Fixes: 176e4961bb ("hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command")
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
33db64cf28 hw/ide: restore the power-on device state before loading
Loading a snapshot reuses the IDEState of the machine it is loaded into:
load_snapshot() resets the machine and then feeds the stream into the
existing devices. The reset does not help, as ide_reset() restores the
logical CHS translation only when the guest asked for power-on defaults to
be reverted with SET FEATURES 0xCC.

A guest that replaced the translation with INITIALIZE DEVICE PARAMETERS
therefore keeps it across the load of a snapshot taken before it did,
while the restored guest expects the geometry of that moment. Every CHS
access then lands on a sector other than the one asked for, with no error
reported. s->reset_reverts survives a load the same way.

Add a pre_load restoring the defaults, which
docs/devel/migration/main.rst recommends for state a stream need not
carry, and which the following subsections rely on. The
RESET_TYPE_SNAPSHOT_LOAD marking that reset would be another way to
recognise the case, but no IDE controller can see it while they all use
device_class_set_legacy_reset().

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Fixes: 176e4961bb ("hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command")
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
b5542796b3 hw/ide: keep the IDENTIFY DEVICE current geometry in sync
Bit 0 of IDENTIFY DEVICE word 53 says that words 54 to 58 describe the CHS
translation in effect, and ATA-5 8.16.8 has INITIALIZE DEVICE PARAMETERS
set words 55 and 56 to the heads and sectors per track it was given. The
data is built once and then cached, so those words kept describing
whatever was in effect when a guest first asked for IDENTIFY DEVICE: the
device reported one geometry while addressing the medium with another, and
nothing reported an error. The revert SET FEATURES 0xCC asks for on the
next reset left the same disagreement.

Do not drop the cached data on a change, as parts of it are guest state
rather than a description of the drive: SET FEATURES records the write
cache setting in word 85, which ide_drive_post_load() reads back after
migration. Refresh the affected words in place instead, the way
ide_identify_size() does for the capacity words.

An ATAPI device has no translation but does take SET FEATURES 0xCC, so
leave its IDENTIFY PACKET DEVICE data alone, where those words differ.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Fixes: 176e4961bb ("hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command")
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
747679ca59 hw/ide: factor out the IDENTIFY DEVICE current geometry words
Words 54 to 58 of IDENTIFY DEVICE describe the CHS translation in effect
and the capacity it addresses. Both ide_identify() and
ide_cfata_identify() fill them the same way while building their cached
data.

Move them into ide_identify_chs(), so that the next change can refresh
them in place once the translation changes, the way ide_identify_size()
does for the capacity words.

No functional change.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
adf1152b34 hw/ide: name the retired IDENTIFY DEVICE words the device fills in
Words 4, 5 and 20 have carried an "XXX: retired, remove ?" since the
device was written, and word 21 is labelled a cache size when it is a
buffer size. ATA-4 8.12.13 retired words 4 and 5, 8.12.17 retired words
20 and 21, and ATA-5 keeps all four that way.

Retired is not a reason to drop them. ATA-5 3.2.3.6 says a retired word
that is still used shall have "the meaning or functionality as described
in previous standards", and that is what these carry: ATA-1 9.9.3, 9.9.4
and 9.9.7 define the unformatted bytes per track and per sector and the
buffer type, and the ATA-1 IDENTIFY table gives word 21 as the buffer
size in 512 byte increments. Software old enough to read them gets what
it expects, so answer the question rather than leave it open.

Word 22 is obsolete rather than retired (ATA-4 8.12.18) and already
carries its ATA-1 9.9.8 name, so leave it alone.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:19 +02:00
Denis V. Lunev
0df27c66dc hw/ide: report the default CHS translation in IDENTIFY DEVICE
IDENTIFY DEVICE words 1, 3 and 6 describe the default CHS translation,
and ATA-5 8.16.8 requires INITIALIZE DEVICE PARAMETERS to leave them
alone; the translation in effect is described by words 54 to 56 instead.
Words 3 and 6 were filled from s->heads and s->sectors, which the command
replaces, so a guest that selected a translation of its own was told that
its choice was what the drive came with, and could no longer find out the
default. Word 1 is already right, as no command changes s->cylinders.

Report s->drive_heads and s->drive_sectors, which ide_init_drive() keeps
for exactly this, along with the retired word 4 derived from them. The
CompactFlash data labels those words as the default geometry too, and
INITIALIZE DEVICE PARAMETERS is accepted for CFA drives, so fix both.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Cc: qemu-stable@nongnu.org
Fixes: 176e4961bb ("hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command")
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
2026-08-26 12:59:18 +02:00
Denis V. Lunev
d6960ecdde tests/qtest/ahci: cover the sector count of INITIALIZE DEVICE PARAMETERS
The sector count register of a legacy port is eight bits wide, so
ide-test can only reach the lower end of the range the command has to
refuse. A register FIS carries a 16 bit count, which leaves AHCI as the
only way to ask for a translation of 256 sectors per logical track or
more.

Ask for 0, 256 and 65535 sectors and expect each to be aborted, then ask
for 32 and expect it to be accepted, so that the check cannot pass by
refusing everything.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:18 +02:00
Denis V. Lunev
5e16adf555 tests/qtest/libqos/ahci: allow a count and an expected error
A command that transfers no data can still take an argument in the count
register of the register FIS, and a test may well expect such a command
to be aborted. AHCICommand is private to the library, so add two
setters: ahci_command_set_count() writes the count of a non-data
command, and ahci_command_expect_error() records the error register bits
the command is expected to complete with, which is what
ahci_atapi_test_ready() does inline for a sense key today.

INITIALIZE DEVICE PARAMETERS is the first user of both, so describe it
in the command properties table as well.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:18 +02:00
Denis V. Lunev
0905ef5b6d tests/qtest/ide-test: cover a CHS translation with zero sectors
Ask for zero sectors per logical track via INITIALIZE DEVICE PARAMETERS
and check that the command is aborted, that IDENTIFY DEVICE still reports
the translation that was in effect before, and that a CHS read then
completes normally rather than killing QEMU with SIGFPE.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
2026-08-26 12:59:18 +02:00
Denis V. Lunev
6c712a86f6 hw/ide: reject an unsupported CHS translation
ide_set_sector() divides by (s->heads * s->sectors) when the drive is
addressed in CHS mode. Both come from the guest via INITIALIZE DEVICE
PARAMETERS, and cmd_specify() stored them without any check, so a guest
asking for zero sectors per logical track killed QEMU with SIGFPE on the
completion of the first CHS read or write. s->heads is safe, as the
command passes a heads-1 value.

The count has an upper bound as well. The legacy sector count register is
eight bits wide, but handle_cmd() takes the count from a 16 bit field of
the register FIS, so an AHCI guest can ask for up to 65535 sectors per
track, and the CHS branch of ide_get_sector() then overflows the int it
multiplies cylinder, heads and sectors in.

ATA-5 6.2 numbers CHS sectors from one and ATA-2 D.2.8 limits IDENTIFY
DEVICE word 56 to 1 through 255, so neither end is a translation a device
may accept. ATA-5 8.16.6 requires an unsupported one to be reported as an
aborted command: do that, leave the translation in effect alone, and
refuse the value rather than checking it at every use.

Cc: John Snow <jsnow@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Cc: qemu-stable@nongnu.org
Fixes: 176e4961bb ("hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command")
Reported-by: Zheyu Ma <zheyuma97@gmail.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2399
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
2026-08-26 12:59:18 +02:00
Richard Henderson
fe11f459f6 Various fixes
Collect various graphics & chardev fixes, and some others.
 
 Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmqNeowACgkQ2ujhCXWW
 nOWcsg//VwpHLApYC+ovKfZJm+4m0NUydmsxsYnQXSNhkPEueXMFPu91qu6sLW+c
 T8eRDwCZaItM4te6nKQ46RiD7GOw5M7AB+D7F6H7za5L8+I7j2QGzTz4N1FQnFLL
 0t3FTjzgNri99/UFd1Tpvkh3r4tmLRN1gvGIslvfVtpXLPq0GlVmseDY+Tih4Vz9
 TZn0jAg1WoR4v4YrtkfWvk/Dl5nzM3CRTiqLYz1/jfUB4kUpo/VxU1pk1Ky3LglK
 osrn6pcWxsFD2VLNZwoIMVzrdLjA9w7cIPwLI3JkNop3MD0GtSkAIoT4nSGji8uI
 Ck3CeuQKwZzHeBb4RJBAjEnVXJSpIhgLD5uQ3B4oIGMvfH0FxUphXZ6I77kehs8V
 awJwlE5c1tsuHcdcj67rrrcW3rzMVdDVCyin+xLJw7TkfofV9P/WH88pGO19EdOY
 eyNuwZLHDmrw08KzGEHlzoPRwh01+ihnTB+/eTPJjDDsOgIIQLjjeD06a878XUkm
 bLFnQktMr0DKFwx1wqkKXAqKLAvoWDTcDhlN9a67Y2G1MsGvROmLOsl4EPFqyfK5
 +phEDzZvRD4dWm1vZhI1ZUfORfTXd67naBLAyvSvFZHEbiDtji6RplmSaP8MgA21
 dRWRkUxlfQp0cIgzq/5DgnA3I0buVwfGxz8oeoQDwe2yXPdJBEs=
 =2qCQ
 -----END PGP SIGNATURE-----

Merge tag 'fixes-pr-v1' of https://gitlab.com/marcandre.lureau/qemu into staging

Various fixes

Collect various graphics & chardev fixes, and some others.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmqNeowACgkQ2ujhCXWW
# nOWcsg//VwpHLApYC+ovKfZJm+4m0NUydmsxsYnQXSNhkPEueXMFPu91qu6sLW+c
# T8eRDwCZaItM4te6nKQ46RiD7GOw5M7AB+D7F6H7za5L8+I7j2QGzTz4N1FQnFLL
# 0t3FTjzgNri99/UFd1Tpvkh3r4tmLRN1gvGIslvfVtpXLPq0GlVmseDY+Tih4Vz9
# TZn0jAg1WoR4v4YrtkfWvk/Dl5nzM3CRTiqLYz1/jfUB4kUpo/VxU1pk1Ky3LglK
# osrn6pcWxsFD2VLNZwoIMVzrdLjA9w7cIPwLI3JkNop3MD0GtSkAIoT4nSGji8uI
# Ck3CeuQKwZzHeBb4RJBAjEnVXJSpIhgLD5uQ3B4oIGMvfH0FxUphXZ6I77kehs8V
# awJwlE5c1tsuHcdcj67rrrcW3rzMVdDVCyin+xLJw7TkfofV9P/WH88pGO19EdOY
# eyNuwZLHDmrw08KzGEHlzoPRwh01+ihnTB+/eTPJjDDsOgIIQLjjeD06a878XUkm
# bLFnQktMr0DKFwx1wqkKXAqKLAvoWDTcDhlN9a67Y2G1MsGvROmLOsl4EPFqyfK5
# +phEDzZvRD4dWm1vZhI1ZUfORfTXd67naBLAyvSvFZHEbiDtji6RplmSaP8MgA21
# dRWRkUxlfQp0cIgzq/5DgnA3I0buVwfGxz8oeoQDwe2yXPdJBEs=
# =2qCQ
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 25 Aug 2026 04:20:44 AM PDT
# gpg:                using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [unknown]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* tag 'fixes-pr-v1' of https://gitlab.com/marcandre.lureau/qemu:
  hw/input/ps2: say why unknown keyboard commands draw a resend
  hw/input/ps2: answer unknown mouse commands with a resend
  hw/display/virtio-gpu: Validate resource per command
  hw/display/virtio-gpu: Check cursor data presence
  hw/display/virtio-gpu: Propagate udmabuf errors
  hw/display/virtio-gpu: Avoid mmap() for empty blob
  hw/display/virtio-gpu: Avoid creating empty udmabuf
  hw/display/vga: fix text-mode OOB write after a graphics surface switch
  chardev: Don't unregister yank upon async path connection failure
  tests/functional: fix pylint false positives for cv2 module
  ui/egl: fix qemu_egl_display type
  ui/egl: fix render node cleanup order
  tests: tag slow tests with 'slow' suite for easy filtering
  crypto: fix build against nettle >= 4
  virtio-gpu: use g_try_malloc to avoid guest-triggered abort
  hw/display/qxl: validate primary surface stride against width
  hw/core/machine: fix fdt memory leak
  migration/multifd: fix Error leak in multifd_recv_terminate_threads()
  hw/misc: fix trace-events

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2026-08-25 06:48:55 -07:00
Christian Quante
a88191a0ca hw/input/ps2: say why unknown keyboard commands draw a resend
The keyboard path has answered unknown commands with KBD_REPLY_RESEND
since commit 06b3611fc2 ("ps2: reject unknown commands, instead of
blindly accepting them"), but never said why. Give it the comment the
mouse path just gained, so the reasoning is written down in both
places.

Suggested-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Christian Quante <christian@quante.one>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Message-ID: <20260825075127.34876-3-christian@quante.one>
2026-08-25 15:20:44 +04:00
Christian Quante
0846740652 hw/input/ps2: answer unknown mouse commands with a resend
ps2_write_mouse() ends its command switch with a bare "default: break;",
so an unknown command draws no reply at all. A real PS/2 device answers
every byte it is given -- ACK (0xFA) when it understood one, resend
(0xFE) when it did not -- and a guest that gets nothing back is left
waiting out its reply timeout. The keyboard path in the same file has
answered unknown commands with KBD_REPLY_RESEND since commit
06b3611fc2 ("ps2: reject unknown commands, instead of blindly
accepting them").

Two guests were measured on this.

OS/2 probes the mouse with the vendor command 0xBB, which QEMU does not
implement, and then polls the status port until its own timeout runs
out. On a Warp 3 guest that wait costs about 25 ms of every boot under
TCG, and 2.1 s under KVM, where each of those polls leaves the guest.
With this patch the wait ends on the first read: the guest takes the
same error path an unexpected reply would, and does not retry.

Linux runs into two of them while probing the mouse: the ALPS probe
sends 0xEC (reset wrap mode), which ps2_write_mouse() only answers
while the mouse is in wrap mode, and the TrackPoint probe sends 0xE1.
Each costs libps2 a 200 ms reply timeout. Timing the psmouse detection
from a mark written to /dev/kmsg to the kernel's "input:" line, three
boots each of a 6.18.35 kernel under TCG: 426.7/428.8/441.6 ms without
this patch, 21.4/21.6/21.2 ms with it. The mouse is detected
identically either way; only the error the probe ends in changes, from
-EIO (nothing came back at all) to -EPROTO (libps2 gives up after its
second attempt).

The specification's second stage -- 0xFC (Error) when the byte after a
rejected one is invalid as well -- is deliberately left out. It would
need state that has to survive migration, no guest is known to test for
it, and the keyboard path does without it as well.

Cc: qemu-stable@nongnu.org
Signed-off-by: Christian Quante <christian@quante.one>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Message-ID: <20260825075127.34876-2-christian@quante.one>
2026-08-25 15:20:44 +04:00
Akihiko Odaki
884363589b hw/display/virtio-gpu: Validate resource per command
virtio_gpu_find_check_resource() checks if the resource has backing
storage if require_backing is true, but the condition conflates backing
storage attachment with host representation; it checks
!res->iov || (!res->image && !res->blob), but !res->iov is sufficient.

Furthermore, its callers passing true as require_backing have different
requirements:

- virtio_gpu_transfer_to_host_2d() requires a non-blob with
  backing storage.
- virtio_gpu_set_scanout() requires a non-blob but does not require
  backing storage.
- virtio_gpu_set_scanout_blob() requires a blob with backing storage.
- virtio_gpu_resource_detach_backing() accepts any resource.

Remove the require_backing parameter and open-code checks appropriate
for each function instead.

Fixes: 25c001a403 ("virtio-gpu: Add virtio_gpu_find_check_resource")
Fixes: e0933d91b1 ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Fixes: 32db3c63ae ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-5-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
2026-08-25 15:20:44 +04:00
Akihiko Odaki
d3c2da174c hw/display/virtio-gpu: Check cursor data presence
Reject a blob that lacks the backing storage for
VIRTIO_GPU_CMD_UPDATE_CURSOR.

Fixes: bdd53f7392 ("virtio-gpu: Update cursor data using blob")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-4-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
2026-08-25 15:20:43 +04:00
Akihiko Odaki
cd71534b22 hw/display/virtio-gpu: Propagate udmabuf errors
Propagate udmabuf errors so that the requested operation will be
canceled instead of producing an incomplete result and the user can
notice the failure.

Fixes: e0933d91b1 ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Fixes: f66767f75c ("virtio-gpu: add virtio-gpu/blob vmstate subsection")
Fixes: 4ae1c5c7d6 ("hw/display/virtio-gpu: Initialize blob mapping for ATTACH_BACKING")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-3-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
2026-08-25 15:20:43 +04:00
Akihiko Odaki
3f163489c6 hw/display/virtio-gpu: Avoid mmap() for empty blob
Calling mmap() for an empty blob fails with EINVAL, causing QEMU to
emit a spurious warning.

Fixes: e0933d91b1 ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-2-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
2026-08-25 15:20:43 +04:00
Akihiko Odaki
14f2511f59 hw/display/virtio-gpu: Avoid creating empty udmabuf
The virtio specification allows creating a blob without backing storage
attached. However, virtio-gpu attempts to create an empty udmabuf for
such a blob. The ioctl fails with EINVAL and emits a spurious warning.
Avoid the invalid ioctl.

Fixes: e0933d91b1 ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Fixes: f66767f75c ("virtio-gpu: add virtio-gpu/blob vmstate subsection")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-1-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
2026-08-25 15:20:43 +04:00
Warisjeet Singh
418396be80 hw/display/vga: fix text-mode OOB write after a graphics surface switch
vga_draw_text() decides whether the console surface needs a resize from
its geometry cache, but none of the cache terms observe the graphics
renderer having replaced the console surface in between:

- last_width/last_height are shared with vga_draw_graphic(), which
  stores them in pixels while the text path stores characters;
- last_depth stays 0 for legacy (non-VBE) graphics modes, because
  vga_get_bpp() only reports a depth when VBE is enabled, so the
  "s->last_depth" term that normally forces a resize after a graphics
  frame does not fire.

So a graphics frame that shrinks the console surface (e.g. 80x25
pixels) followed by a text frame with matching character geometry
(80x25 chars) skips the resize, and the glyph loop then paints
width*cw x height*cheight pixels into the smaller surface, out of
bounds, with guest-controlled (DAC palette) values, on every display
refresh.

Separate the geometry cache per renderer: text paths (vga_draw_text,
vga_update_text, and the text handling in vga_invalidate_display /
vga_common_reset) now only manipulate last_text_{width,height}, in
characters; last_{width,height} become graphics-only, in pixels.
Additionally, make the text path compare the pixel size it is about
to paint against the console surface's actual dimensions.  The
surface check is the load-bearing term: caches in either unit cannot
see the other renderer swapping the surface, the surface can.

Fixes: CVE-2026-77913
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4215
Cc: qemu-stable@nongnu.org
Signed-off-by: Warisjeet Singh (sin99xx) <sinxx198@gmail.com>
Message-ID: <vga-v3-20260824.sinxx198@gmail.com>
2026-08-25 15:20:43 +04:00
Fabiano Rosas
ddf5738503 chardev: Don't unregister yank upon async path connection failure
Commit 5c102ac9 ("chardev: Consolidate yank registration") has moved
yank registration in the tcp_chr_connect_client_async() path to after
the connection is successful. If qio_channel_socket_connect_sync()
fails early, there will be no yank registered to be unregistered in
the error path, leading to assert.

Remove the now-extraneous unregister.

Cc: qemu-stable@nongnu.org
Fixes: 5c102ac9 ("chardev: Consolidate yank registration")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3528
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260603141137.1108963-1-farosas@suse.de>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
4fd6561228 tests/functional: fix pylint false positives for cv2 module
Add generated-members=cv2.* to pylintrc so pylint skips member
checking on the cv2 C extension module, whose members are not
visible to static analysis.

Silence:
2026-08-15 10:42:08,710 - INFO: qemu-test.test_pylint Checking files in /home/elmarco/src/qemu.qom-qapi/tests/functional/arm with pylint
2026-08-15 10:42:10,941 - ERROR: qemu-test.test_pylint "/home/elmarco/src/qemu.qom-qapi/tests/functional/arm/test_integratorcp.py:83: E1101: Module 'cv2' has no 'imread' member (no-member)"

Note: I also tried with extension-pkg-allow-list, but that didn't work
for some reason.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260815072421.4117291-1-marcandre.lureau@redhat.com>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
86fc385ca0 ui/egl: fix qemu_egl_display type
EGLDisplay is already a pointer type (void *), so declaring
qemu_egl_display as EGLDisplay * makes it void **, which
doesn't match any of its usages.

Fixes: 7ced9e9f6d ("ui: add egl-helpers")
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260820131933.2729240-1-marcandre.lureau@redhat.com>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
baca25172d ui/egl: fix render node cleanup order
ASAN detected some memory leaks when terminating. Release thread-bound
EGL state first, destroy the context and terminate the display while the
GBM device is still alive, then destroy GBM and close the render-node
fd.

Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Fixes: a3cf9b55bb ("ui/egl: implement display and EGL cleanup")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260820132014.2729748-1-marcandre.lureau@redhat.com>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
f4b2607228 tests: tag slow tests with 'slow' suite for easy filtering
Add several RCU and thread-pool unit tests to the slow_tests dict,
and tag all slow tests (both qtest and unit) with a 'slow' suite so
they can be excluded or selected via meson test --suite/--no-suite.

Acked-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260512065633.3542562-1-marcandre.lureau@redhat.com>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
0e62034ca1 crypto: fix build against nettle >= 4
sha.h has been deprecated. It seems we can rely on sha1.h/sha2.h
since we depend on >= 3.7.3.

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4184
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
eb2b3a1fa8 virtio-gpu: use g_try_malloc to avoid guest-triggered abort
Use g_try_malloc/g_try_new0 for guest-controlled allocation, so failure
returns an error to the guest rather than crashing the host (glib
behaviour).

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3898
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260805130141.211398-1-marcandre.lureau@redhat.com>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
ab7183ed4e hw/display/qxl: validate primary surface stride against width
The existing validation in qxl_create_guest_primary() checks that
abs(stride) * height fits in vgamem_size and that stride is 4-byte
aligned, but never checks that abs(stride) is large enough to hold one
row of pixels for the declared width and format.

A malicious guest can create a primary surface with a stride much
smaller than width * bytes_per_pixel (e.g. stride=4 for a 64-wide 32bpp
surface). The spice server rejects this via red_validate_surface(), but
the return is void and QEMU unconditionally proceeds to set up the local
rendering state. On the next display refresh, VNC or SDL reads width *
bytes_pp per scanline from a region backed by only stride bytes per
row, causing a host-side out-of-bounds read.

Add three checks in qxl_create_guest_primary() before creating the
surface:
 - reject unknown surface formats
 - reject zero width or height
 - reject surfaces where abs(stride) < width * bytes_per_pixel

Also fix three related issues in qxl-render.c:
 - qxl_blit() used abs_stride to advance the dst pointer into the
   DisplaySurface, but when stride is negative the DisplaySurface is a
   packed buffer whose stride may be smaller. Use surface_stride()
   instead.
 - qxl_render_update_area_unlocked() uses guest_head0_width (set via
   QXL_IO_MONITORS_CONFIG_ASYNC) without validating it against
   abs_stride, bypassing the new validation. Clamp the effective width
   to abs_stride / bytes_pp to prevent out-of-bounds access while
   tolerating the normal transient where the monitor config arrives
   before the primary surface is resized to match.
 - Similarly, guest_head0_height bypasses qxl_create_guest_primary()
   validation. Without clamping, abs_stride * height can overrun
   vgamem_size, and the product can also overflow 32 bits (e.g.
   abs_stride=16 MiB, height=256 wraps to zero), defeating the
   qxl_phys2virt() bounds check. Clamp height to
   vgamem_size / abs_stride to prevent both.

While touch it, fix some endianness issues.

Fixes: CVE-2026-16271
Fixes: a19cbfb346 ("spice: add qxl device")
Fixes: 979f7ef896 ("qxl: use guest_monitor_config for local renderer.")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3637
Reported-by: huntr bubble
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Message-ID: <20260806094028.640676-1-marcandre.lureau@redhat.com>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
df42a1589f hw/core/machine: fix fdt memory leak
The MachineState fdt field is allocated by various machine types via
create_device_tree(), load_device_tree(), or similar, but was never
freed in machine_finalize(). Add the missing g_free() call.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260709111249.1107640-1-marcandre.lureau@redhat.com>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
b5102872b8 migration/multifd: fix Error leak in multifd_recv_terminate_threads()
If err != NULL, free it.

Fixes: 11dd7be575 ("migration/multifd: Remove p->quit from recv side")
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260727-fix2-v2-11-d0c4831ed7ea@redhat.com>
2026-08-25 15:20:43 +04:00
Marc-André Lureau
8fda982a7c hw/misc: fix trace-events
The commit 8041d17308 accidentally removed the vmlaunchupdate.c
trace events.

Fixes: 8041d17308 ("tests/qtest: add test for K230 gsdma")
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Luigi Leonardi <leonardi@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825074114.853069-1-marcandre.lureau@redhat.com>
2026-08-25 15:20:43 +04:00
Richard Henderson
fd7ab698c9 ufs queue
- Separate the UFS controller core from the PCI frontend
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEUBfYMVl8eKPZB+73EuIgTA5dtgIFAmqL1G8ACgkQEuIgTA5d
 tgIWthAAvynqQHh4tnILvApKh/E5ePRV/J9KtTYCJIIU1M1V/Xgr8s8R0UwfxzPM
 dl0mibLBozZuyo5tQGLXtEjXCNUEuKFO3YW+UrNk+iIrNjKBiiqHTrh48g2J9wwd
 OeZawTg2EEIde395pBsidCyKp8M7DGOies/MuI3m2yRifyR7dlq1zUsR4JUUDiXu
 +8LvBng8yZHxPK3j3vxT+3VsxcK3qUord0u3kvFK+m+010l3B2WerxG/ZR110LG7
 mL/0fijD3P25lU0x9fryA6BYIE4LppOdJwZJi5rLl6CXiEKcqRlLEBAfUQAh04a5
 AtfXV5Q7iXjJSC9cZB+NXP6qn+yP6Dq6ioHtlAA4koF08DGzd+xMBsCI4k7Bib28
 r1e4tjIcBa8Xn7e/Lwj1/Co2dmM6DlaRsbi4n0oPp3yp+aavIfaLeIfjPwlRVqLF
 mB/I9rR1d09VVlmNBI40cnVdQzWgNU/wcot+hwZ3gyBx7ow4mOG4XmrEKHj8JaTH
 iAEXZq5LEBbP5T6f+1iPqsB16NkdTc4Sl45SG+rDnOiQz4x6B76PmUU/SyDRFmzy
 RVAKPdPp/xigg1clVEoDxZxVueioX5kpxHxAlmwoFjse5CBZmkLlhRtv4o1R72UP
 MGKbVw8i0tW00bHNjW4IBWy8i5jlIE2gu84AnyZTsqp33Srg+Po=
 =7KSJ
 -----END PGP SIGNATURE-----

Merge tag 'pull-ufs-20260824' of https://gitlab.com/jeuk20.kim/qemu into staging

ufs queue

- Separate the UFS controller core from the PCI frontend

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEUBfYMVl8eKPZB+73EuIgTA5dtgIFAmqL1G8ACgkQEuIgTA5d
# tgIWthAAvynqQHh4tnILvApKh/E5ePRV/J9KtTYCJIIU1M1V/Xgr8s8R0UwfxzPM
# dl0mibLBozZuyo5tQGLXtEjXCNUEuKFO3YW+UrNk+iIrNjKBiiqHTrh48g2J9wwd
# OeZawTg2EEIde395pBsidCyKp8M7DGOies/MuI3m2yRifyR7dlq1zUsR4JUUDiXu
# +8LvBng8yZHxPK3j3vxT+3VsxcK3qUord0u3kvFK+m+010l3B2WerxG/ZR110LG7
# mL/0fijD3P25lU0x9fryA6BYIE4LppOdJwZJi5rLl6CXiEKcqRlLEBAfUQAh04a5
# AtfXV5Q7iXjJSC9cZB+NXP6qn+yP6Dq6ioHtlAA4koF08DGzd+xMBsCI4k7Bib28
# r1e4tjIcBa8Xn7e/Lwj1/Co2dmM6DlaRsbi4n0oPp3yp+aavIfaLeIfjPwlRVqLF
# mB/I9rR1d09VVlmNBI40cnVdQzWgNU/wcot+hwZ3gyBx7ow4mOG4XmrEKHj8JaTH
# iAEXZq5LEBbP5T6f+1iPqsB16NkdTc4Sl45SG+rDnOiQz4x6B76PmUU/SyDRFmzy
# RVAKPdPp/xigg1clVEoDxZxVueioX5kpxHxAlmwoFjse5CBZmkLlhRtv4o1R72UP
# MGKbVw8i0tW00bHNjW4IBWy8i5jlIE2gu84AnyZTsqp33Srg+Po=
# =7KSJ
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 23 Aug 2026 10:19:43 PM PDT
# gpg:                using RSA key 5017D831597C78A3D907EEF712E2204C0E5DB602
# gpg: Good signature from "Jeuk Kim <jeuk20.kim@samsung.com>" [unknown]
# gpg:                 aka "Jeuk Kim <jeuk20.kim@gmail.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 5017 D831 597C 78A3 D907  EEF7 12E2 204C 0E5D B602

* tag 'pull-ufs-20260824' of https://gitlab.com/jeuk20.kim/qemu:
  hw/ufs: Add a generic SysBus frontend
  hw/ufs: Separate the controller core from the PCI frontend

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2026-08-24 10:53:36 -07:00