qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH 1/2] hw/pci-host: add a generic PCI host
@ 2014-06-16 12:55 Rob Herring
  2014-06-16 12:55 ` [Qemu-devel] [RFC PATCH 2/2] hw/arm/virt: Add generic PCI host device Rob Herring
  0 siblings, 1 reply; 2+ messages in thread
From: Rob Herring @ 2014-06-16 12:55 UTC (permalink / raw)
  To: Claudio Fontana, Peter Maydell; +Cc: Rob Herring, qemu-devel

From: Rob Herring <rob.herring@linaro.org>

Add a generic PCI host controller for virtual platforms. This is for ARM
virtual platforms at the moment, but has nothing ARM specific. This
matches the generic PCI host driver added in the 3.16 kernel.

Functioning with OHCI (usb disk), but not LSI SCSI which doesn't find a
disk.

TODO:
- The memory region size and alias offset for the io and memory space
are hardcoded and need to be set from the machine and must match the
values in the DT ranges. Probably need to make these properties.
- More space for PCI memory space needed?
- MSI support - Needs GICv2M or GICv3 support.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
---
 hw/pci-host/Makefile.objs |   2 +-
 hw/pci-host/generic-pci.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 183 insertions(+), 1 deletion(-)
 create mode 100644 hw/pci-host/generic-pci.c

diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
index bb65f9c..8ef9fac 100644
--- a/hw/pci-host/Makefile.objs
+++ b/hw/pci-host/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += pam.o
+common-obj-y += pam.o generic-pci.o
 
 # PPC devices
 common-obj-$(CONFIG_PREP_PCI) += prep.o
diff --git a/hw/pci-host/generic-pci.c b/hw/pci-host/generic-pci.c
new file mode 100644
index 0000000..1632e46
--- /dev/null
+++ b/hw/pci-host/generic-pci.c
@@ -0,0 +1,182 @@
+/*
+ * Generic PCI host controller
+ *
+ * Copyright (c) 2014 Linaro, Ltd.
+ * Author: Rob Herring <rob.herring@linaro.org>
+ *
+ * Based on ARM Versatile PCI controller (hw/pci-host/versatile.c):
+ * Copyright (c) 2006-2009 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_host.h"
+#include "exec/address-spaces.h"
+
+typedef struct {
+    PCIHostState parent_obj;
+
+    qemu_irq irq[4];
+    MemoryRegion mem_config;
+    /* Containers representing the PCI address spaces */
+    MemoryRegion pci_io_space;
+    MemoryRegion pci_mem_space;
+    /* Alias regions into PCI address spaces which we expose as sysbus regions.
+     * The offsets into pci_mem_space are controlled by the imap registers.
+     */
+    MemoryRegion pci_io_window;
+    MemoryRegion pci_mem_window;
+    PCIBus pci_bus;
+    PCIDevice pci_dev;
+} PCIVPBState;
+
+
+static const VMStateDescription pci_generic_host_vmstate = {
+    .name = "generic-host-pci",
+    .version_id = 1,
+    .minimum_version_id = 1,
+};
+
+#define TYPE_GENERIC_PCI "generic_pci"
+#define PCI_GEN(obj) \
+    OBJECT_CHECK(PCIVPBState, (obj), TYPE_GENERIC_PCI)
+
+#define TYPE_GENERIC_PCI_HOST "generic_pci_host"
+#define PCI_GEN_HOST(obj) \
+    OBJECT_CHECK(PCIDevice, (obj), TYPE_GENERIC_PCIHOST)
+
+
+static void pci_cam_config_write(void *opaque, hwaddr addr,
+                                 uint64_t val, unsigned size)
+{
+    PCIVPBState *s = opaque;
+    pci_data_write(&s->pci_bus, addr, val, size);
+}
+
+static uint64_t pci_cam_config_read(void *opaque, hwaddr addr, unsigned size)
+{
+    PCIVPBState *s = opaque;
+    uint32_t val;
+    val = pci_data_read(&s->pci_bus, addr, size);
+    return val;
+}
+
+static const MemoryRegionOps pci_vpb_config_ops = {
+    .read = pci_cam_config_read,
+    .write = pci_cam_config_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void pci_generic_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pic = opaque;
+    qemu_set_irq(pic[irq_num], level);
+}
+
+static void pci_generic_host_init(Object *obj)
+{
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    PCIVPBState *s = PCI_GEN(obj);
+
+    memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 0x10000);
+    memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32);
+
+    pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), "pci",
+                        &s->pci_mem_space, &s->pci_io_space,
+                        PCI_DEVFN(0, 0), TYPE_PCIE_BUS);
+    h->bus = &s->pci_bus;
+
+    object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_GENERIC_PCI_HOST);
+    qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus));
+}
+
+static void pci_generic_host_realize(DeviceState *dev, Error **errp)
+{
+    PCIVPBState *s = PCI_GEN(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        sysbus_init_irq(sbd, &s->irq[i]);
+    }
+
+    pci_bus_irqs(&s->pci_bus, pci_generic_set_irq, pci_swizzle_map_irq_fn,
+                 s->irq, 4);
+
+    /* Our memory regions are:
+     * 0 : PCI config window
+     * 1 : PCI IO window
+     * 2 : PCI memory windows
+     */
+    memory_region_init_io(&s->mem_config, OBJECT(s), &pci_vpb_config_ops, s,
+                          "pci-config", 0x1000000);
+    sysbus_init_mmio(sbd, &s->mem_config);
+
+    /* The window into I/O space is always into a fixed base address;
+     * its size is the same for both realview and versatile.
+     */
+    memory_region_init_alias(&s->pci_io_window, OBJECT(s), "pci-io-win",
+                             &s->pci_io_space, 0, 0x10000);
+    sysbus_init_mmio(sbd, &s->pci_io_space);
+
+    /* Create the alias regions corresponding to our three windows onto
+     * PCI memory space. The sizes vary from board to board; the base
+     * offsets are guest controllable via the IMAP registers.
+     */
+    memory_region_init_alias(&s->pci_mem_window, OBJECT(s), "pci-mem-win",
+                             &s->pci_mem_space, 0x12000000, 0x2e000000);
+    sysbus_init_mmio(sbd, &s->pci_mem_window);
+
+    /* TODO Remove once realize propagates to child devices. */
+    object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
+}
+
+static void pci_generic_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->vendor_id = PCI_VENDOR_ID_REDHAT;
+    k->device_id = 0x1234;
+    k->class_id = PCI_CLASS_PROCESSOR_CO;
+    /*
+     * PCI-facing part of the host bridge, not usable without the
+     * host-facing part, which can't be device_add'ed, yet.
+     */
+    dc->cannot_instantiate_with_device_add_yet = true;
+}
+
+static const TypeInfo pci_generic_host_info = {
+    .name          = TYPE_GENERIC_PCI_HOST,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init    = pci_generic_host_class_init,
+};
+
+static void pci_generic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = pci_generic_host_realize;
+    dc->vmsd = &pci_generic_host_vmstate;
+}
+
+static const TypeInfo pci_generic_info = {
+    .name          = TYPE_GENERIC_PCI,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(PCIVPBState),
+    .instance_init = pci_generic_host_init,
+    .class_init    = pci_generic_class_init,
+};
+
+static void generic_pci_host_register_types(void)
+{
+    type_register_static(&pci_generic_info);
+    type_register_static(&pci_generic_host_info);
+}
+
+type_init(generic_pci_host_register_types)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [Qemu-devel] [RFC PATCH 2/2] hw/arm/virt: Add generic PCI host device
  2014-06-16 12:55 [Qemu-devel] [RFC PATCH 1/2] hw/pci-host: add a generic PCI host Rob Herring
@ 2014-06-16 12:55 ` Rob Herring
  0 siblings, 0 replies; 2+ messages in thread
From: Rob Herring @ 2014-06-16 12:55 UTC (permalink / raw)
  To: Claudio Fontana, Peter Maydell; +Cc: Rob Herring, qemu-devel

From: Rob Herring <rob.herring@linaro.org>

Enable the generic PCI host on ARM virt platform.

TODO:
The memory regions aliases are hard coded in the host ATM. These probably
need to become QOM properties.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
---
 hw/arm/virt.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ea4f02d..951f012 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -37,6 +37,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
 #include "hw/boards.h"
+#include "hw/pci/pci.h"
 #include "exec/address-spaces.h"
 #include "qemu/bitops.h"
 #include "qemu/error-report.h"
@@ -65,6 +66,7 @@ enum {
     VIRT_GIC_CPU,
     VIRT_UART,
     VIRT_MMIO,
+    VIRT_PCI_CFG,
 };
 
 typedef struct MemMapEntry {
@@ -104,6 +106,7 @@ static const MemMapEntry a15memmap[] = {
     [VIRT_MMIO] = { 0xa000000, 0x200 },
     /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
     /* 0x10000000 .. 0x40000000 reserved for PCI */
+    [VIRT_PCI_CFG] = { 0x10000000, 0x01000000 },
     [VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 },
 };
 
@@ -340,6 +343,58 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
     g_free(nodename);
 }
 
+static void create_pci_host(const VirtBoardInfo *vbi, qemu_irq *pic)
+{
+    PCIBus *pci_bus;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    uint32_t gic_phandle;
+    char *nodename;
+    hwaddr base = vbi->memmap[VIRT_PCI_CFG].base;
+    hwaddr size = vbi->memmap[VIRT_PCI_CFG].size;
+
+    nodename = g_strdup_printf("/pci@%" PRIx64, base);
+    qemu_fdt_add_subnode(vbi->fdt, nodename);
+    qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible",
+                            "pci-host-cam-generic");
+    qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "pci");
+    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#address-cells", 0x3);
+    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#size-cells", 0x2);
+    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 0x1);
+
+    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", 2, base, 2, size);
+
+    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges",
+        1, 0x01000000, 2, 0x00000000, 2, 0x11000000, 2, 0x00010000,
+        1, 0x02000000, 2, 0x12000000, 2, 0x12000000, 2, 0x2e000000);
+
+    gic_phandle = qemu_fdt_get_phandle(vbi->fdt, "/intc");
+    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "interrupt-map-mask",
+        1, 0xf800, 1, 0x0, 1, 0x0, 1, 0x7);
+    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "interrupt-map",
+        1, 0x0000, 2, 0x00000000, 1, 0x1, 1, gic_phandle, 1, 0, 1, 0x4, 1, 0x1,
+        1, 0x0800, 2, 0x00000000, 1, 0x1, 1, gic_phandle, 1, 0, 1, 0x5, 1, 0x1,
+        1, 0x1000, 2, 0x00000000, 1, 0x1, 1, gic_phandle, 1, 0, 1, 0x6, 1, 0x1,
+        1, 0x1800, 2, 0x00000000, 1, 0x1, 1, gic_phandle, 1, 0, 1, 0x7, 1, 0x1);
+
+    dev = qdev_create(NULL, "generic_pci");
+    busdev = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(busdev, 0, base);       /* PCI config */
+    sysbus_mmio_map(busdev, 1, 0x11000000); /* PCI I/O */
+    sysbus_mmio_map(busdev, 2, 0x12000000); /* PCI memory window */
+    sysbus_connect_irq(busdev, 0, pic[4]);
+    sysbus_connect_irq(busdev, 1, pic[5]);
+    sysbus_connect_irq(busdev, 2, pic[6]);
+    sysbus_connect_irq(busdev, 3, pic[7]);
+
+    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
+    pci_create_simple(pci_bus, -1, "pci-ohci");
+    pci_create_simple(pci_bus, -1, "lsi53c895a");
+
+    g_free(nodename);
+}
+
 static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
 {
     int i;
@@ -455,6 +510,8 @@ static void machvirt_init(QEMUMachineInitArgs *args)
 
     create_uart(vbi, pic);
 
+    create_pci_host(vbi, pic);
+
     /* Create mmio transports, so the user can create virtio backends
      * (which will be automatically plugged in to the transports). If
      * no backend is created the transport will just sit harmlessly idle.
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2014-06-16 12:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-16 12:55 [Qemu-devel] [RFC PATCH 1/2] hw/pci-host: add a generic PCI host Rob Herring
2014-06-16 12:55 ` [Qemu-devel] [RFC PATCH 2/2] hw/arm/virt: Add generic PCI host device Rob Herring

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).