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