Commit 56b51708 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.9-20170306' into staging



ppc patch queue for 2017-03-06

Looks like my previous batch wasn't quite the last before hard freeze.
This has a handful of bugfixes to go in.  They're all genuine
bugfixes, though not regressions in some cases.

# gpg: Signature made Mon 06 Mar 2017 04:07:48 GMT
# gpg:                using RSA key 0x6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-2.9-20170306:
  target/ppc: use helper for excp handling
  target/ppc: fmadd: add macro for updating flags
  target/ppc: fmadd check for excp independently
  spapr: ensure that all threads within core are on the same NUMA node
  ppc/xics: register reset handlers for the ICP and ICS objects

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents fbddc2e5 182fe2cf
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -333,7 +333,7 @@ static const VMStateDescription vmstate_icp_server = {
    },
};

static void icp_reset(DeviceState *dev)
static void icp_reset(void *dev)
{
    ICPState *icp = ICP(dev);

@@ -359,6 +359,8 @@ static void icp_realize(DeviceState *dev, Error **errp)
    }

    icp->xics = XICS_FABRIC(obj);

    qemu_register_reset(icp_reset, dev);
}


@@ -366,7 +368,6 @@ static void icp_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->reset = icp_reset;
    dc->vmsd = &vmstate_icp_server;
    dc->realize = icp_realize;
}
@@ -522,7 +523,7 @@ static void ics_simple_eoi(ICSState *ics, uint32_t nr)
    }
}

static void ics_simple_reset(DeviceState *dev)
static void ics_simple_reset(void *dev)
{
    ICSState *ics = ICS_SIMPLE(dev);
    int i;
@@ -611,6 +612,8 @@ static void ics_simple_realize(DeviceState *dev, Error **errp)
    }
    ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
    ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);

    qemu_register_reset(ics_simple_reset, dev);
}

static Property ics_simple_properties[] = {
@@ -626,7 +629,6 @@ static void ics_simple_class_init(ObjectClass *klass, void *data)
    isc->realize = ics_simple_realize;
    dc->props = ics_simple_properties;
    dc->vmsd = &vmstate_ics_simple;
    dc->reset = ics_simple_reset;
    isc->reject = ics_simple_reject;
    isc->resend = ics_simple_resend;
    isc->eoi = ics_simple_eoi;
+10 −5
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ static int icp_set_kvm_state(ICPState *icp, int version_id)
    return 0;
}

static void icp_kvm_reset(DeviceState *dev)
static void icp_kvm_reset(void *dev)
{
    ICPState *icp = ICP(dev);

@@ -146,12 +146,17 @@ static void icp_kvm_cpu_setup(ICPState *icp, PowerPCCPU *cpu)
    icp->cap_irq_xics_enabled = true;
}

static void icp_kvm_realize(DeviceState *dev, Error **errp)
{
    qemu_register_reset(icp_kvm_reset, dev);
}

static void icp_kvm_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    ICPStateClass *icpc = ICP_CLASS(klass);

    dc->reset = icp_kvm_reset;
    dc->realize = icp_kvm_realize;
    icpc->pre_save = icp_get_kvm_state;
    icpc->post_load = icp_set_kvm_state;
    icpc->cpu_setup = icp_kvm_cpu_setup;
@@ -293,7 +298,7 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val)
    }
}

static void ics_kvm_reset(DeviceState *dev)
static void ics_kvm_reset(void *dev)
{
    ICSState *ics = ICS_SIMPLE(dev);
    int i;
@@ -324,15 +329,15 @@ static void ics_kvm_realize(DeviceState *dev, Error **errp)
    }
    ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
    ics->qirqs = qemu_allocate_irqs(ics_kvm_set_irq, ics, ics->nr_irqs);

    qemu_register_reset(ics_kvm_reset, dev);
}

static void ics_kvm_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    ICSStateClass *icsc = ICS_BASE_CLASS(klass);

    icsc->realize = ics_kvm_realize;
    dc->reset = ics_kvm_reset;
    icsc->pre_save = ics_get_kvm_state;
    icsc->post_load = ics_set_kvm_state;
}
+0 −2
Original line number Diff line number Diff line
@@ -106,7 +106,6 @@ static int try_create_xics(sPAPRMachineState *spapr, const char *type_ics,
    int i;

    ics = ICS_SIMPLE(object_new(type_ics));
    qdev_set_parent_bus(DEVICE(ics), sysbus_get_default());
    object_property_add_child(OBJECT(spapr), "ics", OBJECT(ics), NULL);
    object_property_set_int(OBJECT(ics), nr_irqs, "nr-irqs", &err);
    object_property_add_const_link(OBJECT(ics), "xics", OBJECT(xi), NULL);
@@ -123,7 +122,6 @@ static int try_create_xics(sPAPRMachineState *spapr, const char *type_ics,
        ICPState *icp = &spapr->icps[i];

        object_initialize(icp, sizeof(*icp), type_icp);
        qdev_set_parent_bus(DEVICE(icp), sysbus_get_default());
        object_property_add_child(OBJECT(spapr), "icp[*]", OBJECT(icp), NULL);
        object_property_add_const_link(OBJECT(icp), "xics", OBJECT(xi), NULL);
        object_property_set_bool(OBJECT(icp), true, "realized", &err);
+15 −8
Original line number Diff line number Diff line
@@ -63,8 +63,6 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
                           Error **errp)
{
    CPUPPCState *env = &cpu->env;
    CPUState *cs = CPU(cpu);
    int i;

    /* Set time-base frequency to 512 MHz */
    cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
@@ -82,12 +80,6 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
        }
    }

    /* Set NUMA node for the added CPUs  */
    i = numa_get_node_for_cpu(cs->cpu_index);
    if (i < nb_numa_nodes) {
            cs->numa_node = i;
    }

    xics_cpu_setup(XICS_FABRIC(spapr), cpu);

    qemu_register_reset(spapr_cpu_reset, cpu);
@@ -171,11 +163,13 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
    const char *typename = object_class_get_name(scc->cpu_class);
    size_t size = object_type_get_instance_size(typename);
    Error *local_err = NULL;
    int core_node_id = numa_get_node_for_cpu(cc->core_id);;
    void *obj;
    int i, j;

    sc->threads = g_malloc0(size * cc->nr_threads);
    for (i = 0; i < cc->nr_threads; i++) {
        int node_id;
        char id[32];
        CPUState *cs;

@@ -184,6 +178,19 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
        object_initialize(obj, size, typename);
        cs = CPU(obj);
        cs->cpu_index = cc->core_id + i;

        /* Set NUMA node for the added CPUs  */
        node_id = numa_get_node_for_cpu(cs->cpu_index);
        if (node_id != core_node_id) {
            error_setg(&local_err, "Invalid node-id=%d of thread[cpu-index: %d]"
                " on CPU[core-id: %d, node-id: %d], node-id must be the same",
                 node_id, cs->cpu_index, cc->core_id, core_node_id);
            goto err;
        }
        if (node_id < nb_numa_nodes) {
            cs->numa_node = node_id;
        }

        snprintf(id, sizeof(id), "thread[%d]", i);
        object_property_add_child(OBJECT(sc), id, obj, &local_err);
        if (local_err) {
+32 −45
Original line number Diff line number Diff line
@@ -743,34 +743,38 @@ uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
    return do_fri(env, arg, float_round_down);
}

static void float64_maddsub_update_excp(CPUPPCState *env, float64 arg1,
                                        float64 arg2, float64 arg3,
                                        unsigned int madd_flags)
{
    if (unlikely((float64_is_infinity(arg1) && float64_is_zero(arg2)) ||
                 (float64_is_zero(arg1) && float64_is_infinity(arg2)))) {
        /* Multiplication of zero by infinity */
        arg1 = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
    } else if (unlikely(float64_is_signaling_nan(arg1, &env->fp_status) ||
                        float64_is_signaling_nan(arg2, &env->fp_status) ||
                        float64_is_signaling_nan(arg3, &env->fp_status))) {
        /* sNaN operation */
        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
    } else if ((float64_is_infinity(arg1) || float64_is_infinity(arg2)) &&
               float64_is_infinity(arg3)) {
        uint8_t aSign, bSign, cSign;

        aSign = float64_is_neg(arg1);
        bSign = float64_is_neg(arg2);
        cSign = float64_is_neg(arg3);
        if (madd_flags & float_muladd_negate_c) {
            cSign ^= 1;
        }
        if (aSign ^ bSign ^ cSign) {
            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
        }
    }
#define FPU_MADDSUB_UPDATE(NAME, TP)                                    \
static void NAME(CPUPPCState *env, TP arg1, TP arg2, TP arg3,           \
                 unsigned int madd_flags)                               \
{                                                                       \
    if (TP##_is_signaling_nan(arg1, &env->fp_status) ||                 \
        TP##_is_signaling_nan(arg2, &env->fp_status) ||                 \
        TP##_is_signaling_nan(arg3, &env->fp_status)) {                 \
        /* sNaN operation */                                            \
        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);          \
    }                                                                   \
    if ((TP##_is_infinity(arg1) && TP##_is_zero(arg2)) ||               \
        (TP##_is_zero(arg1) && TP##_is_infinity(arg2))) {               \
        /* Multiplication of zero by infinity */                        \
        float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);           \
    }                                                                   \
    if ((TP##_is_infinity(arg1) || TP##_is_infinity(arg2)) &&           \
        TP##_is_infinity(arg3)) {                                       \
        uint8_t aSign, bSign, cSign;                                    \
                                                                        \
        aSign = TP##_is_neg(arg1);                                      \
        bSign = TP##_is_neg(arg2);                                      \
        cSign = TP##_is_neg(arg3);                                      \
        if (madd_flags & float_muladd_negate_c) {                       \
            cSign ^= 1;                                                 \
        }                                                               \
        if (aSign ^ bSign ^ cSign) {                                    \
            float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);       \
        }                                                               \
    }                                                                   \
}
FPU_MADDSUB_UPDATE(float32_maddsub_update_excp, float32)
FPU_MADDSUB_UPDATE(float64_maddsub_update_excp, float64)

#define FPU_FMADD(op, madd_flags)                                       \
uint64_t helper_##op(CPUPPCState *env, uint64_t arg1,                   \
@@ -2236,24 +2240,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
        env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
                                                                              \
        if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
            if (tp##_is_signaling_nan(xa.fld, &tstat) ||                      \
                tp##_is_signaling_nan(b->fld, &tstat) ||                      \
                tp##_is_signaling_nan(c->fld, &tstat)) {                      \
                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
                tstat.float_exception_flags &= ~float_flag_invalid;           \
            }                                                                 \
            if ((tp##_is_infinity(xa.fld) && tp##_is_zero(b->fld)) ||         \
                (tp##_is_zero(xa.fld) && tp##_is_infinity(b->fld))) {         \
                xt_out.fld = float64_to_##tp(float_invalid_op_excp(env,       \
                    POWERPC_EXCP_FP_VXIMZ, sfprf), &env->fp_status);          \
                tstat.float_exception_flags &= ~float_flag_invalid;           \
            }                                                                 \
            if ((tstat.float_exception_flags & float_flag_invalid) &&         \
                ((tp##_is_infinity(xa.fld) ||                                 \
                  tp##_is_infinity(b->fld)) &&                                \
                  tp##_is_infinity(c->fld))) {                                \
                float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf);     \
            }                                                                 \
            tp##_maddsub_update_excp(env, xa.fld, b->fld, c->fld, maddflgs);  \
        }                                                                     \
                                                                              \
        if (r2sp) {                                                           \