Date: Sun, 16 Mar 2008 21:13:26 GMT From: John Birrell <jb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 137864 for review Message-ID: <200803162113.m2GLDQTQ063263@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=137864 Change 137864 by jb@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 *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200803162113.m2GLDQTQ063263>