Blame view
drivers/iommu/irq_remapping.c
3.64 KB
457c89965 treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
1c4248ca4 x86, io_apic: Int... |
2 |
#include <linux/cpumask.h> |
736baef44 iommu/vt-d: Make ... |
3 4 5 |
#include <linux/kernel.h> #include <linux/string.h> #include <linux/errno.h> |
98f1ad258 iommu/amd: Fix sp... |
6 |
#include <linux/msi.h> |
5afba62cc x86, msi: Use IRQ... |
7 8 |
#include <linux/irq.h> #include <linux/pci.h> |
a62b32cdd x86/dmar: Use new... |
9 |
#include <linux/irqdomain.h> |
98f1ad258 iommu/amd: Fix sp... |
10 11 12 |
#include <asm/hw_irq.h> #include <asm/irq_remapping.h> |
1c4248ca4 x86, io_apic: Int... |
13 14 15 |
#include <asm/processor.h> #include <asm/x86_init.h> #include <asm/apic.h> |
5fc24d8cb iommu/irq_remappi... |
16 |
#include <asm/hpet.h> |
736baef44 iommu/vt-d: Make ... |
17 |
|
8a8f422d3 iommu: rename int... |
18 |
#include "irq_remapping.h" |
736baef44 iommu/vt-d: Make ... |
19 |
|
95a02e976 iommu: rename int... |
20 |
int irq_remapping_enabled; |
03bbcb2e7 iommu/vt-d: add q... |
21 |
int irq_remap_broken; |
736baef44 iommu/vt-d: Make ... |
22 23 |
int disable_sourceid_checking; int no_x2apic_optout; |
b7d206317 iommu/vt-d: Add a... |
24 |
int disable_irq_post = 0; |
3d9b98f4e iommu, x86: Setup... |
25 |
|
7fa1c842c iommu/irq_remappi... |
26 |
static int disable_irq_remap; |
736baef44 iommu/vt-d: Make ... |
27 |
static struct irq_remap_ops *remap_ops; |
51b146c57 x86/apic: Rename ... |
28 |
static void irq_remapping_restore_boot_irq_mode(void) |
1c4248ca4 x86, io_apic: Int... |
29 30 31 32 33 34 35 36 |
{ /* * With interrupt-remapping, for now we will use virtual wire A * mode, as virtual wire B is little complex (need to configure * both IOAPIC RTE as well as interrupt-remapping table entry). * As this gets called during crash dump, keep this simple for * now. */ |
93984fbd4 x86/cpufeature: R... |
37 |
if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config()) |
1c4248ca4 x86, io_apic: Int... |
38 39 40 41 42 |
disconnect_bsp_APIC(0); } static void __init irq_remapping_modify_x86_ops(void) { |
51b146c57 x86/apic: Rename ... |
43 |
x86_apic_ops.restore = irq_remapping_restore_boot_irq_mode; |
1c4248ca4 x86, io_apic: Int... |
44 |
} |
736baef44 iommu/vt-d: Make ... |
45 46 |
static __init int setup_nointremap(char *str) { |
95a02e976 iommu: rename int... |
47 |
disable_irq_remap = 1; |
736baef44 iommu/vt-d: Make ... |
48 49 50 |
return 0; } early_param("nointremap", setup_nointremap); |
95a02e976 iommu: rename int... |
51 |
static __init int setup_irqremap(char *str) |
736baef44 iommu/vt-d: Make ... |
52 53 54 55 56 |
{ if (!str) return -EINVAL; while (*str) { |
b7d206317 iommu/vt-d: Add a... |
57 |
if (!strncmp(str, "on", 2)) { |
95a02e976 iommu: rename int... |
58 |
disable_irq_remap = 0; |
b7d206317 iommu/vt-d: Add a... |
59 60 |
disable_irq_post = 0; } else if (!strncmp(str, "off", 3)) { |
95a02e976 iommu: rename int... |
61 |
disable_irq_remap = 1; |
b7d206317 iommu/vt-d: Add a... |
62 63 |
disable_irq_post = 1; } else if (!strncmp(str, "nosid", 5)) |
736baef44 iommu/vt-d: Make ... |
64 65 66 |
disable_sourceid_checking = 1; else if (!strncmp(str, "no_x2apic_optout", 16)) no_x2apic_optout = 1; |
b7d206317 iommu/vt-d: Add a... |
67 68 |
else if (!strncmp(str, "nopost", 6)) disable_irq_post = 1; |
736baef44 iommu/vt-d: Make ... |
69 70 71 72 73 74 75 76 |
str += strcspn(str, ","); while (*str == ',') str++; } return 0; } |
95a02e976 iommu: rename int... |
77 |
early_param("intremap", setup_irqremap); |
736baef44 iommu/vt-d: Make ... |
78 |
|
03bbcb2e7 iommu/vt-d: add q... |
79 80 81 82 |
void set_irq_remapping_broken(void) { irq_remap_broken = 1; } |
959c870f7 iommu, x86: Provi... |
83 84 85 |
bool irq_remapping_cap(enum irq_remap_cap cap) { if (!remap_ops || disable_irq_post) |
30e93761f iommu/vt-d: Retur... |
86 |
return false; |
959c870f7 iommu, x86: Provi... |
87 88 89 90 |
return (remap_ops->capability & (1 << cap)); } EXPORT_SYMBOL_GPL(irq_remapping_cap); |
c392f56c9 iommu/irq_remappi... |
91 |
int __init irq_remapping_prepare(void) |
736baef44 iommu/vt-d: Make ... |
92 |
{ |
95a02e976 iommu: rename int... |
93 |
if (disable_irq_remap) |
c392f56c9 iommu/irq_remappi... |
94 |
return -ENOSYS; |
736baef44 iommu/vt-d: Make ... |
95 |
|
30969e34a iommu/irq_remappi... |
96 97 98 99 |
if (intel_irq_remap_ops.prepare() == 0) remap_ops = &intel_irq_remap_ops; else if (IS_ENABLED(CONFIG_AMD_IOMMU) && amd_iommu_irq_ops.prepare() == 0) |
a1dafe857 iommu, x86: Restr... |
100 |
remap_ops = &amd_iommu_irq_ops; |
29217a474 iommu/hyper-v: Ad... |
101 102 103 |
else if (IS_ENABLED(CONFIG_HYPERV_IOMMU) && hyperv_irq_remap_ops.prepare() == 0) remap_ops = &hyperv_irq_remap_ops; |
30969e34a iommu/irq_remappi... |
104 105 106 107 |
else return -ENOSYS; return 0; |
736baef44 iommu/vt-d: Make ... |
108 |
} |
95a02e976 iommu: rename int... |
109 |
int __init irq_remapping_enable(void) |
736baef44 iommu/vt-d: Make ... |
110 |
{ |
1c4248ca4 x86, io_apic: Int... |
111 |
int ret; |
e90117604 iommu/irq_remappi... |
112 |
if (!remap_ops->enable) |
736baef44 iommu/vt-d: Make ... |
113 |
return -ENODEV; |
1c4248ca4 x86, io_apic: Int... |
114 115 116 117 118 119 |
ret = remap_ops->enable(); if (irq_remapping_enabled) irq_remapping_modify_x86_ops(); return ret; |
736baef44 iommu/vt-d: Make ... |
120 |
} |
4f3d8b67a iommu/vt-d: Conve... |
121 |
|
95a02e976 iommu: rename int... |
122 |
void irq_remapping_disable(void) |
4f3d8b67a iommu/vt-d: Conve... |
123 |
{ |
e90117604 iommu/irq_remappi... |
124 125 |
if (irq_remapping_enabled && remap_ops->disable) remap_ops->disable(); |
4f3d8b67a iommu/vt-d: Conve... |
126 |
} |
95a02e976 iommu: rename int... |
127 |
int irq_remapping_reenable(int mode) |
4f3d8b67a iommu/vt-d: Conve... |
128 |
{ |
e90117604 iommu/irq_remappi... |
129 130 |
if (irq_remapping_enabled && remap_ops->reenable) return remap_ops->reenable(mode); |
4f3d8b67a iommu/vt-d: Conve... |
131 |
|
e90117604 iommu/irq_remappi... |
132 |
return 0; |
4f3d8b67a iommu/vt-d: Conve... |
133 |
} |
95a02e976 iommu: rename int... |
134 |
int __init irq_remap_enable_fault_handling(void) |
4f3d8b67a iommu/vt-d: Conve... |
135 |
{ |
70733e0c7 x86, apic: Move i... |
136 137 |
if (!irq_remapping_enabled) return 0; |
e90117604 iommu/irq_remappi... |
138 |
if (!remap_ops->enable_faulting) |
4f3d8b67a iommu/vt-d: Conve... |
139 140 141 142 |
return -ENODEV; return remap_ops->enable_faulting(); } |
0c3f173a8 iommu/vt-d: Conve... |
143 |
|
6a9f5de27 x86, io_apic: Mov... |
144 145 146 147 148 |
void panic_if_irq_remap(const char *msg) { if (irq_remapping_enabled) panic(msg); } |
9b1b0e42f x86, io-apic: Mov... |
149 |
|
947045a2a irq_remapping: In... |
150 |
/** |
947045a2a irq_remapping: In... |
151 152 153 |
* irq_remapping_get_irq_domain - Get the irqdomain serving the request @info * @info: interrupt allocation information, used to identify the IOMMU device * |
947045a2a irq_remapping: In... |
154 155 |
* Returns pointer to IRQ domain, or NULL on failure. */ |
6b6256e61 iommu/irq_remappi... |
156 |
struct irq_domain *irq_remapping_get_irq_domain(struct irq_alloc_info *info) |
947045a2a irq_remapping: In... |
157 158 159 160 161 162 |
{ if (!remap_ops || !remap_ops->get_irq_domain) return NULL; return remap_ops->get_irq_domain(info); } |