* [Qemu-devel] [PATCH v4 0/4] ARM: Add support for a generic PCI Express host bridge @ 2015-02-05 14:55 Alexander Graf 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 1/4] pci: Allocate PCIe host bridge PCI ID Alexander Graf ` (3 more replies) 0 siblings, 4 replies; 9+ messages in thread From: Alexander Graf @ 2015-02-05 14:55 UTC (permalink / raw) To: qemu-devel Cc: Peter Maydell, ard.biesheuvel, rob.herring, mst, claudio.fontana, stuart.yoder, a.rigo Linux implements a nice binding to describe a "generic" PCI Express host bridge using only device tree. This patch set adds enough emulation logic to expose the parts that are "generic" as a simple sysbus device and maps it into ARM's virt machine. With this patch set, we can finally spawn PCI devices on ARM VMs. I was able to have a fully DRM enabled virtual machine with VGA, e1000 and XHCI (for keyboard and mouse) up and working. It's only a small step for QEMU, but a big step for ARM VM's usability. v1 -> v2: - Add documentation links - Remove mmio_window_size - Add define for pci range types - Use 4 PCI INTX IRQ lines v2 -> v3: - Update patch description - Increase ecam region to full size - Expose number of irqs via define - Update header description - Update host bridge qom description string - Use new Red Hat PCIe host bridge PCI ID - Coding style fixes - Map ECAM space via alias to limit its size - Increase ECAM size to 16 buses - Use GPEX IRQ number define - Align ECAM region, Document region allocation better - Move interrupt-map into irq map function - s/FDT_PCI_RANGE_TYPE/FDT_PCI_RANGE_TYPE_MASK/ v3 -> v4: - update memory map comment Alexander Graf (4): pci: Allocate PCIe host bridge PCI ID pci: Add generic PCIe host bridge arm: Add PCIe host bridge in virt machine pci: Move PCI VGA to pci.mak default-configs/alpha-softmmu.mak | 2 - default-configs/arm-softmmu.mak | 2 + default-configs/i386-softmmu.mak | 2 - default-configs/mips-softmmu.mak | 2 - default-configs/mips64-softmmu.mak | 2 - default-configs/mips64el-softmmu.mak | 2 - default-configs/mipsel-softmmu.mak | 2 - default-configs/pci.mak | 2 + default-configs/ppc-softmmu.mak | 2 - default-configs/ppc64-softmmu.mak | 2 - default-configs/ppcemb-softmmu.mak | 2 - default-configs/sparc64-softmmu.mak | 2 - default-configs/x86_64-softmmu.mak | 2 - hw/arm/virt.c | 135 ++++++++++++++++++++++++++++-- hw/pci-host/Makefile.objs | 1 + hw/pci-host/gpex.c | 154 +++++++++++++++++++++++++++++++++++ include/hw/pci-host/gpex.h | 56 +++++++++++++ include/hw/pci/pci.h | 1 + include/sysemu/device_tree.h | 9 ++ 19 files changed, 355 insertions(+), 27 deletions(-) create mode 100644 hw/pci-host/gpex.c create mode 100644 include/hw/pci-host/gpex.h -- 1.7.12.4 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v4 1/4] pci: Allocate PCIe host bridge PCI ID 2015-02-05 14:55 [Qemu-devel] [PATCH v4 0/4] ARM: Add support for a generic PCI Express host bridge Alexander Graf @ 2015-02-05 14:55 ` Alexander Graf 2015-02-05 15:03 ` Peter Maydell 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 2/4] pci: Add generic PCIe host bridge Alexander Graf ` (2 subsequent siblings) 3 siblings, 1 reply; 9+ messages in thread From: Alexander Graf @ 2015-02-05 14:55 UTC (permalink / raw) To: qemu-devel Cc: Peter Maydell, ard.biesheuvel, rob.herring, mst, claudio.fontana, stuart.yoder, a.rigo We are going to introduce a PCIe host controller that doesn't exist that way in real hardware, but still needs to expose some PCIe root device which has PCI IDs. Allocate a PCI ID in the Red Hat space that we use for other devices of this kind. Signed-off-by: Alexander Graf <agraf@suse.de> --- include/hw/pci/pci.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 97a83d3..bdee464 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -89,6 +89,7 @@ #define PCI_DEVICE_ID_REDHAT_SERIAL4 0x0004 #define PCI_DEVICE_ID_REDHAT_TEST 0x0005 #define PCI_DEVICE_ID_REDHAT_SDHCI 0x0007 +#define PCI_DEVICE_ID_REDHAT_PCIE_HOST 0x0008 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100 #define FMT_PCIBUS PRIx64 -- 1.7.12.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v4 1/4] pci: Allocate PCIe host bridge PCI ID 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 1/4] pci: Allocate PCIe host bridge PCI ID Alexander Graf @ 2015-02-05 15:03 ` Peter Maydell 0 siblings, 0 replies; 9+ messages in thread From: Peter Maydell @ 2015-02-05 15:03 UTC (permalink / raw) To: Alexander Graf Cc: Rob Herring, Michael S. Tsirkin, QEMU Developers, Ard Biesheuvel, Claudio Fontana, Alvise Rigo, Stuart Yoder, Paolo Bonzini On 5 February 2015 at 14:55, Alexander Graf <agraf@suse.de> wrote: > We are going to introduce a PCIe host controller that doesn't exist that > way in real hardware, but still needs to expose some PCIe root device which > has PCI IDs. > > Allocate a PCI ID in the Red Hat space that we use for other devices of this > kind. > > Signed-off-by: Alexander Graf <agraf@suse.de> > --- > include/hw/pci/pci.h | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h > index 97a83d3..bdee464 100644 > --- a/include/hw/pci/pci.h > +++ b/include/hw/pci/pci.h > @@ -89,6 +89,7 @@ > #define PCI_DEVICE_ID_REDHAT_SERIAL4 0x0004 > #define PCI_DEVICE_ID_REDHAT_TEST 0x0005 > #define PCI_DEVICE_ID_REDHAT_SDHCI 0x0007 > +#define PCI_DEVICE_ID_REDHAT_PCIE_HOST 0x0008 > #define PCI_DEVICE_ID_REDHAT_QXL 0x0100 > > #define FMT_PCIBUS PRIx64 Reviewed-by: Peter Maydell <peter.maydell@linaro.org> thanks -- PMM ^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v4 2/4] pci: Add generic PCIe host bridge 2015-02-05 14:55 [Qemu-devel] [PATCH v4 0/4] ARM: Add support for a generic PCI Express host bridge Alexander Graf 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 1/4] pci: Allocate PCIe host bridge PCI ID Alexander Graf @ 2015-02-05 14:55 ` Alexander Graf 2015-02-05 15:30 ` Peter Maydell 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 3/4] arm: Add PCIe host bridge in virt machine Alexander Graf 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 4/4] pci: Move PCI VGA to pci.mak Alexander Graf 3 siblings, 1 reply; 9+ messages in thread From: Alexander Graf @ 2015-02-05 14:55 UTC (permalink / raw) To: qemu-devel Cc: Peter Maydell, ard.biesheuvel, rob.herring, mst, claudio.fontana, stuart.yoder, a.rigo With simple exposure of MMFG, ioport window, mmio window and an IRQ line we can successfully create a workable PCIe host bridge that can be mapped anywhere and only needs to get described to the OS using whatever means it likes. This patch implements such a "generic" host bridge. It handles 4 legacy IRQ lines. MSIs need to be handled external to the host bridge. This device is particularly useful for the "pci-host-ecam-generic" driver in Linux. Signed-off-by: Alexander Graf <agraf@suse.de> Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com> Tested-by: Claudio Fontana <claudio.fontana@huawei.com> --- v1 -> v2: - Add documentation links - Remove mmio_window_size - Expose 4 INTX IRQs v2 -> v3: - Update patch description - Increase ecam region to full size - Expose number of irqs via define - Update header description - Update host bridge qom description string - Use new Red Hat PCIe host bridge PCI ID --- hw/pci-host/Makefile.objs | 1 + hw/pci-host/gpex.c | 154 +++++++++++++++++++++++++++++++++++++++++++++ include/hw/pci-host/gpex.h | 56 +++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 hw/pci-host/gpex.c create mode 100644 include/hw/pci-host/gpex.h diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs index bb65f9c..45f1f0e 100644 --- a/hw/pci-host/Makefile.objs +++ b/hw/pci-host/Makefile.objs @@ -15,3 +15,4 @@ common-obj-$(CONFIG_PCI_APB) += apb.o common-obj-$(CONFIG_FULONG) += bonito.o common-obj-$(CONFIG_PCI_PIIX) += piix.o common-obj-$(CONFIG_PCI_Q35) += q35.o +common-obj-$(CONFIG_PCI_GENERIC) += gpex.o diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c new file mode 100644 index 0000000..9d8fb5a --- /dev/null +++ b/hw/pci-host/gpex.c @@ -0,0 +1,154 @@ +/* + * QEMU Generic PCI Express Bridge Emulation + * + * Copyright (C) 2015 Alexander Graf <agraf@suse.de> + * + * Code loosely based on q35.c. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Check out these documents for more information on the device: + * + * http://www.kernel.org/doc/Documentation/devicetree/bindings/pci/host-generic-pci.txt + * http://www.firmware.org/1275/practice/imap/imap0_9d.pdf + */ +#include "hw/hw.h" +#include "hw/pci-host/gpex.h" + +/**************************************************************************** + * GPEX host + */ + +static void gpex_set_irq(void *opaque, int irq_num, int level) +{ + GPEXHost *s = opaque; + + qemu_set_irq(s->irq[irq_num], level); +} + +static void gpex_host_realize(DeviceState *dev, Error **errp) +{ + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + GPEXHost *s = GPEX_HOST(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev); + int i; + + pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX); + memory_region_init(&s->io_mmio, OBJECT(s), "gpex_mmio", UINT64_MAX); + memory_region_init(&s->io_ioport, OBJECT(s), "gpex_ioport", 64 * 1024); + + sysbus_init_mmio(sbd, &pex->mmio); + sysbus_init_mmio(sbd, &s->io_mmio); + sysbus_init_mmio(sbd, &s->io_ioport); + for (i = 0; i < GPEX_NUM_IRQS; i++) { + sysbus_init_irq(sbd, &s->irq[i]); + } + + pci->bus = pci_register_bus(dev, "pcie.0", gpex_set_irq, + pci_swizzle_map_irq_fn, s, &s->io_mmio, + &s->io_ioport, 0, 4, TYPE_PCIE_BUS); + + qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus)); + qdev_init_nofail(DEVICE(&s->gpex_root)); +} + +static const char *gpex_host_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + return "0000:00"; +} + +static void gpex_host_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); + + hc->root_bus_path = gpex_host_root_bus_path; + dc->realize = gpex_host_realize; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->fw_name = "pci"; +} + +static void gpex_host_initfn(Object *obj) +{ + GPEXHost *s = GPEX_HOST(obj); + GPEXRootState *root = &s->gpex_root; + + object_initialize(root, sizeof(*root), TYPE_GPEX_ROOT_DEVICE); + object_property_add_child(obj, "gpex_root", OBJECT(root), NULL); + qdev_prop_set_uint32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); + qdev_prop_set_bit(DEVICE(root), "multifunction", false); +} + +static const TypeInfo gpex_host_info = { + .name = TYPE_GPEX_HOST, + .parent = TYPE_PCIE_HOST_BRIDGE, + .instance_size = sizeof(GPEXHost), + .instance_init = gpex_host_initfn, + .class_init = gpex_host_class_init, +}; + +/**************************************************************************** + * GPEX Root D0:F0 + */ + +static const VMStateDescription vmstate_gpex_root = { + .name = "gpex_root", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(parent_obj, GPEXRootState), + VMSTATE_END_OF_LIST() + } +}; + +static void gpex_root_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->desc = "QEMU generic PCIe host bridge"; + dc->vmsd = &vmstate_gpex_root; + k->vendor_id = PCI_VENDOR_ID_REDHAT; + k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_HOST; + k->revision = 0; + k->class_id = PCI_CLASS_BRIDGE_HOST; + /* + * 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 gpex_root_info = { + .name = TYPE_GPEX_ROOT_DEVICE, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(GPEXRootState), + .class_init = gpex_root_class_init, +}; + +static void gpex_register(void) +{ + type_register_static(&gpex_root_info); + type_register_static(&gpex_host_info); +} + +type_init(gpex_register) diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h new file mode 100644 index 0000000..68c9348 --- /dev/null +++ b/include/hw/pci-host/gpex.h @@ -0,0 +1,56 @@ +/* + * QEMU Generic PCI Express Bridge Emulation + * + * Copyright (C) 2015 Alexander Graf <agraf@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#ifndef HW_GPEX_H +#define HW_GPEX_H + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" + +#define TYPE_GPEX_HOST "gpex-pcihost" +#define GPEX_HOST(obj) \ + OBJECT_CHECK(GPEXHost, (obj), TYPE_GPEX_HOST) + +#define TYPE_GPEX_ROOT_DEVICE "gpex-root" +#define MCH_PCI_DEVICE(obj) \ + OBJECT_CHECK(GPEXRootState, (obj), TYPE_GPEX_ROOT_DEVICE) + +#define GPEX_NUM_IRQS 4 + +typedef struct GPEXRootState { + /*< private >*/ + PCIDevice parent_obj; + /*< public >*/ +} GPEXRootState; + +typedef struct GPEXHost { + /*< private >*/ + PCIExpressHost parent_obj; + /*< public >*/ + + GPEXRootState gpex_root; + + MemoryRegion io_ioport; + MemoryRegion io_mmio; + qemu_irq irq[GPEX_NUM_IRQS]; +} GPEXHost; + +#endif /* HW_GPEX_H */ -- 1.7.12.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v4 2/4] pci: Add generic PCIe host bridge 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 2/4] pci: Add generic PCIe host bridge Alexander Graf @ 2015-02-05 15:30 ` Peter Maydell 0 siblings, 0 replies; 9+ messages in thread From: Peter Maydell @ 2015-02-05 15:30 UTC (permalink / raw) To: Alexander Graf Cc: Rob Herring, Michael S. Tsirkin, QEMU Developers, Ard Biesheuvel, Claudio Fontana, Alvise Rigo, Stuart Yoder On 5 February 2015 at 14:55, Alexander Graf <agraf@suse.de> wrote: > With simple exposure of MMFG, ioport window, mmio window and an IRQ line we > can successfully create a workable PCIe host bridge that can be mapped anywhere > and only needs to get described to the OS using whatever means it likes. > > This patch implements such a "generic" host bridge. It handles 4 legacy IRQ > lines. MSIs need to be handled external to the host bridge. > > This device is particularly useful for the "pci-host-ecam-generic" driver in > Linux. > > Signed-off-by: Alexander Graf <agraf@suse.de> > Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com> > Tested-by: Claudio Fontana <claudio.fontana@huawei.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> thanks -- PMM ^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v4 3/4] arm: Add PCIe host bridge in virt machine 2015-02-05 14:55 [Qemu-devel] [PATCH v4 0/4] ARM: Add support for a generic PCI Express host bridge Alexander Graf 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 1/4] pci: Allocate PCIe host bridge PCI ID Alexander Graf 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 2/4] pci: Add generic PCIe host bridge Alexander Graf @ 2015-02-05 14:55 ` Alexander Graf 2015-02-05 15:49 ` Peter Maydell 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 4/4] pci: Move PCI VGA to pci.mak Alexander Graf 3 siblings, 1 reply; 9+ messages in thread From: Alexander Graf @ 2015-02-05 14:55 UTC (permalink / raw) To: qemu-devel Cc: Peter Maydell, ard.biesheuvel, rob.herring, mst, claudio.fontana, stuart.yoder, a.rigo Now that we have a working "generic" PCIe host bridge driver, we can plug it into ARM's virt machine to always have PCIe available to normal ARM VMs. I've successfully managed to expose a Bochs VGA device, XHCI and an e1000 into an AArch64 VM with this and they all lived happily ever after. Signed-off-by: Alexander Graf <agraf@suse.de> Tested-by: Claudio Fontana <claudio.fontana@huawei.com> --- Linux 3.19 only supports the generic PCIe host bridge driver for 32bit ARM systems. If you want to use it with AArch64 guests, please apply the following patch or wait until upstream cleaned up the code properly: http://csgraf.de/agraf/pci/pci-3.19.patch v1 -> v2: - Add define for pci range types - Remove mmio_window_size - Use 4 PCI INTX IRQ lines v2 -> v3: - Coding style fixes - Map ECAM space via alias to limit its size - Increase ECAM size to 16 buses - Use GPEX IRQ number define - Align ECAM region, Document region allocation better - Move interrupt-map into irq map function - s/FDT_PCI_RANGE_TYPE/FDT_PCI_RANGE_TYPE_MASK/ v3 -> v4: - update memory map comment --- default-configs/arm-softmmu.mak | 2 + hw/arm/virt.c | 135 ++++++++++++++++++++++++++++++++++++++-- include/sysemu/device_tree.h | 9 +++ 3 files changed, 141 insertions(+), 5 deletions(-) diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index f3513fa..7671ee2 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -82,6 +82,8 @@ CONFIG_ZYNQ=y CONFIG_VERSATILE_PCI=y CONFIG_VERSATILE_I2C=y +CONFIG_PCI_GENERIC=y + CONFIG_SDHCI=y CONFIG_INTEGRATOR_DEBUG=y diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 2353440..cf53947 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -42,6 +42,7 @@ #include "exec/address-spaces.h" #include "qemu/bitops.h" #include "qemu/error-report.h" +#include "hw/pci-host/gpex.h" #define NUM_VIRTIO_TRANSPORTS 32 @@ -69,6 +70,7 @@ enum { VIRT_MMIO, VIRT_RTC, VIRT_FW_CFG, + VIRT_PCIE, }; typedef struct MemMapEntry { @@ -129,13 +131,21 @@ static const MemMapEntry a15memmap[] = { [VIRT_FW_CFG] = { 0x09020000, 0x0000000a }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ - /* 0x10000000 .. 0x40000000 reserved for PCI */ + /* + * PCIE verbose map: + * + * MMIO window { 0x10000000, 0x2eff0000 }, + * PIO window { 0x3eff0000, 0x00010000 }, + * ECAM { 0x3f000000, 0x01000000 }, + */ + [VIRT_PCIE] = { 0x10000000, 0x30000000 }, [VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 }, }; static const int a15irqmap[] = { [VIRT_UART] = 1, [VIRT_RTC] = 2, + [VIRT_PCIE] = 3, /* ... to 6 */ [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ }; @@ -312,7 +322,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) } } -static void fdt_add_gic_node(const VirtBoardInfo *vbi) +static uint32_t fdt_add_gic_node(const VirtBoardInfo *vbi) { uint32_t gic_phandle; @@ -331,9 +341,11 @@ static void fdt_add_gic_node(const VirtBoardInfo *vbi) 2, vbi->memmap[VIRT_GIC_CPU].base, 2, vbi->memmap[VIRT_GIC_CPU].size); qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle); + + return gic_phandle; } -static void create_gic(const VirtBoardInfo *vbi, qemu_irq *pic) +static uint32_t create_gic(const VirtBoardInfo *vbi, qemu_irq *pic) { /* We create a standalone GIC v2 */ DeviceState *gicdev; @@ -380,7 +392,7 @@ static void create_gic(const VirtBoardInfo *vbi, qemu_irq *pic) pic[i] = qdev_get_gpio_in(gicdev, i); } - fdt_add_gic_node(vbi); + return fdt_add_gic_node(vbi); } static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic) @@ -556,6 +568,116 @@ static void create_fw_cfg(const VirtBoardInfo *vbi) g_free(nodename); } +static void create_pcie_irq_map(const VirtBoardInfo *vbi, uint32_t gic_phandle, + int first_irq, const char *nodename) +{ + int devfn, pin; + uint32_t full_irq_map[4 * 4 * 8] = { 0 }; + uint32_t *irq_map = full_irq_map; + + for (devfn = 0; devfn <= 0x18; devfn += 0x8) { + for (pin = 0; pin < 4; pin++) { + int irq_type = GIC_FDT_IRQ_TYPE_SPI; + int irq_nr = first_irq + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS); + int irq_level = GIC_FDT_IRQ_FLAGS_LEVEL_HI; + int i; + + uint32_t map[] = { + devfn << 8, 0, 0, /* devfn */ + pin + 1, /* PCI pin */ + gic_phandle, irq_type, irq_nr, irq_level }; /* GIC irq */ + + /* Convert map to big endian */ + for (i = 0; i < 8; i++) { + irq_map[i] = cpu_to_be32(map[i]); + } + irq_map += 8; + } + } + + qemu_fdt_setprop(vbi->fdt, nodename, "interrupt-map", + full_irq_map, sizeof(full_irq_map)); + + qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupt-map-mask", + 0x1800, 0, 0, /* devfn (PCI_SLOT(3)) */ + 0x7 /* PCI irq */); +} + +static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic, + uint32_t gic_phandle) +{ + hwaddr base = vbi->memmap[VIRT_PCIE].base; + hwaddr size = vbi->memmap[VIRT_PCIE].size; + hwaddr end = base + size; + hwaddr size_mmio; + hwaddr size_ioport = 64 * 1024; + hwaddr size_ecam = PCIE_MMCFG_SIZE_MIN * 16; /* 16 PCIe buses */ + hwaddr base_mmio = base; + hwaddr base_ioport; + hwaddr base_ecam; + int irq = vbi->irqmap[VIRT_PCIE]; + MemoryRegion *mmio_alias; + MemoryRegion *mmio_reg; + MemoryRegion *ecam_alias; + MemoryRegion *ecam_reg; + DeviceState *dev; + char *nodename; + int i; + + base_ecam = QEMU_ALIGN_DOWN(end - size_ecam, size_ecam); + size_ecam = end - base_ecam; + base_ioport = QEMU_ALIGN_DOWN(end - size_ecam - size_ioport, size_ioport); + size_ioport = base_ecam - base_ioport; + size_mmio = base_ioport - base; + + dev = qdev_create(NULL, TYPE_GPEX_HOST); + qdev_init_nofail(dev); + + /* Map only the first size_ecam bytes of ECAM space */ + ecam_alias = g_new0(MemoryRegion, 1); + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam", + ecam_reg, 0, size_ecam); + memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias); + + /* Map the MMIO window at the same spot in bus and cpu layouts */ + mmio_alias = g_new0(MemoryRegion, 1); + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio", + mmio_reg, base_mmio, size_mmio); + memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias); + + /* Map IO port space */ + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_ioport); + + for (i = 0; i < GPEX_NUM_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); + } + + nodename = g_strdup_printf("/pcie@%" PRIx64, base); + qemu_fdt_add_subnode(vbi->fdt, nodename); + qemu_fdt_setprop_string(vbi->fdt, nodename, + "compatible", "pci-host-ecam-generic"); + qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "pci"); + qemu_fdt_setprop_cell(vbi->fdt, nodename, "#address-cells", 3); + qemu_fdt_setprop_cell(vbi->fdt, nodename, "#size-cells", 2); + qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0, 1); + + qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + 2, base_ecam, 2, size_ecam); + qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges", + 1, FDT_PCI_RANGE_IOPORT, 2, 0, + 2, base_ioport, 2, size_ioport, + + 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, + 2, base_mmio, 2, size_mmio); + + qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 1); + create_pcie_irq_map(vbi, gic_phandle, irq, nodename); + + g_free(nodename); +} + static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size) { const VirtBoardInfo *board = (const VirtBoardInfo *)binfo; @@ -573,6 +695,7 @@ static void machvirt_init(MachineState *machine) MemoryRegion *ram = g_new(MemoryRegion, 1); const char *cpu_model = machine->cpu_model; VirtBoardInfo *vbi; + uint32_t gic_phandle; if (!cpu_model) { cpu_model = "cortex-a15"; @@ -634,12 +757,14 @@ static void machvirt_init(MachineState *machine) create_flash(vbi); - create_gic(vbi, pic); + gic_phandle = create_gic(vbi, pic); create_uart(vbi, pic); create_rtc(vbi, pic); + create_pcie(vbi, pic, gic_phandle); + /* 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. diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h index 899f05c..359e143 100644 --- a/include/sysemu/device_tree.h +++ b/include/sysemu/device_tree.h @@ -110,4 +110,13 @@ int qemu_fdt_setprop_sized_cells_from_array(void *fdt, qdt_tmp); \ }) +#define FDT_PCI_RANGE_RELOCATABLE 0x80000000 +#define FDT_PCI_RANGE_PREFETCHABLE 0x40000000 +#define FDT_PCI_RANGE_ALIASED 0x20000000 +#define FDT_PCI_RANGE_TYPE_MASK 0x03000000 +#define FDT_PCI_RANGE_MMIO_64BIT 0x03000000 +#define FDT_PCI_RANGE_MMIO 0x02000000 +#define FDT_PCI_RANGE_IOPORT 0x01000000 +#define FDT_PCI_RANGE_CONFIG 0x00000000 + #endif /* __DEVICE_TREE_H__ */ -- 1.7.12.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v4 3/4] arm: Add PCIe host bridge in virt machine 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 3/4] arm: Add PCIe host bridge in virt machine Alexander Graf @ 2015-02-05 15:49 ` Peter Maydell 0 siblings, 0 replies; 9+ messages in thread From: Peter Maydell @ 2015-02-05 15:49 UTC (permalink / raw) To: Alexander Graf Cc: Rob Herring, Michael S. Tsirkin, QEMU Developers, Ard Biesheuvel, Claudio Fontana, Alvise Rigo, Stuart Yoder On 5 February 2015 at 14:55, Alexander Graf <agraf@suse.de> wrote: > Now that we have a working "generic" PCIe host bridge driver, we can plug > it into ARM's virt machine to always have PCIe available to normal ARM VMs. > > I've successfully managed to expose a Bochs VGA device, XHCI and an e1000 > into an AArch64 VM with this and they all lived happily ever after. > > Signed-off-by: Alexander Graf <agraf@suse.de> > Tested-by: Claudio Fontana <claudio.fontana@huawei.com> > +static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic, > + uint32_t gic_phandle) > +{ > + hwaddr base = vbi->memmap[VIRT_PCIE].base; > + hwaddr size = vbi->memmap[VIRT_PCIE].size; > + hwaddr end = base + size; > + hwaddr size_mmio; > + hwaddr size_ioport = 64 * 1024; > + hwaddr size_ecam = PCIE_MMCFG_SIZE_MIN * 16; /* 16 PCIe buses */ > + hwaddr base_mmio = base; > + hwaddr base_ioport; > + hwaddr base_ecam; > + int irq = vbi->irqmap[VIRT_PCIE]; > + MemoryRegion *mmio_alias; > + MemoryRegion *mmio_reg; > + MemoryRegion *ecam_alias; > + MemoryRegion *ecam_reg; > + DeviceState *dev; > + char *nodename; > + int i; > + > + base_ecam = QEMU_ALIGN_DOWN(end - size_ecam, size_ecam); > + size_ecam = end - base_ecam; Why do we do this? If we've had to align down a 256MB ECAM that doesn't mean the space gets bigger -- it's still 256MB. > + base_ioport = QEMU_ALIGN_DOWN(end - size_ecam - size_ioport, size_ioport); Shouldn't the first argument here be 'base_ecam - size_ioport' ? Otherwise if we did have to align down the ECAM window we won't have started the ioport far enough down... > + size_ioport = base_ecam - base_ioport; Again, I don't think the ioport size should get bigger. > + size_mmio = base_ioport - base; > + > + dev = qdev_create(NULL, TYPE_GPEX_HOST); > + qdev_init_nofail(dev); > + > + /* Map only the first size_ecam bytes of ECAM space */ > + ecam_alias = g_new0(MemoryRegion, 1); > + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); > + memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam", > + ecam_reg, 0, size_ecam); > + memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias); > + > + /* Map the MMIO window at the same spot in bus and cpu layouts */ I still think this comment is a little cryptic. I suggest: /* Map the MMIO window into system address space so as to expose * the section of PCI MMIO space which starts at the same base address * (ie 1:1 mapping for that part of PCI MMIO space visible through * the window). */ > + mmio_alias = g_new0(MemoryRegion, 1); > + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); > + memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio", > + mmio_reg, base_mmio, size_mmio); > + memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias); > + > + /* Map IO port space */ > + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_ioport); > + > + for (i = 0; i < GPEX_NUM_IRQS; i++) { > + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); > + } > + > + nodename = g_strdup_printf("/pcie@%" PRIx64, base); > + qemu_fdt_add_subnode(vbi->fdt, nodename); > + qemu_fdt_setprop_string(vbi->fdt, nodename, > + "compatible", "pci-host-ecam-generic"); > + qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "pci"); > + qemu_fdt_setprop_cell(vbi->fdt, nodename, "#address-cells", 3); > + qemu_fdt_setprop_cell(vbi->fdt, nodename, "#size-cells", 2); > + qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0, 1); Is this right? It doesn't seem to match the expanded eCAM size we've used above. (Maybe we should calculate this based on the size_ecam or something?) > + > + qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", > + 2, base_ecam, 2, size_ecam); > + qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges", > + 1, FDT_PCI_RANGE_IOPORT, 2, 0, > + 2, base_ioport, 2, size_ioport, > + I guess this blank line is deliberate to separate out the io from the mmio part of this definition... > + 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, > + 2, base_mmio, 2, size_mmio); > + > + qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 1); > + create_pcie_irq_map(vbi, gic_phandle, irq, nodename); > + > + g_free(nodename); > +} Otherwise looks OK. thanks -- PMM ^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v4 4/4] pci: Move PCI VGA to pci.mak 2015-02-05 14:55 [Qemu-devel] [PATCH v4 0/4] ARM: Add support for a generic PCI Express host bridge Alexander Graf ` (2 preceding siblings ...) 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 3/4] arm: Add PCIe host bridge in virt machine Alexander Graf @ 2015-02-05 14:55 ` Alexander Graf 2015-02-05 15:03 ` Peter Maydell 3 siblings, 1 reply; 9+ messages in thread From: Alexander Graf @ 2015-02-05 14:55 UTC (permalink / raw) To: qemu-devel Cc: Peter Maydell, ard.biesheuvel, rob.herring, mst, claudio.fontana, stuart.yoder, a.rigo Every platform that supports PCI can also spawn the Bochs VGA PCI adapter. Move it to pci.mak to enable it for everyone. Signed-off-by: Alexander Graf <agraf@suse.de> --- default-configs/alpha-softmmu.mak | 2 -- default-configs/i386-softmmu.mak | 2 -- default-configs/mips-softmmu.mak | 2 -- default-configs/mips64-softmmu.mak | 2 -- default-configs/mips64el-softmmu.mak | 2 -- default-configs/mipsel-softmmu.mak | 2 -- default-configs/pci.mak | 2 ++ default-configs/ppc-softmmu.mak | 2 -- default-configs/ppc64-softmmu.mak | 2 -- default-configs/ppcemb-softmmu.mak | 2 -- default-configs/sparc64-softmmu.mak | 2 -- default-configs/x86_64-softmmu.mak | 2 -- 12 files changed, 2 insertions(+), 22 deletions(-) diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak index bc07600..7f6161e 100644 --- a/default-configs/alpha-softmmu.mak +++ b/default-configs/alpha-softmmu.mak @@ -5,8 +5,6 @@ include usb.mak CONFIG_SERIAL=y CONFIG_I8254=y CONFIG_PCKBD=y -CONFIG_VGA=y -CONFIG_VGA_PCI=y CONFIG_VGA_CIRRUS=y CONFIG_IDE_CORE=y CONFIG_IDE_QDEV=y diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index 8e08841..bd99af9 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -3,9 +3,7 @@ include pci.mak include sound.mak include usb.mak -CONFIG_VGA=y CONFIG_QXL=$(CONFIG_SPICE) -CONFIG_VGA_PCI=y CONFIG_VGA_ISA=y CONFIG_VGA_CIRRUS=y CONFIG_VMWARE_VGA=y diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak index 2a80b04..cce2c81 100644 --- a/default-configs/mips-softmmu.mak +++ b/default-configs/mips-softmmu.mak @@ -4,8 +4,6 @@ include pci.mak include sound.mak include usb.mak CONFIG_ESP=y -CONFIG_VGA=y -CONFIG_VGA_PCI=y CONFIG_VGA_ISA=y CONFIG_VGA_ISA_MM=y CONFIG_VGA_CIRRUS=y diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak index f1f933b..7a88a08 100644 --- a/default-configs/mips64-softmmu.mak +++ b/default-configs/mips64-softmmu.mak @@ -4,8 +4,6 @@ include pci.mak include sound.mak include usb.mak CONFIG_ESP=y -CONFIG_VGA=y -CONFIG_VGA_PCI=y CONFIG_VGA_ISA=y CONFIG_VGA_ISA_MM=y CONFIG_VGA_CIRRUS=y diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak index 317b151..095de43 100644 --- a/default-configs/mips64el-softmmu.mak +++ b/default-configs/mips64el-softmmu.mak @@ -4,8 +4,6 @@ include pci.mak include sound.mak include usb.mak CONFIG_ESP=y -CONFIG_VGA=y -CONFIG_VGA_PCI=y CONFIG_VGA_ISA=y CONFIG_VGA_ISA_MM=y CONFIG_VGA_CIRRUS=y diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak index 7708185..0e25108 100644 --- a/default-configs/mipsel-softmmu.mak +++ b/default-configs/mipsel-softmmu.mak @@ -4,8 +4,6 @@ include pci.mak include sound.mak include usb.mak CONFIG_ESP=y -CONFIG_VGA=y -CONFIG_VGA_PCI=y CONFIG_VGA_ISA=y CONFIG_VGA_ISA_MM=y CONFIG_VGA_CIRRUS=y diff --git a/default-configs/pci.mak b/default-configs/pci.mak index 030cdc7..bea6b01 100644 --- a/default-configs/pci.mak +++ b/default-configs/pci.mak @@ -33,3 +33,5 @@ CONFIG_NVME_PCI=y CONFIG_SD=y CONFIG_SDHCI=y CONFIG_EDU=y +CONFIG_VGA=y +CONFIG_VGA_PCI=y diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak index d725b23..aebfab9 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -6,8 +6,6 @@ include usb.mak CONFIG_ISA_MMIO=y CONFIG_ESCC=y CONFIG_M48T59=y -CONFIG_VGA=y -CONFIG_VGA_PCI=y CONFIG_SERIAL=y CONFIG_PARALLEL=y CONFIG_I8254=y diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak index bd30d69..f195a87 100644 --- a/default-configs/ppc64-softmmu.mak +++ b/default-configs/ppc64-softmmu.mak @@ -6,8 +6,6 @@ include usb.mak CONFIG_ISA_MMIO=y CONFIG_ESCC=y CONFIG_M48T59=y -CONFIG_VGA=y -CONFIG_VGA_PCI=y CONFIG_SERIAL=y CONFIG_PARALLEL=y CONFIG_I8254=y diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak index e032761..a1b3d5f 100644 --- a/default-configs/ppcemb-softmmu.mak +++ b/default-configs/ppcemb-softmmu.mak @@ -4,8 +4,6 @@ include pci.mak include sound.mak include usb.mak CONFIG_M48T59=y -CONFIG_VGA=y -CONFIG_VGA_PCI=y CONFIG_SERIAL=y CONFIG_I8257=y CONFIG_OPENPIC=y diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak index 299c97b..123bb99 100644 --- a/default-configs/sparc64-softmmu.mak +++ b/default-configs/sparc64-softmmu.mak @@ -5,8 +5,6 @@ include usb.mak CONFIG_ISA_MMIO=y CONFIG_M48T59=y CONFIG_PTIMER=y -CONFIG_VGA=y -CONFIG_VGA_PCI=y CONFIG_SERIAL=y CONFIG_PARALLEL=y CONFIG_PCKBD=y diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak index 66557ac..e7c2734 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -3,9 +3,7 @@ include pci.mak include sound.mak include usb.mak -CONFIG_VGA=y CONFIG_QXL=$(CONFIG_SPICE) -CONFIG_VGA_PCI=y CONFIG_VGA_ISA=y CONFIG_VGA_CIRRUS=y CONFIG_VMWARE_VGA=y -- 1.7.12.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v4 4/4] pci: Move PCI VGA to pci.mak 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 4/4] pci: Move PCI VGA to pci.mak Alexander Graf @ 2015-02-05 15:03 ` Peter Maydell 0 siblings, 0 replies; 9+ messages in thread From: Peter Maydell @ 2015-02-05 15:03 UTC (permalink / raw) To: Alexander Graf Cc: Rob Herring, Michael S. Tsirkin, QEMU Developers, Ard Biesheuvel, Claudio Fontana, Alvise Rigo, Stuart Yoder On 5 February 2015 at 14:55, Alexander Graf <agraf@suse.de> wrote: > Every platform that supports PCI can also spawn the Bochs VGA PCI adapter. Move > it to pci.mak to enable it for everyone. > > Signed-off-by: Alexander Graf <agraf@suse.de> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> thanks -- PMM ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-02-05 15:49 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-02-05 14:55 [Qemu-devel] [PATCH v4 0/4] ARM: Add support for a generic PCI Express host bridge Alexander Graf 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 1/4] pci: Allocate PCIe host bridge PCI ID Alexander Graf 2015-02-05 15:03 ` Peter Maydell 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 2/4] pci: Add generic PCIe host bridge Alexander Graf 2015-02-05 15:30 ` Peter Maydell 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 3/4] arm: Add PCIe host bridge in virt machine Alexander Graf 2015-02-05 15:49 ` Peter Maydell 2015-02-05 14:55 ` [Qemu-devel] [PATCH v4 4/4] pci: Move PCI VGA to pci.mak Alexander Graf 2015-02-05 15:03 ` Peter Maydell
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).