Re: [Qemu-devel] [PATCH v1 3/5] hw/riscv/virt: Connect the Xilinx PCIe

2018-06-23 Thread Michael Clark



> On 23/06/2018, at 1:07 PM, Peter Maydell  wrote:
> 
> On 22 June 2018 at 20:30, Alistair Francis  wrote:
>> Connect the Xilinx PCIe device based on the device tree included in the
>> HiFive Unleashed ROM.
> 
> Did you consider using the 'gpex' generic PCIe controller here?

Yes. Alastair and I talked about this yesterday and we agreed in principle to 
using ‘gpex’ on the virt machine and the Xilinx PCIe on the SiFive U 
(’sifive_u’) machine, as this reflects one of the IP configurations of SiFive’s 
Coreplex U series when run on FPGA.

By changing this patch to add Xilinx PCIe to ‘sifive_u’, we can plug IO devices 
into the U series machine, and instead add gpex to RISC-V virt. i.e. vendor 
agnostic generic PCIe controller for virt. We would like ‘virt’ to be a 
potential vendor agnostic hardware target when we have kvm, so using gpex fits 
with this strategy (speaking from a RISC-V perspective not a SiFive 
perspective).




Re: [Qemu-devel] [PATCH v1 3/5] hw/riscv/virt: Connect the Xilinx PCIe

2018-06-23 Thread Peter Maydell
On 22 June 2018 at 20:30, Alistair Francis  wrote:
> Connect the Xilinx PCIe device based on the device tree included in the
> HiFive Unleashed ROM.

Did you consider using the 'gpex' generic PCIe controller here?

thanks
-- PMM



[Qemu-devel] [PATCH v1 3/5] hw/riscv/virt: Connect the Xilinx PCIe

2018-06-22 Thread Alistair Francis
Connect the Xilinx PCIe device based on the device tree included in the
HiFive Unleashed ROM.

Signed-off-by: Alistair Francis 
---
 default-configs/riscv32-softmmu.mak |  3 ++
 default-configs/riscv64-softmmu.mak |  3 ++
 hw/riscv/virt.c | 65 +
 include/hw/riscv/virt.h |  4 +-
 4 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/default-configs/riscv32-softmmu.mak 
b/default-configs/riscv32-softmmu.mak
index 7a003eb5e2..b8cac7a49f 100644
--- a/default-configs/riscv32-softmmu.mak
+++ b/default-configs/riscv32-softmmu.mak
@@ -4,3 +4,6 @@ CONFIG_SERIAL=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_VIRTIO=y
 CONFIG_CADENCE=y
+
+CONFIG_PCI=y
+CONFIG_PCI_XILINX=y
diff --git a/default-configs/riscv64-softmmu.mak 
b/default-configs/riscv64-softmmu.mak
index 7a003eb5e2..b8cac7a49f 100644
--- a/default-configs/riscv64-softmmu.mak
+++ b/default-configs/riscv64-softmmu.mak
@@ -4,3 +4,6 @@ CONFIG_SERIAL=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_VIRTIO=y
 CONFIG_CADENCE=y
+
+CONFIG_PCI=y
+CONFIG_PCI_XILINX=y
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index a95ccb2825..7c1ed3aee5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -38,6 +38,8 @@
 #include "sysemu/arch_init.h"
 #include "sysemu/device_tree.h"
 #include "exec/address-spaces.h"
+#include "hw/pci/pci.h"
+#include "hw/pci-host/xilinx-pcie.h"
 #include "elf.h"
 
 #include 
@@ -54,6 +56,7 @@ static const struct MemmapEntry {
 [VIRT_UART0] ={ 0x1000,  0x100 },
 [VIRT_VIRTIO] =   { 0x10001000, 0x1000 },
 [VIRT_DRAM] = { 0x8000,0x0 },
+[VIRT_PCIE] = { 0x20, 0x400 },
 };
 
 static uint64_t load_kernel(const char *kernel_filename)
@@ -232,6 +235,32 @@ static void *create_fdt(RISCVVirtState *s, const struct 
MemmapEntry *memmap,
 g_free(nodename);
 }
 
+nodename = g_strdup_printf("/pci@%lx",
+(long) memmap[VIRT_PCIE].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", 0x3);
+qemu_fdt_setprop_cells(fdt, nodename, "#interrupt-cells", 0x1);
+qemu_fdt_setprop_cells(fdt, nodename, "#size-cells", 0x2);
+qemu_fdt_setprop_string(fdt, nodename, "compatible",
+"xlnx,axi-pcie-host-1.00.a");
+qemu_fdt_setprop_string(fdt, nodename, "device_type", "pci");
+qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x20, 0x0, 0x0,
+   memmap[VIRT_PCIE].size);
+qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control");
+qemu_fdt_setprop_cells(fdt, nodename, "ranges", 0x200, 0x0,
+   0x4000, 0x0, 0x4000, 0x0, 0x2000);
+qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle);
+qemu_fdt_setprop_cells(fdt, nodename, "interrupts", PCIE_IRQ);
+g_free(nodename);
+
+nodename = g_strdup_printf("/pci@%lx/interrupt-controller",
+(long) memmap[VIRT_PCIE].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", 0x00);
+qemu_fdt_setprop_cells(fdt, nodename, "#interrupt-cells", 0x1);
+qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
+g_free(nodename);
+
 nodename = g_strdup_printf("/test@%lx",
 (long)memmap[VIRT_TEST].base);
 qemu_fdt_add_subnode(fdt, nodename);
@@ -259,6 +288,38 @@ static void *create_fdt(RISCVVirtState *s, const struct 
MemmapEntry *memmap,
 return fdt;
 }
 
+
+static inline DeviceState *
+xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr,
+ hwaddr cfg_base, uint64_t cfg_size,
+ hwaddr mmio_base, uint64_t mmio_size,
+ qemu_irq irq, bool link_up)
+{
+DeviceState *dev;
+MemoryRegion *cfg, *mmio;
+
+dev = qdev_create(NULL, TYPE_XILINX_PCIE_HOST);
+
+qdev_prop_set_uint32(dev, "bus_nr", bus_nr);
+qdev_prop_set_uint64(dev, "cfg_base", cfg_base);
+qdev_prop_set_uint64(dev, "cfg_size", cfg_size);
+qdev_prop_set_uint64(dev, "mmio_base", mmio_base);
+qdev_prop_set_uint64(dev, "mmio_size", mmio_size);
+qdev_prop_set_bit(dev, "link_up", link_up);
+
+qdev_init_nofail(dev);
+
+cfg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+memory_region_add_subregion_overlap(sys_mem, cfg_base, cfg, 0);
+
+mmio = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
+memory_region_add_subregion_overlap(sys_mem, 0, mmio, 0);
+
+qdev_connect_gpio_out_named(dev, "interrupt_out", 0, irq);
+
+return dev;
+}
+
 static void riscv_virt_board_init(MachineState *machine)
 {
 const struct MemmapEntry *memmap = virt_memmap;
@@ -382,6 +443,10 @@ static void riscv_virt_board_init(MachineState *machine)
 qdev_get_gpio_in(DEVICE(s->plic), VIRTIO_IRQ + i));
 }
 
+xilinx_pcie_init(system_memory, 0, memmap[VIRT_PCIE].base,
+ memmap[VIRT_PCIE].size, 0x4000, 0x2000,
+