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. */ 3391eaf3e1SJohn Birrell for (i = 1; i <= mp_maxid; i++) { 3491eaf3e1SJohn Birrell if (pcpu_find(i) == NULL) 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 5991eaf3e1SJohn Birrell /* 6091eaf3e1SJohn Birrell * XXX This is a short term hack to avoid having to comment 6191eaf3e1SJohn Birrell * out lots and lots of lock/unlock calls. 6291eaf3e1SJohn Birrell */ 6391eaf3e1SJohn Birrell mutex_init(&mod_lock,"XXX mod_lock hack", MUTEX_DEFAULT, NULL); 6491eaf3e1SJohn Birrell 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); 7691eaf3e1SJohn Birrell mutex_init(&dtrace_errlock,"dtrace error lock", MUTEX_DEFAULT, NULL); 7791eaf3e1SJohn Birrell 7891eaf3e1SJohn Birrell mutex_enter(&dtrace_provider_lock); 7991eaf3e1SJohn Birrell mutex_enter(&dtrace_lock); 8091eaf3e1SJohn Birrell mutex_enter(&cpu_lock); 8191eaf3e1SJohn Birrell 8291eaf3e1SJohn Birrell ASSERT(MUTEX_HELD(&cpu_lock)); 8391eaf3e1SJohn Birrell 8491eaf3e1SJohn Birrell dtrace_arena = new_unrhdr(1, INT_MAX, &dtrace_unr_mtx); 8591eaf3e1SJohn Birrell 8691eaf3e1SJohn Birrell dtrace_state_cache = kmem_cache_create("dtrace_state_cache", 8791eaf3e1SJohn Birrell sizeof (dtrace_dstate_percpu_t) * NCPU, DTRACE_STATE_ALIGN, 8891eaf3e1SJohn Birrell NULL, NULL, NULL, NULL, NULL, 0); 8991eaf3e1SJohn Birrell 9091eaf3e1SJohn Birrell ASSERT(MUTEX_HELD(&cpu_lock)); 9191eaf3e1SJohn Birrell dtrace_bymod = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_mod), 9291eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_nextmod), 9391eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_prevmod)); 9491eaf3e1SJohn Birrell 9591eaf3e1SJohn Birrell dtrace_byfunc = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_func), 9691eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_nextfunc), 9791eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_prevfunc)); 9891eaf3e1SJohn Birrell 9991eaf3e1SJohn Birrell dtrace_byname = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_name), 10091eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_nextname), 10191eaf3e1SJohn Birrell offsetof(dtrace_probe_t, dtpr_prevname)); 10291eaf3e1SJohn Birrell 10391eaf3e1SJohn Birrell if (dtrace_retain_max < 1) { 10491eaf3e1SJohn Birrell cmn_err(CE_WARN, "illegal value (%lu) for dtrace_retain_max; " 10591eaf3e1SJohn Birrell "setting to 1", dtrace_retain_max); 10691eaf3e1SJohn Birrell dtrace_retain_max = 1; 10791eaf3e1SJohn Birrell } 10891eaf3e1SJohn Birrell 10991eaf3e1SJohn Birrell /* 11091eaf3e1SJohn Birrell * Now discover our toxic ranges. 11191eaf3e1SJohn Birrell */ 11291eaf3e1SJohn Birrell dtrace_toxic_ranges(dtrace_toxrange_add); 11391eaf3e1SJohn Birrell 11491eaf3e1SJohn Birrell /* 11591eaf3e1SJohn Birrell * Before we register ourselves as a provider to our own framework, 11691eaf3e1SJohn Birrell * we would like to assert that dtrace_provider is NULL -- but that's 11791eaf3e1SJohn Birrell * not true if we were loaded as a dependency of a DTrace provider. 11891eaf3e1SJohn Birrell * Once we've registered, we can assert that dtrace_provider is our 11991eaf3e1SJohn Birrell * pseudo provider. 12091eaf3e1SJohn Birrell */ 12191eaf3e1SJohn Birrell (void) dtrace_register("dtrace", &dtrace_provider_attr, 12291eaf3e1SJohn Birrell DTRACE_PRIV_NONE, 0, &dtrace_provider_ops, NULL, &id); 12391eaf3e1SJohn Birrell 12491eaf3e1SJohn Birrell ASSERT(dtrace_provider != NULL); 12591eaf3e1SJohn Birrell ASSERT((dtrace_provider_id_t)dtrace_provider == id); 12691eaf3e1SJohn Birrell 12791eaf3e1SJohn Birrell dtrace_probeid_begin = dtrace_probe_create((dtrace_provider_id_t) 12891eaf3e1SJohn Birrell dtrace_provider, NULL, NULL, "BEGIN", 0, NULL); 12991eaf3e1SJohn Birrell dtrace_probeid_end = dtrace_probe_create((dtrace_provider_id_t) 13091eaf3e1SJohn Birrell dtrace_provider, NULL, NULL, "END", 0, NULL); 13191eaf3e1SJohn Birrell dtrace_probeid_error = dtrace_probe_create((dtrace_provider_id_t) 13291eaf3e1SJohn Birrell dtrace_provider, NULL, NULL, "ERROR", 1, NULL); 13391eaf3e1SJohn Birrell 13491eaf3e1SJohn Birrell mutex_exit(&cpu_lock); 13591eaf3e1SJohn Birrell 13691eaf3e1SJohn Birrell /* 13791eaf3e1SJohn Birrell * If DTrace helper tracing is enabled, we need to allocate the 13891eaf3e1SJohn Birrell * trace buffer and initialize the values. 13991eaf3e1SJohn Birrell */ 14091eaf3e1SJohn Birrell if (dtrace_helptrace_enabled) { 14191eaf3e1SJohn Birrell ASSERT(dtrace_helptrace_buffer == NULL); 14291eaf3e1SJohn Birrell dtrace_helptrace_buffer = 14391eaf3e1SJohn Birrell kmem_zalloc(dtrace_helptrace_bufsize, KM_SLEEP); 14491eaf3e1SJohn Birrell dtrace_helptrace_next = 0; 14591eaf3e1SJohn Birrell } 14691eaf3e1SJohn Birrell 14791eaf3e1SJohn Birrell mutex_exit(&dtrace_lock); 14891eaf3e1SJohn Birrell mutex_exit(&dtrace_provider_lock); 14991eaf3e1SJohn Birrell 15091eaf3e1SJohn Birrell mutex_enter(&cpu_lock); 15191eaf3e1SJohn Birrell 15291eaf3e1SJohn Birrell /* Setup the boot CPU */ 15391eaf3e1SJohn Birrell (void) dtrace_cpu_setup(CPU_CONFIG, 0); 15491eaf3e1SJohn Birrell 15591eaf3e1SJohn Birrell mutex_exit(&cpu_lock); 15691eaf3e1SJohn Birrell 157f5a97d1bSCraig Rodrigues #if __FreeBSD_version < 800039 15891eaf3e1SJohn Birrell /* Enable device cloning. */ 15991eaf3e1SJohn Birrell clone_setup(&dtrace_clones); 16091eaf3e1SJohn Birrell 16191eaf3e1SJohn Birrell /* Setup device cloning events. */ 16291eaf3e1SJohn Birrell eh_tag = EVENTHANDLER_REGISTER(dev_clone, dtrace_clone, 0, 1000); 163f5a97d1bSCraig Rodrigues #else 164f5a97d1bSCraig Rodrigues dtrace_dev = make_dev(&dtrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "dtrace/dtrace"); 165f5a97d1bSCraig Rodrigues #endif 16691eaf3e1SJohn Birrell 16791eaf3e1SJohn Birrell return; 16891eaf3e1SJohn Birrell } 169