diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2014-07-28 17:34:15 +0200 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2014-07-28 23:02:39 +0200 |
commit | 07fb61760cdea7c3f1b9c897513986945bca8e89 (patch) | |
tree | e2ff26a669b9587e12bdd4aa86a2ecd244e6b057 /hw/i386/pc_piix.c | |
parent | acd727e7cb11d7aeea3343cf11bba22238530b4c (diff) | |
download | qemu-07fb61760cdea7c3f1b9c897513986945bca8e89.tar.gz qemu-07fb61760cdea7c3f1b9c897513986945bca8e89.tar.bz2 qemu-07fb61760cdea7c3f1b9c897513986945bca8e89.zip |
pc: hack for migration compatibility from QEMU 2.0
Changing the ACPI table size causes migration to break, and the memory
hotplug work opened our eyes on how horribly we were breaking things in
2.0 already.
The ACPI table size is rounded to the next 4k, which one would think
gives some headroom. In practice this is not the case, because the user
can control the ACPI table size (each CPU adds 97 bytes to the SSDT and
8 to the MADT) and so some "-smp" values will break the 4k boundary and
fail to migrate. Similarly, PCI bridges add ~1870 bytes to the SSDT.
This patch concerns itself with fixing migration from QEMU 2.0. It
computes the payload size of QEMU 2.0 and always uses that one.
The previous patch shrunk the ACPI tables enough that the QEMU 2.0 size
should always be enough; non-AML tables can change depending on the
configuration (especially MADT, SRAT, HPET) but they remain the same
between QEMU 2.0 and 2.1, so we only compute our padding based on the
sizes of the SSDT and DSDT.
Migration from QEMU 1.7 should work for guests that have a number of CPUs
other than 12, 13, 14, 54, 55, 56, 97, 98, 139, 140. It was already
broken from QEMU 1.7 to QEMU 2.0 in the same way, though.
Even with this patch, QEMU 1.7 and 2.0 have two different ideas of
"-M pc-i440fx-2.0" when there are PCI bridges. Igor sent a patch to
adopt the QEMU 1.7 definition. I think distributions should apply
it if they move directly from QEMU 1.7 to 2.1+ without ever packaging
version 2.0.
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/i386/pc_piix.c')
-rw-r--r-- | hw/i386/pc_piix.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 7081c08a69..4524e6b56e 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -61,6 +61,7 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; static bool has_pci_info; static bool has_acpi_build = true; +static int legacy_acpi_table_size; static bool smbios_defaults = true; static bool smbios_legacy_mode; /* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to @@ -163,6 +164,7 @@ static void pc_init1(MachineState *machine, guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); guest_info->has_acpi_build = has_acpi_build; + guest_info->legacy_acpi_table_size = legacy_acpi_table_size; guest_info->has_pci_info = has_pci_info; guest_info->isapc_ram_fw = !pci_enabled; @@ -297,6 +299,23 @@ static void pc_init_pci(MachineState *machine) static void pc_compat_2_0(MachineState *machine) { + /* This value depends on the actual DSDT and SSDT compiled into + * the source QEMU; unfortunately it depends on the binary and + * not on the machine type, so we cannot make pc-i440fx-1.7 work on + * both QEMU 1.7 and QEMU 2.0. + * + * Large variations cause migration to fail for more than one + * consecutive value of the "-smp" maxcpus option. + * + * For small variations of the kind caused by different iasl versions, + * the 4k rounding usually leaves slack. However, there could be still + * one or two values that break. For QEMU 1.7 and QEMU 2.0 the + * slack is only ~10 bytes before one "-smp maxcpus" value breaks! + * + * 6652 is valid for QEMU 2.0, the right value for pc-i440fx-1.7 on + * QEMU 1.7 it is 6414. For RHEL/CentOS 7.0 it is 6418. + */ + legacy_acpi_table_size = 6652; smbios_legacy_mode = true; has_reserved_memory = false; } |