lkml.org 
[lkml]   [2008]   [Oct]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
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

\
 
 \ /
  Last update: 2008-10-07 13:47    [from the cache]
©2003-2014 Jasper Spaans. Advertise on this site