96
enum {
97
CMD_DSM = 0x06,
98
CMD_READ = 0x20, /* READ SECTOR(S) */
99
+ CMD_WRITE = 0x30, /* WRITE SECTOR(S) */
100
CMD_DIAGNOSE = 0x90,
101
CMD_INIT_DP = 0x91, /* INITIALIZE DEVICE PARAMETERS */
102
CMD_READ_DMA = 0xc8,
1256
free_pci_device(dev);
1257
}
1258
1259
+/* Addressed by LBA, so no translation can influence where it lands */
1260
+static void ide_write_marker(QTestState *qts, QPCIDevice *dev, QPCIBar ide_bar,
1261
+ uint32_t lba, const char *marker)
1262
+{
1263
+ uint16_t buf[256];
1264
+ uint8_t data;
1265
+ int i;
1266
+
1267
+ memset(buf, 0, sizeof(buf));
1268
+ memcpy(buf, marker, strlen(marker));
1269
+
1270
+ qpci_io_writeb(dev, ide_bar, reg_nsectors, 1);
1271
+ qpci_io_writeb(dev, ide_bar, reg_lba_low, lba & 0xff);
1272
+ qpci_io_writeb(dev, ide_bar, reg_lba_middle, (lba >> 8) & 0xff);
1273
+ qpci_io_writeb(dev, ide_bar, reg_lba_high, (lba >> 16) & 0xff);
1274
+ qpci_io_writeb(dev, ide_bar, reg_device, LBA | ((lba >> 24) & 0xf));
1275
+ qpci_io_writeb(dev, ide_bar, reg_command, CMD_WRITE);
1276
+
1277
+ data = ide_wait_clear(qts, BSY);
1278
+ assert_bit_set(data, DRQ);
1279
+ for (i = 0; i < 256; i++) {
1280
+ qpci_io_writew(dev, ide_bar, reg_data, buf[i]);
1281
+ }
1282
+ data = ide_wait_clear(qts, BSY);
1283
+ assert_bit_clear(data, ERR | DF | DRQ);
1284
+
1285
+ qpci_io_writeb(dev, ide_bar, reg_command, CMD_FLUSH_CACHE);
1286
+ data = ide_wait_clear(qts, BSY);
1287
+ assert_bit_clear(data, ERR | DF);
1288
+}
1289
+
1290
+/* The marker read back names the sector the translation selected */
1291
+static void ide_read_chs_marker(QTestState *qts, QPCIDevice *dev,
1292
+ QPCIBar ide_bar, uint8_t cyl_lo, uint8_t head,
1293
+ uint8_t sector, char out[9])
1294
+{
1295
+ uint16_t buf[256];
1296
+ uint8_t data;
1297
+ int i;
1298
+
1299
+ qpci_io_writeb(dev, ide_bar, reg_nsectors, 1);
1300
+ qpci_io_writeb(dev, ide_bar, reg_lba_low, sector);
1301
+ qpci_io_writeb(dev, ide_bar, reg_lba_middle, cyl_lo);
1302
+ qpci_io_writeb(dev, ide_bar, reg_lba_high, 0);
1303
+ qpci_io_writeb(dev, ide_bar, reg_device, head & 0xf);
1304
+ qpci_io_writeb(dev, ide_bar, reg_command, CMD_READ);
1305
+
1306
+ data = ide_wait_clear(qts, BSY);
1307
+ assert_bit_set(data, DRQ);
1308
+ assert_bit_clear(data, ERR | DF);
1309
+ for (i = 0; i < 256; i++) {
1310
+ buf[i] = qpci_io_readw(dev, ide_bar, reg_data);
1311
+ }
1312
+ data = ide_wait_clear(qts, BSY);
1313
+ assert_bit_clear(data, ERR | DF | DRQ);
1314
+
1315
+ memcpy(out, buf, 8);
1316
+ out[8] = '\0';
1317
+}
1318
+
1319
+static void ide_set_translation(QPCIDevice *dev, QPCIBar ide_bar,
1320
+ uint8_t heads, uint8_t sectors)
1321
+{
1322
+ qpci_io_writeb(dev, ide_bar, reg_nsectors, sectors);
1323
+ qpci_io_writeb(dev, ide_bar, reg_device, heads - 1);
1324
+ qpci_io_writeb(dev, ide_bar, reg_command, CMD_INIT_DP);
1325
+ assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), ERR);
1326
+}
1327
+
1328
+/* CHS 0/1/1 is LBA 32 under 8/32, and LBA 63 under the drive's own 16/63 */
1329
+#define CHS_MARKER_CUSTOM "CUSTOM__"
1330
+#define CHS_MARKER_DEFAULT "DEFAULT_"
1331
+
1332
+static void ide_prepare_markers(QTestState *qts, QPCIDevice *dev,
1333
+ QPCIBar ide_bar)
1334
+{
1335
+ ide_write_marker(qts, dev, ide_bar, 32, CHS_MARKER_CUSTOM);
1336
+ ide_write_marker(qts, dev, ide_bar, 63, CHS_MARKER_DEFAULT);
1337
+}
1338
+
1339
+static void ide_hmp_quiet(QTestState *qts, const char *command)
1340
+{
1341
+ g_autofree char *out = qtest_hmp(qts, "%s", command);
1342
+
1343
+ g_assert_cmpstr(out, ==, "");
1344
+}
1345
+
1346
+static char *ide_migration_status(QTestState *qts)
1347
+{
1348
+ QDict *ret;
1349
+ char *status;
1350
+
1351
+ ret = qtest_qmp_assert_success_ref(qts, "{ 'execute': 'query-migrate' }");
1352
+ g_assert(qdict_haskey(ret, "status"));
1353
+ status = g_strdup(qdict_get_str(ret, "status"));
1354
+ qobject_unref(ret);
1355
+
1356
+ return status;
1357
+}
1358
+
1359
+/* Waiting for the other side's event would hang if it refuses the stream */
1360
+static void ide_migration_wait(QTestState *qts, const char *expected)
1361
+{
1362
+ while (true) {
1363
+ g_autofree char *status = ide_migration_status(qts);
1364
+
1365
+ if (g_str_equal(status, expected)) {
1366
+ return;
1367
+ }
1368
+ if (!g_str_equal(status, "setup") && !g_str_equal(status, "active") &&
1369
+ !g_str_equal(status, "device")) {
1370
+ fprintf(stderr, "Migration status is %s, expected %s\n",
1371
+ status, expected);
1372
+ g_assert_not_reached();
1373
+ }
1374
+ g_usleep(5000);
1375
+ }
1376
+}
1377
+
1378
+static void ide_migrate(QTestState *src, QTestState *dst, const char *uri)
1379
+{
1380
+ qtest_qmp_assert_success(src, "{ 'execute': 'migrate',"
1381
+ " 'arguments': { 'uri': %s } }", uri);
1382
+ qtest_qmp_eventwait(src, "STOP");
1383
+ ide_migration_wait(src, "completed");
1384
+ qtest_qmp_eventwait(dst, "RESUME");
1385
+}
1386
+
1387
+/* A translation the guest selected has to survive migration */
1388
+static void test_migrate_chs_translation(void)
1389
+{
1390
+ QTestState *src, *dst;
1391
+ QPCIDevice *dev;
1392
+ QPCIBar bmdma_bar, ide_bar;
1393
+ g_autofree char *mig_path = NULL;
1394
+ g_autofree char *uri = NULL;
1395
+ g_autofree char *dst_args = NULL;
1396
+ char marker[9];
1397
+ int fd;
1398
+
1399
+ fd = g_file_open_tmp("qtest-ide-migration.XXXXXX", &mig_path, NULL);
1400
+ g_assert(fd >= 0);
1401
+ close(fd);
1402
+ uri = g_strdup_printf("unix:%s", mig_path);
1403
+
1404
+ src = ide_test_start(
1405
+ "-blockdev driver=file,node-name=hda,filename=%s,locking=off "
1406
+ "-device ide-hd,drive=hda,bus=ide.0,unit=0 ",
1407
+ tmp_path[0]);
1408
+ dev = get_pci_device(src, &bmdma_bar, &ide_bar);
1409
+
1410
+ ide_prepare_markers(src, dev, ide_bar);
1411
+ ide_set_translation(dev, ide_bar, 8, 32);
1412
+ ide_read_chs_marker(src, dev, ide_bar, 0, 1, 1, marker);
1413
+ g_assert_cmpstr(marker, ==, CHS_MARKER_CUSTOM);
1414
+
1415
+ dst_args = g_strdup_printf(
1416
+ "-machine pc "
1417
+ "-blockdev driver=file,node-name=hda,filename=%s,locking=off "
1418
+ "-device ide-hd,drive=hda,bus=ide.0,unit=0 -incoming %s",
1419
+ tmp_path[0], uri);
1420
+ dst = qtest_init(dst_args);
1421
+
1422
+ ide_migrate(src, dst, uri);
1423
+
1424
+ /* Talk to the destination instead of the source */
1425
+ qpci_free_pc(pcibus);
1426
+ pcibus = NULL;
1427
+ free_pci_device(dev);
1428
+ dev = get_pci_device(dst, &bmdma_bar, &ide_bar);
1429
+
1430
+ ide_read_chs_marker(dst, dev, ide_bar, 0, 1, 1, marker);
1431
+ g_assert_cmpstr(marker, ==, CHS_MARKER_CUSTOM);
1432
+
1433
+ free_pci_device(dev);
1434
+ qtest_quit(dst);
1435
+ ide_test_quit(src);
1436
+ unlink(mig_path);
1437
+}
1438
+
1439
+/* A translation selected after the snapshot must not outlive loading it */
1440
+static void test_migrate_chs_snapshot(void)
1441
+{
1442
+ QTestState *qts;
1443
+ QPCIDevice *dev;
1444
+ QPCIBar bmdma_bar, ide_bar;
1445
+ g_autofree char *img = NULL;
1446
+ char marker[9];
1447
+ int fd;
1448
+
1449
+ if (!have_qemu_img()) {
1450
+ g_test_skip("QTEST_QEMU_IMG not set, snapshots need a qcow2 image");
1451
+ return;
1452
+ }
1453
+
1454
+ fd = g_file_open_tmp("qtest-ide-snapshot.XXXXXX", &img, NULL);
1455
+ g_assert(fd >= 0);
1456
+ close(fd);
1457
+ g_assert(mkimg(img, "qcow2", TEST_IMAGE_SIZE / (1024 * 1024)));
1458
+
1459
+ qts = ide_test_start(
1460
+ "-blockdev driver=qcow2,node-name=hda,file.driver=file,"
1461
+ "file.filename=%s "
1462
+ "-device ide-hd,drive=hda,bus=ide.0,unit=0 ", img);
1463
+ dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
1464
+
1465
+ ide_prepare_markers(qts, dev, ide_bar);
1466
+
1467
+ /* Snapshot taken while the default translation is in effect */
1468
+ ide_read_chs_marker(qts, dev, ide_bar, 0, 1, 1, marker);
1469
+ g_assert_cmpstr(marker, ==, CHS_MARKER_DEFAULT);
1470
+ ide_hmp_quiet(qts, "savevm s0");
1471
+
1472
+ ide_set_translation(dev, ide_bar, 8, 32);
1473
+ ide_read_chs_marker(qts, dev, ide_bar, 0, 1, 1, marker);
1474
+ g_assert_cmpstr(marker, ==, CHS_MARKER_CUSTOM);
1475
+
1476
+ ide_hmp_quiet(qts, "loadvm s0");
1477
+
1478
+ ide_read_chs_marker(qts, dev, ide_bar, 0, 1, 1, marker);
1479
+ g_assert_cmpstr(marker, ==, CHS_MARKER_DEFAULT);
1480
+
1481
+ free_pci_device(dev);
1482
+ ide_test_quit(qts);
1483
+ unlink(img);
1484
+}
1485
+
1486
static void test_cdrom_pio(void)
1487
{
1488
cdrom_read_impl(1, CDROM_PIO);
1555
1556
qtest_add_func("/ide/read_native", test_specify);
1557
qtest_add_func("/ide/specify/zero_sectors", test_specify_zero_sectors);
1558
+ qtest_add_func("/ide/migration/chs_translation",
1559
+ test_migrate_chs_translation);
1560
+ qtest_add_func("/ide/migration/chs_snapshot", test_migrate_chs_snapshot);
1561
1562
qtest_add_func("/ide/identify", test_identify);
1563