linux-kernel.vger.kernel.org archive mirror
 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>,
	Linux-mm <linux-mm@kvack.org>,
	Arnaldo Carvalho de Melo <acme@infradead.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
	Ananth N Mavinakayanahalli <ananth@in.ibm.com>,
	Christoph Hellwig <hch@infradead.org>,
	Andi Kleen <andi@firstfloor.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Jonathan Corbet <corbet@lwn.net>, Oleg Nesterov <oleg@redhat.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Jim Keniston <jkenisto@linux.vnet.ibm.com>,
	Roland McGrath <roland@hack.frob.com>,
	SystemTap <systemtap@sources.redhat.com>,
	LKML <linux-kernel@vger.kernel.org>
Subject: [PATCH v3 2.6.39-rc1-tip 14/26] 14: x86: x86 specific probe handling
Date: Fri, 01 Apr 2011 20:05:17 +0530	[thread overview]
Message-ID: <20110401143517.15455.88373.sendpatchset@localhost6.localdomain6> (raw)
In-Reply-To: <20110401143223.15455.19844.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          |  171 ++++++++++++++++++++++++++++++++++++
 3 files changed, 178 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 1f2e61e..2dc1921 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 f81e940..bf98841 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -25,6 +25,7 @@
 #include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/uprobes.h>
+#include <linux/uaccess.h>
 
 #include <linux/kdebug.h>
 #include <asm/insn.h>
@@ -412,3 +413,173 @@ int analyze_insn(struct task_struct *tsk, struct uprobe *uprobe)
 	prepare_fixups(uprobe, &insn);
 	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.
+ */
+#ifdef CONFIG_X86_64
+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;
+	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;
+	}
+	return 0;
+}
+#else
+int pre_xol(struct uprobe *uprobe, struct pt_regs *regs)
+{
+	regs->ip = current->utask->xol_vaddr;
+	return 0;
+}
+#endif
+
+/*
+ * 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 = copy_from_user(&ra, (void __user *) sp, rasize);
+	if (unlikely(ncopied))
+		goto fail;
+	ra += correction;
+	ncopied = copy_to_user((void __user *) sp, &ra, rasize);
+	if (unlikely(ncopied))
+		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);
+}
+
+static void handle_riprel_post_xol(struct uprobe *uprobe,
+			struct pt_regs *regs, long *correction)
+{
+	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;
+	}
+}
+#else
+static void handle_riprel_post_xol(struct uprobe *uprobe,
+			struct pt_regs *regs, long *correction)
+{
+}
+#endif
+
+/*
+ * 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);
+	handle_riprel_post_xol(uprobe, regs, &correction);
+	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:[~2011-04-01 14:45 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-01 14:32 [PATCH v3 2.6.39-rc1-tip 0/26] 0: Uprobes patchset with perf probe support Srikar Dronamraju
2011-04-01 14:32 ` [PATCH v3 2.6.39-rc1-tip 1/26] 1: mm: replace_page() loses static attribute Srikar Dronamraju
2011-04-01 14:32 ` [PATCH v3 2.6.39-rc1-tip 2/26] 2: mm: Move replace_page() to mm/memory.c Srikar Dronamraju
2011-04-01 14:33 ` [PATCH v3 2.6.39-rc1-tip 3/26] 3: X86 specific breakpoint definitions Srikar Dronamraju
2011-04-01 14:33 ` [PATCH v3 2.6.39-rc1-tip 4/26] 4: uprobes: Breakground page replacement Srikar Dronamraju
2011-04-18 12:20   ` Peter Zijlstra
2011-04-01 14:33 ` [PATCH v3 2.6.39-rc1-tip 5/26] 5: uprobes: Adding and remove a uprobe in a rb tree Srikar Dronamraju
2011-04-18 12:20   ` Peter Zijlstra
2011-04-01 14:33 ` [PATCH v3 2.6.39-rc1-tip 6/26] 6: Uprobes: register/unregister probes Srikar Dronamraju
2011-04-02  0:26   ` Stephen Wilson
2011-04-02  0:53     ` Srikar Dronamraju
2011-04-02  1:29       ` Stephen Wilson
2011-04-18 12:20   ` Peter Zijlstra
2011-04-01 14:33 ` [PATCH v3 2.6.39-rc1-tip 7/26] 7: x86: analyze instruction and determine fixups Srikar Dronamraju
2011-04-19 13:29   ` Steven Rostedt
2011-04-21 17:31     ` Srikar Dronamraju
2011-04-21 17:52       ` Peter Zijlstra
2011-04-01 14:33 ` [PATCH v3 2.6.39-rc1-tip 8/26] 8: uprobes: store/restore original instruction Srikar Dronamraju
2011-04-18 16:12   ` Peter Zijlstra
2011-04-01 14:34 ` [PATCH v3 2.6.39-rc1-tip 9/26] 9: uprobes: mmap and fork hooks Srikar Dronamraju
2011-04-18 16:21   ` Peter Zijlstra
2011-04-18 16:29   ` Peter Zijlstra
2011-04-19  6:45     ` Srikar Dronamraju
2011-04-01 14:34 ` [PATCH v3 2.6.39-rc1-tip 10/26] 10: x86: architecture specific task information Srikar Dronamraju
2011-04-01 14:34 ` [PATCH v3 2.6.39-rc1-tip 11/26] 11: uprobes: task specific information Srikar Dronamraju
2011-04-01 14:34 ` [PATCH v3 2.6.39-rc1-tip 12/26] 12: uprobes: slot allocation for uprobes Srikar Dronamraju
2011-04-18 16:46   ` Peter Zijlstra
2011-04-19  6:26     ` Srikar Dronamraju
2011-04-19  9:02       ` Peter Zijlstra
2011-04-19  9:11       ` Peter Zijlstra
2011-04-20 13:40       ` Eric Paris
2011-04-20 14:51         ` Frank Ch. Eigler
2011-04-20 15:16           ` Stephen Smalley
2011-04-21 14:11         ` Srikar Dronamraju
2011-04-21 14:45           ` Eric Paris
2011-04-21 16:14             ` Roland McGrath
2011-04-21 16:59             ` Srikar Dronamraju
2011-04-01 14:35 ` [PATCH v3 2.6.39-rc1-tip 13/26] 13: uprobes: get the breakpoint address Srikar Dronamraju
2011-04-18 16:47   ` Peter Zijlstra
2011-04-01 14:35 ` Srikar Dronamraju [this message]
2011-04-18 16:55   ` [PATCH v3 2.6.39-rc1-tip 14/26] 14: x86: x86 specific probe handling Peter Zijlstra
2011-04-19  5:43     ` Srikar Dronamraju
2011-04-18 16:57   ` Peter Zijlstra
2011-04-01 14:35 ` [PATCH v3 2.6.39-rc1-tip 15/26] 15: uprobes: Handing int3 and singlestep exception Srikar Dronamraju
2011-04-19 13:03   ` Peter Zijlstra
2011-04-19 13:12     ` Steven Rostedt
2011-04-21 17:10     ` Srikar Dronamraju
2011-04-21 17:41       ` Peter Zijlstra
2011-04-19 13:39   ` Peter Zijlstra
2011-04-21 17:03     ` Srikar Dronamraju
2011-04-01 14:35 ` [PATCH v3 2.6.39-rc1-tip 16/26] 16: x86: uprobes exception notifier for x86 Srikar Dronamraju
2011-04-01 14:35 ` [PATCH v3 2.6.39-rc1-tip 17/26] 17: uprobes: register a notifier for uprobes Srikar Dronamraju
2011-04-19 13:54   ` Peter Zijlstra
2011-04-01 14:36 ` [PATCH v3 2.6.39-rc1-tip 18/26] 18: uprobes: commonly used filters Srikar Dronamraju
2011-04-05  1:26   ` Masami Hiramatsu
2011-04-19 13:57   ` Peter Zijlstra
2011-04-21 11:09     ` Srikar Dronamraju
2011-04-21 11:37       ` Peter Zijlstra
2011-04-21 11:49         ` Srikar Dronamraju
2011-04-01 14:36 ` [PATCH v3 2.6.39-rc1-tip 19/26] 19: tracing: Extract out common code for kprobes/uprobes traceevents Srikar Dronamraju
2011-04-01 14:36 ` [PATCH v3 2.6.39-rc1-tip 20/26] 20: tracing: uprobes trace_event interface Srikar Dronamraju
2011-04-01 14:36 ` [PATCH v3 2.6.39-rc1-tip 21/26] 21: Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Srikar Dronamraju
2011-04-01 14:47   ` [RESEND] [PATCH v3 2.6.39-rc1-tip 21/26] 21: Uprobe tracer documentation " Srikar Dronamraju
2011-04-01 14:36 ` [PATCH v3 2.6.39-rc1-tip 22/26] 22: perf: rename target_module to target Srikar Dronamraju
2011-04-04 10:06   ` Masami Hiramatsu
2011-04-06 23:46     ` Srikar Dronamraju
2011-04-01 14:37 ` [PATCH v3 2.6.39-rc1-tip 23/26] 23: perf: show possible probes in a given executable file or library Srikar Dronamraju
2011-04-04 10:15   ` Masami Hiramatsu
2011-04-06 22:50     ` Srikar Dronamraju
2011-04-01 14:37 ` [PATCH v3 2.6.39-rc1-tip 24/26] 24: perf: perf interface for uprobes Srikar Dronamraju
2011-04-01 14:37 ` [PATCH v3 2.6.39-rc1-tip 25/26] 25: perf: Documentation for perf uprobes Srikar Dronamraju
2011-04-01 14:37 ` [PATCH v3 2.6.39-rc1-tip 26/26] 26: uprobes: filter chain Srikar Dronamraju
2011-04-05  1:27   ` Masami Hiramatsu
2011-04-06 22:41     ` Srikar Dronamraju
2011-04-07  3:19       ` Masami Hiramatsu

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=20110401143517.15455.88373.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=corbet@lwn.net \
    --cc=hch@infradead.org \
    --cc=jkenisto@linux.vnet.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=mingo@elte.hu \
    --cc=oleg@redhat.com \
    --cc=peterz@infradead.org \
    --cc=roland@hack.frob.com \
    --cc=rostedt@goodmis.org \
    --cc=systemtap@sources.redhat.com \
    --cc=tglx@linutronix.de \
    --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;
as well as URLs for NNTP newsgroup(s).