diff options
author | Robin Getz <robin.getz@analog.com> | 2009-06-21 22:02:16 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-09-16 21:28:28 -0400 |
commit | ae4f073c40bf677b03826262e6022b4a251fe437 (patch) | |
tree | 452c91be30a3970efbea5780d368945e7f63712c /arch/blackfin/kernel | |
parent | d4b834c13940b5433d16ae3605794b3d74804348 (diff) |
Blackfin: make EVT3->EVT5 lowering more robust wrt IPEND[4]
We handle many exceptions at EVT5 (hardware error level) so that we can
catch exceptions in our exception handling code. Today - if the global
interrupt enable bit (IPEND[4]) is set (interrupts disabled) our trap
handling code goes into a infinite loop, since we need interrupts to be
on to defer things to EVT5.
Normal kernel code should not trigger this for any reason as IPEND[4] gets
cleared early (when doing an interrupt context save) and the kernel stack
there should be sane (or something much worse is happening in the system).
But there have been a few times where this has happened, so this change
makes sure we dump a proper crash message even when things have gone south.
Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/traps.c | 19 |
2 files changed, 11 insertions, 9 deletions
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c index b5df9459d6d5..8ad4f2c69961 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c | |||
@@ -145,6 +145,7 @@ int main(void) | |||
145 | DEFINE(PDA_EXBUF, offsetof(struct blackfin_pda, ex_buf)); | 145 | DEFINE(PDA_EXBUF, offsetof(struct blackfin_pda, ex_buf)); |
146 | DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask)); | 146 | DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask)); |
147 | DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack)); | 147 | DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack)); |
148 | DEFINE(PDA_EXIPEND, offsetof(struct blackfin_pda, ex_ipend)); | ||
148 | #ifdef ANOMALY_05000261 | 149 | #ifdef ANOMALY_05000261 |
149 | DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx)); | 150 | DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx)); |
150 | #endif | 151 | #endif |
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index bf2b2d1f8ae5..fccf741ed3b5 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -267,11 +267,6 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
267 | * double faults if the stack has become corrupt | 267 | * double faults if the stack has become corrupt |
268 | */ | 268 | */ |
269 | 269 | ||
270 | #ifndef CONFIG_KGDB | ||
271 | /* IPEND is skipped if KGDB isn't enabled (see entry code) */ | ||
272 | fp->ipend = bfin_read_IPEND(); | ||
273 | #endif | ||
274 | |||
275 | /* trap_c() will be called for exceptions. During exceptions | 270 | /* trap_c() will be called for exceptions. During exceptions |
276 | * processing, the pc value should be set with retx value. | 271 | * processing, the pc value should be set with retx value. |
277 | * With this change we can cleanup some code in signal.c- TODO | 272 | * With this change we can cleanup some code in signal.c- TODO |
@@ -1116,10 +1111,16 @@ void show_regs(struct pt_regs *fp) | |||
1116 | 1111 | ||
1117 | verbose_printk(KERN_NOTICE "%s", linux_banner); | 1112 | verbose_printk(KERN_NOTICE "%s", linux_banner); |
1118 | 1113 | ||
1119 | verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", | 1114 | verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", print_tainted()); |
1120 | print_tainted()); | 1115 | verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx IMASK: %04lx SYSCFG: %04lx\n", |
1121 | verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", | 1116 | (long)fp->seqstat, fp->ipend, cpu_pda[smp_processor_id()].ex_imask, fp->syscfg); |
1122 | (long)fp->seqstat, fp->ipend, fp->syscfg); | 1117 | if (fp->ipend & EVT_IRPTEN) |
1118 | verbose_printk(KERN_NOTICE " Global Interrupts Disabled (IPEND[4])\n"); | ||
1119 | if (!(cpu_pda[smp_processor_id()].ex_imask & (EVT_IVG13 | EVT_IVG12 | EVT_IVG11 | | ||
1120 | EVT_IVG10 | EVT_IVG9 | EVT_IVG8 | EVT_IVG7 | EVT_IVTMR))) | ||
1121 | verbose_printk(KERN_NOTICE " Peripheral interrupts masked off\n"); | ||
1122 | if (!(cpu_pda[smp_processor_id()].ex_imask & (EVT_IVG15 | EVT_IVG14))) | ||
1123 | verbose_printk(KERN_NOTICE " Kernel interrupts masked off\n"); | ||
1123 | if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { | 1124 | if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { |
1124 | verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", | 1125 | verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", |
1125 | (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); | 1126 | (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); |