root/drivers/iommu/irq_remapping.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. irq_remapping_restore_boot_irq_mode
  2. irq_remapping_modify_x86_ops
  3. setup_nointremap
  4. setup_irqremap
  5. set_irq_remapping_broken
  6. irq_remapping_cap
  7. irq_remapping_prepare
  8. irq_remapping_enable
  9. irq_remapping_disable
  10. irq_remapping_reenable
  11. irq_remap_enable_fault_handling
  12. panic_if_irq_remap
  13. irq_remapping_get_ir_irq_domain
  14. irq_remapping_get_irq_domain

   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>
   6 #include <linux/msi.h>
   7 #include <linux/irq.h>
   8 #include <linux/pci.h>
   9 #include <linux/irqdomain.h>
  10 
  11 #include <asm/hw_irq.h>
  12 #include <asm/irq_remapping.h>
  13 #include <asm/processor.h>
  14 #include <asm/x86_init.h>
  15 #include <asm/apic.h>
  16 #include <asm/hpet.h>
  17 
  18 #include "irq_remapping.h"
  19 
  20 int irq_remapping_enabled;
  21 int irq_remap_broken;
  22 int disable_sourceid_checking;
  23 int no_x2apic_optout;
  24 
  25 int disable_irq_post = 0;
  26 
  27 static int disable_irq_remap;
  28 static struct irq_remap_ops *remap_ops;
  29 
  30 static void irq_remapping_restore_boot_irq_mode(void)
  31 {
  32         /*
  33          * With interrupt-remapping, for now we will use virtual wire A
  34          * mode, as virtual wire B is little complex (need to configure
  35          * both IOAPIC RTE as well as interrupt-remapping table entry).
  36          * As this gets called during crash dump, keep this simple for
  37          * now.
  38          */
  39         if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config())
  40                 disconnect_bsp_APIC(0);
  41 }
  42 
  43 static void __init irq_remapping_modify_x86_ops(void)
  44 {
  45         x86_apic_ops.restore = irq_remapping_restore_boot_irq_mode;
  46 }
  47 
  48 static __init int setup_nointremap(char *str)
  49 {
  50         disable_irq_remap = 1;
  51         return 0;
  52 }
  53 early_param("nointremap", setup_nointremap);
  54 
  55 static __init int setup_irqremap(char *str)
  56 {
  57         if (!str)
  58                 return -EINVAL;
  59 
  60         while (*str) {
  61                 if (!strncmp(str, "on", 2)) {
  62                         disable_irq_remap = 0;
  63                         disable_irq_post = 0;
  64                 } else if (!strncmp(str, "off", 3)) {
  65                         disable_irq_remap = 1;
  66                         disable_irq_post = 1;
  67                 } else if (!strncmp(str, "nosid", 5))
  68                         disable_sourceid_checking = 1;
  69                 else if (!strncmp(str, "no_x2apic_optout", 16))
  70                         no_x2apic_optout = 1;
  71                 else if (!strncmp(str, "nopost", 6))
  72                         disable_irq_post = 1;
  73 
  74                 str += strcspn(str, ",");
  75                 while (*str == ',')
  76                         str++;
  77         }
  78 
  79         return 0;
  80 }
  81 early_param("intremap", setup_irqremap);
  82 
  83 void set_irq_remapping_broken(void)
  84 {
  85         irq_remap_broken = 1;
  86 }
  87 
  88 bool irq_remapping_cap(enum irq_remap_cap cap)
  89 {
  90         if (!remap_ops || disable_irq_post)
  91                 return false;
  92 
  93         return (remap_ops->capability & (1 << cap));
  94 }
  95 EXPORT_SYMBOL_GPL(irq_remapping_cap);
  96 
  97 int __init irq_remapping_prepare(void)
  98 {
  99         if (disable_irq_remap)
 100                 return -ENOSYS;
 101 
 102         if (intel_irq_remap_ops.prepare() == 0)
 103                 remap_ops = &intel_irq_remap_ops;
 104         else if (IS_ENABLED(CONFIG_AMD_IOMMU) &&
 105                  amd_iommu_irq_ops.prepare() == 0)
 106                 remap_ops = &amd_iommu_irq_ops;
 107         else if (IS_ENABLED(CONFIG_HYPERV_IOMMU) &&
 108                  hyperv_irq_remap_ops.prepare() == 0)
 109                 remap_ops = &hyperv_irq_remap_ops;
 110         else
 111                 return -ENOSYS;
 112 
 113         return 0;
 114 }
 115 
 116 int __init irq_remapping_enable(void)
 117 {
 118         int ret;
 119 
 120         if (!remap_ops->enable)
 121                 return -ENODEV;
 122 
 123         ret = remap_ops->enable();
 124 
 125         if (irq_remapping_enabled)
 126                 irq_remapping_modify_x86_ops();
 127 
 128         return ret;
 129 }
 130 
 131 void irq_remapping_disable(void)
 132 {
 133         if (irq_remapping_enabled && remap_ops->disable)
 134                 remap_ops->disable();
 135 }
 136 
 137 int irq_remapping_reenable(int mode)
 138 {
 139         if (irq_remapping_enabled && remap_ops->reenable)
 140                 return remap_ops->reenable(mode);
 141 
 142         return 0;
 143 }
 144 
 145 int __init irq_remap_enable_fault_handling(void)
 146 {
 147         if (!irq_remapping_enabled)
 148                 return 0;
 149 
 150         if (!remap_ops->enable_faulting)
 151                 return -ENODEV;
 152 
 153         return remap_ops->enable_faulting();
 154 }
 155 
 156 void panic_if_irq_remap(const char *msg)
 157 {
 158         if (irq_remapping_enabled)
 159                 panic(msg);
 160 }
 161 
 162 /**
 163  * irq_remapping_get_ir_irq_domain - Get the irqdomain associated with the IOMMU
 164  *                                   device serving request @info
 165  * @info: interrupt allocation information, used to identify the IOMMU device
 166  *
 167  * It's used to get parent irqdomain for HPET and IOAPIC irqdomains.
 168  * Returns pointer to IRQ domain, or NULL on failure.
 169  */
 170 struct irq_domain *
 171 irq_remapping_get_ir_irq_domain(struct irq_alloc_info *info)
 172 {
 173         if (!remap_ops || !remap_ops->get_ir_irq_domain)
 174                 return NULL;
 175 
 176         return remap_ops->get_ir_irq_domain(info);
 177 }
 178 
 179 /**
 180  * irq_remapping_get_irq_domain - Get the irqdomain serving the request @info
 181  * @info: interrupt allocation information, used to identify the IOMMU device
 182  *
 183  * There will be one PCI MSI/MSIX irqdomain associated with each interrupt
 184  * remapping device, so this interface is used to retrieve the PCI MSI/MSIX
 185  * irqdomain serving request @info.
 186  * Returns pointer to IRQ domain, or NULL on failure.
 187  */
 188 struct irq_domain *
 189 irq_remapping_get_irq_domain(struct irq_alloc_info *info)
 190 {
 191         if (!remap_ops || !remap_ops->get_irq_domain)
 192                 return NULL;
 193 
 194         return remap_ops->get_irq_domain(info);
 195 }

/* [<][>][^][v][top][bottom][index][help] */