Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Jan 2008 09:04:40 GMT
From:      John Birrell <jb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 132237 for review
Message-ID:  <200801010904.m0194eoY086461@repoman.freebsd.org>

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

Change 132237 by jb@jb_freebsd1 on 2008/01/01 09:03:56

	Remove the M_DTRACE memory type references.
	
	Add the dtrace_trap() function which is hooked into the trap handler
	to deal with traps that occur during DTrace probe execution.

Affected files ...

.. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/amd64/dtrace_subr.c#2 edit
.. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/i386/dtrace_subr.c#5 edit

Differences ...

==== //depot/projects/dtrace/src/sys/cddl/dev/dtrace/amd64/dtrace_subr.c#2 (text+ko) ====

@@ -35,14 +35,14 @@
 #include <sys/kmem.h>
 #include <sys/dtrace_impl.h>
 #include <sys/dtrace_bsd.h>
+#include <machine/frame.h>
 
 extern uintptr_t 	kernelbase;
 extern uintptr_t 	dtrace_in_probe_addr;
 extern int		dtrace_in_probe;
 
 int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
-
-MALLOC_DECLARE(M_DTRACE);
+int dtrace_trap(struct trapframe *, u_int);
 
 typedef struct dtrace_invop_hdlr {
 	int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
@@ -96,7 +96,7 @@
 {
 	dtrace_invop_hdlr_t *hdlr;
 
-	hdlr = malloc(sizeof (dtrace_invop_hdlr_t), M_DTRACE, M_WAITOK);
+	hdlr = kmem_alloc(sizeof (dtrace_invop_hdlr_t), KM_SLEEP);
 	hdlr->dtih_func = func;
 	hdlr->dtih_next = dtrace_invop_hdlr;
 	dtrace_invop_hdlr = hdlr;
@@ -130,7 +130,7 @@
 		prev->dtih_next = hdlr->dtih_next;
 	}
 
-	free(hdlr, M_DTRACE);
+	kmem_free(hdlr, 0);
 
 #ifdef DOODAD
 	if (dtrace_invop_hdlr == NULL)
@@ -438,3 +438,56 @@
 	printf("%s(%d): XXX\n",__func__,__LINE__);
 	return (0);
 }
+
+/* Function to handle DTrace traps during probes. See amd64/amd64/trap.c */
+int
+dtrace_trap(struct trapframe *frame, u_int type)
+{
+	/*
+	 * 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.
+	 *
+	 * Check if DTrace has enabled 'no-fault' mode:
+	 *
+	 */
+	if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
+		/*
+		 * 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 causing the fault.
+			 */
+			frame->tf_rip += dtrace_instr_size((u_char *) frame->tf_rip);
+			return (1);
+		/* Page fault. */
+		case T_PAGEFLT:
+			/* Flag a bad address. */
+			cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR;
+			cpu_core[curcpu].cpuc_dtrace_illval = frame->tf_addr;
+
+			/*
+			 * Offset the instruction pointer to the instruction
+			 * following the one causing the fault.
+			 */
+			frame->tf_rip += dtrace_instr_size((u_char *) frame->tf_rip);
+			return (1);
+		default:
+			/* Handle all other traps in the usual way. */
+			break;
+		}
+	}
+
+	/* Handle the trap in the usual way. */
+	return (0);
+}

==== //depot/projects/dtrace/src/sys/cddl/dev/dtrace/i386/dtrace_subr.c#5 (text+ko) ====

@@ -42,8 +42,6 @@
 
 int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
 
-MALLOC_DECLARE(M_DTRACE);
-
 typedef struct dtrace_invop_hdlr {
 	int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
 	struct dtrace_invop_hdlr *dtih_next;
@@ -96,7 +94,7 @@
 {
 	dtrace_invop_hdlr_t *hdlr;
 
-	hdlr = malloc(sizeof (dtrace_invop_hdlr_t), M_DTRACE, M_WAITOK);
+	hdlr = kmem_alloc(sizeof (dtrace_invop_hdlr_t), KM_SLEEP);
 	hdlr->dtih_func = func;
 	hdlr->dtih_next = dtrace_invop_hdlr;
 	dtrace_invop_hdlr = hdlr;
@@ -128,7 +126,7 @@
 		prev->dtih_next = hdlr->dtih_next;
 	}
 
-	free(hdlr, M_DTRACE);
+	kmem_free(hdlr, 0);
 
 	if (dtrace_invop_hdlr == NULL)
 		dtrace_invop_func = NULL;
@@ -427,3 +425,56 @@
 	return (1);
 }
 #endif
+
+/* Function to handle DTrace traps during probes. See i386/i386/trap.c */
+int
+dtrace_trap(struct trapframe *frame)
+{
+	/*
+	 * 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.
+	 *
+	 * Check if DTrace has enabled 'no-fault' mode:
+	 *
+	 */
+	if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
+		/*
+		 * 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 causing the fault.
+			 */
+			frame->tf_eip += dtrace_instr_size((u_char *) frame->tf_eip);
+			return (1);
+		/* 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 causing the fault.
+			 */
+			frame->tf_eip += dtrace_instr_size((u_char *) frame->tf_eip);
+			return (1);
+		default:
+			/* Handle all other traps in the usual way. */
+			break;
+		}
+	}
+
+	/* Handle the trap in the usual way. */
+	return (0);
+}



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