From: "Denis V. Lunev" <den@openvz.org>
To: qemu-devel@nongnu.org
Cc: qemu-block@nongnu.org, "Denis V. Lunev" <den@openvz.org>,
"John Snow" <jsnow@redhat.com>,
"Philippe Mathieu-Daudé" <philmd@oss.qualcomm.com>
Subject: [PATCH 05/11] tests/qtest/ahci: regression test for a PIO write vs. engine stop
Date: Thu, 20 Aug 2026 16:43:03 +0200 [thread overview]
Message-ID: <20260820144309.835173-6-den@openvz.org> (raw)
In-Reply-To: <20260820144309.835173-1-den@openvz.org>
From: Denis V. Lunev <den@openvz.org>
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>
---
tests/qtest/ahci-test.c | 72 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c
index 30d7005626..84d4e6b0a5 100644
--- a/tests/qtest/ahci-test.c
+++ b/tests/qtest/ahci-test.c
@@ -1793,6 +1793,76 @@ static void test_atapi_engine_restart_dma(void)
test_atapi_engine_restart_in_flight(true);
}
+/*
+ * Regression test: a PIO write outlives the command list it was issued from.
+ * ide_cancel_dma_sync() does not reach s->pio_aiocb, so the second DRQ phase
+ * runs from the write completion after PxCLB has been unmapped and must not
+ * touch the command header any more.
+ */
+static void test_write_engine_stop_in_flight(void)
+{
+ AHCIQState *ahci;
+ AHCICommand *cmd;
+ unsigned char *tx;
+ unsigned char *rx;
+ uint64_t ptr;
+ uint8_t port;
+ size_t bufsize = AHCI_SECTOR_SIZE * 2;
+ size_t i;
+
+ ahci = ahci_boot_and_enable("-drive file=blkdebug::%s,if=none,id=drive0,"
+ "format=%s,cache=writeback "
+ "-M q35 "
+ "-device ide-hd,drive=drive0 ",
+ tmp_path, imgfmt);
+ port = ahci_port_select(ahci);
+ ahci_port_clear(ahci, port);
+
+ tx = g_malloc(bufsize);
+ generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
+ ptr = ahci_alloc(ahci, bufsize);
+ g_assert(ptr);
+ qtest_memwrite(ahci->parent->qts, ptr, tx, bufsize);
+
+ /* Zero the second sector, which the abandoned command must not reach. */
+ rx = g_malloc0(AHCI_SECTOR_SIZE);
+ ahci_io(ahci, port, CMD_WRITE_DMA, rx, AHCI_SECTOR_SIZE, 1);
+
+ /* Suspend the backend write so the first sector stays in flight. */
+ g_free(qtest_hmp(ahci->parent->qts,
+ "qemu-io drive0 \"break write_aio wr\""));
+
+ cmd = ahci_command_create(CMD_WRITE_PIO);
+ ahci_command_adjust(cmd, 0, ptr, bufsize, 0);
+ ahci_command_commit(ahci, cmd, port);
+ ahci_command_issue_async(ahci, cmd);
+
+ /* Drop the command list while the write is still outstanding. */
+ ahci_px_clr(ahci, port, AHCI_PX_CMD, AHCI_PX_CMD_ST);
+
+ g_free(qtest_hmp(ahci->parent->qts, "qemu-io drive0 \"resume wr\""));
+
+ /* Round-trip through the device to confirm qemu is still alive. */
+ ahci_px_rreg(ahci, port, AHCI_PX_TFD);
+
+ /*
+ * The second DRQ phase never fetched its data, so the sector it would
+ * have carried has to be untouched rather than hold a copy of the first.
+ */
+ ahci_px_set(ahci, port, AHCI_PX_CMD, AHCI_PX_CMD_ST);
+ memset(rx, 0xff, AHCI_SECTOR_SIZE);
+ ahci_io(ahci, port, CMD_READ_DMA, rx, AHCI_SECTOR_SIZE, 1);
+ for (i = 0; i < AHCI_SECTOR_SIZE; i++) {
+ g_assert_cmpint(rx[i], ==, 0);
+ }
+
+ ahci_command_free(cmd);
+ ahci_free(ahci, ptr);
+ g_free(rx);
+ g_free(tx);
+ ahci_shutdown(ahci);
+}
+
/*
* Regression test: a multi-sector ATAPI read fetches its later sectors from
* inside the first read's completion; a concurrent drain (as a guest reset
@@ -2281,6 +2351,8 @@ int main(int argc, char **argv)
test_atapi_engine_restart_pio);
qtest_add_func("/ahci/cdrom/engine_restart/dma",
test_atapi_engine_restart_dma);
+ qtest_add_func("/ahci/io/pio/engine_stop",
+ test_write_engine_stop_in_flight);
qtest_add_func("/ahci/cdrom/drain/pio", test_atapi_drain_pio);
qtest_add_func("/ahci/cdrom/drain/dma", test_atapi_drain_dma);
--
2.53.0
next prev parent reply other threads:[~2026-08-20 14:44 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 14:42 [PATCH 00/11] hw/ide: pending IDE fixes Denis V. Lunev
2026-08-20 14:42 ` [PATCH 01/11] hw/ide: reject an out-of-range PIO transfer window on load Denis V. Lunev
2026-08-20 14:43 ` [PATCH 02/11] tests/qtest/ide-test: cover the migrated PIO transfer window Denis V. Lunev
2026-08-20 14:43 ` [PATCH 03/11] hw/ide/ahci: refuse a PIO transfer with no command header Denis V. Lunev
2026-08-20 14:43 ` [PATCH 04/11] hw/ide/ahci: clear cur_cmd when the command list is unmapped Denis V. Lunev
2026-08-20 14:43 ` Denis V. Lunev [this message]
2026-08-20 14:43 ` [PATCH 06/11] hw/ide/ahci: treat a failed PRDT walk as a PIO transfer failure Denis V. Lunev
2026-08-20 14:43 ` [PATCH 07/11] hw/ide/ahci: reject a command header with an invalid FIS length Denis V. Lunev
2026-08-20 14:43 ` [PATCH 08/11] hw/ide/ahci: drain the ports on teardown Denis V. Lunev
2026-08-20 14:43 ` [PATCH 09/11] tests/qtest/ahci: regression test for a request outliving an unplug Denis V. Lunev
2026-08-20 14:43 ` [PATCH 10/11] hw/ide: report ATAPI UDMA5 with a matching standard and cable Denis V. Lunev
2026-08-20 14:43 ` [PATCH 11/11] tests/qtest/ide-test: cover the UDMA5 identify words Denis V. Lunev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260820144309.835173-6-den@openvz.org \
--to=den@openvz.org \
--cc=jsnow@redhat.com \
--cc=philmd@oss.qualcomm.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.