OSDN Git Service

x86: irq_32 move 4kstacks code to one place
authorThomas Gleixner <tglx@linutronix.de>
Mon, 5 May 2008 16:13:50 +0000 (18:13 +0200)
committerIngo Molnar <mingo@elte.hu>
Mon, 12 May 2008 19:28:06 +0000 (21:28 +0200)
Move the 4KSTACKS related code to one place. This allows to un#ifdef
do_IRQ() and share the executed on stack for the stack overflow printk
and the softirq call.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/irq_32.c

index 1c470d2..4e3e8ec 100644 (file)
@@ -83,26 +83,28 @@ union irq_ctx {
 static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
 static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
 
-static inline void call_on_stack(void *func, void *stack,
-                                unsigned long arg1, void *arg2)
+static char softirq_stack[NR_CPUS * THREAD_SIZE]
+               __attribute__((__section__(".bss.page_aligned")));
+
+static char hardirq_stack[NR_CPUS * THREAD_SIZE]
+               __attribute__((__section__(".bss.page_aligned")));
+
+static void call_on_stack(void *func, void *stack)
 {
-       unsigned long bx;
-
-       asm volatile(
-                       "       xchgl  %%ebx,%%esp    \n"
-                       "       call   *%%edi         \n"
-                       "       movl   %%ebx,%%esp    \n"
-                       : "=a" (arg1), "=d" (arg2), "=b" (bx)
-                       :  "0" (arg1),   "1" (arg2),  "2" (stack),
-                          "D" (func)
-                       : "memory", "cc", "ecx");
+       asm volatile("xchgl     %%ebx,%%esp     \n"
+                    "call      *%%edi          \n"
+                    "movl      %%ebx,%%esp     \n"
+                    : "=b" (stack)
+                    : "0" (stack),
+                      "D"(func)
+                    : "memory", "cc", "edx", "ecx", "eax");
 }
 
 static inline int
 execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
 {
        union irq_ctx *curctx, *irqctx;
-       u32 *isp;
+       u32 *isp, arg1, arg2;
 
        curctx = (union irq_ctx *) current_thread_info();
        irqctx = hardirq_ctx[smp_processor_id()];
@@ -130,64 +132,22 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
                (curctx->tinfo.preempt_count & SOFTIRQ_MASK);
 
        if (unlikely(overflow))
-               call_on_stack(print_stack_overflow, isp, 0, NULL);
-
-       call_on_stack(desc->handle_irq, isp, irq, desc);
-
-       return 1;
-}
-
-#else
-static inline int
-execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
-#endif
-
-/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
- */
-unsigned int do_IRQ(struct pt_regs *regs)
-{
-       struct pt_regs *old_regs;
-       /* high bit used in ret_from_ code */
-       int overflow, irq = ~regs->orig_ax;
-       struct irq_desc *desc = irq_desc + irq;
-
-       if (unlikely((unsigned)irq >= NR_IRQS)) {
-               printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
-                                       __func__, irq);
-               BUG();
-       }
-
-       old_regs = set_irq_regs(regs);
-       irq_enter();
-
-       overflow = check_stack_overflow();
-
-       if (!execute_on_irq_stack(overflow, desc, irq)) {
-               if (unlikely(overflow))
-                       print_stack_overflow();
-               desc->handle_irq(irq, desc);
-       }
-
-       irq_exit();
-       set_irq_regs(old_regs);
+               call_on_stack(print_stack_overflow, isp);
+
+       asm volatile("xchgl     %%ebx,%%esp     \n"
+                    "call      *%%edi          \n"
+                    "movl      %%ebx,%%esp     \n"
+                    : "=a" (arg1), "=d" (arg2), "=b" (isp)
+                    :  "0" (irq),   "1" (desc),  "2" (isp),
+                       "D" (desc->handle_irq)
+                    : "memory", "cc", "ecx");
        return 1;
 }
 
-#ifdef CONFIG_4KSTACKS
-
-static char softirq_stack[NR_CPUS * THREAD_SIZE]
-               __attribute__((__section__(".bss.page_aligned")));
-
-static char hardirq_stack[NR_CPUS * THREAD_SIZE]
-               __attribute__((__section__(".bss.page_aligned")));
-
 /*
  * allocate per-cpu stacks for hardirq and for softirq processing
  */
-void irq_ctx_init(int cpu)
+void __cpuinit irq_ctx_init(int cpu)
 {
        union irq_ctx *irqctx;
 
@@ -195,25 +155,25 @@ void irq_ctx_init(int cpu)
                return;
 
        irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE];
-       irqctx->tinfo.task              = NULL;
-       irqctx->tinfo.exec_domain       = NULL;
-       irqctx->tinfo.cpu               = cpu;
-       irqctx->tinfo.preempt_count     = HARDIRQ_OFFSET;
-       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
+       irqctx->tinfo.task              = NULL;
+       irqctx->tinfo.exec_domain       = NULL;
+       irqctx->tinfo.cpu               = cpu;
+       irqctx->tinfo.preempt_count     = HARDIRQ_OFFSET;
+       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
 
        hardirq_ctx[cpu] = irqctx;
 
        irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE];
-       irqctx->tinfo.task              = NULL;
-       irqctx->tinfo.exec_domain       = NULL;
-       irqctx->tinfo.cpu               = cpu;
-       irqctx->tinfo.preempt_count     = 0;
-       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
+       irqctx->tinfo.task              = NULL;
+       irqctx->tinfo.exec_domain       = NULL;
+       irqctx->tinfo.cpu               = cpu;
+       irqctx->tinfo.preempt_count     = 0;
+       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
 
        softirq_ctx[cpu] = irqctx;
 
-       printk("CPU %u irqstacks, hard=%p soft=%p\n",
-               cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
+       printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n",
+              cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
 }
 
 void irq_ctx_exit(int cpu)
@@ -242,25 +202,56 @@ asmlinkage void do_softirq(void)
                /* build the stack frame on the softirq stack */
                isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
 
-               asm volatile(
-                       "       xchgl   %%ebx,%%esp     \n"
-                       "       call    __do_softirq    \n"
-                       "       movl    %%ebx,%%esp     \n"
-                       : "=b"(isp)
-                       : "0"(isp)
-                       : "memory", "cc", "edx", "ecx", "eax"
-               );
+               call_on_stack(__do_softirq, isp);
                /*
                 * Shouldnt happen, we returned above if in_interrupt():
-                */
+                */
                WARN_ON_ONCE(softirq_count());
        }
 
        local_irq_restore(flags);
 }
+
+#else
+static inline int
+execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
 #endif
 
 /*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+unsigned int do_IRQ(struct pt_regs *regs)
+{
+       struct pt_regs *old_regs;
+       /* high bit used in ret_from_ code */
+       int overflow, irq = ~regs->orig_ax;
+       struct irq_desc *desc = irq_desc + irq;
+
+       if (unlikely((unsigned)irq >= NR_IRQS)) {
+               printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+                                       __func__, irq);
+               BUG();
+       }
+
+       old_regs = set_irq_regs(regs);
+       irq_enter();
+
+       overflow = check_stack_overflow();
+
+       if (!execute_on_irq_stack(overflow, desc, irq)) {
+               if (unlikely(overflow))
+                       print_stack_overflow();
+               desc->handle_irq(irq, desc);
+       }
+
+       irq_exit();
+       set_irq_regs(old_regs);
+       return 1;
+}
+
+/*
  * Interrupt statistics:
  */