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 --- |