traps.c (56dd9470d7c8734f055da2a6bac553caf4a468eb) traps.c (6c1e0256fad84a843d915414e4b5973b7443d48d)
1/*
2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
4 *
5 * Pentium III FXSR, SSE support
6 * Gareth Hughes <gareth@valinux.com>, May 2000
7 */
8

--- 161 unchanged lines hidden (view full) ---

170 force_sig_info(signr, info, tsk);
171 else
172 force_sig(signr, tsk);
173}
174
175#define DO_ERROR(trapnr, signr, str, name) \
176dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \
177{ \
1/*
2 * Copyright (C) 1991, 1992 Linus Torvalds
3 * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
4 *
5 * Pentium III FXSR, SSE support
6 * Gareth Hughes <gareth@valinux.com>, May 2000
7 */
8

--- 161 unchanged lines hidden (view full) ---

170 force_sig_info(signr, info, tsk);
171 else
172 force_sig(signr, tsk);
173}
174
175#define DO_ERROR(trapnr, signr, str, name) \
176dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \
177{ \
178 exception_enter(regs); \
178 enum ctx_state prev_state; \
179 \
180 prev_state = exception_enter(); \
179 if (notify_die(DIE_TRAP, str, regs, error_code, \
180 trapnr, signr) == NOTIFY_STOP) { \
181 if (notify_die(DIE_TRAP, str, regs, error_code, \
182 trapnr, signr) == NOTIFY_STOP) { \
181 exception_exit(regs); \
183 exception_exit(prev_state); \
182 return; \
183 } \
184 conditional_sti(regs); \
185 do_trap(trapnr, signr, str, regs, error_code, NULL); \
184 return; \
185 } \
186 conditional_sti(regs); \
187 do_trap(trapnr, signr, str, regs, error_code, NULL); \
186 exception_exit(regs); \
188 exception_exit(prev_state); \
187}
188
189#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
190dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \
191{ \
192 siginfo_t info; \
189}
190
191#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
192dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \
193{ \
194 siginfo_t info; \
195 enum ctx_state prev_state; \
196 \
193 info.si_signo = signr; \
194 info.si_errno = 0; \
195 info.si_code = sicode; \
196 info.si_addr = (void __user *)siaddr; \
197 info.si_signo = signr; \
198 info.si_errno = 0; \
199 info.si_code = sicode; \
200 info.si_addr = (void __user *)siaddr; \
197 exception_enter(regs); \
201 prev_state = exception_enter(); \
198 if (notify_die(DIE_TRAP, str, regs, error_code, \
199 trapnr, signr) == NOTIFY_STOP) { \
202 if (notify_die(DIE_TRAP, str, regs, error_code, \
203 trapnr, signr) == NOTIFY_STOP) { \
200 exception_exit(regs); \
204 exception_exit(prev_state); \
201 return; \
202 } \
203 conditional_sti(regs); \
204 do_trap(trapnr, signr, str, regs, error_code, &info); \
205 return; \
206 } \
207 conditional_sti(regs); \
208 do_trap(trapnr, signr, str, regs, error_code, &info); \
205 exception_exit(regs); \
209 exception_exit(prev_state); \
206}
207
208DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV,
209 regs->ip)
210DO_ERROR(X86_TRAP_OF, SIGSEGV, "overflow", overflow)
211DO_ERROR(X86_TRAP_BR, SIGSEGV, "bounds", bounds)
212DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN,
213 regs->ip)

--- 6 unchanged lines hidden (view full) ---

220#endif
221DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check,
222 BUS_ADRALN, 0)
223
224#ifdef CONFIG_X86_64
225/* Runs on IST stack */
226dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
227{
210}
211
212DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV,
213 regs->ip)
214DO_ERROR(X86_TRAP_OF, SIGSEGV, "overflow", overflow)
215DO_ERROR(X86_TRAP_BR, SIGSEGV, "bounds", bounds)
216DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN,
217 regs->ip)

--- 6 unchanged lines hidden (view full) ---

224#endif
225DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check,
226 BUS_ADRALN, 0)
227
228#ifdef CONFIG_X86_64
229/* Runs on IST stack */
230dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
231{
228 exception_enter(regs);
232 enum ctx_state prev_state;
233
234 prev_state = exception_enter();
229 if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
230 X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) {
231 preempt_conditional_sti(regs);
232 do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);
233 preempt_conditional_cli(regs);
234 }
235 if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
236 X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) {
237 preempt_conditional_sti(regs);
238 do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);
239 preempt_conditional_cli(regs);
240 }
235 exception_exit(regs);
241 exception_exit(prev_state);
236}
237
238dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
239{
240 static const char str[] = "double fault";
241 struct task_struct *tsk = current;
242
242}
243
244dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
245{
246 static const char str[] = "double fault";
247 struct task_struct *tsk = current;
248
243 exception_enter(regs);
249 exception_enter();
244 /* Return not checked because double check cannot be ignored */
245 notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);
246
247 tsk->thread.error_code = error_code;
248 tsk->thread.trap_nr = X86_TRAP_DF;
249
250 /*
251 * This is always a kernel trap and never fixable (and thus must
252 * never return).
253 */
254 for (;;)
255 die(str, regs, error_code);
256}
257#endif
258
259dotraplinkage void __kprobes
260do_general_protection(struct pt_regs *regs, long error_code)
261{
262 struct task_struct *tsk;
250 /* Return not checked because double check cannot be ignored */
251 notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);
252
253 tsk->thread.error_code = error_code;
254 tsk->thread.trap_nr = X86_TRAP_DF;
255
256 /*
257 * This is always a kernel trap and never fixable (and thus must
258 * never return).
259 */
260 for (;;)
261 die(str, regs, error_code);
262}
263#endif
264
265dotraplinkage void __kprobes
266do_general_protection(struct pt_regs *regs, long error_code)
267{
268 struct task_struct *tsk;
269 enum ctx_state prev_state;
263
270
264 exception_enter(regs);
271 prev_state = exception_enter();
265 conditional_sti(regs);
266
267#ifdef CONFIG_X86_32
268 if (regs->flags & X86_VM_MASK) {
269 local_irq_enable();
270 handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
271 goto exit;
272 }

--- 21 unchanged lines hidden (view full) ---

294 tsk->comm, task_pid_nr(tsk),
295 regs->ip, regs->sp, error_code);
296 print_vma_addr(" in ", regs->ip);
297 pr_cont("\n");
298 }
299
300 force_sig(SIGSEGV, tsk);
301exit:
272 conditional_sti(regs);
273
274#ifdef CONFIG_X86_32
275 if (regs->flags & X86_VM_MASK) {
276 local_irq_enable();
277 handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
278 goto exit;
279 }

--- 21 unchanged lines hidden (view full) ---

301 tsk->comm, task_pid_nr(tsk),
302 regs->ip, regs->sp, error_code);
303 print_vma_addr(" in ", regs->ip);
304 pr_cont("\n");
305 }
306
307 force_sig(SIGSEGV, tsk);
308exit:
302 exception_exit(regs);
309 exception_exit(prev_state);
303}
304
305/* May run on IST stack. */
306dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_code)
307{
310}
311
312/* May run on IST stack. */
313dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_code)
314{
315 enum ctx_state prev_state;
316
308#ifdef CONFIG_DYNAMIC_FTRACE
309 /*
310 * ftrace must be first, everything else may cause a recursive crash.
311 * See note by declaration of modifying_ftrace_code in ftrace.c
312 */
313 if (unlikely(atomic_read(&modifying_ftrace_code)) &&
314 ftrace_int3_handler(regs))
315 return;
316#endif
317#ifdef CONFIG_DYNAMIC_FTRACE
318 /*
319 * ftrace must be first, everything else may cause a recursive crash.
320 * See note by declaration of modifying_ftrace_code in ftrace.c
321 */
322 if (unlikely(atomic_read(&modifying_ftrace_code)) &&
323 ftrace_int3_handler(regs))
324 return;
325#endif
317 exception_enter(regs);
326 prev_state = exception_enter();
318#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
319 if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
320 SIGTRAP) == NOTIFY_STOP)
321 goto exit;
322#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
323
324 if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
325 SIGTRAP) == NOTIFY_STOP)

--- 4 unchanged lines hidden (view full) ---

330 * as we may switch to the interrupt stack.
331 */
332 debug_stack_usage_inc();
333 preempt_conditional_sti(regs);
334 do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
335 preempt_conditional_cli(regs);
336 debug_stack_usage_dec();
337exit:
327#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
328 if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
329 SIGTRAP) == NOTIFY_STOP)
330 goto exit;
331#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
332
333 if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
334 SIGTRAP) == NOTIFY_STOP)

--- 4 unchanged lines hidden (view full) ---

339 * as we may switch to the interrupt stack.
340 */
341 debug_stack_usage_inc();
342 preempt_conditional_sti(regs);
343 do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
344 preempt_conditional_cli(regs);
345 debug_stack_usage_dec();
346exit:
338 exception_exit(regs);
347 exception_exit(prev_state);
339}
340
341#ifdef CONFIG_X86_64
342/*
343 * Help handler running on IST stack to switch back to user stack
344 * for scheduling or signal handling. The actual stack switch is done in
345 * entry.S
346 */

--- 40 unchanged lines hidden (view full) ---

387 * find every occurrence of the TF bit that could be saved away even
388 * by user code)
389 *
390 * May run on IST stack.
391 */
392dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
393{
394 struct task_struct *tsk = current;
348}
349
350#ifdef CONFIG_X86_64
351/*
352 * Help handler running on IST stack to switch back to user stack
353 * for scheduling or signal handling. The actual stack switch is done in
354 * entry.S
355 */

--- 40 unchanged lines hidden (view full) ---

396 * find every occurrence of the TF bit that could be saved away even
397 * by user code)
398 *
399 * May run on IST stack.
400 */
401dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
402{
403 struct task_struct *tsk = current;
404 enum ctx_state prev_state;
395 int user_icebp = 0;
396 unsigned long dr6;
397 int si_code;
398
405 int user_icebp = 0;
406 unsigned long dr6;
407 int si_code;
408
399 exception_enter(regs);
409 prev_state = exception_enter();
400
401 get_debugreg(dr6, 6);
402
403 /* Filter out all the reserved bits which are preset to 1 */
404 dr6 &= ~DR6_RESERVED;
405
406 /*
407 * If dr6 has no reason to give us about the origin of this trap,

--- 53 unchanged lines hidden (view full) ---

461 }
462 si_code = get_si_code(tsk->thread.debugreg6);
463 if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
464 send_sigtrap(tsk, regs, error_code, si_code);
465 preempt_conditional_cli(regs);
466 debug_stack_usage_dec();
467
468exit:
410
411 get_debugreg(dr6, 6);
412
413 /* Filter out all the reserved bits which are preset to 1 */
414 dr6 &= ~DR6_RESERVED;
415
416 /*
417 * If dr6 has no reason to give us about the origin of this trap,

--- 53 unchanged lines hidden (view full) ---

471 }
472 si_code = get_si_code(tsk->thread.debugreg6);
473 if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
474 send_sigtrap(tsk, regs, error_code, si_code);
475 preempt_conditional_cli(regs);
476 debug_stack_usage_dec();
477
478exit:
469 exception_exit(regs);
479 exception_exit(prev_state);
470}
471
472/*
473 * Note that we play around with the 'TS' bit in an attempt to get
474 * the correct behaviour even in the presence of the asynchronous
475 * IRQ13 behaviour
476 */
477void math_error(struct pt_regs *regs, int error_code, int trapnr)

--- 77 unchanged lines hidden (view full) ---

555 */
556 return;
557 }
558 force_sig_info(SIGFPE, &info, task);
559}
560
561dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
562{
480}
481
482/*
483 * Note that we play around with the 'TS' bit in an attempt to get
484 * the correct behaviour even in the presence of the asynchronous
485 * IRQ13 behaviour
486 */
487void math_error(struct pt_regs *regs, int error_code, int trapnr)

--- 77 unchanged lines hidden (view full) ---

565 */
566 return;
567 }
568 force_sig_info(SIGFPE, &info, task);
569}
570
571dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
572{
563 exception_enter(regs);
573 enum ctx_state prev_state;
574
575 prev_state = exception_enter();
564 math_error(regs, error_code, X86_TRAP_MF);
576 math_error(regs, error_code, X86_TRAP_MF);
565 exception_exit(regs);
577 exception_exit(prev_state);
566}
567
568dotraplinkage void
569do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
570{
578}
579
580dotraplinkage void
581do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
582{
571 exception_enter(regs);
583 enum ctx_state prev_state;
584
585 prev_state = exception_enter();
572 math_error(regs, error_code, X86_TRAP_XF);
586 math_error(regs, error_code, X86_TRAP_XF);
573 exception_exit(regs);
587 exception_exit(prev_state);
574}
575
576dotraplinkage void
577do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
578{
579 conditional_sti(regs);
580#if 0
581 /* No need to warn about this any longer. */

--- 51 unchanged lines hidden (view full) ---

633
634 tsk->fpu_counter++;
635}
636EXPORT_SYMBOL_GPL(math_state_restore);
637
638dotraplinkage void __kprobes
639do_device_not_available(struct pt_regs *regs, long error_code)
640{
588}
589
590dotraplinkage void
591do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
592{
593 conditional_sti(regs);
594#if 0
595 /* No need to warn about this any longer. */

--- 51 unchanged lines hidden (view full) ---

647
648 tsk->fpu_counter++;
649}
650EXPORT_SYMBOL_GPL(math_state_restore);
651
652dotraplinkage void __kprobes
653do_device_not_available(struct pt_regs *regs, long error_code)
654{
641 exception_enter(regs);
655 enum ctx_state prev_state;
656
657 prev_state = exception_enter();
642 BUG_ON(use_eager_fpu());
643
644#ifdef CONFIG_MATH_EMULATION
645 if (read_cr0() & X86_CR0_EM) {
646 struct math_emu_info info = { };
647
648 conditional_sti(regs);
649
650 info.regs = regs;
651 math_emulate(&info);
658 BUG_ON(use_eager_fpu());
659
660#ifdef CONFIG_MATH_EMULATION
661 if (read_cr0() & X86_CR0_EM) {
662 struct math_emu_info info = { };
663
664 conditional_sti(regs);
665
666 info.regs = regs;
667 math_emulate(&info);
652 exception_exit(regs);
668 exception_exit(prev_state);
653 return;
654 }
655#endif
656 math_state_restore(); /* interrupts still off */
657#ifdef CONFIG_X86_32
658 conditional_sti(regs);
659#endif
669 return;
670 }
671#endif
672 math_state_restore(); /* interrupts still off */
673#ifdef CONFIG_X86_32
674 conditional_sti(regs);
675#endif
660 exception_exit(regs);
676 exception_exit(prev_state);
661}
662
663#ifdef CONFIG_X86_32
664dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
665{
666 siginfo_t info;
677}
678
679#ifdef CONFIG_X86_32
680dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
681{
682 siginfo_t info;
683 enum ctx_state prev_state;
667
684
668 exception_enter(regs);
685 prev_state = exception_enter();
669 local_irq_enable();
670
671 info.si_signo = SIGILL;
672 info.si_errno = 0;
673 info.si_code = ILL_BADSTK;
674 info.si_addr = NULL;
675 if (notify_die(DIE_TRAP, "iret exception", regs, error_code,
676 X86_TRAP_IRET, SIGILL) != NOTIFY_STOP) {
677 do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code,
678 &info);
679 }
686 local_irq_enable();
687
688 info.si_signo = SIGILL;
689 info.si_errno = 0;
690 info.si_code = ILL_BADSTK;
691 info.si_addr = NULL;
692 if (notify_die(DIE_TRAP, "iret exception", regs, error_code,
693 X86_TRAP_IRET, SIGILL) != NOTIFY_STOP) {
694 do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code,
695 &info);
696 }
680 exception_exit(regs);
697 exception_exit(prev_state);
681}
682#endif
683
684/* Set of traps needed for early debugging. */
685void __init early_trap_init(void)
686{
687 set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK);
688 /* int3 can be called from all */

--- 78 unchanged lines hidden ---
698}
699#endif
700
701/* Set of traps needed for early debugging. */
702void __init early_trap_init(void)
703{
704 set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK);
705 /* int3 can be called from all */

--- 78 unchanged lines hidden ---