migration/next for 20150612

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJVemZ1AAoJEPSH7xhYctcjfNwP/jNl1Qe6TNruhMFjcR2jUwhe
 hg/5suRb1XKIga857yWBnFxLdNLxBgwu5XiKENKz5gpjco51MUTMdS5JnfeQbmoE
 J1hbCwT9THjPwT4IjfVcBeW7NYfKT1fA/XUiXozl2/BAN73zbxusMfy9FiL83uRa
 tb7du6Z7MSAfY0BMtHcD/39LOgroH4eKRS0OgquprO+TOcMHU/FSW8LOjF+9N3x9
 HRAxzqzKCiDJzw6xIi6+bdhDexcCa/CQHt2gIG4165gvfnnAsidkCcfFUOTqqVUO
 nPUtbUJFhSv8MUE9gnY5MaG2HZUAdcHxR6dj4dCel2f2O436IA7VZDAmBFXDXr5e
 zKslHU7HAGbtMbqDjkL0Tacd3NuNZlqU+Ib6NuMgLqn6mstLo/rebPoAbMNDm1nj
 hxFLswAYrUn9P3eT5uzoCETgWyyfmPRlp7d9sOXoMqgYzMnfuq3BLnDxQOP9jSCD
 dJY5poOeyQK74iNzzcRRuQo6gfJNG+ktqocapldQ06O//dKEue+wZIcnga09a2rw
 EyfJq6KaVEfhyxbWrsynIP/UGjieIAKV3D7ijJfcSySregZKPAO3JZRpLKzCzSpH
 mU79SGEMVZwk9s1lj69A2toX/B3c8N3Rn7LcHpCdAUQweJiPyeZsDr1lADSVOAEr
 MMcanhHBu9j3rLK01QWf
 =AQxN
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20150612' into staging

migration/next for 20150612

# gpg: Signature made Fri Jun 12 05:56:21 2015 BST using RSA key ID 5872D723
# gpg: Good signature from "Juan Quintela <quintela@redhat.com>"
# gpg:                 aka "Juan Quintela <quintela@trasno.org>"

* remotes/juanquintela/tags/migration/20150612: (21 commits)
  Remove unneeded memset
  Rename RDMA structures to make destination clear
  Teach analyze-migration.py about section footers
  Add a protective section footer
  Disable section footers on older machine types
  Merge section header writing
  Move loadvm_handlers into MigrationIncomingState
  Move copy out of qemu_peek_buffer
  Create MigrationIncomingState
  qemu_ram_foreach_block: pass up error value, and down the ramblock name
  Split header writing out of qemu_savevm_state_begin
  Add qemu_get_counted_string to read a string prefixed by a count byte
  migration: Use normal VMStateDescriptions for Subsections
  migration: create savevm_state
  migration: Remove duplicated assignment of SETUP status
  rdma: Fix qemu crash when IPv6 address is used for migration
  arch_init: Clean up the duplicate variable 'len' defining in ram_load()
  migration: reduce include files
  migration: Add myself to the copyright list of both files
  migration: move savevm.c inside migration/
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-06-12 11:06:03 +01:00
commit a4ef02fd9b
49 changed files with 2204 additions and 2157 deletions

View File

@ -1014,8 +1014,6 @@ M: Amit Shah <amit.shah@redhat.com>
S: Maintained S: Maintained
F: include/migration/ F: include/migration/
F: migration/ F: migration/
F: savevm.c
F: arch_init.c
F: scripts/vmstate-static-checker.py F: scripts/vmstate-static-checker.py
F: tests/vmstate-static-checker-data/ F: tests/vmstate-static-checker-data/

View File

@ -132,9 +132,10 @@ obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
obj-y += qtest.o bootdevice.o obj-y += qtest.o bootdevice.o
obj-y += hw/ obj-y += hw/
obj-$(CONFIG_KVM) += kvm-all.o obj-$(CONFIG_KVM) += kvm-all.o
obj-y += memory.o savevm.o cputlb.o obj-y += memory.o cputlb.o
obj-y += memory_mapping.o obj-y += memory_mapping.o
obj-y += dump.o obj-y += dump.o
obj-y += migration/ram.o migration/savevm.o
LIBS := $(libs_softmmu) $(LIBS) LIBS := $(libs_softmmu) $(LIBS)
# xen support # xen support

File diff suppressed because it is too large Load Diff

11
cpus.c
View File

@ -480,6 +480,7 @@ static const VMStateDescription icount_vmstate_timers = {
.name = "timer/icount", .name = "timer/icount",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = icount_state_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT64(qemu_icount_bias, TimersState), VMSTATE_INT64(qemu_icount_bias, TimersState),
VMSTATE_INT64(qemu_icount, TimersState), VMSTATE_INT64(qemu_icount, TimersState),
@ -497,13 +498,9 @@ static const VMStateDescription vmstate_timers = {
VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2), VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &icount_vmstate_timers,
.vmsd = &icount_vmstate_timers, NULL
.needed = icount_state_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -257,6 +257,7 @@ const VMStateDescription vmstate_ide_drive_pio_state = {
.minimum_version_id = 1, .minimum_version_id = 1,
.pre_save = ide_drive_pio_pre_save, .pre_save = ide_drive_pio_pre_save,
.post_load = ide_drive_pio_post_load, .post_load = ide_drive_pio_post_load,
.needed = ide_drive_pio_state_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(req_nb_sectors, IDEState), VMSTATE_INT32(req_nb_sectors, IDEState),
VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1, VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1,
@ -279,13 +280,9 @@ const VMStateDescription vmstate_ide_drive = {
.... several fields .... .... several fields ....
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_ide_drive_pio_state,
.vmsd = &vmstate_ide_drive_pio_state, NULL
.needed = ide_drive_pio_state_needed,
}, {
/* empty */
}
} }
}; };

21
exec.c
View File

@ -454,6 +454,7 @@ static const VMStateDescription vmstate_cpu_common_exception_index = {
.name = "cpu_common/exception_index", .name = "cpu_common/exception_index",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = cpu_common_exception_index_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(exception_index, CPUState), VMSTATE_INT32(exception_index, CPUState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -471,13 +472,9 @@ const VMStateDescription vmstate_cpu_common = {
VMSTATE_UINT32(interrupt_request, CPUState), VMSTATE_UINT32(interrupt_request, CPUState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_cpu_common_exception_index,
.vmsd = &vmstate_cpu_common_exception_index, NULL
.needed = cpu_common_exception_index_needed,
} , {
/* empty */
}
} }
}; };
@ -3348,14 +3345,20 @@ bool cpu_physical_memory_is_io(hwaddr phys_addr)
return res; return res;
} }
void qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque) int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque)
{ {
RAMBlock *block; RAMBlock *block;
int ret = 0;
rcu_read_lock(); rcu_read_lock();
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
func(block->host, block->offset, block->used_length, opaque); ret = func(block->idstr, block->host, block->offset,
block->used_length, opaque);
if (ret) {
break;
}
} }
rcu_read_unlock(); rcu_read_unlock();
return ret;
} }
#endif #endif

View File

@ -152,6 +152,7 @@ static const VMStateDescription vmstate_memhp_state = {
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.minimum_version_id_old = 1, .minimum_version_id_old = 1,
.needed = vmstate_test_use_memhp,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, ICH9LPCPMRegs), VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, ICH9LPCPMRegs),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -175,12 +176,9 @@ const VMStateDescription vmstate_ich9_pm = {
VMSTATE_UINT32(smi_sts, ICH9LPCPMRegs), VMSTATE_UINT32(smi_sts, ICH9LPCPMRegs),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_memhp_state,
.vmsd = &vmstate_memhp_state, NULL
.needed = vmstate_test_use_memhp,
},
VMSTATE_END_OF_LIST()
} }
}; };

View File

@ -260,6 +260,7 @@ static const VMStateDescription vmstate_memhp_state = {
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.minimum_version_id_old = 1, .minimum_version_id_old = 1,
.needed = vmstate_test_use_memhp,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, PIIX4PMState), VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, PIIX4PMState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -298,12 +299,9 @@ static const VMStateDescription vmstate_acpi = {
vmstate_test_use_acpi_pci_hotplug), vmstate_test_use_acpi_pci_hotplug),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_memhp_state,
.vmsd = &vmstate_memhp_state, NULL
.needed = vmstate_test_use_memhp,
},
VMSTATE_END_OF_LIST()
} }
}; };

View File

@ -699,6 +699,7 @@ static const VMStateDescription vmstate_fdrive_media_changed = {
.name = "fdrive/media_changed", .name = "fdrive/media_changed",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = fdrive_media_changed_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8(media_changed, FDrive), VMSTATE_UINT8(media_changed, FDrive),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -716,6 +717,7 @@ static const VMStateDescription vmstate_fdrive_media_rate = {
.name = "fdrive/media_rate", .name = "fdrive/media_rate",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = fdrive_media_rate_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8(media_rate, FDrive), VMSTATE_UINT8(media_rate, FDrive),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -733,6 +735,7 @@ static const VMStateDescription vmstate_fdrive_perpendicular = {
.name = "fdrive/perpendicular", .name = "fdrive/perpendicular",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = fdrive_perpendicular_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8(perpendicular, FDrive), VMSTATE_UINT8(perpendicular, FDrive),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -756,19 +759,11 @@ static const VMStateDescription vmstate_fdrive = {
VMSTATE_UINT8(sect, FDrive), VMSTATE_UINT8(sect, FDrive),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_fdrive_media_changed,
.vmsd = &vmstate_fdrive_media_changed, &vmstate_fdrive_media_rate,
.needed = &fdrive_media_changed_needed, &vmstate_fdrive_perpendicular,
} , { NULL
.vmsd = &vmstate_fdrive_media_rate,
.needed = &fdrive_media_rate_needed,
} , {
.vmsd = &vmstate_fdrive_perpendicular,
.needed = &fdrive_perpendicular_needed,
} , {
/* empty */
}
} }
}; };
@ -833,6 +828,7 @@ static const VMStateDescription vmstate_fdc_reset_sensei = {
.name = "fdc/reset_sensei", .name = "fdc/reset_sensei",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = fdc_reset_sensei_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(reset_sensei, FDCtrl), VMSTATE_INT32(reset_sensei, FDCtrl),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -850,6 +846,7 @@ static const VMStateDescription vmstate_fdc_result_timer = {
.name = "fdc/result_timer", .name = "fdc/result_timer",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = fdc_result_timer_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_TIMER_PTR(result_timer, FDCtrl), VMSTATE_TIMER_PTR(result_timer, FDCtrl),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -867,6 +864,7 @@ static const VMStateDescription vmstate_fdc_phase = {
.name = "fdc/phase", .name = "fdc/phase",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = fdc_phase_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8(phase, FDCtrl), VMSTATE_UINT8(phase, FDCtrl),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -911,19 +909,11 @@ static const VMStateDescription vmstate_fdc = {
vmstate_fdrive, FDrive), vmstate_fdrive, FDrive),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_fdc_reset_sensei,
.vmsd = &vmstate_fdc_reset_sensei, &vmstate_fdc_result_timer,
.needed = fdc_reset_sensei_needed, &vmstate_fdc_phase,
} , { NULL
.vmsd = &vmstate_fdc_result_timer,
.needed = fdc_result_timer_needed,
} , {
.vmsd = &vmstate_fdc_phase,
.needed = fdc_phase_needed,
} , {
/* empty */
}
} }
}; };

View File

@ -662,6 +662,7 @@ static const VMStateDescription vmstate_serial_thr_ipending = {
.name = "serial/thr_ipending", .name = "serial/thr_ipending",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = serial_thr_ipending_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(thr_ipending, SerialState), VMSTATE_INT32(thr_ipending, SerialState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -678,6 +679,7 @@ static const VMStateDescription vmstate_serial_tsr = {
.name = "serial/tsr", .name = "serial/tsr",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = serial_tsr_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(tsr_retry, SerialState), VMSTATE_INT32(tsr_retry, SerialState),
VMSTATE_UINT8(thr, SerialState), VMSTATE_UINT8(thr, SerialState),
@ -697,6 +699,7 @@ static const VMStateDescription vmstate_serial_recv_fifo = {
.name = "serial/recv_fifo", .name = "serial/recv_fifo",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = serial_recv_fifo_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_STRUCT(recv_fifo, SerialState, 1, vmstate_fifo8, Fifo8), VMSTATE_STRUCT(recv_fifo, SerialState, 1, vmstate_fifo8, Fifo8),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -713,6 +716,7 @@ static const VMStateDescription vmstate_serial_xmit_fifo = {
.name = "serial/xmit_fifo", .name = "serial/xmit_fifo",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = serial_xmit_fifo_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_STRUCT(xmit_fifo, SerialState, 1, vmstate_fifo8, Fifo8), VMSTATE_STRUCT(xmit_fifo, SerialState, 1, vmstate_fifo8, Fifo8),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -729,6 +733,7 @@ static const VMStateDescription vmstate_serial_fifo_timeout_timer = {
.name = "serial/fifo_timeout_timer", .name = "serial/fifo_timeout_timer",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = serial_fifo_timeout_timer_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_TIMER_PTR(fifo_timeout_timer, SerialState), VMSTATE_TIMER_PTR(fifo_timeout_timer, SerialState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -745,6 +750,7 @@ static const VMStateDescription vmstate_serial_timeout_ipending = {
.name = "serial/timeout_ipending", .name = "serial/timeout_ipending",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = serial_timeout_ipending_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(timeout_ipending, SerialState), VMSTATE_INT32(timeout_ipending, SerialState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -760,6 +766,7 @@ static bool serial_poll_needed(void *opaque)
static const VMStateDescription vmstate_serial_poll = { static const VMStateDescription vmstate_serial_poll = {
.name = "serial/poll", .name = "serial/poll",
.version_id = 1, .version_id = 1,
.needed = serial_poll_needed,
.minimum_version_id = 1, .minimum_version_id = 1,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(poll_msl, SerialState), VMSTATE_INT32(poll_msl, SerialState),
@ -788,31 +795,15 @@ const VMStateDescription vmstate_serial = {
VMSTATE_UINT8_V(fcr_vmstate, SerialState, 3), VMSTATE_UINT8_V(fcr_vmstate, SerialState, 3),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_serial_thr_ipending,
.vmsd = &vmstate_serial_thr_ipending, &vmstate_serial_tsr,
.needed = &serial_thr_ipending_needed, &vmstate_serial_recv_fifo,
} , { &vmstate_serial_xmit_fifo,
.vmsd = &vmstate_serial_tsr, &vmstate_serial_fifo_timeout_timer,
.needed = &serial_tsr_needed, &vmstate_serial_timeout_ipending,
} , { &vmstate_serial_poll,
.vmsd = &vmstate_serial_recv_fifo, NULL
.needed = &serial_recv_fifo_needed,
} , {
.vmsd = &vmstate_serial_xmit_fifo,
.needed = &serial_xmit_fifo_needed,
} , {
.vmsd = &vmstate_serial_fifo_timeout_timer,
.needed = &serial_fifo_timeout_timer_needed,
} , {
.vmsd = &vmstate_serial_timeout_ipending,
.needed = &serial_timeout_ipending_needed,
} , {
.vmsd = &vmstate_serial_poll,
.needed = &serial_poll_needed,
} , {
/* empty */
}
} }
}; };

View File

@ -2220,6 +2220,7 @@ static VMStateDescription qxl_vmstate_monitors_config = {
.name = "qxl/monitors-config", .name = "qxl/monitors-config",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = qxl_monitors_config_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice), VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -2253,13 +2254,9 @@ static VMStateDescription qxl_vmstate = {
VMSTATE_UINT64(guest_cursor, PCIQXLDevice), VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &qxl_vmstate_monitors_config,
.vmsd = &qxl_vmstate_monitors_config, NULL
.needed = qxl_monitors_config_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -2035,6 +2035,7 @@ static const VMStateDescription vmstate_vga_endian = {
.name = "vga.endian", .name = "vga.endian",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = vga_endian_state_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_BOOL(big_endian_fb, VGACommonState), VMSTATE_BOOL(big_endian_fb, VGACommonState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -2078,13 +2079,9 @@ const VMStateDescription vmstate_vga_common = {
VMSTATE_UINT32(vbe_bank_mask, VGACommonState), VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_vga_endian,
.vmsd = &vmstate_vga_endian, NULL
.needed = vga_endian_state_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -52,6 +52,7 @@
#ifdef CONFIG_XEN #ifdef CONFIG_XEN
# include <xen/hvm/hvm_info_table.h> # include <xen/hvm/hvm_info_table.h>
#endif #endif
#include "migration/migration.h"
#define MAX_IDE_BUS 2 #define MAX_IDE_BUS 2
@ -305,6 +306,7 @@ static void pc_init1(MachineState *machine)
static void pc_compat_2_3(MachineState *machine) static void pc_compat_2_3(MachineState *machine)
{ {
savevm_skip_section_footers();
} }
static void pc_compat_2_2(MachineState *machine) static void pc_compat_2_2(MachineState *machine)

View File

@ -45,6 +45,7 @@
#include "hw/usb.h" #include "hw/usb.h"
#include "hw/cpu/icc_bus.h" #include "hw/cpu/icc_bus.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "migration/migration.h"
/* ICH9 AHCI has 6 ports */ /* ICH9 AHCI has 6 ports */
#define MAX_SATA_PORTS 6 #define MAX_SATA_PORTS 6
@ -289,6 +290,7 @@ static void pc_q35_init(MachineState *machine)
static void pc_compat_2_3(MachineState *machine) static void pc_compat_2_3(MachineState *machine)
{ {
savevm_skip_section_footers();
} }
static void pc_compat_2_2(MachineState *machine) static void pc_compat_2_2(MachineState *machine)

View File

@ -2561,6 +2561,7 @@ static const VMStateDescription vmstate_ide_atapi_gesn_state = {
.name ="ide_drive/atapi/gesn_state", .name ="ide_drive/atapi/gesn_state",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = ide_atapi_gesn_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_BOOL(events.new_media, IDEState), VMSTATE_BOOL(events.new_media, IDEState),
VMSTATE_BOOL(events.eject_request, IDEState), VMSTATE_BOOL(events.eject_request, IDEState),
@ -2572,6 +2573,7 @@ static const VMStateDescription vmstate_ide_tray_state = {
.name = "ide_drive/tray_state", .name = "ide_drive/tray_state",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = ide_tray_state_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_BOOL(tray_open, IDEState), VMSTATE_BOOL(tray_open, IDEState),
VMSTATE_BOOL(tray_locked, IDEState), VMSTATE_BOOL(tray_locked, IDEState),
@ -2585,6 +2587,7 @@ static const VMStateDescription vmstate_ide_drive_pio_state = {
.minimum_version_id = 1, .minimum_version_id = 1,
.pre_save = ide_drive_pio_pre_save, .pre_save = ide_drive_pio_pre_save,
.post_load = ide_drive_pio_post_load, .post_load = ide_drive_pio_post_load,
.needed = ide_drive_pio_state_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(req_nb_sectors, IDEState), VMSTATE_INT32(req_nb_sectors, IDEState),
VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1, VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1,
@ -2626,19 +2629,11 @@ const VMStateDescription vmstate_ide_drive = {
VMSTATE_UINT8_V(cdrom_changed, IDEState, 3), VMSTATE_UINT8_V(cdrom_changed, IDEState, 3),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_ide_drive_pio_state,
.vmsd = &vmstate_ide_drive_pio_state, &vmstate_ide_tray_state,
.needed = ide_drive_pio_state_needed, &vmstate_ide_atapi_gesn_state,
}, { NULL
.vmsd = &vmstate_ide_tray_state,
.needed = ide_tray_state_needed,
}, {
.vmsd = &vmstate_ide_atapi_gesn_state,
.needed = ide_atapi_gesn_needed,
}, {
/* empty */
}
} }
}; };
@ -2646,6 +2641,7 @@ static const VMStateDescription vmstate_ide_error_status = {
.name ="ide_bus/error", .name ="ide_bus/error",
.version_id = 2, .version_id = 2,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = ide_error_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(error_status, IDEBus), VMSTATE_INT32(error_status, IDEBus),
VMSTATE_INT64_V(retry_sector_num, IDEBus, 2), VMSTATE_INT64_V(retry_sector_num, IDEBus, 2),
@ -2664,13 +2660,9 @@ const VMStateDescription vmstate_ide_bus = {
VMSTATE_UINT8(unit, IDEBus), VMSTATE_UINT8(unit, IDEBus),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_ide_error_status,
.vmsd = &vmstate_ide_error_status, NULL
.needed = ide_error_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -350,6 +350,7 @@ static const VMStateDescription vmstate_bmdma_current = {
.name = "ide bmdma_current", .name = "ide bmdma_current",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = ide_bmdma_current_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT32(cur_addr, BMDMAState), VMSTATE_UINT32(cur_addr, BMDMAState),
VMSTATE_UINT32(cur_prd_last, BMDMAState), VMSTATE_UINT32(cur_prd_last, BMDMAState),
@ -363,6 +364,7 @@ static const VMStateDescription vmstate_bmdma_status = {
.name ="ide bmdma/status", .name ="ide bmdma/status",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = ide_bmdma_status_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8(status, BMDMAState), VMSTATE_UINT8(status, BMDMAState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -383,16 +385,10 @@ static const VMStateDescription vmstate_bmdma = {
VMSTATE_UINT8(migration_retry_unit, BMDMAState), VMSTATE_UINT8(migration_retry_unit, BMDMAState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_bmdma_current,
.vmsd = &vmstate_bmdma_current, &vmstate_bmdma_status,
.needed = ide_bmdma_current_needed, NULL
}, {
.vmsd = &vmstate_bmdma_status,
.needed = ide_bmdma_status_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -391,23 +391,24 @@ static int kbd_outport_post_load(void *opaque, int version_id)
return 0; return 0;
} }
static const VMStateDescription vmstate_kbd_outport = {
.name = "pckbd_outport",
.version_id = 1,
.minimum_version_id = 1,
.post_load = kbd_outport_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT8(outport, KBDState),
VMSTATE_END_OF_LIST()
}
};
static bool kbd_outport_needed(void *opaque) static bool kbd_outport_needed(void *opaque)
{ {
KBDState *s = opaque; KBDState *s = opaque;
return s->outport != kbd_outport_default(s); return s->outport != kbd_outport_default(s);
} }
static const VMStateDescription vmstate_kbd_outport = {
.name = "pckbd_outport",
.version_id = 1,
.minimum_version_id = 1,
.post_load = kbd_outport_post_load,
.needed = kbd_outport_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(outport, KBDState),
VMSTATE_END_OF_LIST()
}
};
static int kbd_post_load(void *opaque, int version_id) static int kbd_post_load(void *opaque, int version_id)
{ {
KBDState *s = opaque; KBDState *s = opaque;
@ -430,12 +431,9 @@ static const VMStateDescription vmstate_kbd = {
VMSTATE_UINT8(pending, KBDState), VMSTATE_UINT8(pending, KBDState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_kbd_outport,
.vmsd = &vmstate_kbd_outport, NULL
.needed = kbd_outport_needed,
},
VMSTATE_END_OF_LIST()
} }
}; };

View File

@ -677,6 +677,7 @@ static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
.version_id = 3, .version_id = 3,
.minimum_version_id = 2, .minimum_version_id = 2,
.post_load = ps2_kbd_ledstate_post_load, .post_load = ps2_kbd_ledstate_post_load,
.needed = ps2_keyboard_ledstate_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(ledstate, PS2KbdState), VMSTATE_INT32(ledstate, PS2KbdState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -717,13 +718,9 @@ static const VMStateDescription vmstate_ps2_keyboard = {
VMSTATE_INT32_V(scancode_set, PS2KbdState,3), VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_ps2_keyboard_ledstate,
.vmsd = &vmstate_ps2_keyboard_ledstate, NULL
.needed = ps2_keyboard_ledstate_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -369,6 +369,7 @@ static const VMStateDescription vmstate_apic_common_sipi = {
.name = "apic_sipi", .name = "apic_sipi",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = apic_common_sipi_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32(sipi_vector, APICCommonState), VMSTATE_INT32(sipi_vector, APICCommonState),
VMSTATE_INT32(wait_for_sipi, APICCommonState), VMSTATE_INT32(wait_for_sipi, APICCommonState),
@ -408,12 +409,9 @@ static const VMStateDescription vmstate_apic_common = {
APICCommonState), /* open-coded timer state */ APICCommonState), /* open-coded timer state */
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_apic_common_sipi,
.vmsd = &vmstate_apic_common_sipi, NULL
.needed = apic_common_sipi_needed,
},
VMSTATE_END_OF_LIST()
} }
}; };

View File

@ -650,6 +650,7 @@ static const VMStateDescription vmstate_ich9_rst_cnt = {
.name = "ICH9LPC/rst_cnt", .name = "ICH9LPC/rst_cnt",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = ich9_rst_cnt_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8(rst_cnt, ICH9LPCState), VMSTATE_UINT8(rst_cnt, ICH9LPCState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -669,12 +670,9 @@ static const VMStateDescription vmstate_ich9_lpc = {
VMSTATE_UINT32(sci_level, ICH9LPCState), VMSTATE_UINT32(sci_level, ICH9LPCState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_ich9_rst_cnt,
.vmsd = &vmstate_ich9_rst_cnt, NULL
.needed = ich9_rst_cnt_needed
},
{ 0 }
} }
}; };

View File

@ -1370,6 +1370,7 @@ static const VMStateDescription vmstate_e1000_mit_state = {
.name = "e1000/mit_state", .name = "e1000/mit_state",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = e1000_mit_state_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT32(mac_reg[RDTR], E1000State), VMSTATE_UINT32(mac_reg[RDTR], E1000State),
VMSTATE_UINT32(mac_reg[RADV], E1000State), VMSTATE_UINT32(mac_reg[RADV], E1000State),
@ -1457,13 +1458,9 @@ static const VMStateDescription vmstate_e1000 = {
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128), VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_e1000_mit_state,
.vmsd = &vmstate_e1000_mit_state, NULL
.needed = e1000_mit_state_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -3240,6 +3240,7 @@ static const VMStateDescription vmstate_rtl8139_hotplug_ready ={
.name = "rtl8139/hotplug_ready", .name = "rtl8139/hotplug_ready",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = rtl8139_hotplug_ready_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
} }
@ -3335,13 +3336,9 @@ static const VMStateDescription vmstate_rtl8139 = {
VMSTATE_UINT32_V(cplus_enabled, RTL8139State, 4), VMSTATE_UINT32_V(cplus_enabled, RTL8139State, 4),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_rtl8139_hotplug_ready,
.vmsd = &vmstate_rtl8139_hotplug_ready, NULL
.needed = rtl8139_hotplug_ready_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -2226,6 +2226,7 @@ static const VMStateDescription vmxstate_vmxnet3_mcast_list = {
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.pre_load = vmxnet3_mcast_list_pre_load, .pre_load = vmxnet3_mcast_list_pre_load,
.needed = vmxnet3_mc_list_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_VBUFFER_UINT32(mcast_list, VMXNET3State, 0, NULL, 0, VMSTATE_VBUFFER_UINT32(mcast_list, VMXNET3State, 0, NULL, 0,
mcast_list_buff_size), mcast_list_buff_size),
@ -2470,14 +2471,9 @@ static const VMStateDescription vmstate_vmxnet3 = {
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmxstate_vmxnet3_mcast_list,
.vmsd = &vmxstate_vmxnet3_mcast_list, NULL
.needed = vmxnet3_mc_list_needed
},
{
/* empty element. */
}
} }
}; };

View File

@ -582,6 +582,7 @@ static const VMStateDescription vmstate_piix3_rcr = {
.name = "PIIX3/rcr", .name = "PIIX3/rcr",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = piix3_rcr_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8(rcr, PIIX3State), VMSTATE_UINT8(rcr, PIIX3State),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -600,12 +601,9 @@ static const VMStateDescription vmstate_piix3 = {
PIIX_NUM_PIRQS, 3), PIIX_NUM_PIRQS, 3),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_piix3_rcr,
.vmsd = &vmstate_piix3_rcr, NULL
.needed = piix3_rcr_needed,
},
{ 0 }
} }
}; };

View File

@ -1968,6 +1968,7 @@ static const VMStateDescription vmstate_scsi_sense_state = {
.name = "SCSIDevice/sense", .name = "SCSIDevice/sense",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = scsi_sense_state_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8_SUB_ARRAY(sense, SCSIDevice, VMSTATE_UINT8_SUB_ARRAY(sense, SCSIDevice,
SCSI_SENSE_BUF_SIZE_OLD, SCSI_SENSE_BUF_SIZE_OLD,
@ -1998,13 +1999,9 @@ const VMStateDescription vmstate_scsi_device = {
}, },
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_scsi_sense_state,
.vmsd = &vmstate_scsi_sense_state, NULL
.needed = scsi_sense_state_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -283,6 +283,7 @@ static const VMStateDescription vmstate_hpet_rtc_irq_level = {
.name = "hpet/rtc_irq_level", .name = "hpet/rtc_irq_level",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = hpet_rtc_irq_level_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8(rtc_irq_level, HPETState), VMSTATE_UINT8(rtc_irq_level, HPETState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -322,13 +323,9 @@ static const VMStateDescription vmstate_hpet = {
vmstate_hpet_timer, HPETTimer), vmstate_hpet_timer, HPETTimer),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_hpet_rtc_irq_level,
.vmsd = &vmstate_hpet_rtc_irq_level, NULL
.needed = hpet_rtc_irq_level_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -733,22 +733,23 @@ static int rtc_post_load(void *opaque, int version_id)
return 0; return 0;
} }
static const VMStateDescription vmstate_rtc_irq_reinject_on_ack_count = {
.name = "mc146818rtc/irq_reinject_on_ack_count",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT16(irq_reinject_on_ack_count, RTCState),
VMSTATE_END_OF_LIST()
}
};
static bool rtc_irq_reinject_on_ack_count_needed(void *opaque) static bool rtc_irq_reinject_on_ack_count_needed(void *opaque)
{ {
RTCState *s = (RTCState *)opaque; RTCState *s = (RTCState *)opaque;
return s->irq_reinject_on_ack_count != 0; return s->irq_reinject_on_ack_count != 0;
} }
static const VMStateDescription vmstate_rtc_irq_reinject_on_ack_count = {
.name = "mc146818rtc/irq_reinject_on_ack_count",
.version_id = 1,
.minimum_version_id = 1,
.needed = rtc_irq_reinject_on_ack_count_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT16(irq_reinject_on_ack_count, RTCState),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_rtc = { static const VMStateDescription vmstate_rtc = {
.name = "mc146818rtc", .name = "mc146818rtc",
.version_id = 3, .version_id = 3,
@ -770,13 +771,9 @@ static const VMStateDescription vmstate_rtc = {
VMSTATE_UINT64_V(next_alarm_time, RTCState, 3), VMSTATE_UINT64_V(next_alarm_time, RTCState, 3),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_rtc_irq_reinject_on_ack_count,
.vmsd = &vmstate_rtc_irq_reinject_on_ack_count, NULL
.needed = rtc_irq_reinject_on_ack_count_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -2034,6 +2034,7 @@ static const VMStateDescription vmstate_ohci_eof_timer = {
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.pre_load = ohci_eof_timer_pre_load, .pre_load = ohci_eof_timer_pre_load,
.needed = ohci_eof_timer_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_TIMER_PTR(eof_timer, OHCIState), VMSTATE_TIMER_PTR(eof_timer, OHCIState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -2081,13 +2082,9 @@ static const VMStateDescription vmstate_ohci_state = {
VMSTATE_BOOL(async_complete, OHCIState), VMSTATE_BOOL(async_complete, OHCIState),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_ohci_eof_timer,
.vmsd = &vmstate_ohci_eof_timer, NULL
.needed = ohci_eof_timer_needed,
} , {
/* empty */
}
} }
}; };

View File

@ -2257,16 +2257,6 @@ static const VMStateInfo usbredir_ep_bufpq_vmstate_info = {
/* For endp_data migration */ /* For endp_data migration */
static const VMStateDescription usbredir_bulk_receiving_vmstate = {
.name = "usb-redir-ep/bulk-receiving",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT8(bulk_receiving_started, struct endp_data),
VMSTATE_END_OF_LIST()
}
};
static bool usbredir_bulk_receiving_needed(void *priv) static bool usbredir_bulk_receiving_needed(void *priv)
{ {
struct endp_data *endp = priv; struct endp_data *endp = priv;
@ -2274,12 +2264,13 @@ static bool usbredir_bulk_receiving_needed(void *priv)
return endp->bulk_receiving_started; return endp->bulk_receiving_started;
} }
static const VMStateDescription usbredir_stream_vmstate = { static const VMStateDescription usbredir_bulk_receiving_vmstate = {
.name = "usb-redir-ep/stream-state", .name = "usb-redir-ep/bulk-receiving",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = usbredir_bulk_receiving_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT32(max_streams, struct endp_data), VMSTATE_UINT8(bulk_receiving_started, struct endp_data),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
} }
}; };
@ -2291,6 +2282,17 @@ static bool usbredir_stream_needed(void *priv)
return endp->max_streams; return endp->max_streams;
} }
static const VMStateDescription usbredir_stream_vmstate = {
.name = "usb-redir-ep/stream-state",
.version_id = 1,
.minimum_version_id = 1,
.needed = usbredir_stream_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT32(max_streams, struct endp_data),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription usbredir_ep_vmstate = { static const VMStateDescription usbredir_ep_vmstate = {
.name = "usb-redir-ep", .name = "usb-redir-ep",
.version_id = 1, .version_id = 1,
@ -2318,16 +2320,10 @@ static const VMStateDescription usbredir_ep_vmstate = {
VMSTATE_INT32(bufpq_target_size, struct endp_data), VMSTATE_INT32(bufpq_target_size, struct endp_data),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &usbredir_bulk_receiving_vmstate,
.vmsd = &usbredir_bulk_receiving_vmstate, &usbredir_stream_vmstate,
.needed = usbredir_bulk_receiving_needed, NULL
}, {
.vmsd = &usbredir_stream_vmstate,
.needed = usbredir_stream_needed,
}, {
/* empty */
}
} }
}; };

View File

@ -1053,6 +1053,7 @@ static const VMStateDescription vmstate_virtio_device_endian = {
.name = "virtio/device_endian", .name = "virtio/device_endian",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = &virtio_device_endian_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT8(device_endian, VirtIODevice), VMSTATE_UINT8(device_endian, VirtIODevice),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -1063,6 +1064,7 @@ static const VMStateDescription vmstate_virtio_64bit_features = {
.name = "virtio/64bit_features", .name = "virtio/64bit_features",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = &virtio_64bit_features_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(guest_features, VirtIODevice), VMSTATE_UINT64(guest_features, VirtIODevice),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -1077,16 +1079,10 @@ static const VMStateDescription vmstate_virtio = {
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_virtio_device_endian,
.vmsd = &vmstate_virtio_device_endian, &vmstate_virtio_64bit_features,
.needed = &virtio_device_endian_needed NULL
},
{
.vmsd = &vmstate_virtio_64bit_features,
.needed = &virtio_64bit_features_needed
},
{ 0 }
} }
}; };

View File

@ -126,10 +126,10 @@ void cpu_flush_icache_range(hwaddr start, int len);
extern struct MemoryRegion io_mem_rom; extern struct MemoryRegion io_mem_rom;
extern struct MemoryRegion io_mem_notdirty; extern struct MemoryRegion io_mem_notdirty;
typedef void (RAMBlockIterFunc)(void *host_addr, typedef int (RAMBlockIterFunc)(const char *block_name, void *host_addr,
ram_addr_t offset, ram_addr_t length, void *opaque); ram_addr_t offset, ram_addr_t length, void *opaque);
void qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque); int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
#endif #endif

View File

@ -34,6 +34,7 @@
#define QEMU_VM_SECTION_FULL 0x04 #define QEMU_VM_SECTION_FULL 0x04
#define QEMU_VM_SUBSECTION 0x05 #define QEMU_VM_SUBSECTION 0x05
#define QEMU_VM_VMDESCRIPTION 0x06 #define QEMU_VM_VMDESCRIPTION 0x06
#define QEMU_VM_SECTION_FOOTER 0x7e
struct MigrationParams { struct MigrationParams {
bool blk; bool blk;
@ -42,6 +43,20 @@ struct MigrationParams {
typedef struct MigrationState MigrationState; typedef struct MigrationState MigrationState;
typedef QLIST_HEAD(, LoadStateEntry) LoadStateEntry_Head;
/* State for the incoming migration */
struct MigrationIncomingState {
QEMUFile *file;
/* See savevm.c */
LoadStateEntry_Head loadvm_handlers;
};
MigrationIncomingState *migration_incoming_get_current(void);
MigrationIncomingState *migration_incoming_state_new(QEMUFile *f);
void migration_incoming_state_destroy(void);
struct MigrationState struct MigrationState
{ {
int64_t bandwidth_limit; int64_t bandwidth_limit;
@ -180,4 +195,6 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
ram_addr_t offset, size_t size, ram_addr_t offset, size_t size,
uint64_t *bytes_sent); uint64_t *bytes_sent);
void ram_mig_init(void);
void savevm_skip_section_footers(void);
#endif #endif

View File

@ -157,7 +157,7 @@ static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
void qemu_put_be16(QEMUFile *f, unsigned int v); void qemu_put_be16(QEMUFile *f, unsigned int v);
void qemu_put_be32(QEMUFile *f, unsigned int v); void qemu_put_be32(QEMUFile *f, unsigned int v);
void qemu_put_be64(QEMUFile *f, uint64_t v); void qemu_put_be64(QEMUFile *f, uint64_t v);
int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset); int qemu_peek_buffer(QEMUFile *f, uint8_t **buf, int size, size_t offset);
int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size); int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size);
ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size, ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size,
int level); int level);
@ -312,4 +312,7 @@ static inline void qemu_get_sbe64s(QEMUFile *f, int64_t *pv)
{ {
qemu_get_be64s(f, (uint64_t *)pv); qemu_get_be64s(f, (uint64_t *)pv);
} }
size_t qemu_get_counted_string(QEMUFile *f, char buf[256]);
#endif #endif

View File

@ -120,11 +120,6 @@ typedef struct {
bool (*field_exists)(void *opaque, int version_id); bool (*field_exists)(void *opaque, int version_id);
} VMStateField; } VMStateField;
typedef struct VMStateSubsection {
const VMStateDescription *vmsd;
bool (*needed)(void *opaque);
} VMStateSubsection;
struct VMStateDescription { struct VMStateDescription {
const char *name; const char *name;
int unmigratable; int unmigratable;
@ -135,8 +130,9 @@ struct VMStateDescription {
int (*pre_load)(void *opaque); int (*pre_load)(void *opaque);
int (*post_load)(void *opaque, int version_id); int (*post_load)(void *opaque, int version_id);
void (*pre_save)(void *opaque); void (*pre_save)(void *opaque);
bool (*needed)(void *opaque);
VMStateField *fields; VMStateField *fields;
const VMStateSubsection *subsections; const VMStateDescription **subsections;
}; };
extern const VMStateDescription vmstate_dummy; extern const VMStateDescription vmstate_dummy;
@ -812,6 +808,8 @@ extern const VMStateInfo vmstate_info_bitmap;
#define SELF_ANNOUNCE_ROUNDS 5 #define SELF_ANNOUNCE_ROUNDS 5
void loadvm_free_handlers(MigrationIncomingState *mis);
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, int version_id); void *opaque, int version_id);
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,

View File

@ -31,6 +31,7 @@ typedef struct I2CBus I2CBus;
typedef struct I2SCodec I2SCodec; typedef struct I2SCodec I2SCodec;
typedef struct ISABus ISABus; typedef struct ISABus ISABus;
typedef struct ISADevice ISADevice; typedef struct ISADevice ISADevice;
typedef struct LoadStateEntry LoadStateEntry;
typedef struct MACAddr MACAddr; typedef struct MACAddr MACAddr;
typedef struct MachineClass MachineClass; typedef struct MachineClass MachineClass;
typedef struct MachineState MachineState; typedef struct MachineState MachineState;
@ -38,6 +39,7 @@ typedef struct MemoryListener MemoryListener;
typedef struct MemoryMappingList MemoryMappingList; typedef struct MemoryMappingList MemoryMappingList;
typedef struct MemoryRegion MemoryRegion; typedef struct MemoryRegion MemoryRegion;
typedef struct MemoryRegionSection MemoryRegionSection; typedef struct MemoryRegionSection MemoryRegionSection;
typedef struct MigrationIncomingState MigrationIncomingState;
typedef struct MigrationParams MigrationParams; typedef struct MigrationParams MigrationParams;
typedef struct Monitor Monitor; typedef struct Monitor Monitor;
typedef struct MouseTransformInfo MouseTransformInfo; typedef struct MouseTransformInfo MouseTransformInfo;

View File

@ -30,7 +30,6 @@ extern const uint32_t arch_type;
void select_soundhw(const char *optarg); void select_soundhw(const char *optarg);
void do_acpitable_option(const QemuOpts *opts); void do_acpitable_option(const QemuOpts *opts);
void do_smbios_option(QemuOpts *opts); void do_smbios_option(QemuOpts *opts);
void ram_mig_init(void);
void cpudef_init(void); void cpudef_init(void);
void audio_init(void); void audio_init(void);
int kvm_available(void); int kvm_available(void);

View File

@ -84,6 +84,7 @@ void qemu_announce_self(void);
bool qemu_savevm_state_blocked(Error **errp); bool qemu_savevm_state_blocked(Error **errp);
void qemu_savevm_state_begin(QEMUFile *f, void qemu_savevm_state_begin(QEMUFile *f,
const MigrationParams *params); const MigrationParams *params);
void qemu_savevm_state_header(QEMUFile *f);
int qemu_savevm_state_iterate(QEMUFile *f); int qemu_savevm_state_iterate(QEMUFile *f);
void qemu_savevm_state_complete(QEMUFile *f); void qemu_savevm_state_complete(QEMUFile *f);
void qemu_savevm_state_cancel(void); void qemu_savevm_state_cancel(void);

View File

@ -53,6 +53,7 @@ static bool deferred_incoming;
migrations at once. For now we don't need to add migrations at once. For now we don't need to add
dynamic creation of migration */ dynamic creation of migration */
/* For outgoing */
MigrationState *migrate_get_current(void) MigrationState *migrate_get_current(void)
{ {
static MigrationState current_migration = { static MigrationState current_migration = {
@ -71,6 +72,30 @@ MigrationState *migrate_get_current(void)
return &current_migration; return &current_migration;
} }
/* For incoming */
static MigrationIncomingState *mis_current;
MigrationIncomingState *migration_incoming_get_current(void)
{
return mis_current;
}
MigrationIncomingState *migration_incoming_state_new(QEMUFile* f)
{
mis_current = g_malloc0(sizeof(MigrationIncomingState));
mis_current->file = f;
QLIST_INIT(&mis_current->loadvm_handlers);
return mis_current;
}
void migration_incoming_state_destroy(void)
{
loadvm_free_handlers(mis_current);
g_free(mis_current);
mis_current = NULL;
}
/* /*
* Called on -incoming with a defer: uri. * Called on -incoming with a defer: uri.
* The migration can be started later after any parameters have been * The migration can be started later after any parameters have been
@ -115,9 +140,14 @@ static void process_incoming_migration_co(void *opaque)
Error *local_err = NULL; Error *local_err = NULL;
int ret; int ret;
migration_incoming_state_new(f);
ret = qemu_loadvm_state(f); ret = qemu_loadvm_state(f);
qemu_fclose(f); qemu_fclose(f);
free_xbzrle_decoded_buf(); free_xbzrle_decoded_buf();
migration_incoming_state_destroy();
if (ret < 0) { if (ret < 0) {
error_report("load of migration failed: %s", strerror(-ret)); error_report("load of migration failed: %s", strerror(-ret));
migrate_decompress_threads_join(); migrate_decompress_threads_join();
@ -738,6 +768,7 @@ static void *migration_thread(void *opaque)
int64_t start_time = initial_time; int64_t start_time = initial_time;
bool old_vm_running = false; bool old_vm_running = false;
qemu_savevm_state_header(s->file);
qemu_savevm_state_begin(s->file, &s->params); qemu_savevm_state_begin(s->file, &s->params);
s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start; s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start;
@ -838,9 +869,6 @@ static void *migration_thread(void *opaque)
void migrate_fd_connect(MigrationState *s) void migrate_fd_connect(MigrationState *s)
{ {
s->state = MIGRATION_STATUS_SETUP;
trace_migrate_set_state(MIGRATION_STATUS_SETUP);
/* This is a best 1st approximation. ns to ms */ /* This is a best 1st approximation. ns to ms */
s->expected_downtime = max_downtime/1000000; s->expected_downtime = max_downtime/1000000;
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s); s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);

View File

@ -349,14 +349,14 @@ void qemu_file_skip(QEMUFile *f, int size)
} }
/* /*
* Read 'size' bytes from file (at 'offset') into buf without moving the * Read 'size' bytes from file (at 'offset') without moving the
* pointer. * pointer and set 'buf' to point to that data.
* *
* It will return size bytes unless there was an error, in which case it will * It will return size bytes unless there was an error, in which case it will
* return as many as it managed to read (assuming blocking fd's which * return as many as it managed to read (assuming blocking fd's which
* all current QEMUFile are) * all current QEMUFile are)
*/ */
int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset) int qemu_peek_buffer(QEMUFile *f, uint8_t **buf, int size, size_t offset)
{ {
int pending; int pending;
int index; int index;
@ -392,7 +392,7 @@ int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
size = pending; size = pending;
} }
memcpy(buf, f->buf + index, size); *buf = f->buf + index;
return size; return size;
} }
@ -411,11 +411,13 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
while (pending > 0) { while (pending > 0) {
int res; int res;
uint8_t *src;
res = qemu_peek_buffer(f, buf, MIN(pending, IO_BUF_SIZE), 0); res = qemu_peek_buffer(f, &src, MIN(pending, IO_BUF_SIZE), 0);
if (res == 0) { if (res == 0) {
return done; return done;
} }
memcpy(buf, src, res);
qemu_file_skip(f, res); qemu_file_skip(f, res);
buf += res; buf += res;
pending -= res; pending -= res;
@ -585,3 +587,20 @@ int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src)
} }
return len; return len;
} }
/*
* Get a string whose length is determined by a single preceding byte
* A preallocated 256 byte buffer must be passed in.
* Returns: len on success and a 0 terminated string in the buffer
* else 0
* (Note a 0 length string will return 0 either way)
*/
size_t qemu_get_counted_string(QEMUFile *f, char buf[256])
{
size_t len = qemu_get_byte(f);
size_t res = qemu_get_buffer(f, (uint8_t *)buf, len);
buf[res] = 0;
return res == len ? res : 0;
}

1628
migration/ram.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -236,13 +236,13 @@ typedef struct RDMALocalBlock {
* corresponding RDMALocalBlock with * corresponding RDMALocalBlock with
* the information needed to perform the actual RDMA. * the information needed to perform the actual RDMA.
*/ */
typedef struct QEMU_PACKED RDMARemoteBlock { typedef struct QEMU_PACKED RDMADestBlock {
uint64_t remote_host_addr; uint64_t remote_host_addr;
uint64_t offset; uint64_t offset;
uint64_t length; uint64_t length;
uint32_t remote_rkey; uint32_t remote_rkey;
uint32_t padding; uint32_t padding;
} RDMARemoteBlock; } RDMADestBlock;
static uint64_t htonll(uint64_t v) static uint64_t htonll(uint64_t v)
{ {
@ -258,20 +258,20 @@ static uint64_t ntohll(uint64_t v) {
return ((uint64_t)ntohl(u.lv[0]) << 32) | (uint64_t) ntohl(u.lv[1]); return ((uint64_t)ntohl(u.lv[0]) << 32) | (uint64_t) ntohl(u.lv[1]);
} }
static void remote_block_to_network(RDMARemoteBlock *rb) static void dest_block_to_network(RDMADestBlock *db)
{ {
rb->remote_host_addr = htonll(rb->remote_host_addr); db->remote_host_addr = htonll(db->remote_host_addr);
rb->offset = htonll(rb->offset); db->offset = htonll(db->offset);
rb->length = htonll(rb->length); db->length = htonll(db->length);
rb->remote_rkey = htonl(rb->remote_rkey); db->remote_rkey = htonl(db->remote_rkey);
} }
static void network_to_remote_block(RDMARemoteBlock *rb) static void network_to_dest_block(RDMADestBlock *db)
{ {
rb->remote_host_addr = ntohll(rb->remote_host_addr); db->remote_host_addr = ntohll(db->remote_host_addr);
rb->offset = ntohll(rb->offset); db->offset = ntohll(db->offset);
rb->length = ntohll(rb->length); db->length = ntohll(db->length);
rb->remote_rkey = ntohl(rb->remote_rkey); db->remote_rkey = ntohl(db->remote_rkey);
} }
/* /*
@ -350,7 +350,7 @@ typedef struct RDMAContext {
* Description of ram blocks used throughout the code. * Description of ram blocks used throughout the code.
*/ */
RDMALocalBlocks local_ram_blocks; RDMALocalBlocks local_ram_blocks;
RDMARemoteBlock *block; RDMADestBlock *dest_blocks;
/* /*
* Migration on *destination* started. * Migration on *destination* started.
@ -570,10 +570,10 @@ static int rdma_add_block(RDMAContext *rdma, void *host_addr,
* in advanced before the migration starts. This tells us where the RAM blocks * in advanced before the migration starts. This tells us where the RAM blocks
* are so that we can register them individually. * are so that we can register them individually.
*/ */
static void qemu_rdma_init_one_block(void *host_addr, static int qemu_rdma_init_one_block(const char *block_name, void *host_addr,
ram_addr_t block_offset, ram_addr_t length, void *opaque) ram_addr_t block_offset, ram_addr_t length, void *opaque)
{ {
rdma_add_block(opaque, host_addr, block_offset, length); return rdma_add_block(opaque, host_addr, block_offset, length);
} }
/* /*
@ -590,7 +590,7 @@ static int qemu_rdma_init_ram_blocks(RDMAContext *rdma)
memset(local, 0, sizeof *local); memset(local, 0, sizeof *local);
qemu_ram_foreach_block(qemu_rdma_init_one_block, rdma); qemu_ram_foreach_block(qemu_rdma_init_one_block, rdma);
trace_qemu_rdma_init_ram_blocks(local->nb_blocks); trace_qemu_rdma_init_ram_blocks(local->nb_blocks);
rdma->block = (RDMARemoteBlock *) g_malloc0(sizeof(RDMARemoteBlock) * rdma->dest_blocks = (RDMADestBlock *) g_malloc0(sizeof(RDMADestBlock) *
rdma->local_ram_blocks.nb_blocks); rdma->local_ram_blocks.nb_blocks);
local->init = true; local->init = true;
return 0; return 0;
@ -790,6 +790,13 @@ static int qemu_rdma_broken_ipv6_kernel(Error **errp, struct ibv_context *verbs)
for (x = 0; x < num_devices; x++) { for (x = 0; x < num_devices; x++) {
verbs = ibv_open_device(dev_list[x]); verbs = ibv_open_device(dev_list[x]);
if (!verbs) {
if (errno == EPERM) {
continue;
} else {
return -EINVAL;
}
}
if (ibv_query_port(verbs, 1, &port_attr)) { if (ibv_query_port(verbs, 1, &port_attr)) {
ibv_close_device(verbs); ibv_close_device(verbs);
@ -2177,8 +2184,8 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
rdma->connected = false; rdma->connected = false;
} }
g_free(rdma->block); g_free(rdma->dest_blocks);
rdma->block = NULL; rdma->dest_blocks = NULL;
for (idx = 0; idx < RDMA_WRID_MAX; idx++) { for (idx = 0; idx < RDMA_WRID_MAX; idx++) {
if (rdma->wr_data[idx].control_mr) { if (rdma->wr_data[idx].control_mr) {
@ -2445,7 +2452,6 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
if (host_port) { if (host_port) {
rdma = g_malloc0(sizeof(RDMAContext)); rdma = g_malloc0(sizeof(RDMAContext));
memset(rdma, 0, sizeof(RDMAContext));
rdma->current_index = -1; rdma->current_index = -1;
rdma->current_chunk = -1; rdma->current_chunk = -1;
@ -2967,25 +2973,25 @@ static int qemu_rdma_registration_handle(QEMUFile *f, void *opaque,
* their "local" descriptions with what was sent. * their "local" descriptions with what was sent.
*/ */
for (i = 0; i < local->nb_blocks; i++) { for (i = 0; i < local->nb_blocks; i++) {
rdma->block[i].remote_host_addr = rdma->dest_blocks[i].remote_host_addr =
(uintptr_t)(local->block[i].local_host_addr); (uintptr_t)(local->block[i].local_host_addr);
if (rdma->pin_all) { if (rdma->pin_all) {
rdma->block[i].remote_rkey = local->block[i].mr->rkey; rdma->dest_blocks[i].remote_rkey = local->block[i].mr->rkey;
} }
rdma->block[i].offset = local->block[i].offset; rdma->dest_blocks[i].offset = local->block[i].offset;
rdma->block[i].length = local->block[i].length; rdma->dest_blocks[i].length = local->block[i].length;
remote_block_to_network(&rdma->block[i]); dest_block_to_network(&rdma->dest_blocks[i]);
} }
blocks.len = rdma->local_ram_blocks.nb_blocks blocks.len = rdma->local_ram_blocks.nb_blocks
* sizeof(RDMARemoteBlock); * sizeof(RDMADestBlock);
ret = qemu_rdma_post_send_control(rdma, ret = qemu_rdma_post_send_control(rdma,
(uint8_t *) rdma->block, &blocks); (uint8_t *) rdma->dest_blocks, &blocks);
if (ret < 0) { if (ret < 0) {
error_report("rdma migration: error sending remote info"); error_report("rdma migration: error sending remote info");
@ -3141,7 +3147,7 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
if (flags == RAM_CONTROL_SETUP) { if (flags == RAM_CONTROL_SETUP) {
RDMAControlHeader resp = {.type = RDMA_CONTROL_RAM_BLOCKS_RESULT }; RDMAControlHeader resp = {.type = RDMA_CONTROL_RAM_BLOCKS_RESULT };
RDMALocalBlocks *local = &rdma->local_ram_blocks; RDMALocalBlocks *local = &rdma->local_ram_blocks;
int reg_result_idx, i, j, nb_remote_blocks; int reg_result_idx, i, j, nb_dest_blocks;
head.type = RDMA_CONTROL_RAM_BLOCKS_REQUEST; head.type = RDMA_CONTROL_RAM_BLOCKS_REQUEST;
trace_qemu_rdma_registration_stop_ram(); trace_qemu_rdma_registration_stop_ram();
@ -3162,7 +3168,7 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
return ret; return ret;
} }
nb_remote_blocks = resp.len / sizeof(RDMARemoteBlock); nb_dest_blocks = resp.len / sizeof(RDMADestBlock);
/* /*
* The protocol uses two different sets of rkeys (mutually exclusive): * The protocol uses two different sets of rkeys (mutually exclusive):
@ -3176,7 +3182,7 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
* and then propagates the remote ram block descriptions to his local copy. * and then propagates the remote ram block descriptions to his local copy.
*/ */
if (local->nb_blocks != nb_remote_blocks) { if (local->nb_blocks != nb_dest_blocks) {
ERROR(errp, "ram blocks mismatch #1! " ERROR(errp, "ram blocks mismatch #1! "
"Your QEMU command line parameters are probably " "Your QEMU command line parameters are probably "
"not identical on both the source and destination."); "not identical on both the source and destination.");
@ -3184,26 +3190,26 @@ static int qemu_rdma_registration_stop(QEMUFile *f, void *opaque,
} }
qemu_rdma_move_header(rdma, reg_result_idx, &resp); qemu_rdma_move_header(rdma, reg_result_idx, &resp);
memcpy(rdma->block, memcpy(rdma->dest_blocks,
rdma->wr_data[reg_result_idx].control_curr, resp.len); rdma->wr_data[reg_result_idx].control_curr, resp.len);
for (i = 0; i < nb_remote_blocks; i++) { for (i = 0; i < nb_dest_blocks; i++) {
network_to_remote_block(&rdma->block[i]); network_to_dest_block(&rdma->dest_blocks[i]);
/* search local ram blocks */ /* search local ram blocks */
for (j = 0; j < local->nb_blocks; j++) { for (j = 0; j < local->nb_blocks; j++) {
if (rdma->block[i].offset != local->block[j].offset) { if (rdma->dest_blocks[i].offset != local->block[j].offset) {
continue; continue;
} }
if (rdma->block[i].length != local->block[j].length) { if (rdma->dest_blocks[i].length != local->block[j].length) {
ERROR(errp, "ram blocks mismatch #2! " ERROR(errp, "ram blocks mismatch #2! "
"Your QEMU command line parameters are probably " "Your QEMU command line parameters are probably "
"not identical on both the source and destination."); "not identical on both the source and destination.");
return -EINVAL; return -EINVAL;
} }
local->block[j].remote_host_addr = local->block[j].remote_host_addr =
rdma->block[i].remote_host_addr; rdma->dest_blocks[i].remote_host_addr;
local->block[j].remote_rkey = rdma->block[i].remote_rkey; local->block[j].remote_rkey = rdma->dest_blocks[i].remote_rkey;
break; break;
} }

View File

@ -2,6 +2,10 @@
* QEMU System Emulator * QEMU System Emulator
* *
* Copyright (c) 2003-2008 Fabrice Bellard * Copyright (c) 2003-2008 Fabrice Bellard
* Copyright (c) 2009-2015 Red Hat Inc
*
* Authors:
* Juan Quintela <quintela@redhat.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -51,6 +55,8 @@
#define ARP_PTYPE_IP 0x0800 #define ARP_PTYPE_IP 0x0800
#define ARP_OP_REQUEST_REV 0x3 #define ARP_OP_REQUEST_REV 0x3
static bool skip_section_footers;
static int announce_self_create(uint8_t *buf, static int announce_self_create(uint8_t *buf,
uint8_t *mac_addr) uint8_t *mac_addr)
{ {
@ -235,10 +241,15 @@ typedef struct SaveStateEntry {
int is_ram; int is_ram;
} SaveStateEntry; } SaveStateEntry;
typedef struct SaveState {
QTAILQ_HEAD(, SaveStateEntry) handlers;
int global_section_id;
} SaveState;
static QTAILQ_HEAD(savevm_handlers, SaveStateEntry) savevm_handlers = static SaveState savevm_state = {
QTAILQ_HEAD_INITIALIZER(savevm_handlers); .handlers = QTAILQ_HEAD_INITIALIZER(savevm_state.handlers),
static int global_section_id; .global_section_id = 0,
};
static void dump_vmstate_vmsd(FILE *out_file, static void dump_vmstate_vmsd(FILE *out_file,
const VMStateDescription *vmsd, int indent, const VMStateDescription *vmsd, int indent,
@ -263,11 +274,11 @@ static void dump_vmstate_vmsf(FILE *out_file, const VMStateField *field,
} }
static void dump_vmstate_vmss(FILE *out_file, static void dump_vmstate_vmss(FILE *out_file,
const VMStateSubsection *subsection, const VMStateDescription **subsection,
int indent) int indent)
{ {
if (subsection->vmsd != NULL) { if (*subsection != NULL) {
dump_vmstate_vmsd(out_file, subsection->vmsd, indent, true); dump_vmstate_vmsd(out_file, *subsection, indent, true);
} }
} }
@ -308,12 +319,12 @@ static void dump_vmstate_vmsd(FILE *out_file,
fprintf(out_file, "\n%*s]", indent, ""); fprintf(out_file, "\n%*s]", indent, "");
} }
if (vmsd->subsections != NULL) { if (vmsd->subsections != NULL) {
const VMStateSubsection *subsection = vmsd->subsections; const VMStateDescription **subsection = vmsd->subsections;
bool first; bool first;
fprintf(out_file, ",\n%*s\"Subsections\": [\n", indent, ""); fprintf(out_file, ",\n%*s\"Subsections\": [\n", indent, "");
first = true; first = true;
while (subsection->vmsd != NULL) { while (*subsection != NULL) {
if (!first) { if (!first) {
fprintf(out_file, ",\n"); fprintf(out_file, ",\n");
} }
@ -383,7 +394,7 @@ static int calculate_new_instance_id(const char *idstr)
SaveStateEntry *se; SaveStateEntry *se;
int instance_id = 0; int instance_id = 0;
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (strcmp(idstr, se->idstr) == 0 if (strcmp(idstr, se->idstr) == 0
&& instance_id <= se->instance_id) { && instance_id <= se->instance_id) {
instance_id = se->instance_id + 1; instance_id = se->instance_id + 1;
@ -397,7 +408,7 @@ static int calculate_compat_instance_id(const char *idstr)
SaveStateEntry *se; SaveStateEntry *se;
int instance_id = 0; int instance_id = 0;
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!se->compat) { if (!se->compat) {
continue; continue;
} }
@ -425,7 +436,7 @@ int register_savevm_live(DeviceState *dev,
se = g_malloc0(sizeof(SaveStateEntry)); se = g_malloc0(sizeof(SaveStateEntry));
se->version_id = version_id; se->version_id = version_id;
se->section_id = global_section_id++; se->section_id = savevm_state.global_section_id++;
se->ops = ops; se->ops = ops;
se->opaque = opaque; se->opaque = opaque;
se->vmsd = NULL; se->vmsd = NULL;
@ -457,7 +468,7 @@ int register_savevm_live(DeviceState *dev,
} }
assert(!se->compat || se->instance_id == 0); assert(!se->compat || se->instance_id == 0);
/* add at the end of list */ /* add at the end of list */
QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry); QTAILQ_INSERT_TAIL(&savevm_state.handlers, se, entry);
return 0; return 0;
} }
@ -491,9 +502,9 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
} }
pstrcat(id, sizeof(id), idstr); pstrcat(id, sizeof(id), idstr);
QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) { QTAILQ_FOREACH_SAFE(se, &savevm_state.handlers, entry, new_se) {
if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) { if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
QTAILQ_REMOVE(&savevm_handlers, se, entry); QTAILQ_REMOVE(&savevm_state.handlers, se, entry);
if (se->compat) { if (se->compat) {
g_free(se->compat); g_free(se->compat);
} }
@ -515,7 +526,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
se = g_malloc0(sizeof(SaveStateEntry)); se = g_malloc0(sizeof(SaveStateEntry));
se->version_id = vmsd->version_id; se->version_id = vmsd->version_id;
se->section_id = global_section_id++; se->section_id = savevm_state.global_section_id++;
se->opaque = opaque; se->opaque = opaque;
se->vmsd = vmsd; se->vmsd = vmsd;
se->alias_id = alias_id; se->alias_id = alias_id;
@ -543,7 +554,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
} }
assert(!se->compat || se->instance_id == 0); assert(!se->compat || se->instance_id == 0);
/* add at the end of list */ /* add at the end of list */
QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry); QTAILQ_INSERT_TAIL(&savevm_state.handlers, se, entry);
return 0; return 0;
} }
@ -552,9 +563,9 @@ void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
{ {
SaveStateEntry *se, *new_se; SaveStateEntry *se, *new_se;
QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) { QTAILQ_FOREACH_SAFE(se, &savevm_state.handlers, entry, new_se) {
if (se->vmsd == vmsd && se->opaque == opaque) { if (se->vmsd == vmsd && se->opaque == opaque) {
QTAILQ_REMOVE(&savevm_handlers, se, entry); QTAILQ_REMOVE(&savevm_state.handlers, se, entry);
if (se->compat) { if (se->compat) {
g_free(se->compat); g_free(se->compat);
} }
@ -602,11 +613,84 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc)
vmstate_save_state(f, se->vmsd, se->opaque, vmdesc); vmstate_save_state(f, se->vmsd, se->opaque, vmdesc);
} }
void savevm_skip_section_footers(void)
{
skip_section_footers = true;
}
/*
* Write the header for device section (QEMU_VM_SECTION START/END/PART/FULL)
*/
static void save_section_header(QEMUFile *f, SaveStateEntry *se,
uint8_t section_type)
{
qemu_put_byte(f, section_type);
qemu_put_be32(f, se->section_id);
if (section_type == QEMU_VM_SECTION_FULL ||
section_type == QEMU_VM_SECTION_START) {
/* ID string */
size_t len = strlen(se->idstr);
qemu_put_byte(f, len);
qemu_put_buffer(f, (uint8_t *)se->idstr, len);
qemu_put_be32(f, se->instance_id);
qemu_put_be32(f, se->version_id);
}
}
/*
* Write a footer onto device sections that catches cases misformatted device
* sections.
*/
static void save_section_footer(QEMUFile *f, SaveStateEntry *se)
{
if (!skip_section_footers) {
qemu_put_byte(f, QEMU_VM_SECTION_FOOTER);
qemu_put_be32(f, se->section_id);
}
}
/*
* Read a footer off the wire and check that it matches the expected section
*
* Returns: true if the footer was good
* false if there is a problem (and calls error_report to say why)
*/
static bool check_section_footer(QEMUFile *f, SaveStateEntry *se)
{
uint8_t read_mark;
uint32_t read_section_id;
if (skip_section_footers) {
/* No footer to check */
return true;
}
read_mark = qemu_get_byte(f);
if (read_mark != QEMU_VM_SECTION_FOOTER) {
error_report("Missing section footer for %s", se->idstr);
return false;
}
read_section_id = qemu_get_be32(f);
if (read_section_id != se->section_id) {
error_report("Mismatched section id in footer for %s -"
" read 0x%x expected 0x%x",
se->idstr, read_section_id, se->section_id);
return false;
}
/* All good */
return true;
}
bool qemu_savevm_state_blocked(Error **errp) bool qemu_savevm_state_blocked(Error **errp)
{ {
SaveStateEntry *se; SaveStateEntry *se;
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (se->vmsd && se->vmsd->unmigratable) { if (se->vmsd && se->vmsd->unmigratable) {
error_setg(errp, "State blocked by non-migratable device '%s'", error_setg(errp, "State blocked by non-migratable device '%s'",
se->idstr); se->idstr);
@ -616,6 +700,13 @@ bool qemu_savevm_state_blocked(Error **errp)
return false; return false;
} }
void qemu_savevm_state_header(QEMUFile *f)
{
trace_savevm_state_header();
qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
qemu_put_be32(f, QEMU_VM_FILE_VERSION);
}
void qemu_savevm_state_begin(QEMUFile *f, void qemu_savevm_state_begin(QEMUFile *f,
const MigrationParams *params) const MigrationParams *params)
{ {
@ -623,19 +714,14 @@ void qemu_savevm_state_begin(QEMUFile *f,
int ret; int ret;
trace_savevm_state_begin(); trace_savevm_state_begin();
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!se->ops || !se->ops->set_params) { if (!se->ops || !se->ops->set_params) {
continue; continue;
} }
se->ops->set_params(params, se->opaque); se->ops->set_params(params, se->opaque);
} }
qemu_put_be32(f, QEMU_VM_FILE_MAGIC); QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
qemu_put_be32(f, QEMU_VM_FILE_VERSION);
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
int len;
if (!se->ops || !se->ops->save_live_setup) { if (!se->ops || !se->ops->save_live_setup) {
continue; continue;
} }
@ -644,19 +730,10 @@ void qemu_savevm_state_begin(QEMUFile *f,
continue; continue;
} }
} }
/* Section type */ save_section_header(f, se, QEMU_VM_SECTION_START);
qemu_put_byte(f, QEMU_VM_SECTION_START);
qemu_put_be32(f, se->section_id);
/* ID string */
len = strlen(se->idstr);
qemu_put_byte(f, len);
qemu_put_buffer(f, (uint8_t *)se->idstr, len);
qemu_put_be32(f, se->instance_id);
qemu_put_be32(f, se->version_id);
ret = se->ops->save_live_setup(f, se->opaque); ret = se->ops->save_live_setup(f, se->opaque);
save_section_footer(f, se);
if (ret < 0) { if (ret < 0) {
qemu_file_set_error(f, ret); qemu_file_set_error(f, ret);
break; break;
@ -676,7 +753,7 @@ int qemu_savevm_state_iterate(QEMUFile *f)
int ret = 1; int ret = 1;
trace_savevm_state_iterate(); trace_savevm_state_iterate();
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!se->ops || !se->ops->save_live_iterate) { if (!se->ops || !se->ops->save_live_iterate) {
continue; continue;
} }
@ -689,12 +766,12 @@ int qemu_savevm_state_iterate(QEMUFile *f)
return 0; return 0;
} }
trace_savevm_section_start(se->idstr, se->section_id); trace_savevm_section_start(se->idstr, se->section_id);
/* Section type */
qemu_put_byte(f, QEMU_VM_SECTION_PART); save_section_header(f, se, QEMU_VM_SECTION_PART);
qemu_put_be32(f, se->section_id);
ret = se->ops->save_live_iterate(f, se->opaque); ret = se->ops->save_live_iterate(f, se->opaque);
trace_savevm_section_end(se->idstr, se->section_id, ret); trace_savevm_section_end(se->idstr, se->section_id, ret);
save_section_footer(f, se);
if (ret < 0) { if (ret < 0) {
qemu_file_set_error(f, ret); qemu_file_set_error(f, ret);
@ -727,7 +804,7 @@ void qemu_savevm_state_complete(QEMUFile *f)
cpu_synchronize_all_states(); cpu_synchronize_all_states();
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!se->ops || !se->ops->save_live_complete) { if (!se->ops || !se->ops->save_live_complete) {
continue; continue;
} }
@ -737,12 +814,12 @@ void qemu_savevm_state_complete(QEMUFile *f)
} }
} }
trace_savevm_section_start(se->idstr, se->section_id); trace_savevm_section_start(se->idstr, se->section_id);
/* Section type */
qemu_put_byte(f, QEMU_VM_SECTION_END); save_section_header(f, se, QEMU_VM_SECTION_END);
qemu_put_be32(f, se->section_id);
ret = se->ops->save_live_complete(f, se->opaque); ret = se->ops->save_live_complete(f, se->opaque);
trace_savevm_section_end(se->idstr, se->section_id, ret); trace_savevm_section_end(se->idstr, se->section_id, ret);
save_section_footer(f, se);
if (ret < 0) { if (ret < 0) {
qemu_file_set_error(f, ret); qemu_file_set_error(f, ret);
return; return;
@ -752,8 +829,7 @@ void qemu_savevm_state_complete(QEMUFile *f)
vmdesc = qjson_new(); vmdesc = qjson_new();
json_prop_int(vmdesc, "page_size", TARGET_PAGE_SIZE); json_prop_int(vmdesc, "page_size", TARGET_PAGE_SIZE);
json_start_array(vmdesc, "devices"); json_start_array(vmdesc, "devices");
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
int len;
if ((!se->ops || !se->ops->save_state) && !se->vmsd) { if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
continue; continue;
@ -764,22 +840,13 @@ void qemu_savevm_state_complete(QEMUFile *f)
json_prop_str(vmdesc, "name", se->idstr); json_prop_str(vmdesc, "name", se->idstr);
json_prop_int(vmdesc, "instance_id", se->instance_id); json_prop_int(vmdesc, "instance_id", se->instance_id);
/* Section type */ save_section_header(f, se, QEMU_VM_SECTION_FULL);
qemu_put_byte(f, QEMU_VM_SECTION_FULL);
qemu_put_be32(f, se->section_id);
/* ID string */
len = strlen(se->idstr);
qemu_put_byte(f, len);
qemu_put_buffer(f, (uint8_t *)se->idstr, len);
qemu_put_be32(f, se->instance_id);
qemu_put_be32(f, se->version_id);
vmstate_save(f, se, vmdesc); vmstate_save(f, se, vmdesc);
json_end_object(vmdesc); json_end_object(vmdesc);
trace_savevm_section_end(se->idstr, se->section_id, 0); trace_savevm_section_end(se->idstr, se->section_id, 0);
save_section_footer(f, se);
} }
qemu_put_byte(f, QEMU_VM_EOF); qemu_put_byte(f, QEMU_VM_EOF);
@ -803,7 +870,7 @@ uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size)
SaveStateEntry *se; SaveStateEntry *se;
uint64_t ret = 0; uint64_t ret = 0;
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!se->ops || !se->ops->save_live_pending) { if (!se->ops || !se->ops->save_live_pending) {
continue; continue;
} }
@ -822,7 +889,7 @@ void qemu_savevm_state_cancel(void)
SaveStateEntry *se; SaveStateEntry *se;
trace_savevm_state_cancel(); trace_savevm_state_cancel();
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (se->ops && se->ops->cancel) { if (se->ops && se->ops->cancel) {
se->ops->cancel(se->opaque); se->ops->cancel(se->opaque);
} }
@ -842,6 +909,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp)
} }
qemu_mutex_unlock_iothread(); qemu_mutex_unlock_iothread();
qemu_savevm_state_header(f);
qemu_savevm_state_begin(f, &params); qemu_savevm_state_begin(f, &params);
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
@ -872,9 +940,7 @@ static int qemu_save_device_state(QEMUFile *f)
cpu_synchronize_all_states(); cpu_synchronize_all_states();
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
int len;
if (se->is_ram) { if (se->is_ram) {
continue; continue;
} }
@ -882,19 +948,11 @@ static int qemu_save_device_state(QEMUFile *f)
continue; continue;
} }
/* Section type */ save_section_header(f, se, QEMU_VM_SECTION_FULL);
qemu_put_byte(f, QEMU_VM_SECTION_FULL);
qemu_put_be32(f, se->section_id);
/* ID string */
len = strlen(se->idstr);
qemu_put_byte(f, len);
qemu_put_buffer(f, (uint8_t *)se->idstr, len);
qemu_put_be32(f, se->instance_id);
qemu_put_be32(f, se->version_id);
vmstate_save(f, se, NULL); vmstate_save(f, se, NULL);
save_section_footer(f, se);
} }
qemu_put_byte(f, QEMU_VM_EOF); qemu_put_byte(f, QEMU_VM_EOF);
@ -906,7 +964,7 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
{ {
SaveStateEntry *se; SaveStateEntry *se;
QTAILQ_FOREACH(se, &savevm_handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!strcmp(se->idstr, idstr) && if (!strcmp(se->idstr, idstr) &&
(instance_id == se->instance_id || (instance_id == se->instance_id ||
instance_id == se->alias_id)) instance_id == se->alias_id))
@ -922,18 +980,26 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
return NULL; return NULL;
} }
typedef struct LoadStateEntry { struct LoadStateEntry {
QLIST_ENTRY(LoadStateEntry) entry; QLIST_ENTRY(LoadStateEntry) entry;
SaveStateEntry *se; SaveStateEntry *se;
int section_id; int section_id;
int version_id; int version_id;
} LoadStateEntry; };
void loadvm_free_handlers(MigrationIncomingState *mis)
{
LoadStateEntry *le, *new_le;
QLIST_FOREACH_SAFE(le, &mis->loadvm_handlers, entry, new_le) {
QLIST_REMOVE(le, entry);
g_free(le);
}
}
int qemu_loadvm_state(QEMUFile *f) int qemu_loadvm_state(QEMUFile *f)
{ {
QLIST_HEAD(, LoadStateEntry) loadvm_handlers = MigrationIncomingState *mis = migration_incoming_get_current();
QLIST_HEAD_INITIALIZER(loadvm_handlers);
LoadStateEntry *le, *new_le;
Error *local_err = NULL; Error *local_err = NULL;
uint8_t section_type; uint8_t section_type;
unsigned int v; unsigned int v;
@ -964,8 +1030,8 @@ int qemu_loadvm_state(QEMUFile *f)
while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) { while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
uint32_t instance_id, version_id, section_id; uint32_t instance_id, version_id, section_id;
SaveStateEntry *se; SaveStateEntry *se;
char idstr[257]; LoadStateEntry *le;
int len; char idstr[256];
trace_qemu_loadvm_state_section(section_type); trace_qemu_loadvm_state_section(section_type);
switch (section_type) { switch (section_type) {
@ -973,9 +1039,11 @@ int qemu_loadvm_state(QEMUFile *f)
case QEMU_VM_SECTION_FULL: case QEMU_VM_SECTION_FULL:
/* Read section start */ /* Read section start */
section_id = qemu_get_be32(f); section_id = qemu_get_be32(f);
len = qemu_get_byte(f); if (!qemu_get_counted_string(f, idstr)) {
qemu_get_buffer(f, (uint8_t *)idstr, len); error_report("Unable to read ID string for section %u",
idstr[len] = 0; section_id);
return -EINVAL;
}
instance_id = qemu_get_be32(f); instance_id = qemu_get_be32(f);
version_id = qemu_get_be32(f); version_id = qemu_get_be32(f);
@ -1004,7 +1072,7 @@ int qemu_loadvm_state(QEMUFile *f)
le->se = se; le->se = se;
le->section_id = section_id; le->section_id = section_id;
le->version_id = version_id; le->version_id = version_id;
QLIST_INSERT_HEAD(&loadvm_handlers, le, entry); QLIST_INSERT_HEAD(&mis->loadvm_handlers, le, entry);
ret = vmstate_load(f, le->se, le->version_id); ret = vmstate_load(f, le->se, le->version_id);
if (ret < 0) { if (ret < 0) {
@ -1012,13 +1080,17 @@ int qemu_loadvm_state(QEMUFile *f)
" device '%s'", instance_id, idstr); " device '%s'", instance_id, idstr);
goto out; goto out;
} }
if (!check_section_footer(f, le->se)) {
ret = -EINVAL;
goto out;
}
break; break;
case QEMU_VM_SECTION_PART: case QEMU_VM_SECTION_PART:
case QEMU_VM_SECTION_END: case QEMU_VM_SECTION_END:
section_id = qemu_get_be32(f); section_id = qemu_get_be32(f);
trace_qemu_loadvm_state_section_partend(section_id); trace_qemu_loadvm_state_section_partend(section_id);
QLIST_FOREACH(le, &loadvm_handlers, entry) { QLIST_FOREACH(le, &mis->loadvm_handlers, entry) {
if (le->section_id == section_id) { if (le->section_id == section_id) {
break; break;
} }
@ -1035,6 +1107,10 @@ int qemu_loadvm_state(QEMUFile *f)
section_id, le->se->idstr); section_id, le->se->idstr);
goto out; goto out;
} }
if (!check_section_footer(f, le->se)) {
ret = -EINVAL;
goto out;
}
break; break;
default: default:
error_report("Unknown savevm section type %d", section_type); error_report("Unknown savevm section type %d", section_type);
@ -1066,11 +1142,6 @@ int qemu_loadvm_state(QEMUFile *f)
ret = 0; ret = 0;
out: out:
QLIST_FOREACH_SAFE(le, &loadvm_handlers, entry, new_le) {
QLIST_REMOVE(le, entry);
g_free(le);
}
if (ret == 0) { if (ret == 0) {
/* We may not have a VMDESC section, so ignore relative errors */ /* We may not have a VMDESC section, so ignore relative errors */
ret = file_error_after_eof; ret = file_error_after_eof;
@ -1314,9 +1385,11 @@ int load_vmstate(const char *name)
} }
qemu_system_reset(VMRESET_SILENT); qemu_system_reset(VMRESET_SILENT);
migration_incoming_state_new(f);
ret = qemu_loadvm_state(f); ret = qemu_loadvm_state(f);
qemu_fclose(f); qemu_fclose(f);
migration_incoming_state_destroy();
if (ret < 0) { if (ret < 0) {
error_report("Error %d while loading VM state", ret); error_report("Error %d while loading VM state", ret);
return ret; return ret;

View File

@ -341,11 +341,11 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
} }
static const VMStateDescription * static const VMStateDescription *
vmstate_get_subsection(const VMStateSubsection *sub, char *idstr) vmstate_get_subsection(const VMStateDescription **sub, char *idstr)
{ {
while (sub && sub->needed) { while (sub && *sub && (*sub)->needed) {
if (strcmp(idstr, sub->vmsd->name) == 0) { if (strcmp(idstr, (*sub)->name) == 0) {
return sub->vmsd; return *sub;
} }
sub++; sub++;
} }
@ -358,7 +358,7 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
trace_vmstate_subsection_load(vmsd->name); trace_vmstate_subsection_load(vmsd->name);
while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) { while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
char idstr[256]; char idstr[256], *idstr_ret;
int ret; int ret;
uint8_t version_id, len, size; uint8_t version_id, len, size;
const VMStateDescription *sub_vmsd; const VMStateDescription *sub_vmsd;
@ -369,11 +369,12 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
trace_vmstate_subsection_load_bad(vmsd->name, "(short)"); trace_vmstate_subsection_load_bad(vmsd->name, "(short)");
return 0; return 0;
} }
size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2); size = qemu_peek_buffer(f, (uint8_t **)&idstr_ret, len, 2);
if (size != len) { if (size != len) {
trace_vmstate_subsection_load_bad(vmsd->name, "(peek fail)"); trace_vmstate_subsection_load_bad(vmsd->name, "(peek fail)");
return 0; return 0;
} }
memcpy(idstr, idstr_ret, size);
idstr[size] = 0; idstr[size] = 0;
if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) { if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
@ -405,12 +406,12 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc) void *opaque, QJSON *vmdesc)
{ {
const VMStateSubsection *sub = vmsd->subsections; const VMStateDescription **sub = vmsd->subsections;
bool subsection_found = false; bool subsection_found = false;
while (sub && sub->needed) { while (sub && *sub && (*sub)->needed) {
if (sub->needed(opaque)) { if ((*sub)->needed(opaque)) {
const VMStateDescription *vmsd = sub->vmsd; const VMStateDescription *vmsd = *sub;
uint8_t len; uint8_t len;
if (vmdesc) { if (vmdesc) {

View File

@ -474,6 +474,7 @@ class MigrationDump(object):
QEMU_VM_SECTION_FULL = 0x04 QEMU_VM_SECTION_FULL = 0x04
QEMU_VM_SUBSECTION = 0x05 QEMU_VM_SUBSECTION = 0x05
QEMU_VM_VMDESCRIPTION = 0x06 QEMU_VM_VMDESCRIPTION = 0x06
QEMU_VM_SECTION_FOOTER= 0x7e
def __init__(self, filename): def __init__(self, filename):
self.section_classes = { ( 'ram', 0 ) : [ RamSection, None ], self.section_classes = { ( 'ram', 0 ) : [ RamSection, None ],
@ -526,6 +527,10 @@ class MigrationDump(object):
elif section_type == self.QEMU_VM_SECTION_PART or section_type == self.QEMU_VM_SECTION_END: elif section_type == self.QEMU_VM_SECTION_PART or section_type == self.QEMU_VM_SECTION_END:
section_id = file.read32() section_id = file.read32()
self.sections[section_id].read() self.sections[section_id].read()
elif section_type == self.QEMU_VM_SECTION_FOOTER:
read_section_id = file.read32()
if read_section_id != section_id:
raise Exception("Mismatched section footer: %x vs %x" % (read_section_id, section_id))
else: else:
raise Exception("Unknown section type: %d" % section_type) raise Exception("Unknown section type: %d" % section_type)
file.close() file.close()

View File

@ -40,6 +40,7 @@ static const VMStateDescription vmstate_vfp = {
.name = "cpu/vfp", .name = "cpu/vfp",
.version_id = 3, .version_id = 3,
.minimum_version_id = 3, .minimum_version_id = 3,
.needed = vfp_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64), VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64),
/* The xregs array is a little awkward because element 1 (FPSCR) /* The xregs array is a little awkward because element 1 (FPSCR)
@ -72,6 +73,7 @@ static const VMStateDescription vmstate_iwmmxt = {
.name = "cpu/iwmmxt", .name = "cpu/iwmmxt",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = iwmmxt_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64_ARRAY(env.iwmmxt.regs, ARMCPU, 16), VMSTATE_UINT64_ARRAY(env.iwmmxt.regs, ARMCPU, 16),
VMSTATE_UINT32_ARRAY(env.iwmmxt.cregs, ARMCPU, 16), VMSTATE_UINT32_ARRAY(env.iwmmxt.cregs, ARMCPU, 16),
@ -91,6 +93,7 @@ static const VMStateDescription vmstate_m = {
.name = "cpu/m", .name = "cpu/m",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = m_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT32(env.v7m.other_sp, ARMCPU), VMSTATE_UINT32(env.v7m.other_sp, ARMCPU),
VMSTATE_UINT32(env.v7m.vecbase, ARMCPU), VMSTATE_UINT32(env.v7m.vecbase, ARMCPU),
@ -114,6 +117,7 @@ static const VMStateDescription vmstate_thumb2ee = {
.name = "cpu/thumb2ee", .name = "cpu/thumb2ee",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = thumb2ee_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT32(env.teecr, ARMCPU), VMSTATE_UINT32(env.teecr, ARMCPU),
VMSTATE_UINT32(env.teehbr, ARMCPU), VMSTATE_UINT32(env.teehbr, ARMCPU),
@ -282,21 +286,11 @@ const VMStateDescription vmstate_arm_cpu = {
VMSTATE_BOOL(powered_off, ARMCPU), VMSTATE_BOOL(powered_off, ARMCPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_vfp,
.vmsd = &vmstate_vfp, &vmstate_iwmmxt,
.needed = vfp_needed, &vmstate_m,
} , { &vmstate_thumb2ee,
.vmsd = &vmstate_iwmmxt, NULL
.needed = iwmmxt_needed,
} , {
.vmsd = &vmstate_m,
.needed = m_needed,
} , {
.vmsd = &vmstate_thumb2ee,
.needed = thumb2ee_needed,
} , {
/* empty */
}
} }
}; };

View File

@ -403,6 +403,7 @@ static const VMStateDescription vmstate_steal_time_msr = {
.name = "cpu/steal_time_msr", .name = "cpu/steal_time_msr",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = steal_time_msr_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.steal_time_msr, X86CPU), VMSTATE_UINT64(env.steal_time_msr, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -413,6 +414,7 @@ static const VMStateDescription vmstate_async_pf_msr = {
.name = "cpu/async_pf_msr", .name = "cpu/async_pf_msr",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = async_pf_msr_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.async_pf_en_msr, X86CPU), VMSTATE_UINT64(env.async_pf_en_msr, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -423,6 +425,7 @@ static const VMStateDescription vmstate_pv_eoi_msr = {
.name = "cpu/async_pv_eoi_msr", .name = "cpu/async_pv_eoi_msr",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = pv_eoi_msr_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.pv_eoi_en_msr, X86CPU), VMSTATE_UINT64(env.pv_eoi_en_msr, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -441,6 +444,7 @@ static const VMStateDescription vmstate_fpop_ip_dp = {
.name = "cpu/fpop_ip_dp", .name = "cpu/fpop_ip_dp",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = fpop_ip_dp_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT16(env.fpop, X86CPU), VMSTATE_UINT16(env.fpop, X86CPU),
VMSTATE_UINT64(env.fpip, X86CPU), VMSTATE_UINT64(env.fpip, X86CPU),
@ -461,6 +465,7 @@ static const VMStateDescription vmstate_msr_tsc_adjust = {
.name = "cpu/msr_tsc_adjust", .name = "cpu/msr_tsc_adjust",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = tsc_adjust_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.tsc_adjust, X86CPU), VMSTATE_UINT64(env.tsc_adjust, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -479,6 +484,7 @@ static const VMStateDescription vmstate_msr_tscdeadline = {
.name = "cpu/msr_tscdeadline", .name = "cpu/msr_tscdeadline",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = tscdeadline_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.tsc_deadline, X86CPU), VMSTATE_UINT64(env.tsc_deadline, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -505,6 +511,7 @@ static const VMStateDescription vmstate_msr_ia32_misc_enable = {
.name = "cpu/msr_ia32_misc_enable", .name = "cpu/msr_ia32_misc_enable",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = misc_enable_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.msr_ia32_misc_enable, X86CPU), VMSTATE_UINT64(env.msr_ia32_misc_enable, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -515,6 +522,7 @@ static const VMStateDescription vmstate_msr_ia32_feature_control = {
.name = "cpu/msr_ia32_feature_control", .name = "cpu/msr_ia32_feature_control",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = feature_control_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.msr_ia32_feature_control, X86CPU), VMSTATE_UINT64(env.msr_ia32_feature_control, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -549,6 +557,7 @@ static const VMStateDescription vmstate_msr_architectural_pmu = {
.name = "cpu/msr_architectural_pmu", .name = "cpu/msr_architectural_pmu",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = pmu_enable_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.msr_fixed_ctr_ctrl, X86CPU), VMSTATE_UINT64(env.msr_fixed_ctr_ctrl, X86CPU),
VMSTATE_UINT64(env.msr_global_ctrl, X86CPU), VMSTATE_UINT64(env.msr_global_ctrl, X86CPU),
@ -584,6 +593,7 @@ static const VMStateDescription vmstate_mpx = {
.name = "cpu/mpx", .name = "cpu/mpx",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = mpx_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_BND_REGS(env.bnd_regs, X86CPU, 4), VMSTATE_BND_REGS(env.bnd_regs, X86CPU, 4),
VMSTATE_UINT64(env.bndcs_regs.cfgu, X86CPU), VMSTATE_UINT64(env.bndcs_regs.cfgu, X86CPU),
@ -605,6 +615,7 @@ static const VMStateDescription vmstate_msr_hypercall_hypercall = {
.name = "cpu/msr_hyperv_hypercall", .name = "cpu/msr_hyperv_hypercall",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = hyperv_hypercall_enable_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.msr_hv_guest_os_id, X86CPU), VMSTATE_UINT64(env.msr_hv_guest_os_id, X86CPU),
VMSTATE_UINT64(env.msr_hv_hypercall, X86CPU), VMSTATE_UINT64(env.msr_hv_hypercall, X86CPU),
@ -624,6 +635,7 @@ static const VMStateDescription vmstate_msr_hyperv_vapic = {
.name = "cpu/msr_hyperv_vapic", .name = "cpu/msr_hyperv_vapic",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = hyperv_vapic_enable_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.msr_hv_vapic, X86CPU), VMSTATE_UINT64(env.msr_hv_vapic, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -642,6 +654,7 @@ static const VMStateDescription vmstate_msr_hyperv_time = {
.name = "cpu/msr_hyperv_time", .name = "cpu/msr_hyperv_time",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = hyperv_time_enable_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.msr_hv_tsc, X86CPU), VMSTATE_UINT64(env.msr_hv_tsc, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -683,6 +696,7 @@ static const VMStateDescription vmstate_avx512 = {
.name = "cpu/avx512", .name = "cpu/avx512",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = avx512_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64_ARRAY(env.opmask_regs, X86CPU, NB_OPMASK_REGS), VMSTATE_UINT64_ARRAY(env.opmask_regs, X86CPU, NB_OPMASK_REGS),
VMSTATE_ZMMH_REGS_VARS(env.xmm_regs, X86CPU, 0), VMSTATE_ZMMH_REGS_VARS(env.xmm_regs, X86CPU, 0),
@ -705,6 +719,7 @@ static const VMStateDescription vmstate_xss = {
.name = "cpu/xss", .name = "cpu/xss",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = xss_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.xss, X86CPU), VMSTATE_UINT64(env.xss, X86CPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -813,54 +828,22 @@ VMStateDescription vmstate_x86_cpu = {
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
/* The above list is not sorted /wrt version numbers, watch out! */ /* The above list is not sorted /wrt version numbers, watch out! */
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_async_pf_msr,
.vmsd = &vmstate_async_pf_msr, &vmstate_pv_eoi_msr,
.needed = async_pf_msr_needed, &vmstate_steal_time_msr,
} , { &vmstate_fpop_ip_dp,
.vmsd = &vmstate_pv_eoi_msr, &vmstate_msr_tsc_adjust,
.needed = pv_eoi_msr_needed, &vmstate_msr_tscdeadline,
} , { &vmstate_msr_ia32_misc_enable,
.vmsd = &vmstate_steal_time_msr, &vmstate_msr_ia32_feature_control,
.needed = steal_time_msr_needed, &vmstate_msr_architectural_pmu,
} , { &vmstate_mpx,
.vmsd = &vmstate_fpop_ip_dp, &vmstate_msr_hypercall_hypercall,
.needed = fpop_ip_dp_needed, &vmstate_msr_hyperv_vapic,
}, { &vmstate_msr_hyperv_time,
.vmsd = &vmstate_msr_tsc_adjust, &vmstate_avx512,
.needed = tsc_adjust_needed, &vmstate_xss,
}, { NULL
.vmsd = &vmstate_msr_tscdeadline,
.needed = tscdeadline_needed,
}, {
.vmsd = &vmstate_msr_ia32_misc_enable,
.needed = misc_enable_needed,
}, {
.vmsd = &vmstate_msr_ia32_feature_control,
.needed = feature_control_needed,
}, {
.vmsd = &vmstate_msr_architectural_pmu,
.needed = pmu_enable_needed,
} , {
.vmsd = &vmstate_mpx,
.needed = mpx_needed,
}, {
.vmsd = &vmstate_msr_hypercall_hypercall,
.needed = hyperv_hypercall_enable_needed,
}, {
.vmsd = &vmstate_msr_hyperv_vapic,
.needed = hyperv_vapic_enable_needed,
}, {
.vmsd = &vmstate_msr_hyperv_time,
.needed = hyperv_time_enable_needed,
}, {
.vmsd = &vmstate_avx512,
.needed = avx512_needed,
}, {
.vmsd = &vmstate_xss,
.needed = xss_needed,
} , {
/* empty */
}
} }
}; };

View File

@ -213,6 +213,7 @@ static const VMStateDescription vmstate_fpu = {
.name = "cpu/fpu", .name = "cpu/fpu",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = fpu_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_FLOAT64_ARRAY(env.fpr, PowerPCCPU, 32), VMSTATE_FLOAT64_ARRAY(env.fpr, PowerPCCPU, 32),
VMSTATE_UINTTL(env.fpscr, PowerPCCPU), VMSTATE_UINTTL(env.fpscr, PowerPCCPU),
@ -231,6 +232,7 @@ static const VMStateDescription vmstate_altivec = {
.name = "cpu/altivec", .name = "cpu/altivec",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = altivec_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_AVR_ARRAY(env.avr, PowerPCCPU, 32), VMSTATE_AVR_ARRAY(env.avr, PowerPCCPU, 32),
VMSTATE_UINT32(env.vscr, PowerPCCPU), VMSTATE_UINT32(env.vscr, PowerPCCPU),
@ -249,6 +251,7 @@ static const VMStateDescription vmstate_vsx = {
.name = "cpu/vsx", .name = "cpu/vsx",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = vsx_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64_ARRAY(env.vsr, PowerPCCPU, 32), VMSTATE_UINT64_ARRAY(env.vsr, PowerPCCPU, 32),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -269,6 +272,7 @@ static const VMStateDescription vmstate_tm = {
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.minimum_version_id_old = 1, .minimum_version_id_old = 1,
.needed = tm_needed,
.fields = (VMStateField []) { .fields = (VMStateField []) {
VMSTATE_UINTTL_ARRAY(env.tm_gpr, PowerPCCPU, 32), VMSTATE_UINTTL_ARRAY(env.tm_gpr, PowerPCCPU, 32),
VMSTATE_AVR_ARRAY(env.tm_vsr, PowerPCCPU, 64), VMSTATE_AVR_ARRAY(env.tm_vsr, PowerPCCPU, 64),
@ -302,6 +306,7 @@ static const VMStateDescription vmstate_sr = {
.name = "cpu/sr", .name = "cpu/sr",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = sr_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.sr, PowerPCCPU, 32), VMSTATE_UINTTL_ARRAY(env.sr, PowerPCCPU, 32),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -351,6 +356,7 @@ static const VMStateDescription vmstate_slb = {
.name = "cpu/slb", .name = "cpu/slb",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = slb_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32_EQUAL(env.slb_nr, PowerPCCPU), VMSTATE_INT32_EQUAL(env.slb_nr, PowerPCCPU),
VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, MAX_SLB_ENTRIES), VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, MAX_SLB_ENTRIES),
@ -383,6 +389,7 @@ static const VMStateDescription vmstate_tlb6xx = {
.name = "cpu/tlb6xx", .name = "cpu/tlb6xx",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = tlb6xx_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU), VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU),
VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlb6, PowerPCCPU, VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlb6, PowerPCCPU,
@ -429,6 +436,7 @@ static const VMStateDescription vmstate_pbr403 = {
.name = "cpu/pbr403", .name = "cpu/pbr403",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = pbr403_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.pb, PowerPCCPU, 4), VMSTATE_UINTTL_ARRAY(env.pb, PowerPCCPU, 4),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
@ -439,6 +447,7 @@ static const VMStateDescription vmstate_tlbemb = {
.name = "cpu/tlb6xx", .name = "cpu/tlb6xx",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = tlbemb_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU), VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU),
VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlbe, PowerPCCPU, VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlbe, PowerPCCPU,
@ -448,13 +457,9 @@ static const VMStateDescription vmstate_tlbemb = {
/* 403 protection registers */ /* 403 protection registers */
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_pbr403,
.vmsd = &vmstate_pbr403, NULL
.needed = pbr403_needed,
} , {
/* empty */
}
} }
}; };
@ -483,6 +488,7 @@ static const VMStateDescription vmstate_tlbmas = {
.name = "cpu/tlbmas", .name = "cpu/tlbmas",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = tlbmas_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU), VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU),
VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlbm, PowerPCCPU, VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlbm, PowerPCCPU,
@ -533,38 +539,18 @@ const VMStateDescription vmstate_ppc_cpu = {
VMSTATE_UINT32_EQUAL(env.nb_BATs, PowerPCCPU), VMSTATE_UINT32_EQUAL(env.nb_BATs, PowerPCCPU),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection []) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_fpu,
.vmsd = &vmstate_fpu, &vmstate_altivec,
.needed = fpu_needed, &vmstate_vsx,
} , { &vmstate_sr,
.vmsd = &vmstate_altivec,
.needed = altivec_needed,
} , {
.vmsd = &vmstate_vsx,
.needed = vsx_needed,
} , {
.vmsd = &vmstate_sr,
.needed = sr_needed,
} , {
#ifdef TARGET_PPC64 #ifdef TARGET_PPC64
.vmsd = &vmstate_tm, &vmstate_tm,
.needed = tm_needed, &vmstate_slb,
} , {
.vmsd = &vmstate_slb,
.needed = slb_needed,
} , {
#endif /* TARGET_PPC64 */ #endif /* TARGET_PPC64 */
.vmsd = &vmstate_tlb6xx, &vmstate_tlb6xx,
.needed = tlb6xx_needed, &vmstate_tlbemb,
} , { &vmstate_tlbmas,
.vmsd = &vmstate_tlbemb, NULL
.needed = tlbemb_needed,
} , {
.vmsd = &vmstate_tlbmas,
.needed = tlbmas_needed,
} , {
/* empty */
}
} }
}; };

View File

@ -42,10 +42,17 @@ static void cpu_pre_save(void *opaque)
} }
} }
static inline bool fpu_needed(void *opaque)
{
/* This looks odd, but we might want to NOT transfer fprs in the future */
return true;
}
const VMStateDescription vmstate_fpu = { const VMStateDescription vmstate_fpu = {
.name = "cpu/fpu", .name = "cpu/fpu",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = fpu_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_UINT64(env.vregs[0][0].ll, S390CPU), VMSTATE_UINT64(env.vregs[0][0].ll, S390CPU),
VMSTATE_UINT64(env.vregs[1][0].ll, S390CPU), VMSTATE_UINT64(env.vregs[1][0].ll, S390CPU),
@ -68,16 +75,11 @@ const VMStateDescription vmstate_fpu = {
} }
}; };
static inline bool fpu_needed(void *opaque)
{
/* This looks odd, but we might want to NOT transfer fprs in the future */
return true;
}
const VMStateDescription vmstate_vregs = { const VMStateDescription vmstate_vregs = {
.name = "cpu/vregs", .name = "cpu/vregs",
.version_id = 1, .version_id = 1,
.minimum_version_id = 1, .minimum_version_id = 1,
.needed = vregs_needed,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
/* vregs[0][0] -> vregs[15][0] and fregs are overlays */ /* vregs[0][0] -> vregs[15][0] and fregs are overlays */
VMSTATE_UINT64(env.vregs[16][0].ll, S390CPU), VMSTATE_UINT64(env.vregs[16][0].ll, S390CPU),
@ -159,16 +161,10 @@ const VMStateDescription vmstate_s390_cpu = {
VMSTATE_VBUFFER_UINT32(irqstate, S390CPU, 4, NULL, 0, VMSTATE_VBUFFER_UINT32(irqstate, S390CPU, 4, NULL, 0,
irqstate_saved_size), irqstate_saved_size),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
.subsections = (VMStateSubsection[]) { .subsections = (const VMStateDescription*[]) {
{ &vmstate_fpu,
.vmsd = &vmstate_fpu, &vmstate_vregs,
.needed = fpu_needed, NULL
} , {
.vmsd = &vmstate_vregs,
.needed = vregs_needed,
} , {
/* empty */
}
}, },
}; };

View File

@ -1179,13 +1179,14 @@ virtio_gpu_cmd_res_flush(uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint3
virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 0x%" PRIx64 ", type 0x%x" virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 0x%" PRIx64 ", type 0x%x"
virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64 virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
# savevm.c # migration/savevm.c
qemu_loadvm_state_section(unsigned int section_type) "%d" qemu_loadvm_state_section(unsigned int section_type) "%d"
qemu_loadvm_state_section_partend(uint32_t section_id) "%u" qemu_loadvm_state_section_partend(uint32_t section_id) "%u"
qemu_loadvm_state_section_startfull(uint32_t section_id, const char *idstr, uint32_t instance_id, uint32_t version_id) "%u(%s) %u %u" qemu_loadvm_state_section_startfull(uint32_t section_id, const char *idstr, uint32_t instance_id, uint32_t version_id) "%u(%s) %u %u"
savevm_section_start(const char *id, unsigned int section_id) "%s, section_id %u" savevm_section_start(const char *id, unsigned int section_id) "%s, section_id %u"
savevm_section_end(const char *id, unsigned int section_id, int ret) "%s, section_id %u -> %d" savevm_section_end(const char *id, unsigned int section_id, int ret) "%s, section_id %u -> %d"
savevm_state_begin(void) "" savevm_state_begin(void) ""
savevm_state_header(void) ""
savevm_state_iterate(void) "" savevm_state_iterate(void) ""
savevm_state_complete(void) "" savevm_state_complete(void) ""
savevm_state_cancel(void) "" savevm_state_cancel(void) ""
@ -1205,7 +1206,7 @@ vmstate_subsection_load_good(const char *parent) "%s"
# qemu-file.c # qemu-file.c
qemu_file_fclose(void) "" qemu_file_fclose(void) ""
# arch_init.c # migration/ram.c
migration_bitmap_sync_start(void) "" migration_bitmap_sync_start(void) ""
migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64"" migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64""
migration_throttle(void) "" migration_throttle(void) ""