linux/arch/x86/kernel/irq_64.c
<<
>>
Prefs
   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#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{
  31        u64 curbase = (u64)task_stack_page(current);
  32        static unsigned long warned = -60*HZ;
  33
  34        if (regs->sp >= curbase && regs->sp <= curbase + THREAD_SIZE &&
  35            regs->sp <  curbase + sizeof(struct thread_info) + 128 &&
  36            time_after(jiffies, warned + 60*HZ)) {
  37                printk("do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n",
  38                       current->comm, curbase, regs->sp);
  39                show_stack(NULL,NULL);
  40                warned = jiffies;
  41        }
  42}
  43#endif
  44
  45/*
  46 * do_IRQ handles all normal device IRQ's (the special
  47 * SMP cross-CPU interrupts have their own specific
  48 * handlers).
  49 */
  50asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
  51{
  52        struct pt_regs *old_regs = set_irq_regs(regs);
  53        struct irq_desc *desc;
  54
  55        /* high bit used in ret_from_ code  */
  56        unsigned vector = ~regs->orig_ax;
  57        unsigned irq;
  58
  59        exit_idle();
  60        irq_enter();
  61        irq = __get_cpu_var(vector_irq)[vector];
  62
  63#ifdef CONFIG_DEBUG_STACKOVERFLOW
  64        stack_overflow_check(regs);
  65#endif
  66
  67        desc = irq_to_desc(irq);
  68        if (likely(desc))
  69                generic_handle_irq_desc(irq, desc);
  70        else {
  71                if (!disable_apic)
  72                        ack_APIC_irq();
  73
  74                if (printk_ratelimit())
  75                        printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n",
  76                                __func__, smp_processor_id(), vector);
  77        }
  78
  79        irq_exit();
  80
  81        set_irq_regs(old_regs);
  82        return 1;
  83}
  84
  85#ifdef CONFIG_HOTPLUG_CPU
  86void fixup_irqs(cpumask_t map)
  87{
  88        unsigned int irq;
  89        static int warned;
  90        struct irq_desc *desc;
  91
  92        for_each_irq_desc(irq, desc) {
  93                cpumask_t mask;
  94                int break_affinity = 0;
  95                int set_affinity = 1;
  96
  97                if (irq == 2)
  98                        continue;
  99
 100                /* interrupt's are disabled at this point */
 101                spin_lock(&desc->lock);
 102
 103                if (!irq_has_action(irq) ||
 104                    cpus_equal(desc->affinity, map)) {
 105                        spin_unlock(&desc->lock);
 106                        continue;
 107                }
 108
 109                cpus_and(mask, desc->affinity, map);
 110                if (cpus_empty(mask)) {
 111                        break_affinity = 1;
 112                        mask = map;
 113                }
 114
 115                if (desc->chip->mask)
 116                        desc->chip->mask(irq);
 117
 118                if (desc->chip->set_affinity)
 119                        desc->chip->set_affinity(irq, mask);
 120                else if (!(warned++))
 121                        set_affinity = 0;
 122
 123                if (desc->chip->unmask)
 124                        desc->chip->unmask(irq);
 125
 126                spin_unlock(&desc->lock);
 127
 128                if (break_affinity && set_affinity)
 129                        printk("Broke affinity for irq %i\n", irq);
 130                else if (!set_affinity)
 131                        printk("Cannot set affinity for irq %i\n", irq);
 132        }
 133
 134        /* That doesn't seem sufficient.  Give it 1ms. */
 135        local_irq_enable();
 136        mdelay(1);
 137        local_irq_disable();
 138}
 139#endif
 140
 141extern void call_softirq(void);
 142
 143asmlinkage void do_softirq(void)
 144{
 145        __u32 pending;
 146        unsigned long flags;
 147
 148        if (in_interrupt())
 149                return;
 150
 151        local_irq_save(flags);
 152        pending = local_softirq_pending();
 153        /* Switch to interrupt stack */
 154        if (pending) {
 155                call_softirq();
 156                WARN_ON_ONCE(softirq_count());
 157        }
 158        local_irq_restore(flags);
 159}
 160
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.