aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r--arch/blackfin/kernel/traps.c75
1 files changed, 38 insertions, 37 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index bef025b07443..17d8e4172896 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -75,16 +75,6 @@ void __init trap_init(void)
75 CSYNC(); 75 CSYNC();
76} 76}
77 77
78/*
79 * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR
80 * values across the transition from exception to IRQ5.
81 * We put these in L1, so they are going to be in a valid
82 * location during exception context
83 */
84__attribute__((l1_data))
85unsigned long saved_retx, saved_seqstat,
86 saved_icplb_fault_addr, saved_dcplb_fault_addr;
87
88static void decode_address(char *buf, unsigned long address) 78static void decode_address(char *buf, unsigned long address)
89{ 79{
90#ifdef CONFIG_DEBUG_VERBOSE 80#ifdef CONFIG_DEBUG_VERBOSE
@@ -211,18 +201,18 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
211 printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); 201 printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
212#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT 202#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
213 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { 203 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
204 unsigned int cpu = smp_processor_id();
214 char buf[150]; 205 char buf[150];
215 decode_address(buf, saved_retx); 206 decode_address(buf, cpu_pda[cpu].retx);
216 printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", 207 printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
217 (int)saved_seqstat & SEQSTAT_EXCAUSE, buf); 208 (unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
218 decode_address(buf, saved_dcplb_fault_addr); 209 decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
219 printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); 210 printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf);
220 decode_address(buf, saved_icplb_fault_addr); 211 decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
221 printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); 212 printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf);
222 213
223 decode_address(buf, fp->retx); 214 decode_address(buf, fp->retx);
224 printk(KERN_NOTICE "The instruction at %s caused a double exception\n", 215 printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf);
225 buf);
226 } else 216 } else
227#endif 217#endif
228 { 218 {
@@ -240,6 +230,9 @@ asmlinkage void trap_c(struct pt_regs *fp)
240#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON 230#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
241 int j; 231 int j;
242#endif 232#endif
233#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
234 unsigned int cpu = smp_processor_id();
235#endif
243 int sig = 0; 236 int sig = 0;
244 siginfo_t info; 237 siginfo_t info;
245 unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; 238 unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
@@ -417,7 +410,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
417 info.si_code = ILL_CPLB_MULHIT; 410 info.si_code = ILL_CPLB_MULHIT;
418 sig = SIGSEGV; 411 sig = SIGSEGV;
419#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO 412#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
420 if (saved_dcplb_fault_addr < FIXED_CODE_START) 413 if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
421 verbose_printk(KERN_NOTICE "NULL pointer access\n"); 414 verbose_printk(KERN_NOTICE "NULL pointer access\n");
422 else 415 else
423#endif 416#endif
@@ -471,7 +464,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
471 info.si_code = ILL_CPLB_MULHIT; 464 info.si_code = ILL_CPLB_MULHIT;
472 sig = SIGSEGV; 465 sig = SIGSEGV;
473#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO 466#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
474 if (saved_icplb_fault_addr < FIXED_CODE_START) 467 if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
475 verbose_printk(KERN_NOTICE "Jump to NULL address\n"); 468 verbose_printk(KERN_NOTICE "Jump to NULL address\n");
476 else 469 else
477#endif 470#endif
@@ -584,10 +577,15 @@ asmlinkage void trap_c(struct pt_regs *fp)
584 } 577 }
585 } 578 }
586 579
587 info.si_signo = sig; 580#ifdef CONFIG_IPIPE
588 info.si_errno = 0; 581 if (!ipipe_trap_notify(fp->seqstat & 0x3f, fp))
589 info.si_addr = (void __user *)fp->pc; 582#endif
590 force_sig_info(sig, &info, current); 583 {
584 info.si_signo = sig;
585 info.si_errno = 0;
586 info.si_addr = (void __user *)fp->pc;
587 force_sig_info(sig, &info, current);
588 }
591 589
592 trace_buffer_restore(j); 590 trace_buffer_restore(j);
593 return; 591 return;
@@ -656,13 +654,13 @@ static bool get_instruction(unsigned short *val, unsigned short *address)
656 return false; 654 return false;
657} 655}
658 656
659/* 657/*
660 * decode the instruction if we are printing out the trace, as it 658 * decode the instruction if we are printing out the trace, as it
661 * makes things easier to follow, without running it through objdump 659 * makes things easier to follow, without running it through objdump
662 * These are the normal instructions which cause change of flow, which 660 * These are the normal instructions which cause change of flow, which
663 * would be at the source of the trace buffer 661 * would be at the source of the trace buffer
664 */ 662 */
665#ifdef CONFIG_DEBUG_VERBOSE 663#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_BFIN_HWTRACE_ON)
666static void decode_instruction(unsigned short *address) 664static void decode_instruction(unsigned short *address)
667{ 665{
668 unsigned short opcode; 666 unsigned short opcode;
@@ -846,7 +844,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
846 } 844 }
847 if (fp) { 845 if (fp) {
848 frame = fp; 846 frame = fp;
849 printk(" FP: (0x%p)\n", fp); 847 printk(KERN_NOTICE " FP: (0x%p)\n", fp);
850 } else 848 } else
851 frame = 0; 849 frame = 0;
852 850
@@ -960,6 +958,7 @@ void dump_bfin_process(struct pt_regs *fp)
960 else 958 else
961 verbose_printk(KERN_NOTICE "COMM= invalid\n"); 959 verbose_printk(KERN_NOTICE "COMM= invalid\n");
962 960
961 printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
963 if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) 962 if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
964 verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" 963 verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
965 KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" 964 KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
@@ -1053,6 +1052,7 @@ void show_regs(struct pt_regs *fp)
1053 struct irqaction *action; 1052 struct irqaction *action;
1054 unsigned int i; 1053 unsigned int i;
1055 unsigned long flags; 1054 unsigned long flags;
1055 unsigned int cpu = smp_processor_id();
1056 1056
1057 verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); 1057 verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
1058 verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", 1058 verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
@@ -1112,9 +1112,9 @@ unlock:
1112 1112
1113 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && 1113 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
1114 (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { 1114 (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
1115 decode_address(buf, saved_dcplb_fault_addr); 1115 decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
1116 verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); 1116 verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
1117 decode_address(buf, saved_icplb_fault_addr); 1117 decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
1118 verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); 1118 verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
1119 } 1119 }
1120 1120
@@ -1153,20 +1153,21 @@ unlock:
1153asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text)); 1153asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
1154#endif 1154#endif
1155 1155
1156asmlinkage int sys_bfin_spinlock(int *spinlock) 1156static DEFINE_SPINLOCK(bfin_spinlock_lock);
1157
1158asmlinkage int sys_bfin_spinlock(int *p)
1157{ 1159{
1158 int ret = 0; 1160 int ret, tmp = 0;
1159 int tmp = 0;
1160 1161
1161 local_irq_disable(); 1162 spin_lock(&bfin_spinlock_lock); /* This would also hold kernel preemption. */
1162 ret = get_user(tmp, spinlock); 1163 ret = get_user(tmp, p);
1163 if (ret == 0) { 1164 if (likely(ret == 0)) {
1164 if (tmp) 1165 if (unlikely(tmp))
1165 ret = 1; 1166 ret = 1;
1166 tmp = 1; 1167 else
1167 put_user(tmp, spinlock); 1168 put_user(1, p);
1168 } 1169 }
1169 local_irq_enable(); 1170 spin_unlock(&bfin_spinlock_lock);
1170 return ret; 1171 return ret;
1171} 1172}
1172 1173