Commit 7bf59dfe authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.8-20161017' into staging



ppc patch queue 2016-10-17

Highlights:
    * Significant rework of how PCI IO windows are placed for the
      pseries machine type
    * A number of extra tests added for ppc
    * Other tests clean up / fixed
    * Some cleanups to the XICS interrupt controller in preparation
      for the 'powernv' machine type

A number of the test changes aren't strictly in ppc related code, but
are included via my tree because they're primarily focused on
improving test coverage for ppc.

# gpg: Signature made Mon 17 Oct 2016 03:42:41 BST
# 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.8-20161017:
  spapr: Improved placement of PCI host bridges in guest memory map
  spapr_pci: Add a 64-bit MMIO window
  spapr: Adjust placement of PCI host bridge to allow > 1TiB RAM
  spapr_pci: Delegate placement of PCI host bridges to machine type
  libqos: Limit spapr-pci to 32-bit MMIO for now
  libqos: Correct error in PCI hole sizing for spapr
  libqos: Isolate knowledge of spapr memory map to qpci_init_spapr()
  ppc/xics: Split ICS into ics-base and ics class
  ppc/xics: Make the ICSState a list
  spapr: fix inheritance chain for default machine options
  target-ppc: implement vexts[bh]2w and vexts[bhw]2d
  tests/boot-sector: Increase time-out to 90 seconds
  tests/boot-sector: Use mkstemp() to create a unique file name
  tests/boot-sector: Use minimum length for the Forth boot script
  qtest: ask endianness of the target in qtest_init()
  tests: minor cleanups in usb-hcd-uhci-test

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents ad728364 357d1e3b
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -50,16 +50,17 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx3
xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
xics_masked_pending(void) "set_irq_msi: masked pending"
xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
xics_ics_eoi(int nr) "ics_eoi: irq %#x"
xics_alloc(int src, int irq) "source#%d, irq %d"
xics_alloc_block(int src, int first, int num, bool lsi, int align) "source#%d, first irq %d, %d irqs, lsi=%d, alignnum %d"
xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
xics_ics_simple_reject(int nr, int srcno) "reject irq %#x [src %d]"
xics_ics_simple_eoi(int nr) "ics_eoi: irq %#x"
xics_alloc(int irq) "irq %d"
xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free"
xics_icp_post_load(uint32_t server_no, uint32_t xirr, uint64_t addr, uint8_t pend) "server_no %d, xirr %#x, xirr_owner 0x%" PRIx64 ", pending %d"

# hw/intc/s390_flic_kvm.c
flic_create_device(int err) "flic: create device failed %d"
+141 −90
Original line number Diff line number Diff line
@@ -96,13 +96,16 @@ void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
static void xics_common_reset(DeviceState *d)
{
    XICSState *xics = XICS_COMMON(d);
    ICSState *ics;
    int i;

    for (i = 0; i < xics->nr_servers; i++) {
        device_reset(DEVICE(&xics->ss[i]));
    }

    device_reset(DEVICE(xics->ics));
    QLIST_FOREACH(ics, &xics->ics, list) {
        device_reset(DEVICE(ics));
    }
}

static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
@@ -134,7 +137,6 @@ static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name,
    }

    assert(info->set_nr_irqs);
    assert(xics->ics);
    info->set_nr_irqs(xics, value, errp);
}

@@ -174,6 +176,9 @@ static void xics_prop_set_nr_servers(Object *obj, Visitor *v,

static void xics_common_initfn(Object *obj)
{
    XICSState *xics = XICS_COMMON(obj);

    QLIST_INIT(&xics->ics);
    object_property_add(obj, "nr_irqs", "int",
                        xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
                        NULL, NULL, NULL);
@@ -208,37 +213,62 @@ static const TypeInfo xics_common_info = {
#define XISR(ss)   (((ss)->xirr) & XISR_MASK)
#define CPPR(ss)   (((ss)->xirr) >> 24)

static void ics_reject(ICSState *ics, int nr);
static void ics_resend(ICSState *ics);
static void ics_eoi(ICSState *ics, int nr);
static void ics_reject(ICSState *ics, uint32_t nr)
{
    ICSStateClass *k = ICS_BASE_GET_CLASS(ics);

static void icp_check_ipi(XICSState *xics, int server)
    if (k->reject) {
        k->reject(ics, nr);
    }
}

static void ics_resend(ICSState *ics)
{
    ICPState *ss = xics->ss + server;
    ICSStateClass *k = ICS_BASE_GET_CLASS(ics);

    if (k->resend) {
        k->resend(ics);
    }
}

static void ics_eoi(ICSState *ics, int nr)
{
    ICSStateClass *k = ICS_BASE_GET_CLASS(ics);

    if (k->eoi) {
        k->eoi(ics, nr);
    }
}

static void icp_check_ipi(ICPState *ss)
{
    if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
        return;
    }

    trace_xics_icp_check_ipi(server, ss->mfrr);
    trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr);

    if (XISR(ss)) {
        ics_reject(xics->ics, XISR(ss));
    if (XISR(ss) && ss->xirr_owner) {
        ics_reject(ss->xirr_owner, XISR(ss));
    }

    ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
    ss->pending_priority = ss->mfrr;
    ss->xirr_owner = NULL;
    qemu_irq_raise(ss->output);
}

static void icp_resend(XICSState *xics, int server)
{
    ICPState *ss = xics->ss + server;
    ICSState *ics;

    if (ss->mfrr < CPPR(ss)) {
        icp_check_ipi(xics, server);
        icp_check_ipi(ss);
    }
    QLIST_FOREACH(ics, &xics->ics, list) {
        ics_resend(ics);
    }
    ics_resend(xics->ics);
}

void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
@@ -256,7 +286,10 @@ void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
            ss->xirr &= ~XISR_MASK; /* Clear XISR */
            ss->pending_priority = 0xff;
            qemu_irq_lower(ss->output);
            ics_reject(xics->ics, old_xisr);
            if (ss->xirr_owner) {
                ics_reject(ss->xirr_owner, old_xisr);
                ss->xirr_owner = NULL;
            }
        }
    } else {
        if (!XISR(ss)) {
@@ -271,7 +304,7 @@ void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)

    ss->mfrr = mfrr;
    if (mfrr < CPPR(ss)) {
        icp_check_ipi(xics, server);
        icp_check_ipi(ss);
    }
}

@@ -282,6 +315,7 @@ uint32_t icp_accept(ICPState *ss)
    qemu_irq_lower(ss->output);
    ss->xirr = ss->pending_priority << 24;
    ss->pending_priority = 0xff;
    ss->xirr_owner = NULL;

    trace_xics_icp_accept(xirr, ss->xirr);

@@ -299,30 +333,40 @@ uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
void icp_eoi(XICSState *xics, int server, uint32_t xirr)
{
    ICPState *ss = xics->ss + server;
    ICSState *ics;
    uint32_t irq;

    /* Send EOI -> ICS */
    ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
    trace_xics_icp_eoi(server, xirr, ss->xirr);
    ics_eoi(xics->ics, xirr & XISR_MASK);
    irq = xirr & XISR_MASK;
    QLIST_FOREACH(ics, &xics->ics, list) {
        if (ics_valid_irq(ics, irq)) {
            ics_eoi(ics, irq);
        }
    }
    if (!XISR(ss)) {
        icp_resend(xics, server);
    }
}

static void icp_irq(XICSState *xics, int server, int nr, uint8_t priority)
static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
{
    XICSState *xics = ics->xics;
    ICPState *ss = xics->ss + server;

    trace_xics_icp_irq(server, nr, priority);

    if ((priority >= CPPR(ss))
        || (XISR(ss) && (ss->pending_priority <= priority))) {
        ics_reject(xics->ics, nr);
        ics_reject(ics, nr);
    } else {
        if (XISR(ss)) {
            ics_reject(xics->ics, XISR(ss));
        if (XISR(ss) && ss->xirr_owner) {
            ics_reject(ss->xirr_owner, XISR(ss));
            ss->xirr_owner = NULL;
        }
        ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
        ss->xirr_owner = ics;
        ss->pending_priority = priority;
        trace_xics_icp_raise(ss->xirr, ss->pending_priority);
        qemu_irq_raise(ss->output);
@@ -397,7 +441,7 @@ static const TypeInfo icp_info = {
/*
 * ICS: Source layer
 */
static void resend_msi(ICSState *ics, int srcno)
static void ics_simple_resend_msi(ICSState *ics, int srcno)
{
    ICSIRQState *irq = ics->irqs + srcno;

@@ -405,13 +449,12 @@ static void resend_msi(ICSState *ics, int srcno)
    if (irq->status & XICS_STATUS_REJECTED) {
        irq->status &= ~XICS_STATUS_REJECTED;
        if (irq->priority != 0xff) {
            icp_irq(ics->xics, irq->server, srcno + ics->offset,
                    irq->priority);
            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
        }
    }
}

static void resend_lsi(ICSState *ics, int srcno)
static void ics_simple_resend_lsi(ICSState *ics, int srcno)
{
    ICSIRQState *irq = ics->irqs + srcno;

@@ -419,51 +462,51 @@ static void resend_lsi(ICSState *ics, int srcno)
        && (irq->status & XICS_STATUS_ASSERTED)
        && !(irq->status & XICS_STATUS_SENT)) {
        irq->status |= XICS_STATUS_SENT;
        icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
        icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
    }
}

static void set_irq_msi(ICSState *ics, int srcno, int val)
static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
{
    ICSIRQState *irq = ics->irqs + srcno;

    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
    trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset);

    if (val) {
        if (irq->priority == 0xff) {
            irq->status |= XICS_STATUS_MASKED_PENDING;
            trace_xics_masked_pending();
        } else  {
            icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
            icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
        }
    }
}

static void set_irq_lsi(ICSState *ics, int srcno, int val)
static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
{
    ICSIRQState *irq = ics->irqs + srcno;

    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
    trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset);
    if (val) {
        irq->status |= XICS_STATUS_ASSERTED;
    } else {
        irq->status &= ~XICS_STATUS_ASSERTED;
    }
    resend_lsi(ics, srcno);
    ics_simple_resend_lsi(ics, srcno);
}

static void ics_set_irq(void *opaque, int srcno, int val)
static void ics_simple_set_irq(void *opaque, int srcno, int val)
{
    ICSState *ics = (ICSState *)opaque;

    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
        set_irq_lsi(ics, srcno, val);
        ics_simple_set_irq_lsi(ics, srcno, val);
    } else {
        set_irq_msi(ics, srcno, val);
        ics_simple_set_irq_msi(ics, srcno, val);
    }
}

static void write_xive_msi(ICSState *ics, int srcno)
static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
{
    ICSIRQState *irq = ics->irqs + srcno;

@@ -473,38 +516,38 @@ static void write_xive_msi(ICSState *ics, int srcno)
    }

    irq->status &= ~XICS_STATUS_MASKED_PENDING;
    icp_irq(ics->xics, irq->server, srcno + ics->offset, irq->priority);
    icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
}

static void write_xive_lsi(ICSState *ics, int srcno)
static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
{
    resend_lsi(ics, srcno);
    ics_simple_resend_lsi(ics, srcno);
}

void ics_write_xive(ICSState *ics, int nr, int server,
void ics_simple_write_xive(ICSState *ics, int srcno, int server,
                           uint8_t priority, uint8_t saved_priority)
{
    int srcno = nr - ics->offset;
    ICSIRQState *irq = ics->irqs + srcno;

    irq->server = server;
    irq->priority = priority;
    irq->saved_priority = saved_priority;

    trace_xics_ics_write_xive(nr, srcno, server, priority);
    trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server,
                                     priority);

    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
        write_xive_lsi(ics, srcno);
        ics_simple_write_xive_lsi(ics, srcno);
    } else {
        write_xive_msi(ics, srcno);
        ics_simple_write_xive_msi(ics, srcno);
    }
}

static void ics_reject(ICSState *ics, int nr)
static void ics_simple_reject(ICSState *ics, uint32_t nr)
{
    ICSIRQState *irq = ics->irqs + nr - ics->offset;

    trace_xics_ics_reject(nr, nr - ics->offset);
    trace_xics_ics_simple_reject(nr, nr - ics->offset);
    if (irq->flags & XICS_FLAGS_IRQ_MSI) {
        irq->status |= XICS_STATUS_REJECTED;
    } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
@@ -512,35 +555,35 @@ static void ics_reject(ICSState *ics, int nr)
    }
}

static void ics_resend(ICSState *ics)
static void ics_simple_resend(ICSState *ics)
{
    int i;

    for (i = 0; i < ics->nr_irqs; i++) {
        /* FIXME: filter by server#? */
        if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
            resend_lsi(ics, i);
            ics_simple_resend_lsi(ics, i);
        } else {
            resend_msi(ics, i);
            ics_simple_resend_msi(ics, i);
        }
    }
}

static void ics_eoi(ICSState *ics, int nr)
static void ics_simple_eoi(ICSState *ics, uint32_t nr)
{
    int srcno = nr - ics->offset;
    ICSIRQState *irq = ics->irqs + srcno;

    trace_xics_ics_eoi(nr);
    trace_xics_ics_simple_eoi(nr);

    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
        irq->status &= ~XICS_STATUS_SENT;
    }
}

static void ics_reset(DeviceState *dev)
static void ics_simple_reset(DeviceState *dev)
{
    ICSState *ics = ICS(dev);
    ICSState *ics = ICS_SIMPLE(dev);
    int i;
    uint8_t flags[ics->nr_irqs];

@@ -557,7 +600,7 @@ static void ics_reset(DeviceState *dev)
    }
}

static int ics_post_load(ICSState *ics, int version_id)
static int ics_simple_post_load(ICSState *ics, int version_id)
{
    int i;

@@ -568,20 +611,20 @@ static int ics_post_load(ICSState *ics, int version_id)
    return 0;
}

static void ics_dispatch_pre_save(void *opaque)
static void ics_simple_dispatch_pre_save(void *opaque)
{
    ICSState *ics = opaque;
    ICSStateClass *info = ICS_GET_CLASS(ics);
    ICSStateClass *info = ICS_BASE_GET_CLASS(ics);

    if (info->pre_save) {
        info->pre_save(ics);
    }
}

static int ics_dispatch_post_load(void *opaque, int version_id)
static int ics_simple_dispatch_post_load(void *opaque, int version_id)
{
    ICSState *ics = opaque;
    ICSStateClass *info = ICS_GET_CLASS(ics);
    ICSStateClass *info = ICS_BASE_GET_CLASS(ics);

    if (info->post_load) {
        return info->post_load(ics, version_id);
@@ -590,7 +633,7 @@ static int ics_dispatch_post_load(void *opaque, int version_id)
    return 0;
}

static const VMStateDescription vmstate_ics_irq = {
static const VMStateDescription vmstate_ics_simple_irq = {
    .name = "ics/irq",
    .version_id = 2,
    .minimum_version_id = 1,
@@ -604,86 +647,93 @@ static const VMStateDescription vmstate_ics_irq = {
    },
};

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

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

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

    ics->offset = XICS_IRQ_BASE;
}

static void ics_realize(DeviceState *dev, Error **errp)
static void ics_simple_realize(DeviceState *dev, Error **errp)
{
    ICSState *ics = ICS(dev);
    ICSState *ics = ICS_SIMPLE(dev);

    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_set_irq, ics, ics->nr_irqs);
    ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
}

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

    dc->realize = ics_realize;
    dc->vmsd = &vmstate_ics;
    dc->reset = ics_reset;
    isc->post_load = ics_post_load;
    dc->realize = ics_simple_realize;
    dc->vmsd = &vmstate_ics_simple;
    dc->reset = ics_simple_reset;
    isc->post_load = ics_simple_post_load;
    isc->reject = ics_simple_reject;
    isc->resend = ics_simple_resend;
    isc->eoi = ics_simple_eoi;
}

static const TypeInfo ics_info = {
    .name = TYPE_ICS,
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 const TypeInfo ics_base_info = {
    .name = TYPE_ICS_BASE,
    .parent = TYPE_DEVICE,
    .abstract = true,
    .instance_size = sizeof(ICSState),
    .class_init = ics_class_init,
    .class_size = sizeof(ICSStateClass),
    .instance_init = ics_initfn,
};

/*
 * Exported functions
 */
int xics_find_source(XICSState *xics, int irq)
ICSState *xics_find_source(XICSState *xics, int irq)
{
    int sources = 1;
    int src;
    ICSState *ics;

    /* FIXME: implement multiple sources */
    for (src = 0; src < sources; ++src) {
        ICSState *ics = &xics->ics[src];
    QLIST_FOREACH(ics, &xics->ics, list) {
        if (ics_valid_irq(ics, irq)) {
            return src;
            return ics;
        }
    }

    return -1;
    return NULL;
}

qemu_irq xics_get_qirq(XICSState *xics, int irq)
{
    int src = xics_find_source(xics, irq);
    ICSState *ics = xics_find_source(xics, irq);

    if (src >= 0) {
        ICSState *ics = &xics->ics[src];
    if (ics) {
        return ics->qirqs[irq - ics->offset];
    }

@@ -701,7 +751,8 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
static void xics_register_types(void)
{
    type_register_static(&xics_common_info);
    type_register_static(&ics_info);
    type_register_static(&ics_simple_info);
    type_register_static(&ics_base_info);
    type_register_static(&icp_info);
}

+24 −13
Original line number Diff line number Diff line
@@ -272,7 +272,7 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val)

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

@@ -293,7 +293,7 @@ static void ics_kvm_reset(DeviceState *dev)

static void ics_kvm_realize(DeviceState *dev, Error **errp)
{
    ICSState *ics = ICS(dev);
    ICSState *ics = ICS_SIMPLE(dev);

    if (!ics->nr_irqs) {
        error_setg(errp, "Number of interrupts needs to be greater 0");
@@ -306,7 +306,7 @@ static void ics_kvm_realize(DeviceState *dev, Error **errp)
static void ics_kvm_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    ICSStateClass *icsc = ICS_CLASS(klass);
    ICSStateClass *icsc = ICS_BASE_CLASS(klass);

    dc->realize = ics_kvm_realize;
    dc->reset = ics_kvm_reset;
@@ -315,8 +315,8 @@ static void ics_kvm_class_init(ObjectClass *klass, void *data)
}

static const TypeInfo ics_kvm_info = {
    .name = TYPE_KVM_ICS,
    .parent = TYPE_ICS,
    .name = TYPE_ICS_KVM,
    .parent = TYPE_ICS_SIMPLE,
    .instance_size = sizeof(ICSState),
    .class_init = ics_kvm_class_init,
};
@@ -361,7 +361,13 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
                                 Error **errp)
{
    xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
    ICSState *ics = QLIST_FIRST(&xics->ics);

    /* This needs to be deprecated ... */
    xics->nr_irqs = nr_irqs;
    if (ics) {
        ics->nr_irqs = nr_irqs;
    }
}

static void xics_kvm_set_nr_servers(XICSState *xics, uint32_t nr_servers,
@@ -394,6 +400,7 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
{
    KVMXICSState *xicskvm = XICS_SPAPR_KVM(dev);
    XICSState *xics = XICS_COMMON(dev);
    ICSState *ics;
    int i, rc;
    Error *error = NULL;
    struct kvm_create_device xics_create_device = {
@@ -445,11 +452,13 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)

    xicskvm->kernel_xics_fd = xics_create_device.fd;

    object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
    QLIST_FOREACH(ics, &xics->ics, list) {
        object_property_set_bool(OBJECT(ics), true, "realized", &error);
        if (error) {
            error_propagate(errp, error);
            goto fail;
        }
    }

    assert(xics->nr_servers);
    for (i = 0; i < xics->nr_servers; i++) {
@@ -477,10 +486,12 @@ fail:
static void xics_kvm_initfn(Object *obj)
{
    XICSState *xics = XICS_COMMON(obj);
    ICSState *ics;

    xics->ics = ICS(object_new(TYPE_KVM_ICS));
    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
    xics->ics->xics = xics;
    ics = ICS_SIMPLE(object_new(TYPE_ICS_KVM));
    object_property_add_child(obj, "ics", OBJECT(ics), NULL);
    ics->xics = xics;
    QLIST_INSERT_HEAD(&xics->ics, ics, list);
}

static void xics_kvm_class_init(ObjectClass *oc, void *data)
+73 −43

File changed.

Preview size limit exceeded, changes collapsed.

+116 −2
Original line number Diff line number Diff line
@@ -2370,6 +2370,56 @@ static HotpluggableCPUList *spapr_query_hotpluggable_cpus(MachineState *machine)
    return head;
}

static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index,
                                uint64_t *buid, hwaddr *pio,
                                hwaddr *mmio32, hwaddr *mmio64,
                                unsigned n_dma, uint32_t *liobns, Error **errp)
{
    /*
     * New-style PHB window placement.
     *
     * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window
     * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO
     * windows.
     *
     * Some guest kernels can't work with MMIO windows above 1<<46
     * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB
     *
     * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each
     * PHB stacked together.  (32TiB+2GiB)..(32TiB+64GiB) contains the
     * 2GiB 32-bit MMIO windows for each PHB.  Then 33..64TiB has the
     * 1TiB 64-bit MMIO windows for each PHB.
     */
    const uint64_t base_buid = 0x800000020000000ULL;
    const int max_phbs =
        (SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / SPAPR_PCI_MEM64_WIN_SIZE - 1;
    int i;

    /* Sanity check natural alignments */
    QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
    QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
    QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0);
    QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0);
    /* Sanity check bounds */
    QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_IO_WIN_SIZE) > SPAPR_PCI_MEM32_WIN_SIZE);
    QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_MEM32_WIN_SIZE) > SPAPR_PCI_MEM64_WIN_SIZE);

    if (index >= max_phbs) {
        error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
                   max_phbs - 1);
        return;
    }

    *buid = base_buid + index;
    for (i = 0; i < n_dma; ++i) {
        liobns[i] = SPAPR_PCI_LIOBN(index, i);
    }

    *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE;
    *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE;
    *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE;
}

static void spapr_machine_class_init(ObjectClass *oc, void *data)
{
    MachineClass *mc = MACHINE_CLASS(oc);
@@ -2406,6 +2456,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
    mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus;
    fwc->get_dev_path = spapr_get_fw_dev_path;
    nc->nmi_monitor_handler = spapr_nmi;
    smc->phb_placement = spapr_phb_placement;
}

static const TypeInfo spapr_machine_info = {
@@ -2472,9 +2523,69 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", true);
 */
#define SPAPR_COMPAT_2_7                            \
    HW_COMPAT_2_7                                   \
    {                                               \
        .driver   = TYPE_SPAPR_PCI_HOST_BRIDGE,     \
        .property = "mem_win_size",                 \
        .value    = stringify(SPAPR_PCI_2_7_MMIO_WIN_SIZE),\
    },                                              \
    {                                               \
        .driver   = TYPE_SPAPR_PCI_HOST_BRIDGE,     \
        .property = "mem64_win_size",               \
        .value    = "0",                            \
    },

static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
                              uint64_t *buid, hwaddr *pio,
                              hwaddr *mmio32, hwaddr *mmio64,
                              unsigned n_dma, uint32_t *liobns, Error **errp)
{
    /* Legacy PHB placement for pseries-2.7 and earlier machine types */
    const uint64_t base_buid = 0x800000020000000ULL;
    const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */
    const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */
    const hwaddr pio_offset = 0x80000000; /* 2 GiB */
    const uint32_t max_index = 255;
    const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */

    uint64_t ram_top = MACHINE(spapr)->ram_size;
    hwaddr phb0_base, phb_base;
    int i;

    /* Do we have hotpluggable memory? */
    if (MACHINE(spapr)->maxram_size > ram_top) {
        /* Can't just use maxram_size, because there may be an
         * alignment gap between normal and hotpluggable memory
         * regions */
        ram_top = spapr->hotplug_memory.base +
            memory_region_size(&spapr->hotplug_memory.mr);
    }

    phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment);

    if (index > max_index) {
        error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
                   max_index);
        return;
    }

    *buid = base_buid + index;
    for (i = 0; i < n_dma; ++i) {
        liobns[i] = SPAPR_PCI_LIOBN(index, i);
    }

    phb_base = phb0_base + index * phb_spacing;
    *pio = phb_base + pio_offset;
    *mmio32 = phb_base + mmio_offset;
    /*
     * We don't set the 64-bit MMIO window, relying on the PHB's
     * fallback behaviour of automatically splitting a large "32-bit"
     * window into contiguous 32-bit and 64-bit windows
     */
}

static void spapr_machine_2_7_instance_options(MachineState *machine)
{
    spapr_machine_2_8_instance_options(machine);
}

static void spapr_machine_2_7_class_options(MachineClass *mc)
@@ -2484,6 +2595,7 @@ static void spapr_machine_2_7_class_options(MachineClass *mc)
    spapr_machine_2_8_class_options(mc);
    smc->tcg_default_cpu = "POWER7";
    SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7);
    smc->phb_placement = phb_placement_2_7;
}

DEFINE_SPAPR_MACHINE(2_7, "2.7", false);
@@ -2501,6 +2613,7 @@ DEFINE_SPAPR_MACHINE(2_7, "2.7", false);

static void spapr_machine_2_6_instance_options(MachineState *machine)
{
    spapr_machine_2_7_instance_options(machine);
}

static void spapr_machine_2_6_class_options(MachineClass *mc)
@@ -2525,6 +2638,7 @@ DEFINE_SPAPR_MACHINE(2_6, "2.6", false);

static void spapr_machine_2_5_instance_options(MachineState *machine)
{
    spapr_machine_2_6_instance_options(machine);
}

static void spapr_machine_2_5_class_options(MachineClass *mc)
Loading