Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755344Ab2FFJWM (ORCPT ); Wed, 6 Jun 2012 05:22:12 -0400 Received: from e31.co.us.ibm.com ([32.97.110.149]:46456 "EHLO e31.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751493Ab2FFJWK (ORCPT ); Wed, 6 Jun 2012 05:22:10 -0400 Date: Wed, 6 Jun 2012 14:51:50 +0530 From: Ananth N Mavinakayanahalli To: linuxppc-dev@lists.ozlabs.org, lkml Cc: Paul Mackerras , benh@kernel.crashing.org, Srikar Dronamraju , Anton Blanchard , Ingo Molnar , peterz@infradead.org, oleg@redhat.com Subject: [PATCH 2/2] [POWERPC] uprobes: powerpc port Message-ID: <20120606092150.GC6745@in.ibm.com> Reply-To: ananth@in.ibm.com References: <20120606091950.GB6745@in.ibm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20120606091950.GB6745@in.ibm.com> User-Agent: Mutt/1.5.17 (2007-11-01) X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12060609-7282-0000-0000-000009A80262 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 13197 Lines: 364 From: Ananth N Mavinakayanahalli This is the port of uprobes to powerpc. Usage is similar to x86. One TODO in this port compared to x86 is the uprobe abort_xol() logic. x86 depends on the thread_struct.trap_nr (absent in powerpc) to determine if a signal was caused when the uprobed instruction was single-stepped/ emulated, in which case, we reset the instruction pointer to the probed address and retry the probe again. [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 # ======== # captured on: Mon Jun 4 05:26:31 2012 # hostname : xxxx.ibm.com # os release : 3.4.0-uprobe # perf version : 3.4.0 # arch : ppc64 # nrcpus online : 4 # nrcpus avail : 4 # cpudesc : POWER6 (raw), altivec supported # cpuid : 62,769 # total memory : 7310528 kB # cmdline : /root/bin/perf record -e probe_libc:malloc -aR sleep 20 # event : name = probe_libc:malloc, type = 2, config = 0x124, config1 = 0x0, con # HEADER_CPU_TOPOLOGY info available, use -I to display # HEADER_NUMA_TOPOLOGY info available, use -I to display # ======== # # 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 Signed-off-by: Ananth N Mavinakayanahalli Index: linux-3.5-rc1/arch/powerpc/include/asm/thread_info.h =================================================================== --- linux-3.5-rc1.orig/arch/powerpc/include/asm/thread_info.h 2012-06-03 06:59:26.000000000 +0530 +++ linux-3.5-rc1/arch/powerpc/include/asm/thread_info.h 2012-06-03 21:05:48.226233001 +0530 @@ -96,6 +96,7 @@ #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 */ @@ -112,12 +113,13 @@ #define _TIF_RESTOREALL (1< + */ + +#include + +typedef unsigned int uprobe_opcode_t; + +#define MAX_UINSN_BYTES 4 +#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES) + +#define UPROBE_SWBP_INSN 0x7fe00008 +#define UPROBE_SWBP_INSN_SIZE 4 /* swbp insn size in bytes */ + +struct arch_uprobe { + u8 insn[MAX_UINSN_BYTES]; +}; + +struct arch_uprobe_task { +}; + +extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, loff_t vaddr); +extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs); +extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); +extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); +extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); +extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data); +extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs); +#endif /* _ASM_UPROBES_H */ Index: linux-3.5-rc1/arch/powerpc/kernel/Makefile =================================================================== --- linux-3.5-rc1.orig/arch/powerpc/kernel/Makefile 2012-06-03 06:59:26.000000000 +0530 +++ linux-3.5-rc1/arch/powerpc/kernel/Makefile 2012-06-03 21:05:48.226233001 +0530 @@ -96,6 +96,7 @@ 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 Index: linux-3.5-rc1/arch/powerpc/kernel/signal.c =================================================================== --- linux-3.5-rc1.orig/arch/powerpc/kernel/signal.c 2012-06-03 06:59:26.000000000 +0530 +++ linux-3.5-rc1/arch/powerpc/kernel/signal.c 2012-06-03 21:05:48.236233000 +0530 @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -157,6 +158,11 @@ 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); Index: linux-3.5-rc1/arch/powerpc/kernel/uprobes.c =================================================================== --- linux-3.5-rc1.orig/arch/powerpc/kernel/uprobes.c 2012-05-31 02:23:15.746233001 +0530 +++ linux-3.5-rc1/arch/powerpc/kernel/uprobes.c 2012-06-03 21:05:48.236233000 +0530 @@ -0,0 +1,163 @@ +/* + * User-space Probes (UProbes) for powerpc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2007-2012 + * + * Adapted from the x86 port by Ananth N Mavinakayanahalli + */ +#include +#include +#include +#include +#include + +#include +#include + +/** + * arch_uprobe_analyze_insn + * @mm: the probed address space. + * @arch_uprobe: the probepoint information. + * Return 0 on success or a -ve number on error. + */ +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, loff_t vaddr) +{ + if (vaddr & 0x03) + return -EINVAL; + return 0; +} + +/* + * arch_uprobe_pre_xol - prepare to execute out of line. + * @auprobe: the probepoint information. + * @regs: reflects the saved user state of current task. + */ +int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + /* FIXME: We don't support abort_xol on powerpc for now */ + regs->nip = current->utask->xol_vaddr; + return 0; +} + +/** + * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs + * @regs: Reflects the saved state of the task after it has hit a breakpoint + * instruction. + * Return the address of the breakpoint instruction. + */ +unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) +{ + return instruction_pointer(regs); +} + +/* + * If xol insn itself traps and generates a signal (SIGILL/SIGSEGV/etc), + * then detect the case where a singlestepped instruction jumps back to its + * own address. It is assumed that anything like do_page_fault/do_trap/etc + * sets thread.trap_nr != -1. + * + * FIXME: powerpc however doesn't have thread.trap_nr yet. + * + * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr, + * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to + * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol(). + */ +bool arch_uprobe_xol_was_trapped(struct task_struct *t) +{ + /* FIXME: We don't support abort_xol on powerpc for now */ + return false; +} + +/* + * 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. + */ +int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + /* FIXME: We don't support abort_xol on powerpc for now */ + + /* + * On powerpc, except for loads and stores, most instructions + * including ones that alter code flow (branches, calls, returns) + * are emulated in the kernel. We get here only if the emulation + * support doesn't exist and have to fix-up the next instruction + * to be executed. + */ + regs->nip = current->utask->vaddr + MAX_UINSN_BYTES; + return 0; +} + +/* callback routine for handling exceptions. */ +int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data) +{ + struct die_args *args = data; + struct pt_regs *regs = args->regs; + int ret = NOTIFY_DONE; + + /* We are only interested in userspace traps */ + if (regs && !user_mode(regs)) + return NOTIFY_DONE; + + switch (val) { + case DIE_BPT: + if (uprobe_pre_sstep_notifier(regs)) + ret = NOTIFY_STOP; + break; + case DIE_SSTEP: + if (uprobe_post_sstep_notifier(regs)) + ret = NOTIFY_STOP; + default: + break; + } + return ret; +} + +/* + * This function gets called when XOL instruction either gets trapped or + * the thread has a fatal signal, so reset the instruction pointer to its + * probed address. + */ +void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + /* FIXME: We don't support abort_xol on powerpc for now */ + return; +} + +/* + * See if the instruction can be emulated. + * Returns true if instruction was emulated, false otherwise. + */ +bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + int ret; + unsigned int insn; + + memcpy(&insn, auprobe->insn, MAX_UINSN_BYTES); + + /* + * emulate_step() returns 1 if the insn was successfully emulated. + * For all other cases, we need to single-step in hardware. + */ + ret = emulate_step(regs, insn); + if (ret > 0) + return true; + + return false; +} Index: linux-3.5-rc1/arch/powerpc/Kconfig =================================================================== --- linux-3.5-rc1.orig/arch/powerpc/Kconfig 2012-06-03 06:59:26.000000000 +0530 +++ linux-3.5-rc1/arch/powerpc/Kconfig 2012-06-03 21:05:48.246233000 +0530 @@ -237,6 +237,9 @@ 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 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/