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>
Denis V. Lunev committed
Aug 4, 2026 at 18:34 UTC
0905ef5b6d483da0e27831152fdde059595244b9
1 file changed
+62
tests/qtest/ide-test.c
+62
@@ -95,6 +95,7 @@ enum {
95
96
enum {
97
CMD_DSM = 0x06,
98
+ CMD_READ = 0x20, /* READ SECTOR(S) */
99
CMD_DIAGNOSE = 0x90,
100
CMD_INIT_DP = 0x91, /* INITIALIZE DEVICE PARAMETERS */
101
CMD_READ_DMA = 0xc8,
@@ -1194,6 +1195,66 @@ static void cdrom_read_impl(int nblocks, unsigned flags)
1195
free_pci_device(dev);
1196
}
1197
1198
+/* Zero sectors per track has to abort (ATA-5 8.16.6), not divide by zero */
1199
+static void test_specify_zero_sectors(void)
1200
+{
1201
+ QTestState *qts;
1202
+ QPCIDevice *dev;
1203
+ QPCIBar bmdma_bar, ide_bar;
1204
+ uint16_t buf[256];
1205
+ uint8_t data;
1206
+ int i;
1207
+
1208
+ qts = ide_test_start(
1209
+ "-blockdev driver=file,node-name=hda,filename=%s "
1210
+ "-device ide-hd,drive=hda,bus=ide.0,unit=0 ",
1211
+ tmp_path[0]);
1212
+
1213
+ dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
1214
+
1215
+ qpci_io_writeb(dev, ide_bar, reg_nsectors, 0);
1216
+ qpci_io_writeb(dev, ide_bar, reg_device, 0);
1217
+ qpci_io_writeb(dev, ide_bar, reg_command, CMD_INIT_DP);
1218
+
1219
+ assert_bit_set(qpci_io_readb(dev, ide_bar, reg_status), ERR);
1220
+ assert_bit_set(qpci_io_readb(dev, ide_bar, reg_error), ABRT);
1221
+
1222
+ /* The refused request has to leave the default translation in effect */
1223
+ qpci_io_writeb(dev, ide_bar, reg_device, 0);
1224
+ qpci_io_writeb(dev, ide_bar, reg_command, CMD_IDENTIFY);
1225
+ for (i = 0; i < 256; i++) {
1226
+ buf[i] = qpci_io_readw(dev, ide_bar, reg_data);
1227
+ }
1228
+ g_assert_cmpint(buf[55], ==, 16);
1229
+ g_assert_cmpint(buf[56], ==, 63);
1230
+
1231
+ /* READ SECTOR(S) of CHS 0/0/1, which used to crash QEMU */
1232
+ qpci_io_writeb(dev, ide_bar, reg_nsectors, 1);
1233
+ qpci_io_writeb(dev, ide_bar, reg_lba_low, 1);
1234
+ qpci_io_writeb(dev, ide_bar, reg_lba_middle, 0);
1235
+ qpci_io_writeb(dev, ide_bar, reg_lba_high, 0);
1236
+ qpci_io_writeb(dev, ide_bar, reg_device, 0);
1237
+ qpci_io_writeb(dev, ide_bar, reg_command, CMD_READ);
1238
+
1239
+ data = ide_wait_clear(qts, BSY);
1240
+ assert_bit_set(data, DRQ);
1241
+ assert_bit_clear(data, ERR | DF);
1242
+ for (i = 0; i < 256; i++) {
1243
+ buf[i] = qpci_io_readw(dev, ide_bar, reg_data);
1244
+ }
1245
+ assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), ERR | DF | DRQ);
1246
+
1247
+ /* A supported translation is still accepted */
1248
+ qpci_io_writeb(dev, ide_bar, reg_nsectors, 32);
1249
+ qpci_io_writeb(dev, ide_bar, reg_device, 7);
1250
+ qpci_io_writeb(dev, ide_bar, reg_command, CMD_INIT_DP);
1251
+
1252
+ assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), ERR);
1253
+
1254
+ ide_test_quit(qts);
1255
+ free_pci_device(dev);
1256
+}
1257
+
1258
static void test_cdrom_pio(void)
1259
{
1260
cdrom_read_impl(1, CDROM_PIO);
@@ -1265,6 +1326,7 @@ int main(int argc, char **argv)
1326
g_test_init(&argc, &argv, NULL);
1327
1328
qtest_add_func("/ide/read_native", test_specify);
1329
+ qtest_add_func("/ide/specify/zero_sectors", test_specify_zero_sectors);
1330
1331
qtest_add_func("/ide/identify", test_identify);
1332