[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 16/16] HACK: xen: arm: map PCI controller ranges region MMIOs to dom0.
The ranges property of a node with device_type = "pci" is defined in ePAPR 2.3.8. Map the appropriate MMIO regions through to dom0. This is a hack/PoC since it actually crashes for some reason. Hence it contains a hacked in hardcoded list suitable for Xgene while I figure this out. This should also eventually handle the interrupt-map and (ePAPR 2.4.3.1) and possibly dma-ranges (ePAPR 2.3.9) and msi-ranges (unspeciifed?) too. --- xen/arch/arm/domain_build.c | 103 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index aa7e3d2..e778c06 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -702,6 +702,69 @@ static int make_xen_node(const struct domain *d, void *fdt, return res; } +static int map_pci_device_ranges(struct domain *d, + const struct dt_device_node *dev, + const struct dt_property *ranges) +{ + const __be32 *cells; + + int size_cells, addr_cells, i, nr; + + u32 pci_space; + u64 child_addr; + u64 host_addr; + u64 length; + + printk("%s(%p, %p, %p)\n", __func__, d, dev, ranges); + printk("%s device %s\n", __func__, dt_node_full_name(dev)); + return 0; + + cells = ranges->value; + printk("%s ranges at %p, length %d\n", __func__, cells, ranges->length); + size_cells = dt_n_size_cells(dev); + addr_cells = dt_n_addr_cells(dev); + + /* + * Range is child address, host address (#address-cells), length + * (#size-cells),see ePAPR 2.3.8. + * + * PCI child address is u32 space + u64 address, see ePAPR 6.2.2. + * + */ + nr = ranges->length / ( 3 + size_cells + addr_cells ); + printk("PCI device %s: #address-cells %d, #size-cells %d. len %d, entries %d\n", + dt_node_name(dev), addr_cells, size_cells, ranges->length, nr); + + for ( i = 0; i < nr ; i++ ) + { + pci_space = (u32)dt_next_cell(1, &cells); + child_addr = dt_next_cell(2, &cells); + host_addr = dt_next_cell(addr_cells, &cells); + length = dt_next_cell(size_cells, &cells); + printk("PCI SPACE 0x%08x, 0x%"PRIx64" maps to 0x%"PRIx64" size 0x%"PRIx64"\n", + pci_space, child_addr, host_addr, length); + } + return 0; +} + +static int map_device_ranges(struct domain *d, const struct dt_device_node *dev) +{ + const struct dt_property *ranges; + u32 len; + + ranges = dt_get_property(dev, "ranges", &len); + /* No ranges, nothing to do */ + if ( !ranges ) + return 0; + + if ( dt_device_type_is_equal(dev, "pci") ) + return map_pci_device_ranges(d, dev, ranges); + + printk("Cannot handle ranges for non-PCI device type %s\n", dev->type); + /* Lets not worry for now... */ + return 0; +} + /* Map the device in the domain */ static int map_device(struct domain *d, const struct dt_device_node *dev) { @@ -767,6 +830,9 @@ static int map_device(struct domain *d, const struct dt_device_node *dev) DPRINT("addr %u = 0x%"PRIx64" - 0x%"PRIx64"\n", i, addr, addr + size - 1); + if ( size == 0 ) + continue; + res = map_mmio_regions(d, addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1, addr & PAGE_MASK); @@ -779,6 +845,8 @@ static int map_device(struct domain *d, const struct dt_device_node *dev) } } + res = map_device_ranges(d, dev); + return 0; } @@ -903,6 +971,41 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo) if ( ret ) goto err; + { + struct dt_irq irq; + + ret = map_mmio_regions(d, + 0xe000000000UL, + 0xe00fffffffUL, + 0xe000000000UL); + if (ret) printk("PCI REGION 0 failed\n"); + ret = map_mmio_regions(d, + 0xe080000000UL, + 0xe08fffffffUL, + 0xe080000000UL); + if (ret) printk("PCI REGION 1 failed\n"); + ret = map_mmio_regions(d, + 0xe010000000UL, + 0xe010000000UL, + 0xe01000ffffUL); + if (ret) printk("PCI REGION 2 failed\n"); + + irq.type = 0x4; + + irq.irq = 0xc2 + 32; + ret = gic_route_irq_to_guest(d, &irq, "PCI#INTA"); + if (ret) printk("PCI INTA failed\n"); + irq.irq = 0xc3 + 32; + ret = gic_route_irq_to_guest(d, &irq, "PCI#INTB"); + if (ret) printk("PCI INTB failed\n"); + irq.irq = 0xc4 + 32; + ret = gic_route_irq_to_guest(d, &irq, "PCI#INTC"); + if (ret) printk("PCI INTC failed\n"); + irq.irq = 0xc5 + 32; + ret = gic_route_irq_to_guest(d, &irq, "PCI#INTD"); + if (ret) printk("PCI INTD failed\n"); + } + ret = fdt_finish(kinfo->fdt); if ( ret < 0 ) goto err; -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |