From: Ananth N Mavinakayanahalli <hidden> Date: 2012-08-24 07:26:49
From: Ananth N Mavinakayanahalli <redacted>
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.
Signed-off-by: Ananth N Mavinakayanahalli <redacted>
---
arch/powerpc/include/asm/kprobes.h | 15 +------------
arch/powerpc/include/asm/probes.h | 42 +++++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 13 deletions(-)
Index: linux-tip-23aug/arch/powerpc/include/asm/kprobes.h
===================================================================
@@ -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)
From: Ananth N Mavinakayanahalli <hidden> Date: 2012-08-24 07:27:26
From: Ananth N Mavinakayanahalli <redacted>
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.
Signed-off-by: Ananth N Mavinakayanahalli <redacted>
---
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(+)
Index: linux-26jul/arch/powerpc/include/asm/processor.h
===================================================================
From: Ananth N Mavinakayanahalli <hidden> Date: 2012-08-24 07:32:06
From: Ananth N Mavinakayanahalli <redacted>
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.
Signed-off-by: Ananth N Mavinakayanahalli <redacted>
---
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(-)
Index: linux-tip-23aug/arch/powerpc/include/asm/thread_info.h
===================================================================
@@ -0,0 +1,55 @@+#ifndef _ASM_UPROBES_H+#define _ASM_UPROBES_H+/*+*User-spaceProbes(UProbes)forpowerpc+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby+*theFreeSoftwareFoundation;eitherversion2oftheLicense,or+*(atyouroption)anylaterversion.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram;ifnot,writetotheFreeSoftware+*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.+*+*CopyrightIBMCorporation,2007-2012+*+*Adaptedfromthex86portbyAnanthNMavinakayanahalli<ananth@in.ibm.com>+*/++#include<linux/notifier.h>+#include<asm/probes.h>++typedefopcode_tuprobe_opcode_t;++#define MAX_UINSN_BYTES 4+#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)++/* The following alias is needed for reference from arch-agnostic code */+#define UPROBE_SWBP_INSN BREAKPOINT_INSTRUCTION+#define UPROBE_SWBP_INSN_SIZE 4 /* swbp insn size in bytes */++structarch_uprobe{+union{+u8insn[MAX_UINSN_BYTES];+u32ainsn;+};+};++structarch_uprobe_task{+unsignedlongsaved_trap_nr;+};++externintarch_uprobe_analyze_insn(structarch_uprobe*aup,structmm_struct*mm,unsignedlongaddr);+externunsignedlonguprobe_get_swbp_addr(structpt_regs*regs);+externintarch_uprobe_pre_xol(structarch_uprobe*aup,structpt_regs*regs);+externintarch_uprobe_post_xol(structarch_uprobe*aup,structpt_regs*regs);+externboolarch_uprobe_xol_was_trapped(structtask_struct*tsk);+externintarch_uprobe_exception_notify(structnotifier_block*self,unsignedlongval,void*data);+externvoidarch_uprobe_abort_xol(structarch_uprobe*aup,structpt_regs*regs);+#endif /* _ASM_UPROBES_H */
@@ -0,0 +1,184 @@+/*+*User-spaceProbes(UProbes)forpowerpc+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby+*theFreeSoftwareFoundation;eitherversion2oftheLicense,or+*(atyouroption)anylaterversion.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram;ifnot,writetotheFreeSoftware+*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.+*+*CopyrightIBMCorporation,2007-2012+*+*Adaptedfromthex86portbyAnanthNMavinakayanahalli<ananth@in.ibm.com>+*/+#include<linux/kernel.h>+#include<linux/sched.h>+#include<linux/ptrace.h>+#include<linux/uprobes.h>+#include<linux/uaccess.h>+#include<linux/kdebug.h>++#include<asm/sstep.h>++#define UPROBE_TRAP_NR UINT_MAX++/**+*arch_uprobe_analyze_insn+*@mm:theprobedaddressspace.+*@arch_uprobe:theprobepointinformation.+*@addr:vaddrtoprobe.+*Return0onsuccessora-venumberonerror.+*/+intarch_uprobe_analyze_insn(structarch_uprobe*auprobe,+structmm_struct*mm,unsignedlongaddr)+{+if(addr&0x03)+return-EINVAL;++/*+*Wecurrentlydon'tsupportauprobeonanalready+*existingbreakpointinstructionunderneath+*/+if(is_trap(auprobe->ainsn))+return-ENOTSUPP;+return0;+}++/*+*arch_uprobe_pre_xol-preparetoexecuteoutofline.+*@auprobe:theprobepointinformation.+*@regs:reflectsthesaveduserstateofcurrenttask.+*/+intarch_uprobe_pre_xol(structarch_uprobe*auprobe,structpt_regs*regs)+{+structarch_uprobe_task*autask=¤t->utask->autask;++autask->saved_trap_nr=current->thread.trap_nr;+current->thread.trap_nr=UPROBE_TRAP_NR;+regs->nip=current->utask->xol_vaddr;+return0;+}++/**+*uprobe_get_swbp_addr-computeaddressofswbpgivenpost-swbpregs+*@regs:Reflectsthesavedstateofthetaskafterithashitabreakpoint+*instruction.+*Returntheaddressofthebreakpointinstruction.+*/+unsignedlonguprobe_get_swbp_addr(structpt_regs*regs)+{+returninstruction_pointer(regs);+}++/*+*Ifxolinsnitselftrapsandgeneratesasignal(SIGILL/SIGSEGV/etc),+*thendetectthecasewhereasinglesteppedinstructionjumpsbacktoits+*ownaddress.Itisassumedthatanythinglikedo_page_fault/do_trap/etc+*setsthread.trap_nr!=UINT_MAX.+*+*arch_uprobe_pre_xol/arch_uprobe_post_xolsave/restorethread.trap_nr,+*arch_uprobe_xol_was_trapped()simplychecksthat->trap_nrisnotequalto+*UPROBE_TRAP_NR==UINT_MAXsetbyarch_uprobe_pre_xol().+*/+boolarch_uprobe_xol_was_trapped(structtask_struct*t)+{+if(t->thread.trap_nr!=UPROBE_TRAP_NR)+returntrue;++returnfalse;+}++/*+*Calledaftersingle-stepping.ToavoidtheSMPproblemsthatcan+*occurwhenwetemporarilyputbacktheoriginalopcodeto+*single-step,wesingle-steppedacopyoftheinstruction.+*+*Thisfunctionpreparestoresumeexecutionafterthesingle-step.+*/+intarch_uprobe_post_xol(structarch_uprobe*auprobe,structpt_regs*regs)+{+structuprobe_task*utask=current->utask;++WARN_ON_ONCE(current->thread.trap_nr!=UPROBE_TRAP_NR);++current->thread.trap_nr=utask->autask.saved_trap_nr;++/*+*Onpowerpc,exceptforloadsandstores,mostinstructions+*includingonesthataltercodeflow(branches,calls,returns)+*areemulatedinthekernel.Wegethereonlyiftheemulation+*supportdoesn'texistandhavetofix-upthenextinstruction+*tobeexecuted.+*/+regs->nip=utask->vaddr+MAX_UINSN_BYTES;+return0;+}++/* callback routine for handling exceptions. */+intarch_uprobe_exception_notify(structnotifier_block*self,+unsignedlongval,void*data)+{+structdie_args*args=data;+structpt_regs*regs=args->regs;++/* regs == NULL is a kernel bug */+if(WARN_ON(!regs))+returnNOTIFY_DONE;++/* We are only interested in userspace traps */+if(!user_mode(regs))+returnNOTIFY_DONE;++switch(val){+caseDIE_BPT:+if(uprobe_pre_sstep_notifier(regs))+returnNOTIFY_STOP;+break;+caseDIE_SSTEP:+if(uprobe_post_sstep_notifier(regs))+returnNOTIFY_STOP;+default:+break;+}+returnNOTIFY_DONE;+}++/*+*ThisfunctiongetscalledwhenXOLinstructioneithergetstrappedor+*thethreadhasafatalsignal,soresettheinstructionpointertoits+*probedaddress.+*/+voidarch_uprobe_abort_xol(structarch_uprobe*auprobe,structpt_regs*regs)+{+structuprobe_task*utask=current->utask;++current->thread.trap_nr=utask->autask.saved_trap_nr;+instruction_pointer_set(regs,utask->vaddr);+}++/*+*Seeiftheinstructioncanbeemulated.+*Returnstrueifinstructionwasemulated,falseotherwise.+*/+boolarch_uprobe_skip_sstep(structarch_uprobe*auprobe,structpt_regs*regs)+{+intret;++/*+*emulate_step()returns1iftheinsnwassuccessfullyemulated.+*Forallothercases,weneedtosingle-stepinhardware.+*/+ret=emulate_step(regs,auprobe->ainsn);+if(ret>0)+returntrue;++returnfalse;+}
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2012-09-05 05:27:35
On Fri, 2012-08-24 at 13:01 +0530, Ananth N Mavinakayanahalli wrote:
From: Ananth N Mavinakayanahalli <redacted>
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.
From: Ananth N Mavinakayanahalli <hidden> Date: 2012-09-05 05:45:12
On Wed, Sep 05, 2012 at 03:26:59PM +1000, Benjamin Herrenschmidt wrote:
On Fri, 2012-08-24 at 13:01 +0530, Ananth N Mavinakayanahalli wrote:
quoted
From: Ananth N Mavinakayanahalli <redacted>
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).
Sorry Ben. That was an oversight. Won't happen again.
Regards,
Ananth