]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - arch/x86/kernel/irq_64.c
x86_64: fix the check in stack_overflow_check
[mirror_ubuntu-zesty-kernel.git] / arch / x86 / kernel / irq_64.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
3 *
4 * This file contains the lowest level x86_64-specific interrupt
5 * entry and irq statistics code. All the remaining irq logic is
6 * done by the generic kernel/irq/ code and in the
7 * x86_64-specific irq controller code. (e.g. i8259.c and
8 * io_apic.c.)
9 */
10
11#include <linux/kernel_stat.h>
12#include <linux/interrupt.h>
13#include <linux/seq_file.h>
14#include <linux/module.h>
76e4f660 15#include <linux/delay.h>
1da177e4
LT
16#include <asm/uaccess.h>
17#include <asm/io_apic.h>
95833c83 18#include <asm/idle.h>
2fb12a9b 19#include <asm/smp.h>
1da177e4 20
4961f10e
ES
21#ifdef CONFIG_DEBUG_STACKOVERFLOW
22/*
23 * Probabilistic stack overflow check:
24 *
25 * Only check the stack in process context, because everything else
26 * runs on the big interrupt stacks. Checking reliably is too expensive,
27 * so we just check from interrupts.
28 */
29static inline void stack_overflow_check(struct pt_regs *regs)
30{
c9f4f06d 31 u64 curbase = (u64)task_stack_page(current);
3aeb95d5 32 static unsigned long warned = INITIAL_JIFFIES - 60*HZ;
4961f10e 33
65ea5b03 34 if (regs->sp >= curbase && regs->sp <= curbase + THREAD_SIZE &&
3aeb95d5 35 regs->sp < curbase + sizeof(struct thread_info) +
36 sizeof(struct pt_regs) + 128 &&
37 time_after(jiffies, warned + 60*HZ)) {
65ea5b03
PA
38 printk("do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n",
39 current->comm, curbase, regs->sp);
4961f10e
ES
40 show_stack(NULL,NULL);
41 warned = jiffies;
42 }
43}
44#endif
45
1da177e4
LT
46/*
47 * do_IRQ handles all normal device IRQ's (the special
48 * SMP cross-CPU interrupts have their own specific
49 * handlers).
50 */
51asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
7d12e780
DH
52{
53 struct pt_regs *old_regs = set_irq_regs(regs);
46926b67 54 struct irq_desc *desc;
7d12e780 55
19eadf98 56 /* high bit used in ret_from_ code */
65ea5b03 57 unsigned vector = ~regs->orig_ax;
e500f574
EB
58 unsigned irq;
59
60 exit_idle();
61 irq_enter();
550f2299 62 irq = __get_cpu_var(vector_irq)[vector];
1da177e4 63
4961f10e
ES
64#ifdef CONFIG_DEBUG_STACKOVERFLOW
65 stack_overflow_check(regs);
66#endif
d3696cf7 67
cb5bc832 68 desc = irq_to_desc(irq);
46926b67
YL
69 if (likely(desc))
70 generic_handle_irq_desc(irq, desc);
2fb12a9b
EB
71 else {
72 if (!disable_apic)
73 ack_APIC_irq();
74
75 if (printk_ratelimit())
76 printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n",
77 __func__, smp_processor_id(), vector);
78 }
d3696cf7 79
1da177e4
LT
80 irq_exit();
81
7d12e780 82 set_irq_regs(old_regs);
1da177e4
LT
83 return 1;
84}
85
76e4f660
AR
86#ifdef CONFIG_HOTPLUG_CPU
87void fixup_irqs(cpumask_t map)
88{
89 unsigned int irq;
90 static int warned;
2c6927a3 91 struct irq_desc *desc;
76e4f660 92
2c6927a3 93 for_each_irq_desc(irq, desc) {
76e4f660 94 cpumask_t mask;
48d8d7ee
SS
95 int break_affinity = 0;
96 int set_affinity = 1;
97
76e4f660
AR
98 if (irq == 2)
99 continue;
100
48d8d7ee 101 /* interrupt's are disabled at this point */
08678b08 102 spin_lock(&desc->lock);
48d8d7ee
SS
103
104 if (!irq_has_action(irq) ||
08678b08
YL
105 cpus_equal(desc->affinity, map)) {
106 spin_unlock(&desc->lock);
48d8d7ee
SS
107 continue;
108 }
109
08678b08 110 cpus_and(mask, desc->affinity, map);
48d8d7ee
SS
111 if (cpus_empty(mask)) {
112 break_affinity = 1;
76e4f660
AR
113 mask = map;
114 }
48d8d7ee 115
08678b08
YL
116 if (desc->chip->mask)
117 desc->chip->mask(irq);
48d8d7ee 118
08678b08
YL
119 if (desc->chip->set_affinity)
120 desc->chip->set_affinity(irq, mask);
48d8d7ee
SS
121 else if (!(warned++))
122 set_affinity = 0;
123
08678b08
YL
124 if (desc->chip->unmask)
125 desc->chip->unmask(irq);
48d8d7ee 126
08678b08 127 spin_unlock(&desc->lock);
48d8d7ee
SS
128
129 if (break_affinity && set_affinity)
130 printk("Broke affinity for irq %i\n", irq);
131 else if (!set_affinity)
76e4f660
AR
132 printk("Cannot set affinity for irq %i\n", irq);
133 }
134
135 /* That doesn't seem sufficient. Give it 1ms. */
136 local_irq_enable();
137 mdelay(1);
138 local_irq_disable();
139}
140#endif
ed6b676c
AK
141
142extern void call_softirq(void);
143
144asmlinkage void do_softirq(void)
145{
146 __u32 pending;
147 unsigned long flags;
148
149 if (in_interrupt())
150 return;
151
152 local_irq_save(flags);
153 pending = local_softirq_pending();
154 /* Switch to interrupt stack */
2601e64d 155 if (pending) {
ed6b676c 156 call_softirq();
2601e64d
IM
157 WARN_ON_ONCE(softirq_count());
158 }
ed6b676c
AK
159 local_irq_restore(flags);
160}