@@ -66,8 +66,8 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
{
uint32_t nr_spis = 0;
unsigned int i;
- uint32_t vuart_irq, virtio_irq = 0;
- bool vuart_enabled = false, virtio_enabled = false;
+ uint32_t vuart_irq, virtio_irq = 0, vsmmu_irq = 0;
+ bool vuart_enabled = false, virtio_enabled = false, vsmmu_enabled = false;
uint64_t virtio_mmio_base = GUEST_VIRTIO_MMIO_BASE;
uint32_t virtio_mmio_irq = GUEST_VIRTIO_MMIO_SPI_FIRST;
@@ -81,6 +81,12 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
vuart_enabled = true;
}
+ if (d_config->num_pcidevs || d_config->b_info.device_tree) {
+ nr_spis += (GUEST_VSMMU_SPI - 32) + 1;
+ vsmmu_irq = GUEST_VSMMU_SPI;
+ vsmmu_enabled = true;
+ }
+
for (i = 0; i < d_config->num_disks; i++) {
libxl_device_disk *disk = &d_config->disks[i];
@@ -136,6 +142,11 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
return ERROR_FAIL;
}
+ if (vsmmu_enabled && irq == vsmmu_irq) {
+ LOG(ERROR, "Physical IRQ %u conflicting with vSMMUv3 SPI\n", irq);
+ return ERROR_FAIL;
+ }
+
if (irq < 32)
continue;
@@ -837,6 +848,7 @@ static int make_vsmmuv3_node(libxl__gc *gc, void *fdt,
{
int res;
const char *name = GCSPRINTF("iommu@%llx", GUEST_VSMMUV3_BASE);
+ gic_interrupt intr;
res = fdt_begin_node(fdt, name);
if (res) return res;
@@ -855,6 +867,14 @@ static int make_vsmmuv3_node(libxl__gc *gc, void *fdt,
res = fdt_property_cell(fdt, "#iommu-cells", 1);
if (res) return res;
+ res = fdt_property_string(fdt, "interrupt-names", "combined");
+ if (res) return res;
+
+ set_interrupt(intr, GUEST_VSMMU_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
+
+ res = fdt_property_interrupts(gc, fdt, &intr, 1);
+ if (res) return res;
+
res = fdt_end_node(fdt);
if (res) return res;
@@ -2329,6 +2329,7 @@ static int __init make_vsmmuv3_node(const struct kernel_info *kinfo)
char buf[24];
__be32 reg[GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS];
__be32 *cells;
+ gic_interrupt_t intr;
void *fdt = kinfo->fdt;
snprintf(buf, sizeof(buf), "iommu@%llx", GUEST_VSMMUV3_BASE);
@@ -2359,6 +2360,16 @@ static int __init make_vsmmuv3_node(const struct kernel_info *kinfo)
if ( res )
return res;
+ res = fdt_property_string(fdt, "interrupt-names", "combined");
+ if ( res )
+ return res;
+
+ set_interrupt(intr, GUEST_VSMMU_SPI, 0xf, DT_IRQ_TYPE_LEVEL_HIGH);
+
+ res = fdt_property_interrupts(kinfo, &intr, 1);
+ if ( res )
+ return res;
+
res = fdt_end_node(fdt);
return res;
@@ -728,6 +728,7 @@ static const struct mmio_handler_ops vsmmuv3_mmio_handler = {
static int vsmmuv3_init_single(struct domain *d, paddr_t addr,
paddr_t size, uint32_t virq)
{
+ int ret;
struct virt_smmu *smmu;
smmu = xzalloc(struct virt_smmu);
@@ -743,12 +744,21 @@ static int vsmmuv3_init_single(struct domain *d, paddr_t addr,
spin_lock_init(&smmu->cmd_queue_lock);
+ ret = vgic_reserve_virq(d, virq);
+ if ( !ret )
+ goto out;
+
register_mmio_handler(d, &vsmmuv3_mmio_handler, addr, size, smmu);
/* Register the vIOMMU to be able to clean it up later. */
list_add_tail(&smmu->viommu_list, &d->arch.viommu_list);
return 0;
+
+out:
+ xfree(smmu);
+ vgic_free_virq(d, virq);
+ return ret;
}
int domain_vsmmuv3_init(struct domain *d)
Alloc and reserve virq for event queue and global error to send event to guests. Also Modify the libxl to accomadate the new define virq. Signed-off-by: Rahul Singh <rahul.singh@arm.com> --- tools/libs/light/libxl_arm.c | 24 ++++++++++++++++++++++-- xen/arch/arm/domain_build.c | 11 +++++++++++ xen/drivers/passthrough/arm/vsmmu-v3.c | 10 ++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-)