Skip to contentSkip to conversation

powerpc: Consolidate *probe definitions

PATCH New Ananth N Mavinakayanahalli 2 participants 5 messages Aug 24, 2012 – Sep 5, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/3 powerpc: Consolidate *probe definitions

From: Ananth N Mavinakayanahalli <[email protected]>

Move is_trap() and relatives to a common file to be shared between *probes. Code movement only; no change in functionality.

Suggested by Michael Ellerman.

---
 arch/powerpc/include/asm/kprobes.h |   15 +------------
 arch/powerpc/include/asm/probes.h  |   42 +++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 13 deletions(-)
arch/powerpc/include/asm/kprobes.h +2 -13
Index: linux-tip-23aug/arch/powerpc/include/asm/kprobes.h
===================================================================
@@ -29,21 +29,16 @@
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
+#include <asm/probes.h>
 
 #define  __ARCH_WANT_KPROBES_INSN_SLOT
 
 struct pt_regs;
 struct kprobe;
 
-typedef unsigned int kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x7fe00008	/* trap */
+typedef opcode_t kprobe_opcode_t;
 #define MAX_INSN_SIZE 1
 
-#define IS_TW(instr)		(((instr) & 0xfc0007fe) == 0x7c000008)
-#define IS_TD(instr)		(((instr) & 0xfc0007fe) == 0x7c000088)
-#define IS_TDI(instr)		(((instr) & 0xfc000000) == 0x08000000)
-#define IS_TWI(instr)		(((instr) & 0xfc000000) == 0x0c000000)
-
 #ifdef CONFIG_PPC64
 /*
  * 64bit powerpc uses function descriptors.
@@ -72,12 +67,6 @@ typedef unsigned int kprobe_opcode_t;
 		addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
 	}								\
 }
-
-#define is_trap(instr)	(IS_TW(instr) || IS_TD(instr) || \
-			IS_TWI(instr) || IS_TDI(instr))
-#else
-/* Use stock kprobe_lookup_name since ppc32 doesn't use function descriptors */
-#define is_trap(instr)	(IS_TW(instr) || IS_TWI(instr))
 #endif
 
 #define flush_insn_slot(p)	do { } while (0)
arch/powerpc/include/asm/probes.h new file +42 -0

42 lines not on this page · raw message

#1 lore raw

PATCH 2/3 powerpc: Add trap_nr to thread_struct

From: Ananth N Mavinakayanahalli <[email protected]>

Add thread_struct.trap_nr and use it to store the last exception the thread experienced. In this patch, we populate the field at various places where we force_sig_info() to the process.

This is also used in uprobes to determine if the probed instruction caused an exception.

---
 arch/powerpc/include/asm/processor.h |    1 +
 arch/powerpc/kernel/process.c        |    2 ++
 arch/powerpc/kernel/traps.c          |    1 +
 arch/powerpc/mm/fault.c              |    1 +
 4 files changed, 5 insertions(+)
arch/powerpc/include/asm/processor.h +1 -0
Index: linux-26jul/arch/powerpc/include/asm/processor.h
===================================================================
@@ -219,6 +219,7 @@ struct thread_struct {
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #endif
 	unsigned long	dabr;		/* Data address breakpoint register */
+	unsigned long	trap_nr;	/* last trap # on this thread */
 #ifdef CONFIG_ALTIVEC
 	/* Complete AltiVec register set */
 	vector128	vr[32] __attribute__((aligned(16)));
arch/powerpc/kernel/process.c +2 -0
Index: linux-26jul/arch/powerpc/kernel/process.c
===================================================================
@@ -258,6 +258,7 @@ void do_send_trap(struct pt_regs *regs, 
 {
 	siginfo_t info;
 
+	current->thread.trap_nr = signal_code;
 	if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
 			11, SIGSEGV) == NOTIFY_STOP)
 		return;
@@ -275,6 +276,7 @@ void do_dabr(struct pt_regs *regs, unsig
 {
 	siginfo_t info;
 
+	current->thread.trap_nr = TRAP_HWBKPT;
 	if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
 			11, SIGSEGV) == NOTIFY_STOP)
 		return;
arch/powerpc/kernel/traps.c +1 -0
Index: linux-26jul/arch/powerpc/kernel/traps.c
===================================================================
@@ -251,6 +251,7 @@ void _exception(int signr, struct pt_reg
 	if (arch_irqs_disabled() && !arch_irq_disabled_regs(regs))
 		local_irq_enable();
 
+	current->thread.trap_nr = code;
 	memset(&info, 0, sizeof(info));
 	info.si_signo = signr;
 	info.si_code = code;
arch/powerpc/mm/fault.c +1 -0
Index: linux-26jul/arch/powerpc/mm/fault.c
===================================================================
@@ -133,6 +133,7 @@ static int do_sigbus(struct pt_regs *reg
 	up_read(&current->mm->mmap_sem);
 
 	if (user_mode(regs)) {
+		current->thread.trap_nr = BUS_ADRERR;
 		info.si_signo = SIGBUS;
 		info.si_errno = 0;
 		info.si_code = BUS_ADRERR;
#2 lore raw

PATCH v5 3/3 powerpc: Uprobes port to powerpc

In reply to Ananth N Mavinakayanahalli

From: Ananth N Mavinakayanahalli <[email protected]>

This is the port of uprobes to powerpc. Usage is similar to x86.

[root@xxxx ~]# ./bin/perf probe -x /lib64/libc.so.6 malloc Added new event:
probe_libc:malloc (on 0xb4860)

You can now use it in all perf tools, such as:

perf record -e probe_libc:malloc -aR sleep 1

[root@xxxx ~]# ./bin/perf record -e probe_libc:malloc -aR sleep 20 [ perf record: Woken up 22 times to write data ]
[ perf record: Captured and wrote 5.843 MB perf.data (~255302 samples) ] [root@xxxx ~]# ./bin/perf report --stdio
...

# Samples: 83K of event 'probe_libc:malloc'
# Event count (approx.): 83484
#
# Overhead Command Shared Object Symbol

# ........  ............  .............  ..........
#
    69.05%           tar  libc-2.12.so   [.] malloc
    28.57%            rm  libc-2.12.so   [.] malloc
     1.32%  avahi-daemon  libc-2.12.so   [.] malloc
     0.58%          bash  libc-2.12.so   [.] malloc
     0.28%          sshd  libc-2.12.so   [.] malloc
     0.08%    irqbalance  libc-2.12.so   [.] malloc
     0.05%         bzip2  libc-2.12.so   [.] malloc
     0.04%         sleep  libc-2.12.so   [.] malloc
     0.03%    multipathd  libc-2.12.so   [.] malloc
     0.01%      sendmail  libc-2.12.so   [.] malloc
     0.01%     automount  libc-2.12.so   [.] malloc

The trap_nr addition patch is a prereq.

---

Tested on POWER6; I don't see anything here that should stop it from working on a ppc32; since I don't have access to a ppc32 machine, it would be good if somoene could verify that part.

TODO:
Testsuite for uprobes (Not powerpc specific).

V5:
a. Incorporated Oleg's suggestion to make arch_uprobe a union for
easier deref of u32 on powerpc.
b. Incorporated various review comments by Michael Ellerman and
Benjamin Herrenschmidt.

V4:
Enhance arch_analyze_uprobe_insn() to reject uprobes on trap variants.

V3:
Added abort_xol() logic for powerpc, using thread_struct.trap_nr to determine if the stepped instruction caused an exception.

V2:
a. arch_uprobe_analyze_insn() now gets unsigned long addr. b. Verified that mtmsr[d] and rfi[d] are handled correctly by
emulate_step() (no changes to this patch).

 arch/powerpc/Kconfig                   |    3 
 arch/powerpc/include/asm/thread_info.h |    4 
 arch/powerpc/include/asm/uprobes.h     |   55 +++++++++
 arch/powerpc/kernel/Makefile           |    1 
 arch/powerpc/kernel/signal.c           |    6 +
 arch/powerpc/kernel/uprobes.c          |  184 +++++++++++++++++++++++++++++++++
 6 files changed, 252 insertions(+), 1 deletion(-)
arch/powerpc/include/asm/thread_info.h +3 -1
Index: linux-tip-23aug/arch/powerpc/include/asm/thread_info.h
===================================================================
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 #define TIF_RESTOREALL		11	/* Restore all regs (implies NOERROR) */
 #define TIF_NOERROR		12	/* Force successful syscall return */
 #define TIF_NOTIFY_RESUME	13	/* callback before returning to user */
+#define TIF_UPROBE		14	/* breakpointed or single-stepping */
 #define TIF_SYSCALL_TRACEPOINT	15	/* syscall tracepoint instrumentation */
 
 /* as above, but as bit values */
@@ -118,12 +119,13 @@ static inline struct thread_info *curren
 #define _TIF_RESTOREALL		(1<<TIF_RESTOREALL)
 #define _TIF_NOERROR		(1<<TIF_NOERROR)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_UPROBE		(1<<TIF_UPROBE)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
 				 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
 
 #define _TIF_USER_WORK_MASK	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
-				 _TIF_NOTIFY_RESUME)
+				 _TIF_NOTIFY_RESUME | _TIF_UPROBE)
 #define _TIF_PERSYSCALL_MASK	(_TIF_RESTOREALL|_TIF_NOERROR)
 
 /* Bits in local_flags */
arch/powerpc/include/asm/uprobes.h new file +55 -0

55 lines not on this page · raw message

arch/powerpc/kernel/Makefile +1 -0
Index: linux-tip-23aug/arch/powerpc/kernel/Makefile
===================================================================
@@ -96,6 +96,7 @@ obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
+obj-$(CONFIG_UPROBES)		+= uprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_SWIOTLB)		+= dma-swiotlb.o
arch/powerpc/kernel/signal.c +6 -0
Index: linux-tip-23aug/arch/powerpc/kernel/signal.c
===================================================================
@@ -11,6 +11,7 @@
 
 #include <linux/tracehook.h>
 #include <linux/signal.h>
+#include <linux/uprobes.h>
 #include <linux/key.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/uaccess.h>
@@ -157,6 +158,11 @@ static int do_signal(struct pt_regs *reg
 
 void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
 {
+	if (thread_info_flags & _TIF_UPROBE) {
+		clear_thread_flag(TIF_UPROBE);
+		uprobe_notify_resume(regs);
+	}
+
 	if (thread_info_flags & _TIF_SIGPENDING)
 		do_signal(regs);
 
arch/powerpc/kernel/uprobes.c new file +184 -0

184 lines not on this page · raw message

arch/powerpc/Kconfig +3 -0
Index: linux-tip-23aug/arch/powerpc/Kconfig
===================================================================
@@ -239,6 +239,9 @@ config PPC_OF_PLATFORM_PCI
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 	def_bool y
 
+config ARCH_SUPPORTS_UPROBES
+	def_bool y
+
 config PPC_ADV_DEBUG_REGS
 	bool
 	depends on 40x || BOOKE
#3 lore raw

Re: [PATCH v5 3/3] powerpc: Uprobes port to powerpc

Quoted 3 lines · Ananth N Mavinakayanahalli

From: Ananth N Mavinakayanahalli <[email protected]>

This is the port of uprobes to powerpc. Usage is similar to x86.

Guys, can you do a minimum of build testing ?

This one breaks due to uprobe_get_swbp_addr() being defined in both asm and include/linux when CONFIG_UPROBE isn't set. You don't need to define it at all in fact, the generic code takes care of both the declaration for CONFIG_UPROBE and the empty inline for !CONFIG_UPROBE.

I'm fixing that one up myself but please, please, get yourself a test build script or something to make sure you don't at least break the build when the stuff you're adding isn't enabled (among others).

Cheers,
Ben.

#4 lore raw

Re: [PATCH v5 3/3] powerpc: Uprobes port to powerpc

Quoted 7 lines · Benjamin Herrenschmidt
Quoted 3 lines · Ananth N Mavinakayanahalli

From: Ananth N Mavinakayanahalli <[email protected]>

This is the port of uprobes to powerpc. Usage is similar to x86.

Guys, can you do a minimum of build testing ?

Quoted 8 lines

This one breaks due to uprobe_get_swbp_addr() being defined in both asm and include/linux when CONFIG_UPROBE isn't set. You don't need to define it at all in fact, the generic code takes care of both the declaration for CONFIG_UPROBE and the empty inline for !CONFIG_UPROBE.

I'm fixing that one up myself but please, please, get yourself a test build script or something to make sure you don't at least break the build when the stuff you're adding isn't enabled (among others).

Sorry Ben. That was an oversight. Won't happen again.

Regards,
Ananth