diff options
-rw-r--r-- | tests/ahci-test.c | 34 | ||||
-rw-r--r-- | tests/ide-test.c | 43 |
2 files changed, 75 insertions, 2 deletions
diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 57dc44c..9c0adce 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -1063,11 +1063,34 @@ static void test_dma_fragmented(void) g_free(tx); } +/* + * Write sector 1 with random data to make AHCI storage dirty + * Needed for flush tests so that flushes actually go though the block layer + */ +static void make_dirty(AHCIQState* ahci, uint8_t port) +{ + uint64_t ptr; + unsigned bufsize = 512; + + ptr = ahci_alloc(ahci, bufsize); + g_assert(ptr); + + ahci_guest_io(ahci, port, CMD_WRITE_DMA, ptr, bufsize, 1); + ahci_free(ahci, ptr); +} + static void test_flush(void) { AHCIQState *ahci; + uint8_t port; ahci = ahci_boot_and_enable(NULL); + + port = ahci_port_select(ahci); + ahci_port_clear(ahci, port); + + make_dirty(ahci, port); + ahci_test_flush(ahci); ahci_shutdown(ahci); } @@ -1087,10 +1110,13 @@ static void test_flush_retry(void) debug_path, tmp_path, imgfmt); - /* Issue Flush Command and wait for error */ port = ahci_port_select(ahci); ahci_port_clear(ahci, port); + /* Issue write so that flush actually goes to disk */ + make_dirty(ahci, port); + + /* Issue Flush Command and wait for error */ cmd = ahci_guest_io_halt(ahci, port, CMD_FLUSH_CACHE, 0, 0, 0); ahci_guest_io_resume(ahci, cmd); @@ -1343,9 +1369,13 @@ static void test_flush_migrate(void) set_context(src->parent); - /* Issue Flush Command */ px = ahci_port_select(src); ahci_port_clear(src, px); + + /* Dirty device so that flush reaches disk */ + make_dirty(src, px); + + /* Issue Flush Command */ cmd = ahci_command_create(CMD_FLUSH_CACHE); ahci_command_commit(src, cmd, px); ahci_command_issue_async(src, cmd); diff --git a/tests/ide-test.c b/tests/ide-test.c index fed1b2e..1e51af2 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -499,6 +499,39 @@ static void test_identify(void) ide_test_quit(); } +/* + * Write sector 1 with random data to make IDE storage dirty + * Needed for flush tests so that flushes actually go though the block layer + */ +static void make_dirty(uint8_t device) +{ + uint8_t status; + size_t len = 512; + uintptr_t guest_buf; + void* buf; + + guest_buf = guest_alloc(guest_malloc, len); + buf = g_malloc(len); + g_assert(guest_buf); + g_assert(buf); + + memwrite(guest_buf, buf, len); + + PrdtEntry prdt[] = { + { + .addr = cpu_to_le32(guest_buf), + .size = cpu_to_le32(len | PRDT_EOT), + }, + }; + + status = send_dma_request(CMD_WRITE_DMA, 1, 1, prdt, + ARRAY_SIZE(prdt), NULL); + g_assert_cmphex(status, ==, BM_STS_INTR); + assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + + g_free(buf); +} + static void test_flush(void) { uint8_t data; @@ -507,6 +540,11 @@ static void test_flush(void) "-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw", tmp_path); + qtest_irq_intercept_in(global_qtest, "ioapic"); + + /* Dirty media so that CMD_FLUSH_CACHE will actually go to disk */ + make_dirty(0); + /* Delay the completion of the flush request until we explicitly do it */ g_free(hmp("qemu-io ide0-hd0 \"break flush_to_os A\"")); @@ -549,6 +587,11 @@ static void test_retry_flush(const char *machine) "rerror=stop,werror=stop", debug_path, tmp_path); + qtest_irq_intercept_in(global_qtest, "ioapic"); + + /* Dirty media so that CMD_FLUSH_CACHE will actually go to disk */ + make_dirty(0); + /* FLUSH CACHE command on device 0*/ outb(IDE_BASE + reg_device, 0); outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE); |