diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c index 866e58c66b..1a3ac1646e 100644 --- a/tools/libs/light/libxl_arm.c +++ b/tools/libs/light/libxl_arm.c @@ -865,9 +865,32 @@ static int make_vpci_node(libxl__gc *gc, void *fdt, return 0; } +static int make_xen_iommu_node(libxl__gc *gc, void *fdt) +{ + int res; + + /* See Linux Documentation/devicetree/bindings/iommu/xen,grant-dma.yaml */ + res = fdt_begin_node(fdt, "xen_iommu"); + if (res) return res; + + res = fdt_property_compat(gc, fdt, 1, "xen,grant-dma"); + if (res) return res; + + res = fdt_property_cell(fdt, "#iommu-cells", 1); + if (res) return res; + + res = fdt_property_cell(fdt, "phandle", GUEST_PHANDLE_IOMMU); + if (res) return res; + + res = fdt_end_node(fdt); + if (res) return res; + + return 0; +} static int make_virtio_mmio_node(libxl__gc *gc, void *fdt, - uint64_t base, uint32_t irq) + uint64_t base, uint32_t irq, + uint32_t backend_domid) { int res; gic_interrupt intr; @@ -890,6 +913,16 @@ static int make_virtio_mmio_node(libxl__gc *gc, void *fdt, res = fdt_property(fdt, "dma-coherent", NULL, 0); if (res) return res; + if (backend_domid != LIBXL_TOOLSTACK_DOMID) { + uint32_t iommus_prop[2]; + + iommus_prop[0] = cpu_to_fdt32(GUEST_PHANDLE_IOMMU); + iommus_prop[1] = cpu_to_fdt32(backend_domid); + + res = fdt_property(fdt, "iommus", iommus_prop, sizeof(iommus_prop)); + if (res) return res; + } + res = fdt_end_node(fdt); if (res) return res; @@ -1097,6 +1130,7 @@ static int libxl__prepare_dtb(libxl__gc *gc, libxl_domain_config *d_config, size_t fdt_size = 0; int pfdt_size = 0; libxl_domain_build_info *const info = &d_config->b_info; + bool iommu_created; unsigned int i; const libxl_version_info *vers; @@ -1204,11 +1238,20 @@ next_resize: if (d_config->num_pcidevs) FDT( make_vpci_node(gc, fdt, ainfo, dom) ); + iommu_created = false; for (i = 0; i < d_config->num_disks; i++) { libxl_device_disk *disk = &d_config->disks[i]; - if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) - FDT( make_virtio_mmio_node(gc, fdt, disk->base, disk->irq) ); + if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) { + if (disk->backend_domid != LIBXL_TOOLSTACK_DOMID && + !iommu_created) { + FDT( make_xen_iommu_node(gc, fdt) ); + iommu_created = true; + } + + FDT( make_virtio_mmio_node(gc, fdt, disk->base, disk->irq, + disk->backend_domid) ); + } } if (pfdt) diff --git a/xen/include/public/device_tree_defs.h b/xen/include/public/device_tree_defs.h index 209d43de3f..228daafe81 100644 --- a/xen/include/public/device_tree_defs.h +++ b/xen/include/public/device_tree_defs.h @@ -4,9 +4,10 @@ #if defined(__XEN__) || defined(__XEN_TOOLS__) /* * The device tree compiler (DTC) is allocating the phandle from 1 to - * onwards. Reserve a high value for the GIC phandle. + * onwards. Reserve high values for the specific phandles. */ #define GUEST_PHANDLE_GIC (65000) +#define GUEST_PHANDLE_IOMMU (GUEST_PHANDLE_GIC + 1) #define GUEST_ROOT_ADDRESS_CELLS 2 #define GUEST_ROOT_SIZE_CELLS 2