From patchwork Fri Jun 8 09:34:45 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ananth N Mavinakayanahalli X-Patchwork-Id: 163739 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id 183751008FB for ; Fri, 8 Jun 2012 19:35:57 +1000 (EST) Received: from e34.co.us.ibm.com (e34.co.us.ibm.com [32.97.110.152]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "e34.co.us.ibm.com", Issuer "Equifax" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 3C8D9B6FC5 for ; Fri, 8 Jun 2012 19:34:55 +1000 (EST) Received: from /spool/local by e34.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 8 Jun 2012 03:34:53 -0600 Received: from d03dlp01.boulder.ibm.com (9.17.202.177) by e34.co.us.ibm.com (192.168.1.134) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 8 Jun 2012 03:34:50 -0600 Received: from d03relay03.boulder.ibm.com (d03relay03.boulder.ibm.com [9.17.195.228]) by d03dlp01.boulder.ibm.com (Postfix) with ESMTP id 780D61FF001D for ; Fri, 8 Jun 2012 09:34:49 +0000 (WET) Received: from d03av01.boulder.ibm.com (d03av01.boulder.ibm.com [9.17.195.167]) by d03relay03.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q589YmJH160558 for ; Fri, 8 Jun 2012 03:34:48 -0600 Received: from d03av01.boulder.ibm.com (loopback [127.0.0.1]) by d03av01.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q589Yl2h010854 for ; Fri, 8 Jun 2012 03:34:48 -0600 Received: from thinktux.localdomain (thinktux.in.ibm.com [9.124.35.98]) by d03av01.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q589YjfF010813; Fri, 8 Jun 2012 03:34:46 -0600 Received: by thinktux.localdomain (Postfix, from userid 500) id 60DF72200A2; Fri, 8 Jun 2012 15:04:45 +0530 (IST) Date: Fri, 8 Jun 2012 15:04:45 +0530 From: Ananth N Mavinakayanahalli To: linuxppc-dev@lists.ozlabs.org, lkml Subject: [PATCH v2 2/2] [POWERPC] uprobes: powerpc port Message-ID: <20120608093445.GH13409@in.ibm.com> References: <20120608093257.GG13409@in.ibm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20120608093257.GG13409@in.ibm.com> User-Agent: Mutt/1.5.17 (2007-11-01) X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12060809-1780-0000-0000-000006438C2F X-IBM-ISS-SpamDetectors: X-IBM-ISS-DetailInfo: BY=3.00000281; HX=3.00000190; KW=3.00000007; PH=3.00000001; SC=3.00000002; SDB=6.00146215; UDB=6.00033466; UTC=2012-06-08 09:34:51 Cc: Srikar Dronamraju , peterz@infradead.org, antonb@thinktux.localdomain, oleg@redhat.com, michael@ellerman.id.au, Jim Keniston , Paul Mackerras , Ingo Molnar X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15rc1 Precedence: list Reply-To: ananth@in.ibm.com List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" 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. 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. [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 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). Signed-off-by: Ananth N Mavinakayanahalli --- arch/powerpc/Kconfig | 3 arch/powerpc/include/asm/thread_info.h | 4 arch/powerpc/include/asm/uprobes.h | 49 +++++++++ arch/powerpc/kernel/Makefile | 1 arch/powerpc/kernel/signal.c | 6 + arch/powerpc/kernel/uprobes.c | 164 +++++++++++++++++++++++++++++++++ 6 files changed, 226 insertions(+), 1 deletion(-) Index: linux-3.5-rc1/arch/powerpc/include/asm/thread_info.h =================================================================== --- linux-3.5-rc1.orig/arch/powerpc/include/asm/thread_info.h +++ linux-3.5-rc1/arch/powerpc/include/asm/thread_info.h @@ -96,6 +96,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 */ @@ -112,12 +113,13 @@ static inline struct thread_info *curren #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, unsigned long addr); +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 +++ linux-3.5-rc1/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 Index: linux-3.5-rc1/arch/powerpc/kernel/signal.c =================================================================== --- linux-3.5-rc1.orig/arch/powerpc/kernel/signal.c +++ linux-3.5-rc1/arch/powerpc/kernel/signal.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -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); Index: linux-3.5-rc1/arch/powerpc/kernel/uprobes.c =================================================================== --- /dev/null +++ linux-3.5-rc1/arch/powerpc/kernel/uprobes.c @@ -0,0 +1,164 @@ +/* + * 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. + * @addr: vaddr to probe. + * Return 0 on success or a -ve number on error. + */ +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) +{ + if (addr & 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 +++ linux-3.5-rc1/arch/powerpc/Kconfig @@ -237,6 +237,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