Print this page
4469 DTrace helper tracing should be dynamic

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/dtrace/dtrace.c
          +++ new/usr/src/uts/common/dtrace/dtrace.c
↓ open down ↓ 261 lines elided ↑ open up ↑
 262  262          NULL,
 263  263          (void (*)(void *, dtrace_id_t, void *))dtrace_nullop
 264  264  };
 265  265  
 266  266  static dtrace_id_t      dtrace_probeid_begin;   /* special BEGIN probe */
 267  267  static dtrace_id_t      dtrace_probeid_end;     /* special END probe */
 268  268  dtrace_id_t             dtrace_probeid_error;   /* special ERROR probe */
 269  269  
 270  270  /*
 271  271   * DTrace Helper Tracing Variables
 272      - */
 273      -uint32_t dtrace_helptrace_next = 0;
 274      -uint32_t dtrace_helptrace_nlocals;
 275      -char    *dtrace_helptrace_buffer;
 276      -int     dtrace_helptrace_bufsize = 512 * 1024;
 277      -
 278      -#ifdef DEBUG
 279      -int     dtrace_helptrace_enabled = 1;
 280      -#else
 281      -int     dtrace_helptrace_enabled = 0;
 282      -#endif
      272 + *
      273 + * These variables should be set dynamically to enable helper tracing.  The
      274 + * only variables that should be set are dtrace_helptrace_enable (which should
      275 + * be set to a non-zero value to allocate helper tracing buffers on the next
      276 + * open of /dev/dtrace) and dtrace_helptrace_disable (which should be set to a
      277 + * non-zero value to deallocate helper tracing buffers on the next close of
      278 + * /dev/dtrace).  When (and only when) helper tracing is disabled, the
      279 + * buffer size may also be set via dtrace_helptrace_bufsize.
      280 + */
      281 +int                     dtrace_helptrace_enable = 0;
      282 +int                     dtrace_helptrace_disable = 0;
      283 +int                     dtrace_helptrace_bufsize = 16 * 1024 * 1024;
      284 +uint32_t                dtrace_helptrace_nlocals;
      285 +static dtrace_helptrace_t *dtrace_helptrace_buffer;
      286 +static uint32_t         dtrace_helptrace_next = 0;
      287 +static int              dtrace_helptrace_wrapped = 0;
 283  288  
 284  289  /*
 285  290   * DTrace Error Hashing
 286  291   *
 287  292   * On DEBUG kernels, DTrace will track the errors that has seen in a hash
 288  293   * table.  This is very useful for checking coverage of tests that are
 289  294   * expected to induce DIF or DOF processing errors, and may be useful for
 290  295   * debugging problems in the DIF code generator or in DOF generation .  The
 291  296   * error hash may be examined with the ::dtrace_errhash MDB dcmd.
 292  297   */
↓ open down ↓ 14021 lines elided ↑ open up ↑
14314 14319  }
14315 14320  
14316 14321  /*
14317 14322   * DTrace Helper Functions
14318 14323   */
14319 14324  static void
14320 14325  dtrace_helper_trace(dtrace_helper_action_t *helper,
14321 14326      dtrace_mstate_t *mstate, dtrace_vstate_t *vstate, int where)
14322 14327  {
14323 14328          uint32_t size, next, nnext, i;
14324      -        dtrace_helptrace_t *ent;
     14329 +        dtrace_helptrace_t *ent, *buffer;
14325 14330          uint16_t flags = cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
14326 14331  
14327      -        if (!dtrace_helptrace_enabled)
     14332 +        if ((buffer = dtrace_helptrace_buffer) == NULL)
14328 14333                  return;
14329 14334  
14330 14335          ASSERT(vstate->dtvs_nlocals <= dtrace_helptrace_nlocals);
14331 14336  
14332 14337          /*
14333 14338           * What would a tracing framework be without its own tracing
14334 14339           * framework?  (Well, a hell of a lot simpler, for starters...)
14335 14340           */
14336 14341          size = sizeof (dtrace_helptrace_t) + dtrace_helptrace_nlocals *
14337 14342              sizeof (uint64_t) - sizeof (uint64_t);
↓ open down ↓ 7 lines elided ↑ open up ↑
14345 14350                  if (next + size < dtrace_helptrace_bufsize) {
14346 14351                          nnext = next + size;
14347 14352                  } else {
14348 14353                          nnext = size;
14349 14354                  }
14350 14355          } while (dtrace_cas32(&dtrace_helptrace_next, next, nnext) != next);
14351 14356  
14352 14357          /*
14353 14358           * We have our slot; fill it in.
14354 14359           */
14355      -        if (nnext == size)
     14360 +        if (nnext == size) {
     14361 +                dtrace_helptrace_wrapped++;
14356 14362                  next = 0;
     14363 +        }
14357 14364  
14358      -        ent = (dtrace_helptrace_t *)&dtrace_helptrace_buffer[next];
     14365 +        ent = (dtrace_helptrace_t *)((uintptr_t)buffer + next);
14359 14366          ent->dtht_helper = helper;
14360 14367          ent->dtht_where = where;
14361 14368          ent->dtht_nlocals = vstate->dtvs_nlocals;
14362 14369  
14363 14370          ent->dtht_fltoffs = (mstate->dtms_present & DTRACE_MSTATE_FLTOFFS) ?
14364 14371              mstate->dtms_fltoffs : -1;
14365 14372          ent->dtht_fault = DTRACE_FLAGS2FLT(flags);
14366 14373          ent->dtht_illval = cpu_core[CPU->cpu_id].cpuc_dtrace_illval;
14367 14374  
14368 14375          for (i = 0; i < vstate->dtvs_nlocals; i++) {
↓ open down ↓ 13 lines elided ↑ open up ↑
14382 14389      dtrace_state_t *state, uint64_t arg0, uint64_t arg1)
14383 14390  {
14384 14391          uint16_t *flags = &cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
14385 14392          uint64_t sarg0 = mstate->dtms_arg[0];
14386 14393          uint64_t sarg1 = mstate->dtms_arg[1];
14387 14394          uint64_t rval;
14388 14395          dtrace_helpers_t *helpers = curproc->p_dtrace_helpers;
14389 14396          dtrace_helper_action_t *helper;
14390 14397          dtrace_vstate_t *vstate;
14391 14398          dtrace_difo_t *pred;
14392      -        int i, trace = dtrace_helptrace_enabled;
     14399 +        int i, trace = dtrace_helptrace_buffer != NULL;
14393 14400  
14394 14401          ASSERT(which >= 0 && which < DTRACE_NHELPER_ACTIONS);
14395 14402  
14396 14403          if (helpers == NULL)
14397 14404                  return (0);
14398 14405  
14399 14406          if ((helper = helpers->dthps_actions[which]) == NULL)
14400 14407                  return (0);
14401 14408  
14402 14409          vstate = &helpers->dthps_vstate;
↓ open down ↓ 1296 lines elided ↑ open up ↑
15699 15706              dtrace_provider, NULL, NULL, "BEGIN", 0, NULL);
15700 15707          dtrace_probeid_end = dtrace_probe_create((dtrace_provider_id_t)
15701 15708              dtrace_provider, NULL, NULL, "END", 0, NULL);
15702 15709          dtrace_probeid_error = dtrace_probe_create((dtrace_provider_id_t)
15703 15710              dtrace_provider, NULL, NULL, "ERROR", 1, NULL);
15704 15711  
15705 15712          dtrace_anon_property();
15706 15713          mutex_exit(&cpu_lock);
15707 15714  
15708 15715          /*
15709      -         * If DTrace helper tracing is enabled, we need to allocate the
15710      -         * trace buffer and initialize the values.
15711      -         */
15712      -        if (dtrace_helptrace_enabled) {
15713      -                ASSERT(dtrace_helptrace_buffer == NULL);
15714      -                dtrace_helptrace_buffer =
15715      -                    kmem_zalloc(dtrace_helptrace_bufsize, KM_SLEEP);
15716      -                dtrace_helptrace_next = 0;
15717      -        }
15718      -
15719      -        /*
15720 15716           * If there are already providers, we must ask them to provide their
15721 15717           * probes, and then match any anonymous enabling against them.  Note
15722 15718           * that there should be no other retained enablings at this time:
15723 15719           * the only retained enablings at this time should be the anonymous
15724 15720           * enabling.
15725 15721           */
15726 15722          if (dtrace_anon.dta_enabling != NULL) {
15727 15723                  ASSERT(dtrace_retained == dtrace_anon.dta_enabling);
15728 15724  
15729 15725                  dtrace_enabling_provide(NULL);
↓ open down ↓ 75 lines elided ↑ open up ↑
15805 15801           * If the kernel debugger is active (that is, if the kernel debugger
15806 15802           * modified text in some way), we won't allow the open.
15807 15803           */
15808 15804          if (kdi_dtrace_set(KDI_DTSET_DTRACE_ACTIVATE) != 0) {
15809 15805                  dtrace_opens--;
15810 15806                  mutex_exit(&cpu_lock);
15811 15807                  mutex_exit(&dtrace_lock);
15812 15808                  return (EBUSY);
15813 15809          }
15814 15810  
     15811 +        if (dtrace_helptrace_enable && dtrace_helptrace_buffer == NULL) {
     15812 +                /*
     15813 +                 * If DTrace helper tracing is enabled, we need to allocate the
     15814 +                 * trace buffer and initialize the values.
     15815 +                 */
     15816 +                dtrace_helptrace_buffer =
     15817 +                    kmem_zalloc(dtrace_helptrace_bufsize, KM_SLEEP);
     15818 +                dtrace_helptrace_next = 0;
     15819 +                dtrace_helptrace_wrapped = 0;
     15820 +                dtrace_helptrace_enable = 0;
     15821 +        }
     15822 +
15815 15823          state = dtrace_state_create(devp, cred_p);
15816 15824          mutex_exit(&cpu_lock);
15817 15825  
15818 15826          if (state == NULL) {
15819 15827                  if (--dtrace_opens == 0 && dtrace_anon.dta_enabling == NULL)
15820 15828                          (void) kdi_dtrace_set(KDI_DTSET_DTRACE_DEACTIVATE);
15821 15829                  mutex_exit(&dtrace_lock);
15822 15830                  return (EAGAIN);
15823 15831          }
15824 15832  
↓ open down ↓ 1 lines elided ↑ open up ↑
15826 15834  
15827 15835          return (0);
15828 15836  }
15829 15837  
15830 15838  /*ARGSUSED*/
15831 15839  static int
15832 15840  dtrace_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
15833 15841  {
15834 15842          minor_t minor = getminor(dev);
15835 15843          dtrace_state_t *state;
     15844 +        dtrace_helptrace_t *buf = NULL;
15836 15845  
15837 15846          if (minor == DTRACEMNRN_HELPER)
15838 15847                  return (0);
15839 15848  
15840 15849          state = ddi_get_soft_state(dtrace_softstate, minor);
15841 15850  
15842 15851          mutex_enter(&cpu_lock);
15843 15852          mutex_enter(&dtrace_lock);
15844 15853  
15845 15854          if (state->dts_anon) {
15846 15855                  /*
15847 15856                   * There is anonymous state. Destroy that first.
15848 15857                   */
15849 15858                  ASSERT(dtrace_anon.dta_state == NULL);
15850 15859                  dtrace_state_destroy(state->dts_anon);
15851 15860          }
15852 15861  
     15862 +        if (dtrace_helptrace_disable) {
     15863 +                /*
     15864 +                 * If we have been told to disable helper tracing, set the
     15865 +                 * buffer to NULL before calling into dtrace_state_destroy();
     15866 +                 * we take advantage of its dtrace_sync() to know that no
     15867 +                 * CPU is in probe context with enabled helper tracing
     15868 +                 * after it returns.
     15869 +                 */
     15870 +                buf = dtrace_helptrace_buffer;
     15871 +                dtrace_helptrace_buffer = NULL;
     15872 +        }
     15873 +
15853 15874          dtrace_state_destroy(state);
15854 15875          ASSERT(dtrace_opens > 0);
15855 15876  
15856 15877          /*
15857 15878           * Only relinquish control of the kernel debugger interface when there
15858 15879           * are no consumers and no anonymous enablings.
15859 15880           */
15860 15881          if (--dtrace_opens == 0 && dtrace_anon.dta_enabling == NULL)
15861 15882                  (void) kdi_dtrace_set(KDI_DTSET_DTRACE_DEACTIVATE);
15862 15883  
     15884 +        if (buf != NULL) {
     15885 +                kmem_free(buf, dtrace_helptrace_bufsize);
     15886 +                dtrace_helptrace_disable = 0;
     15887 +        }
     15888 +
15863 15889          mutex_exit(&dtrace_lock);
15864 15890          mutex_exit(&cpu_lock);
15865 15891  
15866 15892          return (0);
15867 15893  }
15868 15894  
15869 15895  /*ARGSUSED*/
15870 15896  static int
15871 15897  dtrace_ioctl_helper(int cmd, intptr_t arg, int *rv)
15872 15898  {
↓ open down ↓ 873 lines elided ↑ open up ↑
16746 16772          dtrace_debugger_init = NULL;
16747 16773          dtrace_debugger_fini = NULL;
16748 16774          dtrace_modload = NULL;
16749 16775          dtrace_modunload = NULL;
16750 16776  
16751 16777          ASSERT(dtrace_getf == 0);
16752 16778          ASSERT(dtrace_closef == NULL);
16753 16779  
16754 16780          mutex_exit(&cpu_lock);
16755 16781  
16756      -        if (dtrace_helptrace_enabled) {
16757      -                kmem_free(dtrace_helptrace_buffer, dtrace_helptrace_bufsize);
16758      -                dtrace_helptrace_buffer = NULL;
16759      -        }
16760      -
16761 16782          kmem_free(dtrace_probes, dtrace_nprobes * sizeof (dtrace_probe_t *));
16762 16783          dtrace_probes = NULL;
16763 16784          dtrace_nprobes = 0;
16764 16785  
16765 16786          dtrace_hash_destroy(dtrace_bymod);
16766 16787          dtrace_hash_destroy(dtrace_byfunc);
16767 16788          dtrace_hash_destroy(dtrace_byname);
16768 16789          dtrace_bymod = NULL;
16769 16790          dtrace_byfunc = NULL;
16770 16791          dtrace_byname = NULL;
↓ open down ↓ 122 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX