Re: [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs

2017-08-19 Thread David Gibson
On Fri, Aug 18, 2017 at 01:07:28PM +0200, François Revol wrote:
> Hi,
> 
> Le 18/08/2017 à 03:53, David Gibson a écrit :
> > On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> > 
> > You know I'm going to say it, right: needs a commit message.
> > 
> > What's a "plb-pcix", and what's an example of a 440 SoCs which has it.
> 
> IIRC that's the PCI(express) controller, which is not memory-mapped but
> inside the DCR address space, so accessed from the PLB.
> 
> See:
> 
> http://www.embeddeddeveloper.com/assets/processors/amcc/datasheets/PP460EX_DS2063.pdf
> 
> page 9, 13.

Sure, I can guess that.  But my point is that this is the sort of
information (including the link) that ought to be in the commit
message.

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs

2017-08-18 Thread François Revol
Hi,

Le 18/08/2017 à 03:53, David Gibson a écrit :
> On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:
> 
> You know I'm going to say it, right: needs a commit message.
> 
> What's a "plb-pcix", and what's an example of a 440 SoCs which has it.

IIRC that's the PCI(express) controller, which is not memory-mapped but
inside the DCR address space, so accessed from the PLB.

See:

http://www.embeddeddeveloper.com/assets/processors/amcc/datasheets/PP460EX_DS2063.pdf

page 9, 13.



François.



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs

2017-08-17 Thread David Gibson
On Sun, Aug 13, 2017 at 07:04:38PM +0200, BALATON Zoltan wrote:

You know I'm going to say it, right: needs a commit message.

What's a "plb-pcix", and what's an example of a 440 SoCs which has it.

This is basically a new device, so I'm pretty willing to merge for
2.11 with minimal review once rebased with the rest of the series.

Couple of comments below

[snip]
> +static void ppc440_pcix_reset(DeviceState *dev)
> +{
> +struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev);
> +int i;
> +
> +memset(s->pom, 0, sizeof(s->pom));
> +memset(s->pim, 0, sizeof(s->pim));

Is it safe to just memset() the memory region objects within the
pim/pom arrays without cleaning them up?  I'm guessing not..

> +for (i = 0; i < PPC440_PCIX_NR_PIMS; i++) {
> +s->pim[i].sa = 0xULL;
> +}
> +s->sts = 0;
> +}
> +
> +/* All pins from each slot are tied to a single board IRQ.
> + * This may need further refactoring for other boards. */
> +static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
> +{
> +int slot = pci_dev->devfn >> 3;
> +
> +DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
> +pci_dev->devfn, irq_num, slot);
> +
> +return slot - 1;
> +}
> +
> +static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level)
> +{
> +qemu_irq *pci_irqs = opaque;
> +
> +DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
> +if (irq_num < 0) {
> +fprintf(stderr, "%s: PCI irq %d\n", __func__, irq_num);

Use report_error() please.

> +return;
> +}
> +qemu_set_irq(pci_irqs[irq_num], level);
> +}
> +
> +static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int 
> devfn)
> +{
> +PPC440PCIXState *s = opaque;
> +
> +return &s->bm_as;
> +}
> +
> +static int ppc440_pcix_initfn(SysBusDevice *dev)
> +{
> +PPC440PCIXState *s;
> +PCIHostState *h;
> +int i;
> +
> +h = PCI_HOST_BRIDGE(dev);
> +s = PPC440_PCIX_HOST_BRIDGE(dev);
> +
> +for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
> +sysbus_init_irq(dev, &s->irq[i]);
> +}
> +
> +memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", 
> UINT64_MAX);
> +h->bus = pci_register_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
> + ppc440_pcix_map_irq, s->irq, &s->busmem,
> + get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
> +
> +s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), 
> "ppc4xx-host-bridge");
> +
> +memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
> +memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
> +address_space_init(&s->bm_as, &s->bm, "pci-bm");
> +pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);
> +
> +memory_region_init(&s->container, OBJECT(s), "pci-container", 
> PCI_ALL_SIZE);
> +memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h,
> +  "pci-conf-idx", 4);
> +memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h,
> +  "pci-conf-data", 4);
> +memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
> +  "pci.reg", PPC440_REG_SIZE);
> +memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
> +memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
> +memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
> +sysbus_init_mmio(dev, &s->container);
> +
> +return 0;
> +}
> +
> +static void ppc440_pcix_class_init(ObjectClass *klass, void *data)
> +{
> +SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
> +DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +k->init = ppc440_pcix_initfn;
> +dc->reset = ppc440_pcix_reset;
> +}
> +
> +static const TypeInfo ppc440_pcix_info = {
> +.name  = TYPE_PPC440_PCIX_HOST_BRIDGE,
> +.parent= TYPE_PCI_HOST_BRIDGE,
> +.instance_size = sizeof(PPC440PCIXState),
> +.class_init= ppc440_pcix_class_init,
> +};
> +
> +static void ppc440_pcix_register_types(void)
> +{
> +type_register_static(&ppc440_pcix_info);
> +}
> +
> +type_init(ppc440_pcix_register_types)

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


[Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs

2017-08-13 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 hw/ppc/Makefile.objs |   2 +-
 hw/ppc/ppc440_pcix.c | 506 +++
 2 files changed, 507 insertions(+), 1 deletion(-)
 create mode 100644 hw/ppc/ppc440_pcix.c

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 2077216..9c5d58a 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -13,7 +13,7 @@ endif
 obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
 # PowerPC 4xx boards
 obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
-obj-y += ppc4xx_pci.o ppc4xx_i2c.o
+obj-y += ppc4xx_pci.o ppc440_pcix.o ppc4xx_i2c.o
 # PReP
 obj-$(CONFIG_PREP) += prep.o
 obj-$(CONFIG_PREP) += prep_systemio.o
diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c
new file mode 100644
index 000..3abd0d0
--- /dev/null
+++ b/hw/ppc/ppc440_pcix.c
@@ -0,0 +1,506 @@
+/*
+ * Emulation of the ibm,plb-pcix PCI controller
+ * This is found in some 440 SoCs e.g. the 460EX.
+ *
+ * Copyright (c) 2016 BALATON Zoltan
+ *
+ * Derived from ppc4xx_pci.c and pci-host/ppce500.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc4xx.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "exec/address-spaces.h"
+
+/*#define DEBUG_PCI*/
+
+#ifdef DEBUG_PCI
+#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__);
+#else
+#define DPRINTF(fmt, ...)
+#endif /* DEBUG */
+
+struct PLBOutMap {
+uint64_t la;
+uint64_t pcia;
+uint32_t sa;
+MemoryRegion mr;
+};
+
+struct PLBInMap {
+uint64_t sa;
+uint64_t la;
+MemoryRegion mr;
+};
+
+#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host"
+#define PPC440_PCIX_HOST_BRIDGE(obj) \
+OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE)
+
+#define PPC440_PCIX_NR_POMS 3
+#define PPC440_PCIX_NR_PIMS 3
+
+typedef struct PPC440PCIXState {
+PCIHostState parent_obj;
+
+PCIDevice *dev;
+struct PLBOutMap pom[PPC440_PCIX_NR_POMS];
+struct PLBInMap pim[PPC440_PCIX_NR_PIMS];
+uint32_t sts;
+qemu_irq irq[PCI_NUM_PINS];
+AddressSpace bm_as;
+MemoryRegion bm;
+
+MemoryRegion container;
+MemoryRegion iomem;
+MemoryRegion busmem;
+} PPC440PCIXState;
+
+#define PPC440_REG_BASE 0x8
+#define PPC440_REG_SIZE 0xff
+
+#define PCIC0_CFGADDR   0x0
+#define PCIC0_CFGDATA   0x4
+
+#define PCIX0_POM0LAL   0x68
+#define PCIX0_POM0LAH   0x6c
+#define PCIX0_POM0SA0x70
+#define PCIX0_POM0PCIAL 0x74
+#define PCIX0_POM0PCIAH 0x78
+#define PCIX0_POM1LAL   0x7c
+#define PCIX0_POM1LAH   0x80
+#define PCIX0_POM1SA0x84
+#define PCIX0_POM1PCIAL 0x88
+#define PCIX0_POM1PCIAH 0x8c
+#define PCIX0_POM2SA0x90
+
+#define PCIX0_PIM0SAL   0x98
+#define PCIX0_PIM0LAL   0x9c
+#define PCIX0_PIM0LAH   0xa0
+#define PCIX0_PIM1SA0xa4
+#define PCIX0_PIM1LAL   0xa8
+#define PCIX0_PIM1LAH   0xac
+#define PCIX0_PIM2SAL   0xb0
+#define PCIX0_PIM2LAL   0xb4
+#define PCIX0_PIM2LAH   0xb8
+#define PCIX0_PIM0SAH   0xf8
+#define PCIX0_PIM2SAH   0xfc
+
+#define PCIX0_STS   0xe0
+
+#define PCI_ALL_SIZE(PPC440_REG_BASE + PPC440_REG_SIZE)
+
+/* DMA mapping */
+static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx)
+{
+MemoryRegion *mem = &s->pim[idx].mr;
+char *name;
+uint64_t size;
+
+if (memory_region_is_mapped(mem)) {
+/* Before we modify anything, unmap and destroy the region */
+memory_region_del_subregion(&s->bm, mem);
+object_unparent(OBJECT(mem));
+}
+
+if (!(s->pim[idx].sa & 1)) {
+/* Not enabled, nothing to do */
+return;
+}
+
+name = g_strdup_printf("PCI Inbound Window %d", idx);
+size = ~(s->pim[idx].sa & ~7ULL) + 1;
+memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(),
+ s->pim[idx].la, size);
+memory_region_add_subregion_overlap(&s->bm, 0, mem, -1);
+g_free(name);
+
+DPRINTF("%s: Added window %d of size=%#"PRIx64" to CPU=%#"PRIx64"\n",
+__func__, idx, size, s->pim[idx].la);
+}
+
+/* BAR mapping */
+static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx)
+{
+MemoryRegion *mem = &s->pom[idx].mr;
+MemoryRegion *address_space_mem = get_system_memory();
+char *name;
+uint32_t size;
+
+if (memory_region_is