The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
To: Peter Zijlstra <peterz@infradead.org>, Ingo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>,
	Srikar Dronamraju <srikar@linux.vnet.ibm.com>,
	Arnaldo Carvalho de Melo <acme@infradead.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
	Christoph Hellwig <hch@infradead.org>,
	Andi Kleen <andi@firstfloor.org>, Oleg Nesterov <oleg@redhat.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	SystemTap <systemtap@sources.redhat.com>,
	Linux-mm <linux-mm@vger.kernel.org>,
	Jim Keniston <jkenisto@linux.vnet.ibm.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Ananth N Mavinakayanahalli <ananth@in.ibm.com>,
	LKML <linux-kernel@vger.kernel.org>,
	"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Subject: [RFC] [PATCH 2.6.37-rc5-tip 13/20] 13: x86: x86 specific probe handling
Date: Thu, 16 Dec 2010 15:29:47 +0530	[thread overview]
Message-ID: <20101216095947.23751.75003.sendpatchset@localhost6.localdomain6> (raw)
In-Reply-To: <20101216095714.23751.52601.sendpatchset@localhost6.localdomain6>


Provides x86 specific implementations for setting the current
instruction pointer, pre single-step and post-singlestep handling,
enabling and disabling singlestep.

This patch also introduces TIF_UPROBE which is set by uprobes notifier
code. TIF_UPROBE indicates that there is pending work that needs to be
done at do_notify_resume time.

Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
---
 arch/x86/include/asm/thread_info.h |    2 
 arch/x86/include/asm/uprobes.h     |    5 +
 arch/x86/kernel/uprobes.c          |  155 ++++++++++++++++++++++++++++++++++++
 3 files changed, 162 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index f0b6e5d..5b9c9f0 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -84,6 +84,7 @@ struct thread_info {
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_MCE_NOTIFY		10	/* notify userspace of an MCE */
 #define TIF_USER_RETURN_NOTIFY	11	/* notify kernel of userspace return */
+#define TIF_UPROBE		12	/* breakpointed or singlestepping */
 #define TIF_NOTSC		16	/* TSC is not accessible in userland */
 #define TIF_IA32		17	/* 32bit process */
 #define TIF_FORK		18	/* ret_from_fork */
@@ -107,6 +108,7 @@ struct thread_info {
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_MCE_NOTIFY		(1 << TIF_MCE_NOTIFY)
 #define _TIF_USER_RETURN_NOTIFY	(1 << TIF_USER_RETURN_NOTIFY)
+#define _TIF_UPROBE		(1 << TIF_UPROBE)
 #define _TIF_NOTSC		(1 << TIF_NOTSC)
 #define _TIF_IA32		(1 << TIF_IA32)
 #define _TIF_FORK		(1 << TIF_FORK)
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index e38950f..0c9c8b6 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -44,4 +44,9 @@ struct uprobe_task_arch_info {};
 #endif
 struct uprobe;
 extern int analyze_insn(struct task_struct *tsk, struct uprobe *uprobe);
+extern void set_ip(struct pt_regs *regs, unsigned long vaddr);
+extern int pre_xol(struct uprobe *uprobe, struct pt_regs *regs);
+extern int post_xol(struct uprobe *uprobe, struct pt_regs *regs);
+extern void arch_uprobe_enable_sstep(struct pt_regs *regs);
+extern void arch_uprobe_disable_sstep(struct pt_regs *regs);
 #endif	/* _ASM_UPROBES_H */
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 352c71f..9a0b8a9 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -413,3 +413,158 @@ int analyze_insn(struct task_struct *tsk, struct uprobe *uprobe)
 	return 0;
 }
 
+/*
+ * @reg: reflects the saved state of the task
+ * @vaddr: the virtual address to jump to.
+ * Return 0 on success or a -ve number on error.
+ */
+void set_ip(struct pt_regs *regs, unsigned long vaddr)
+{
+	regs->ip = vaddr;
+}
+
+/*
+ * pre_xol - prepare to execute out of line.
+ * @uprobe: the probepoint information.
+ * @regs: reflects the saved user state of @tsk.
+ *
+ * If we're emulating a rip-relative instruction, save the contents
+ * of the scratch register and store the target address in that register.
+ *
+ * Returns true if @uprobe->opcode is @bkpt_insn.
+ */
+int pre_xol(struct uprobe *uprobe, struct pt_regs *regs)
+{
+	struct uprobe_task_arch_info *tskinfo = &current->utask->tskinfo;
+
+	regs->ip = current->utask->xol_vaddr;
+#ifdef CONFIG_X86_64
+	if (uprobe->fixups & UPROBES_FIX_RIP_AX) {
+		tskinfo->saved_scratch_register = regs->ax;
+		regs->ax = current->utask->vaddr;
+		regs->ax += uprobe->arch_info.rip_rela_target_address;
+	} else if (uprobe->fixups & UPROBES_FIX_RIP_CX) {
+		tskinfo->saved_scratch_register = regs->cx;
+		regs->cx = current->utask->vaddr;
+		regs->cx += uprobe->arch_info.rip_rela_target_address;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * Called by post_xol() to adjust the return address pushed by a call
+ * instruction executed out of line.
+ */
+static int adjust_ret_addr(unsigned long sp, long correction)
+{
+	int rasize, ncopied;
+	long ra = 0;
+
+	if (is_32bit_app(current))
+		rasize = 4;
+	else
+		rasize = 8;
+	ncopied = uprobes_read_vm(current, (void __user *) sp, &ra, rasize);
+	if (unlikely(ncopied != rasize))
+		goto fail;
+	ra += correction;
+	ncopied = uprobes_write_vm(current, (void __user *) sp, &ra, rasize);
+	if (unlikely(ncopied != rasize))
+		goto fail;
+	return 0;
+
+fail:
+	printk(KERN_ERR
+		"uprobes: Failed to adjust return address after"
+		" single-stepping call instruction;"
+		" pid=%d, sp=%#lx\n", current->pid, sp);
+	return -EFAULT;
+}
+
+#ifdef CONFIG_X86_64
+static bool is_riprel_insn(struct uprobe *uprobe)
+{
+	return ((uprobe->fixups &
+			(UPROBES_FIX_RIP_AX | UPROBES_FIX_RIP_CX)) != 0);
+}
+
+#endif	/* CONFIG_X86_64 */
+
+/*
+ * Called after single-stepping. To avoid the SMP problems that can
+ * occur when we temporarily put back the original opcode to
+ * single-step, we single-stepped a copy of the instruction.
+ *
+ * This function prepares to resume execution after the single-step.
+ * We have to fix things up as follows:
+ *
+ * Typically, the new ip is relative to the copied instruction.  We need
+ * to make it relative to the original instruction (FIX_IP).  Exceptions
+ * are return instructions and absolute or indirect jump or call instructions.
+ *
+ * If the single-stepped instruction was a call, the return address that
+ * is atop the stack is the address following the copied instruction.  We
+ * need to make it the address following the original instruction (FIX_CALL).
+ *
+ * If the original instruction was a rip-relative instruction such as
+ * "movl %edx,0xnnnn(%rip)", we have instead executed an equivalent
+ * instruction using a scratch register -- e.g., "movl %edx,(%rax)".
+ * We need to restore the contents of the scratch register and adjust
+ * the ip, keeping in mind that the instruction we executed is 4 bytes
+ * shorter than the original instruction (since we squeezed out the offset
+ * field).  (FIX_RIP_AX or FIX_RIP_CX)
+ */
+int post_xol(struct uprobe *uprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+	int result = 0;
+	long correction;
+
+	correction = (long)(utask->vaddr - utask->xol_vaddr);
+#ifdef CONFIG_X86_64
+	if (is_riprel_insn(uprobe)) {
+		struct uprobe_task_arch_info *tskinfo;
+		tskinfo = &current->utask->tskinfo;
+
+		if (uprobe->fixups & UPROBES_FIX_RIP_AX)
+			regs->ax = tskinfo->saved_scratch_register;
+		else
+			regs->cx = tskinfo->saved_scratch_register;
+		/*
+		 * The original instruction includes a displacement, and so
+		 * is 4 bytes longer than what we've just single-stepped.
+		 * Fall through to handle stuff like "jmpq *...(%rip)" and
+		 * "callq *...(%rip)".
+		 */
+		correction += 4;
+	}
+#endif
+	if (uprobe->fixups & UPROBES_FIX_IP)
+		regs->ip += correction;
+	if (uprobe->fixups & UPROBES_FIX_CALL)
+		result = adjust_ret_addr(regs->sp, correction);
+	return result;
+}
+
+void arch_uprobe_enable_sstep(struct pt_regs *regs)
+{
+	/*
+	 * Enable single-stepping by
+	 * - Set TF on stack
+	 * - Set TIF_SINGLESTEP: Guarantees that TF is set when
+	 *	returning to user mode.
+	 *  - Indicate that TF is set by us.
+	 */
+	regs->flags |= X86_EFLAGS_TF;
+	set_thread_flag(TIF_SINGLESTEP);
+	set_thread_flag(TIF_FORCED_TF);
+}
+
+void arch_uprobe_disable_sstep(struct pt_regs *regs)
+{
+	/* Disable single-stepping by clearing what we set */
+	clear_thread_flag(TIF_SINGLESTEP);
+	clear_thread_flag(TIF_FORCED_TF);
+	regs->flags &= ~X86_EFLAGS_TF;
+}

  parent reply	other threads:[~2010-12-16 10:02 UTC|newest]

Thread overview: 91+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-16  9:57 [RFC] [PATCH 2.6.37-rc5-tip 0/20] 0: Inode based uprobes Srikar Dronamraju
2010-12-16  9:57 ` [RFC] [PATCH 2.6.37-rc5-tip 1/20] 1: mm: Move replace_page() / write_protect_page() to mm/memory.c Srikar Dronamraju
2010-12-16  9:57 ` [RFC] [PATCH 2.6.37-rc5-tip 2/20] 2: X86 specific breakpoint definitions Srikar Dronamraju
2010-12-16  9:57 ` [RFC] [PATCH 2.6.37-rc5-tip 3/20] 3: uprobes: Breakground page replacement Srikar Dronamraju
2010-12-16  9:58 ` [RFC] [PATCH 2.6.37-rc5-tip 4/20] 4: uprobes: Adding and remove a uprobe in a rb tree Srikar Dronamraju
2011-01-25 12:15   ` Peter Zijlstra
2011-01-26  8:37     ` Srikar Dronamraju
2011-01-25 12:15   ` Peter Zijlstra
2011-01-26  8:41     ` Srikar Dronamraju
2011-01-26 10:13       ` Peter Zijlstra
2011-01-25 12:15   ` Peter Zijlstra
2011-01-26  8:38     ` Srikar Dronamraju
2011-01-25 13:56   ` Peter Zijlstra
2011-01-26  8:45     ` Srikar Dronamraju
2011-01-26 10:14       ` Peter Zijlstra
2011-01-26 15:18         ` Srikar Dronamraju
2011-01-26 15:33           ` Peter Zijlstra
2010-12-16  9:58 ` [RFC] [PATCH 2.6.37-rc5-tip 5/20] 5: Uprobes: register/unregister probes Srikar Dronamraju
2011-01-25 12:15   ` Peter Zijlstra
2011-01-26  7:55     ` Srikar Dronamraju
2011-01-26 10:11       ` Peter Zijlstra
2011-01-26 15:30         ` Srikar Dronamraju
2011-01-26 15:45           ` Peter Zijlstra
2011-01-26 16:56             ` Srikar Dronamraju
2011-01-26 17:12               ` Peter Zijlstra
2011-01-27 10:01                 ` Srikar Dronamraju
2011-01-27 10:23                   ` Peter Zijlstra
2011-01-27 10:25                     ` Srikar Dronamraju
2011-01-27 10:41                       ` Peter Zijlstra
2011-01-27 10:29                   ` Peter Zijlstra
2011-01-25 12:15   ` Peter Zijlstra
2011-01-26  7:47     ` Srikar Dronamraju
2011-01-26 10:10       ` Peter Zijlstra
2010-12-16  9:58 ` [RFC] [PATCH 2.6.37-rc5-tip 6/20] 6: x86: analyze instruction and determine fixups Srikar Dronamraju
2010-12-16  9:58 ` [RFC] [PATCH 2.6.37-rc5-tip 7/20] 7: uprobes: store/restore original instruction Srikar Dronamraju
2011-01-25 12:15   ` Peter Zijlstra
2010-12-16  9:58 ` [RFC] [PATCH 2.6.37-rc5-tip 8/20] 8: uprobes: mmap and fork hooks Srikar Dronamraju
2011-01-25 12:15   ` Peter Zijlstra
2011-01-26  9:03     ` Srikar Dronamraju
2011-01-26 10:20       ` Peter Zijlstra
2011-01-26 14:59         ` Srikar Dronamraju
2011-01-26 15:16           ` Peter Zijlstra
2011-01-26 16:30             ` Srikar Dronamraju
2011-01-25 12:15   ` Peter Zijlstra
2011-01-25 20:05     ` Steven Rostedt
2011-01-26  9:06       ` Srikar Dronamraju
2011-01-27 17:03         ` Steven Rostedt
2011-01-28  4:53           ` Srikar Dronamraju
2011-01-28 13:57             ` Steven Rostedt
2011-01-28 14:28               ` Steven Rostedt
2011-01-28 14:46                 ` Srikar Dronamraju
2011-01-28 15:02                   ` Steven Rostedt
2011-01-26 15:09     ` Srikar Dronamraju
2011-01-26 15:20       ` Peter Zijlstra
2010-12-16  9:58 ` [RFC] [PATCH 2.6.37-rc5-tip 9/20] 9: x86: architecture specific task information Srikar Dronamraju
2010-12-16  9:59 ` [RFC] [PATCH 2.6.37-rc5-tip 10/20] 10: uprobes: task specific information Srikar Dronamraju
2011-01-25 13:56   ` Peter Zijlstra
2011-01-25 18:38     ` Josh Stone
2011-01-25 18:55       ` Roland McGrath
2011-01-25 19:56       ` Peter Zijlstra
2010-12-16  9:59 ` [RFC] [PATCH 2.6.37-rc5-tip 11/20] 11: uprobes: slot allocation for uprobes Srikar Dronamraju
2011-01-25 13:56   ` Peter Zijlstra
2010-12-16  9:59 ` [RFC] [PATCH 2.6.37-rc5-tip 12/20] 12: uprobes: get the breakpoint address Srikar Dronamraju
2011-01-25 13:56   ` Peter Zijlstra
2010-12-16  9:59 ` Srikar Dronamraju [this message]
2011-01-25 13:56   ` [RFC] [PATCH 2.6.37-rc5-tip 13/20] 13: x86: x86 specific probe handling Peter Zijlstra
2011-01-27  9:40     ` Srikar Dronamraju
2011-01-27 10:22       ` Peter Zijlstra
2011-01-27 19:11         ` Roland McGrath
2011-01-28  4:57           ` Srikar Dronamraju
2011-01-28  6:23             ` Roland McGrath
2011-01-28  8:36               ` Peter Zijlstra
2011-01-28 18:23                 ` Roland McGrath
2010-12-16  9:59 ` [RFC] [PATCH 2.6.37-rc5-tip 14/20] 14: uprobes: Handing int3 and singlestep exception Srikar Dronamraju
2011-01-25 13:56   ` Peter Zijlstra
2011-01-25 13:56   ` Peter Zijlstra
2011-01-26  8:52     ` Srikar Dronamraju
2011-01-26 10:17       ` Peter Zijlstra
2011-01-26 15:14         ` Srikar Dronamraju
2011-01-26 15:29           ` Peter Zijlstra
2010-12-16 10:00 ` [RFC] [PATCH 2.6.37-rc5-tip 15/20] 15: x86: uprobes exception notifier for x86 Srikar Dronamraju
2010-12-16 10:00 ` [RFC] [PATCH 2.6.37-rc5-tip 16/20] 16: uprobes: register a notifier for uprobes Srikar Dronamraju
2011-01-25 13:56   ` Peter Zijlstra
2011-01-27  6:50     ` Srikar Dronamraju
2010-12-16 10:00 ` [RFC] [PATCH 2.6.37-rc5-tip 17/20] 17: uprobes: filter chain Srikar Dronamraju
2010-12-16 10:00 ` [RFC] [PATCH 2.6.37-rc5-tip 18/20] 18: uprobes: commonly used filters Srikar Dronamraju
2010-12-17 19:32   ` Valdis.Kletnieks
2010-12-18  3:04     ` Srikar Dronamraju
2010-12-16 10:00 ` [RFC] [PATCH 2.6.37-rc5-tip 19/20] 19: tracing: Extract out common code for kprobes/uprobes traceevents Srikar Dronamraju
2010-12-16 10:01 ` [RFC] [PATCH 2.6.37-rc5-tip 20/20] 20: tracing: uprobes trace_event interface Srikar Dronamraju
2010-12-16 10:07 ` [RFC] [PATCH 2.6.37-rc5-tip 0/20] 0: Inode based uprobes Srikar Dronamraju

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101216095947.23751.75003.sendpatchset@localhost6.localdomain6 \
    --to=srikar@linux.vnet.ibm.com \
    --cc=acme@infradead.org \
    --cc=akpm@linux-foundation.org \
    --cc=ananth@in.ibm.com \
    --cc=andi@firstfloor.org \
    --cc=fweisbec@gmail.com \
    --cc=hch@infradead.org \
    --cc=jkenisto@linux.vnet.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@vger.kernel.org \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=mingo@elte.hu \
    --cc=oleg@redhat.com \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=systemtap@sources.redhat.com \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox