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

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-3.0-20180703' into staging



ppc patch queue 2018-07-03

Here's a last minue pull request before today's soft freeze.  Ideally
I would have sent this earlier, but I was waiting for a couple of
extra fixes I knew were close.  And the freeze crept up on me, like
always.

Most of the changes here are bugfixes in any case.  There are some
cleanups as well, which have been in my staging tree for a little
while.  There are a couple of truly new features (some extensions to
the sam460ex platform), but these are low risk, since they only affect
a new and not really stabilized machine type anyway.

Higlights are:
  * Mac platform improvements from Mark Cave-Ayland
  * Sam460ex improvements from BALATON Zoltan et al.
  * XICS interrupt handler cleanups from Cédric Le Goater
  * TCG improvements for atomic loads and stores from Richard
    Henderson
  * Assorted other bugfixes

# gpg: Signature made Tue 03 Jul 2018 06:55:22 BST
# gpg:                using RSA key 6C38CACA20D9B392
# 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-3.0-20180703: (35 commits)
  ppc: Include vga cirrus card into the compiling process
  target/ppc: Relax reserved bitmask of indexed store instructions
  target/ppc: set is_jmp on ppc_tr_breakpoint_check
  spapr: compute default value of "hpt-max-page-size" later
  target/ppc/kvm: don't pass cpu to kvm_get_smmu_info()
  target/ppc/kvm: get rid of kvm_get_fallback_smmu_info()
  ppc440_uc: Basic emulation of PPC440 DMA controller
  sam460ex: Add RTC device
  hw/timer: Add basic M41T80 emulation
  ppc4xx_i2c: Rewrite to model hardware more closely
  hw/ppc: Give sam46ex its own config option
  fpu_helper.c: fix setting FPSCR[FI] bit
  target/ppc: Implement the rest of gen_st_atomic
  target/ppc: Implement the rest of gen_ld_atomic
  target/ppc: Use atomic min/max helpers
  target/ppc: Use MO_ALIGN for EXIWX and ECOWX
  target/ppc: Split out gen_st_atomic
  target/ppc: Split out gen_ld_atomic
  target/ppc: Split out gen_load_locked
  target/ppc: Tidy gen_conditional_store
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>

# Conflicts:
#	hw/ppc/spapr.c
parents a395717c 29f9cef3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -851,6 +851,7 @@ M: BALATON Zoltan <balaton@eik.bme.hu>
L: qemu-ppc@nongnu.org
S: Maintained
F: hw/ide/sii3112.c
F: hw/timer/m41t80.c

SH4 Machines
------------
+3 −0
Original line number Diff line number Diff line
@@ -22,11 +22,14 @@ CONFIG_OPENPIC_KVM=$(call land,$(CONFIG_E500),$(CONFIG_KVM))
CONFIG_PLATFORM_BUS=y
CONFIG_ETSEC=y
# For Sam460ex
CONFIG_SAM460EX=y
CONFIG_USB_EHCI_SYSBUS=y
CONFIG_SM501=y
CONFIG_IDE_SII3112=y
CONFIG_I2C=y
CONFIG_BITBANG_I2C=y
CONFIG_M41T80=y
CONFIG_VGA_CIRRUS=y

# For Macs
CONFIG_MAC=y
+157 −142
Original line number Diff line number Diff line
@@ -34,16 +34,50 @@

#define PPC4xx_I2C_MEM_SIZE 18

enum {
    IIC_MDBUF = 0,
    /* IIC_SDBUF = 2, */
    IIC_LMADR = 4,
    IIC_HMADR,
    IIC_CNTL,
    IIC_MDCNTL,
    IIC_STS,
    IIC_EXTSTS,
    IIC_LSADR,
    IIC_HSADR,
    IIC_CLKDIV,
    IIC_INTRMSK,
    IIC_XFRCNT,
    IIC_XTCNTLSS,
    IIC_DIRECTCNTL
    /* IIC_INTR */
};

#define IIC_CNTL_PT         (1 << 0)
#define IIC_CNTL_READ       (1 << 1)
#define IIC_CNTL_CHT        (1 << 2)
#define IIC_CNTL_RPST       (1 << 3)
#define IIC_CNTL_AMD        (1 << 6)
#define IIC_CNTL_HMT        (1 << 7)

#define IIC_MDCNTL_EINT     (1 << 2)
#define IIC_MDCNTL_ESM      (1 << 3)
#define IIC_MDCNTL_FMDB     (1 << 6)

#define IIC_STS_PT          (1 << 0)
#define IIC_STS_IRQA        (1 << 1)
#define IIC_STS_ERR         (1 << 2)
#define IIC_STS_MDBF        (1 << 4)
#define IIC_STS_MDBS        (1 << 5)

#define IIC_EXTSTS_XFRA     (1 << 0)
#define IIC_EXTSTS_BCS_FREE (4 << 4)
#define IIC_EXTSTS_BCS_BUSY (5 << 4)

#define IIC_INTRMSK_EIMTC   (1 << 0)
#define IIC_INTRMSK_EITA    (1 << 1)
#define IIC_INTRMSK_EIIC    (1 << 2)
#define IIC_INTRMSK_EIHE    (1 << 3)

#define IIC_XTCNTLSS_SRST   (1 << 0)

@@ -56,130 +90,83 @@ static void ppc4xx_i2c_reset(DeviceState *s)
{
    PPC4xxI2CState *i2c = PPC4xx_I2C(s);

    /* FIXME: Should also reset bus?
     *if (s->address != ADDR_RESET) {
     *    i2c_end_transfer(s->bus);
     *}
     */

    i2c->mdata = 0;
    i2c->lmadr = 0;
    i2c->hmadr = 0;
    i2c->mdidx = -1;
    memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata));
    /* [hl][ms]addr are not affected by reset */
    i2c->cntl = 0;
    i2c->mdcntl = 0;
    i2c->sts = 0;
    i2c->extsts = 0x8f;
    i2c->lsadr = 0;
    i2c->hsadr = 0;
    i2c->extsts = IIC_EXTSTS_BCS_FREE;
    i2c->clkdiv = 0;
    i2c->intrmsk = 0;
    i2c->xfrcnt = 0;
    i2c->xtcntlss = 0;
    i2c->directcntl = 0xf;
}

static inline bool ppc4xx_i2c_is_master(PPC4xxI2CState *i2c)
{
    return true;
    i2c->directcntl = 0xf; /* all non-reserved bits set */
}

static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
{
    PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
    uint64_t ret;
    int i;

    switch (addr) {
    case 0:
        ret = i2c->mdata;
        if (ppc4xx_i2c_is_master(i2c)) {
    case IIC_MDBUF:
        if (i2c->mdidx < 0) {
            ret = 0xff;

            if (!(i2c->sts & IIC_STS_MDBS)) {
                qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read "
                              "without starting transfer\n",
                              TYPE_PPC4xx_I2C, __func__);
            } else {
                int pending = (i2c->cntl >> 4) & 3;

                /* get the next byte */
                int byte = i2c_recv(i2c->bus);

                if (byte < 0) {
                    qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed "
                                  "for device 0x%02x\n", TYPE_PPC4xx_I2C,
                                  __func__, i2c->lmadr);
                    ret = 0xff;
                } else {
                    ret = byte;
                    /* Raise interrupt if enabled */
                    /*ppc4xx_i2c_raise_interrupt(i2c)*/;
            break;
        }

                if (!pending) {
        ret = i2c->mdata[0];
        if (i2c->mdidx == 3) {
            i2c->sts &= ~IIC_STS_MDBF;
        } else if (i2c->mdidx == 0) {
            i2c->sts &= ~IIC_STS_MDBS;
                    /*i2c_end_transfer(i2c->bus);*/
                /*} else if (i2c->cntl & (IIC_CNTL_RPST | IIC_CNTL_CHT)) {*/
                } else if (pending) {
                    /* current smbus implementation doesn't like
                       multibyte xfer repeated start */
                    i2c_end_transfer(i2c->bus);
                    if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
                        /* if non zero is returned, the adress is not valid */
                        i2c->sts &= ~IIC_STS_PT;
                        i2c->sts |= IIC_STS_ERR;
                        i2c->extsts |= IIC_EXTSTS_XFRA;
                    } else {
                        /*i2c->sts |= IIC_STS_PT;*/
                        i2c->sts |= IIC_STS_MDBS;
                        i2c->sts &= ~IIC_STS_ERR;
                        i2c->extsts = 0;
        }
        for (i = 0; i < i2c->mdidx; i++) {
            i2c->mdata[i] = i2c->mdata[i + 1];
        }
                pending--;
                i2c->cntl = (i2c->cntl & 0xcf) | (pending << 4);
            }
        } else {
            qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n",
                          TYPE_PPC4xx_I2C, __func__);
        if (i2c->mdidx >= 0) {
            i2c->mdidx--;
        }
        break;
    case 4:
    case IIC_LMADR:
        ret = i2c->lmadr;
        break;
    case 5:
    case IIC_HMADR:
        ret = i2c->hmadr;
        break;
    case 6:
    case IIC_CNTL:
        ret = i2c->cntl;
        break;
    case 7:
    case IIC_MDCNTL:
        ret = i2c->mdcntl;
        break;
    case 8:
    case IIC_STS:
        ret = i2c->sts;
        break;
    case 9:
        ret = i2c->extsts;
    case IIC_EXTSTS:
        ret = i2c_bus_busy(i2c->bus) ?
              IIC_EXTSTS_BCS_BUSY : IIC_EXTSTS_BCS_FREE;
        break;
    case 10:
    case IIC_LSADR:
        ret = i2c->lsadr;
        break;
    case 11:
    case IIC_HSADR:
        ret = i2c->hsadr;
        break;
    case 12:
    case IIC_CLKDIV:
        ret = i2c->clkdiv;
        break;
    case 13:
    case IIC_INTRMSK:
        ret = i2c->intrmsk;
        break;
    case 14:
    case IIC_XFRCNT:
        ret = i2c->xfrcnt;
        break;
    case 15:
    case IIC_XTCNTLSS:
        ret = i2c->xtcntlss;
        break;
    case 16:
    case IIC_DIRECTCNTL:
        ret = i2c->directcntl;
        break;
    default:
@@ -202,99 +189,127 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
    PPC4xxI2CState *i2c = opaque;

    switch (addr) {
    case 0:
        i2c->mdata = value;
    case IIC_MDBUF:
        if (i2c->mdidx >= 3) {
            break;
        }
        i2c->mdata[++i2c->mdidx] = value;
        if (i2c->mdidx == 3) {
            i2c->sts |= IIC_STS_MDBF;
        } else if (i2c->mdidx == 0) {
            i2c->sts |= IIC_STS_MDBS;
        }
        break;
    case IIC_LMADR:
        i2c->lmadr = value;
        break;
    case IIC_HMADR:
        i2c->hmadr = value;
        break;
    case IIC_CNTL:
        i2c->cntl = value & ~IIC_CNTL_PT;
        if (value & IIC_CNTL_AMD) {
            qemu_log_mask(LOG_UNIMP, "%s: only 7 bit addresses supported\n",
                          __func__);
        }
        if (value & IIC_CNTL_HMT && i2c_bus_busy(i2c->bus)) {
            i2c_end_transfer(i2c->bus);
            if (i2c->mdcntl & IIC_MDCNTL_EINT &&
                i2c->intrmsk & IIC_INTRMSK_EIHE) {
                i2c->sts |= IIC_STS_IRQA;
                qemu_irq_raise(i2c->irq);
            }
        } else if (value & IIC_CNTL_PT) {
            int recv = (value & IIC_CNTL_READ) >> 1;
            int tct = value >> 4 & 3;
            int i;

            if (recv && (i2c->lmadr >> 1) >= 0x50 && (i2c->lmadr >> 1) < 0x58) {
                /* smbus emulation does not like multi byte reads w/o restart */
                value |= IIC_CNTL_RPST;
            }

            for (i = 0; i <= tct; i++) {
                if (!i2c_bus_busy(i2c->bus)) {
            /* assume we start a write transfer */
            if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 0)) {
                /* if non zero is returned, the adress is not valid */
                i2c->sts &= ~IIC_STS_PT;
                    i2c->extsts = IIC_EXTSTS_BCS_FREE;
                    if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, recv)) {
                        i2c->sts |= IIC_STS_ERR;
                        i2c->extsts |= IIC_EXTSTS_XFRA;
                        break;
                    } else {
                i2c->sts |= IIC_STS_PT;
                        i2c->sts &= ~IIC_STS_ERR;
                i2c->extsts = 0;
                    }
                }
        if (i2c_bus_busy(i2c->bus)) {
            if (i2c_send(i2c->bus, i2c->mdata)) {
                /* if the target return non zero then end the transfer */
                i2c->sts &= ~IIC_STS_PT;
                if (!(i2c->sts & IIC_STS_ERR) &&
                    i2c_send_recv(i2c->bus, &i2c->mdata[i], !recv)) {
                    i2c->sts |= IIC_STS_ERR;
                    i2c->extsts |= IIC_EXTSTS_XFRA;
                i2c_end_transfer(i2c->bus);
            }
        }
                    break;
    case 4:
        i2c->lmadr = value;
        if (i2c_bus_busy(i2c->bus)) {
            i2c_end_transfer(i2c->bus);
                }
        break;
    case 5:
        i2c->hmadr = value;
        break;
    case 6:
        i2c->cntl = value;
        if (i2c->cntl & IIC_CNTL_PT) {
            if (i2c->cntl & IIC_CNTL_READ) {
                if (i2c_bus_busy(i2c->bus)) {
                    /* end previous transfer */
                    i2c->sts &= ~IIC_STS_PT;
                if (value & IIC_CNTL_RPST || !(value & IIC_CNTL_CHT)) {
                    i2c_end_transfer(i2c->bus);
                }
                if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) {
                    /* if non zero is returned, the adress is not valid */
                    i2c->sts &= ~IIC_STS_PT;
                    i2c->sts |= IIC_STS_ERR;
                    i2c->extsts |= IIC_EXTSTS_XFRA;
                } else {
                    /*i2c->sts |= IIC_STS_PT;*/
            }
            i2c->xfrcnt = i;
            i2c->mdidx = i - 1;
            if (recv && i2c->mdidx >= 0) {
                i2c->sts |= IIC_STS_MDBS;
                    i2c->sts &= ~IIC_STS_ERR;
                    i2c->extsts = 0;
            }
            } else {
                /* we actually already did the write transfer... */
                i2c->sts &= ~IIC_STS_PT;
            if (recv && i2c->mdidx == 3) {
                i2c->sts |= IIC_STS_MDBF;
            }
            if (i && i2c->mdcntl & IIC_MDCNTL_EINT &&
                i2c->intrmsk & IIC_INTRMSK_EIMTC) {
                i2c->sts |= IIC_STS_IRQA;
                qemu_irq_raise(i2c->irq);
            }
        }
        break;
    case 7:
        i2c->mdcntl = value & 0xdf;
    case IIC_MDCNTL:
        i2c->mdcntl = value & 0x3d;
        if (value & IIC_MDCNTL_ESM) {
            qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n",
                          __func__);
        }
        if (value & IIC_MDCNTL_FMDB) {
            i2c->mdidx = -1;
            memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata));
            i2c->sts &= ~(IIC_STS_MDBF | IIC_STS_MDBS);
        }
        break;
    case 8:
        i2c->sts &= ~(value & 0xa);
    case IIC_STS:
        i2c->sts &= ~(value & 0x0a);
        if (value & IIC_STS_IRQA && i2c->mdcntl & IIC_MDCNTL_EINT) {
            qemu_irq_lower(i2c->irq);
        }
        break;
    case 9:
    case IIC_EXTSTS:
        i2c->extsts &= ~(value & 0x8f);
        break;
    case 10:
    case IIC_LSADR:
        i2c->lsadr = value;
        break;
    case 11:
    case IIC_HSADR:
        i2c->hsadr = value;
        break;
    case 12:
    case IIC_CLKDIV:
        i2c->clkdiv = value;
        break;
    case 13:
    case IIC_INTRMSK:
        i2c->intrmsk = value;
        break;
    case 14:
    case IIC_XFRCNT:
        i2c->xfrcnt = value & 0x77;
        break;
    case 15:
    case IIC_XTCNTLSS:
        i2c->xtcntlss &= ~(value & 0xf0);
        if (value & IIC_XTCNTLSS_SRST) {
            /* Is it actually a full reset? U-Boot sets some regs before */
            ppc4xx_i2c_reset(DEVICE(i2c));
            break;
        }
        i2c->xtcntlss = value;
        break;
    case 16:
    case IIC_DIRECTCNTL:
        i2c->directcntl = value & (IIC_DIRECTCNTL_SDAC & IIC_DIRECTCNTL_SCLC);
        i2c->directcntl |= (value & IIC_DIRECTCNTL_SCLC ? 1 : 0);
        bitbang_i2c_set(i2c->bitbang, BITBANG_I2C_SCL,
+93 −81
Original line number Diff line number Diff line
@@ -294,7 +294,6 @@ static const VMStateDescription vmstate_icp_server = {
static void icp_reset(void *dev)
{
    ICPState *icp = ICP(dev);
    ICPStateClass *icpc = ICP_GET_CLASS(icp);

    icp->xirr = 0;
    icp->pending_priority = 0xff;
@@ -302,16 +301,11 @@ static void icp_reset(void *dev)

    /* Make all outputs are deasserted */
    qemu_set_irq(icp->output, 0);

    if (icpc->reset) {
        icpc->reset(icp);
    }
}

static void icp_realize(DeviceState *dev, Error **errp)
{
    ICPState *icp = ICP(dev);
    ICPStateClass *icpc = ICP_GET_CLASS(dev);
    PowerPCCPU *cpu;
    CPUPPCState *env;
    Object *obj;
@@ -351,10 +345,6 @@ static void icp_realize(DeviceState *dev, Error **errp)
        return;
    }

    if (icpc->realize) {
        icpc->realize(icp, errp);
    }

    qemu_register_reset(icp_reset, dev);
    vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp);
}
@@ -547,9 +537,61 @@ static void ics_simple_eoi(ICSState *ics, uint32_t nr)
    }
}

static void ics_simple_reset(void *dev)
static void ics_simple_reset(DeviceState *dev)
{
    ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);

    icsc->parent_reset(dev);
}

static void ics_simple_reset_handler(void *dev)
{
    ics_simple_reset(dev);
}

static void ics_simple_realize(DeviceState *dev, Error **errp)
{
    ICSState *ics = ICS_SIMPLE(dev);
    ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics);
    Error *local_err = NULL;

    icsc->parent_realize(dev, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);

    qemu_register_reset(ics_simple_reset_handler, ics);
}

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

    device_class_set_parent_realize(dc, ics_simple_realize,
                                    &isc->parent_realize);
    device_class_set_parent_reset(dc, ics_simple_reset,
                                  &isc->parent_reset);

    isc->reject = ics_simple_reject;
    isc->resend = ics_simple_resend;
    isc->eoi = ics_simple_eoi;
}

static const TypeInfo ics_simple_info = {
    .name = TYPE_ICS_SIMPLE,
    .parent = TYPE_ICS_BASE,
    .instance_size = sizeof(ICSState),
    .class_init = ics_simple_class_init,
    .class_size = sizeof(ICSStateClass),
};

static void ics_base_reset(DeviceState *dev)
{
    ICSState *ics = ICS_BASE(dev);
    int i;
    uint8_t flags[ics->nr_irqs];

@@ -566,7 +608,35 @@ static void ics_simple_reset(void *dev)
    }
}

static int ics_simple_dispatch_pre_save(void *opaque)
static void ics_base_realize(DeviceState *dev, Error **errp)
{
    ICSState *ics = ICS_BASE(dev);
    Object *obj;
    Error *err = NULL;

    obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err);
    if (!obj) {
        error_propagate(errp, err);
        error_prepend(errp, "required link '" ICS_PROP_XICS "' not found: ");
        return;
    }
    ics->xics = XICS_FABRIC(obj);

    if (!ics->nr_irqs) {
        error_setg(errp, "Number of interrupts needs to be greater 0");
        return;
    }
    ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
}

static void ics_base_instance_init(Object *obj)
{
    ICSState *ics = ICS_BASE(obj);

    ics->offset = XICS_IRQ_BASE;
}

static int ics_base_dispatch_pre_save(void *opaque)
{
    ICSState *ics = opaque;
    ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
@@ -578,7 +648,7 @@ static int ics_simple_dispatch_pre_save(void *opaque)
    return 0;
}

static int ics_simple_dispatch_post_load(void *opaque, int version_id)
static int ics_base_dispatch_post_load(void *opaque, int version_id)
{
    ICSState *ics = opaque;
    ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
@@ -590,7 +660,7 @@ static int ics_simple_dispatch_post_load(void *opaque, int version_id)
    return 0;
}

static const VMStateDescription vmstate_ics_simple_irq = {
static const VMStateDescription vmstate_ics_base_irq = {
    .name = "ics/irq",
    .version_id = 2,
    .minimum_version_id = 1,
@@ -604,95 +674,36 @@ static const VMStateDescription vmstate_ics_simple_irq = {
    },
};

static const VMStateDescription vmstate_ics_simple = {
static const VMStateDescription vmstate_ics_base = {
    .name = "ics",
    .version_id = 1,
    .minimum_version_id = 1,
    .pre_save = ics_simple_dispatch_pre_save,
    .post_load = ics_simple_dispatch_post_load,
    .pre_save = ics_base_dispatch_pre_save,
    .post_load = ics_base_dispatch_post_load,
    .fields = (VMStateField[]) {
        /* Sanity check */
        VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL),

        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
                                             vmstate_ics_simple_irq,
                                             vmstate_ics_base_irq,
                                             ICSIRQState),
        VMSTATE_END_OF_LIST()
    },
};

static void ics_simple_initfn(Object *obj)
{
    ICSState *ics = ICS_SIMPLE(obj);

    ics->offset = XICS_IRQ_BASE;
}

static void ics_simple_realize(ICSState *ics, Error **errp)
{
    if (!ics->nr_irqs) {
        error_setg(errp, "Number of interrupts needs to be greater 0");
        return;
    }
    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, ics);
}

static Property ics_simple_properties[] = {
static Property ics_base_properties[] = {
    DEFINE_PROP_UINT32("nr-irqs", ICSState, nr_irqs, 0),
    DEFINE_PROP_END_OF_LIST(),
};

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

    isc->realize = ics_simple_realize;
    dc->props = ics_simple_properties;
    dc->vmsd = &vmstate_ics_simple;
    isc->reject = ics_simple_reject;
    isc->resend = ics_simple_resend;
    isc->eoi = ics_simple_eoi;
}

static const TypeInfo ics_simple_info = {
    .name = TYPE_ICS_SIMPLE,
    .parent = TYPE_ICS_BASE,
    .instance_size = sizeof(ICSState),
    .class_init = ics_simple_class_init,
    .class_size = sizeof(ICSStateClass),
    .instance_init = ics_simple_initfn,
};

static void ics_base_realize(DeviceState *dev, Error **errp)
{
    ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);
    ICSState *ics = ICS_BASE(dev);
    Object *obj;
    Error *err = NULL;

    obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err);
    if (!obj) {
        error_propagate(errp, err);
        error_prepend(errp, "required link '" ICS_PROP_XICS "' not found: ");
        return;
    }
    ics->xics = XICS_FABRIC(obj);


    if (icsc->realize) {
        icsc->realize(ics, errp);
    }
}

static void ics_base_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->realize = ics_base_realize;
    dc->props = ics_base_properties;
    dc->reset = ics_base_reset;
    dc->vmsd = &vmstate_ics_base;
}

static const TypeInfo ics_base_info = {
@@ -700,6 +711,7 @@ static const TypeInfo ics_base_info = {
    .parent = TYPE_DEVICE,
    .abstract = true,
    .instance_size = sizeof(ICSState),
    .instance_init = ics_base_instance_init,
    .class_init = ics_base_class_init,
    .class_size = sizeof(ICSStateClass),
};
+51 −29
Original line number Diff line number Diff line
@@ -114,22 +114,38 @@ static int icp_set_kvm_state(ICPState *icp, int version_id)
    return 0;
}

static void icp_kvm_reset(ICPState *icp)
static void icp_kvm_reset(DeviceState *dev)
{
    icp_set_kvm_state(icp, 1);
    ICPStateClass *icpc = ICP_GET_CLASS(dev);

    icpc->parent_reset(dev);

    icp_set_kvm_state(ICP(dev), 1);
}

static void icp_kvm_realize(ICPState *icp, Error **errp)
static void icp_kvm_realize(DeviceState *dev, Error **errp)
{
    CPUState *cs = icp->cs;
    ICPState *icp = ICP(dev);
    ICPStateClass *icpc = ICP_GET_CLASS(icp);
    Error *local_err = NULL;
    CPUState *cs;
    KVMEnabledICP *enabled_icp;
    unsigned long vcpu_id = kvm_arch_vcpu_id(cs);
    unsigned long vcpu_id;
    int ret;

    if (kernel_xics_fd == -1) {
        abort();
    }

    icpc->parent_realize(dev, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    cs = icp->cs;
    vcpu_id = kvm_arch_vcpu_id(cs);

    /*
     * If we are reusing a parked vCPU fd corresponding to the CPU
     * which was hot-removed earlier we don't have to renable
@@ -154,12 +170,16 @@ static void icp_kvm_realize(ICPState *icp, Error **errp)

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

    device_class_set_parent_realize(dc, icp_kvm_realize,
                                    &icpc->parent_realize);
    device_class_set_parent_reset(dc, icp_kvm_reset,
                                  &icpc->parent_reset);

    icpc->pre_save = icp_get_kvm_state;
    icpc->post_load = icp_set_kvm_state;
    icpc->realize = icp_kvm_realize;
    icpc->reset = icp_kvm_reset;
    icpc->synchronize_state = icp_synchronize_state;
}

@@ -304,44 +324,46 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val)
    }
}

static void ics_kvm_reset(void *dev)
static void ics_kvm_reset(DeviceState *dev)
{
    ICSState *ics = ICS_SIMPLE(dev);
    int i;
    uint8_t flags[ics->nr_irqs];
    ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);

    for (i = 0; i < ics->nr_irqs; i++) {
        flags[i] = ics->irqs[i].flags;
    }
    icsc->parent_reset(dev);

    memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);

    for (i = 0; i < ics->nr_irqs; i++) {
        ics->irqs[i].priority = 0xff;
        ics->irqs[i].saved_priority = 0xff;
        ics->irqs[i].flags = flags[i];
    ics_set_kvm_state(ICS_KVM(dev), 1);
}

    ics_set_kvm_state(ics, 1);
static void ics_kvm_reset_handler(void *dev)
{
    ics_kvm_reset(dev);
}

static void ics_kvm_realize(ICSState *ics, Error **errp)
static void ics_kvm_realize(DeviceState *dev, Error **errp)
{
    if (!ics->nr_irqs) {
        error_setg(errp, "Number of interrupts needs to be greater 0");
    ICSState *ics = ICS_KVM(dev);
    ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics);
    Error *local_err = NULL;

    icsc->parent_realize(dev, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    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, ics);
    qemu_register_reset(ics_kvm_reset_handler, ics);
}

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

    device_class_set_parent_realize(dc, ics_kvm_realize,
                                    &icsc->parent_realize);
    device_class_set_parent_reset(dc, ics_kvm_reset,
                                  &icsc->parent_reset);

    icsc->realize = ics_kvm_realize;
    icsc->pre_save = ics_get_kvm_state;
    icsc->post_load = ics_set_kvm_state;
    icsc->synchronize_state = ics_synchronize_state;
@@ -349,7 +371,7 @@ static void ics_kvm_class_init(ObjectClass *klass, void *data)

static const TypeInfo ics_kvm_info = {
    .name = TYPE_ICS_KVM,
    .parent = TYPE_ICS_SIMPLE,
    .parent = TYPE_ICS_BASE,
    .instance_size = sizeof(ICSState),
    .class_init = ics_kvm_class_init,
};
Loading