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.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJYNP4mAAoJEGw4ysog2bOSouIQALsw0PNpduvEsUzgEZ6GOgFw
 77jEawt4me+eCgB0oipj0Bz9ho2DIGeheiFrvU7vTsD/q00CDc5kZ6GNPlY43sGM
 OzT65EyycQ7MDZFDfVgpmaHjXqIGVf5zZbyz8ZD5wU3w10DdRtrDogYcjb+ZQzCG
 0vRnAkV/tuVkn9Z5ogWrdvhQa0/ER3Yk/BpTXoe4JFoLgViwydkI6yCSw5dwatEU
 djprDinCsBziKDT03Z9wmiTGTvZk6iGHMJWPOLJOSTBd5v9pzdpxtuNrZrF1oOQd
 pBE1qlNkCpnd+LLKyW+nsTdo1FyxUg0pg7kWqnSPwqm+KM09Phpp00FN69Hmz/DR
 P+aMX9qKaTJoNPHklY15pmF/olIkcxVlidNKaqgKAbZZR5BuHF3YBVILWL8ZfaeE
 n6Gw0GqJeTSW5mO81uikKTZt5kqOVChHbxXcxfVl/4vzk8TTS3fy5AW0IERbfgHN
 NbBesSZejqL++xzVrfoVyfJV8nkF1M+08FITQdyXpkdYVB565e9YmlIaLpZ5a7It
 gLVBqbAEOaC+5swlEyAp70h+nhjVN631+b8gs+bi9trrBL9IL8q3g7U0l7XKM0Zs
 MU6nxV2zogbdVraiPv9KrwtOeUKXAPUJfe3fXRr4rBYTL7HK9CBQWjaGNVtFJPKk
 vWybUBSmwF402OmslZKp
 =cds8
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Stefan Hajnoczi 2016-11-23 11:46:15 +00:00
commit 659fc8d342
14 changed files with 195 additions and 27 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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,

View file

@ -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;
}

View file

@ -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),

View file

@ -79,6 +79,12 @@ struct sPAPRPHBState {
uint64_t dma64_win_addr;
uint32_t numa_node;
/* Fields for migration compatibility hacks */
bool pre_2_8_migration;
uint32_t mig_liobn;
hwaddr mig_mem_win_addr, mig_mem_win_size;
hwaddr mig_io_win_addr, mig_io_win_size;
};
#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL

View file

@ -37,6 +37,7 @@
#define _SPAPR_OVEC_H
#include "cpu.h"
#include "migration/vmstate.h"
typedef struct sPAPROptionVector sPAPROptionVector;
@ -64,4 +65,7 @@ sPAPROptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector);
int spapr_ovec_populate_dt(void *fdt, int fdt_offset,
sPAPROptionVector *ov, const char *name);
/* migration */
extern const VMStateDescription vmstate_spapr_ovec;
#endif /* !defined (_SPAPR_OVEC_H) */

View file

@ -18,6 +18,8 @@
VMSTATE_UINT64_EQUAL_V(_f, _s, _v)
#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \
VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v)
#define VMSTATE_UINTTL_TEST(_f, _s, _t) \
VMSTATE_UINT64_TEST(_f, _s, _t)
#define vmstate_info_uinttl vmstate_info_uint64
#else
#define qemu_put_betl qemu_put_be32
@ -35,6 +37,8 @@
VMSTATE_UINT32_EQUAL_V(_f, _s, _v)
#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \
VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)
#define VMSTATE_UINTTL_TEST(_f, _s, _t) \
VMSTATE_UINT32_TEST(_f, _s, _t)
#define vmstate_info_uinttl vmstate_info_uint32
#endif

View file

@ -1166,6 +1166,13 @@ struct PowerPCCPU {
int cpu_dt_id;
uint32_t max_compat;
uint32_t cpu_version;
/* Fields related to migration compatibility hacks */
bool pre_2_8_migration;
target_ulong mig_msr_mask;
uint64_t mig_insns_flags;
uint64_t mig_insns_flags2;
uint32_t mig_nb_BATs;
};
static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)

View file

@ -131,11 +131,14 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
}
/* If PR=1 then EE, IR and DR must be 1
*
* Note: We only enforce this on 64-bit processors. It appears that
* 32-bit implementations supports PR=1 and EE/DR/IR=0 and MacOS
* exploits it.
* Note: We only enforce this on 64-bit server processors.
* It appears that:
* - 32-bit implementations supports PR=1 and EE/DR/IR=0 and MacOS
* exploits it.
* - 64-bit embedded implementations do not need any operation to be
* performed when PR is set.
*/
if ((env->insns_flags & PPC_64B) && ((value >> MSR_PR) & 1)) {
if ((env->insns_flags & PPC_SEGMENT_64B) && ((value >> MSR_PR) & 1)) {
value |= (1 << MSR_EE) | (1 << MSR_DR) | (1 << MSR_IR);
}
#endif

View file

@ -2572,7 +2572,7 @@ static int bcd_cmp_zero(ppc_avr_t *bcd)
static uint16_t get_national_digit(ppc_avr_t *reg, int n)
{
#if defined(HOST_WORDS_BIGENDIAN)
return reg->u16[8 - n];
return reg->u16[7 - n];
#else
return reg->u16[n];
#endif
@ -2581,7 +2581,7 @@ static uint16_t get_national_digit(ppc_avr_t *reg, int n)
static void set_national_digit(ppc_avr_t *reg, uint8_t val, int n)
{
#if defined(HOST_WORDS_BIGENDIAN)
reg->u16[8 - n] = val;
reg->u16[7 - n] = val;
#else
reg->u16[n] = val;
#endif

View file

@ -135,11 +135,33 @@ static const VMStateInfo vmstate_info_avr = {
#define VMSTATE_AVR_ARRAY(_f, _s, _n) \
VMSTATE_AVR_ARRAY_V(_f, _s, _n, 0)
static bool cpu_pre_2_8_migration(void *opaque, int version_id)
{
PowerPCCPU *cpu = opaque;
return cpu->pre_2_8_migration;
}
static void cpu_pre_save(void *opaque)
{
PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
int i;
uint64_t insns_compat_mask =
PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB
| PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES
| PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_FRSQRTES
| PPC_FLOAT_STFIWX | PPC_FLOAT_EXT
| PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ
| PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC
| PPC_64B | PPC_64BX | PPC_ALTIVEC
| PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD;
uint64_t insns_compat_mask2 = PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX
| PPC2_PERM_ISA206 | PPC2_DIVE_ISA206
| PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206
| PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207
| PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207
| PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 | PPC2_TM;
env->spr[SPR_LR] = env->lr;
env->spr[SPR_CTR] = env->ctr;
@ -161,6 +183,14 @@ static void cpu_pre_save(void *opaque)
env->spr[SPR_IBAT4U + 2*i] = env->IBAT[0][i+4];
env->spr[SPR_IBAT4U + 2*i + 1] = env->IBAT[1][i+4];
}
/* Hacks for migration compatibility between 2.6, 2.7 & 2.8 */
if (cpu->pre_2_8_migration) {
cpu->mig_msr_mask = env->msr_mask;
cpu->mig_insns_flags = env->insns_flags & insns_compat_mask;
cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2;
cpu->mig_nb_BATs = env->nb_BATs;
}
}
static int cpu_post_load(void *opaque, int version_id)
@ -561,10 +591,11 @@ const VMStateDescription vmstate_ppc_cpu = {
/* FIXME: access_type? */
/* Sanity checking */
VMSTATE_UINTTL_EQUAL(env.msr_mask, PowerPCCPU),
VMSTATE_UINT64_EQUAL(env.insns_flags, PowerPCCPU),
VMSTATE_UINT64_EQUAL(env.insns_flags2, PowerPCCPU),
VMSTATE_UINT32_EQUAL(env.nb_BATs, PowerPCCPU),
VMSTATE_UINTTL_TEST(mig_msr_mask, PowerPCCPU, cpu_pre_2_8_migration),
VMSTATE_UINT64_TEST(mig_insns_flags, PowerPCCPU, cpu_pre_2_8_migration),
VMSTATE_UINT64_TEST(mig_insns_flags2, PowerPCCPU,
cpu_pre_2_8_migration),
VMSTATE_UINT32_TEST(mig_nb_BATs, PowerPCCPU, cpu_pre_2_8_migration),
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription*[]) {

View file

@ -10520,6 +10520,11 @@ static gchar *ppc_gdb_arch_name(CPUState *cs)
#endif
}
static Property ppc_cpu_properties[] = {
DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, false),
DEFINE_PROP_END_OF_LIST(),
};
static void ppc_cpu_class_init(ObjectClass *oc, void *data)
{
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
@ -10532,6 +10537,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
dc->realize = ppc_cpu_realizefn;
dc->unrealize = ppc_cpu_unrealizefn;
dc->props = ppc_cpu_properties;
pcc->parent_reset = cc->reset;
cc->reset = ppc_cpu_reset;

View file

@ -380,17 +380,21 @@ static void test_migrate(void)
" -incoming %s",
tmpfs, bootpath, uri);
} else if (strcmp(arch, "ppc64") == 0) {
const char *accel;
/* On ppc64, the test only works with kvm-hv, but not with kvm-pr */
accel = access("/sys/module/kvm_hv", F_OK) ? "tcg" : "kvm:tcg";
init_bootfile_ppc(bootpath);
cmd_src = g_strdup_printf("-machine accel=kvm:tcg -m 256M"
cmd_src = g_strdup_printf("-machine accel=%s -m 256M"
" -name pcsource,debug-threads=on"
" -serial file:%s/src_serial"
" -drive file=%s,if=pflash,format=raw",
tmpfs, bootpath);
cmd_dst = g_strdup_printf("-machine accel=kvm:tcg -m 256M"
accel, tmpfs, bootpath);
cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
" -name pcdest,debug-threads=on"
" -serial file:%s/dest_serial"
" -incoming %s",
tmpfs, uri);
accel, tmpfs, uri);
} else {
g_assert_not_reached();
}