diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 45b8479c9864..789881ca83d4 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
35 | #include <asm/kdebug.h> | 35 | #include <asm/kdebug.h> |
36 | #include <asm/sections.h> | 36 | #include <asm/sections.h> |
37 | #include <asm/uaccess.h> | ||
37 | 38 | ||
38 | extern void jprobe_inst_return(void); | 39 | extern void jprobe_inst_return(void); |
39 | 40 | ||
@@ -722,13 +723,50 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) | |||
722 | struct kprobe *cur = kprobe_running(); | 723 | struct kprobe *cur = kprobe_running(); |
723 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 724 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
724 | 725 | ||
725 | if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) | ||
726 | return 1; | ||
727 | 726 | ||
728 | if (kcb->kprobe_status & KPROBE_HIT_SS) { | 727 | switch(kcb->kprobe_status) { |
729 | resume_execution(cur, regs); | 728 | case KPROBE_HIT_SS: |
730 | reset_current_kprobe(); | 729 | case KPROBE_REENTER: |
730 | /* | ||
731 | * We are here because the instruction being single | ||
732 | * stepped caused a page fault. We reset the current | ||
733 | * kprobe and the instruction pointer points back to | ||
734 | * the probe address and allow the page fault handler | ||
735 | * to continue as a normal page fault. | ||
736 | */ | ||
737 | regs->cr_iip = ((unsigned long)cur->addr) & ~0xFULL; | ||
738 | ia64_psr(regs)->ri = ((unsigned long)cur->addr) & 0xf; | ||
739 | if (kcb->kprobe_status == KPROBE_REENTER) | ||
740 | restore_previous_kprobe(kcb); | ||
741 | else | ||
742 | reset_current_kprobe(); | ||
731 | preempt_enable_no_resched(); | 743 | preempt_enable_no_resched(); |
744 | break; | ||
745 | case KPROBE_HIT_ACTIVE: | ||
746 | case KPROBE_HIT_SSDONE: | ||
747 | /* | ||
748 | * We increment the nmissed count for accounting, | ||
749 | * we can also use npre/npostfault count for accouting | ||
750 | * these specific fault cases. | ||
751 | */ | ||
752 | kprobes_inc_nmissed_count(cur); | ||
753 | |||
754 | /* | ||
755 | * We come here because instructions in the pre/post | ||
756 | * handler caused the page_fault, this could happen | ||
757 | * if handler tries to access user space by | ||
758 | * copy_from_user(), get_user() etc. Let the | ||
759 | * user-specified handler try to fix it first. | ||
760 | */ | ||
761 | if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) | ||
762 | return 1; | ||
763 | |||
764 | /* | ||
765 | * Let ia64_do_page_fault() fix it. | ||
766 | */ | ||
767 | break; | ||
768 | default: | ||
769 | break; | ||
732 | } | 770 | } |
733 | 771 | ||
734 | return 0; | 772 | return 0; |