]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
m68k: Simplify low level interrupt handling code
authorThomas Gleixner <tglx@linutronix.de>
Mon, 11 Nov 2013 20:01:03 +0000 (21:01 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 13 Nov 2013 19:21:46 +0000 (20:21 +0100)
The low level interrupt entry code of m68k contains the following:

    add_preempt_count(HARDIRQ_OFFSET);

    do_IRQ();
irq_enter();
    add_preempt_count(HARDIRQ_OFFSET);
handle_interrupt();
irq_exit();
    sub_preempt_count(HARDIRQ_OFFSET);
    if (in_interrupt())
               return; <---- On m68k always taken!
    if (local_softirq_pending())
               do_softirq();

    sub_preempt_count(HARDIRQ_OFFSET);
    if (in_hardirq())
       return;
    if (status_on_stack_has_interrupt_priority_mask > 0)
       return;
    if (local_softirq_pending())
       do_softirq();

    ret_from_exception:
if (interrupted_context_is_kernel)
   return:
....

I tried to find a proper explanation for this, but the changelog is
sparse and there are no mails explaining it further. But obviously
this relates to the interrupt priority levels of the m68k and tries to
be extra clever with nested interrupts. Though this cleverness just
adds code bloat to the interrupt hotpath.

For the common case of non nested interrupts the code runs through two
extra conditionals to the only important one, which checks whether the
return is to kernel or user space.

For the nested case the checks for in_hardirq() and the priority mask
value on stack catch only the case where the nested interrupt happens
inside the hard irq context of the first interrupt. If the nested
interrupt happens while the first interrupt handles soft interrupts,
then these extra checks buy nothing. The nested interrupt will fall
through to the final kernel/user space return check at
ret_from_exception.

Changing the code flow in the following way:

    do_IRQ();
irq_enter();
    add_preempt_count(HARDIRQ_OFFSET);
handle_interrupt();
irq_exit();
    sub_preempt_count(HARDIRQ_OFFSET);
    if (in_interrupt())
               return;
    if (local_softirq_pending())
               do_softirq();

    ret_from_exception:
if (interrupted_context_is_kernel)
   return:

makes the region protected by the hardirq count slightly smaller and
the softirq handling is invoked with a minimal deeper stack. But
otherwise it's completely functional equivalent and saves 104 bytes of
text in arch/m68k/kernel/entry.o.

This modification allows us further to get rid of the limitations
which m68k puts on the preempt_count layout, so we can make the
preempt count bits completely generic.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Linux/m68k <linux-m68k@vger.kernel.org>
Cc: Andreas Schwab <schwab@linux-m68k.org>
Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1311112052360.30673@ionos.tec.linutronix.de
arch/m68k/kernel/entry.S
arch/m68k/kernel/ints.c
arch/m68k/platform/68000/entry.S
arch/m68k/platform/68360/entry.S

index a78f5649e8decf3fbd80c3d1a54567644f6fd385..b54ac7aba850eaf02ac995a857e673102039f3be 100644 (file)
@@ -45,7 +45,7 @@
 .globl system_call, buserr, trap, resume
 .globl sys_call_table
 .globl __sys_fork, __sys_clone, __sys_vfork
-.globl ret_from_interrupt, bad_interrupt
+.globl bad_interrupt
 .globl auto_irqhandler_fixup
 .globl user_irqvec_fixup
 
@@ -275,8 +275,6 @@ do_delayed_trace:
 ENTRY(auto_inthandler)
        SAVE_ALL_INT
        GET_CURRENT(%d0)
-       movel   %d0,%a1
-       addqb   #1,%a1@(TINFO_PREEMPT+1)
                                        |  put exception # in d0
        bfextu  %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
        subw    #VEC_SPUR,%d0
@@ -286,32 +284,13 @@ ENTRY(auto_inthandler)
 auto_irqhandler_fixup = . + 2
        jsr     do_IRQ                  |  process the IRQ
        addql   #8,%sp                  |  pop parameters off stack
-
-ret_from_interrupt:
-       movel   %curptr@(TASK_STACK),%a1
-       subqb   #1,%a1@(TINFO_PREEMPT+1)
-       jeq     ret_from_last_interrupt
-2:     RESTORE_ALL
-
-       ALIGN
-ret_from_last_interrupt:
-       moveq   #(~ALLOWINT>>8)&0xff,%d0
-       andb    %sp@(PT_OFF_SR),%d0
-       jne     2b
-
-       /* check if we need to do software interrupts */
-       tstl    irq_stat+CPUSTAT_SOFTIRQ_PENDING
-       jeq     .Lret_from_exception
-       pea     ret_from_exception
-       jra     do_softirq
+       jra     ret_from_exception
 
 /* Handler for user defined interrupt vectors */
 
 ENTRY(user_inthandler)
        SAVE_ALL_INT
        GET_CURRENT(%d0)
-       movel   %d0,%a1
-       addqb   #1,%a1@(TINFO_PREEMPT+1)
                                        |  put exception # in d0
        bfextu  %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
 user_irqvec_fixup = . + 2
@@ -321,29 +300,18 @@ user_irqvec_fixup = . + 2
        movel   %d0,%sp@-               |  put vector # on stack
        jsr     do_IRQ                  |  process the IRQ
        addql   #8,%sp                  |  pop parameters off stack
-
-       movel   %curptr@(TASK_STACK),%a1
-       subqb   #1,%a1@(TINFO_PREEMPT+1)
-       jeq     ret_from_last_interrupt
-       RESTORE_ALL
+       jra     ret_from_exception
 
 /* Handler for uninitialized and spurious interrupts */
 
 ENTRY(bad_inthandler)
        SAVE_ALL_INT
        GET_CURRENT(%d0)
-       movel   %d0,%a1
-       addqb   #1,%a1@(TINFO_PREEMPT+1)
 
        movel   %sp,%sp@-
        jsr     handle_badint
        addql   #4,%sp
-
-       movel   %curptr@(TASK_STACK),%a1
-       subqb   #1,%a1@(TINFO_PREEMPT+1)
-       jeq     ret_from_last_interrupt
-       RESTORE_ALL
-
+       jra     ret_from_exception
 
 resume:
        /*
index 4d7da384eea03d5a1101859a5814c7dccce53a9e..077d3a70fed1995611f89e0f5795c40da07378df 100644 (file)
@@ -58,12 +58,6 @@ void __init init_IRQ(void)
 {
        int i;
 
-       /* assembly irq entry code relies on this... */
-       if (HARDIRQ_MASK != 0x00ff0000) {
-               extern void hardirq_mask_is_broken(void);
-               hardirq_mask_is_broken();
-       }
-
        for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
                irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq);
 
index 7f91c2fde5096b9eaaef2e33334cf0339b896352..23ac054c6e1ad929fa40e8aa033e51251c96538d 100644 (file)
@@ -27,7 +27,6 @@
 .globl ret_from_exception
 .globl ret_from_signal
 .globl sys_call_table
-.globl ret_from_interrupt
 .globl bad_interrupt
 .globl inthandler1
 .globl inthandler2
@@ -137,7 +136,7 @@ inthandler1:
        movel   #65,%sp@-               /*  put vector # on stack*/
        jbsr    process_int             /*  process the IRQ*/
 3:             addql   #8,%sp                  /*  pop parameters off stack*/
-       bra     ret_from_interrupt
+       bra     ret_from_exception
 
 inthandler2:
        SAVE_ALL_INT
@@ -148,7 +147,7 @@ inthandler2:
        movel   #66,%sp@-               /*  put vector # on stack*/
        jbsr    process_int             /*  process the IRQ*/
 3:             addql   #8,%sp                  /*  pop parameters off stack*/
-       bra     ret_from_interrupt
+       bra     ret_from_exception
 
 inthandler3:
        SAVE_ALL_INT
@@ -159,7 +158,7 @@ inthandler3:
        movel   #67,%sp@-               /*  put vector # on stack*/
        jbsr    process_int             /*  process the IRQ*/
 3:             addql   #8,%sp                  /*  pop parameters off stack*/
-       bra     ret_from_interrupt
+       bra     ret_from_exception
 
 inthandler4:
        SAVE_ALL_INT
@@ -170,7 +169,7 @@ inthandler4:
        movel   #68,%sp@-               /*  put vector # on stack*/
        jbsr    process_int             /*  process the IRQ*/
 3:             addql   #8,%sp                  /*  pop parameters off stack*/
-       bra     ret_from_interrupt
+       bra     ret_from_exception
 
 inthandler5:
        SAVE_ALL_INT
@@ -181,7 +180,7 @@ inthandler5:
        movel   #69,%sp@-               /*  put vector # on stack*/
        jbsr    process_int             /*  process the IRQ*/
 3:             addql   #8,%sp                  /*  pop parameters off stack*/
-       bra     ret_from_interrupt
+       bra     ret_from_exception
 
 inthandler6:
        SAVE_ALL_INT
@@ -192,7 +191,7 @@ inthandler6:
        movel   #70,%sp@-               /*  put vector # on stack*/
        jbsr    process_int             /*  process the IRQ*/
 3:             addql   #8,%sp                  /*  pop parameters off stack*/
-       bra     ret_from_interrupt
+       bra     ret_from_exception
 
 inthandler7:
        SAVE_ALL_INT
@@ -203,7 +202,7 @@ inthandler7:
        movel   #71,%sp@-               /*  put vector # on stack*/
        jbsr    process_int             /*  process the IRQ*/
 3:             addql   #8,%sp                  /*  pop parameters off stack*/
-       bra     ret_from_interrupt
+       bra     ret_from_exception
 
 inthandler:
        SAVE_ALL_INT
@@ -214,23 +213,7 @@ inthandler:
        movel   %d0,%sp@-               /*  put vector # on stack*/
        jbsr    process_int             /*  process the IRQ*/
 3:             addql   #8,%sp                  /*  pop parameters off stack*/
-       bra     ret_from_interrupt
-
-ret_from_interrupt:
-       jeq     1f
-2:
-       RESTORE_ALL
-1:
-       moveb   %sp@(PT_OFF_SR), %d0
-       and     #7, %d0
-       jhi     2b
-
-       /* check if we need to do software interrupts */
-       jeq     ret_from_exception
-
-       pea     ret_from_exception
-       jra     do_softirq
-
+       bra     ret_from_exception
 
 /*
  * Handler for uninitialized and spurious interrupts.
index 904fd9a4af4e45d472a121fdc678a523655059cc..447c33ef37fda3456b5fad22d705f123c91b4f84 100644 (file)
@@ -29,7 +29,6 @@
 .globl ret_from_exception
 .globl ret_from_signal
 .globl sys_call_table
-.globl ret_from_interrupt
 .globl bad_interrupt
 .globl inthandler
 
@@ -132,26 +131,9 @@ inthandler:
 
        movel   %sp,%sp@-
        movel   %d0,%sp@-               /*  put vector # on stack*/
-       jbsr    do_IRQ                  /*  process the IRQ*/
-3:             addql   #8,%sp                  /*  pop parameters off stack*/
-       bra     ret_from_interrupt
-
-ret_from_interrupt:
-       jeq     1f
-2:
-       RESTORE_ALL
-1:
-       moveb   %sp@(PT_OFF_SR), %d0
-       and     #7, %d0
-       jhi     2b
-       /* check if we need to do software interrupts */
-
-       movel   irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0
-       jeq     ret_from_exception
-
-       pea     ret_from_exception
-       jra     do_softirq
-
+       jbsr    do_IRQ                  /*  process the IRQ */
+       addql   #8,%sp                  /*  pop parameters off stack*/
+       jra     ret_from_exception
 
 /*
  * Handler for uninitialized and spurious interrupts.