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)