Re: [Qemu-devel] [PATCH v3 3/4] arm: Add PCIe host bridge in virt machine

2015-01-30 Thread Peter Maydell
On 29 January 2015 at 15:06, Alexander Graf ag...@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.
 -/* 0x1000 .. 0x4000 reserved for PCI */
 +/* PCIe region layout: [ MMIO | PIO | ECAM ] */
 +[VIRT_PCIE] =   { 0x1000, 0x3000 },

 +/*
 + * Align all the regions to their respective positions. Eventually
 + * we want to have:
 + *
 + *   MMIO space 
 + *   IO Port space 
 + *   ECAM space 
 + *
 + * all naturally aligned after each other. The MMIO region always starts
 + * at 0 and shrinks depending on the size of the other 2 regions.
 + */

This is still very opaque to me. Can't we just have a comment that
tells the reader how big the MMIO, IO and ECAM windows are without
requiring them to cross reference it with the previous array and
do a bunch of mental arithmetic?

For preference, this comment should live in the a15memmap[] array
where we document all the rest of the memory map.

thanks
-- PMM



[Qemu-devel] [PATCH v3 3/4] arm: Add PCIe host bridge in virt machine

2015-01-29 Thread Alexander Graf
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 ag...@suse.de
Tested-by: Claudio Fontana claudio.font...@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/
---
 default-configs/arm-softmmu.mak |   2 +
 hw/arm/virt.c   | 140 ++--
 include/sysemu/device_tree.h|   9 +++
 3 files changed, 146 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..5bbc7cb 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,15 @@ static const MemMapEntry a15memmap[] = {
 [VIRT_FW_CFG] = { 0x0902, 0x000a },
 [VIRT_MMIO] =   { 0x0a00, 0x0200 },
 /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
-/* 0x1000 .. 0x4000 reserved for PCI */
+/* PCIe region layout: [ MMIO | PIO | ECAM ] */
+[VIRT_PCIE] =   { 0x1000, 0x3000 },
 [VIRT_MEM] ={ 0x4000, 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 +316,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 +335,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 +386,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 +562,127 @@ 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,