Import 2.3.18pre1
[davej-history.git] / arch / sh / kernel / traps.c
blob3d3cba23cf39623961b9eb53e7f2e841634c4180
1 /*
2 * linux/arch/sh/traps.c
4 * SuperH version: Copyright (C) 1999 Niibe Yutaka
5 */
7 /*
8 * 'Traps.c' handles hardware traps and faults after we have saved some
9 * state in 'entry.S'.
11 #include <linux/sched.h>
12 #include <linux/kernel.h>
13 #include <linux/string.h>
14 #include <linux/errno.h>
15 #include <linux/ptrace.h>
16 #include <linux/timer.h>
17 #include <linux/mm.h>
18 #include <linux/smp.h>
19 #include <linux/smp_lock.h>
20 #include <linux/init.h>
21 #include <linux/delay.h>
22 #include <linux/spinlock.h>
24 #include <asm/system.h>
25 #include <asm/uaccess.h>
26 #include <asm/io.h>
27 #include <asm/atomic.h>
29 static inline void console_verbose(void)
31 extern int console_loglevel;
32 console_loglevel = 15;
35 #define DO_ERROR(trapnr, signr, str, name, tsk) \
36 asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
37 unsigned long r6, unsigned long r7, \
38 struct pt_regs regs) \
39 { \
40 unsigned long error_code; \
42 asm volatile("stc r2_bank,%0": "=r" (error_code)); \
43 sti(); \
44 regs.syscall_nr = -1; \
45 tsk->thread.error_code = error_code; \
46 tsk->thread.trap_no = trapnr; \
47 force_sig(signr, tsk); \
48 die_if_no_fixup(str,&regs,error_code); \
52 * These constants are for searching for possible module text
53 * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
54 * a guess of how much space is likely to be vmalloced.
56 #define VMALLOC_OFFSET (8*1024*1024)
57 #define MODULE_RANGE (8*1024*1024)
59 static void show_registers(struct pt_regs *regs)
60 {/* Not implemented yet. */
63 spinlock_t die_lock;
65 void die(const char * str, struct pt_regs * regs, long err)
67 console_verbose();
68 spin_lock_irq(&die_lock);
69 printk("%s: %04lx\n", str, err & 0xffff);
70 show_registers(regs);
71 spin_unlock_irq(&die_lock);
72 do_exit(SIGSEGV);
75 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
77 if (!user_mode(regs))
78 die(str, regs, err);
81 static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
83 if (!user_mode(regs))
85 unsigned long fixup;
86 fixup = search_exception_table(regs->pc);
87 if (fixup) {
88 regs->pc = fixup;
89 return;
91 die(str, regs, err);
95 DO_ERROR( 7, SIGSEGV, "address error (load)", address_error_load, current)
96 DO_ERROR( 8, SIGSEGV, "address error (store)", address_error_store, current)
97 DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current)
98 DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current)
100 asmlinkage void do_exception_error (unsigned long r4, unsigned long r5,
101 unsigned long r6, unsigned long r7,
102 struct pt_regs regs)
104 long ex;
105 asm volatile("stc r2_bank,%0" : "=r" (ex));
106 die_if_kernel("exception", &regs, ex);
109 void __init trap_init(void)
111 extern void *vbr_base;
112 extern void *exception_handling_table[14];
114 exception_handling_table[7] = (void *)do_address_error_load;
115 exception_handling_table[8] = (void *)do_address_error_store;
116 exception_handling_table[12] = (void *)do_reserved_inst;
117 exception_handling_table[13] = (void *)do_illegal_slot_inst;
119 /* NOTE: The VBR value should be at P1
120 (or P2, virtural "fixed" address space).
121 It's definitely should not in physical address. */
123 asm volatile("ldc %0,vbr"
124 : /* no output */
125 : "r" (&vbr_base)
126 : "memory");