aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/kernel/traps.c')
-rw-r--r--arch/arc/kernel/traps.c52
1 files changed, 24 insertions, 28 deletions
diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c
index 0471d9c9dd54..e21692d2fdab 100644
--- a/arch/arc/kernel/traps.c
+++ b/arch/arc/kernel/traps.c
@@ -28,10 +28,9 @@ void __init trap_init(void)
28 return; 28 return;
29} 29}
30 30
31void die(const char *str, struct pt_regs *regs, unsigned long address, 31void die(const char *str, struct pt_regs *regs, unsigned long address)
32 unsigned long cause_reg)
33{ 32{
34 show_kernel_fault_diag(str, regs, address, cause_reg); 33 show_kernel_fault_diag(str, regs, address);
35 34
36 /* DEAD END */ 35 /* DEAD END */
37 __asm__("flag 1"); 36 __asm__("flag 1");
@@ -42,14 +41,13 @@ void die(const char *str, struct pt_regs *regs, unsigned long address,
42 * -for user faults enqueues requested signal 41 * -for user faults enqueues requested signal
43 * -for kernel, chk if due to copy_(to|from)_user, otherwise die() 42 * -for kernel, chk if due to copy_(to|from)_user, otherwise die()
44 */ 43 */
45static noinline int handle_exception(unsigned long cause, char *str, 44static noinline int
46 struct pt_regs *regs, siginfo_t *info) 45handle_exception(const char *str, struct pt_regs *regs, siginfo_t *info)
47{ 46{
48 if (user_mode(regs)) { 47 if (user_mode(regs)) {
49 struct task_struct *tsk = current; 48 struct task_struct *tsk = current;
50 49
51 tsk->thread.fault_address = (__force unsigned int)info->si_addr; 50 tsk->thread.fault_address = (__force unsigned int)info->si_addr;
52 tsk->thread.cause_code = cause;
53 51
54 force_sig_info(info->si_signo, info, tsk); 52 force_sig_info(info->si_signo, info, tsk);
55 53
@@ -58,14 +56,14 @@ static noinline int handle_exception(unsigned long cause, char *str,
58 if (fixup_exception(regs)) 56 if (fixup_exception(regs))
59 return 0; 57 return 0;
60 58
61 die(str, regs, (unsigned long)info->si_addr, cause); 59 die(str, regs, (unsigned long)info->si_addr);
62 } 60 }
63 61
64 return 1; 62 return 1;
65} 63}
66 64
67#define DO_ERROR_INFO(signr, str, name, sicode) \ 65#define DO_ERROR_INFO(signr, str, name, sicode) \
68int name(unsigned long cause, unsigned long address, struct pt_regs *regs) \ 66int name(unsigned long address, struct pt_regs *regs) \
69{ \ 67{ \
70 siginfo_t info = { \ 68 siginfo_t info = { \
71 .si_signo = signr, \ 69 .si_signo = signr, \
@@ -73,7 +71,7 @@ int name(unsigned long cause, unsigned long address, struct pt_regs *regs) \
73 .si_code = sicode, \ 71 .si_code = sicode, \
74 .si_addr = (void __user *)address, \ 72 .si_addr = (void __user *)address, \
75 }; \ 73 }; \
76 return handle_exception(cause, str, regs, &info);\ 74 return handle_exception(str, regs, &info);\
77} 75}
78 76
79/* 77/*
@@ -90,11 +88,11 @@ DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN)
90/* 88/*
91 * Entry Point for Misaligned Data access Exception, for emulating in software 89 * Entry Point for Misaligned Data access Exception, for emulating in software
92 */ 90 */
93int do_misaligned_access(unsigned long cause, unsigned long address, 91int do_misaligned_access(unsigned long address, struct pt_regs *regs,
94 struct pt_regs *regs, struct callee_regs *cregs) 92 struct callee_regs *cregs)
95{ 93{
96 if (misaligned_fixup(address, regs, cause, cregs) != 0) 94 if (misaligned_fixup(address, regs, cregs) != 0)
97 return do_misaligned_error(cause, address, regs); 95 return do_misaligned_error(address, regs);
98 96
99 return 0; 97 return 0;
100} 98}
@@ -104,10 +102,9 @@ int do_misaligned_access(unsigned long cause, unsigned long address,
104 * Entry point for miscll errors such as Nested Exceptions 102 * Entry point for miscll errors such as Nested Exceptions
105 * -Duplicate TLB entry is handled seperately though 103 * -Duplicate TLB entry is handled seperately though
106 */ 104 */
107void do_machine_check_fault(unsigned long cause, unsigned long address, 105void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
108 struct pt_regs *regs)
109{ 106{
110 die("Machine Check Exception", regs, address, cause); 107 die("Machine Check Exception", regs, address);
111} 108}
112 109
113 110
@@ -120,23 +117,22 @@ void do_machine_check_fault(unsigned long cause, unsigned long address,
120 * -1 used for software breakpointing (gdb) 117 * -1 used for software breakpointing (gdb)
121 * -2 used by kprobes 118 * -2 used by kprobes
122 */ 119 */
123void do_non_swi_trap(unsigned long cause, unsigned long address, 120void do_non_swi_trap(unsigned long address, struct pt_regs *regs)
124 struct pt_regs *regs)
125{ 121{
126 unsigned int param = cause & 0xff; 122 unsigned int param = regs->ecr_param;
127 123
128 switch (param) { 124 switch (param) {
129 case 1: 125 case 1:
130 trap_is_brkpt(cause, address, regs); 126 trap_is_brkpt(address, regs);
131 break; 127 break;
132 128
133 case 2: 129 case 2:
134 trap_is_kprobe(param, address, regs); 130 trap_is_kprobe(address, regs);
135 break; 131 break;
136 132
137 case 3: 133 case 3:
138 case 4: 134 case 4:
139 kgdb_trap(regs, param); 135 kgdb_trap(regs);
140 break; 136 break;
141 137
142 default: 138 default:
@@ -149,14 +145,14 @@ void do_non_swi_trap(unsigned long cause, unsigned long address,
149 * -For a corner case, ARC kprobes implementation resorts to using 145 * -For a corner case, ARC kprobes implementation resorts to using
150 * this exception, hence the check 146 * this exception, hence the check
151 */ 147 */
152void do_insterror_or_kprobe(unsigned long cause, 148void do_insterror_or_kprobe(unsigned long address, struct pt_regs *regs)
153 unsigned long address,
154 struct pt_regs *regs)
155{ 149{
150 int rc;
151
156 /* Check if this exception is caused by kprobes */ 152 /* Check if this exception is caused by kprobes */
157 if (notify_die(DIE_IERR, "kprobe_ierr", regs, address, 153 rc = notify_die(DIE_IERR, "kprobe_ierr", regs, address, 0, SIGILL);
158 cause, SIGILL) == NOTIFY_STOP) 154 if (rc == NOTIFY_STOP)
159 return; 155 return;
160 156
161 insterror_is_error(cause, address, regs); 157 insterror_is_error(address, regs);
162} 158}