191eaf3e1SJohn Birrell /* 291eaf3e1SJohn Birrell * CDDL HEADER START 391eaf3e1SJohn Birrell * 491eaf3e1SJohn Birrell * The contents of this file are subject to the terms of the 591eaf3e1SJohn Birrell * Common Development and Distribution License (the "License"). 691eaf3e1SJohn Birrell * You may not use this file except in compliance with the License. 791eaf3e1SJohn Birrell * 891eaf3e1SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 991eaf3e1SJohn Birrell * or http://www.opensolaris.org/os/licensing. 1091eaf3e1SJohn Birrell * See the License for the specific language governing permissions 1191eaf3e1SJohn Birrell * and limitations under the License. 1291eaf3e1SJohn Birrell * 1391eaf3e1SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 1491eaf3e1SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1591eaf3e1SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 1691eaf3e1SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 1791eaf3e1SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 1891eaf3e1SJohn Birrell * 1991eaf3e1SJohn Birrell * CDDL HEADER END 2091eaf3e1SJohn Birrell * 2191eaf3e1SJohn Birrell * $FreeBSD$ 2291eaf3e1SJohn Birrell * 2391eaf3e1SJohn Birrell */ 2491eaf3e1SJohn Birrell 2591eaf3e1SJohn Birrell static void 2691eaf3e1SJohn Birrell dtrace_ap_start(void *dummy) 2791eaf3e1SJohn Birrell { 2891eaf3e1SJohn Birrell int i; 2991eaf3e1SJohn Birrell 3091eaf3e1SJohn Birrell mutex_enter(&cpu_lock); 3191eaf3e1SJohn Birrell 3291eaf3e1SJohn Birrell /* Setup the rest of the CPUs. */ 333aa6d94eSJohn Baldwin CPU_FOREACH(i) { 343aa6d94eSJohn Baldwin if (i == 0) 3591eaf3e1SJohn Birrell continue; 3691eaf3e1SJohn Birrell 3791eaf3e1SJohn Birrell (void) dtrace_cpu_setup(CPU_CONFIG, i); 3891eaf3e1SJohn Birrell } 3991eaf3e1SJohn Birrell 4091eaf3e1SJohn Birrell mutex_exit(&cpu_lock); 4191eaf3e1SJohn Birrell } 4291eaf3e1SJohn Birrell 4391eaf3e1SJohn Birrell SYSINIT(dtrace_ap_start, SI_SUB_SMP, SI_ORDER_ANY, dtrace_ap_start, NULL); 4491eaf3e1SJohn Birrell 4591eaf3e1SJohn Birrell static void 4691eaf3e1SJohn Birrell dtrace_load(void *dummy) 4791eaf3e1SJohn Birrell { 4891eaf3e1SJohn Birrell dtrace_provider_id_t id; 4991eaf3e1SJohn Birrell 5091eaf3e1SJohn Birrell /* Hook into the trap handler. */ 5191eaf3e1SJohn Birrell dtrace_trap_func = dtrace_trap; 5291eaf3e1SJohn Birrell 5391eaf3e1SJohn Birrell /* Hang our hook for thread switches. */ 5491eaf3e1SJohn Birrell dtrace_vtime_switch_func = dtrace_vtime_switch; 5591eaf3e1SJohn Birrell 5691eaf3e1SJohn Birrell /* Hang our hook for exceptions. */ 5791eaf3e1SJohn Birrell dtrace_invop_init(); 5891eaf3e1SJohn Birrell 598776669bSMark Johnston /* Register callbacks for module load and unload events. */ 608776669bSMark Johnston dtrace_modload_tag = EVENTHANDLER_REGISTER(mod_load, 618776669bSMark Johnston dtrace_mod_load, NULL, EVENTHANDLER_PRI_ANY); 628776669bSMark Johnston dtrace_modunload_tag = EVENTHANDLER_REGISTER(mod_unload, 638776669bSMark Johnston dtrace_mod_unload, NULL, EVENTHANDLER_PRI_ANY); 648776669bSMark Johnston 6591eaf3e1SJohn Birrell /* 6691eaf3e1SJohn Birrell * Initialise the mutexes without 'witness' because the dtrace 6791eaf3e1SJohn Birrell * code is mostly written to wait for memory. To have the 6891eaf3e1SJohn Birrell * witness code change a malloc() from M_WAITOK to M_NOWAIT 6991eaf3e1SJohn Birrell * because a lock is held would surely create a panic in a 7091eaf3e1SJohn Birrell * low memory situation. And that low memory situation might be 7191eaf3e1SJohn Birrell * the very problem we are trying to trace. 7291eaf3e1SJohn Birrell */ 7391eaf3e1SJohn Birrell mutex_init(&dtrace_lock,"dtrace probe state", MUTEX_DEFAULT, NULL); 7491eaf3e1SJohn Birrell mutex_init(&dtrace_provider_lock,"dtrace provider state", MUTEX_DEFAULT, NULL); 7591eaf3e1SJohn Birrell mutex_init(&dtrace_meta_lock,"dtrace meta-provider state", MUTEX_DEFAULT, NULL); 76c319ea15SAndriy Gapon #ifdef DEBUG 7791eaf3e1SJohn Birrell mutex_init(&dtrace_errlock,"dtrace error lock", MUTEX_DEFAULT, NULL); 78c319ea15SAndriy Gapon #endif 7991eaf3e1SJohn Birrell 8091eaf3e1SJohn Birrell mutex_enter(&dtrace_provider_lock); 8191eaf3e1SJohn Birrell mutex_enter(&dtrace_lock); 8291eaf3e1SJohn Birrell mutex_enter(&cpu_lock); 8391eaf3e1SJohn Birrell 8491eaf3e1SJohn Birrell ASSERT(MUTEX_HELD(&cpu_lock)); 8591eaf3e1SJohn Birrell 8691eaf3e1SJohn Birrell dtrace_arena = new_unrhdr(1, INT_MAX, &dtrace_unr_mtx); 8791eaf3e1SJohn Birrell 8891eaf3e1SJohn Birrell dtrace_state_cache = kmem_cache_create("dtrace_state_cache", 8991eaf3e1SJohn Birrell sizeof (dtrace_dstate_percpu_t) * NCPU, DTRACE_STATE_ALIGN, 9091eaf3e1SJohn Birrell NULL, NULL, NULL, NULL, NULL, 0); 9191eaf3e1SJohn Birrell 9291eaf3e1SJohn Birrell ASSERT(MUTEX_HELD(&cpu_lock)); 9391eaf3e1SJohn Birrell dtrace_bymod = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_mod), 9491eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_nextmod), 9591eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_prevmod)); 9691eaf3e1SJohn Birrell 9791eaf3e1SJohn Birrell dtrace_byfunc = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_func), 9891eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_nextfunc), 9991eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_prevfunc)); 10091eaf3e1SJohn Birrell 10191eaf3e1SJohn Birrell dtrace_byname = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_name), 10291eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_nextname), 10391eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_prevname)); 10491eaf3e1SJohn Birrell 10591eaf3e1SJohn Birrell if (dtrace_retain_max < 1) { 10691eaf3e1SJohn Birrell cmn_err(CE_WARN, "illegal value (%lu) for dtrace_retain_max; " 10791eaf3e1SJohn Birrell "setting to 1", dtrace_retain_max); 10891eaf3e1SJohn Birrell dtrace_retain_max = 1; 10991eaf3e1SJohn Birrell } 11091eaf3e1SJohn Birrell 11191eaf3e1SJohn Birrell /* 11291eaf3e1SJohn Birrell * Now discover our toxic ranges. 11391eaf3e1SJohn Birrell */ 11491eaf3e1SJohn Birrell dtrace_toxic_ranges(dtrace_toxrange_add); 11591eaf3e1SJohn Birrell 11691eaf3e1SJohn Birrell /* 11791eaf3e1SJohn Birrell * Before we register ourselves as a provider to our own framework, 11891eaf3e1SJohn Birrell * we would like to assert that dtrace_provider is NULL -- but that's 11991eaf3e1SJohn Birrell * not true if we were loaded as a dependency of a DTrace provider. 12091eaf3e1SJohn Birrell * Once we've registered, we can assert that dtrace_provider is our 12191eaf3e1SJohn Birrell * pseudo provider. 12291eaf3e1SJohn Birrell */ 12391eaf3e1SJohn Birrell (void) dtrace_register("dtrace", &dtrace_provider_attr, 12491eaf3e1SJohn Birrell DTRACE_PRIV_NONE, 0, &dtrace_provider_ops, NULL, &id); 12591eaf3e1SJohn Birrell 12691eaf3e1SJohn Birrell ASSERT(dtrace_provider != NULL); 12791eaf3e1SJohn Birrell ASSERT((dtrace_provider_id_t)dtrace_provider == id); 12891eaf3e1SJohn Birrell 12991eaf3e1SJohn Birrell dtrace_probeid_begin = dtrace_probe_create((dtrace_provider_id_t) 13091eaf3e1SJohn Birrell dtrace_provider, NULL, NULL, "BEGIN", 0, NULL); 13191eaf3e1SJohn Birrell dtrace_probeid_end = dtrace_probe_create((dtrace_provider_id_t) 13291eaf3e1SJohn Birrell dtrace_provider, NULL, NULL, "END", 0, NULL); 13391eaf3e1SJohn Birrell dtrace_probeid_error = dtrace_probe_create((dtrace_provider_id_t) 13491eaf3e1SJohn Birrell dtrace_provider, NULL, NULL, "ERROR", 1, NULL); 13591eaf3e1SJohn Birrell 13691eaf3e1SJohn Birrell mutex_exit(&cpu_lock); 13791eaf3e1SJohn Birrell 13891eaf3e1SJohn Birrell /* 13991eaf3e1SJohn Birrell * If DTrace helper tracing is enabled, we need to allocate the 14091eaf3e1SJohn Birrell * trace buffer and initialize the values. 14191eaf3e1SJohn Birrell */ 14291eaf3e1SJohn Birrell if (dtrace_helptrace_enabled) { 14391eaf3e1SJohn Birrell ASSERT(dtrace_helptrace_buffer == NULL); 14491eaf3e1SJohn Birrell dtrace_helptrace_buffer = 14591eaf3e1SJohn Birrell kmem_zalloc(dtrace_helptrace_bufsize, KM_SLEEP); 14691eaf3e1SJohn Birrell dtrace_helptrace_next = 0; 14791eaf3e1SJohn Birrell } 14891eaf3e1SJohn Birrell 14991eaf3e1SJohn Birrell mutex_exit(&dtrace_lock); 15091eaf3e1SJohn Birrell mutex_exit(&dtrace_provider_lock); 15191eaf3e1SJohn Birrell 15291eaf3e1SJohn Birrell mutex_enter(&cpu_lock); 15391eaf3e1SJohn Birrell 15491eaf3e1SJohn Birrell /* Setup the boot CPU */ 15591eaf3e1SJohn Birrell (void) dtrace_cpu_setup(CPU_CONFIG, 0); 15691eaf3e1SJohn Birrell 15791eaf3e1SJohn Birrell mutex_exit(&cpu_lock); 15891eaf3e1SJohn Birrell 159f5a97d1bSCraig Rodrigues #if __FreeBSD_version < 800039 16091eaf3e1SJohn Birrell /* Enable device cloning. */ 16191eaf3e1SJohn Birrell clone_setup(&dtrace_clones); 16291eaf3e1SJohn Birrell 16391eaf3e1SJohn Birrell /* Setup device cloning events. */ 16491eaf3e1SJohn Birrell eh_tag = EVENTHANDLER_REGISTER(dev_clone, dtrace_clone, 0, 1000); 165f5a97d1bSCraig Rodrigues #else 166c6f5742fSRui Paulo dtrace_dev = make_dev(&dtrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 167c6f5742fSRui Paulo "dtrace/dtrace"); 168ea950d20SRui Paulo helper_dev = make_dev(&helper_cdevsw, 0, UID_ROOT, GID_WHEEL, 0660, 169c6f5742fSRui Paulo "dtrace/helper"); 170f5a97d1bSCraig Rodrigues #endif 17191eaf3e1SJohn Birrell 17291eaf3e1SJohn Birrell return; 17391eaf3e1SJohn Birrell } 174