PERFORCE change 137864 for review
John Birrell
jb at FreeBSD.org
Sun Mar 16 21:13:27 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=137864
Change 137864 by jb at jb_freebsd8 on 2008/03/16 21:12:39
Add a reset mechanism to the double trap handler to cater for
those occasions when fbt enables a probe on something that ends
up being called unexpectedly from the probe context. We need to
reset the probe points so that the double trap is handled
properly and we end up back in ddb.
In fbt itself, do not instrument functions with names starting
with two underscores. There are one or two of these that can
cause a double fault when instrumented with fbt, so the simple
solution is to avoid doing that.
rwatson: this is the "bewm" problem you saw. :-)
Affected files ...
.. //depot/projects/dtrace/src/sys/cddl/dev/fbt/fbt.c#9 edit
.. //depot/projects/dtrace/src/sys/i386/i386/trap.c#28 edit
.. //depot/projects/dtrace/src/sys/sys/dtrace_bsd.h#14 edit
Differences ...
==== //depot/projects/dtrace/src/sys/cddl/dev/fbt/fbt.c#9 (text+ko) ====
@@ -59,6 +59,7 @@
#include <machine/stdarg.h>
#include <sys/dtrace.h>
+#include <sys/dtrace_bsd.h>
MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing");
@@ -147,6 +148,20 @@
static int fbt_probetab_mask;
static int fbt_verbose = 0;
+static void
+fbt_doubletrap(void)
+{
+ fbt_probe_t *fbt;
+ int i;
+
+ for (i = 0; i < fbt_probetab_size; i++) {
+ fbt = fbt_probetab[i];
+
+ for (; fbt != NULL; fbt = fbt->fbtp_next)
+ *fbt->fbtp_patchpoint = fbt->fbtp_savedval;
+ }
+}
+
static int
fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
{
@@ -228,6 +243,9 @@
return (0);
}
+ if (name[0] == '_' && name[1] == '_')
+ return (0);
+
size = symval->size;
instr = (u_int8_t *) symval->value;
@@ -1321,6 +1339,7 @@
fbt_probetab =
malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO);
+ dtrace_doubletrap_func = fbt_doubletrap;
dtrace_invop_add(fbt_invop);
if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER,
@@ -1337,6 +1356,8 @@
/* De-register the invalid opcode handler. */
dtrace_invop_remove(fbt_invop);
+ dtrace_doubletrap_func = NULL;
+
/* De-register this DTrace provider. */
if ((error = dtrace_unregister(fbt_id)) != 0)
return (error);
==== //depot/projects/dtrace/src/sys/i386/i386/trap.c#28 (text+ko) ====
@@ -113,6 +113,8 @@
*/
dtrace_trap_func_t dtrace_trap_func;
+dtrace_doubletrap_func_t dtrace_doubletrap_func;
+
/*
* This is a hook which is initialised by the systrace module
* when it is loaded. This keeps the DTrace syscall provider
@@ -952,6 +954,10 @@
void
dblfault_handler()
{
+#ifdef KDTRACE_HOOKS
+ if (dtrace_doubletrap_func != NULL)
+ (*dtrace_doubletrap_func)();
+#endif
printf("\nFatal double fault:\n");
printf("eip = 0x%x\n", PCPU_GET(common_tss.tss_eip));
printf("esp = 0x%x\n", PCPU_GET(common_tss.tss_esp));
==== //depot/projects/dtrace/src/sys/sys/dtrace_bsd.h#14 (text+ko) ====
@@ -62,9 +62,11 @@
/* Used by the machine dependent trap() code. */
typedef int (*dtrace_invop_func_t)(uintptr_t, uintptr_t *, uintptr_t);
+typedef void (*dtrace_doubletrap_func_t)(void);
-/* Global variable in trap.c */
+/* Global variables in trap.c */
extern dtrace_invop_func_t dtrace_invop_func;
+extern dtrace_doubletrap_func_t dtrace_doubletrap_func;
/* Virtual time hook function type. */
typedef void (*dtrace_vtime_switch_func_t)(struct thread *);
More information about the p4-projects
mailing list