[PATCH 08/15] hw/ide: migrate the logical CHS translation
"Denis V. Lunev" <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu.block,gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
From: Denis V. Lunev <[email protected]> INITIALIZE DEVICE PARAMETERS lets a guest replace the logical CHS translation used to turn the CHS registers into an LBA, but s->heads and s->sectors were in no VMStateDescription. The destination rebuilt them from the drive configuration, so a guest that had selected one of its own kept addressing the disk in it while the device translated with the default, landing on sectors nobody asked for. Add a subsection for it, sent only when the guest replaced the default, so that migration to an older QEMU keeps working for every other guest. s->cylinders is left out, as no command changes it. Validate what is loaded in the existing post_load: ide_get_sector() multiplies by these fields and ide_set_sector() divides by them. Cc: John Snow <[email protected]> Cc: Peter Maydell <[email protected]> Fixes: 176e4961bb33 ("hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command") Signed-off-by: Denis V. Lunev <[email protected]> --- hw/ide/core.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/hw/ide/core.c b/hw/ide/core.c index 3b67409eb4..ab8c23e5b9 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2879,6 +2879,13 @@ static int ide_drive_post_load(void *opaque, int version_id) { IDEState *s = opaque; + /* Only a disk has a translation; an empty slot and ATAPI keep these zero */ + if (s->blk && s->drive_kind != IDE_CD && + (s->heads < 1 || s->heads > 16 || + s->sectors < 1 || s->sectors > 255)) { + return -EINVAL; + } + if (s->blk && s->identify_set) { blk_set_enable_write_cache(s->blk, !!(s->identify_data[85] & (1 << 5))); } @@ -2962,6 +2969,25 @@ static const VMStateDescription vmstate_ide_atapi_gesn_state = { } }; +static bool ide_chs_translation_needed(void *opaque) +{ + IDEState *s = opaque; + + return s->heads != s->drive_heads || s->sectors != s->drive_sectors; +} + +static const VMStateDescription vmstate_ide_drive_chs_translation = { + .name = "ide_drive/chs_translation", + .version_id = 1, + .minimum_version_id = 1, + .needed = ide_chs_translation_needed, + .fields = (const VMStateField[]) { + VMSTATE_INT32(heads, IDEState), + VMSTATE_INT32(sectors, IDEState), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_ide_tray_state = { .name = "ide_drive/tray_state", .version_id = 1, @@ -3025,6 +3051,7 @@ const VMStateDescription vmstate_ide_drive = { }, .subsections = (const VMStateDescription * const []) { &vmstate_ide_drive_pio_state, + &vmstate_ide_drive_chs_translation, &vmstate_ide_tray_state, &vmstate_ide_atapi_gesn_state, NULL -- 2.53.0