Module Name:    src
Committed By:   ozaki-r
Date:           Sat Mar 15 05:58:30 UTC 2014

Modified Files:
        src/sys/arch/arm/arm: undefined.c

Log Message:
Add a trap handler for DTrace FBT provider


To generate a diff of this commit:
cvs rdiff -u -r1.52 -r1.53 src/sys/arch/arm/arm/undefined.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/arm/undefined.c
diff -u src/sys/arch/arm/arm/undefined.c:1.52 src/sys/arch/arm/arm/undefined.c:1.53
--- src/sys/arch/arm/arm/undefined.c:1.52	Wed Mar  5 02:18:30 2014
+++ src/sys/arch/arm/arm/undefined.c	Sat Mar 15 05:58:30 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: undefined.c,v 1.52 2014/03/05 02:18:30 matt Exp $	*/
+/*	$NetBSD: undefined.c,v 1.53 2014/03/15 05:58:30 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 2001 Ben Harris.
@@ -48,13 +48,14 @@
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
+#include "opt_dtrace.h"
 
 #include <sys/param.h>
 #ifdef KGDB
 #include <sys/kgdb.h>
 #endif
 
-__KERNEL_RCSID(0, "$NetBSD: undefined.c,v 1.52 2014/03/05 02:18:30 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: undefined.c,v 1.53 2014/03/15 05:58:30 ozaki-r Exp $");
 
 #include <sys/kmem.h>
 #include <sys/queue.h>
@@ -220,6 +221,45 @@ static struct undefined_handler gdb_uh;
 static struct undefined_handler gdb_uh_thumb;
 #endif
 
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+
+/* Not used for now, but needed for dtrace/fbt modules */
+dtrace_doubletrap_func_t	dtrace_doubletrap_func = NULL;
+dtrace_trap_func_t		dtrace_trap_func = NULL;
+
+int (* dtrace_invop_jump_addr)(uintptr_t, uintptr_t *, uintptr_t);
+void (* dtrace_emulation_jump_addr)(int, struct trapframe *);
+
+static int
+dtrace_trapper(u_int addr, struct trapframe *frame)
+{
+	int op;
+	struct trapframe back;
+	u_int insn = read_insn(addr, false);
+
+	if (dtrace_invop_jump_addr == NULL || dtrace_emulation_jump_addr == NULL)
+		return 1;
+
+	if (!DTRACE_IS_BREAKPOINT(insn))
+		return 1;
+
+	/* cond value is encoded in the first byte */
+	if (!arm_cond_ok_p(__SHIFTIN(insn, INSN_COND_MASK), frame->tf_spsr)) {
+		frame->tf_pc += INSN_SIZE;
+		return 0;
+	}
+
+	back = *frame;
+	op = dtrace_invop_jump_addr(addr, (uintptr_t *) frame->tf_svc_sp, frame->tf_r0);
+	*frame = back;
+
+	dtrace_emulation_jump_addr(op, frame);
+
+	return 0;
+}
+#endif
+
 void
 undefined_init(void)
 {
@@ -262,6 +302,15 @@ undefinedinstruction(trapframe_t *tf)
 
 	und_ev.ev_count++;
 
+#ifdef KDTRACE_HOOKS
+	if ((tf->tf_spsr & PSR_MODE) != PSR_USR32_MODE) {
+		tf->tf_pc -= INSN_SIZE;
+		if (dtrace_trapper(tf->tf_pc, tf) == 0)
+			return;
+		tf->tf_pc += INSN_SIZE; /* Reset for the rest code */
+	}
+#endif
+
 	/* Enable interrupts if they were enabled before the exception. */
 #ifdef acorn26
 	if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0)

Reply via email to