Date: Thu, 20 Dec 2007 03:09:16 GMT From: John Birrell <jb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 131281 for review Message-ID: <200712200309.lBK39GHB022812@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=131281 Change 131281 by jb@jb_freebsd1 on 2007/12/20 03:08:21 Add the hook for the 'systrace' (syscall) provider and the entry and return calls using it. The implementation is opaque. The sysent support for this was added to current prior to the RELENG_7 branch. Add a hook for the DTrace 'safety' implementation. This is an opaque implementation of the previous one I did which assumed that certain OpenSolaris headers would be relicensed. Now that I know that won't happen, the code that relies on them *must* be loaded as part of the dtrace kernel module. In OpenSolaris there is a 'cpu_core' array that is has fields that DTrace uses to flag the fact that it is executing a probe. If a trap occurs with that flag set, then it assumes that the trap was caused by it (by referencing an address that isn't mapped, for example) and it sets an error flag in the same array and just returns from the trap, expecting that the RISC engine executing the DIF (DTrace intermediate format) will detect the error and just abort the probe processing. The new DTrace port will still rely on the cpu_core array, but it will be private to the DTrace module, thereby keeping the CDDL licensed code together. Affected files ... .. //depot/projects/dtrace/src/sys/amd64/amd64/trap.c#19 edit .. //depot/projects/dtrace/src/sys/i386/i386/trap.c#24 edit .. //depot/projects/dtrace/src/sys/sys/dtrace_bsd.h#4 edit Differences ... ==== //depot/projects/dtrace/src/sys/amd64/amd64/trap.c#19 (text+ko) ==== @@ -49,6 +49,7 @@ #include "opt_hwpmc_hooks.h" #include "opt_isa.h" #include "opt_kdb.h" +#include "opt_kdtrace.h" #include "opt_ktrace.h" #include <sys/param.h> @@ -94,6 +95,24 @@ #endif #include <machine/tss.h> +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> + +/* + * This is a hook which is initialised by the dtrace module + * to handle traps which might occur during DTrace probe + * execution. + */ +dtrace_trap_func_t dtrace_trap_func; + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + extern void trap(struct trapframe *frame); extern void syscall(struct trapframe *frame); void dblfault_handler(struct trapframe *frame); @@ -199,6 +218,24 @@ goto out; #endif +#ifdef KDTRACE_HOOKS + /* + * A trap can occur while DTrace executes a probe. Before + * executing the probe, DTrace blocks re-scheduling and sets + * a flag in it's per-cpu flags to indicate that it doesn't + * want to fault. On returning from the the probe, the no-fault + * flag is cleared and finally re-scheduling is enabled. + * + * If the DTrace kernel module has registered a trap handler, + * call it and if it returns non-zero, assume that it has + * handled the trap and modified the trap frame so that this + * function can return normally. + */ + if (dtrace_trap_func != NULL) + if ((*dtrace_trap_func)(frame)) + goto out; +#endif + if ((frame->tf_rflags & PSL_I) == 0) { /* * Buggy application or kernel code has disabled @@ -847,9 +884,35 @@ PTRACESTOP_SC(p, td, S_PT_SCE); +#ifdef KDTRACE_HOOKS + /* + * If the systrace module has registered it's probe + * callback and if there is a probe active for the + * syscall 'entry', process the probe. + */ + if (systrace_probe_func != NULL && callp->sy_entry != 0) + (*systrace_probe_func)(callp->sy_entry, code, callp, + args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, argp); AUDIT_SYSCALL_EXIT(error, td); + +#ifdef KDTRACE_HOOKS + /* Save the error return variable for DTrace to reference. */ + args[0] = error; + args[1] = error; + + /* + * If the systrace module has registered it's probe + * callback and if there is a probe active for the + * syscall 'return', process the probe. + */ + if (systrace_probe_func != NULL && callp->sy_return != 0) + (*systrace_probe_func)(callp->sy_return, code, callp, + args); +#endif } switch (error) { ==== //depot/projects/dtrace/src/sys/i386/i386/trap.c#24 (text+ko) ==== @@ -49,6 +49,7 @@ #include "opt_hwpmc_hooks.h" #include "opt_isa.h" #include "opt_kdb.h" +#include "opt_kdtrace.h" #include "opt_ktrace.h" #include "opt_npx.h" #include "opt_trap.h" @@ -102,6 +103,24 @@ #include <machine/clock.h> #endif +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> + +/* + * This is a hook which is initialised by the dtrace module + * to handle traps which might occur during DTrace probe + * execution. + */ +dtrace_trap_func_t dtrace_trap_func; + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + extern void trap(struct trapframe *frame); extern void syscall(struct trapframe *frame); @@ -218,6 +237,24 @@ goto out; #endif +#ifdef KDTRACE_HOOKS + /* + * A trap can occur while DTrace executes a probe. Before + * executing the probe, DTrace blocks re-scheduling and sets + * a flag in it's per-cpu flags to indicate that it doesn't + * want to fault. On returning from the the probe, the no-fault + * flag is cleared and finally re-scheduling is enabled. + * + * If the DTrace kernel module has registered a trap handler, + * call it and if it returns non-zero, assume that it has + * handled the trap and modified the trap frame so that this + * function can return normally. + */ + if (dtrace_trap_func != NULL) + if ((*dtrace_trap_func)(frame)) + goto out; +#endif + if ((frame->tf_eflags & PSL_I) == 0) { /* * Buggy application or kernel code has disabled @@ -1030,9 +1067,35 @@ PTRACESTOP_SC(p, td, S_PT_SCE); +#ifdef KDTRACE_HOOKS + /* + * If the systrace module has registered it's probe + * callback and if there is a probe active for the + * syscall 'entry', process the probe. + */ + if (systrace_probe_func != NULL && callp->sy_entry != 0) + (*systrace_probe_func)(callp->sy_entry, code, callp, + args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, args); AUDIT_SYSCALL_EXIT(error, td); + +#ifdef KDTRACE_HOOKS + /* Save the error return variable for DTrace to reference. */ + args[0] = error; + args[1] = error; + + /* + * If the systrace module has registered it's probe + * callback and if there is a probe active for the + * syscall 'return', process the probe. + */ + if (systrace_probe_func != NULL && callp->sy_return != 0) + (*systrace_probe_func)(callp->sy_return, code, callp, + args); +#endif } switch (error) { ==== //depot/projects/dtrace/src/sys/sys/dtrace_bsd.h#4 (text+ko) ==== @@ -37,6 +37,13 @@ */ typedef void (*cyclic_clock_func_t)(void); +/* + * The dtrace module handles traps that occur during a DTrace probe. + * This type definition is used in the trap handler to provide a + * hook for the dtrace module to register it's handler with. + */ +typedef int (*dtrace_trap_func_t)(struct trapframe *); + /* Used by the machine dependent trap() code. */ typedef int (*dtrace_invop_func_t)(uintptr_t, uintptr_t *, uintptr_t);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712200309.lBK39GHB022812>