On Mon, Jul 14, 2014 at 04:38:17AM +0000, Mark Johnston wrote:
> Author: markj
> Date: Mon Jul 14 04:38:17 2014
> New Revision: 268600
> URL: http://svnweb.freebsd.org/changeset/base/268600
> 
> Log:
>   Invoke the DTrace trap handler before calling trap() on amd64. This matches
>   the upstream implementation and helps ensure that a trap induced by tracing
>   fbt::trap:entry is handled without recursively generating another trap.
>   
>   This makes it possible to run most (but not all) of the DTrace tests under
>   common/safety/ without triggering a kernel panic.
>   
>   Submitted by:       Anton Rang <[email protected]> (original version)
>   Phabric:    D95
> 
> Modified:
>   head/sys/amd64/amd64/exception.S
>   head/sys/amd64/amd64/trap.c
>   head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
>   head/sys/cddl/dev/dtrace/i386/dtrace_subr.c
>   head/sys/cddl/dev/dtrace/mips/dtrace_subr.c
>   head/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
>   head/sys/i386/i386/trap.c
>   head/sys/mips/mips/trap.c
>   head/sys/powerpc/aim/trap.c
>   head/sys/sys/dtrace_bsd.h
> 
> Modified: head/sys/amd64/amd64/exception.S
> ==============================================================================
> --- head/sys/amd64/amd64/exception.S  Mon Jul 14 00:16:49 2014        
> (r268599)
> +++ head/sys/amd64/amd64/exception.S  Mon Jul 14 04:38:17 2014        
> (r268600)
> @@ -228,7 +228,24 @@ alltraps_pushregs_no_rdi:
>       .type   calltrap,@function
>  calltrap:
>       movq    %rsp,%rdi
> +#ifdef KDTRACE_HOOKS
> +     /*
> +      * Give DTrace a chance to vet this trap and skip the call to trap() if
> +      * it turns out that it was caused by a DTrace probe.
> +      */
> +     movq    dtrace_trap_func,%rax
> +     testq   %rax,%rax
> +     je      skiphook
> +     call    *%rax
> +     testq   %rax,%rax
> +     jne     skiptrap
> +     movq    %rsp,%rdi
> +skiphook:
> +#endif
>       call    trap
Why is this fragment done in asm ?  I see it relatively easy to
either move to the start of trap(), or create a new wrapper around
current trap() which calls dtrace_trap_func conditionally, and then
resorts to the old trap.

> +#ifdef KDTRACE_HOOKS
> +skiptrap:
> +#endif
>       MEXITCOUNT
>       jmp     doreti                  /* Handle any pending ASTs */
>  
> 
> Modified: head/sys/amd64/amd64/trap.c
> ==============================================================================
> --- head/sys/amd64/amd64/trap.c       Mon Jul 14 00:16:49 2014        
> (r268599)
> +++ head/sys/amd64/amd64/trap.c       Mon Jul 14 04:38:17 2014        
> (r268600)
> @@ -218,18 +218,6 @@ trap(struct trapframe *frame)
>               goto out;
>       }
>  
> -#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 (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
> -             goto out;
> -#endif
> -
>       if ((frame->tf_rflags & PSL_I) == 0) {
>               /*
>                * Buggy application or kernel code has disabled
> 
> Modified: head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
> ==============================================================================
> --- head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c      Mon Jul 14 00:16:49 
> 2014        (r268599)
> +++ head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c      Mon Jul 14 04:38:17 
> 2014        (r268600)
> @@ -462,29 +462,27 @@ dtrace_gethrestime(void)
>       return (current_time.tv_sec * 1000000000ULL + current_time.tv_nsec);
>  }
>  
> -/* Function to handle DTrace traps during probes. See amd64/amd64/trap.c */
> +/*
> + * Function to handle DTrace traps during probes. See 
> amd64/amd64/exception.S.
> + */
>  int
> -dtrace_trap(struct trapframe *frame, u_int type)
> +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
> +      * 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.
>        *
>        * 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) {
> -             /* Privilieged instruction fault. */
> -             case T_PRIVINFLT:
> -                     break;
> +             switch (frame->tf_trapno) {
>               /* General protection fault. */
>               case T_PROTFLT:
>                       /* Flag an illegal operation. */
> 
> Modified: head/sys/cddl/dev/dtrace/i386/dtrace_subr.c
> ==============================================================================
> --- head/sys/cddl/dev/dtrace/i386/dtrace_subr.c       Mon Jul 14 00:16:49 
> 2014        (r268599)
> +++ head/sys/cddl/dev/dtrace/i386/dtrace_subr.c       Mon Jul 14 04:38:17 
> 2014        (r268600)
> @@ -473,24 +473,23 @@ dtrace_gethrestime(void)
>  
>  /* Function to handle DTrace traps during probes. See i386/i386/trap.c */
>  int
> -dtrace_trap(struct trapframe *frame, u_int type)
> +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
> +      * 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.
>        *
>        * 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) {
> +             switch (frame->tf_trapno) {
>               /* General protection fault. */
>               case T_PROTFLT:
>                       /* Flag an illegal operation. */
> 
> Modified: head/sys/cddl/dev/dtrace/mips/dtrace_subr.c
> ==============================================================================
> --- head/sys/cddl/dev/dtrace/mips/dtrace_subr.c       Mon Jul 14 00:16:49 
> 2014        (r268599)
> +++ head/sys/cddl/dev/dtrace/mips/dtrace_subr.c       Mon Jul 14 04:38:17 
> 2014        (r268600)
> @@ -137,17 +137,20 @@ dtrace_gethrestime(void)
>  
>  /* Function to handle DTrace traps during probes. See amd64/amd64/trap.c */
>  int
> -dtrace_trap(struct trapframe *frame, u_int type)
> +dtrace_trap(struct trapframe *frame)
>  {
> +     u_int type;
> +
> +     type = (trapframe->cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
> +
>       /*
>        * 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
> +      * 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.
>        *
>        * Check if DTrace has enabled 'no-fault' mode:
> -      *
>        */
>       if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
>               /*
> 
> Modified: head/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
> ==============================================================================
> --- head/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c    Mon Jul 14 00:16:49 
> 2014        (r268599)
> +++ head/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c    Mon Jul 14 04:38:17 
> 2014        (r268600)
> @@ -262,24 +262,23 @@ dtrace_gethrestime(void)
>  
>  /* Function to handle DTrace traps during probes. See powerpc/powerpc/trap.c 
> */
>  int
> -dtrace_trap(struct trapframe *frame, u_int type)
> +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
> +      * 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.
>        *
>        * 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) {
> +             switch (frame->exc) {
>               /* Page fault. */
>               case EXC_DSI:
>               case EXC_DSE:
> 
> Modified: head/sys/i386/i386/trap.c
> ==============================================================================
> --- head/sys/i386/i386/trap.c Mon Jul 14 00:16:49 2014        (r268599)
> +++ head/sys/i386/i386/trap.c Mon Jul 14 04:38:17 2014        (r268600)
> @@ -246,7 +246,7 @@ trap(struct trapframe *frame)
>        * 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))
> +         dtrace_trap_func != NULL && (*dtrace_trap_func)(frame))
>               goto out;
>  #endif
>  
> 
> Modified: head/sys/mips/mips/trap.c
> ==============================================================================
> --- head/sys/mips/mips/trap.c Mon Jul 14 00:16:49 2014        (r268599)
> +++ head/sys/mips/mips/trap.c Mon Jul 14 04:38:17 2014        (r268600)
> @@ -605,7 +605,7 @@ trap(struct trapframe *trapframe)
>       /*
>        * 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
> +      * 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.
>        *
> @@ -618,7 +618,7 @@ trap(struct trapframe *trapframe)
>        * XXXDTRACE: add pid probe handler here (if ever)
>        */
>       if (!usermode) {
> -             if (dtrace_trap_func != NULL && (*dtrace_trap_func)(trapframe, 
> type))
> +             if (dtrace_trap_func != NULL && (*dtrace_trap_func)(trapframe))
>                       return (trapframe->pc);
>       }
>  #endif
> 
> Modified: head/sys/powerpc/aim/trap.c
> ==============================================================================
> --- head/sys/powerpc/aim/trap.c       Mon Jul 14 00:16:49 2014        
> (r268599)
> +++ head/sys/powerpc/aim/trap.c       Mon Jul 14 04:38:17 2014        
> (r268600)
> @@ -167,7 +167,7 @@ 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
> +      * 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.
>        *
> @@ -176,7 +176,7 @@ trap(struct trapframe *frame)
>        * handled the trap and modified the trap frame so that this
>        * function can return normally.
>        */
> -     if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
> +     if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame))
>               return;
>  #endif
>  
> 
> Modified: head/sys/sys/dtrace_bsd.h
> ==============================================================================
> --- head/sys/sys/dtrace_bsd.h Mon Jul 14 00:16:49 2014        (r268599)
> +++ head/sys/sys/dtrace_bsd.h Mon Jul 14 04:38:17 2014        (r268600)
> @@ -48,15 +48,14 @@ extern cyclic_clock_func_t        cyclic_clock_
>  
>  void clocksource_cyc_set(const struct bintime *t);
>  
> +int dtrace_trap(struct trapframe *);
> +
>  /*
>   * 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.
> + * hook for the dtrace module to register its handler with.
>   */
> -typedef int (*dtrace_trap_func_t)(struct trapframe *, u_int);
> -
> -int  dtrace_trap(struct trapframe *, u_int);
> -
> +typedef int (*dtrace_trap_func_t)(struct trapframe *);
>  extern dtrace_trap_func_t    dtrace_trap_func;
>  
>  /*

Attachment: pgpjQE2LijsrD.pgp
Description: PGP signature

Reply via email to