Blame view

drivers/iommu/irq_remapping.c 3.64 KB
457c89965   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1c4248ca4   Joerg Roedel   x86, io_apic: Int...
2
  #include <linux/cpumask.h>
736baef44   Joerg Roedel   iommu/vt-d: Make ...
3
4
5
  #include <linux/kernel.h>
  #include <linux/string.h>
  #include <linux/errno.h>
98f1ad258   Joerg Roedel   iommu/amd: Fix sp...
6
  #include <linux/msi.h>
5afba62cc   Joerg Roedel   x86, msi: Use IRQ...
7
8
  #include <linux/irq.h>
  #include <linux/pci.h>
a62b32cdd   Jiang Liu   x86/dmar: Use new...
9
  #include <linux/irqdomain.h>
98f1ad258   Joerg Roedel   iommu/amd: Fix sp...
10
11
12
  
  #include <asm/hw_irq.h>
  #include <asm/irq_remapping.h>
1c4248ca4   Joerg Roedel   x86, io_apic: Int...
13
14
15
  #include <asm/processor.h>
  #include <asm/x86_init.h>
  #include <asm/apic.h>
5fc24d8cb   Yijing Wang   iommu/irq_remappi...
16
  #include <asm/hpet.h>
736baef44   Joerg Roedel   iommu/vt-d: Make ...
17

8a8f422d3   Suresh Siddha   iommu: rename int...
18
  #include "irq_remapping.h"
736baef44   Joerg Roedel   iommu/vt-d: Make ...
19

95a02e976   Suresh Siddha   iommu: rename int...
20
  int irq_remapping_enabled;
03bbcb2e7   Neil Horman   iommu/vt-d: add q...
21
  int irq_remap_broken;
736baef44   Joerg Roedel   iommu/vt-d: Make ...
22
23
  int disable_sourceid_checking;
  int no_x2apic_optout;
b7d206317   Feng Wu   iommu/vt-d: Add a...
24
  int disable_irq_post = 0;
3d9b98f4e   Feng Wu   iommu, x86: Setup...
25

7fa1c842c   Jiang Liu   iommu/irq_remappi...
26
  static int disable_irq_remap;
736baef44   Joerg Roedel   iommu/vt-d: Make ...
27
  static struct irq_remap_ops *remap_ops;
51b146c57   Baoquan He   x86/apic: Rename ...
28
  static void irq_remapping_restore_boot_irq_mode(void)
1c4248ca4   Joerg Roedel   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   Borislav Petkov   x86/cpufeature: R...
37
  	if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config())
1c4248ca4   Joerg Roedel   x86, io_apic: Int...
38
39
40
41
42
  		disconnect_bsp_APIC(0);
  }
  
  static void __init irq_remapping_modify_x86_ops(void)
  {
51b146c57   Baoquan He   x86/apic: Rename ...
43
  	x86_apic_ops.restore = irq_remapping_restore_boot_irq_mode;
1c4248ca4   Joerg Roedel   x86, io_apic: Int...
44
  }
736baef44   Joerg Roedel   iommu/vt-d: Make ...
45
46
  static __init int setup_nointremap(char *str)
  {
95a02e976   Suresh Siddha   iommu: rename int...
47
  	disable_irq_remap = 1;
736baef44   Joerg Roedel   iommu/vt-d: Make ...
48
49
50
  	return 0;
  }
  early_param("nointremap", setup_nointremap);
95a02e976   Suresh Siddha   iommu: rename int...
51
  static __init int setup_irqremap(char *str)
736baef44   Joerg Roedel   iommu/vt-d: Make ...
52
53
54
55
56
  {
  	if (!str)
  		return -EINVAL;
  
  	while (*str) {
b7d206317   Feng Wu   iommu/vt-d: Add a...
57
  		if (!strncmp(str, "on", 2)) {
95a02e976   Suresh Siddha   iommu: rename int...
58
  			disable_irq_remap = 0;
b7d206317   Feng Wu   iommu/vt-d: Add a...
59
60
  			disable_irq_post = 0;
  		} else if (!strncmp(str, "off", 3)) {
95a02e976   Suresh Siddha   iommu: rename int...
61
  			disable_irq_remap = 1;
b7d206317   Feng Wu   iommu/vt-d: Add a...
62
63
  			disable_irq_post = 1;
  		} else if (!strncmp(str, "nosid", 5))
736baef44   Joerg Roedel   iommu/vt-d: Make ...
64
65
66
  			disable_sourceid_checking = 1;
  		else if (!strncmp(str, "no_x2apic_optout", 16))
  			no_x2apic_optout = 1;
b7d206317   Feng Wu   iommu/vt-d: Add a...
67
68
  		else if (!strncmp(str, "nopost", 6))
  			disable_irq_post = 1;
736baef44   Joerg Roedel   iommu/vt-d: Make ...
69
70
71
72
73
74
75
76
  
  		str += strcspn(str, ",");
  		while (*str == ',')
  			str++;
  	}
  
  	return 0;
  }
95a02e976   Suresh Siddha   iommu: rename int...
77
  early_param("intremap", setup_irqremap);
736baef44   Joerg Roedel   iommu/vt-d: Make ...
78

03bbcb2e7   Neil Horman   iommu/vt-d: add q...
79
80
81
82
  void set_irq_remapping_broken(void)
  {
  	irq_remap_broken = 1;
  }
959c870f7   Feng Wu   iommu, x86: Provi...
83
84
85
  bool irq_remapping_cap(enum irq_remap_cap cap)
  {
  	if (!remap_ops || disable_irq_post)
30e93761f   Joerg Roedel   iommu/vt-d: Retur...
86
  		return false;
959c870f7   Feng Wu   iommu, x86: Provi...
87
88
89
90
  
  	return (remap_ops->capability & (1 << cap));
  }
  EXPORT_SYMBOL_GPL(irq_remapping_cap);
c392f56c9   Jiang Liu   iommu/irq_remappi...
91
  int __init irq_remapping_prepare(void)
736baef44   Joerg Roedel   iommu/vt-d: Make ...
92
  {
95a02e976   Suresh Siddha   iommu: rename int...
93
  	if (disable_irq_remap)
c392f56c9   Jiang Liu   iommu/irq_remappi...
94
  		return -ENOSYS;
736baef44   Joerg Roedel   iommu/vt-d: Make ...
95

30969e34a   Jiang Liu   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   Thomas Gleixner   iommu, x86: Restr...
100
  		remap_ops = &amd_iommu_irq_ops;
29217a474   Lan Tianyu   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   Jiang Liu   iommu/irq_remappi...
104
105
106
107
  	else
  		return -ENOSYS;
  
  	return 0;
736baef44   Joerg Roedel   iommu/vt-d: Make ...
108
  }
95a02e976   Suresh Siddha   iommu: rename int...
109
  int __init irq_remapping_enable(void)
736baef44   Joerg Roedel   iommu/vt-d: Make ...
110
  {
1c4248ca4   Joerg Roedel   x86, io_apic: Int...
111
  	int ret;
e90117604   Jiang Liu   iommu/irq_remappi...
112
  	if (!remap_ops->enable)
736baef44   Joerg Roedel   iommu/vt-d: Make ...
113
  		return -ENODEV;
1c4248ca4   Joerg Roedel   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   Joerg Roedel   iommu/vt-d: Make ...
120
  }
4f3d8b67a   Joerg Roedel   iommu/vt-d: Conve...
121

95a02e976   Suresh Siddha   iommu: rename int...
122
  void irq_remapping_disable(void)
4f3d8b67a   Joerg Roedel   iommu/vt-d: Conve...
123
  {
e90117604   Jiang Liu   iommu/irq_remappi...
124
125
  	if (irq_remapping_enabled && remap_ops->disable)
  		remap_ops->disable();
4f3d8b67a   Joerg Roedel   iommu/vt-d: Conve...
126
  }
95a02e976   Suresh Siddha   iommu: rename int...
127
  int irq_remapping_reenable(int mode)
4f3d8b67a   Joerg Roedel   iommu/vt-d: Conve...
128
  {
e90117604   Jiang Liu   iommu/irq_remappi...
129
130
  	if (irq_remapping_enabled && remap_ops->reenable)
  		return remap_ops->reenable(mode);
4f3d8b67a   Joerg Roedel   iommu/vt-d: Conve...
131

e90117604   Jiang Liu   iommu/irq_remappi...
132
  	return 0;
4f3d8b67a   Joerg Roedel   iommu/vt-d: Conve...
133
  }
95a02e976   Suresh Siddha   iommu: rename int...
134
  int __init irq_remap_enable_fault_handling(void)
4f3d8b67a   Joerg Roedel   iommu/vt-d: Conve...
135
  {
70733e0c7   Joerg Roedel   x86, apic: Move i...
136
137
  	if (!irq_remapping_enabled)
  		return 0;
e90117604   Jiang Liu   iommu/irq_remappi...
138
  	if (!remap_ops->enable_faulting)
4f3d8b67a   Joerg Roedel   iommu/vt-d: Conve...
139
140
141
142
  		return -ENODEV;
  
  	return remap_ops->enable_faulting();
  }
0c3f173a8   Joerg Roedel   iommu/vt-d: Conve...
143

6a9f5de27   Joerg Roedel   x86, io_apic: Mov...
144
145
146
147
148
  void panic_if_irq_remap(const char *msg)
  {
  	if (irq_remapping_enabled)
  		panic(msg);
  }
9b1b0e42f   Joerg Roedel   x86, io-apic: Mov...
149

947045a2a   Jiang Liu   irq_remapping: In...
150
  /**
947045a2a   Jiang Liu   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   Jiang Liu   irq_remapping: In...
154
155
   * Returns pointer to IRQ domain, or NULL on failure.
   */
6b6256e61   Thomas Gleixner   iommu/irq_remappi...
156
  struct irq_domain *irq_remapping_get_irq_domain(struct irq_alloc_info *info)
947045a2a   Jiang Liu   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);
  }