Commit bbe16574 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/vivier2/tags/ppc-for-4.2-pull-request' into staging



ppc patch queue 2019-11-15

Several fixes for 4.2.0-rc2:

fix mos6522 performance issue,
xive/xics issues,
fix /chosen device-tree on reset
and KVM default cpu-model for all machine classes

# gpg: Signature made Mon 18 Nov 2019 10:52:19 GMT
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "lvivier@redhat.com"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* remotes/vivier2/tags/ppc-for-4.2-pull-request:
  mos6522: fix T1 and T2 timers
  spapr/kvm: Set default cpu model for all machine classes
  spapr: Add /chosen to FDT only at reset time to preserve kernel and initramdisk
  ppc: Skip partially initialized vCPUs in 'info pic'
  xive, xics: Fix reference counting on CPU objects
  ppc: Add intc_destroy() handlers to SpaprInterruptController/PnvChip

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 369e8f5b cd8843ff
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -555,6 +555,15 @@ static void spapr_xive_cpu_intc_reset(SpaprInterruptController *intc,
    xive_tctx_set_os_cam(tctx, xive_nvt_cam_line(nvt_blk, nvt_idx));
}

static void spapr_xive_cpu_intc_destroy(SpaprInterruptController *intc,
                                        PowerPCCPU *cpu)
{
    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);

    xive_tctx_destroy(spapr_cpu->tctx);
    spapr_cpu->tctx = NULL;
}

static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val)
{
    SpaprXive *xive = SPAPR_XIVE(intc);
@@ -692,6 +701,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
    sicc->deactivate = spapr_xive_deactivate;
    sicc->cpu_intc_create = spapr_xive_cpu_intc_create;
    sicc->cpu_intc_reset = spapr_xive_cpu_intc_reset;
    sicc->cpu_intc_destroy = spapr_xive_cpu_intc_destroy;
    sicc->claim_irq = spapr_xive_claim_irq;
    sicc->free_irq = spapr_xive_free_irq;
    sicc->set_irq = spapr_xive_set_irq;
+21 −1
Original line number Diff line number Diff line
@@ -44,7 +44,16 @@

void icp_pic_print_info(ICPState *icp, Monitor *mon)
{
    int cpu_index = icp->cs ? icp->cs->cpu_index : -1;
    int cpu_index;

    /* Skip partially initialized vCPUs. This can happen on sPAPR when vCPUs
     * are hot plugged or unplugged.
     */
    if (!icp) {
        return;
    }

    cpu_index = icp->cs ? icp->cs->cpu_index : -1;

    if (!icp->output) {
        return;
@@ -388,8 +397,10 @@ Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp)
    obj = object_new(type);
    object_property_add_child(cpu, type, obj, &error_abort);
    object_unref(obj);
    object_ref(OBJECT(xi));
    object_property_add_const_link(obj, ICP_PROP_XICS, OBJECT(xi),
                                   &error_abort);
    object_ref(cpu);
    object_property_add_const_link(obj, ICP_PROP_CPU, cpu, &error_abort);
    object_property_set_bool(obj, true, "realized", &local_err);
    if (local_err) {
@@ -401,6 +412,15 @@ Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp)
    return obj;
}

void icp_destroy(ICPState *icp)
{
    Object *obj = OBJECT(icp);

    object_unref(object_property_get_link(obj, ICP_PROP_CPU, &error_abort));
    object_unref(object_property_get_link(obj, ICP_PROP_XICS, &error_abort));
    object_unparent(obj);
}

/*
 * ICS: Source layer
 */
+10 −0
Original line number Diff line number Diff line
@@ -352,6 +352,15 @@ static void xics_spapr_cpu_intc_reset(SpaprInterruptController *intc,
    icp_reset(spapr_cpu_state(cpu)->icp);
}

static void xics_spapr_cpu_intc_destroy(SpaprInterruptController *intc,
                                        PowerPCCPU *cpu)
{
    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);

    icp_destroy(spapr_cpu->icp);
    spapr_cpu->icp = NULL;
}

static int xics_spapr_claim_irq(SpaprInterruptController *intc, int irq,
                                bool lsi, Error **errp)
{
@@ -440,6 +449,7 @@ static void ics_spapr_class_init(ObjectClass *klass, void *data)
    sicc->deactivate = xics_spapr_deactivate;
    sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
    sicc->cpu_intc_reset = xics_spapr_cpu_intc_reset;
    sicc->cpu_intc_destroy = xics_spapr_cpu_intc_destroy;
    sicc->claim_irq = xics_spapr_claim_irq;
    sicc->free_irq = xics_spapr_free_irq;
    sicc->set_irq = xics_spapr_set_irq;
+19 −1
Original line number Diff line number Diff line
@@ -523,9 +523,18 @@ static const char * const xive_tctx_ring_names[] = {

void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon)
{
    int cpu_index = tctx->cs ? tctx->cs->cpu_index : -1;
    int cpu_index;
    int i;

    /* Skip partially initialized vCPUs. This can happen on sPAPR when vCPUs
     * are hot plugged or unplugged.
     */
    if (!tctx) {
        return;
    }

    cpu_index = tctx->cs ? tctx->cs->cpu_index : -1;

    if (kvm_irqchip_in_kernel()) {
        Error *local_err = NULL;

@@ -682,6 +691,7 @@ Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp)
    obj = object_new(TYPE_XIVE_TCTX);
    object_property_add_child(cpu, TYPE_XIVE_TCTX, obj, &error_abort);
    object_unref(obj);
    object_ref(cpu);
    object_property_add_const_link(obj, "cpu", cpu, &error_abort);
    object_property_set_bool(obj, true, "realized", &local_err);
    if (local_err) {
@@ -696,6 +706,14 @@ error:
    return NULL;
}

void xive_tctx_destroy(XiveTCTX *tctx)
{
    Object *obj = OBJECT(tctx);

    object_unref(object_property_get_link(obj, "cpu", &error_abort));
    object_unparent(obj);
}

/*
 * XIVE ESB helpers
 */
+52 −15
Original line number Diff line number Diff line
@@ -38,7 +38,9 @@

/* XXX: implement all timer modes */

static void mos6522_timer_update(MOS6522State *s, MOS6522Timer *ti,
static void mos6522_timer1_update(MOS6522State *s, MOS6522Timer *ti,
                                  int64_t current_time);
static void mos6522_timer2_update(MOS6522State *s, MOS6522Timer *ti,
                                  int64_t current_time);

static void mos6522_update_irq(MOS6522State *s)
@@ -98,7 +100,11 @@ static void set_counter(MOS6522State *s, MOS6522Timer *ti, unsigned int val)
    trace_mos6522_set_counter(1 + ti->index, val);
    ti->load_time = get_load_time(s, ti);
    ti->counter_value = val;
    mos6522_timer_update(s, ti, ti->load_time);
    if (ti->index == 0) {
        mos6522_timer1_update(s, ti, ti->load_time);
    } else {
        mos6522_timer2_update(s, ti, ti->load_time);
    }
}

static int64_t get_next_irq_time(MOS6522State *s, MOS6522Timer *ti,
@@ -130,19 +136,34 @@ static int64_t get_next_irq_time(MOS6522State *s, MOS6522Timer *ti,
    trace_mos6522_get_next_irq_time(ti->latch, d, next_time - d);
    next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, ti->frequency) +
                         ti->load_time;

    if (next_time <= current_time) {
        next_time = current_time + 1;
    }
    return next_time;
}

static void mos6522_timer_update(MOS6522State *s, MOS6522Timer *ti,
static void mos6522_timer1_update(MOS6522State *s, MOS6522Timer *ti,
                                 int64_t current_time)
{
    if (!ti->timer) {
        return;
    }
    if (ti->index == 0 && (s->acr & T1MODE) != T1MODE_CONT) {
    if ((s->ier & T1_INT) == 0 || (s->acr & T1MODE) != T1MODE_CONT) {
        timer_del(ti->timer);
    } else {
        ti->next_irq_time = get_next_irq_time(s, ti, current_time);
        timer_mod(ti->timer, ti->next_irq_time);
    }
}

static void mos6522_timer2_update(MOS6522State *s, MOS6522Timer *ti,
                                 int64_t current_time)
{
    if (!ti->timer) {
        return;
    }
    if ((s->ier & T2_INT) == 0) {
        timer_del(ti->timer);
    } else {
        ti->next_irq_time = get_next_irq_time(s, ti, current_time);
@@ -155,7 +176,7 @@ static void mos6522_timer1(void *opaque)
    MOS6522State *s = opaque;
    MOS6522Timer *ti = &s->timers[0];

    mos6522_timer_update(s, ti, ti->next_irq_time);
    mos6522_timer1_update(s, ti, ti->next_irq_time);
    s->ifr |= T1_INT;
    mos6522_update_irq(s);
}
@@ -165,7 +186,7 @@ static void mos6522_timer2(void *opaque)
    MOS6522State *s = opaque;
    MOS6522Timer *ti = &s->timers[1];

    mos6522_timer_update(s, ti, ti->next_irq_time);
    mos6522_timer2_update(s, ti, ti->next_irq_time);
    s->ifr |= T2_INT;
    mos6522_update_irq(s);
}
@@ -204,7 +225,16 @@ uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size)
{
    MOS6522State *s = opaque;
    uint32_t val;
    int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);

    if (now >= s->timers[0].next_irq_time) {
        mos6522_timer1_update(s, &s->timers[0], now);
        s->ifr |= T1_INT;
    }
    if (now >= s->timers[1].next_irq_time) {
        mos6522_timer2_update(s, &s->timers[1], now);
        s->ifr |= T2_INT;
    }
    switch (addr) {
    case VIA_REG_B:
        val = s->b;
@@ -299,7 +329,7 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
        break;
    case VIA_REG_T1CL:
        s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
        mos6522_timer_update(s, &s->timers[0],
        mos6522_timer1_update(s, &s->timers[0],
                              qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
        break;
    case VIA_REG_T1CH:
@@ -309,13 +339,13 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
        break;
    case VIA_REG_T1LL:
        s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
        mos6522_timer_update(s, &s->timers[0],
        mos6522_timer1_update(s, &s->timers[0],
                              qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
        break;
    case VIA_REG_T1LH:
        s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
        s->ifr &= ~T1_INT;
        mos6522_timer_update(s, &s->timers[0],
        mos6522_timer1_update(s, &s->timers[0],
                              qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
        break;
    case VIA_REG_T2CL:
@@ -334,7 +364,7 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
        break;
    case VIA_REG_ACR:
        s->acr = val;
        mos6522_timer_update(s, &s->timers[0],
        mos6522_timer1_update(s, &s->timers[0],
                              qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
        break;
    case VIA_REG_PCR:
@@ -354,6 +384,11 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
            s->ier &= ~val;
        }
        mos6522_update_irq(s);
        /* if IER is modified starts needed timers */
        mos6522_timer1_update(s, &s->timers[0],
                              qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
        mos6522_timer2_update(s, &s->timers[1],
                              qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
        break;
    default:
    case VIA_REG_ANH:
@@ -426,9 +461,11 @@ static void mos6522_reset(DeviceState *dev)
    s->timers[0].frequency = s->frequency;
    s->timers[0].latch = 0xffff;
    set_counter(s, &s->timers[0], 0xffff);
    timer_del(s->timers[0].timer);

    s->timers[1].frequency = s->frequency;
    s->timers[1].latch = 0xffff;
    timer_del(s->timers[1].timer);
}

static void mos6522_init(Object *obj)
Loading