Messages in this thread Patch in this message | | | Date | Thu, 9 Oct 2008 00:54:45 +0530 | From | "K.Prasad" <> | Subject | [RFC Patch 4/9] Modify kprobe exception handler to recognise single-stepping by HW Breakpoint handler |
| |
This patch modifies the kprobe handler to help it recognise single-stepping by the HW Breakpoint exception code. A per-cpu variable called 'sstep_reason' to distinguish the source of single-step exceptions.
Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com> Signed-off-by: Alan Stern <stern@rowland.harvard.edu> --- arch/x86/kernel/kprobes.c | 18 ++++++++++++++++-- include/asm-x86/kprobes.h | 8 ++++++++ 2 files changed, 24 insertions(+), 2 deletions(-)
Index: linux-bkpt-lkml-27-rc9/arch/x86/kernel/kprobes.c =================================================================== --- linux-bkpt-lkml-27-rc9.orig/arch/x86/kernel/kprobes.c +++ linux-bkpt-lkml-27-rc9/arch/x86/kernel/kprobes.c @@ -54,6 +54,7 @@ #include <asm/pgtable.h> #include <asm/uaccess.h> #include <asm/alternative.h> +#include <asm/debugreg.h> void jprobe_return_end(void); @@ -517,6 +518,7 @@ static int __kprobes kprobe_handler(stru kprobe_opcode_t *addr; struct kprobe *p; struct kprobe_ctlblk *kcb; + unsigned int *ssr; addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t)); if (*addr != BREAKPOINT_INSTRUCTION) { @@ -541,6 +543,7 @@ static int __kprobes kprobe_handler(stru */ preempt_disable(); + ssr = &(__get_cpu_var(sstep_reason)); kcb = get_kprobe_ctlblk(); p = get_kprobe(addr); @@ -560,14 +563,17 @@ static int __kprobes kprobe_handler(stru * for jprobe processing, so get out doing nothing * more here. */ - if (!p->pre_handler || !p->pre_handler(p, regs)) + if (!p->pre_handler || !p->pre_handler(p, regs)) { setup_singlestep(p, regs, kcb); + (*ssr) |= SSTEP_KPROBE; + } return 1; } } else if (kprobe_running()) { p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { setup_singlestep(p, regs, kcb); + (*ssr) |= SSTEP_KPROBE; return 1; } } /* else: not a kprobe fault; let the kernel handle it */ @@ -952,6 +958,7 @@ int __kprobes kprobe_exceptions_notify(s { struct die_args *args = data; int ret = NOTIFY_DONE; + unsigned int *ssr = &(__get_cpu_var(sstep_reason)); if (args->regs && user_mode_vm(args->regs)) return ret; @@ -962,8 +969,15 @@ int __kprobes kprobe_exceptions_notify(s ret = NOTIFY_STOP; break; case DIE_DEBUG: - if (post_kprobe_handler(args->regs)) + /* We could be here due to single-stepping after a pre-handler + * execution of HW Breakpoint or kprobes. We determine the cause + * using the bitmask flag 'sstep_reason'. + */ + if (((*ssr) & SSTEP_KPROBE) && + post_kprobe_handler(args->regs)) { + current->thread.vdr6 &= ~DR_STEP; ret = NOTIFY_STOP; + } break; case DIE_GPF: /* Index: linux-bkpt-lkml-27-rc9/include/asm-x86/kprobes.h =================================================================== --- linux-bkpt-lkml-27-rc9.orig/include/asm-x86/kprobes.h +++ linux-bkpt-lkml-27-rc9/include/asm-x86/kprobes.h @@ -30,6 +30,14 @@ struct pt_regs; struct kprobe; +/* Single stepping can be initiated for kprobes post handler or following HW + * Breakpoint exception. The bitmask below is used to identify the cause. + */ +#define SSTEP_KPROBE 1 +#define SSTEP_HWBKPT 2 + +DECLARE_PER_CPU(unsigned int, sstep_reason); + typedef u8 kprobe_opcode_t; #define BREAKPOINT_INSTRUCTION 0xcc #define RELATIVEJUMP_INSTRUCTION 0xe9
| |