diff options
Diffstat (limited to 'arch/arc/kernel/traps.c')
-rw-r--r-- | arch/arc/kernel/traps.c | 52 |
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 | ||
31 | void die(const char *str, struct pt_regs *regs, unsigned long address, | 31 | void 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 | */ |
45 | static noinline int handle_exception(unsigned long cause, char *str, | 44 | static noinline int |
46 | struct pt_regs *regs, siginfo_t *info) | 45 | handle_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) \ |
68 | int name(unsigned long cause, unsigned long address, struct pt_regs *regs) \ | 66 | int 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 | */ |
93 | int do_misaligned_access(unsigned long cause, unsigned long address, | 91 | int 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 | */ |
107 | void do_machine_check_fault(unsigned long cause, unsigned long address, | 105 | void 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 | */ |
123 | void do_non_swi_trap(unsigned long cause, unsigned long address, | 120 | void 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 | */ |
152 | void do_insterror_or_kprobe(unsigned long cause, | 148 | void 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 | } |