irq_remapping.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. #include <asm/hw_irq.h>
  11. #include <asm/irq_remapping.h>
  12. #include <asm/processor.h>
  13. #include <asm/x86_init.h>
  14. #include <asm/apic.h>
  15. #include <asm/hpet.h>
  16. #include "irq_remapping.h"
  17. int irq_remapping_enabled;
  18. int irq_remap_broken;
  19. int disable_sourceid_checking;
  20. int no_x2apic_optout;
  21. int disable_irq_post = 0;
  22. bool enable_posted_msi __ro_after_init;
  23. static int disable_irq_remap;
  24. static struct irq_remap_ops *remap_ops;
  25. static void irq_remapping_restore_boot_irq_mode(void)
  26. {
  27. /*
  28. * With interrupt-remapping, for now we will use virtual wire A
  29. * mode, as virtual wire B is little complex (need to configure
  30. * both IOAPIC RTE as well as interrupt-remapping table entry).
  31. * As this gets called during crash dump, keep this simple for
  32. * now.
  33. */
  34. if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config())
  35. disconnect_bsp_APIC(0);
  36. }
  37. static void __init irq_remapping_modify_x86_ops(void)
  38. {
  39. x86_apic_ops.restore = irq_remapping_restore_boot_irq_mode;
  40. }
  41. static __init int setup_nointremap(char *str)
  42. {
  43. disable_irq_remap = 1;
  44. return 0;
  45. }
  46. early_param("nointremap", setup_nointremap);
  47. static __init int setup_irqremap(char *str)
  48. {
  49. if (!str)
  50. return -EINVAL;
  51. while (*str) {
  52. if (!strncmp(str, "on", 2)) {
  53. disable_irq_remap = 0;
  54. disable_irq_post = 0;
  55. } else if (!strncmp(str, "off", 3)) {
  56. disable_irq_remap = 1;
  57. disable_irq_post = 1;
  58. } else if (!strncmp(str, "nosid", 5))
  59. disable_sourceid_checking = 1;
  60. else if (!strncmp(str, "no_x2apic_optout", 16))
  61. no_x2apic_optout = 1;
  62. else if (!strncmp(str, "nopost", 6))
  63. disable_irq_post = 1;
  64. else if (IS_ENABLED(CONFIG_X86_POSTED_MSI) && !strncmp(str, "posted_msi", 10))
  65. enable_posted_msi = true;
  66. str += strcspn(str, ",");
  67. while (*str == ',')
  68. str++;
  69. }
  70. return 0;
  71. }
  72. early_param("intremap", setup_irqremap);
  73. void set_irq_remapping_broken(void)
  74. {
  75. irq_remap_broken = 1;
  76. }
  77. bool irq_remapping_cap(enum irq_remap_cap cap)
  78. {
  79. if (!remap_ops || disable_irq_post)
  80. return false;
  81. return (remap_ops->capability & (1 << cap));
  82. }
  83. EXPORT_SYMBOL_GPL(irq_remapping_cap);
  84. int __init irq_remapping_prepare(void)
  85. {
  86. if (disable_irq_remap)
  87. return -ENOSYS;
  88. if (IS_ENABLED(CONFIG_INTEL_IOMMU) &&
  89. intel_irq_remap_ops.prepare() == 0)
  90. remap_ops = &intel_irq_remap_ops;
  91. else if (IS_ENABLED(CONFIG_AMD_IOMMU) &&
  92. amd_iommu_irq_ops.prepare() == 0)
  93. remap_ops = &amd_iommu_irq_ops;
  94. else if (IS_ENABLED(CONFIG_HYPERV_IOMMU) &&
  95. hyperv_irq_remap_ops.prepare() == 0)
  96. remap_ops = &hyperv_irq_remap_ops;
  97. else
  98. return -ENOSYS;
  99. return 0;
  100. }
  101. int __init irq_remapping_enable(void)
  102. {
  103. int ret;
  104. if (!remap_ops->enable)
  105. return -ENODEV;
  106. ret = remap_ops->enable();
  107. if (irq_remapping_enabled)
  108. irq_remapping_modify_x86_ops();
  109. return ret;
  110. }
  111. void irq_remapping_disable(void)
  112. {
  113. if (irq_remapping_enabled && remap_ops->disable)
  114. remap_ops->disable();
  115. }
  116. int irq_remapping_reenable(int mode)
  117. {
  118. if (irq_remapping_enabled && remap_ops->reenable)
  119. return remap_ops->reenable(mode);
  120. return 0;
  121. }
  122. int __init irq_remap_enable_fault_handling(void)
  123. {
  124. if (!irq_remapping_enabled)
  125. return 0;
  126. if (!remap_ops->enable_faulting)
  127. return -ENODEV;
  128. cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "dmar:enable_fault_handling",
  129. remap_ops->enable_faulting, NULL);
  130. return remap_ops->enable_faulting(smp_processor_id());
  131. }
  132. void panic_if_irq_remap(const char *msg)
  133. {
  134. if (irq_remapping_enabled)
  135. panic(msg);
  136. }