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>
This commit is contained in:
committed by
Mike Frysinger
parent
d4b834c139
commit
ae4f073c40
@ -145,6 +145,7 @@ int main(void)
|
||||
DEFINE(PDA_EXBUF, offsetof(struct blackfin_pda, ex_buf));
|
||||
DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask));
|
||||
DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack));
|
||||
DEFINE(PDA_EXIPEND, offsetof(struct blackfin_pda, ex_ipend));
|
||||
#ifdef ANOMALY_05000261
|
||||
DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx));
|
||||
#endif
|
||||
|
@ -267,11 +267,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
* double faults if the stack has become corrupt
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_KGDB
|
||||
/* IPEND is skipped if KGDB isn't enabled (see entry code) */
|
||||
fp->ipend = bfin_read_IPEND();
|
||||
#endif
|
||||
|
||||
/* trap_c() will be called for exceptions. During exceptions
|
||||
* processing, the pc value should be set with retx value.
|
||||
* With this change we can cleanup some code in signal.c- TODO
|
||||
@ -1116,10 +1111,16 @@ void show_regs(struct pt_regs *fp)
|
||||
|
||||
verbose_printk(KERN_NOTICE "%s", linux_banner);
|
||||
|
||||
verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n",
|
||||
print_tainted());
|
||||
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
|
||||
(long)fp->seqstat, fp->ipend, fp->syscfg);
|
||||
verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", print_tainted());
|
||||
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx IMASK: %04lx SYSCFG: %04lx\n",
|
||||
(long)fp->seqstat, fp->ipend, cpu_pda[smp_processor_id()].ex_imask, fp->syscfg);
|
||||
if (fp->ipend & EVT_IRPTEN)
|
||||
verbose_printk(KERN_NOTICE " Global Interrupts Disabled (IPEND[4])\n");
|
||||
if (!(cpu_pda[smp_processor_id()].ex_imask & (EVT_IVG13 | EVT_IVG12 | EVT_IVG11 |
|
||||
EVT_IVG10 | EVT_IVG9 | EVT_IVG8 | EVT_IVG7 | EVT_IVTMR)))
|
||||
verbose_printk(KERN_NOTICE " Peripheral interrupts masked off\n");
|
||||
if (!(cpu_pda[smp_processor_id()].ex_imask & (EVT_IVG15 | EVT_IVG14)))
|
||||
verbose_printk(KERN_NOTICE " Kernel interrupts masked off\n");
|
||||
if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
|
||||
verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n",
|
||||
(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
|
||||
|
Reference in New Issue
Block a user