@samitouri / QOSamiQemu / commits / 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: 176e4961bb33 ("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>

Denis V. Lunev committed Aug 14, 2026 at 17:46 UTC cafb3d96254fee4705d58cea2a8221498a361475
10 files changed +30 -25
hw/ide/ahci.c
+6 -6
@@ -37,7 +37,7 @@
37
38 static void check_cmd(AHCIState *s, int port);
39 static void handle_cmd(AHCIState *s, int port, uint8_t slot);
40 -static void ahci_reset_port(AHCIState *s, int port);
40 +static void ahci_reset_port(AHCIState *s, int port, IDEResetKind kind);
41 static bool ahci_write_fis_d2h(AHCIDevice *ad, bool d2h_fis_i);
42 static void ahci_clear_cmd_issue(AHCIDevice *ad, uint8_t slot);
43 static void ahci_init_d2h(AHCIDevice *ad);
@@ -334,7 +334,7 @@ static void ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
334 case AHCI_PORT_REG_SCR_CTL:
335 if (((pr->scr_ctl & AHCI_SCR_SCTL_DET) == 1) &&
336 ((val & AHCI_SCR_SCTL_DET) == 0)) {
337 - ahci_reset_port(s, port);
337 + ahci_reset_port(s, port, IDE_RESET_HARDWARE);
338 }
339 pr->scr_ctl = val;
340 break;
@@ -619,7 +619,7 @@ static void ahci_set_signature(AHCIDevice *ad, uint32_t sig)
619 s->lcyl, s->hcyl, sig);
620 }
621
622 -static void ahci_reset_port(AHCIState *s, int port)
622 +static void ahci_reset_port(AHCIState *s, int port, IDEResetKind kind)
623 {
624 AHCIDevice *d = &s->dev[port];
625 AHCIPortRegs *pr = &d->port_regs;
@@ -628,7 +628,7 @@ static void ahci_reset_port(AHCIState *s, int port)
628
629 trace_ahci_reset_port(s, port);
630
631 - ide_bus_reset(&d->port);
631 + ide_bus_reset(&d->port, kind);
632 ide_state->ncq_queues = AHCI_MAX_CMDS;
633
634 pr->scr_stat = 0;
@@ -1244,7 +1244,7 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
1244 * COMRESET or by setting and clearing the SRST bit. Therefore,
1245 * the logic for this is found in ahci_init_d2h() and not here.
1246 */
1247 - ahci_reset_port(s, port);
1247 + ahci_reset_port(s, port, IDE_RESET_SOFTWARE);
1248 }
1249 break;
1250 }
@@ -1650,7 +1650,7 @@ void ahci_reset(AHCIState *s)
1650 pr->irq_mask = 0;
1651 pr->scr_ctl = 0;
1652 pr->cmd = PORT_CMD_SPIN_UP | PORT_CMD_POWER_ON;
1653 - ahci_reset_port(s, i);
1653 + ahci_reset_port(s, i, IDE_RESET_HARDWARE);
1654 }
1655 }
1656
hw/ide/cmd646.c
+1 -1
@@ -214,7 +214,7 @@ static void cmd646_reset(DeviceState *dev)
214 unsigned int i;
215
216 for (i = 0; i < 2; i++) {
217 - ide_bus_reset(&d->bus[i]);
217 + ide_bus_reset(&d->bus[i], IDE_RESET_HARDWARE);
218 }
219 }
220
hw/ide/core.c
+9 -9
@@ -1347,7 +1347,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
1347 }
1348 }
1349
1350 -static void ide_reset(IDEState *s)
1350 +static void ide_reset(IDEState *s, IDEResetKind kind)
1351 {
1352 trace_ide_reset(s);
1353
@@ -1356,7 +1356,7 @@ static void ide_reset(IDEState *s)
1356 s->pio_aiocb = NULL;
1357 }
1358
1359 - if (s->reset_reverts) {
1359 + if (kind == IDE_RESET_HARDWARE || s->reset_reverts) {
1360 s->reset_reverts = false;
1361 s->heads = s->drive_heads;
1362 s->sectors = s->drive_sectors;
@@ -1424,7 +1424,7 @@ static bool cmd_device_reset(IDEState *s, uint8_t cmd)
1424 ide_cancel_dma_sync(s);
1425
1426 /* Reset any PIO commands, reset signature, etc */
1427 - ide_reset(s);
1427 + ide_reset(s, IDE_RESET_SOFTWARE);
1428
1429 /* RESET: ATA8-ACS3 7.10.4 "Normal Outputs";
1430 * ATA8-ACS3 Table 184 "Device Signatures for Normal Output" */
@@ -2348,7 +2348,7 @@ static void ide_perform_srst(IDEState *s)
2348 ide_cancel_dma_sync(s);
2349
2350 /* Cancel PIO callback, reset registers/signature, etc */
2351 - ide_reset(s);
2351 + ide_reset(s, IDE_RESET_SOFTWARE);
2352
2353 /* perform diagnostic */
2354 cmd_exec_dev_diagnostic(s, WIN_DIAGNOSE);
@@ -2553,7 +2553,7 @@ static void ide_dummy_transfer_stop(IDEState *s)
2553 s->io_buffer[3] = 0xff;
2554 }
2555
2556 -void ide_bus_reset(IDEBus *bus)
2556 +void ide_bus_reset(IDEBus *bus, IDEResetKind kind)
2557 {
2558 /* pending async DMA - needs the IDEState before it is reset */
2559 if (bus->dma->aiocb) {
@@ -2564,8 +2564,8 @@ void ide_bus_reset(IDEBus *bus)
2564
2565 bus->unit = 0;
2566 bus->cmd = 0;
2567 - ide_reset(&bus->ifs[0]);
2568 - ide_reset(&bus->ifs[1]);
2567 + ide_reset(&bus->ifs[0], kind);
2568 + ide_reset(&bus->ifs[1], kind);
2569 ide_clear_hob(bus);
2570
2571 /* reset dma provider too */
@@ -2679,7 +2679,7 @@ int ide_init_drive(IDEState *s, IDEDevice *dev, IDEDriveKind kind, Error **errp)
2679 pstrcpy(s->version, sizeof(s->version), QEMU_HW_VERSION);
2680 }
2681
2682 - ide_reset(s);
2682 + ide_reset(s, IDE_RESET_HARDWARE);
2683 blk_iostatus_enable(s->blk);
2684 return 0;
2685 }
@@ -2816,7 +2816,7 @@ void ide_bus_init_output_irq(IDEBus *bus, qemu_irq irq_out)
2816
2817 for(i = 0; i < 2; i++) {
2818 ide_init1(bus, i);
2819 - ide_reset(&bus->ifs[i]);
2819 + ide_reset(&bus->ifs[i], IDE_RESET_HARDWARE);
2820 }
2821 bus->irq = irq_out;
2822 bus->dma = &ide_dma_nop;
hw/ide/ide-internal.h
+6 -1
@@ -393,7 +393,12 @@ extern const VMStateDescription vmstate_ide_drive;
393 #define VMSTATE_IDE_DRIVE(_field, _state) \
394 VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_drive, IDEState)
395
396 -void ide_bus_reset(IDEBus *bus);
396 +typedef enum {
397 + IDE_RESET_HARDWARE, /* power on, hardware reset or COMRESET, ATA-5 9.1 */
398 + IDE_RESET_SOFTWARE, /* SRST or DEVICE RESET, ATA-5 9.2 */
399 +} IDEResetKind;
400 +
401 +void ide_bus_reset(IDEBus *bus, IDEResetKind kind);
402 int64_t ide_get_sector(IDEState *s);
403 void ide_set_sector(IDEState *s, int64_t sector_num);
404
hw/ide/isa.c
+1 -1
@@ -51,7 +51,7 @@ static void isa_ide_reset(DeviceState *d)
51 {
52 ISAIDEState *s = ISA_IDE(d);
53
54 - ide_bus_reset(&s->bus);
54 + ide_bus_reset(&s->bus, IDE_RESET_HARDWARE);
55 }
56
57 static const VMStateDescription vmstate_ide_isa = {
hw/ide/macio.c
+1 -1
@@ -368,7 +368,7 @@ static void macio_ide_reset(DeviceState *dev)
368 {
369 MACIOIDEState *d = MACIO_IDE(dev);
370
371 - ide_bus_reset(&d->bus);
371 + ide_bus_reset(&d->bus, IDE_RESET_HARDWARE);
372 }
373
374 static int ide_nop_int(const IDEDMA *dma, bool is_write)
hw/ide/mmio.c
+1 -1
@@ -55,7 +55,7 @@ static void mmio_ide_reset(DeviceState *dev)
55 {
56 MMIOIDEState *s = MMIO_IDE(dev);
57
58 - ide_bus_reset(&s->bus);
58 + ide_bus_reset(&s->bus, IDE_RESET_HARDWARE);
59 }
60
61 static uint64_t mmio_ide_read(void *opaque, hwaddr addr,
hw/ide/piix.c
+1 -1
@@ -111,7 +111,7 @@ static void piix_ide_reset(DeviceState *dev)
111 int i;
112
113 for (i = 0; i < 2; i++) {
114 - ide_bus_reset(&d->bus[i]);
114 + ide_bus_reset(&d->bus[i], IDE_RESET_HARDWARE);
115 }
116
117 /* PCI command register default value (0000h) per [1, p.48]. */
hw/ide/sii3112.c
+3 -3
@@ -185,7 +185,7 @@ static void sii3112_reg_write(void *opaque, hwaddr addr,
185 case 0x100:
186 d->regs[0].scontrol = val & 0xfff;
187 if (val & 1) {
188 - ide_bus_reset(&d->i.bus[0]);
188 + ide_bus_reset(&d->i.bus[0], IDE_RESET_HARDWARE);
189 }
190 break;
191 case 0x148:
@@ -194,7 +194,7 @@ static void sii3112_reg_write(void *opaque, hwaddr addr,
194 case 0x180:
195 d->regs[1].scontrol = val & 0xfff;
196 if (val & 1) {
197 - ide_bus_reset(&d->i.bus[1]);
197 + ide_bus_reset(&d->i.bus[1], IDE_RESET_HARDWARE);
198 }
199 break;
200 case 0x1c8:
@@ -243,7 +243,7 @@ static void sii3112_reset(DeviceState *dev)
243
244 for (i = 0; i < 2; i++) {
245 s->regs[i].confstat = 0x6515 << 16;
246 - ide_bus_reset(&s->i.bus[i]);
246 + ide_bus_reset(&s->i.bus[i], IDE_RESET_HARDWARE);
247 }
248 }
249
hw/ide/via.c
+1 -1
@@ -127,7 +127,7 @@ static void via_ide_reset(DeviceState *dev)
127 int i;
128
129 for (i = 0; i < ARRAY_SIZE(d->bus); i++) {
130 - ide_bus_reset(&d->bus[i]);
130 + ide_bus_reset(&d->bus[i], IDE_RESET_HARDWARE);
131 }
132
133 pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy mode */