From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30945 invoked by alias); 26 Oct 2009 22:06:24 -0000 Received: (qmail 30676 invoked by uid 22791); 26 Oct 2009 22:06:22 -0000 X-SWARE-Spam-Status: No, hits=-2.5 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 26 Oct 2009 22:06:13 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n9QM6Cve014384 for ; Mon, 26 Oct 2009 18:06:12 -0400 Received: from [10.3.226.95] (vpn-226-95.phx2.redhat.com [10.3.226.95]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id n9QM6BLs003098; Mon, 26 Oct 2009 18:06:11 -0400 Message-ID: <4AE61D52.40805@redhat.com> Date: Mon, 26 Oct 2009 22:06:00 -0000 From: Masami Hiramatsu User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.4pre) Gecko/20091014 Fedora/3.0-2.8.b4.fc11 Thunderbird/3.0b4 MIME-Version: 1.0 To: Mahesh J Salgaonkar CC: systemtap@sources.redhat.com Subject: Re: [PATCH -tip tracing/kprobes] Powerpc port of the kprobe-based event tracer. References: <20091020121505.724222003@mars.in.ibm.com> <20091026111742.GA11639@in.ibm.com> In-Reply-To: <20091026111742.GA11639@in.ibm.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org X-SW-Source: 2009-q4/txt/msg00294.txt.bz2 Hi Mahesh, Mahesh J Salgaonkar wrote: > This patch ports the kprobe-based event tracer to powerpc. This patch > is based on x86 port. > > Port the following API's to ppc for accessing registers and stack entries > from pt_regs. > > - regs_query_register_offset(const char *name) > Query the offset of "name" register. > > - regs_query_register_name(unsigned int offset) > Query the name of register by its offset. > > - regs_get_register(struct pt_regs *regs, unsigned int offset) > Get the value of a register by its offset. > > - regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) > Check the address is in the kernel stack. > > - regs_get_kernel_stack_nth(struct pt_regs *reg, unsigned int nth) > Get Nth entry of the kernel stack. (N>= 0) > > - regs_get_argument_nth(struct pt_regs *reg, unsigned int nth) > Get Nth argument at function call. (N>= 0) > > Signed-off-by: Mahesh Salgaonkar Thank you for porting! > --- > arch/powerpc/include/asm/ptrace.h | 65 +++++++++++++++++ > arch/powerpc/kernel/ptrace.c | 141 ++++++++++++++++++++++++++++++++++++++ > kernel/trace/Kconfig | 2 > 3 files changed, 207 insertions(+), 1 deletion(-) > > Index: linux-2.6-tip/arch/powerpc/include/asm/ptrace.h > =================================================================== > --- linux-2.6-tip.orig/arch/powerpc/include/asm/ptrace.h > +++ linux-2.6-tip/arch/powerpc/include/asm/ptrace.h > @@ -131,6 +131,71 @@ do { \ > } while (0) > #endif /* __powerpc64__ */ > > +/* Query offset/name of register from its name/offset */ > +#include > +#include > +extern int regs_query_register_offset(const char *name); > +extern const char *regs_query_register_name(unsigned int offset); > +#define MAX_REG_OFFSET (offsetof(struct pt_regs, result)) > +#define kernel_stack_pointer(regs) ((regs)->gpr[1]) Hmm, kernel_stack_pointer() would better be defined just after user_stack_pointer(). [...] > Index: linux-2.6-tip/arch/powerpc/kernel/ptrace.c > =================================================================== > --- linux-2.6-tip.orig/arch/powerpc/kernel/ptrace.c > +++ linux-2.6-tip/arch/powerpc/kernel/ptrace.c > @@ -39,6 +39,147 @@ > #include > > /* > + * The parameter save area on the stack is used to store arguments being passed > + * to callee function and is located at fixed offset from stack pointer. > + */ > +#ifdef CONFIG_PPC32 > +#define PARAMETER_SAVE_AREA_OFFSET 24 /* bytes */ > +#else /* CONFIG_PPC32 */ > +#define PARAMETER_SAVE_AREA_OFFSET 48 /* bytes */ > +#endif > + > +struct pt_regs_offset { > + const char *name; > + int offset; > +}; > + > +#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} > +#define REG_OFFSET_END {.name = NULL, .offset = 0} > + > +static const struct pt_regs_offset regoffset_table[] = { > + REG_OFFSET_NAME(gpr[0]), > + REG_OFFSET_NAME(gpr[1]), > + REG_OFFSET_NAME(gpr[2]), > + REG_OFFSET_NAME(gpr[3]), > + REG_OFFSET_NAME(gpr[4]), > + REG_OFFSET_NAME(gpr[5]), > + REG_OFFSET_NAME(gpr[6]), > + REG_OFFSET_NAME(gpr[7]), > + REG_OFFSET_NAME(gpr[8]), > + REG_OFFSET_NAME(gpr[9]), > + REG_OFFSET_NAME(gpr[10]), > + REG_OFFSET_NAME(gpr[11]), > + REG_OFFSET_NAME(gpr[12]), > + REG_OFFSET_NAME(gpr[13]), > + REG_OFFSET_NAME(gpr[14]), > + REG_OFFSET_NAME(gpr[15]), > + REG_OFFSET_NAME(gpr[16]), > + REG_OFFSET_NAME(gpr[17]), > + REG_OFFSET_NAME(gpr[18]), > + REG_OFFSET_NAME(gpr[19]), > + REG_OFFSET_NAME(gpr[20]), > + REG_OFFSET_NAME(gpr[21]), > + REG_OFFSET_NAME(gpr[22]), > + REG_OFFSET_NAME(gpr[23]), > + REG_OFFSET_NAME(gpr[24]), > + REG_OFFSET_NAME(gpr[25]), > + REG_OFFSET_NAME(gpr[26]), > + REG_OFFSET_NAME(gpr[27]), > + REG_OFFSET_NAME(gpr[28]), > + REG_OFFSET_NAME(gpr[29]), > + REG_OFFSET_NAME(gpr[30]), > + REG_OFFSET_NAME(gpr[31]), > + REG_OFFSET_NAME(nip), > + REG_OFFSET_NAME(msr), > + REG_OFFSET_NAME(orig_gpr3), > + REG_OFFSET_NAME(ctr), > + REG_OFFSET_NAME(link), > + REG_OFFSET_NAME(xer), > + REG_OFFSET_NAME(ccr), > +#ifdef CONFIG_PPC64 > + REG_OFFSET_NAME(softe), > +#else > + REG_OFFSET_NAME(mq), > +#endif > + REG_OFFSET_NAME(trap), > + REG_OFFSET_NAME(dar), > + REG_OFFSET_NAME(dsisr), > + REG_OFFSET_NAME(result), > + REG_OFFSET_END, > +}; > + > +/** > + * regs_query_register_offset() - query register offset from its name > + * @name: the name of a register > + * > + * regs_query_register_offset() returns the offset of a register in struct > + * pt_regs from its name. If the name is invalid, this returns -EINVAL; > + */ > +int regs_query_register_offset(const char *name) > +{ > + const struct pt_regs_offset *roff; > + for (roff = regoffset_table; roff->name != NULL; roff++) > + if (!strcmp(roff->name, name)) > + return roff->offset; > + return -EINVAL; > +} > + > +/** > + * regs_query_register_name() - query register name from its offset > + * @offset: the offset of a register in struct pt_regs. > + * > + * regs_query_register_name() returns the name of a register from its > + * offset in struct pt_regs. If the @offset is invalid, this returns NULL; > + */ > +const char *regs_query_register_name(unsigned int offset) > +{ > + const struct pt_regs_offset *roff; > + for (roff = regoffset_table; roff->name != NULL; roff++) > + if (roff->offset == offset) > + return roff->name; > + return NULL; > +} > + > +static const int arg_offs_table[] = { > + [0] = offsetof(struct pt_regs, gpr[3]), > + [1] = offsetof(struct pt_regs, gpr[4]), > + [2] = offsetof(struct pt_regs, gpr[5]), > + [3] = offsetof(struct pt_regs, gpr[6]), > + [4] = offsetof(struct pt_regs, gpr[7]), > + [5] = offsetof(struct pt_regs, gpr[8]), > + [6] = offsetof(struct pt_regs, gpr[9]), > + [7] = offsetof(struct pt_regs, gpr[10]) > +}; > + > +/** > + * regs_get_argument_nth() - get Nth argument at function call > + * @regs: pt_regs which contains registers at function entry. > + * @n: argument number. > + * > + * regs_get_argument_nth() returns @n th argument of a function call. > + * Since usually the kernel stack will be changed right after function entry, > + * you must use this at function entry. If the @n th entry is NOT in the > + * kernel stack or pt_regs, this returns 0. > + */ > +unsigned long regs_get_argument_nth(struct pt_regs *regs, unsigned int n) > +{ > + if (n< ARRAY_SIZE(arg_offs_table)) ^ here, we needs a space. > + return *(unsigned long *)((char *)regs + arg_offs_table[n]); > + else { > + /* > + * If more arguments are passed that can be stored in > + * registers, the remaining arguments are stored in the > + * parameter save area located at fixed offset from stack > + * pointer. > + * Following the PowerPC ABI, the first few arguments are > + * actually passed in registers (r3-r10), with equivalent space > + * left unused in the parameter save area. > + */ > + n += (PARAMETER_SAVE_AREA_OFFSET / sizeof(unsigned long)); > + return regs_get_kernel_stack_nth(regs, n); > + } > +} > +/* > * does not yet catch signals sent when the child dies. > * in exit.c or in signal.c. > */ > others seems good! Thank you! -- Masami Hiramatsu Software Engineer Hitachi Computer Products (America), Inc. Software Solutions Division e-mail: mhiramat@redhat.com