[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [qemu-xen master] Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.8-20161017' into staging
=== This changeset includes merge from high-traffic branch === Commits on that branch are not reported individually. commit 7bf59dfec4234e75e31b3f397374cb5bab1a5b2c Merge: ad728364e3916e1159ee94e5cd82b7a9c81d2dcc 357d1e3bc7d2d80e5271bc4f3ac8537e30dc8046 Author: Peter Maydell <peter.maydell@xxxxxxxxxx> AuthorDate: Mon Oct 17 12:59:54 2016 +0100 Commit: Peter Maydell <peter.maydell@xxxxxxxxxx> CommitDate: Mon Oct 17 12:59:54 2016 +0100 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@xxxxxxxxxxxxxxxxxxxxx>" # gpg: aka "David Gibson (Red Hat) <dgibson@xxxxxxxxxx>" # gpg: aka "David Gibson (ozlabs.org) <dgibson@xxxxxxxxxx>" # gpg: aka "David Gibson (kernel.org) <dwg@xxxxxxxxxx>" # 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: Peter Maydell <peter.maydell@xxxxxxxxxx> hw/intc/trace-events | 15 +-- hw/intc/xics.c | 231 ++++++++++++++++++++++-------------- hw/intc/xics_kvm.c | 37 ++++-- hw/intc/xics_spapr.c | 116 +++++++++++------- hw/ppc/spapr.c | 118 +++++++++++++++++- hw/ppc/spapr_events.c | 2 +- hw/ppc/spapr_pci.c | 95 ++++++++++----- hw/ppc/spapr_vio.c | 2 +- include/hw/pci-host/spapr.h | 25 ++-- include/hw/ppc/spapr.h | 4 + include/hw/ppc/xics.h | 40 ++++--- qtest.c | 7 ++ target-ppc/helper.h | 5 + target-ppc/int_helper.c | 15 +++ target-ppc/translate/vmx-impl.inc.c | 5 + target-ppc/translate/vmx-ops.inc.c | 5 + tests/bios-tables-test.c | 2 +- tests/boot-sector.c | 25 ++-- tests/boot-sector.h | 4 +- tests/endianness-test.c | 3 +- tests/libqos/pci-spapr.c | 116 ++++++++++-------- tests/libqos/virtio-pci.c | 2 +- tests/libqtest.c | 68 ++++------- tests/libqtest.h | 16 ++- tests/pxe-test.c | 2 +- tests/spapr-phb-test.c | 2 +- tests/usb-hcd-uhci-test.c | 15 ++- tests/virtio-blk-test.c | 2 +- 28 files changed, 642 insertions(+), 337 deletions(-) diff --git a/hw/intc/trace-events b/hw/intc/trace-events index f12192c..a367b46 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -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" diff --git a/hw/intc/xics.c b/hw/intc/xics.c index 69162f0..f40b000 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -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, - uint8_t priority, uint8_t saved_priority) +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); } diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index c9caefc..9c2f198 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -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,10 +452,12 @@ 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); - if (error) { - error_propagate(errp, error); - goto fail; + 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); @@ -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) diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index 618826d..e8d0623 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -113,13 +113,17 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { - ICSState *ics = spapr->xics->ics; - uint32_t nr, server, priority; + ICSState *ics = QLIST_FIRST(&spapr->xics->ics); + uint32_t nr, srcno, server, priority; if ((nargs != 3) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } + if (!ics) { + rtas_st(rets, 0, RTAS_OUT_HW_ERROR); + return; + } nr = rtas_ld(args, 0); server = xics_get_cpu_index_by_dt_id(rtas_ld(args, 1)); @@ -131,7 +135,8 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr, return; } - ics_write_xive(ics, nr, server, priority, priority); + srcno = nr - ics->offset; + ics_simple_write_xive(ics, srcno, server, priority, priority); rtas_st(rets, 0, RTAS_OUT_SUCCESS); } @@ -141,13 +146,17 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { - ICSState *ics = spapr->xics->ics; - uint32_t nr; + ICSState *ics = QLIST_FIRST(&spapr->xics->ics); + uint32_t nr, srcno; if ((nargs != 1) || (nret != 3)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } + if (!ics) { + rtas_st(rets, 0, RTAS_OUT_HW_ERROR); + return; + } nr = rtas_ld(args, 0); @@ -157,8 +166,9 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr, } rtas_st(rets, 0, RTAS_OUT_SUCCESS); - rtas_st(rets, 1, ics->irqs[nr - ics->offset].server); - rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority); + srcno = nr - ics->offset; + rtas_st(rets, 1, ics->irqs[srcno].server); + rtas_st(rets, 2, ics->irqs[srcno].priority); } static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr, @@ -166,13 +176,17 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { - ICSState *ics = spapr->xics->ics; - uint32_t nr; + ICSState *ics = QLIST_FIRST(&spapr->xics->ics); + uint32_t nr, srcno; if ((nargs != 1) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } + if (!ics) { + rtas_st(rets, 0, RTAS_OUT_HW_ERROR); + return; + } nr = rtas_ld(args, 0); @@ -181,8 +195,9 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr, return; } - ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff, - ics->irqs[nr - ics->offset].priority); + srcno = nr - ics->offset; + ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff, + ics->irqs[srcno].priority); rtas_st(rets, 0, RTAS_OUT_SUCCESS); } @@ -192,13 +207,17 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { - ICSState *ics = spapr->xics->ics; - uint32_t nr; + ICSState *ics = QLIST_FIRST(&spapr->xics->ics); + uint32_t nr, srcno; if ((nargs != 1) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } + if (!ics) { + rtas_st(rets, 0, RTAS_OUT_HW_ERROR); + return; + } nr = rtas_ld(args, 0); @@ -207,9 +226,10 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr, return; } - ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, - ics->irqs[nr - ics->offset].saved_priority, - ics->irqs[nr - ics->offset].saved_priority); + srcno = nr - ics->offset; + ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server, + ics->irqs[srcno].saved_priority, + ics->irqs[srcno].saved_priority); rtas_st(rets, 0, RTAS_OUT_SUCCESS); } @@ -217,7 +237,13 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr, static void xics_spapr_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_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers, @@ -240,6 +266,7 @@ static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers, static void xics_spapr_realize(DeviceState *dev, Error **errp) { XICSState *xics = XICS_SPAPR(dev); + ICSState *ics; Error *error = NULL; int i; @@ -261,10 +288,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp) spapr_register_hypercall(H_EOI, h_eoi); spapr_register_hypercall(H_IPOLL, h_ipoll); - object_property_set_bool(OBJECT(xics->ics), true, "realized", &error); - if (error) { - error_propagate(errp, error); - return; + QLIST_FOREACH(ics, &xics->ics, list) { + object_property_set_bool(OBJECT(ics), true, "realized", &error); + if (error) { + error_propagate(errp, error); + return; + } } for (i = 0; i < xics->nr_servers; i++) { @@ -280,10 +309,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp) static void xics_spapr_initfn(Object *obj) { XICSState *xics = XICS_SPAPR(obj); + ICSState *ics; - xics->ics = ICS(object_new(TYPE_ICS)); - object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL); - xics->ics->xics = xics; + ics = ICS_SIMPLE(object_new(TYPE_ICS_SIMPLE)); + object_property_add_child(obj, "ics", OBJECT(ics), NULL); + ics->xics = xics; + QLIST_INSERT_HEAD(&xics->ics, ics, list); } static void xics_spapr_class_init(ObjectClass *oc, void *data) @@ -329,14 +360,15 @@ static int ics_find_free_block(ICSState *ics, int num, int alignnum) return -1; } -int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi, - Error **errp) +int xics_spapr_alloc(XICSState *xics, int irq_hint, bool lsi, Error **errp) { - ICSState *ics = &xics->ics[src]; + ICSState *ics = QLIST_FIRST(&xics->ics); int irq; + if (!ics) { + return -1; + } if (irq_hint) { - assert(src == xics_find_source(xics, irq_hint)); if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) { error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint); return -1; @@ -352,7 +384,7 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi, } ics_set_irq_type(ics, irq - ics->offset, lsi); - trace_xics_alloc(src, irq); + trace_xics_alloc(irq); return irq; } @@ -361,13 +393,16 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi, * Allocate block of consecutive IRQs, and return the number of the first IRQ in * the block. If align==true, aligns the first IRQ number to num. */ -int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi, - bool align, Error **errp) +int xics_spapr_alloc_block(XICSState *xics, int num, bool lsi, bool align, + Error **errp) { + ICSState *ics = QLIST_FIRST(&xics->ics); int i, first = -1; - ICSState *ics = &xics->ics[src]; - assert(src == 0); + if (!ics) { + return -1; + } + /* * MSIMesage::data is used for storing VIRQ so * it has to be aligned to num to support multiple @@ -394,7 +429,7 @@ int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi, } first += ics->offset; - trace_xics_alloc_block(src, first, num, lsi, align); + trace_xics_alloc_block(first, num, lsi, align); return first; } @@ -405,7 +440,7 @@ static void ics_free(ICSState *ics, int srcno, int num) for (i = srcno; i < srcno + num; ++i) { if (ICS_IRQ_FREE(ics, i)) { - trace_xics_ics_free_warn(ics - ics->xics->ics, i + ics->offset); + trace_xics_ics_free_warn(0, i + ics->offset); } memset(&ics->irqs[i], 0, sizeof(ICSIRQState)); } @@ -413,15 +448,10 @@ static void ics_free(ICSState *ics, int srcno, int num) void xics_spapr_free(XICSState *xics, int irq, int num) { - int src = xics_find_source(xics, irq); - - if (src >= 0) { - ICSState *ics = &xics->ics[src]; - - /* FIXME: implement multiple sources */ - assert(src == 0); + ICSState *ics = xics_find_source(xics, irq); - trace_xics_ics_free(ics - xics->ics, irq, num); + if (ics) { + trace_xics_ics_free(0, irq, num); ics_free(ics, irq - ics->offset, num); } } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 03e3803..ddb7438 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -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 = { @@ -2470,11 +2521,71 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", true); /* * pseries-2.7 */ -#define SPAPR_COMPAT_2_7 \ - HW_COMPAT_2_7 \ +#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) diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 4c7b6ae..6d35345 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -594,7 +594,7 @@ out_no_events: void spapr_events_init(sPAPRMachineState *spapr) { QTAILQ_INIT(&spapr->pending_events); - spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, 0, false, + spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, false, &error_fatal); spapr->epow_notifier.notify = spapr_powerdown_req; qemu_register_powerdown_notifier(&spapr->epow_notifier); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 4f00865..2a1ccf5 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -363,7 +363,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, } /* Allocate MSIs */ - irq = xics_spapr_alloc_block(spapr->xics, 0, req_num, false, + irq = xics_spapr_alloc_block(spapr->xics, req_num, false, ret_intr_type == RTAS_TYPE_MSI, &err); if (err) { error_reportf_err(err, "Can't allocate MSIs for device %x: ", @@ -1311,32 +1311,27 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; if (sphb->index != (uint32_t)-1) { - hwaddr windows_base; + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); + Error *local_err = NULL; if ((sphb->buid != (uint64_t)-1) || (sphb->dma_liobn[0] != (uint32_t)-1) || (sphb->dma_liobn[1] != (uint32_t)-1 && windows_supported == 2) || (sphb->mem_win_addr != (hwaddr)-1) + || (sphb->mem64_win_addr != (hwaddr)-1) || (sphb->io_win_addr != (hwaddr)-1)) { error_setg(errp, "Either \"index\" or other parameters must" " be specified for PAPR PHB, not both"); return; } - if (sphb->index > SPAPR_PCI_MAX_INDEX) { - error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", - SPAPR_PCI_MAX_INDEX); + smc->phb_placement(spapr, sphb->index, + &sphb->buid, &sphb->io_win_addr, + &sphb->mem_win_addr, &sphb->mem64_win_addr, + windows_supported, sphb->dma_liobn, &local_err); + if (local_err) { + error_propagate(errp, local_err); return; } - - sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index; - for (i = 0; i < windows_supported; ++i) { - sphb->dma_liobn[i] = SPAPR_PCI_LIOBN(sphb->index, i); - } - - windows_base = SPAPR_PCI_WINDOW_BASE - + sphb->index * SPAPR_PCI_WINDOW_SPACING; - sphb->mem_win_addr = windows_base + SPAPR_PCI_MMIO_WIN_OFF; - sphb->io_win_addr = windows_base + SPAPR_PCI_IO_WIN_OFF; } if (sphb->buid == (uint64_t)-1) { @@ -1360,6 +1355,38 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) return; } + if (sphb->mem64_win_size != 0) { + if (sphb->mem64_win_addr == (hwaddr)-1) { + error_setg(errp, + "64-bit memory window address not specified for PHB"); + return; + } + + if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) { + error_setg(errp, "32-bit memory window of size 0x%"HWADDR_PRIx + " (max 2 GiB)", sphb->mem_win_size); + return; + } + + if (sphb->mem64_win_pciaddr == (hwaddr)-1) { + /* 64-bit window defaults to identity mapping */ + sphb->mem64_win_pciaddr = sphb->mem64_win_addr; + } + } else if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) { + /* + * For compatibility with old configuration, if no 64-bit MMIO + * window is specified, but the ordinary (32-bit) memory + * window is specified as > 2GiB, we treat it as a 2GiB 32-bit + * window, with a 64-bit MMIO window following on immediately + * afterwards + */ + sphb->mem64_win_size = sphb->mem_win_size - SPAPR_PCI_MEM32_WIN_SIZE; + sphb->mem64_win_addr = sphb->mem_win_addr + SPAPR_PCI_MEM32_WIN_SIZE; + sphb->mem64_win_pciaddr = + SPAPR_PCI_MEM_WIN_BUS_OFFSET + SPAPR_PCI_MEM32_WIN_SIZE; + sphb->mem_win_size = SPAPR_PCI_MEM32_WIN_SIZE; + } + if (spapr_pci_find_phb(spapr, sphb->buid)) { error_setg(errp, "PCI host bridges must have unique BUIDs"); return; @@ -1373,12 +1400,19 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) sprintf(namebuf, "%s.mmio", sphb->dtbusname); memory_region_init(&sphb->memspace, OBJECT(sphb), namebuf, UINT64_MAX); - sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname); - memory_region_init_alias(&sphb->memwindow, OBJECT(sphb), + sprintf(namebuf, "%s.mmio32-alias", sphb->dtbusname); + memory_region_init_alias(&sphb->mem32window, OBJECT(sphb), namebuf, &sphb->memspace, SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size); memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr, - &sphb->memwindow); + &sphb->mem32window); + + sprintf(namebuf, "%s.mmio64-alias", sphb->dtbusname); + memory_region_init_alias(&sphb->mem64window, OBJECT(sphb), + namebuf, &sphb->memspace, + sphb->mem64_win_pciaddr, sphb->mem64_win_size); + memory_region_add_subregion(get_system_memory(), sphb->mem64_win_addr, + &sphb->mem64window); /* Initialize IO regions */ sprintf(namebuf, "%s.io", sphb->dtbusname); @@ -1445,8 +1479,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) uint32_t irq; Error *local_err = NULL; - irq = xics_spapr_alloc_block(spapr->xics, 0, 1, true, false, - &local_err); + irq = xics_spapr_alloc_block(spapr->xics, 1, true, false, &local_err); if (local_err) { error_propagate(errp, local_err); error_prepend(errp, "can't allocate LSIs: "); @@ -1531,7 +1564,12 @@ static Property spapr_phb_properties[] = { DEFINE_PROP_UINT32("liobn64", sPAPRPHBState, dma_liobn[1], -1), DEFINE_PROP_UINT64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1), DEFINE_PROP_UINT64("mem_win_size", sPAPRPHBState, mem_win_size, - SPAPR_PCI_MMIO_WIN_SIZE), + SPAPR_PCI_MEM32_WIN_SIZE), + DEFINE_PROP_UINT64("mem64_win_addr", sPAPRPHBState, mem64_win_addr, -1), + DEFINE_PROP_UINT64("mem64_win_size", sPAPRPHBState, mem64_win_size, + SPAPR_PCI_MEM64_WIN_SIZE), + DEFINE_PROP_UINT64("mem64_win_pciaddr", sPAPRPHBState, mem64_win_pciaddr, + -1), DEFINE_PROP_UINT64("io_win_addr", sPAPRPHBState, io_win_addr, -1), DEFINE_PROP_UINT64("io_win_size", sPAPRPHBState, io_win_size, SPAPR_PCI_IO_WIN_SIZE), @@ -1767,10 +1805,6 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, int bus_off, i, j, ret; char nodename[FDT_NAME_MAX]; uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) }; - const uint64_t mmiosize = memory_region_size(&phb->memwindow); - const uint64_t w32max = (1ULL << 32) - SPAPR_PCI_MEM_WIN_BUS_OFFSET; - const uint64_t w32size = MIN(w32max, mmiosize); - const uint64_t w64size = (mmiosize > w32size) ? (mmiosize - w32size) : 0; struct { uint32_t hi; uint64_t child; @@ -1785,15 +1819,16 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, { cpu_to_be32(b_ss(2)), cpu_to_be64(SPAPR_PCI_MEM_WIN_BUS_OFFSET), cpu_to_be64(phb->mem_win_addr), - cpu_to_be64(w32size), + cpu_to_be64(phb->mem_win_size), }, { - cpu_to_be32(b_ss(3)), cpu_to_be64(1ULL << 32), - cpu_to_be64(phb->mem_win_addr + w32size), - cpu_to_be64(w64size) + cpu_to_be32(b_ss(3)), cpu_to_be64(phb->mem64_win_pciaddr), + cpu_to_be64(phb->mem64_win_addr), + cpu_to_be64(phb->mem64_win_size), }, }; - const unsigned sizeof_ranges = (w64size ? 3 : 2) * sizeof(ranges[0]); + const unsigned sizeof_ranges = + (phb->mem64_win_size ? 3 : 2) * sizeof(ranges[0]); uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 }; uint32_t interrupt_map_mask[] = { cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)}; diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index d68dd35..3648aa5 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -453,7 +453,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) dev->qdev.id = id; } - dev->irq = xics_spapr_alloc(spapr->xics, 0, dev->irq, false, &local_err); + dev->irq = xics_spapr_alloc(spapr->xics, dev->irq, false, &local_err); if (local_err) { error_propagate(errp, local_err); return; diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index 30dbd46..b92c1b5 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -53,8 +53,10 @@ struct sPAPRPHBState { bool dr_enabled; MemoryRegion memspace, iospace; - hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size; - MemoryRegion memwindow, iowindow, msiwindow; + hwaddr mem_win_addr, mem_win_size, mem64_win_addr, mem64_win_size; + uint64_t mem64_win_pciaddr; + hwaddr io_win_addr, io_win_size; + MemoryRegion mem32window, mem64window, iowindow, msiwindow; uint32_t dma_liobn[SPAPR_PCI_DMA_MAX_WINDOWS]; hwaddr dma_win_addr, dma_win_size; @@ -79,18 +81,17 @@ struct sPAPRPHBState { uint32_t numa_node; }; -#define SPAPR_PCI_MAX_INDEX 255 - -#define SPAPR_PCI_BASE_BUID 0x800000020000000ULL - #define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL +#define SPAPR_PCI_MEM32_WIN_SIZE \ + ((1ULL << 32) - SPAPR_PCI_MEM_WIN_BUS_OFFSET) +#define SPAPR_PCI_MEM64_WIN_SIZE 0x10000000000ULL /* 1 TiB */ + +/* Without manual configuration, all PCI outbound windows will be + * within this range */ +#define SPAPR_PCI_BASE (1ULL << 45) /* 32 TiB */ +#define SPAPR_PCI_LIMIT (1ULL << 46) /* 64 TiB */ -#define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL -#define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL -#define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000 -#define SPAPR_PCI_MMIO_WIN_SIZE (SPAPR_PCI_WINDOW_SPACING - \ - SPAPR_PCI_MEM_WIN_BUS_OFFSET) -#define SPAPR_PCI_IO_WIN_OFF 0x80000000 +#define SPAPR_PCI_2_7_MMIO_WIN_SIZE 0xf80000000 #define SPAPR_PCI_IO_WIN_SIZE 0x10000 #define SPAPR_PCI_MSI_WINDOW 0x40000000000ULL diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 39dadaa..aeaba3e 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -40,6 +40,10 @@ struct sPAPRMachineClass { bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */ bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */ const char *tcg_default_cpu; /* which (TCG) CPU to simulate by default */ + void (*phb_placement)(sPAPRMachineState *spapr, uint32_t index, + uint64_t *buid, hwaddr *pio, + hwaddr *mmio32, hwaddr *mmio64, + unsigned n_dma, uint32_t *liobns, Error **errp); }; /** diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h index 5aac67a..66ae55d 100644 --- a/include/hw/ppc/xics.h +++ b/include/hw/ppc/xics.h @@ -85,7 +85,7 @@ struct XICSState { uint32_t nr_servers; uint32_t nr_irqs; ICPState *ss; - ICSState *ics; + QLIST_HEAD(, ICSState) ics; }; #define TYPE_ICP "icp" @@ -111,6 +111,7 @@ struct ICPState { DeviceState parent_obj; /*< public >*/ CPUState *cs; + ICSState *xirr_owner; uint32_t xirr; uint8_t pending_priority; uint8_t mfrr; @@ -118,22 +119,29 @@ struct ICPState { bool cap_irq_xics_enabled; }; -#define TYPE_ICS "ics" -#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS) +#define TYPE_ICS_BASE "ics-base" +#define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_BASE) -#define TYPE_KVM_ICS "icskvm" -#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS) +/* Retain ics for sPAPR for migration from existing sPAPR guests */ +#define TYPE_ICS_SIMPLE "ics" +#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE) -#define ICS_CLASS(klass) \ - OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS) -#define ICS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS) +#define TYPE_ICS_KVM "icskvm" +#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM) + +#define ICS_BASE_CLASS(klass) \ + OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_BASE) +#define ICS_BASE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_BASE) struct ICSStateClass { DeviceClass parent_class; void (*pre_save)(ICSState *s); int (*post_load)(ICSState *s, int version_id); + void (*reject)(ICSState *s, uint32_t irq); + void (*resend)(ICSState *s); + void (*eoi)(ICSState *s, uint32_t irq); }; struct ICSState { @@ -145,6 +153,7 @@ struct ICSState { qemu_irq *qirqs; ICSIRQState *irqs; XICSState *xics; + QLIST_ENTRY(ICSState) list; }; static inline bool ics_valid_irq(ICSState *ics, uint32_t nr) @@ -172,10 +181,9 @@ struct ICSIRQState { #define XICS_IRQS_SPAPR 1024 qemu_irq xics_get_qirq(XICSState *icp, int irq); -int xics_spapr_alloc(XICSState *icp, int src, int irq_hint, bool lsi, - Error **errp); -int xics_spapr_alloc_block(XICSState *icp, int src, int num, bool lsi, - bool align, Error **errp); +int xics_spapr_alloc(XICSState *icp, int irq_hint, bool lsi, Error **errp); +int xics_spapr_alloc_block(XICSState *icp, int num, bool lsi, bool align, + Error **errp); void xics_spapr_free(XICSState *icp, int irq, int num); void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu); @@ -190,11 +198,11 @@ uint32_t icp_accept(ICPState *ss); uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr); void icp_eoi(XICSState *icp, int server, uint32_t xirr); -void ics_write_xive(ICSState *ics, int nr, int server, - uint8_t priority, uint8_t saved_priority); +void ics_simple_write_xive(ICSState *ics, int nr, int server, + uint8_t priority, uint8_t saved_priority); void ics_set_irq_type(ICSState *ics, int srcno, bool lsi); -int xics_find_source(XICSState *icp, int irq); +ICSState *xics_find_source(XICSState *icp, int irq); #endif /* XICS_H */ diff --git a/qtest.c b/qtest.c index 22482cc..b53b39c 100644 --- a/qtest.c +++ b/qtest.c @@ -537,6 +537,13 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) qtest_send_prefix(chr); qtest_send(chr, "OK\n"); + } else if (strcmp(words[0], "endianness") == 0) { + qtest_send_prefix(chr); +#if defined(TARGET_WORDS_BIGENDIAN) + qtest_sendf(chr, "OK big\n"); +#else + qtest_sendf(chr, "OK little\n"); +#endif #ifdef TARGET_PPC64 } else if (strcmp(words[0], "rtas") == 0) { uint64_t res, args, ret; diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 796ad45..04c6421 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -267,6 +267,11 @@ DEF_HELPER_3(vinsertb, void, avr, avr, i32) DEF_HELPER_3(vinserth, void, avr, avr, i32) DEF_HELPER_3(vinsertw, void, avr, avr, i32) DEF_HELPER_3(vinsertd, void, avr, avr, i32) +DEF_HELPER_2(vextsb2w, void, avr, avr) +DEF_HELPER_2(vextsh2w, void, avr, avr) +DEF_HELPER_2(vextsb2d, void, avr, avr) +DEF_HELPER_2(vextsh2d, void, avr, avr) +DEF_HELPER_2(vextsw2d, void, avr, avr) DEF_HELPER_2(vupkhpx, void, avr, avr) DEF_HELPER_2(vupklpx, void, avr, avr) DEF_HELPER_2(vupkhsb, void, avr, avr) diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index 202854f..5aee0a8 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -1934,6 +1934,21 @@ VEXTRACT(uw, u32) VEXTRACT(d, u64) #undef VEXTRACT +#define VEXT_SIGNED(name, element, mask, cast, recast) \ +void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \ +{ \ + int i; \ + VECTOR_FOR_INORDER_I(i, element) { \ + r->element[i] = (recast)((cast)(b->element[i] & mask)); \ + } \ +} +VEXT_SIGNED(vextsb2w, s32, UINT8_MAX, int8_t, int32_t) +VEXT_SIGNED(vextsb2d, s64, UINT8_MAX, int8_t, int64_t) +VEXT_SIGNED(vextsh2w, s32, UINT16_MAX, int16_t, int32_t) +VEXT_SIGNED(vextsh2d, s64, UINT16_MAX, int16_t, int64_t) +VEXT_SIGNED(vextsw2d, s64, UINT32_MAX, int32_t, int64_t) +#undef VEXT_SIGNED + #define VSPLTI(suffix, element, splat_type) \ void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \ { \ diff --git a/target-ppc/translate/vmx-impl.inc.c b/target-ppc/translate/vmx-impl.inc.c index 25cd073..c8998f3 100644 --- a/target-ppc/translate/vmx-impl.inc.c +++ b/target-ppc/translate/vmx-impl.inc.c @@ -815,6 +815,11 @@ GEN_VXFORM_NOA(vclzb, 1, 28) GEN_VXFORM_NOA(vclzh, 1, 29) GEN_VXFORM_NOA(vclzw, 1, 30) GEN_VXFORM_NOA(vclzd, 1, 31) +GEN_VXFORM_NOA_2(vextsb2w, 1, 24, 16) +GEN_VXFORM_NOA_2(vextsh2w, 1, 24, 17) +GEN_VXFORM_NOA_2(vextsb2d, 1, 24, 24) +GEN_VXFORM_NOA_2(vextsh2d, 1, 24, 25) +GEN_VXFORM_NOA_2(vextsw2d, 1, 24, 26) GEN_VXFORM_NOA_2(vctzb, 1, 24, 28) GEN_VXFORM_NOA_2(vctzh, 1, 24, 29) GEN_VXFORM_NOA_2(vctzw, 1, 24, 30) diff --git a/target-ppc/translate/vmx-ops.inc.c b/target-ppc/translate/vmx-ops.inc.c index ac1dc9b..68cba3e 100644 --- a/target-ppc/translate/vmx-ops.inc.c +++ b/target-ppc/translate/vmx-ops.inc.c @@ -215,6 +215,11 @@ GEN_VXFORM_DUAL_INV(vspltish, vinserth, 6, 13, 0x00000000, 0x100000, GEN_VXFORM_DUAL_INV(vspltisw, vinsertw, 6, 14, 0x00000000, 0x100000, PPC_ALTIVEC), GEN_VXFORM_300_EXT(vinsertd, 6, 15, 0x100000), +GEN_VXFORM_300_EO(vextsb2w, 0x01, 0x18, 0x10), +GEN_VXFORM_300_EO(vextsh2w, 0x01, 0x18, 0x11), +GEN_VXFORM_300_EO(vextsb2d, 0x01, 0x18, 0x18), +GEN_VXFORM_300_EO(vextsh2d, 0x01, 0x18, 0x19), +GEN_VXFORM_300_EO(vextsw2d, 0x01, 0x18, 0x1A), GEN_VXFORM_300_EO(vctzb, 0x01, 0x18, 0x1C), GEN_VXFORM_300_EO(vctzh, 0x01, 0x18, 0x1D), GEN_VXFORM_300_EO(vctzw, 0x01, 0x18, 0x1E), diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 6ea2b6d..812f830 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -112,7 +112,7 @@ typedef struct { g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \ } while (0) -static const char *disk = "tests/acpi-test-disk.raw"; +static char disk[] = "tests/acpi-test-disk-XXXXXX"; static const char *data_dir = "tests/acpi-test-data"; #ifdef CONFIG_IASL static const char *iasl = stringify(CONFIG_IASL); diff --git a/tests/boot-sector.c b/tests/boot-sector.c index e3193c0..e3880f4 100644 --- a/tests/boot-sector.c +++ b/tests/boot-sector.c @@ -69,25 +69,32 @@ static uint8_t boot_sector[0x7e000] = { }; /* Create boot disk file. */ -int boot_sector_init(const char *fname) +int boot_sector_init(char *fname) { - FILE *f = fopen(fname, "w"); + int fd, ret; + size_t len = sizeof boot_sector; - if (!f) { + fd = mkstemp(fname); + if (fd < 0) { fprintf(stderr, "Couldn't open \"%s\": %s", fname, strerror(errno)); return 1; } /* For Open Firmware based system, we can use a Forth script instead */ if (strcmp(qtest_get_arch(), "ppc64") == 0) { - memset(boot_sector, ' ', sizeof boot_sector); - sprintf((char *)boot_sector, "\\ Bootscript\n%x %x c! %x %x c!\n", + len = sprintf((char *)boot_sector, "\\ Bootscript\n%x %x c! %x %x c!\n", LOW(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET, HIGH(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1); } - fwrite(boot_sector, 1, sizeof boot_sector, f); - fclose(f); + ret = write(fd, boot_sector, len); + close(fd); + + if (ret != len) { + fprintf(stderr, "Could not write \"%s\"", fname); + return 1; + } + return 0; } @@ -99,9 +106,9 @@ void boot_sector_test(void) uint16_t signature; int i; - /* Wait at most 1 minute */ + /* Wait at most 90 seconds */ #define TEST_DELAY (1 * G_USEC_PER_SEC / 10) -#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1) +#define TEST_CYCLES MAX((90 * G_USEC_PER_SEC / TEST_DELAY), 1) /* Poll until code has run and modified memory. Once it has we know BIOS * initialization is done. TODO: check that IP reached the halt diff --git a/tests/boot-sector.h b/tests/boot-sector.h index f64b477..35d61c7 100644 --- a/tests/boot-sector.h +++ b/tests/boot-sector.h @@ -14,8 +14,8 @@ #ifndef TEST_BOOT_SECTOR_H #define TEST_BOOT_SECTOR_H -/* Create boot disk file. */ -int boot_sector_init(const char *fname); +/* Create boot disk file. fname must be a suitable string for mkstemp() */ +int boot_sector_init(char *fname); /* Loop until signature in memory is OK. */ void boot_sector_test(void); diff --git a/tests/endianness-test.c b/tests/endianness-test.c index b7a120e..cf8d41b 100644 --- a/tests/endianness-test.c +++ b/tests/endianness-test.c @@ -38,7 +38,8 @@ static const TestCase test_cases[] = { { "ppc", "prep", 0x80000000, .bswap = true }, { "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" }, { "ppc64", "mac99", 0xf2000000, .bswap = true, .superio = "i82378" }, - { "ppc64", "pseries", 0x10080000000ULL, + { "ppc64", "pseries", (1ULL << 45), .bswap = true, .superio = "i82378" }, + { "ppc64", "pseries-2.7", 0x10080000000ULL, .bswap = true, .superio = "i82378" }, { "sh4", "r2d", 0xfe240000, .superio = "i82378" }, { "sh4eb", "r2d", 0xfe240000, .bswap = true, .superio = "i82378" }, diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c index 2f73bad..2eaaf91 100644 --- a/tests/libqos/pci-spapr.c +++ b/tests/libqos/pci-spapr.c @@ -18,30 +18,23 @@ /* From include/hw/pci-host/spapr.h */ -#define SPAPR_PCI_BASE_BUID 0x800000020000000ULL - -#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL - -#define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL -#define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL -#define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000 -#define SPAPR_PCI_MMIO_WIN_SIZE (SPAPR_PCI_WINDOW_SPACING - \ - SPAPR_PCI_MEM_WIN_BUS_OFFSET) -#define SPAPR_PCI_IO_WIN_OFF 0x80000000 -#define SPAPR_PCI_IO_WIN_SIZE 0x10000 - -/* index is the phb index */ - -#define BUIDBASE(index) (SPAPR_PCI_BASE_BUID + (index)) -#define PCIBASE(index) (SPAPR_PCI_WINDOW_BASE + \ - (index) * SPAPR_PCI_WINDOW_SPACING) -#define IOBASE(index) (PCIBASE(index) + SPAPR_PCI_IO_WIN_OFF) -#define MMIOBASE(index) (PCIBASE(index) + SPAPR_PCI_MMIO_WIN_OFF) +typedef struct QPCIWindow { + uint64_t pci_base; /* window address in PCI space */ + uint64_t size; /* window size */ +} QPCIWindow; typedef struct QPCIBusSPAPR { QPCIBus bus; QGuestAllocator *alloc; + uint64_t buid; + + uint64_t pio_cpu_base; + QPCIWindow pio; + + uint64_t mmio32_cpu_base; + QPCIWindow mmio32; + uint64_t pci_hole_start; uint64_t pci_hole_size; uint64_t pci_hole_alloc; @@ -59,69 +52,75 @@ typedef struct QPCIBusSPAPR { static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr) { + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint64_t port = (uintptr_t)addr; uint8_t v; - if (port < SPAPR_PCI_IO_WIN_SIZE) { - v = readb(IOBASE(0) + port); + if (port < s->pio.size) { + v = readb(s->pio_cpu_base + port); } else { - v = readb(MMIOBASE(0) + port); + v = readb(s->mmio32_cpu_base + port); } return v; } static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr) { + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint64_t port = (uintptr_t)addr; uint16_t v; - if (port < SPAPR_PCI_IO_WIN_SIZE) { - v = readw(IOBASE(0) + port); + if (port < s->pio.size) { + v = readw(s->pio_cpu_base + port); } else { - v = readw(MMIOBASE(0) + port); + v = readw(s->mmio32_cpu_base + port); } return bswap16(v); } static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr) { + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint64_t port = (uintptr_t)addr; uint32_t v; - if (port < SPAPR_PCI_IO_WIN_SIZE) { - v = readl(IOBASE(0) + port); + if (port < s->pio.size) { + v = readl(s->pio_cpu_base + port); } else { - v = readl(MMIOBASE(0) + port); + v = readl(s->mmio32_cpu_base + port); } return bswap32(v); } static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value) { + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint64_t port = (uintptr_t)addr; - if (port < SPAPR_PCI_IO_WIN_SIZE) { - writeb(IOBASE(0) + port, value); + if (port < s->pio.size) { + writeb(s->pio_cpu_base + port, value); } else { - writeb(MMIOBASE(0) + port, value); + writeb(s->mmio32_cpu_base + port, value); } } static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value) { + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint64_t port = (uintptr_t)addr; value = bswap16(value); - if (port < SPAPR_PCI_IO_WIN_SIZE) { - writew(IOBASE(0) + port, value); + if (port < s->pio.size) { + writew(s->pio_cpu_base + port, value); } else { - writew(MMIOBASE(0) + port, value); + writew(s->mmio32_cpu_base + port, value); } } static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value) { + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint64_t port = (uintptr_t)addr; value = bswap32(value); - if (port < SPAPR_PCI_IO_WIN_SIZE) { - writel(IOBASE(0) + port, value); + if (port < s->pio.size) { + writel(s->pio_cpu_base + port, value); } else { - writel(MMIOBASE(0) + port, value); + writel(s->mmio32_cpu_base + port, value); } } @@ -129,24 +128,21 @@ static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset) { QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint32_t config_addr = (devfn << 8) | offset; - return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0), - config_addr, 1); + return qrtas_ibm_read_pci_config(s->alloc, s->buid, config_addr, 1); } static uint16_t qpci_spapr_config_readw(QPCIBus *bus, int devfn, uint8_t offset) { QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint32_t config_addr = (devfn << 8) | offset; - return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0), - config_addr, 2); + return qrtas_ibm_read_pci_config(s->alloc, s->buid, config_addr, 2); } static uint32_t qpci_spapr_config_readl(QPCIBus *bus, int devfn, uint8_t offset) { QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint32_t config_addr = (devfn << 8) | offset; - return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0), - config_addr, 4); + return qrtas_ibm_read_pci_config(s->alloc, s->buid, config_addr, 4); } static void qpci_spapr_config_writeb(QPCIBus *bus, int devfn, uint8_t offset, @@ -154,8 +150,7 @@ static void qpci_spapr_config_writeb(QPCIBus *bus, int devfn, uint8_t offset, { QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint32_t config_addr = (devfn << 8) | offset; - qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0), - config_addr, 1, value); + qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 1, value); } static void qpci_spapr_config_writew(QPCIBus *bus, int devfn, uint8_t offset, @@ -163,8 +158,7 @@ static void qpci_spapr_config_writew(QPCIBus *bus, int devfn, uint8_t offset, { QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint32_t config_addr = (devfn << 8) | offset; - qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0), - config_addr, 2, value); + qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 2, value); } static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset, @@ -172,8 +166,7 @@ static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset, { QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus); uint32_t config_addr = (devfn << 8) | offset; - qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0), - config_addr, 4, value); + qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 4, value); } static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno, @@ -242,6 +235,11 @@ static void qpci_spapr_iounmap(QPCIBus *bus, void *data) /* FIXME */ } +#define SPAPR_PCI_BASE (1ULL << 45) + +#define SPAPR_PCI_MMIO32_WIN_SIZE 0x80000000 /* 2 GiB */ +#define SPAPR_PCI_IO_WIN_SIZE 0x10000 + QPCIBus *qpci_init_spapr(QGuestAllocator *alloc) { QPCIBusSPAPR *ret; @@ -269,12 +267,28 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc) ret->bus.iomap = qpci_spapr_iomap; ret->bus.iounmap = qpci_spapr_iounmap; + /* FIXME: We assume the default location of the PHB for now. + * Ideally we'd parse the device tree deposited in the guest to + * get the window locations */ + ret->buid = 0x800000020000000ULL; + + ret->pio_cpu_base = SPAPR_PCI_BASE; + ret->pio.pci_base = 0; + ret->pio.size = SPAPR_PCI_IO_WIN_SIZE; + + /* 32-bit portion of the MMIO window is at PCI address 2..4 GiB */ + ret->mmio32_cpu_base = SPAPR_PCI_BASE + SPAPR_PCI_MMIO32_WIN_SIZE; + ret->mmio32.pci_base = 0x80000000; /* 2 GiB */ + ret->mmio32.size = SPAPR_PCI_MMIO32_WIN_SIZE; + ret->pci_hole_start = 0xC0000000; - ret->pci_hole_size = SPAPR_PCI_MMIO_WIN_SIZE; + ret->pci_hole_size = + ret->mmio32.pci_base + ret->mmio32.size - ret->pci_hole_start; ret->pci_hole_alloc = 0; ret->pci_iohole_start = 0xc000; - ret->pci_iohole_size = SPAPR_PCI_IO_WIN_SIZE; + ret->pci_iohole_size = + ret->pio.pci_base + ret->pio.size - ret->pci_iohole_start; ret->pci_iohole_alloc = 0; return &ret->bus; diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c index 18b92b9..6e005c1 100644 --- a/tests/libqos/virtio-pci.c +++ b/tests/libqos/virtio-pci.c @@ -86,7 +86,7 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr) int i; uint64_t u64 = 0; - if (qtest_big_endian()) { + if (target_big_endian()) { for (i = 0; i < 8; ++i) { u64 |= (uint64_t)qpci_io_readb(dev->pdev, (void *)(uintptr_t)addr + i) << (7 - i) * 8; diff --git a/tests/libqtest.c b/tests/libqtest.c index 6f6bdf1..d4e6bff 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -37,6 +37,7 @@ struct QTestState bool irq_level[MAX_IRQ]; GString *rx; pid_t qemu_pid; /* our child QEMU process */ + bool big_endian; }; static GHookList abrt_hooks; @@ -47,6 +48,8 @@ static struct sigaction sigact_old; g_assert_cmpint(ret, !=, -1); \ } while (0) +static int qtest_query_target_endianness(QTestState *s); + static int init_socket(const char *socket_path) { struct sockaddr_un addr; @@ -209,6 +212,10 @@ QTestState *qtest_init(const char *extra_args) kill(s->qemu_pid, SIGSTOP); } + /* ask endianness of the target */ + + s->big_endian = qtest_query_target_endianness(s); + return s; } @@ -342,6 +349,20 @@ redo: return words; } +static int qtest_query_target_endianness(QTestState *s) +{ + gchar **args; + int big_endian; + + qtest_sendf(s, "endianness\n"); + args = qtest_rsp(s, 1); + g_assert(strcmp(args[1], "big") == 0 || strcmp(args[1], "little") == 0); + big_endian = strcmp(args[1], "big") == 0; + g_strfreev(args); + + return big_endian; +} + typedef struct { JSONMessageParser parser; QDict *response; @@ -886,50 +907,7 @@ char *hmp(const char *fmt, ...) return ret; } -bool qtest_big_endian(void) +bool qtest_big_endian(QTestState *s) { - const char *arch = qtest_get_arch(); - int i; - - static const struct { - const char *arch; - bool big_endian; - } endianness[] = { - { "aarch64", false }, - { "alpha", false }, - { "arm", false }, - { "cris", false }, - { "i386", false }, - { "lm32", true }, - { "m68k", true }, - { "microblaze", true }, - { "microblazeel", false }, - { "mips", true }, - { "mips64", true }, - { "mips64el", false }, - { "mipsel", false }, - { "moxie", true }, - { "or32", true }, - { "ppc", true }, - { "ppc64", true }, - { "ppcemb", true }, - { "s390x", true }, - { "sh4", false }, - { "sh4eb", true }, - { "sparc", true }, - { "sparc64", true }, - { "unicore32", false }, - { "x86_64", false }, - { "xtensa", false }, - { "xtensaeb", true }, - {}, - }; - - for (i = 0; endianness[i].arch; i++) { - if (strcmp(endianness[i].arch, arch) == 0) { - return endianness[i].big_endian; - } - } - - return false; + return s->big_endian; } diff --git a/tests/libqtest.h b/tests/libqtest.h index f7402e0..4be1f77 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -410,6 +410,14 @@ int64_t qtest_clock_step(QTestState *s, int64_t step); int64_t qtest_clock_set(QTestState *s, int64_t val); /** + * qtest_big_endian: + * @s: QTestState instance to operate on. + * + * Returns: True if the architecture under test has a big endian configuration. + */ +bool qtest_big_endian(QTestState *s); + +/** * qtest_get_arch: * * Returns: The architecture for the QEMU executable under test. @@ -874,12 +882,14 @@ static inline int64_t clock_set(int64_t val) } /** - * qtest_big_endian: + * target_big_endian: * * Returns: True if the architecture under test has a big endian configuration. */ -bool qtest_big_endian(void); - +static inline bool target_big_endian(void) +{ + return qtest_big_endian(global_qtest); +} QDict *qmp_fd_receive(int fd); void qmp_fd_sendv(int fd, const char *fmt, va_list ap); diff --git a/tests/pxe-test.c b/tests/pxe-test.c index 5d3ddbe..34282d3 100644 --- a/tests/pxe-test.c +++ b/tests/pxe-test.c @@ -19,7 +19,7 @@ #define NETNAME "net0" -static const char *disk = "tests/pxe-test-disk.raw"; +static char disk[] = "tests/pxe-test-disk-XXXXXX"; static void test_pxe_one(const char *params, bool ipv6) { diff --git a/tests/spapr-phb-test.c b/tests/spapr-phb-test.c index 21004a7..d3522ea 100644 --- a/tests/spapr-phb-test.c +++ b/tests/spapr-phb-test.c @@ -25,7 +25,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); qtest_add_func("/spapr-phb/device", test_phb_device); - qtest_start("-device " TYPE_SPAPR_PCI_HOST_BRIDGE ",index=100"); + qtest_start("-device " TYPE_SPAPR_PCI_HOST_BRIDGE ",index=30"); ret = g_test_run(); diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c index 4b951ce..e956b9c 100644 --- a/tests/usb-hcd-uhci-test.c +++ b/tests/usb-hcd-uhci-test.c @@ -77,6 +77,9 @@ static void test_usb_storage_hotplug(void) int main(int argc, char **argv) { const char *arch = qtest_get_arch(); + const char *cmd = "-device piix3-usb-uhci,id=uhci,addr=1d.0" + " -drive id=drive0,if=none,file=/dev/null,format=raw" + " -device usb-tablet,bus=uhci.0,port=1"; int ret; g_test_init(&argc, &argv, NULL); @@ -87,13 +90,13 @@ int main(int argc, char **argv) qtest_add_func("/uhci/pci/hotplug/usb-storage", test_usb_storage_hotplug); if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qs = qtest_pc_boot("-device piix3-usb-uhci,id=uhci,addr=1d.0" - " -drive id=drive0,if=none,file=/dev/null,format=raw" - " -device usb-tablet,bus=uhci.0,port=1"); + qs = qtest_pc_boot(cmd); } else if (strcmp(arch, "ppc64") == 0) { - qs = qtest_spapr_boot("-device piix3-usb-uhci,id=uhci,addr=1d.0" - " -drive id=drive0,if=none,file=/dev/null,format=raw" - " -device usb-tablet,bus=uhci.0,port=1"); + qs = qtest_spapr_boot(cmd); + } else { + g_printerr("usb-hcd-uhci-test tests are only " + "available on x86 or ppc64\n"); + exit(EXIT_FAILURE); } ret = g_test_run(); qtest_shutdown(qs); diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index 3c4fecc..0506917 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -125,7 +125,7 @@ static inline void virtio_blk_fix_request(QVirtioBlkReq *req) bool host_endian = false; #endif - if (qtest_big_endian() != host_endian) { + if (target_big_endian() != host_endian) { req->type = bswap32(req->type); req->ioprio = bswap32(req->ioprio); req->sector = bswap64(req->sector); -- generated by git-patchbot for /home/xen/git/qemu-xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |