1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/cpumask.h>
3 #include <linux/kernel.h>
4 #include <linux/string.h>
5 #include <linux/errno.h>
9 #include <linux/irqdomain.h>
11 #include <asm/hw_irq.h>
12 #include <asm/irq_remapping.h>
13 #include <asm/processor.h>
14 #include <asm/x86_init.h>
18 #include "irq_remapping.h"
20 int irq_remapping_enabled
;
22 int disable_sourceid_checking
;
25 int disable_irq_post
= 0;
27 bool enable_posted_msi __ro_after_init
;
29 static int disable_irq_remap
;
30 static struct irq_remap_ops
*remap_ops
;
32 static void irq_remapping_restore_boot_irq_mode(void)
35 * With interrupt-remapping, for now we will use virtual wire A
36 * mode, as virtual wire B is little complex (need to configure
37 * both IOAPIC RTE as well as interrupt-remapping table entry).
38 * As this gets called during crash dump, keep this simple for
41 if (boot_cpu_has(X86_FEATURE_APIC
) || apic_from_smp_config())
42 disconnect_bsp_APIC(0);
45 static void __init
irq_remapping_modify_x86_ops(void)
47 x86_apic_ops
.restore
= irq_remapping_restore_boot_irq_mode
;
50 static __init
int setup_nointremap(char *str
)
52 disable_irq_remap
= 1;
55 early_param("nointremap", setup_nointremap
);
57 static __init
int setup_irqremap(char *str
)
63 if (!strncmp(str
, "on", 2)) {
64 disable_irq_remap
= 0;
66 } else if (!strncmp(str
, "off", 3)) {
67 disable_irq_remap
= 1;
69 } else if (!strncmp(str
, "nosid", 5))
70 disable_sourceid_checking
= 1;
71 else if (!strncmp(str
, "no_x2apic_optout", 16))
73 else if (!strncmp(str
, "nopost", 6))
75 else if (IS_ENABLED(CONFIG_X86_POSTED_MSI
) && !strncmp(str
, "posted_msi", 10))
76 enable_posted_msi
= true;
77 str
+= strcspn(str
, ",");
84 early_param("intremap", setup_irqremap
);
86 void set_irq_remapping_broken(void)
91 bool irq_remapping_cap(enum irq_remap_cap cap
)
93 if (!remap_ops
|| disable_irq_post
)
96 return (remap_ops
->capability
& (1 << cap
));
98 EXPORT_SYMBOL_GPL(irq_remapping_cap
);
100 int __init
irq_remapping_prepare(void)
102 if (disable_irq_remap
)
105 if (IS_ENABLED(CONFIG_INTEL_IOMMU
) &&
106 intel_irq_remap_ops
.prepare() == 0)
107 remap_ops
= &intel_irq_remap_ops
;
108 else if (IS_ENABLED(CONFIG_AMD_IOMMU
) &&
109 amd_iommu_irq_ops
.prepare() == 0)
110 remap_ops
= &amd_iommu_irq_ops
;
111 else if (IS_ENABLED(CONFIG_HYPERV_IOMMU
) &&
112 hyperv_irq_remap_ops
.prepare() == 0)
113 remap_ops
= &hyperv_irq_remap_ops
;
120 int __init
irq_remapping_enable(void)
124 if (!remap_ops
->enable
)
127 ret
= remap_ops
->enable();
129 if (irq_remapping_enabled
)
130 irq_remapping_modify_x86_ops();
135 void irq_remapping_disable(void)
137 if (irq_remapping_enabled
&& remap_ops
->disable
)
138 remap_ops
->disable();
141 int irq_remapping_reenable(int mode
)
143 if (irq_remapping_enabled
&& remap_ops
->reenable
)
144 return remap_ops
->reenable(mode
);
149 int __init
irq_remap_enable_fault_handling(void)
151 if (!irq_remapping_enabled
)
154 if (!remap_ops
->enable_faulting
)
157 cpuhp_setup_state(CPUHP_AP_ONLINE_DYN
, "dmar:enable_fault_handling",
158 remap_ops
->enable_faulting
, NULL
);
160 return remap_ops
->enable_faulting(smp_processor_id());
163 void panic_if_irq_remap(const char *msg
)
165 if (irq_remapping_enabled
)