xref: /onnv-gate/usr/src/cmd/mdb/common/kmdb/kctl/kctl_main.c (revision 10271:7c80b70bb8de)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53446Smrj  * Common Development and Distribution License (the "License").
63446Smrj  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*10271SJason.Beloro@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <kmdb/kctl/kctl.h>
270Sstevel@tonic-gate #include <kmdb/kctl/kctl_wr.h>
280Sstevel@tonic-gate #include <kmdb/kmdb_kctl.h>
290Sstevel@tonic-gate #include <kmdb/kmdb_kdi.h>
300Sstevel@tonic-gate #include <kmdb/kmdb_auxv.h>
310Sstevel@tonic-gate #include <mdb/mdb_errno.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <sys/sysmacros.h>
340Sstevel@tonic-gate #include <sys/reboot.h>
350Sstevel@tonic-gate #include <sys/atomic.h>
360Sstevel@tonic-gate #include <sys/bootconf.h>
370Sstevel@tonic-gate #include <sys/kmdb.h>
380Sstevel@tonic-gate #include <sys/kobj.h>
390Sstevel@tonic-gate #include <sys/kobj_impl.h>
400Sstevel@tonic-gate #include <sys/promimpl.h>
410Sstevel@tonic-gate #include <sys/kdi_impl.h>
420Sstevel@tonic-gate #include <sys/ctf_api.h>
430Sstevel@tonic-gate #include <vm/seg_kmem.h>
440Sstevel@tonic-gate 
450Sstevel@tonic-gate kctl_t kctl;
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #define	KCTL_EXECNAME		"/kernel/drv/kmdb"
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #if defined(_LP64)
500Sstevel@tonic-gate #define	KCTL_MEM_GOALSZ		(20 * 1024 * 1024)
510Sstevel@tonic-gate #else
520Sstevel@tonic-gate #define	KCTL_MEM_GOALSZ		(10 * 1024 * 1024)
530Sstevel@tonic-gate #endif
540Sstevel@tonic-gate 
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate  * kmdb will call its own copies of the promif routines during
570Sstevel@tonic-gate  * initialization.  As these routines are intended to be used when the
580Sstevel@tonic-gate  * world is stopped, they don't attempt to grab the PROM lock.  Very
590Sstevel@tonic-gate  * Bad Things could happen if kmdb called a prom routine while someone
600Sstevel@tonic-gate  * else was calling the kernel's copy of another prom routine, so we
610Sstevel@tonic-gate  * grab the PROM lock ourselves before we start initialization.
620Sstevel@tonic-gate  */
630Sstevel@tonic-gate #ifdef __sparc
640Sstevel@tonic-gate #define	KCTL_PROM_LOCK		promif_preprom()
650Sstevel@tonic-gate #define	KCTL_PROM_UNLOCK	promif_postprom()
660Sstevel@tonic-gate #else
670Sstevel@tonic-gate #define	KCTL_PROM_LOCK
680Sstevel@tonic-gate #define	KCTL_PROM_UNLOCK
690Sstevel@tonic-gate #endif
700Sstevel@tonic-gate 
710Sstevel@tonic-gate static int
kctl_init(void)720Sstevel@tonic-gate kctl_init(void)
730Sstevel@tonic-gate {
740Sstevel@tonic-gate 	if (kobj_kdi.kdi_version != KDI_VERSION) {
750Sstevel@tonic-gate 		kctl_warn("kmdb/kernel version mismatch (expected %d, "
760Sstevel@tonic-gate 		    "found %d)", KDI_VERSION, kobj_kdi.kdi_version);
770Sstevel@tonic-gate 		return (-1);
780Sstevel@tonic-gate 	}
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	sema_init(&kctl.kctl_wr_avail_sem, 0, NULL, SEMA_DRIVER, NULL);
810Sstevel@tonic-gate 	mutex_init(&kctl.kctl_wr_lock, NULL, MUTEX_DRIVER, NULL);
820Sstevel@tonic-gate 	cv_init(&kctl.kctl_wr_cv, NULL, CV_DRIVER, NULL);
830Sstevel@tonic-gate 	mutex_init(&kctl.kctl_lock, NULL, MUTEX_DRIVER, NULL);
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	kctl.kctl_execname = KCTL_EXECNAME; /* XXX get from modctl? */
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	kctl.kctl_state = KCTL_ST_INACTIVE;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	kctl.kctl_dseg = kctl.kctl_mrbase = NULL;
900Sstevel@tonic-gate 	kctl.kctl_dseg_size = kctl.kctl_mrsize = 0;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	kctl_dmod_init();
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	return (0);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate 
970Sstevel@tonic-gate static void
kctl_fini(void)980Sstevel@tonic-gate kctl_fini(void)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate 	kctl_dmod_fini();
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	mutex_destroy(&kctl.kctl_lock);
1030Sstevel@tonic-gate 	cv_destroy(&kctl.kctl_wr_cv);
1040Sstevel@tonic-gate 	mutex_destroy(&kctl.kctl_wr_lock);
1050Sstevel@tonic-gate 	sema_destroy(&kctl.kctl_wr_avail_sem);
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate static uint_t
kctl_set_state(uint_t state)1090Sstevel@tonic-gate kctl_set_state(uint_t state)
1100Sstevel@tonic-gate {
1110Sstevel@tonic-gate 	uint_t ostate = kctl.kctl_state;
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	/* forward progess only, please */
1140Sstevel@tonic-gate 	if (state > ostate) {
1150Sstevel@tonic-gate 		kctl_dprintf("new kctl state: %d", state);
1160Sstevel@tonic-gate 		kctl.kctl_state = state;
1170Sstevel@tonic-gate 	}
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	return (ostate);
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate static int
kctl_boot_dseg_alloc(caddr_t dsegaddr,size_t dsegsz)1230Sstevel@tonic-gate kctl_boot_dseg_alloc(caddr_t dsegaddr, size_t dsegsz)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate 	/*
1260Sstevel@tonic-gate 	 * The Intel boot memory allocator will cleverly map us onto a 4M
1270Sstevel@tonic-gate 	 * page if we request the whole 4M Intel segment at once.  This
1280Sstevel@tonic-gate 	 * will break physical memory r/w, so we break the request into
1290Sstevel@tonic-gate 	 * chunks.  The allocator isn't smart enough to combine requests,
1300Sstevel@tonic-gate 	 * so it'll give us a bunch of 4k pages.
1310Sstevel@tonic-gate 	 */
1320Sstevel@tonic-gate 	while (dsegsz >= 1024*1024) {
1330Sstevel@tonic-gate 		size_t sz = MIN(dsegsz, 1024*1024);
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 		if (BOP_ALLOC(kctl.kctl_boot_ops, dsegaddr, sz, BO_NO_ALIGN) !=
1360Sstevel@tonic-gate 		    dsegaddr)
1370Sstevel@tonic-gate 			return (-1);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 		dsegaddr += sz;
1400Sstevel@tonic-gate 		dsegsz -= sz;
1410Sstevel@tonic-gate 	}
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	return (0);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate static int
kctl_dseg_alloc(caddr_t addr,size_t sz)1470Sstevel@tonic-gate kctl_dseg_alloc(caddr_t addr, size_t sz)
1480Sstevel@tonic-gate {
1490Sstevel@tonic-gate 	ASSERT(((uintptr_t)addr & PAGEOFFSET) == 0);
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	/* make sure there isn't something there already (like kadb) */
1520Sstevel@tonic-gate 	if (hat_getpfnum(kas.a_hat, addr) != PFN_INVALID)
1530Sstevel@tonic-gate 		return (EAGAIN);
1540Sstevel@tonic-gate 
155*10271SJason.Beloro@Sun.COM 	if (segkmem_xalloc(NULL, addr, sz, VM_NOSLEEP, 0, segkmem_page_create,
156*10271SJason.Beloro@Sun.COM 	    NULL) == NULL)
1570Sstevel@tonic-gate 		return (ENOMEM);
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	return (0);
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate static void
kctl_dseg_free(caddr_t addr,size_t sz)1630Sstevel@tonic-gate kctl_dseg_free(caddr_t addr, size_t sz)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate 	ASSERT(((uintptr_t)addr & PAGEOFFSET) == 0);
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	segkmem_free(NULL, addr, sz);
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate static void
kctl_memavail(void)1710Sstevel@tonic-gate kctl_memavail(void)
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate 	size_t needed;
1740Sstevel@tonic-gate 	caddr_t base;
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	/*
1770Sstevel@tonic-gate 	 * We're now free to allocate the non-fixed portion of the debugger's
1780Sstevel@tonic-gate 	 * memory region.
1790Sstevel@tonic-gate 	 */
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	needed = P2ROUNDUP(kctl.kctl_memgoalsz <= kctl.kctl_dseg_size ? 0 :
1820Sstevel@tonic-gate 	    kctl.kctl_memgoalsz - kctl.kctl_dseg_size, PAGESIZE);
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	if (needed == 0)
1850Sstevel@tonic-gate 		return;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	if ((base = kmem_zalloc(needed, KM_NOSLEEP)) == NULL) {
1880Sstevel@tonic-gate 		/*
1890Sstevel@tonic-gate 		 * If we're going to wedge the machine during debugger startup,
1900Sstevel@tonic-gate 		 * at least let them know why it's going to wedge.
1910Sstevel@tonic-gate 		 */
1923446Smrj 		cmn_err(CE_WARN, "retrying of kmdb allocation of 0x%lx bytes",
1930Sstevel@tonic-gate 		    (ulong_t)needed);
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 		base = kmem_zalloc(needed, KM_SLEEP);
1960Sstevel@tonic-gate 	}
1970Sstevel@tonic-gate 
1983446Smrj 	kdi_dvec->dv_memavail(base, needed);
1990Sstevel@tonic-gate 	kctl.kctl_mrbase = base;
2000Sstevel@tonic-gate 	kctl.kctl_mrsize = needed;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate void
kctl_cleanup(void)2040Sstevel@tonic-gate kctl_cleanup(void)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate 	uint_t state = kctl_set_state(KCTL_ST_DEACTIVATING);
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	kctl_dprintf("cleaning up from state %d", state);
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	ASSERT(kctl.kctl_boot_loaded == 0);
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	switch (state) {
2130Sstevel@tonic-gate 	case KCTL_ST_ACTIVE:
2140Sstevel@tonic-gate 		boothowto &= ~RB_DEBUG;
2150Sstevel@tonic-gate 		/* XXX there's a race here */
2160Sstevel@tonic-gate 		kdi_dvec = NULL;
2170Sstevel@tonic-gate 		/*FALLTHROUGH*/
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	case KCTL_ST_DBG_ACTIVATED:
2200Sstevel@tonic-gate 		KCTL_PROM_LOCK;
2210Sstevel@tonic-gate 		kmdb_deactivate();
2220Sstevel@tonic-gate 		KCTL_PROM_UNLOCK;
2230Sstevel@tonic-gate 		/*FALLTHROUGH*/
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	case KCTL_ST_THREAD_STARTED:
2260Sstevel@tonic-gate 		if (curthread != kctl.kctl_wr_thr) {
2270Sstevel@tonic-gate 			kctl_wr_thr_stop();
2280Sstevel@tonic-gate 			kctl_wr_thr_join();
2290Sstevel@tonic-gate 		}
2300Sstevel@tonic-gate 		/*FALLTHROUGH*/
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	case KCTL_ST_MOD_NOTIFIERS:
2330Sstevel@tonic-gate 		kctl_mod_notify_unreg();
2340Sstevel@tonic-gate 		/*FALLTHROUGH*/
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	case KCTL_ST_KCTL_PREACTIVATED:
2370Sstevel@tonic-gate 		kctl_depreactivate_isadep();
2380Sstevel@tonic-gate 		/*FALLTHROUGH*/
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	case KCTL_ST_INITIALIZED:
2410Sstevel@tonic-gate 		/* There's no kmdb_fini */
2420Sstevel@tonic-gate 	case KCTL_ST_DSEG_ALLOCED:
2430Sstevel@tonic-gate 		kctl_dseg_free(kctl.kctl_dseg, kctl.kctl_dseg_size);
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 		if (kctl.kctl_mrbase != NULL)
2460Sstevel@tonic-gate 			kmem_free(kctl.kctl_mrbase, kctl.kctl_mrsize);
2470Sstevel@tonic-gate 		/*FALLTHROUGH*/
2480Sstevel@tonic-gate 	}
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	kctl.kctl_state = KCTL_ST_INACTIVE;
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate static void
kctl_startup_modules(void)2540Sstevel@tonic-gate kctl_startup_modules(void)
2550Sstevel@tonic-gate {
2560Sstevel@tonic-gate 	struct modctl *modp;
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	/*
2590Sstevel@tonic-gate 	 * Normal module load and unload is now available.  Prior to this point,
2600Sstevel@tonic-gate 	 * we could only load modules, and that only when the debugger was being
2610Sstevel@tonic-gate 	 * initialized.
2620Sstevel@tonic-gate 	 *
2630Sstevel@tonic-gate 	 * We'll need to prepare the modules we've already loaded (if any) for
2640Sstevel@tonic-gate 	 * the brave new world in which boot is unmapped.
2650Sstevel@tonic-gate 	 */
2660Sstevel@tonic-gate 	kctl_dmod_sync();
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	/*
2690Sstevel@tonic-gate 	 * Process any outstanding loads or unloads and prepare for automatic
2700Sstevel@tonic-gate 	 * module loading and unloading.
2710Sstevel@tonic-gate 	 */
2720Sstevel@tonic-gate 	(void) kctl_wr_process();
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	kctl_mod_notify_reg();
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_MOD_NOTIFIERS);
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	modp = &modules;
2790Sstevel@tonic-gate 	do {
2800Sstevel@tonic-gate 		kctl_mod_loaded(modp);
2810Sstevel@tonic-gate 	} while ((modp = modp->mod_next) != &modules);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate static void
kctl_startup_thread(void)2850Sstevel@tonic-gate kctl_startup_thread(void)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate 	/*
2880Sstevel@tonic-gate 	 * Create the worker thread, which will handle future requests from the
2890Sstevel@tonic-gate 	 * debugger.
2900Sstevel@tonic-gate 	 */
2910Sstevel@tonic-gate 	kctl_wr_thr_start();
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_THREAD_STARTED);
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate static int
kctl_startup_boot(void)2970Sstevel@tonic-gate kctl_startup_boot(void)
2980Sstevel@tonic-gate {
2990Sstevel@tonic-gate 	struct modctl_list *lp, **lpp;
3000Sstevel@tonic-gate 	int rc;
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	if (kctl_wr_process() < 0) {
3030Sstevel@tonic-gate 		kctl_warn("kmdb: failed to load modules");
3040Sstevel@tonic-gate 		return (-1);
3050Sstevel@tonic-gate 	}
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	mutex_enter(&mod_lock);
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	for (lpp = kobj_linkmaps; *lpp != NULL; lpp++) {
3100Sstevel@tonic-gate 		for (lp = *lpp; lp != NULL; lp = lp->modl_next) {
3110Sstevel@tonic-gate 			if ((rc = kctl_mod_decompress(lp->modl_modp)) != 0) {
3120Sstevel@tonic-gate 				kctl_warn("kmdb: failed to decompress CTF data "
3130Sstevel@tonic-gate 				    "for %s: %s", lp->modl_modp->mod_modname,
3140Sstevel@tonic-gate 				    ctf_errmsg(rc));
3150Sstevel@tonic-gate 			}
3160Sstevel@tonic-gate 		}
3170Sstevel@tonic-gate 	}
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	mutex_exit(&mod_lock);
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 	return (0);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate static int
kctl_startup_preactivate(void * romp,const char * cfg,const char ** argv)3250Sstevel@tonic-gate kctl_startup_preactivate(void *romp, const char *cfg, const char **argv)
3260Sstevel@tonic-gate {
3270Sstevel@tonic-gate 	kmdb_auxv_t kav;
3280Sstevel@tonic-gate 	int rc;
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	kctl_auxv_init(&kav, cfg, argv, romp);
3310Sstevel@tonic-gate 	KCTL_PROM_LOCK;
3320Sstevel@tonic-gate 	rc = kmdb_init(kctl.kctl_execname, &kav);
3330Sstevel@tonic-gate 	KCTL_PROM_UNLOCK;
3340Sstevel@tonic-gate 	kctl_auxv_fini(&kav);
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	if (rc < 0)
3370Sstevel@tonic-gate 		return (EMDB_KNOLOAD);
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_INITIALIZED);
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	if (kctl_preactivate_isadep() != 0)
3420Sstevel@tonic-gate 		return (EIO);
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_KCTL_PREACTIVATED);
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	return (0);
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate static int
kctl_startup_activate(uint_t flags)3500Sstevel@tonic-gate kctl_startup_activate(uint_t flags)
3510Sstevel@tonic-gate {
3520Sstevel@tonic-gate 	kdi_debugvec_t *dvec;
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	KCTL_PROM_LOCK;
3550Sstevel@tonic-gate 	kmdb_activate(&dvec, flags);
3560Sstevel@tonic-gate 	KCTL_PROM_UNLOCK;
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_DBG_ACTIVATED);
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	/*
3610Sstevel@tonic-gate 	 * fill in a few remaining debugvec entries.
3620Sstevel@tonic-gate 	 */
3630Sstevel@tonic-gate 	dvec->dv_kctl_modavail = kctl_startup_modules;
3640Sstevel@tonic-gate 	dvec->dv_kctl_thravail = kctl_startup_thread;
3650Sstevel@tonic-gate 	dvec->dv_kctl_memavail = kctl_memavail;
3660Sstevel@tonic-gate 
3673446Smrj 	kctl_activate_isadep(dvec);
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	kdi_dvec = dvec;
3700Sstevel@tonic-gate 	membar_producer();
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	boothowto |= RB_DEBUG;
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_ACTIVE);
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	return (0);
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate static int
kctl_state_check(uint_t state,uint_t ok_state)3800Sstevel@tonic-gate kctl_state_check(uint_t state, uint_t ok_state)
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate 	if (state == ok_state)
3830Sstevel@tonic-gate 		return (0);
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	if (state == KCTL_ST_INACTIVE)
3860Sstevel@tonic-gate 		return (EMDB_KINACTIVE);
3870Sstevel@tonic-gate 	else if (kctl.kctl_state > KCTL_ST_INACTIVE &&
3880Sstevel@tonic-gate 	    kctl.kctl_state < KCTL_ST_ACTIVE)
3890Sstevel@tonic-gate 		return (EMDB_KACTIVATING);
3900Sstevel@tonic-gate 	else if (kctl.kctl_state == KCTL_ST_ACTIVE)
3910Sstevel@tonic-gate 		return (EMDB_KACTIVE);
3920Sstevel@tonic-gate 	else if (kctl.kctl_state == KCTL_ST_DEACTIVATING)
3930Sstevel@tonic-gate 		return (EMDB_KDEACTIVATING);
3940Sstevel@tonic-gate 	else
3950Sstevel@tonic-gate 		return (EINVAL);
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate int
kctl_deactivate(void)3990Sstevel@tonic-gate kctl_deactivate(void)
4000Sstevel@tonic-gate {
4010Sstevel@tonic-gate 	int rc;
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	mutex_enter(&kctl.kctl_lock);
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	if (kctl.kctl_boot_loaded) {
4060Sstevel@tonic-gate 		rc = EMDB_KNOUNLOAD;
4070Sstevel@tonic-gate 		goto deactivate_done;
4080Sstevel@tonic-gate 	}
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	if ((rc = kctl_state_check(kctl.kctl_state, KCTL_ST_ACTIVE)) != 0)
4110Sstevel@tonic-gate 		goto deactivate_done;
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 	kmdb_kdi_set_unload_request();
4143446Smrj 	kmdb_kdi_kmdb_enter();
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	/*
4170Sstevel@tonic-gate 	 * The debugger will pass the request to the work thread, which will
4180Sstevel@tonic-gate 	 * stop itself.
4190Sstevel@tonic-gate 	 */
4200Sstevel@tonic-gate 	kctl_wr_thr_join();
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate deactivate_done:
4230Sstevel@tonic-gate 	mutex_exit(&kctl.kctl_lock);
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	return (rc);
4260Sstevel@tonic-gate }
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate /*
4290Sstevel@tonic-gate  * Called from krtld, this indicates that the user loaded kmdb at boot.  We
4300Sstevel@tonic-gate  * track activation states, but we don't attempt to clean up if activation
4310Sstevel@tonic-gate  * fails, because boot debugger load failures are fatal.
4320Sstevel@tonic-gate  *
4330Sstevel@tonic-gate  * Further complicating matters, various kernel routines, such as bcopy and
4340Sstevel@tonic-gate  * mutex_enter, assume the presence of some basic state.  On SPARC, it's the
4350Sstevel@tonic-gate  * presence of a valid curthread pointer.  On AMD64, it's a valid curcpu
4360Sstevel@tonic-gate  * pointer in GSBASE.  We set up temporary versions of these before beginning
4370Sstevel@tonic-gate  * activation, and tear them down when we're done.
4380Sstevel@tonic-gate  */
4390Sstevel@tonic-gate int
kctl_boot_activate(struct bootops * ops,void * romp,size_t memsz,const char ** argv)4400Sstevel@tonic-gate kctl_boot_activate(struct bootops *ops, void *romp, size_t memsz,
4410Sstevel@tonic-gate     const char **argv)
4420Sstevel@tonic-gate {
4430Sstevel@tonic-gate 	void *old;
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate #ifdef __lint
4460Sstevel@tonic-gate 	{
4470Sstevel@tonic-gate 	/*
4480Sstevel@tonic-gate 	 * krtld does a name-based symbol lookup to find this routine.  It then
4490Sstevel@tonic-gate 	 * casts the address it gets, calling the result.  We want to make sure
4500Sstevel@tonic-gate 	 * that the call in krtld stays in sync with the prototype for this
4510Sstevel@tonic-gate 	 * function, so we define a type (kctl_boot_activate_f) that matches the
4520Sstevel@tonic-gate 	 * current prototype.  The following assignment ensures that the type
4530Sstevel@tonic-gate 	 * still matches the declaration, with lint as the enforcer.
4540Sstevel@tonic-gate 	 */
4550Sstevel@tonic-gate 	kctl_boot_activate_f *kba = kctl_boot_activate;
4560Sstevel@tonic-gate 	if (kba == NULL)	/* Make lint think kba is actually used */
4570Sstevel@tonic-gate 		return (0);
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate #endif
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	old = kctl_boot_tmpinit();	/* Set up temporary state */
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	ASSERT(ops != NULL);
4640Sstevel@tonic-gate 	kctl.kctl_boot_ops = ops;	/* must be set before kctl_init */
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	if (kctl_init() < 0)
4670Sstevel@tonic-gate 		return (-1);
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	kctl.kctl_boot_loaded = 1;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	kctl_dprintf("beginning kmdb initialization");
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	if (memsz == 0)
4740Sstevel@tonic-gate 		memsz = KCTL_MEM_GOALSZ;
4750Sstevel@tonic-gate 
4763446Smrj 	kctl.kctl_dseg = kdi_segdebugbase;
4773446Smrj 	kctl.kctl_dseg_size =
4783446Smrj 	    memsz > kdi_segdebugsize ? kdi_segdebugsize : memsz;
4790Sstevel@tonic-gate 	kctl.kctl_memgoalsz = memsz;
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	if (kctl_boot_dseg_alloc(kctl.kctl_dseg, kctl.kctl_dseg_size) < 0) {
4823446Smrj 		kctl_warn("kmdb: failed to allocate %lu-byte debugger area at "
4833446Smrj 		    "%p", kctl.kctl_dseg_size, (void *)kctl.kctl_dseg);
4840Sstevel@tonic-gate 		return (-1);
4850Sstevel@tonic-gate 	}
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_DSEG_ALLOCED);
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	if (kctl_startup_preactivate(romp, NULL, argv) != 0 ||
4900Sstevel@tonic-gate 	    kctl_startup_activate(KMDB_ACT_F_BOOT)) {
4910Sstevel@tonic-gate 		kctl_warn("kmdb: failed to activate");
4920Sstevel@tonic-gate 		return (-1);
4930Sstevel@tonic-gate 	}
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	if (kctl_startup_boot() < 0)
4960Sstevel@tonic-gate 		return (-1);
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 	kctl_dprintf("finished with kmdb initialization");
4990Sstevel@tonic-gate 
5003446Smrj 	kctl_boot_tmpfini(old);
5013446Smrj 
5020Sstevel@tonic-gate 	kctl.kctl_boot_ops = NULL;
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	return (0);
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate int
kctl_modload_activate(size_t memsz,const char * cfg,uint_t flags)5080Sstevel@tonic-gate kctl_modload_activate(size_t memsz, const char *cfg, uint_t flags)
5090Sstevel@tonic-gate {
5100Sstevel@tonic-gate 	int rc;
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 	mutex_enter(&kctl.kctl_lock);
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	if ((rc = kctl_state_check(kctl.kctl_state, KCTL_ST_INACTIVE)) != 0) {
5150Sstevel@tonic-gate 		if ((flags & KMDB_F_AUTO_ENTRY) && rc == EMDB_KACTIVE) {
5163446Smrj 			kmdb_kdi_kmdb_enter();
5170Sstevel@tonic-gate 			rc = 0;
5180Sstevel@tonic-gate 		}
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 		mutex_exit(&kctl.kctl_lock);
5210Sstevel@tonic-gate 		return (rc);
5220Sstevel@tonic-gate 	}
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 	kctl.kctl_flags = flags;
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	if (memsz == 0)
5270Sstevel@tonic-gate 		memsz = KCTL_MEM_GOALSZ;
5280Sstevel@tonic-gate 
5293446Smrj 	kctl.kctl_dseg = kdi_segdebugbase;
5303446Smrj 	kctl.kctl_dseg_size =
5313446Smrj 	    memsz > kdi_segdebugsize ? kdi_segdebugsize : memsz;
5320Sstevel@tonic-gate 	kctl.kctl_memgoalsz = memsz;
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	if ((rc = kctl_dseg_alloc(kctl.kctl_dseg, kctl.kctl_dseg_size)) != 0)
5350Sstevel@tonic-gate 		goto activate_fail;
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_DSEG_ALLOCED);
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	if ((rc = kctl_startup_preactivate(NULL, cfg, NULL)) != 0)
5400Sstevel@tonic-gate 		goto activate_fail;
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 	kctl_startup_modules();
5430Sstevel@tonic-gate 	kctl_startup_thread();
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 	if ((rc = kctl_startup_activate(0)) != 0)
5460Sstevel@tonic-gate 		goto activate_fail;
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	kctl_memavail();	/* Must be after kdi_dvec is set */
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	if (kctl.kctl_flags & KMDB_F_AUTO_ENTRY)
5513446Smrj 		kmdb_kdi_kmdb_enter();
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	mutex_exit(&kctl.kctl_lock);
5540Sstevel@tonic-gate 	return (0);
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate activate_fail:
5570Sstevel@tonic-gate 	kctl_cleanup();
5580Sstevel@tonic-gate 	mutex_exit(&kctl.kctl_lock);
5590Sstevel@tonic-gate 	return (rc);
5600Sstevel@tonic-gate }
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate /*
5630Sstevel@tonic-gate  * This interface will be called when drv/kmdb loads.  When we get the call, one
5640Sstevel@tonic-gate  * of two things will have happened:
5650Sstevel@tonic-gate  *
5660Sstevel@tonic-gate  *  1. The debugger was loaded at boot.  We've progressed far enough into boot
5670Sstevel@tonic-gate  *     as to allow drv/kmdb to be loaded as a non-primary.  Invocation of this
5680Sstevel@tonic-gate  *     interface is the signal to the debugger that it can start allowing things
5690Sstevel@tonic-gate  *     like dmod loading and automatic CTF decompression - things which require
5700Sstevel@tonic-gate  *     the system services that have now been started.
5710Sstevel@tonic-gate  *
5720Sstevel@tonic-gate  *  2. The debugger was loaded after boot.  mdb opened /dev/kmdb, causing
5730Sstevel@tonic-gate  *     drv/kmdb to load, followed by misc/kmdb.  Nothing has been set up yet,
5740Sstevel@tonic-gate  *     so we need to initialize.  Activation will occur separately, so we don't
5750Sstevel@tonic-gate  *     have to worry about that.
5760Sstevel@tonic-gate  */
5770Sstevel@tonic-gate int
kctl_attach(dev_info_t * dip)5780Sstevel@tonic-gate kctl_attach(dev_info_t *dip)
5790Sstevel@tonic-gate {
5800Sstevel@tonic-gate 	kctl.kctl_drv_dip = dip;
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	return (0);
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate int
kctl_detach(void)5860Sstevel@tonic-gate kctl_detach(void)
5870Sstevel@tonic-gate {
5880Sstevel@tonic-gate 	return (kctl.kctl_state == KCTL_ST_INACTIVE ? 0 : EBUSY);
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate static struct modlmisc modlmisc = {
5920Sstevel@tonic-gate 	&mod_miscops,
5930Sstevel@tonic-gate 	KMDB_VERSION
5940Sstevel@tonic-gate };
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate static struct modlinkage modlinkage = {
5970Sstevel@tonic-gate 	MODREV_1,
5980Sstevel@tonic-gate 	(void *)&modlmisc,
5990Sstevel@tonic-gate 	NULL
6000Sstevel@tonic-gate };
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate /*
6030Sstevel@tonic-gate  * Invoked only when debugger is loaded via modload - not invoked when debugger
6040Sstevel@tonic-gate  * is loaded at boot.  kctl_boot_activate needs to call anything (aside from
6050Sstevel@tonic-gate  * mod_install) this function does.
6060Sstevel@tonic-gate  */
6070Sstevel@tonic-gate int
_init(void)6080Sstevel@tonic-gate _init(void)
6090Sstevel@tonic-gate {
6100Sstevel@tonic-gate 	if (kctl_init() < 0)
6110Sstevel@tonic-gate 		return (EINVAL);
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	return (mod_install(&modlinkage));
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate int
_info(struct modinfo * modinfop)6170Sstevel@tonic-gate _info(struct modinfo *modinfop)
6180Sstevel@tonic-gate {
6190Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate int
_fini(void)6230Sstevel@tonic-gate _fini(void)
6240Sstevel@tonic-gate {
6250Sstevel@tonic-gate 	kctl_fini();
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
6280Sstevel@tonic-gate }
629