aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2006-01-11 16:42:14 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-11 22:01:10 -0500
commit6e3f361781573a27296c77a79c9892dec8f2e36c (patch)
treeb08ff3ed470d0e21ce3d462f16d6d3f0a6965a9c
parent5c617cfa6422bfba9e79d8d004303a6cc3d2e7d7 (diff)
[PATCH] x86_64: make trap information available to die notification handlers
This adjusts things so that handlers of the die() notifier will have sufficient information about the trap currently being handled. It also adjusts the notify_die() prototype to (again) match that of i386. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/x86_64/kernel/mce.c2
-rw-r--r--arch/x86_64/kernel/traps.c33
-rw-r--r--arch/x86_64/mm/fault.c8
-rw-r--r--include/asm-x86_64/kdebug.h13
4 files changed, 37 insertions, 19 deletions
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index ee5f65c44214..63777b8cb8c1 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -169,7 +169,7 @@ void do_machine_check(struct pt_regs * regs, long error_code)
169 int panicm_found = 0; 169 int panicm_found = 0;
170 170
171 if (regs) 171 if (regs)
172 notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL); 172 notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL);
173 if (!banks) 173 if (!banks)
174 return; 174 return;
175 175
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 0fd17e01de06..0266b523e8d0 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -382,7 +382,7 @@ void __die(const char * str, struct pt_regs * regs, long err)
382 printk("DEBUG_PAGEALLOC"); 382 printk("DEBUG_PAGEALLOC");
383#endif 383#endif
384 printk("\n"); 384 printk("\n");
385 notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); 385 notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
386 show_registers(regs); 386 show_registers(regs);
387 /* Executive summary in case the oops scrolled away */ 387 /* Executive summary in case the oops scrolled away */
388 printk(KERN_ALERT "RIP "); 388 printk(KERN_ALERT "RIP ");
@@ -421,19 +421,20 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
421 struct pt_regs * regs, long error_code, 421 struct pt_regs * regs, long error_code,
422 siginfo_t *info) 422 siginfo_t *info)
423{ 423{
424 struct task_struct *tsk = current;
425
424 conditional_sti(regs); 426 conditional_sti(regs);
425 427
426 if (user_mode(regs)) { 428 tsk->thread.error_code = error_code;
427 struct task_struct *tsk = current; 429 tsk->thread.trap_no = trapnr;
428 430
431 if (user_mode(regs)) {
429 if (exception_trace && unhandled_signal(tsk, signr)) 432 if (exception_trace && unhandled_signal(tsk, signr))
430 printk(KERN_INFO 433 printk(KERN_INFO
431 "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n", 434 "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
432 tsk->comm, tsk->pid, str, 435 tsk->comm, tsk->pid, str,
433 regs->rip,regs->rsp,error_code); 436 regs->rip,regs->rsp,error_code);
434 437
435 tsk->thread.error_code = error_code;
436 tsk->thread.trap_no = trapnr;
437 if (info) 438 if (info)
438 force_sig_info(signr, info, tsk); 439 force_sig_info(signr, info, tsk);
439 else 440 else
@@ -493,19 +494,20 @@ DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
493asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, 494asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
494 long error_code) 495 long error_code)
495{ 496{
497 struct task_struct *tsk = current;
498
496 conditional_sti(regs); 499 conditional_sti(regs);
497 500
498 if (user_mode(regs)) { 501 tsk->thread.error_code = error_code;
499 struct task_struct *tsk = current; 502 tsk->thread.trap_no = 13;
500 503
504 if (user_mode(regs)) {
501 if (exception_trace && unhandled_signal(tsk, SIGSEGV)) 505 if (exception_trace && unhandled_signal(tsk, SIGSEGV))
502 printk(KERN_INFO 506 printk(KERN_INFO
503 "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n", 507 "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
504 tsk->comm, tsk->pid, 508 tsk->comm, tsk->pid,
505 regs->rip,regs->rsp,error_code); 509 regs->rip,regs->rsp,error_code);
506 510
507 tsk->thread.error_code = error_code;
508 tsk->thread.trap_no = 13;
509 force_sig(SIGSEGV, tsk); 511 force_sig(SIGSEGV, tsk);
510 return; 512 return;
511 } 513 }
@@ -568,7 +570,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
568 reason = get_nmi_reason(); 570 reason = get_nmi_reason();
569 571
570 if (!(reason & 0xc0)) { 572 if (!(reason & 0xc0)) {
571 if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) 573 if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
572 == NOTIFY_STOP) 574 == NOTIFY_STOP)
573 return; 575 return;
574#ifdef CONFIG_X86_LOCAL_APIC 576#ifdef CONFIG_X86_LOCAL_APIC
@@ -584,7 +586,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
584 unknown_nmi_error(reason, regs); 586 unknown_nmi_error(reason, regs);
585 return; 587 return;
586 } 588 }
587 if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP) 589 if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
588 return; 590 return;
589 591
590 /* AK: following checks seem to be broken on modern chipsets. FIXME */ 592 /* AK: following checks seem to be broken on modern chipsets. FIXME */
@@ -693,7 +695,7 @@ clear_TF_reenable:
693 regs->eflags &= ~TF_MASK; 695 regs->eflags &= ~TF_MASK;
694} 696}
695 697
696static int kernel_math_error(struct pt_regs *regs, char *str) 698static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
697{ 699{
698 const struct exception_table_entry *fixup; 700 const struct exception_table_entry *fixup;
699 fixup = search_exception_tables(regs->rip); 701 fixup = search_exception_tables(regs->rip);
@@ -701,8 +703,9 @@ static int kernel_math_error(struct pt_regs *regs, char *str)
701 regs->rip = fixup->fixup; 703 regs->rip = fixup->fixup;
702 return 1; 704 return 1;
703 } 705 }
704 notify_die(DIE_GPF, str, regs, 0, 16, SIGFPE); 706 notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
705 /* Illegal floating point operation in the kernel */ 707 /* Illegal floating point operation in the kernel */
708 current->thread.trap_no = trapnr;
706 die(str, regs, 0); 709 die(str, regs, 0);
707 return 0; 710 return 0;
708} 711}
@@ -721,7 +724,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
721 724
722 conditional_sti(regs); 725 conditional_sti(regs);
723 if (!user_mode(regs) && 726 if (!user_mode(regs) &&
724 kernel_math_error(regs, "kernel x87 math error")) 727 kernel_math_error(regs, "kernel x87 math error", 16))
725 return; 728 return;
726 729
727 /* 730 /*
@@ -790,7 +793,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
790 793
791 conditional_sti(regs); 794 conditional_sti(regs);
792 if (!user_mode(regs) && 795 if (!user_mode(regs) &&
793 kernel_math_error(regs, "kernel simd math error")) 796 kernel_math_error(regs, "kernel simd math error", 19))
794 return; 797 return;
795 798
796 /* 799 /*
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 3a63707a698b..21d1596946d6 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -222,10 +222,15 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
222 unsigned long error_code) 222 unsigned long error_code)
223{ 223{
224 unsigned long flags = oops_begin(); 224 unsigned long flags = oops_begin();
225 struct task_struct *tsk;
225 226
226 printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", 227 printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
227 current->comm, address); 228 current->comm, address);
228 dump_pagetable(address); 229 dump_pagetable(address);
230 tsk = current;
231 tsk->thread.cr2 = address;
232 tsk->thread.trap_no = 14;
233 tsk->thread.error_code = error_code;
229 __die("Bad pagetable", regs, error_code); 234 __die("Bad pagetable", regs, error_code);
230 oops_end(flags); 235 oops_end(flags);
231 do_exit(SIGKILL); 236 do_exit(SIGKILL);
@@ -521,6 +526,9 @@ no_context:
521 printk_address(regs->rip); 526 printk_address(regs->rip);
522 printk("\n"); 527 printk("\n");
523 dump_pagetable(address); 528 dump_pagetable(address);
529 tsk->thread.cr2 = address;
530 tsk->thread.trap_no = 14;
531 tsk->thread.error_code = error_code;
524 __die("Oops", regs, error_code); 532 __die("Oops", regs, error_code);
525 /* Executive summary in case the body of the oops scrolled away */ 533 /* Executive summary in case the body of the oops scrolled away */
526 printk(KERN_EMERG "CR2: %016lx\n", address); 534 printk(KERN_EMERG "CR2: %016lx\n", address);
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index f604e84c5303..b9ed4c0c8783 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -35,9 +35,16 @@ enum die_val {
35 DIE_PAGE_FAULT, 35 DIE_PAGE_FAULT,
36}; 36};
37 37
38static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) 38static inline int notify_die(enum die_val val, const char *str,
39{ 39 struct pt_regs *regs, long err, int trap, int sig)
40 struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig }; 40{
41 struct die_args args = {
42 .regs = regs,
43 .str = str,
44 .err = err,
45 .trapnr = trap,
46 .signr = sig
47 };
41 return notifier_call_chain(&die_chain, val, &args); 48 return notifier_call_chain(&die_chain, val, &args);
42} 49}
43 50