Path: blob/main/sys/cddl/dev/dtrace/dtrace_load.c
103316 views
/*1* CDDL HEADER START2*3* The contents of this file are subject to the terms of the4* Common Development and Distribution License (the "License").5* You may not use this file except in compliance with the License.6*7* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE8* or http://www.opensolaris.org/os/licensing.9* See the License for the specific language governing permissions10* and limitations under the License.11*12* When distributing Covered Code, include this CDDL HEADER in each13* file and include the License file at usr/src/OPENSOLARIS.LICENSE.14* If applicable, add the following below this CDDL HEADER, with the15* fields enclosed by brackets "[]" replaced with your own identifying16* information: Portions Copyright [yyyy] [name of copyright owner]17*18* CDDL HEADER END19*20*/2122#ifndef EARLY_AP_STARTUP23static void24dtrace_ap_start(void *dummy)25{26int i;2728mutex_enter(&cpu_lock);2930/* Setup the rest of the CPUs. */31CPU_FOREACH(i) {32if (i == 0)33continue;3435(void) dtrace_cpu_setup(CPU_CONFIG, i);36}3738mutex_exit(&cpu_lock);39}4041SYSINIT(dtrace_ap_start, SI_SUB_SMP, SI_ORDER_ANY, dtrace_ap_start, NULL);42#endif4344static void45dtrace_load(void *dummy)46{47dtrace_provider_id_t id;48#ifdef EARLY_AP_STARTUP49int i;50#endif5152#ifndef illumos53/*54* DTrace uses negative logic for the destructive mode switch, so it55* is required to translate from the sysctl which uses positive logic.56*/57if (dtrace_allow_destructive)58dtrace_destructive_disallow = 0;59else60dtrace_destructive_disallow = 1;61#endif6263/* Hook into the trap handler. */64dtrace_trap_func = dtrace_trap;6566/* Hang our hook for thread switches. */67dtrace_vtime_switch_func = dtrace_vtime_switch;6869/* Hang our hook for exceptions. */70dtrace_invop_init();7172dtrace_taskq = taskq_create("dtrace_taskq", 1, maxclsyspri, 0, 0, 0);7374dtrace_arena = new_unrhdr(1, INT_MAX, &dtrace_unr_mtx);7576/* Register callbacks for linker file load and unload events. */77dtrace_kld_load_tag = EVENTHANDLER_REGISTER(kld_load,78dtrace_kld_load, NULL, EVENTHANDLER_PRI_ANY);79dtrace_kld_unload_try_tag = EVENTHANDLER_REGISTER(kld_unload_try,80dtrace_kld_unload_try, NULL, EVENTHANDLER_PRI_ANY);8182/*83* Initialise the mutexes without 'witness' because the dtrace84* code is mostly written to wait for memory. To have the85* witness code change a malloc() from M_WAITOK to M_NOWAIT86* because a lock is held would surely create a panic in a87* low memory situation. And that low memory situation might be88* the very problem we are trying to trace.89*/90mutex_init(&dtrace_lock,"dtrace probe state", MUTEX_DEFAULT, NULL);91mutex_init(&dtrace_provider_lock,"dtrace provider state", MUTEX_DEFAULT, NULL);92mutex_init(&dtrace_meta_lock,"dtrace meta-provider state", MUTEX_DEFAULT, NULL);93#ifdef DEBUG94mutex_init(&dtrace_errlock,"dtrace error lock", MUTEX_DEFAULT, NULL);95#endif9697mutex_enter(&cpu_lock);98mutex_enter(&dtrace_provider_lock);99mutex_enter(&dtrace_lock);100101dtrace_state_cache = kmem_cache_create("dtrace_state_cache",102sizeof (dtrace_dstate_percpu_t) * (mp_maxid + 1),103DTRACE_STATE_ALIGN, NULL, NULL, NULL, NULL, NULL, 0);104105ASSERT(MUTEX_HELD(&cpu_lock));106dtrace_bymod = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_mod),107offsetof(dtrace_probe_t, dtpr_nextmod),108offsetof(dtrace_probe_t, dtpr_prevmod));109110dtrace_byfunc = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_func),111offsetof(dtrace_probe_t, dtpr_nextfunc),112offsetof(dtrace_probe_t, dtpr_prevfunc));113114dtrace_byname = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_name),115offsetof(dtrace_probe_t, dtpr_nextname),116offsetof(dtrace_probe_t, dtpr_prevname));117118if (dtrace_retain_max < 1) {119cmn_err(CE_WARN, "illegal value (%zu) for dtrace_retain_max; "120"setting to 1", dtrace_retain_max);121dtrace_retain_max = 1;122}123124/*125* Now discover our toxic ranges.126*/127dtrace_toxic_ranges(dtrace_toxrange_add);128129/*130* Before we register ourselves as a provider to our own framework,131* we would like to assert that dtrace_provider is NULL -- but that's132* not true if we were loaded as a dependency of a DTrace provider.133* Once we've registered, we can assert that dtrace_provider is our134* pseudo provider.135*/136(void) dtrace_register("dtrace", &dtrace_provider_attr,137DTRACE_PRIV_NONE, 0, &dtrace_provider_ops, NULL, &id);138139ASSERT(dtrace_provider != NULL);140ASSERT((dtrace_provider_id_t)dtrace_provider == id);141142dtrace_probeid_begin = dtrace_probe_create((dtrace_provider_id_t)143dtrace_provider, NULL, NULL, "BEGIN", 0, NULL);144dtrace_probeid_end = dtrace_probe_create((dtrace_provider_id_t)145dtrace_provider, NULL, NULL, "END", 0, NULL);146dtrace_probeid_error = dtrace_probe_create((dtrace_provider_id_t)147dtrace_provider, NULL, NULL, "ERROR", 1, NULL);148149mutex_exit(&dtrace_lock);150mutex_exit(&dtrace_provider_lock);151152#ifdef EARLY_AP_STARTUP153CPU_FOREACH(i) {154(void) dtrace_cpu_setup(CPU_CONFIG, i);155}156#else157/* Setup the boot CPU */158(void) dtrace_cpu_setup(CPU_CONFIG, 0);159#endif160161mutex_exit(&cpu_lock);162163dtrace_dev = make_dev(&dtrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,164"dtrace/dtrace");165helper_dev = make_dev(&helper_cdevsw, 0, UID_ROOT, GID_WHEEL, 0660,166"dtrace/helper");167}168169170