dtrace script matching lot of probes simply resets on i386

Mark Johnston markj at freebsd.org
Wed Nov 6 15:36:34 UTC 2019


On Tue, Nov 05, 2019 at 11:23:28AM +0000, Bjoern A. Zeeb wrote:
> Hi,
> 
> I had an i386 kernel (amd64 machine) simply going to POST.  After a lot 
> of “doh” I realised that it was a dtrace script which was matching a 
> lot of probes running as part of some automated stuff.
> 
> The problematic part from the middle of that script was a section which 
> I can reduce to
> 
> fbt:kernel::entry		# or simply :::
> /self->foo == 1/
> {
> 
>     printf(“Hello\n”);
> }
> 
> Anyone wants to investigate this or should I open a PR?

Can you test this patch?  I only tried to compile it.  Basically, we
must handle FBT probes before calling trap().

diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s
index b288543dafe1..8a8de5fb1d09 100644
--- a/sys/i386/i386/exception.s
+++ b/sys/i386/i386/exception.s
@@ -175,7 +175,7 @@ alltraps_with_regs_pushed:
 	FAKE_MCOUNT(TF_EIP(%esp))
 calltrap:
 	pushl	%esp
-	movl	$trap,%eax
+	movl	$trap_check,%eax
 	call	*%eax
 	add	$4, %esp
 
@@ -317,7 +317,7 @@ dbg_user:
 	movl	$handle_ibrs_entry,%eax
 	call	*%eax
 	pushl	%esp
-	movl	$trap,%eax
+	movl	$trap_check,%eax
 	call	*%eax
 	add	$4, %esp
 	movl	$T_RESERVED, TF_TRAPNO(%esp)
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index bb71317de000..83ac97887feb 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -112,6 +112,7 @@ PMC_SOFT_DEFINE( , , page_fault, write);
 #endif
 
 void trap(struct trapframe *frame);
+void trap_check(struct trapframe *frame);
 void syscall(struct trapframe *frame);
 
 static int trap_pfault(struct trapframe *, bool, vm_offset_t, int *, int *);
@@ -186,6 +187,21 @@ SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RW,
     &uprintf_signal, 0,
     "Print debugging information on trap signal to ctty");
 
+/*
+ * Ensure that we ignore any DTrace-induced faults. This function cannot
+ * be instrumented, so it cannot generate such faults itself.
+ */
+void
+trap_check(struct trapframe *frame)
+{
+#ifdef KDTRACE_HOOKS
+	if (dtrace_trap_func != NULL &&
+	    (*dtrace_trap_func)(frame, frame->tf_trapno))
+		return;
+#endif
+	trap(frame);
+}
+
 /*
  * Exception, fault, and trap interface to the FreeBSD kernel.
  * This common code is called from assembly language IDT gate entry
@@ -260,19 +276,6 @@ trap(struct trapframe *frame)
 		return;
 	}
 
-#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 its per-cpu flags to indicate that it doesn't
-	 * want to fault. On returning from the probe, the no-fault
-	 * flag is cleared and finally re-scheduling is enabled.
-	 */
-	if ((type == T_PROTFLT || type == T_PAGEFLT) &&
-	    dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
-		return;
-#endif
-
 	/*
 	 * We must not allow context switches until %cr2 is read.
 	 * Also, for some Cyrix CPUs, %cr2 is clobbered by interrupts.


More information about the freebsd-dtrace mailing list