Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Nov 2006 00:44:18 GMT
From:      John Birrell <jb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 109251 for review
Message-ID:  <200611050044.kA50iI9w092463@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=109251

Change 109251 by jb@jb_freebsd8 on 2006/11/05 00:43:18

	Merge the DTrace stuff back in.

Affected files ...

.. //depot/projects/dtrace/src/sys/i386/i386/trap.c#15 edit

Differences ...

==== //depot/projects/dtrace/src/sys/i386/i386/trap.c#15 (text+ko) ====

@@ -102,6 +102,35 @@
 #include <machine/clock.h>
 #endif
 
+#ifdef KDTRACE
+#include <sys/cpuvar.h>
+#include <machine/dtrace.h>
+
+/*
+ * These are hooks which are  initialised by the dtrace module
+ * when it is loaded. This keeps the DTrace implementation
+ * opaque.
+ *
+ * All that the trap() function below needs to determine
+ * is how many instruction bytes to offset the instruction
+ * pointer before returning from a trap that occured durin a
+ * 'no-fault' DTrace probe.
+ */
+dtrace_instr_size_func_t	dtrace_instr_size_func;
+
+/*
+ * This hook handles invalid opcodes.
+ */
+dtrace_invop_func_t	dtrace_invop_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);
 
@@ -216,6 +245,69 @@
 	    goto out;
 #endif
 
+#ifdef	KDTRACE
+	/*
+	 * If DTrace support is compiled into the kernel, a trap can
+	 * occur while DTrace executes a probe. Before executing the
+	 * probe, DTrace disables interrupts 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 interrupts are re-enabled.
+	 *
+	 * Check if DTrace has enabled 'no-fault' mode:
+	 *
+	 */
+	if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
+		/*
+		 * When the dtrace module was loaded (or initialised
+		 * if linked into the kernel), it should have set it's
+		 * machine dependent instruction size function pointer
+		 * for use here. If not, the trap will just end up
+		 * being processed as a panic like any other.
+		 */
+		if (dtrace_instr_size_func != NULL) {
+			/*
+			 * There are only a couple of trap types that
+			 * are expected. All the rest will be handled
+			 * in the usual way.
+			 */
+			switch (type) {
+			/* General protection fault. */
+			case T_PROTFLT:
+				/* Flag an illegal operation. */
+				cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_ILLOP;
+
+				/*
+				 * Offset the instruction pointer
+				 * to the instruction following the
+				 * one casing the fault.
+				 */
+				frame.tf_eip += (*dtrace_instr_size_func)((u_char *) frame.tf_eip);
+				goto out;
+			/* Page fault. */
+			case T_PAGEFLT:
+				/* Flag a bad address. */
+				cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR;
+				cpu_core[curcpu].cpuc_dtrace_illval = rcr2();
+
+				/*
+				 * Offset the instruction pointer
+				 * to the instruction following the
+				 * one casing the fault.
+				 */
+				frame.tf_eip += (*dtrace_instr_size_func)((u_char *) frame.tf_eip);
+				goto out;
+			default:
+				/*
+				 * Handle all other traps in the usual
+				 * way.
+				 */
+				break;
+			}
+		}
+	}
+#endif
+
 	if ((frame.tf_eflags & PSL_I) == 0) {
 		/*
 		 * Buggy application or kernel code has disabled
@@ -1006,9 +1098,34 @@
 
 		PTRACESTOP_SC(p, td, S_PT_SCE);
 
+#ifdef KDTRACE
+		/*
+		 * 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
+		/* Save the error return variable for DTrace to reference. */
+		td->td_errno = 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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611050044.kA50iI9w092463>