aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJulien Thierry <julien.thierry@arm.com>2019-01-31 09:53:58 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2019-02-05 09:36:57 -0500
commitb525903c254dab2491410f0f23707691b7c2c317 (patch)
tree11bad762c8aae79bfa042e47d263362f8d288b20 /kernel
parent49a57857aeea06ca831043acbb0fa5e0f50602fd (diff)
genirq: Provide basic NMI management for interrupt lines
Add functionality to allocate interrupt lines that will deliver IRQs as Non-Maskable Interrupts. These allocations are only successful if the irqchip provides the necessary support and allows NMI delivery for the interrupt line. Interrupt lines allocated for NMI delivery must be enabled/disabled through enable_nmi/disable_nmi_nosync to keep their state consistent. To treat a PERCPU IRQ as NMI, the interrupt must not be shared nor threaded, the irqchip directly managing the IRQ must be the root irqchip and the irqchip cannot be behind a slow bus. Signed-off-by: Julien Thierry <julien.thierry@arm.com> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/irq/debugfs.c6
-rw-r--r--kernel/irq/internals.h2
-rw-r--r--kernel/irq/manage.c228
3 files changed, 233 insertions, 3 deletions
diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c
index 6f636136cccc..59a04d2a66df 100644
--- a/kernel/irq/debugfs.c
+++ b/kernel/irq/debugfs.c
@@ -56,6 +56,7 @@ static const struct irq_bit_descr irqchip_flags[] = {
56 BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE), 56 BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE),
57 BIT_MASK_DESCR(IRQCHIP_EOI_THREADED), 57 BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
58 BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI), 58 BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
59 BIT_MASK_DESCR(IRQCHIP_SUPPORTS_NMI),
59}; 60};
60 61
61static void 62static void
@@ -140,6 +141,7 @@ static const struct irq_bit_descr irqdesc_istates[] = {
140 BIT_MASK_DESCR(IRQS_WAITING), 141 BIT_MASK_DESCR(IRQS_WAITING),
141 BIT_MASK_DESCR(IRQS_PENDING), 142 BIT_MASK_DESCR(IRQS_PENDING),
142 BIT_MASK_DESCR(IRQS_SUSPENDED), 143 BIT_MASK_DESCR(IRQS_SUSPENDED),
144 BIT_MASK_DESCR(IRQS_NMI),
143}; 145};
144 146
145 147
@@ -203,8 +205,8 @@ static ssize_t irq_debug_write(struct file *file, const char __user *user_buf,
203 chip_bus_lock(desc); 205 chip_bus_lock(desc);
204 raw_spin_lock_irqsave(&desc->lock, flags); 206 raw_spin_lock_irqsave(&desc->lock, flags);
205 207
206 if (irq_settings_is_level(desc)) { 208 if (irq_settings_is_level(desc) || desc->istate & IRQS_NMI) {
207 /* Can't do level, sorry */ 209 /* Can't do level nor NMIs, sorry */
208 err = -EINVAL; 210 err = -EINVAL;
209 } else { 211 } else {
210 desc->istate |= IRQS_PENDING; 212 desc->istate |= IRQS_PENDING;
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index ca6afa267070..2a77cdd27ca9 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -49,6 +49,7 @@ enum {
49 * IRQS_WAITING - irq is waiting 49 * IRQS_WAITING - irq is waiting
50 * IRQS_PENDING - irq is pending and replayed later 50 * IRQS_PENDING - irq is pending and replayed later
51 * IRQS_SUSPENDED - irq is suspended 51 * IRQS_SUSPENDED - irq is suspended
52 * IRQS_NMI - irq line is used to deliver NMIs
52 */ 53 */
53enum { 54enum {
54 IRQS_AUTODETECT = 0x00000001, 55 IRQS_AUTODETECT = 0x00000001,
@@ -60,6 +61,7 @@ enum {
60 IRQS_PENDING = 0x00000200, 61 IRQS_PENDING = 0x00000200,
61 IRQS_SUSPENDED = 0x00000800, 62 IRQS_SUSPENDED = 0x00000800,
62 IRQS_TIMINGS = 0x00001000, 63 IRQS_TIMINGS = 0x00001000,
64 IRQS_NMI = 0x00002000,
63}; 65};
64 66
65#include "debug.h" 67#include "debug.h"
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a4888ce4667a..9472ae987946 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -341,7 +341,7 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify)
341 /* The release function is promised process context */ 341 /* The release function is promised process context */
342 might_sleep(); 342 might_sleep();
343 343
344 if (!desc) 344 if (!desc || desc->istate & IRQS_NMI)
345 return -EINVAL; 345 return -EINVAL;
346 346
347 /* Complete initialisation of *notify */ 347 /* Complete initialisation of *notify */
@@ -550,6 +550,21 @@ bool disable_hardirq(unsigned int irq)
550} 550}
551EXPORT_SYMBOL_GPL(disable_hardirq); 551EXPORT_SYMBOL_GPL(disable_hardirq);
552 552
553/**
554 * disable_nmi_nosync - disable an nmi without waiting
555 * @irq: Interrupt to disable
556 *
557 * Disable the selected interrupt line. Disables and enables are
558 * nested.
559 * The interrupt to disable must have been requested through request_nmi.
560 * Unlike disable_nmi(), this function does not ensure existing
561 * instances of the IRQ handler have completed before returning.
562 */
563void disable_nmi_nosync(unsigned int irq)
564{
565 disable_irq_nosync(irq);
566}
567
553void __enable_irq(struct irq_desc *desc) 568void __enable_irq(struct irq_desc *desc)
554{ 569{
555 switch (desc->depth) { 570 switch (desc->depth) {
@@ -606,6 +621,20 @@ out:
606} 621}
607EXPORT_SYMBOL(enable_irq); 622EXPORT_SYMBOL(enable_irq);
608 623
624/**
625 * enable_nmi - enable handling of an nmi
626 * @irq: Interrupt to enable
627 *
628 * The interrupt to enable must have been requested through request_nmi.
629 * Undoes the effect of one call to disable_nmi(). If this
630 * matches the last disable, processing of interrupts on this
631 * IRQ line is re-enabled.
632 */
633void enable_nmi(unsigned int irq)
634{
635 enable_irq(irq);
636}
637
609static int set_irq_wake_real(unsigned int irq, unsigned int on) 638static int set_irq_wake_real(unsigned int irq, unsigned int on)
610{ 639{
611 struct irq_desc *desc = irq_to_desc(irq); 640 struct irq_desc *desc = irq_to_desc(irq);
@@ -641,6 +670,12 @@ int irq_set_irq_wake(unsigned int irq, unsigned int on)
641 if (!desc) 670 if (!desc)
642 return -EINVAL; 671 return -EINVAL;
643 672
673 /* Don't use NMIs as wake up interrupts please */
674 if (desc->istate & IRQS_NMI) {
675 ret = -EINVAL;
676 goto out_unlock;
677 }
678
644 /* wakeup-capable irqs can be shared between drivers that 679 /* wakeup-capable irqs can be shared between drivers that
645 * don't need to have the same sleep mode behaviors. 680 * don't need to have the same sleep mode behaviors.
646 */ 681 */
@@ -663,6 +698,8 @@ int irq_set_irq_wake(unsigned int irq, unsigned int on)
663 irqd_clear(&desc->irq_data, IRQD_WAKEUP_STATE); 698 irqd_clear(&desc->irq_data, IRQD_WAKEUP_STATE);
664 } 699 }
665 } 700 }
701
702out_unlock:
666 irq_put_desc_busunlock(desc, flags); 703 irq_put_desc_busunlock(desc, flags);
667 return ret; 704 return ret;
668} 705}
@@ -1125,6 +1162,39 @@ static void irq_release_resources(struct irq_desc *desc)
1125 c->irq_release_resources(d); 1162 c->irq_release_resources(d);
1126} 1163}
1127 1164
1165static bool irq_supports_nmi(struct irq_desc *desc)
1166{
1167 struct irq_data *d = irq_desc_get_irq_data(desc);
1168
1169#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
1170 /* Only IRQs directly managed by the root irqchip can be set as NMI */
1171 if (d->parent_data)
1172 return false;
1173#endif
1174 /* Don't support NMIs for chips behind a slow bus */
1175 if (d->chip->irq_bus_lock || d->chip->irq_bus_sync_unlock)
1176 return false;
1177
1178 return d->chip->flags & IRQCHIP_SUPPORTS_NMI;
1179}
1180
1181static int irq_nmi_setup(struct irq_desc *desc)
1182{
1183 struct irq_data *d = irq_desc_get_irq_data(desc);
1184 struct irq_chip *c = d->chip;
1185
1186 return c->irq_nmi_setup ? c->irq_nmi_setup(d) : -EINVAL;
1187}
1188
1189static void irq_nmi_teardown(struct irq_desc *desc)
1190{
1191 struct irq_data *d = irq_desc_get_irq_data(desc);
1192 struct irq_chip *c = d->chip;
1193
1194 if (c->irq_nmi_teardown)
1195 c->irq_nmi_teardown(d);
1196}
1197
1128static int 1198static int
1129setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary) 1199setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary)
1130{ 1200{
@@ -1299,9 +1369,17 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
1299 * fields must have IRQF_SHARED set and the bits which 1369 * fields must have IRQF_SHARED set and the bits which
1300 * set the trigger type must match. Also all must 1370 * set the trigger type must match. Also all must
1301 * agree on ONESHOT. 1371 * agree on ONESHOT.
1372 * Interrupt lines used for NMIs cannot be shared.
1302 */ 1373 */
1303 unsigned int oldtype; 1374 unsigned int oldtype;
1304 1375
1376 if (desc->istate & IRQS_NMI) {
1377 pr_err("Invalid attempt to share NMI for %s (irq %d) on irqchip %s.\n",
1378 new->name, irq, desc->irq_data.chip->name);
1379 ret = -EINVAL;
1380 goto out_unlock;
1381 }
1382
1305 /* 1383 /*
1306 * If nobody did set the configuration before, inherit 1384 * If nobody did set the configuration before, inherit
1307 * the one provided by the requester. 1385 * the one provided by the requester.
@@ -1753,6 +1831,59 @@ const void *free_irq(unsigned int irq, void *dev_id)
1753} 1831}
1754EXPORT_SYMBOL(free_irq); 1832EXPORT_SYMBOL(free_irq);
1755 1833
1834/* This function must be called with desc->lock held */
1835static const void *__cleanup_nmi(unsigned int irq, struct irq_desc *desc)
1836{
1837 const char *devname = NULL;
1838
1839 desc->istate &= ~IRQS_NMI;
1840
1841 if (!WARN_ON(desc->action == NULL)) {
1842 irq_pm_remove_action(desc, desc->action);
1843 devname = desc->action->name;
1844 unregister_handler_proc(irq, desc->action);
1845
1846 kfree(desc->action);
1847 desc->action = NULL;
1848 }
1849
1850 irq_settings_clr_disable_unlazy(desc);
1851 irq_shutdown(desc);
1852
1853 irq_release_resources(desc);
1854
1855 irq_chip_pm_put(&desc->irq_data);
1856 module_put(desc->owner);
1857
1858 return devname;
1859}
1860
1861const void *free_nmi(unsigned int irq, void *dev_id)
1862{
1863 struct irq_desc *desc = irq_to_desc(irq);
1864 unsigned long flags;
1865 const void *devname;
1866
1867 if (!desc || WARN_ON(!(desc->istate & IRQS_NMI)))
1868 return NULL;
1869
1870 if (WARN_ON(irq_settings_is_per_cpu_devid(desc)))
1871 return NULL;
1872
1873 /* NMI still enabled */
1874 if (WARN_ON(desc->depth == 0))
1875 disable_nmi_nosync(irq);
1876
1877 raw_spin_lock_irqsave(&desc->lock, flags);
1878
1879 irq_nmi_teardown(desc);
1880 devname = __cleanup_nmi(irq, desc);
1881
1882 raw_spin_unlock_irqrestore(&desc->lock, flags);
1883
1884 return devname;
1885}
1886
1756/** 1887/**
1757 * request_threaded_irq - allocate an interrupt line 1888 * request_threaded_irq - allocate an interrupt line
1758 * @irq: Interrupt line to allocate 1889 * @irq: Interrupt line to allocate
@@ -1922,6 +2053,101 @@ int request_any_context_irq(unsigned int irq, irq_handler_t handler,
1922} 2053}
1923EXPORT_SYMBOL_GPL(request_any_context_irq); 2054EXPORT_SYMBOL_GPL(request_any_context_irq);
1924 2055
2056/**
2057 * request_nmi - allocate an interrupt line for NMI delivery
2058 * @irq: Interrupt line to allocate
2059 * @handler: Function to be called when the IRQ occurs.
2060 * Threaded handler for threaded interrupts.
2061 * @irqflags: Interrupt type flags
2062 * @name: An ascii name for the claiming device
2063 * @dev_id: A cookie passed back to the handler function
2064 *
2065 * This call allocates interrupt resources and enables the
2066 * interrupt line and IRQ handling. It sets up the IRQ line
2067 * to be handled as an NMI.
2068 *
2069 * An interrupt line delivering NMIs cannot be shared and IRQ handling
2070 * cannot be threaded.
2071 *
2072 * Interrupt lines requested for NMI delivering must produce per cpu
2073 * interrupts and have auto enabling setting disabled.
2074 *
2075 * Dev_id must be globally unique. Normally the address of the
2076 * device data structure is used as the cookie. Since the handler
2077 * receives this value it makes sense to use it.
2078 *
2079 * If the interrupt line cannot be used to deliver NMIs, function
2080 * will fail and return a negative value.
2081 */
2082int request_nmi(unsigned int irq, irq_handler_t handler,
2083 unsigned long irqflags, const char *name, void *dev_id)
2084{
2085 struct irqaction *action;
2086 struct irq_desc *desc;
2087 unsigned long flags;
2088 int retval;
2089
2090 if (irq == IRQ_NOTCONNECTED)
2091 return -ENOTCONN;
2092
2093 /* NMI cannot be shared, used for Polling */
2094 if (irqflags & (IRQF_SHARED | IRQF_COND_SUSPEND | IRQF_IRQPOLL))
2095 return -EINVAL;
2096
2097 if (!(irqflags & IRQF_PERCPU))
2098 return -EINVAL;
2099
2100 if (!handler)
2101 return -EINVAL;
2102
2103 desc = irq_to_desc(irq);
2104
2105 if (!desc || irq_settings_can_autoenable(desc) ||
2106 !irq_settings_can_request(desc) ||
2107 WARN_ON(irq_settings_is_per_cpu_devid(desc)) ||
2108 !irq_supports_nmi(desc))
2109 return -EINVAL;
2110
2111 action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
2112 if (!action)
2113 return -ENOMEM;
2114
2115 action->handler = handler;
2116 action->flags = irqflags | IRQF_NO_THREAD | IRQF_NOBALANCING;
2117 action->name = name;
2118 action->dev_id = dev_id;
2119
2120 retval = irq_chip_pm_get(&desc->irq_data);
2121 if (retval < 0)
2122 goto err_out;
2123
2124 retval = __setup_irq(irq, desc, action);
2125 if (retval)
2126 goto err_irq_setup;
2127
2128 raw_spin_lock_irqsave(&desc->lock, flags);
2129
2130 /* Setup NMI state */
2131 desc->istate |= IRQS_NMI;
2132 retval = irq_nmi_setup(desc);
2133 if (retval) {
2134 __cleanup_nmi(irq, desc);
2135 raw_spin_unlock_irqrestore(&desc->lock, flags);
2136 return -EINVAL;
2137 }
2138
2139 raw_spin_unlock_irqrestore(&desc->lock, flags);
2140
2141 return 0;
2142
2143err_irq_setup:
2144 irq_chip_pm_put(&desc->irq_data);
2145err_out:
2146 kfree(action);
2147
2148 return retval;
2149}
2150
1925void enable_percpu_irq(unsigned int irq, unsigned int type) 2151void enable_percpu_irq(unsigned int irq, unsigned int type)
1926{ 2152{
1927 unsigned int cpu = smp_processor_id(); 2153 unsigned int cpu = smp_processor_id();