Commit baf4326e authored by Paul Mundt's avatar Paul Mundt

sh: interrupt exception handling rework

Kill off interrupt_table for all of the CPU subtypes, we now
default in to stepping in to do_IRQ() for _all_ IRQ exceptions
and counting the spurious ones, rather than simply flipping on
the ones we cared about. This and enabling the IRQ by default
automatically has already uncovered a couple of bugs and IRQs
that weren't being caught, as well as some that are being
generated far too often (SCI Tx Data Empty, for example).

The general rationale is to use a marker for interrupt exceptions,
test for it in the handle_exception() path, and skip out to
do_IRQ() if it's found. Everything else follows the same behaviour
of finding the cached EXPEVT value in r2/r2_bank, we just rip out
the INTEVT read from entry.S entirely (except for in the kGDB NMI
case, which is another matter).

Note that while this changes the do_IRQ() semantics regarding r4
handling, they were fundamentally broken anyways (relying entirely
on r2_bank for the cached code). With this, we do the INTEVT read
from do_IRQ() itself (in the CONFIG_CPU_HAS_INTEVT case), or fall
back on r4 for the muxed IRQ number, which should also be closer
to what SH-2 and SH-2A want anyways.
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 8884c4cb
......@@ -49,198 +49,3 @@ ENTRY(nmi_slot)
#endif
ENTRY(user_break_point_trap)
.long break_point_trap /* 1E0 */
ENTRY(interrupt_table)
! external hardware
.long do_IRQ ! 0000 /* 200 */
.long do_IRQ ! 0001
.long do_IRQ ! 0010
.long do_IRQ ! 0011
.long do_IRQ ! 0100
.long do_IRQ ! 0101
.long do_IRQ ! 0110
.long do_IRQ ! 0111
.long do_IRQ ! 1000 /* 300 */
.long do_IRQ ! 1001
.long do_IRQ ! 1010
.long do_IRQ ! 1011
.long do_IRQ ! 1100
.long do_IRQ ! 1101
.long do_IRQ ! 1110
.long exception_error
! Internal hardware
.long do_IRQ ! TMU0 tuni0 /* 400 */
.long do_IRQ ! TMU1 tuni1
.long do_IRQ ! TMU2 tuni2
.long do_IRQ ! ticpi2
.long do_IRQ ! RTC ati
.long do_IRQ ! pri
.long do_IRQ ! cui
.long do_IRQ ! SCI eri
.long do_IRQ ! rxi /* 500 */
.long do_IRQ ! txi
.long do_IRQ ! tei
.long do_IRQ ! WDT iti /* 560 */
.long do_IRQ ! REF rcmi
.long do_IRQ ! rovi
.long do_IRQ
.long do_IRQ /* 5E0 */
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
defined(CONFIG_CPU_SUBTYPE_SH7709) || \
defined(CONFIG_CPU_SUBTYPE_SH7706) || \
defined(CONFIG_CPU_SUBTYPE_SH7300) || \
defined(CONFIG_CPU_SUBTYPE_SH7705) || \
defined(CONFIG_CPU_SUBTYPE_SH7710)
.long do_IRQ ! 32 IRQ irq0 /* 600 */
.long do_IRQ ! 33 irq1
.long do_IRQ ! 34 irq2
.long do_IRQ ! 35 irq3
.long do_IRQ ! 36 irq4
.long do_IRQ ! 37 irq5
.long do_IRQ ! 38
.long do_IRQ ! 39
.long do_IRQ ! 40 PINT pint0-7 /* 700 */
.long do_IRQ ! 41 pint8-15
.long do_IRQ ! 42
.long do_IRQ ! 43
.long do_IRQ ! 44
.long do_IRQ ! 45
.long do_IRQ ! 46
.long do_IRQ ! 47
.long do_IRQ ! 48 DMAC dei0 /* 800 */
.long do_IRQ ! 49 dei1
.long do_IRQ ! 50 dei2
.long do_IRQ ! 51 dei3
.long do_IRQ ! 52 IrDA eri1
.long do_IRQ ! 53 rxi1
.long do_IRQ ! 54 bri1
.long do_IRQ ! 55 txi1
.long do_IRQ ! 56 SCIF eri2
.long do_IRQ ! 57 rxi2
.long do_IRQ ! 58 bri2
.long do_IRQ ! 59 txi2
.long do_IRQ ! 60 ADC adi /* 980 */
#if defined(CONFIG_CPU_SUBTYPE_SH7705)
.long exception_none ! 61 /* 9A0 */
.long exception_none ! 62
.long exception_none ! 63
.long exception_none ! 64 /* A00 */
.long do_IRQ ! 65 USB usi0
.long do_IRQ ! 66 usi1
.long exception_none ! 67
.long exception_none ! 68
.long exception_none ! 69
.long exception_none ! 70
.long exception_none ! 71
.long exception_none ! 72 /* B00 */
.long exception_none ! 73
.long exception_none ! 74
.long exception_none ! 75
.long exception_none ! 76
.long exception_none ! 77
.long exception_none ! 78
.long exception_none ! 79
.long do_IRQ ! 80 TPU0 tpi0 /* C00 */
.long do_IRQ ! 81 TPU1 tpi1
.long exception_none ! 82
.long exception_none ! 83
.long do_IRQ ! 84 TPU2 tpi2
.long do_IRQ ! 85 TPU3 tpi3 /* CA0 */
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7300)
.long do_IRQ ! 61 LCDC lcdi /* 9A0 */
.long do_IRQ ! 62 PCC pcc0i
.long do_IRQ ! 63 pcc1i /* 9E0 */
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7710)
.long exception_none ! 61 /* 9A0 */
.long exception_none ! 62
.long exception_none ! 63
.long exception_none ! 64 /* A00 */
.long exception_none ! 65
.long exception_none ! 66
.long exception_none ! 67
.long exception_none ! 68
.long exception_none ! 69
.long exception_none ! 70
.long exception_none ! 71
.long exception_none ! 72 /* B00 */
.long exception_none ! 73
.long exception_none ! 74
.long exception_none ! 75
.long do_IRQ ! 76 DMAC2 dei4 /* B80 */
.long do_IRQ ! 77 DMAC2 dei5
.long exception_none ! 78
.long do_IRQ ! 79 IPSEC ipseci /* BE0 */
.long do_IRQ ! 80 EDMAC eint0 /* C00 */
.long do_IRQ ! 81 EDMAC eint1
.long do_IRQ ! 82 EDMAC eint2
.long exception_none ! 83 /* C60 */
.long exception_none ! 84
.long exception_none ! 85
.long exception_none ! 86
.long exception_none ! 87
.long exception_none ! 88 /* D00 */
.long exception_none ! 89
.long exception_none ! 90
.long exception_none ! 91
.long exception_none ! 92
.long exception_none ! 93
.long exception_none ! 94
.long exception_none ! 95
.long do_IRQ ! 96 SIOF eri0 /* E00 */
.long do_IRQ ! 97 txi0
.long do_IRQ ! 98 rxi0
.long do_IRQ ! 99 cci0
.long do_IRQ ! 100 eri1 /* E80 */
.long do_IRQ ! 101 txi1
.long do_IRQ ! 102 rxi2
.long do_IRQ ! 103 cci3
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7300)
.long do_IRQ ! 64
.long do_IRQ ! 65
.long do_IRQ ! 66
.long do_IRQ ! 67
.long do_IRQ ! 68
.long do_IRQ ! 69
.long do_IRQ ! 70
.long do_IRQ ! 71
.long do_IRQ ! 72
.long do_IRQ ! 73
.long do_IRQ ! 74
.long do_IRQ ! 75
.long do_IRQ ! 76
.long do_IRQ ! 77
.long do_IRQ ! 78
.long do_IRQ ! 79
.long do_IRQ ! 80 SCIF0(SH7300)
.long do_IRQ ! 81
.long do_IRQ ! 82
.long do_IRQ ! 83
.long do_IRQ ! 84
.long do_IRQ ! 85
.long do_IRQ ! 86
.long do_IRQ ! 87
.long do_IRQ ! 88
.long do_IRQ ! 89
.long do_IRQ ! 90
.long do_IRQ ! 91
.long do_IRQ ! 92
.long do_IRQ ! 93
.long do_IRQ ! 94
.long do_IRQ ! 95
.long do_IRQ ! 96
.long do_IRQ ! 97
.long do_IRQ ! 98
.long do_IRQ ! 99
.long do_IRQ ! 100
.long do_IRQ ! 101
.long do_IRQ ! 102
.long do_IRQ ! 103
.long do_IRQ ! 104
.long do_IRQ ! 105
.long do_IRQ ! 106
.long do_IRQ ! 107
.long do_IRQ ! 108
#endif
#endif
This diff is collapsed.
/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
*
/*
* linux/arch/sh/entry.S
*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
* Copyright (C) 2003 Paul Mundt
* Copyright (C) 2003 - 2006 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
......@@ -78,7 +77,6 @@ OFF_TRA = (16*4+6*4)
#define k3 r3
#define k4 r4
#define k_ex_code r2_bank /* r2_bank1 */
#define g_imask r6 /* r6_bank1 */
#define k_g_imask r6_bank /* r6_bank1 */
#define current r7 /* r7_bank1 */
......@@ -691,7 +689,7 @@ interrupt:
0:
#endif /* defined(CONFIG_KGDB_NMI) */
bra handle_exception
mov.l @k2, k2
mov #-1, k2 ! interrupt exception marker
.align 2
1: .long EXPEVT
......@@ -717,8 +715,7 @@ ENTRY(handle_exception)
add current, k1
mov k1, r15 ! change to kernel stack
!
1: mov #-1, k4
mov.l 2f, k1
1: mov.l 2f, k1
!
#ifdef CONFIG_SH_DSP
mov.l r2, @-r15 ! Save r2, we need another reg
......@@ -763,6 +760,8 @@ skip_save:
#endif
! Save the user registers on the stack.
mov.l k2, @-r15 ! EXPEVT
mov #-1, k4
mov.l k4, @-r15 ! set TRA (default: -1)
!
sts.l macl, @-r15
......@@ -797,8 +796,21 @@ skip_save:
mov.l r2, @-r15
mov.l r1, @-r15
mov.l r0, @-r15
! Then, dispatch to the handler, according to the exception code.
stc k_ex_code, r8
/*
* This gets a bit tricky.. in the INTEVT case we don't want to use
* the VBR offset as a destination in the jump call table, since all
* of the destinations are the same. In this case, (interrupt) sets
* a marker in r2 (now r2_bank since SR.RB changed), which we check
* to determine the exception type. For all other exceptions, we
* forcibly read EXPEVT from memory and fix up the jump address, in
* the interrupt exception case we jump to do_IRQ() and defer the
* INTEVT read until there. As a bonus, we can also clean up the SR.RB
* checks that do_IRQ() was doing..
*/
stc r2_bank, r8
cmp/pz r8
bf interrupt_exception
shlr2 r8
shlr r8
mov.l 4f, r9
......@@ -806,6 +818,8 @@ skip_save:
mov.l @r9, r9
jmp @r9
nop
rts
nop
.align 2
1: .long 0x00001000 ! DSP=1
......@@ -813,8 +827,17 @@ skip_save:
3: .long 0xcfffffff ! RB=0, BL=0
4: .long exception_handling_table
interrupt_exception:
mov.l 1f, r9
jmp @r9
nop
rts
nop
.align 2
1: .long do_IRQ
.align 2
ENTRY(exception_none)
rts
nop
......@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
......@@ -26,6 +27,7 @@ atomic_t irq_err_count;
*/
void ack_bad_irq(unsigned int irq)
{
atomic_inc(&irq_err_count);
printk("unexpected IRQ trap at vector %02x\n", irq);
}
......@@ -85,7 +87,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
struct pt_regs regs)
{
struct pt_regs *old_regs = set_irq_regs(&regs);
int irq = r4;
int irq;
#ifdef CONFIG_4KSTACKS
union irq_ctx *curctx, *irqctx;
#endif
......@@ -109,20 +111,9 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
#endif
#ifdef CONFIG_CPU_HAS_INTEVT
__asm__ __volatile__ (
#ifdef CONFIG_CPU_HAS_SR_RB
"stc r2_bank, %0\n\t"
irq = (ctrl_inl(INTEVT) >> 5) - 16;
#else
"mov.l @%1, %0\n\t"
#endif
"shlr2 %0\n\t"
"shlr2 %0\n\t"
"shlr %0\n\t"
"add #-16, %0\n\t"
: "=z" (irq), "=r" (r4)
: "1" (INTEVT)
: "memory"
);
irq = r4;
#endif
irq = irq_demux(irq);
......@@ -147,9 +138,9 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
__asm__ __volatile__ (
"mov %0, r4 \n"
"mov r15, r9 \n"
"jsr @%2 \n"
"jsr @%1 \n"
/* swith to the irq stack */
" mov %3, r15 \n"
" mov %2, r15 \n"
/* restore the stack (ring zero) */
"mov r9, r15 \n"
: /* no outputs */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment