PERFORCE change 131281 for review
John Birrell
jb at FreeBSD.org
Wed Dec 19 19:09:18 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=131281
Change 131281 by jb at 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);
More information about the p4-projects
mailing list