diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2016-11-23 11:46:15 +0000 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2016-11-23 11:46:15 +0000 |
commit | 659fc8d3427bf54ff50b7fffb2ca2fc0690d5e92 (patch) | |
tree | 051737f34916d9f58499e48ca8d143f3f9ac26fc /hw | |
parent | f0c10c392fc23d4bfeca0afe0de80d5036ed92ed (diff) | |
parent | 5c4537bded40640b166ec77e112592174b048c21 (diff) |
Merge remote-tracking branch 'dgibson/tags/ppc-for-2.8-20161123' into staging
ppc patch queue 2016-11-23
Here's the first set of 2.8 hard freeze bugfixes for ppc.
The biggest thing here is a batch of fixes for migration breakages in
both 2.7 and current 2.8. Alas, there is at least one more migration
problem, which prevents memory unplug after a migration. I hoped to
include a fix for that here, but it turned out to have some problems
bigger than those it was solving. So, I expect at least one more hard
freeze pull request.
There are also a few other assorted bug fixes.
# gpg: Signature made Wed 23 Nov 2016 02:25:42 AM GMT
# gpg: using RSA key 0x6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>"
# gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392
* dgibson/tags/ppc-for-2.8-20161123:
spapr: Fix 2.7<->2.8 migration of PCI host bridge
Revert "spapr: Fix migration of PCI host bridges from qemu-2.7"
target-ppc: Allow eventual removal of old migration mistakes
migration: Add VMSTATE_UINTTL_TEST()
target-ppc: Fix CPU migration from qemu-2.6 <-> later versions
ppc: Make uninorth interrupt swizzling identical to Grackle
target-ppc: fix index array of national digits
hw/char/spapr_vty: Return amount of free buffer entries in vty_can_receive()
ppc: BOOK3E: nothing should be done when MSR:PR is set
spapr: migration support for CAS-negotiated option vectors
tests/postcopy: Use KVM on ppc64 only if it is KVM-HV
Message-id: 1479869383-16162-1-git-send-email-david@gibson.dropbear.id.au
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/char/spapr_vty.c | 2 | ||||
-rw-r--r-- | hw/pci-host/uninorth.c | 4 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 76 | ||||
-rw-r--r-- | hw/ppc/spapr_ovec.c | 12 | ||||
-rw-r--r-- | hw/ppc/spapr_pci.c | 35 |
5 files changed, 116 insertions, 13 deletions
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index 06b9b3917f..7c22b8bd0e 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -25,7 +25,7 @@ static int vty_can_receive(void *opaque) { VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque); - return (dev->in - dev->out) < VTERM_BUFSIZE; + return VTERM_BUFSIZE - (dev->in - dev->out); } static void vty_receive(void *opaque, const uint8_t *buf, int size) diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index 7aac4d67a4..df342ac3cb 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -62,9 +62,7 @@ typedef struct UNINState { static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num) { - int devfn = pci_dev->devfn & 0x00FFFFFF; - - return (((devfn >> 11) & 0x1F) + irq_num) & 3; + return (irq_num + (pci_dev->devfn >> 3)) & 3; } static void pci_unin_set_irq(void *opaque, int irq_num, int level) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 0cbab24c91..c3269c7f50 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1267,6 +1267,68 @@ static bool version_before_3(void *opaque, int version_id) return version_id < 3; } +static bool spapr_ov5_cas_needed(void *opaque) +{ + sPAPRMachineState *spapr = opaque; + sPAPROptionVector *ov5_mask = spapr_ovec_new(); + sPAPROptionVector *ov5_legacy = spapr_ovec_new(); + sPAPROptionVector *ov5_removed = spapr_ovec_new(); + bool cas_needed; + + /* Prior to the introduction of sPAPROptionVector, we had two option + * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. + * Both of these options encode machine topology into the device-tree + * in such a way that the now-booted OS should still be able to interact + * appropriately with QEMU regardless of what options were actually + * negotiatied on the source side. + * + * As such, we can avoid migrating the CAS-negotiated options if these + * are the only options available on the current machine/platform. + * Since these are the only options available for pseries-2.7 and + * earlier, this allows us to maintain old->new/new->old migration + * compatibility. + * + * For QEMU 2.8+, there are additional CAS-negotiatable options available + * via default pseries-2.8 machines and explicit command-line parameters. + * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware + * of the actual CAS-negotiated values to continue working properly. For + * example, availability of memory unplug depends on knowing whether + * OV5_HP_EVT was negotiated via CAS. + * + * Thus, for any cases where the set of available CAS-negotiatable + * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we + * include the CAS-negotiated options in the migration stream. + */ + spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); + spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); + + /* spapr_ovec_diff returns true if bits were removed. we avoid using + * the mask itself since in the future it's possible "legacy" bits may be + * removed via machine options, which could generate a false positive + * that breaks migration. + */ + spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask); + cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy); + + spapr_ovec_cleanup(ov5_mask); + spapr_ovec_cleanup(ov5_legacy); + spapr_ovec_cleanup(ov5_removed); + + return cas_needed; +} + +static const VMStateDescription vmstate_spapr_ov5_cas = { + .name = "spapr_option_vector_ov5_cas", + .version_id = 1, + .minimum_version_id = 1, + .needed = spapr_ov5_cas_needed, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_POINTER_V(ov5_cas, sPAPRMachineState, 1, + vmstate_spapr_ovec, sPAPROptionVector), + VMSTATE_END_OF_LIST() + }, +}; + static const VMStateDescription vmstate_spapr = { .name = "spapr", .version_id = 3, @@ -1282,6 +1344,10 @@ static const VMStateDescription vmstate_spapr = { VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), VMSTATE_END_OF_LIST() }, + .subsections = (const VMStateDescription*[]) { + &vmstate_spapr_ov5_cas, + NULL + } }; static int htab_save_setup(QEMUFile *f, void *opaque) @@ -2701,6 +2767,16 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", true); .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ .property = "mem64_win_size", \ .value = "0", \ + }, \ + { \ + .driver = TYPE_POWERPC_CPU, \ + .property = "pre-2.8-migration", \ + .value = "on", \ + }, \ + { \ + .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ + .property = "pre-2.8-migration", \ + .value = "on", \ }, static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index, diff --git a/hw/ppc/spapr_ovec.c b/hw/ppc/spapr_ovec.c index c2a0d18577..3eb1d5976f 100644 --- a/hw/ppc/spapr_ovec.c +++ b/hw/ppc/spapr_ovec.c @@ -37,6 +37,17 @@ */ struct sPAPROptionVector { unsigned long *bitmap; + int32_t bitmap_size; /* only used for migration */ +}; + +const VMStateDescription vmstate_spapr_ovec = { + .name = "spapr_option_vector", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_BITMAP(bitmap, sPAPROptionVector, 1, bitmap_size), + VMSTATE_END_OF_LIST() + } }; sPAPROptionVector *spapr_ovec_new(void) @@ -45,6 +56,7 @@ sPAPROptionVector *spapr_ovec_new(void) ov = g_new0(sPAPROptionVector, 1); ov->bitmap = bitmap_new(OV_MAXBITS); + ov->bitmap_size = OV_MAXBITS; return ov; } diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index f9661b7d1a..fd6fc1d953 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1590,6 +1590,8 @@ static Property spapr_phb_properties[] = { DEFINE_PROP_UINT64("pgsz", sPAPRPHBState, page_size_mask, (1ULL << 12) | (1ULL << 16)), DEFINE_PROP_UINT32("numa_node", sPAPRPHBState, numa_node, -1), + DEFINE_PROP_BOOL("pre-2.8-migration", sPAPRPHBState, + pre_2_8_migration, false), DEFINE_PROP_END_OF_LIST(), }; @@ -1636,6 +1638,20 @@ static void spapr_pci_pre_save(void *opaque) sphb->msi_devs[i].key = *(uint32_t *) key; sphb->msi_devs[i].value = *(spapr_pci_msi *) value; } + + if (sphb->pre_2_8_migration) { + sphb->mig_liobn = sphb->dma_liobn[0]; + sphb->mig_mem_win_addr = sphb->mem_win_addr; + sphb->mig_mem_win_size = sphb->mem_win_size; + sphb->mig_io_win_addr = sphb->io_win_addr; + sphb->mig_io_win_size = sphb->io_win_size; + + if ((sphb->mem64_win_size != 0) + && (sphb->mem64_win_addr + == (sphb->mem_win_addr + sphb->mem_win_size))) { + sphb->mig_mem_win_size += sphb->mem64_win_size; + } + } } static int spapr_pci_post_load(void *opaque, int version_id) @@ -1658,25 +1674,26 @@ static int spapr_pci_post_load(void *opaque, int version_id) return 0; } -static bool version_before_3(void *opaque, int version_id) +static bool pre_2_8_migration(void *opaque, int version_id) { - return version_id < 3; + sPAPRPHBState *sphb = opaque; + + return sphb->pre_2_8_migration; } static const VMStateDescription vmstate_spapr_pci = { .name = "spapr_pci", - .version_id = 3, + .version_id = 2, .minimum_version_id = 2, .pre_save = spapr_pci_pre_save, .post_load = spapr_pci_post_load, .fields = (VMStateField[]) { VMSTATE_UINT64_EQUAL(buid, sPAPRPHBState), - VMSTATE_UNUSED_TEST(version_before_3, - sizeof(uint32_t) /* dma_liobn[0] */ - + sizeof(uint64_t) /* mem_win_addr */ - + sizeof(uint64_t) /* mem_win_size */ - + sizeof(uint64_t) /* io_win_addr */ - + sizeof(uint64_t) /* io_win_size */), + VMSTATE_UINT32_TEST(mig_liobn, sPAPRPHBState, pre_2_8_migration), + VMSTATE_UINT64_TEST(mig_mem_win_addr, sPAPRPHBState, pre_2_8_migration), + VMSTATE_UINT64_TEST(mig_mem_win_size, sPAPRPHBState, pre_2_8_migration), + VMSTATE_UINT64_TEST(mig_io_win_addr, sPAPRPHBState, pre_2_8_migration), + VMSTATE_UINT64_TEST(mig_io_win_size, sPAPRPHBState, pre_2_8_migration), VMSTATE_STRUCT_ARRAY(lsi_table, sPAPRPHBState, PCI_NUM_PINS, 0, vmstate_spapr_pci_lsi, struct spapr_pci_lsi), VMSTATE_INT32(msi_devs_num, sPAPRPHBState), |