This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

arm64 kprobes/systemtap support progress


Hi All,

Dave Long has been working on getting arm64 kprobes support merged into the upstream kernels.  The kprobes64 branch of the git tree at 
https://git.linaro.org/people/dave.long/linux.git

I have been using systemtap to exercise the arm64 kprobes support and flush out any problems with them.  The attached kernel patch fixes a couple problems observed in the arm64 kprobes:

- irq needs to be masked during single step
- the address to continue execution should be statically computed and not change

With the attached patch and recent correction to the systemtap runtime time.c for arm64. periodic.stp run on arm64:

# ~/systemtap_write/install/bin/stap --all-modules  periodic.stp 
#monitoring timer periods (press control-c for output)
^C#type   function                                            period(us)     count
kernel  0xfffffdfffcaf2c50 [stap_41b9ddd4f103a617201d73e05       10008      1230
kernel  0xfffffdfffcaf3280 [stap_41b9ddd4f103a617201d73e05       20032       614
process xfsaild/dm-0(404)                                        50000       246
process rcu_sched(7)                                            159873        77
work_q  phy_state_machine                                      1000011        11
work_q  vmstat_update                                          1000009        11
work_q  vmstat_update                                          1000919        11
work_q  vmstat_update                                          1000010        11
work_q  vmstat_update                                          1000018        11
work_q  vmstat_update                                          1352511         8
work_q  vmstat_update                                          1512865         7
kernel  br_hello_timer_expired+0x0/0x90 [bridge]               1999999         5
kernel  dev_watchdog+0x0/0x280 [kernel]                        4999999         2
kernel  0xfffffdfffcaf1b40 [stap_41b9ddd4f103a617201d73e05    10021293         1
kernel  0xfffffdfffcaf1b40 [stap_41b9ddd4f103a617201d73e05    10021056         1
work_q  bdi_writeback_workfn                                   5010523         1
kernel  0xfffffdfffcaf1b40 [stap_41b9ddd4f103a617201d73e05    10021037         1
work_q  xfs_reclaim_worker                                     5010503         1
kernel  0xfffffdfffcaf1b40 [stap_41b9ddd4f103a617201d73e05    10011035         1
work_q  vmstat_update                                          5941334         1
kernel  0xfffffdfffcaf1b40 [stap_41b9ddd4f103a617201d73e05    10022237         1
work_q  vmstat_update                                          5992305         1
kernel  0xfffffdfffcaf1b40 [stap_41b9ddd4f103a617201d73e05    10023836         1
kernel  writeout_period+0x0/0x9c [kernel]                      5992292         1
kernel  0xfffffdfffcaf1b40 [stap_41b9ddd4f103a617201d73e05    10021077         1
kernel  0xfffffdfffcaf1b40 [stap_41b9ddd4f103a617201d73e05    10021999         1

-Will
diff -up arch/arm64/kernel/kprobes.c.irq arch/arm64/kernel/kprobes.c
--- arch/arm64/kernel/kprobes.c.irq	2014-10-29 22:01:35.234174228 -0400
+++ arch/arm64/kernel/kprobes.c	2014-10-30 16:10:16.165804247 -0400
@@ -23,6 +23,7 @@
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
 #include <asm/traps.h>
+#include <asm/ptrace.h>
 #include <asm/cacheflush.h>
 #include <asm/debug-monitors.h>
 #include <asm/system_misc.h>
@@ -47,12 +48,23 @@ static void __kprobes arch_prepare_ss_sl
 
 	flush_icache_range((uintptr_t) (p->ainsn.insn),
 			   (uintptr_t) (p->ainsn.insn) + MAX_INSN_SIZE);
+
+	/*
+	 * Needs restoring of return address after stepping xol.
+	 */
+	p->ainsn.restore.addr = (unsigned long) p->addr +
+	  sizeof(kprobe_opcode_t);
+	p->ainsn.restore.type = RESTORE_PC;
 }
 
 static void __kprobes arch_prepare_simulate(struct kprobe *p)
 {
 	if (p->ainsn.prepare)
 		p->ainsn.prepare(p, &p->ainsn);
+
+	/* This instructions is not executed xol. No need to adjust the PC */
+	p->ainsn.restore.addr = 0;
+	p->ainsn.restore.type = NO_RESTORE;
 }
 
 static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs)
@@ -167,9 +179,9 @@ spsr_set_debug_flag(struct pt_regs *regs
 	unsigned long spsr = regs->pstate;
 
 	if (mask)
-		spsr |= (1 << 9);
+		spsr |= PSR_D_BIT;
 	else
-		spsr &= ~(1 << 9);
+		spsr &= ~PSR_D_BIT;
 
 	regs->pstate = spsr;
 }
@@ -186,7 +198,7 @@ static void __kprobes kprobes_save_local
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-	kcb->saved_irqflag = (interrupts_enabled(regs)) ? 0 : 1;
+	kcb->saved_irqflag = regs->pstate;
 	regs->pstate |= PSR_I_BIT;
 }
 
@@ -194,10 +206,10 @@ static void __kprobes kprobes_restore_lo
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-	if (kcb->saved_irqflag)
-		regs->pstate &= ~PSR_I_BIT;
-	else
+	if (kcb->saved_irqflag & PSR_I_BIT)
 		regs->pstate |= PSR_I_BIT;
+	else
+		regs->pstate &= ~PSR_I_BIT;
 }
 
 static void __kprobes
@@ -243,19 +255,13 @@ static void __kprobes setup_singlestep(s
 		/* prepare for single stepping */
 		slot = (unsigned long)p->ainsn.insn;
 
-		/*
-		 * Needs restoring of return address after stepping xol.
-		 */
-		p->ainsn.restore.addr = instruction_pointer(regs) +
-				sizeof(kprobe_opcode_t);
-
-		p->ainsn.restore.type = RESTORE_PC;
-
 		set_ss_context(kcb, slot);	/* mark pending ss */
 
 		if (kcb->kprobe_status == KPROBE_REENTER)
 			spsr_set_debug_flag(regs, 0);
 
+		/* IRQs and single stepping do not mix well. */
+		local_irq_disable();
 		kernel_enable_single_step(regs);
 		instruction_pointer(regs) = slot;
 	} else	{
@@ -304,8 +310,7 @@ post_kprobe_handler(struct kprobe_ctlblk
 	/* return addr restore if non-branching insn */
 	if (cur->ainsn.restore.type == RESTORE_PC) {
 		instruction_pointer(regs) = cur->ainsn.restore.addr;
-		cur->ainsn.restore.addr = 0;
-		cur->ainsn.restore.type = NO_RESTORE;
+		if (!instruction_pointer(regs)) BUG();
 	}
 
 	/* restore back original saved kprobe variables and continue */
@@ -343,6 +348,7 @@ int __kprobes kprobe_fault_handler(struc
 		 * normal page fault.
 		 */
 		instruction_pointer(regs) = (unsigned long)cur->addr;
+		if (!instruction_pointer(regs)) BUG();
 		if (kcb->kprobe_status == KPROBE_REENTER)
 			restore_previous_kprobe(kcb);
 		else

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]