Skip to content

Commit

Permalink
iommu/vt-d: Allocate DMAR fault interrupts locally
Browse files Browse the repository at this point in the history
The Intel IOMMU code currently tries to allocate all DMAR fault interrupt
vectors on the boot cpu.  On large systems with high DMAR counts this
results in vector exhaustion, and most of the vectors are not initially
allocated socket local.

Instead, have a cpu on each node do the vector allocation for the DMARs on
that node.  The boot cpu still does the allocation for its node during its
boot sequence.

Signed-off-by: Dimitri Sivanich <sivanich@hpe.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Link: https://lore.kernel.org/r/Zfydpp2Hm+as16TY@hpe.com
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Dimitri Sivanich authored and Joerg Roedel committed Apr 26, 2024
1 parent 9e7ee0f commit d74169c
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 7 deletions.
2 changes: 1 addition & 1 deletion drivers/iommu/amd/amd_iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ int amd_iommu_prepare(void);
int amd_iommu_enable(void);
void amd_iommu_disable(void);
int amd_iommu_reenable(int mode);
int amd_iommu_enable_faulting(void);
int amd_iommu_enable_faulting(unsigned int cpu);
extern int amd_iommu_guest_ir;
extern enum io_pgtable_fmt amd_iommu_pgtable;
extern int amd_iommu_gpt_level;
Expand Down
2 changes: 1 addition & 1 deletion drivers/iommu/amd/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -3392,7 +3392,7 @@ int amd_iommu_reenable(int mode)
return 0;
}

int __init amd_iommu_enable_faulting(void)
int __init amd_iommu_enable_faulting(unsigned int cpu)
{
/* We enable MSI later when PCI is initialized */
return 0;
Expand Down
9 changes: 7 additions & 2 deletions drivers/iommu/intel/dmar.c
Original file line number Diff line number Diff line change
Expand Up @@ -2121,7 +2121,7 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
return ret;
}

int __init enable_drhd_fault_handling(void)
int enable_drhd_fault_handling(unsigned int cpu)
{
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu;
Expand All @@ -2131,7 +2131,12 @@ int __init enable_drhd_fault_handling(void)
*/
for_each_iommu(iommu, drhd) {
u32 fault_status;
int ret = dmar_set_interrupt(iommu);
int ret;

if (iommu->irq || iommu->node != cpu_to_node(cpu))
continue;

ret = dmar_set_interrupt(iommu);

if (ret) {
pr_err("DRHD %Lx: failed to enable fault, interrupt, ret %d\n",
Expand Down
5 changes: 4 additions & 1 deletion drivers/iommu/irq_remapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,10 @@ int __init irq_remap_enable_fault_handling(void)
if (!remap_ops->enable_faulting)
return -ENODEV;

return remap_ops->enable_faulting();
cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "dmar:enable_fault_handling",
remap_ops->enable_faulting, NULL);

return remap_ops->enable_faulting(smp_processor_id());
}

void panic_if_irq_remap(const char *msg)
Expand Down
2 changes: 1 addition & 1 deletion drivers/iommu/irq_remapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ struct irq_remap_ops {
int (*reenable)(int);

/* Enable fault handling */
int (*enable_faulting)(void);
int (*enable_faulting)(unsigned int);
};

extern struct irq_remap_ops intel_irq_remap_ops;
Expand Down
2 changes: 1 addition & 1 deletion include/linux/dmar.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
int count);
/* Intel IOMMU detection */
void detect_intel_iommu(void);
extern int enable_drhd_fault_handling(void);
extern int enable_drhd_fault_handling(unsigned int cpu);
extern int dmar_device_add(acpi_handle handle);
extern int dmar_device_remove(acpi_handle handle);

Expand Down

0 comments on commit d74169c

Please sign in to comment.