1 /* 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> 15 #include <linux/delay.h> 16 #include <asm/uaccess.h> 17 #include <asm/io_apic.h> 18 #include <asm/idle.h> 19 #include <asm/smp.h> 20 21 atomic_t irq_err_count; 22 23 #ifdef CONFIG_DEBUG_STACKOVERFLOW 24 /* 25 * Probabilistic stack overflow check: 26 * 27 * Only check the stack in process context, because everything else 28 * runs on the big interrupt stacks. Checking reliably is too expensive, 29 * so we just check from interrupts. 30 */ 31 static inline void stack_overflow_check(struct pt_regs *regs) 32 { 33 u64 curbase = (u64)task_stack_page(current); 34 static unsigned long warned = -60*HZ; 35 36 if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE && 37 regs->rsp < curbase + sizeof(struct thread_info) + 128 && 38 time_after(jiffies, warned + 60*HZ)) { 39 printk("do_IRQ: %s near stack overflow (cur:%Lx,rsp:%lx)\n", 40 current->comm, curbase, regs->rsp); 41 show_stack(NULL,NULL); 42 warned = jiffies; 43 } 44 } 45 #endif 46 47 /* 48 * Generic, controller-independent functions: 49 */ 50 51 int show_interrupts(struct seq_file *p, void *v) 52 { 53 int i = *(loff_t *) v, j; 54 struct irqaction * action; 55 unsigned long flags; 56 57 if (i == 0) { 58 seq_printf(p, " "); 59 for_each_online_cpu(j) 60 seq_printf(p, "CPU%-8d",j); 61 seq_putc(p, '\n'); 62 } 63 64 if (i < NR_IRQS) { 65 spin_lock_irqsave(&irq_desc[i].lock, flags); 66 action = irq_desc[i].action; 67 if (!action) 68 goto skip; 69 seq_printf(p, "%3d: ",i); 70 #ifndef CONFIG_SMP 71 seq_printf(p, "%10u ", kstat_irqs(i)); 72 #else 73 for_each_online_cpu(j) 74 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); 75 #endif 76 seq_printf(p, " %8s", irq_desc[i].chip->name); 77 seq_printf(p, "-%-8s", irq_desc[i].name); 78 79 seq_printf(p, " %s", action->name); 80 for (action=action->next; action; action = action->next) 81 seq_printf(p, ", %s", action->name); 82 seq_putc(p, '\n'); 83 skip: 84 spin_unlock_irqrestore(&irq_desc[i].lock, flags); 85 } else if (i == NR_IRQS) { 86 seq_printf(p, "NMI: "); 87 for_each_online_cpu(j) 88 seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count); 89 seq_putc(p, '\n'); 90 seq_printf(p, "LOC: "); 91 for_each_online_cpu(j) 92 seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs); 93 seq_putc(p, '\n'); 94 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); 95 } 96 return 0; 97 } 98 99 /* 100 * do_IRQ handles all normal device IRQ's (the special 101 * SMP cross-CPU interrupts have their own specific 102 * handlers). 103 */ 104 asmlinkage unsigned int do_IRQ(struct pt_regs *regs) 105 { 106 struct pt_regs *old_regs = set_irq_regs(regs); 107 108 /* high bit used in ret_from_ code */ 109 unsigned vector = ~regs->orig_rax; 110 unsigned irq; 111 112 exit_idle(); 113 irq_enter(); 114 irq = __get_cpu_var(vector_irq)[vector]; 115 116 #ifdef CONFIG_DEBUG_STACKOVERFLOW 117 stack_overflow_check(regs); 118 #endif 119 120 if (likely(irq < NR_IRQS)) 121 generic_handle_irq(irq); 122 else { 123 if (!disable_apic) 124 ack_APIC_irq(); 125 126 if (printk_ratelimit()) 127 printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n", 128 __func__, smp_processor_id(), vector); 129 } 130 131 irq_exit(); 132 133 set_irq_regs(old_regs); 134 return 1; 135 } 136 137 #ifdef CONFIG_HOTPLUG_CPU 138 void fixup_irqs(cpumask_t map) 139 { 140 unsigned int irq; 141 static int warned; 142 143 for (irq = 0; irq < NR_IRQS; irq++) { 144 cpumask_t mask; 145 int break_affinity = 0; 146 int set_affinity = 1; 147 148 if (irq == 2) 149 continue; 150 151 /* interrupt's are disabled at this point */ 152 spin_lock(&irq_desc[irq].lock); 153 154 if (!irq_has_action(irq) || 155 cpus_equal(irq_desc[irq].affinity, map)) { 156 spin_unlock(&irq_desc[irq].lock); 157 continue; 158 } 159 160 cpus_and(mask, irq_desc[irq].affinity, map); 161 if (cpus_empty(mask)) { 162 break_affinity = 1; 163 mask = map; 164 } 165 166 if (irq_desc[irq].chip->mask) 167 irq_desc[irq].chip->mask(irq); 168 169 if (irq_desc[irq].chip->set_affinity) 170 irq_desc[irq].chip->set_affinity(irq, mask); 171 else if (!(warned++)) 172 set_affinity = 0; 173 174 if (irq_desc[irq].chip->unmask) 175 irq_desc[irq].chip->unmask(irq); 176 177 spin_unlock(&irq_desc[irq].lock); 178 179 if (break_affinity && set_affinity) 180 printk("Broke affinity for irq %i\n", irq); 181 else if (!set_affinity) 182 printk("Cannot set affinity for irq %i\n", irq); 183 } 184 185 /* That doesn't seem sufficient. Give it 1ms. */ 186 local_irq_enable(); 187 mdelay(1); 188 local_irq_disable(); 189 } 190 #endif 191 192 extern void call_softirq(void); 193 194 asmlinkage void do_softirq(void) 195 { 196 __u32 pending; 197 unsigned long flags; 198 199 if (in_interrupt()) 200 return; 201 202 local_irq_save(flags); 203 pending = local_softirq_pending(); 204 /* Switch to interrupt stack */ 205 if (pending) { 206 call_softirq(); 207 WARN_ON_ONCE(softirq_count()); 208 } 209 local_irq_restore(flags); 210 } 211