The static allocation of the save space is not only very inefficient (most of the array slots won't ever get used), but is also the sole reason for a build-time upper bound on the number of IOMMUs. Introduce a structure containing just the one needed field we can't (easily) restore from other in-memory state, and allocate the respective array dynamically.
Take the opportunity and make the FEUADDR write dependent upon x2apic_enabled, like is already the case in dma_msi_set_affinity(). Also alter properties of nr_iommus: static, unsigned, and __initdata. Signed-off-by: Jan Beulich <[email protected]> --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -57,7 +57,7 @@ bool __read_mostly iommu_qinval = true; bool __read_mostly iommu_snoop = true; #endif -int nr_iommus; +static unsigned int __initdata nr_iommus; static struct iommu_ops vtd_ops; static struct tasklet vtd_fault_tasklet; @@ -1165,13 +1165,6 @@ int __init iommu_alloc(struct acpi_drhd_ unsigned long sagaw, nr_dom; int agaw; - if ( nr_iommus >= MAX_IOMMUS ) - { - dprintk(XENLOG_ERR VTDPREFIX, - "IOMMU: nr_iommus %d > MAX_IOMMUS\n", nr_iommus + 1); - return -ENOMEM; - } - iommu = xzalloc(struct vtd_iommu); if ( iommu == NULL ) return -ENOMEM; @@ -2226,6 +2219,10 @@ static void __hwdom_init setup_hwdom_rmr pcidevs_unlock(); } +static struct iommu_state { + uint32_t fectl; +} *__read_mostly iommu_state; + static int __init vtd_setup(void) { struct acpi_drhd_unit *drhd; @@ -2251,6 +2248,13 @@ static int __init vtd_setup(void) goto error; } + iommu_state = xmalloc_array(struct iommu_state, nr_iommus); + if ( !iommu_state ) + { + ret = -ENOMEM; + goto error; + } + /* We enable the following features only if they are supported by all VT-d * engines: Snoop Control, DMA passthrough, Queued Invalidation, Interrupt * Remapping, and Posted Interrupt @@ -2508,8 +2512,6 @@ static int intel_iommu_group_id(u16 seg, return PCI_BDF2(bus, devfn); } -static u32 iommu_state[MAX_IOMMUS][MAX_IOMMU_REGS]; - static int __must_check vtd_suspend(void) { struct acpi_drhd_unit *drhd; @@ -2534,14 +2536,7 @@ static int __must_check vtd_suspend(void iommu = drhd->iommu; i = iommu->index; - iommu_state[i][DMAR_FECTL_REG] = - (u32) dmar_readl(iommu->reg, DMAR_FECTL_REG); - iommu_state[i][DMAR_FEDATA_REG] = - (u32) dmar_readl(iommu->reg, DMAR_FEDATA_REG); - iommu_state[i][DMAR_FEADDR_REG] = - (u32) dmar_readl(iommu->reg, DMAR_FEADDR_REG); - iommu_state[i][DMAR_FEUADDR_REG] = - (u32) dmar_readl(iommu->reg, DMAR_FEUADDR_REG); + iommu_state[i].fectl = dmar_readl(iommu->reg, DMAR_FECTL_REG); /* don't disable VT-d engine when force_iommu is set. */ if ( force_iommu ) @@ -2594,15 +2589,13 @@ static void vtd_resume(void) for_each_drhd_unit ( drhd ) { iommu = drhd->iommu; - i = iommu->index; spin_lock_irqsave(&iommu->register_lock, flags); - dmar_writel(iommu->reg, DMAR_FEDATA_REG, - iommu_state[i][DMAR_FEDATA_REG]); - dmar_writel(iommu->reg, DMAR_FEADDR_REG, - iommu_state[i][DMAR_FEADDR_REG]); - dmar_writel(iommu->reg, DMAR_FEUADDR_REG, - iommu_state[i][DMAR_FEUADDR_REG]); + dmar_writel(iommu->reg, DMAR_FEDATA_REG, iommu->msi.msg.data); + dmar_writel(iommu->reg, DMAR_FEADDR_REG, iommu->msi.msg.address_lo); + if ( x2apic_enabled ) + dmar_writel(iommu->reg, DMAR_FEUADDR_REG, + iommu->msi.msg.address_hi); spin_unlock_irqrestore(&iommu->register_lock, flags); } @@ -2615,8 +2608,7 @@ static void vtd_resume(void) i = iommu->index; spin_lock_irqsave(&iommu->register_lock, flags); - dmar_writel(iommu->reg, DMAR_FECTL_REG, - (u32) iommu_state[i][DMAR_FECTL_REG]); + dmar_writel(iommu->reg, DMAR_FECTL_REG, iommu_state[i].fectl); spin_unlock_irqrestore(&iommu->register_lock, flags); iommu_enable_translation(drhd); --- a/xen/drivers/passthrough/vtd/iommu.h +++ b/xen/drivers/passthrough/vtd/iommu.h @@ -499,8 +499,6 @@ struct qinval_entry { #define VTD_PAGE_TABLE_LEVEL_3 3 #define VTD_PAGE_TABLE_LEVEL_4 4 -#define MAX_IOMMU_REGS 0xc0 - extern struct list_head acpi_drhd_units; extern struct list_head acpi_rmrr_units; extern struct list_head acpi_ioapic_units; --- a/xen/include/asm-x86/iommu.h +++ b/xen/include/asm-x86/iommu.h @@ -22,7 +22,6 @@ #include <asm/hvm/vmx/vmcs.h> #define DEFAULT_DOMAIN_ADDRESS_WIDTH 48 -#define MAX_IOMMUS 32 struct g2m_ioport { struct list_head list;
