* Re: [PATCH] save parameter registers and restore them for jprobe handling
2005-12-01 2:28 [PATCH] save parameter registers and restore them for jprobe handling Zhang, Yanmin
@ 2005-12-01 2:37 ` Keith Owens
2005-12-01 5:19 ` Zhang, Yanmin
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Keith Owens @ 2005-12-01 2:37 UTC (permalink / raw)
To: linux-ia64
On Thu, 1 Dec 2005 10:28:09 +0800,
"Zhang, Yanmin" <yanmin.zhang@intel.com> wrote:
>Content-Transfer-Encoding: base64
Why base64 encoding for the patch?
+/*Invalidate stacked registers outside the current frame*/
+#define invalidate_stacked_regs() { \
+ unsigned long rsc_save = 0; \
+ asm volatile("mov %0=ar.rsc;;\n\t" \
+ "mov ar.rsc=0;;\n\t" \
+ "{\n\tloadrs;;\n\t\n\t\n\t}\n\t" \
+ "mov ar.rsc=%1\n\t" \
+ :"=r" (rsc_save):"r" (rsc_save):"memory"); \
+ }
+
We try to avoid inline asm in the .c files, it makes it harder to
compile the kernel with Intel compilers.
^ permalink raw reply [flat|nested] 6+ messages in thread* RE: [PATCH] save parameter registers and restore them for jprobe handling
2005-12-01 2:28 [PATCH] save parameter registers and restore them for jprobe handling Zhang, Yanmin
2005-12-01 2:37 ` Keith Owens
@ 2005-12-01 5:19 ` Zhang, Yanmin
2005-12-01 19:25 ` Chen, Kenneth W
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Zhang, Yanmin @ 2005-12-01 5:19 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 1104 bytes --]
>>-----Original Message-----
>>From: linux-ia64-owner@vger.kernel.org
>>[mailto:linux-ia64-owner@vger.kernel.org] On Behalf Of Keith Owens
>>Sent: 2005年12月1日 10:37
>>To: Zhang, Yanmin
>>Cc: linux-ia64@vger.kernel.org; Keshavamurthy, Anil S;
>>systemtap@sources.redhat.com
>>Subject: Re: [PATCH] save parameter registers and restore them for jprobe
>>handling
>>
>>On Thu, 1 Dec 2005 10:28:09 +0800,
>>"Zhang, Yanmin" <yanmin.zhang@intel.com> wrote:
>>>Content-Transfer-Encoding: base64
>>
>>Why base64 encoding for the patch?
>>
>>+/*Invalidate stacked registers outside the current frame*/
>>+#define invalidate_stacked_regs() { \
>>+ unsigned long rsc_save = 0; \
>>+ asm volatile("mov %0=ar.rsc;;\n\t" \
>>+ "mov ar.rsc=0;;\n\t" \
>>+ "{\n\tloadrs;;\n\t\n\t\n\t}\n\t" \
>>+ "mov ar.rsc=%1\n\t" \
>>+ :"=r" (rsc_save):"r" (rsc_save):"memory"); \
>>+ }
>>+
>>
>>We try to avoid inline asm in the .c files, it makes it harder to
>>compile the kernel with Intel compilers.
How about the new patch? I add a new function in arch/ia64/kernel/entry.S.
[-- Attachment #2: jprobe_protect_out_reg_ia64_v3.patch --]
[-- Type: application/octet-stream, Size: 3964 bytes --]
diff -Nraup linux-2.6.14_mm1/arch/ia64/kernel/entry.S linux-2.6.14_mm1_jprobe/arch/ia64/kernel/entry.S
--- linux-2.6.14_mm1/arch/ia64/kernel/entry.S 2005-11-09 19:08:51.000000000 +0800
+++ linux-2.6.14_mm1_jprobe/arch/ia64/kernel/entry.S 2005-11-30 20:50:47.000000000 +0800
@@ -1340,6 +1340,25 @@ GLOBAL_ENTRY(unw_init_running)
br.ret.sptk.many rp
END(unw_init_running)
+GLOBAL_ENTRY(invalidate_stacked_regs)
+ movl r16=invalidate_restore_cfm
+ ;;
+ mov b6=r16
+ ;;
+ br.ret.sptk.many b6
+ ;;
+invalidate_restore_cfm:
+ mov r16=ar.rsc
+ ;;
+ mov ar.rsc=r0
+ ;;
+ loadrs
+ ;;
+ mov ar.rsc=r16
+ ;;
+ br.cond.sptk.many rp
+END(invalidate_stacked_regs)
+
.rodata
.align 8
.globl sys_call_table
diff -Nraup linux-2.6.14_mm1/arch/ia64/kernel/kprobes.c linux-2.6.14_mm1_jprobe/arch/ia64/kernel/kprobes.c
--- linux-2.6.14_mm1/arch/ia64/kernel/kprobes.c 2005-11-09 19:08:51.000000000 +0800
+++ linux-2.6.14_mm1_jprobe/arch/ia64/kernel/kprobes.c 2005-11-30 17:58:03.000000000 +0800
@@ -759,13 +759,49 @@ int __kprobes kprobe_exceptions_notify(s
return ret;
}
+struct param_bsp_cfm {
+ unsigned long ip;
+ unsigned long *bsp;
+ unsigned long cfm;
+};
+
+static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg)
+{
+ unsigned long ip;
+ struct param_bsp_cfm *lp = arg;
+
+ do {
+ unw_get_ip(info, &ip);
+ if (ip == 0)
+ break;
+ if (ip == lp->ip) {
+ unw_get_bsp(info, (unsigned long*)&lp->bsp);
+ unw_get_cfm(info, (unsigned long*)&lp->cfm);
+ return;
+ }
+ } while (unw_unwind(info) >= 0);
+ lp->bsp = 0;
+ lp->cfm = 0;
+ return;
+}
+
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ struct param_bsp_cfm pa;
+ int bytes;
/* save architectural state */
+ pa.ip = regs->cr_iip;
+ unw_init_running(ia64_get_bsp_cfm, &pa);
+ bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f)
+ - (char *)pa.bsp;
+ memcpy( kcb->jprobes_saved_stacked_regs,
+ pa.bsp,
+ bytes );
+
kcb->jprobe_saved_regs = *regs;
/* after rfi, execute the jprobe instrumented function */
@@ -785,8 +821,19 @@ int __kprobes setjmp_pre_handler(struct
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ struct param_bsp_cfm pa;
+ int bytes;
*regs = kcb->jprobe_saved_regs;
+ pa.ip = regs->cr_iip;
+ unw_init_running(ia64_get_bsp_cfm, &pa);
+ bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f)
+ - (char *)pa.bsp;
+ memcpy( pa.bsp,
+ kcb->jprobes_saved_stacked_regs,
+ bytes );
+ invalidate_stacked_regs();
+
preempt_enable_no_resched();
return 1;
}
diff -Nraup linux-2.6.14_mm1/include/asm-ia64/kprobes.h linux-2.6.14_mm1_jprobe/include/asm-ia64/kprobes.h
--- linux-2.6.14_mm1/include/asm-ia64/kprobes.h 2005-11-09 19:08:43.000000000 +0800
+++ linux-2.6.14_mm1_jprobe/include/asm-ia64/kprobes.h 2005-11-30 20:27:33.000000000 +0800
@@ -68,10 +68,12 @@ struct prev_kprobe {
unsigned long status;
};
+#define MAX_PARAM_RSE_SIZE (0x80+0x80/0x3f)
/* per-cpu kprobe control block */
struct kprobe_ctlblk {
unsigned long kprobe_status;
struct pt_regs jprobe_saved_regs;
+ unsigned long jprobes_saved_stacked_regs[MAX_PARAM_RSE_SIZE];
struct prev_kprobe prev_kprobe;
};
diff -Nraup linux-2.6.14_mm1/include/asm-ia64/ptrace.h linux-2.6.14_mm1_jprobe/include/asm-ia64/ptrace.h
--- linux-2.6.14_mm1/include/asm-ia64/ptrace.h 2005-11-09 19:08:43.000000000 +0800
+++ linux-2.6.14_mm1_jprobe/include/asm-ia64/ptrace.h 2005-11-30 20:32:49.000000000 +0800
@@ -297,6 +297,8 @@ struct switch_stack {
extern void ia64_increment_ip (struct pt_regs *pt);
extern void ia64_decrement_ip (struct pt_regs *pt);
+ extern void invalidate_stacked_regs(void);
+
#endif /* !__KERNEL__ */
/* pt_all_user_regs is used for PTRACE_GETREGS PTRACE_SETREGS */
^ permalink raw reply [flat|nested] 6+ messages in thread* RE: [PATCH] save parameter registers and restore them for jprobe handling
2005-12-01 2:28 [PATCH] save parameter registers and restore them for jprobe handling Zhang, Yanmin
2005-12-01 2:37 ` Keith Owens
2005-12-01 5:19 ` Zhang, Yanmin
@ 2005-12-01 19:25 ` Chen, Kenneth W
2005-12-01 20:06 ` Keshavamurthy Anil S
2005-12-02 2:29 ` Zhang, Yanmin
4 siblings, 0 replies; 6+ messages in thread
From: Chen, Kenneth W @ 2005-12-01 19:25 UTC (permalink / raw)
To: linux-ia64
Zhang, Yanmin wrote on Wednesday, November 30, 2005 9:19 PM
> >>We try to avoid inline asm in the .c files, it makes it harder to
> >>compile the kernel with Intel compilers.
>
> How about the new patch? I add a new function in arch/ia64/kernel/entry.S.
I think it's more appropriate to place the new assembly function in
arch/ia64/kernel/jprobes.S.
- Ken
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] save parameter registers and restore them for jprobe handling
2005-12-01 2:28 [PATCH] save parameter registers and restore them for jprobe handling Zhang, Yanmin
` (2 preceding siblings ...)
2005-12-01 19:25 ` Chen, Kenneth W
@ 2005-12-01 20:06 ` Keshavamurthy Anil S
2005-12-02 2:29 ` Zhang, Yanmin
4 siblings, 0 replies; 6+ messages in thread
From: Keshavamurthy Anil S @ 2005-12-01 20:06 UTC (permalink / raw)
To: linux-ia64
On Wed, Nov 30, 2005 at 09:19:02PM -0800, Zhang, Yanmin wrote:
> How about the new patch? I add a new function in arch/ia64/kernel/entry.S.
>
I agree with Ken, move the assembly function to arch/ia64/kernel/jprobe.S file.
Also, please see my comments.
> int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
> {
[...]
> /* save architectural state */
Wrong comment above, we are not saving architectural state.
I guess the comment should be
"Callee owns the argument space and could overwrite it, eg
tail call optimization. So to be absolutely safe
we save the argument space before transfering the control
to instrumented jprobe function which runs in
the process context"
> @@ -785,8 +821,19 @@ int __kprobes setjmp_pre_handler(struct
> int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
> {
[....]
> + unw_init_running(ia64_get_bsp_cfm, &pa);
Just an optimization, avoid calling unw_init_running()
and just save bsp and cfm in the previous call and
reuse it. I think you can save in the kcb
structure.
> + bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f)
> + - (char *)pa.bsp;
Again Comment please.. like
/* restoring the original argument space */
> + memcpy( pa.bsp,
> + kcb->jprobes_saved_stacked_regs,
> + bytes );
-Anil Keshavamurthy
^ permalink raw reply [flat|nested] 6+ messages in thread* RE: [PATCH] save parameter registers and restore them for jprobe handling
2005-12-01 2:28 [PATCH] save parameter registers and restore them for jprobe handling Zhang, Yanmin
` (3 preceding siblings ...)
2005-12-01 20:06 ` Keshavamurthy Anil S
@ 2005-12-02 2:29 ` Zhang, Yanmin
4 siblings, 0 replies; 6+ messages in thread
From: Zhang, Yanmin @ 2005-12-02 2:29 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 538 bytes --]
>>-----Original Message-----
>>From: Keshavamurthy Anil S [mailto:anil.s.keshavamurthy@intel.com]
>>Sent: 2005年12月2日 4:07
>>To: Zhang, Yanmin
>>Cc: Keith Owens; linux-ia64@vger.kernel.org; Keshavamurthy, Anil S;
>>systemtap@sources.redhat.com
>>Subject: Re: [PATCH] save parameter registers and restore them for jprobe
>>handling
Thanks. I updated the patch.
1) Move the assembly function to arch/ia64/kernel/jprobe.S;
2) Add/change comments;
3) Optimize. To do so, I add a new assembly function to flush register stack.
[-- Attachment #2: jprobe_protect_out_reg_ia64_v3.patch --]
[-- Type: application/octet-stream, Size: 4171 bytes --]
diff -Nraup linux-2.6.14_mm1/arch/ia64/kernel/jprobes.S linux-2.6.14_mm1_jprobe/arch/ia64/kernel/jprobes.S
--- linux-2.6.14_mm1/arch/ia64/kernel/jprobes.S 2005-11-09 19:08:51.000000000 +0800
+++ linux-2.6.14_mm1_jprobe/arch/ia64/kernel/jprobes.S 2005-12-01 17:59:04.000000000 +0800
@@ -60,3 +60,30 @@ END(jprobe_break)
GLOBAL_ENTRY(jprobe_inst_return)
br.call.sptk.many b0=jprobe_break
END(jprobe_inst_return)
+
+GLOBAL_ENTRY(invalidate_stacked_regs)
+ movl r16=invalidate_restore_cfm
+ ;;
+ mov b6=r16
+ ;;
+ br.ret.sptk.many b6
+ ;;
+invalidate_restore_cfm:
+ mov r16=ar.rsc
+ ;;
+ mov ar.rsc=r0
+ ;;
+ loadrs
+ ;;
+ mov ar.rsc=r16
+ ;;
+ br.cond.sptk.many rp
+END(invalidate_stacked_regs)
+
+GLOBAL_ENTRY(flush_register_stack)
+ // flush dirty regs to backing store (must be first in insn group)
+ flushrs
+ ;;
+ br.ret.sptk.many rp
+END(flush_register_stack)
+
diff -Nraup linux-2.6.14_mm1/arch/ia64/kernel/kprobes.c linux-2.6.14_mm1_jprobe/arch/ia64/kernel/kprobes.c
--- linux-2.6.14_mm1/arch/ia64/kernel/kprobes.c 2005-11-09 19:08:51.000000000 +0800
+++ linux-2.6.14_mm1_jprobe/arch/ia64/kernel/kprobes.c 2005-12-01 18:00:03.000000000 +0800
@@ -759,11 +759,56 @@ int __kprobes kprobe_exceptions_notify(s
return ret;
}
+struct param_bsp_cfm {
+ unsigned long ip;
+ unsigned long *bsp;
+ unsigned long cfm;
+};
+
+static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg)
+{
+ unsigned long ip;
+ struct param_bsp_cfm *lp = arg;
+
+ do {
+ unw_get_ip(info, &ip);
+ if (ip == 0)
+ break;
+ if (ip == lp->ip) {
+ unw_get_bsp(info, (unsigned long*)&lp->bsp);
+ unw_get_cfm(info, (unsigned long*)&lp->cfm);
+ return;
+ }
+ } while (unw_unwind(info) >= 0);
+ lp->bsp = 0;
+ lp->cfm = 0;
+ return;
+}
+
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ struct param_bsp_cfm pa;
+ int bytes;
+
+ /*
+ * Callee owns the argument space and could overwrite it, eg
+ * tail call optimization. So to be absolutely safe
+ * we save the argument space before transfering the control
+ * to instrumented jprobe function which runs in
+ * the process context
+ */
+ pa.ip = regs->cr_iip;
+ unw_init_running(ia64_get_bsp_cfm, &pa);
+ bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f)
+ - (char *)pa.bsp;
+ memcpy( kcb->jprobes_saved_stacked_regs,
+ pa.bsp,
+ bytes );
+ kcb->bsp = pa.bsp;
+ kcb->cfm = pa.cfm;
/* save architectural state */
kcb->jprobe_saved_regs = *regs;
@@ -785,8 +830,20 @@ int __kprobes setjmp_pre_handler(struct
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ int bytes;
+ /* restoring architectural state */
*regs = kcb->jprobe_saved_regs;
+
+ /* restoring the original argument space */
+ flush_register_stack();
+ bytes = (char *)ia64_rse_skip_regs(kcb->bsp, kcb->cfm & 0x3f)
+ - (char *)kcb->bsp;
+ memcpy( kcb->bsp,
+ kcb->jprobes_saved_stacked_regs,
+ bytes );
+ invalidate_stacked_regs();
+
preempt_enable_no_resched();
return 1;
}
diff -Nraup linux-2.6.14_mm1/include/asm-ia64/kprobes.h linux-2.6.14_mm1_jprobe/include/asm-ia64/kprobes.h
--- linux-2.6.14_mm1/include/asm-ia64/kprobes.h 2005-11-09 19:08:43.000000000 +0800
+++ linux-2.6.14_mm1_jprobe/include/asm-ia64/kprobes.h 2005-12-01 18:13:28.000000000 +0800
@@ -68,10 +68,14 @@ struct prev_kprobe {
unsigned long status;
};
+#define MAX_PARAM_RSE_SIZE (0x60+0x60/0x3f)
/* per-cpu kprobe control block */
struct kprobe_ctlblk {
unsigned long kprobe_status;
struct pt_regs jprobe_saved_regs;
+ unsigned long jprobes_saved_stacked_regs[MAX_PARAM_RSE_SIZE];
+ unsigned long *bsp;
+ unsigned long cfm;
struct prev_kprobe prev_kprobe;
};
@@ -124,6 +128,8 @@ static inline void jprobe_return(void)
{
}
+extern void invalidate_stacked_regs(void);
+extern void flush_register_stack(void);
#else /* !CONFIG_KPROBES */
static inline int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data)
^ permalink raw reply [flat|nested] 6+ messages in thread