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>