diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-05-07 11:59:39 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2014-05-14 07:57:27 -0400 |
commit | 958d3d729802f7d741cbe8400e69b89baae580ee (patch) | |
tree | 3ed3667300363041c3e81a583db877807ee57589 /arch | |
parent | dff0796e53c29147c9bd1f5567a261dcf0e528bc (diff) |
x86/traps: Introduce fill_trap_info(), simplify DO_ERROR_INFO()
Extract the fill-siginfo code from DO_ERROR_INFO() into the new helper,
fill_trap_info().
It can calculate si_code and si_addr looking at trapnr, so we can remove
these arguments from DO_ERROR_INFO() and simplify the source code. The
generated code is the same, __builtin_constant_p(trapnr) == T.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/traps.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index ab8dad719b9e..1cf8a4c409b6 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -136,6 +136,33 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, | |||
136 | return -1; | 136 | return -1; |
137 | } | 137 | } |
138 | 138 | ||
139 | static void fill_trap_info(struct pt_regs *regs, int signr, int trapnr, | ||
140 | siginfo_t *info) | ||
141 | { | ||
142 | unsigned long siaddr; | ||
143 | int sicode; | ||
144 | |||
145 | switch (trapnr) { | ||
146 | case X86_TRAP_DE: | ||
147 | sicode = FPE_INTDIV; | ||
148 | siaddr = regs->ip; | ||
149 | break; | ||
150 | case X86_TRAP_UD: | ||
151 | sicode = ILL_ILLOPN; | ||
152 | siaddr = regs->ip; | ||
153 | break; | ||
154 | case X86_TRAP_AC: | ||
155 | sicode = BUS_ADRALN; | ||
156 | siaddr = 0; | ||
157 | break; | ||
158 | } | ||
159 | |||
160 | info->si_signo = signr; | ||
161 | info->si_errno = 0; | ||
162 | info->si_code = sicode; | ||
163 | info->si_addr = (void __user *)siaddr; | ||
164 | } | ||
165 | |||
139 | static void __kprobes | 166 | static void __kprobes |
140 | do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, | 167 | do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, |
141 | long error_code, siginfo_t *info) | 168 | long error_code, siginfo_t *info) |
@@ -191,30 +218,26 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ | |||
191 | do_error_trap(regs, error_code, str, trapnr, signr, NULL); \ | 218 | do_error_trap(regs, error_code, str, trapnr, signr, NULL); \ |
192 | } | 219 | } |
193 | 220 | ||
194 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ | 221 | #define DO_ERROR_INFO(trapnr, signr, str, name) \ |
195 | dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ | 222 | dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ |
196 | { \ | 223 | { \ |
197 | siginfo_t info; \ | 224 | siginfo_t info; \ |
198 | \ | 225 | \ |
199 | info.si_signo = signr; \ | 226 | fill_trap_info(regs, signr, trapnr, &info); \ |
200 | info.si_errno = 0; \ | ||
201 | info.si_code = sicode; \ | ||
202 | info.si_addr = (void __user *)siaddr; \ | ||
203 | \ | ||
204 | do_error_trap(regs, error_code, str, trapnr, signr, &info); \ | 227 | do_error_trap(regs, error_code, str, trapnr, signr, &info); \ |
205 | } | 228 | } |
206 | 229 | ||
207 | DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip ) | 230 | DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error) |
208 | DO_ERROR (X86_TRAP_OF, SIGSEGV, "overflow", overflow ) | 231 | DO_ERROR (X86_TRAP_OF, SIGSEGV, "overflow", overflow) |
209 | DO_ERROR (X86_TRAP_BR, SIGSEGV, "bounds", bounds ) | 232 | DO_ERROR (X86_TRAP_BR, SIGSEGV, "bounds", bounds) |
210 | DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip ) | 233 | DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op) |
211 | DO_ERROR (X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun ) | 234 | DO_ERROR (X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) |
212 | DO_ERROR (X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS ) | 235 | DO_ERROR (X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS) |
213 | DO_ERROR (X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present ) | 236 | DO_ERROR (X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present) |
214 | #ifdef CONFIG_X86_32 | 237 | #ifdef CONFIG_X86_32 |
215 | DO_ERROR (X86_TRAP_SS, SIGBUS, "stack segment", stack_segment ) | 238 | DO_ERROR (X86_TRAP_SS, SIGBUS, "stack segment", stack_segment) |
216 | #endif | 239 | #endif |
217 | DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0 ) | 240 | DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check) |
218 | 241 | ||
219 | #ifdef CONFIG_X86_64 | 242 | #ifdef CONFIG_X86_64 |
220 | /* Runs on IST stack */ | 243 | /* Runs on IST stack */ |