17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5ae115bc7Smrj  * Common Development and Distribution License (the "License").
6ae115bc7Smrj  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*9d0d62adSJason Beloro  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <kmdb/kctl/kctl.h>
277c478bd9Sstevel@tonic-gate #include <kmdb/kctl/kctl_wr.h>
287c478bd9Sstevel@tonic-gate #include <kmdb/kmdb_kctl.h>
297c478bd9Sstevel@tonic-gate #include <kmdb/kmdb_kdi.h>
307c478bd9Sstevel@tonic-gate #include <kmdb/kmdb_auxv.h>
317c478bd9Sstevel@tonic-gate #include <mdb/mdb_errno.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
357c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
367c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
377c478bd9Sstevel@tonic-gate #include <sys/kmdb.h>
387c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
397c478bd9Sstevel@tonic-gate #include <sys/kobj_impl.h>
407c478bd9Sstevel@tonic-gate #include <sys/promimpl.h>
417c478bd9Sstevel@tonic-gate #include <sys/kdi_impl.h>
427c478bd9Sstevel@tonic-gate #include <sys/ctf_api.h>
437c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate kctl_t kctl;
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #define	KCTL_EXECNAME		"/kernel/drv/kmdb"
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #if defined(_LP64)
507c478bd9Sstevel@tonic-gate #define	KCTL_MEM_GOALSZ		(20 * 1024 * 1024)
517c478bd9Sstevel@tonic-gate #else
527c478bd9Sstevel@tonic-gate #define	KCTL_MEM_GOALSZ		(10 * 1024 * 1024)
537c478bd9Sstevel@tonic-gate #endif
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate  * kmdb will call its own copies of the promif routines during
577c478bd9Sstevel@tonic-gate  * initialization.  As these routines are intended to be used when the
587c478bd9Sstevel@tonic-gate  * world is stopped, they don't attempt to grab the PROM lock.  Very
597c478bd9Sstevel@tonic-gate  * Bad Things could happen if kmdb called a prom routine while someone
607c478bd9Sstevel@tonic-gate  * else was calling the kernel's copy of another prom routine, so we
617c478bd9Sstevel@tonic-gate  * grab the PROM lock ourselves before we start initialization.
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate #ifdef __sparc
647c478bd9Sstevel@tonic-gate #define	KCTL_PROM_LOCK		promif_preprom()
657c478bd9Sstevel@tonic-gate #define	KCTL_PROM_UNLOCK	promif_postprom()
667c478bd9Sstevel@tonic-gate #else
677c478bd9Sstevel@tonic-gate #define	KCTL_PROM_LOCK
687c478bd9Sstevel@tonic-gate #define	KCTL_PROM_UNLOCK
697c478bd9Sstevel@tonic-gate #endif
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate static int
kctl_init(void)727c478bd9Sstevel@tonic-gate kctl_init(void)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	if (kobj_kdi.kdi_version != KDI_VERSION) {
757c478bd9Sstevel@tonic-gate 		kctl_warn("kmdb/kernel version mismatch (expected %d, "
767c478bd9Sstevel@tonic-gate 		    "found %d)", KDI_VERSION, kobj_kdi.kdi_version);
777c478bd9Sstevel@tonic-gate 		return (-1);
787c478bd9Sstevel@tonic-gate 	}
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	sema_init(&kctl.kctl_wr_avail_sem, 0, NULL, SEMA_DRIVER, NULL);
817c478bd9Sstevel@tonic-gate 	mutex_init(&kctl.kctl_wr_lock, NULL, MUTEX_DRIVER, NULL);
827c478bd9Sstevel@tonic-gate 	cv_init(&kctl.kctl_wr_cv, NULL, CV_DRIVER, NULL);
837c478bd9Sstevel@tonic-gate 	mutex_init(&kctl.kctl_lock, NULL, MUTEX_DRIVER, NULL);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	kctl.kctl_execname = KCTL_EXECNAME; /* XXX get from modctl? */
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	kctl.kctl_state = KCTL_ST_INACTIVE;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	kctl.kctl_dseg = kctl.kctl_mrbase = NULL;
907c478bd9Sstevel@tonic-gate 	kctl.kctl_dseg_size = kctl.kctl_mrsize = 0;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	kctl_dmod_init();
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	return (0);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate static void
kctl_fini(void)987c478bd9Sstevel@tonic-gate kctl_fini(void)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 	kctl_dmod_fini();
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	mutex_destroy(&kctl.kctl_lock);
1037c478bd9Sstevel@tonic-gate 	cv_destroy(&kctl.kctl_wr_cv);
1047c478bd9Sstevel@tonic-gate 	mutex_destroy(&kctl.kctl_wr_lock);
1057c478bd9Sstevel@tonic-gate 	sema_destroy(&kctl.kctl_wr_avail_sem);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate static uint_t
kctl_set_state(uint_t state)1097c478bd9Sstevel@tonic-gate kctl_set_state(uint_t state)
1107c478bd9Sstevel@tonic-gate {
1117c478bd9Sstevel@tonic-gate 	uint_t ostate = kctl.kctl_state;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	/* forward progess only, please */
1147c478bd9Sstevel@tonic-gate 	if (state > ostate) {
1157c478bd9Sstevel@tonic-gate 		kctl_dprintf("new kctl state: %d", state);
1167c478bd9Sstevel@tonic-gate 		kctl.kctl_state = state;
1177c478bd9Sstevel@tonic-gate 	}
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	return (ostate);
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate static int
kctl_boot_dseg_alloc(caddr_t dsegaddr,size_t dsegsz)1237c478bd9Sstevel@tonic-gate kctl_boot_dseg_alloc(caddr_t dsegaddr, size_t dsegsz)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	/*
1267c478bd9Sstevel@tonic-gate 	 * The Intel boot memory allocator will cleverly map us onto a 4M
1277c478bd9Sstevel@tonic-gate 	 * page if we request the whole 4M Intel segment at once.  This
1287c478bd9Sstevel@tonic-gate 	 * will break physical memory r/w, so we break the request into
1297c478bd9Sstevel@tonic-gate 	 * chunks.  The allocator isn't smart enough to combine requests,
1307c478bd9Sstevel@tonic-gate 	 * so it'll give us a bunch of 4k pages.
1317c478bd9Sstevel@tonic-gate 	 */
1327c478bd9Sstevel@tonic-gate 	while (dsegsz >= 1024*1024) {
1337c478bd9Sstevel@tonic-gate 		size_t sz = MIN(dsegsz, 1024*1024);
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 		if (BOP_ALLOC(kctl.kctl_boot_ops, dsegaddr, sz, BO_NO_ALIGN) !=
1367c478bd9Sstevel@tonic-gate 		    dsegaddr)
1377c478bd9Sstevel@tonic-gate 			return (-1);
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 		dsegaddr += sz;
1407c478bd9Sstevel@tonic-gate 		dsegsz -= sz;
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	return (0);
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate static int
kctl_dseg_alloc(caddr_t addr,size_t sz)1477c478bd9Sstevel@tonic-gate kctl_dseg_alloc(caddr_t addr, size_t sz)
1487c478bd9Sstevel@tonic-gate {
1497c478bd9Sstevel@tonic-gate 	ASSERT(((uintptr_t)addr & PAGEOFFSET) == 0);
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	/* make sure there isn't something there already (like kadb) */
1527c478bd9Sstevel@tonic-gate 	if (hat_getpfnum(kas.a_hat, addr) != PFN_INVALID)
1537c478bd9Sstevel@tonic-gate 		return (EAGAIN);
1547c478bd9Sstevel@tonic-gate 
155*9d0d62adSJason Beloro 	if (segkmem_xalloc(NULL, addr, sz, VM_NOSLEEP, 0, segkmem_page_create,
156*9d0d62adSJason Beloro 	    NULL) == NULL)
1577c478bd9Sstevel@tonic-gate 		return (ENOMEM);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	return (0);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate static void
kctl_dseg_free(caddr_t addr,size_t sz)1637c478bd9Sstevel@tonic-gate kctl_dseg_free(caddr_t addr, size_t sz)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	ASSERT(((uintptr_t)addr & PAGEOFFSET) == 0);
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	segkmem_free(NULL, addr, sz);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate static void
kctl_memavail(void)1717c478bd9Sstevel@tonic-gate kctl_memavail(void)
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate 	size_t needed;
1747c478bd9Sstevel@tonic-gate 	caddr_t base;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	/*
1777c478bd9Sstevel@tonic-gate 	 * We're now free to allocate the non-fixed portion of the debugger's
1787c478bd9Sstevel@tonic-gate 	 * memory region.
1797c478bd9Sstevel@tonic-gate 	 */
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	needed = P2ROUNDUP(kctl.kctl_memgoalsz <= kctl.kctl_dseg_size ? 0 :
1827c478bd9Sstevel@tonic-gate 	    kctl.kctl_memgoalsz - kctl.kctl_dseg_size, PAGESIZE);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	if (needed == 0)
1857c478bd9Sstevel@tonic-gate 		return;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	if ((base = kmem_zalloc(needed, KM_NOSLEEP)) == NULL) {
1887c478bd9Sstevel@tonic-gate 		/*
1897c478bd9Sstevel@tonic-gate 		 * If we're going to wedge the machine during debugger startup,
1907c478bd9Sstevel@tonic-gate 		 * at least let them know why it's going to wedge.
1917c478bd9Sstevel@tonic-gate 		 */
192ae115bc7Smrj 		cmn_err(CE_WARN, "retrying of kmdb allocation of 0x%lx bytes",
1937c478bd9Sstevel@tonic-gate 		    (ulong_t)needed);
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 		base = kmem_zalloc(needed, KM_SLEEP);
1967c478bd9Sstevel@tonic-gate 	}
1977c478bd9Sstevel@tonic-gate 
198ae115bc7Smrj 	kdi_dvec->dv_memavail(base, needed);
1997c478bd9Sstevel@tonic-gate 	kctl.kctl_mrbase = base;
2007c478bd9Sstevel@tonic-gate 	kctl.kctl_mrsize = needed;
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate void
kctl_cleanup(void)2047c478bd9Sstevel@tonic-gate kctl_cleanup(void)
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate 	uint_t state = kctl_set_state(KCTL_ST_DEACTIVATING);
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	kctl_dprintf("cleaning up from state %d", state);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	ASSERT(kctl.kctl_boot_loaded == 0);
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	switch (state) {
2137c478bd9Sstevel@tonic-gate 	case KCTL_ST_ACTIVE:
2147c478bd9Sstevel@tonic-gate 		boothowto &= ~RB_DEBUG;
2157c478bd9Sstevel@tonic-gate 		/* XXX there's a race here */
2167c478bd9Sstevel@tonic-gate 		kdi_dvec = NULL;
2177c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	case KCTL_ST_DBG_ACTIVATED:
2207c478bd9Sstevel@tonic-gate 		KCTL_PROM_LOCK;
2217c478bd9Sstevel@tonic-gate 		kmdb_deactivate();
2227c478bd9Sstevel@tonic-gate 		KCTL_PROM_UNLOCK;
2237c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	case KCTL_ST_THREAD_STARTED:
2267c478bd9Sstevel@tonic-gate 		if (curthread != kctl.kctl_wr_thr) {
2277c478bd9Sstevel@tonic-gate 			kctl_wr_thr_stop();
2287c478bd9Sstevel@tonic-gate 			kctl_wr_thr_join();
2297c478bd9Sstevel@tonic-gate 		}
2307c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	case KCTL_ST_MOD_NOTIFIERS:
2337c478bd9Sstevel@tonic-gate 		kctl_mod_notify_unreg();
2347c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	case KCTL_ST_KCTL_PREACTIVATED:
2377c478bd9Sstevel@tonic-gate 		kctl_depreactivate_isadep();
2387c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	case KCTL_ST_INITIALIZED:
2417c478bd9Sstevel@tonic-gate 		/* There's no kmdb_fini */
2427c478bd9Sstevel@tonic-gate 	case KCTL_ST_DSEG_ALLOCED:
2437c478bd9Sstevel@tonic-gate 		kctl_dseg_free(kctl.kctl_dseg, kctl.kctl_dseg_size);
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 		if (kctl.kctl_mrbase != NULL)
2467c478bd9Sstevel@tonic-gate 			kmem_free(kctl.kctl_mrbase, kctl.kctl_mrsize);
2477c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	kctl.kctl_state = KCTL_ST_INACTIVE;
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate static void
kctl_startup_modules(void)2547c478bd9Sstevel@tonic-gate kctl_startup_modules(void)
2557c478bd9Sstevel@tonic-gate {
2567c478bd9Sstevel@tonic-gate 	struct modctl *modp;
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	/*
2597c478bd9Sstevel@tonic-gate 	 * Normal module load and unload is now available.  Prior to this point,
2607c478bd9Sstevel@tonic-gate 	 * we could only load modules, and that only when the debugger was being
2617c478bd9Sstevel@tonic-gate 	 * initialized.
2627c478bd9Sstevel@tonic-gate 	 *
2637c478bd9Sstevel@tonic-gate 	 * We'll need to prepare the modules we've already loaded (if any) for
2647c478bd9Sstevel@tonic-gate 	 * the brave new world in which boot is unmapped.
2657c478bd9Sstevel@tonic-gate 	 */
2667c478bd9Sstevel@tonic-gate 	kctl_dmod_sync();
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	/*
2697c478bd9Sstevel@tonic-gate 	 * Process any outstanding loads or unloads and prepare for automatic
2707c478bd9Sstevel@tonic-gate 	 * module loading and unloading.
2717c478bd9Sstevel@tonic-gate 	 */
2727c478bd9Sstevel@tonic-gate 	(void) kctl_wr_process();
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	kctl_mod_notify_reg();
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_MOD_NOTIFIERS);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	modp = &modules;
2797c478bd9Sstevel@tonic-gate 	do {
2807c478bd9Sstevel@tonic-gate 		kctl_mod_loaded(modp);
2817c478bd9Sstevel@tonic-gate 	} while ((modp = modp->mod_next) != &modules);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate static void
kctl_startup_thread(void)2857c478bd9Sstevel@tonic-gate kctl_startup_thread(void)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate 	/*
2887c478bd9Sstevel@tonic-gate 	 * Create the worker thread, which will handle future requests from the
2897c478bd9Sstevel@tonic-gate 	 * debugger.
2907c478bd9Sstevel@tonic-gate 	 */
2917c478bd9Sstevel@tonic-gate 	kctl_wr_thr_start();
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_THREAD_STARTED);
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate static int
kctl_startup_boot(void)2977c478bd9Sstevel@tonic-gate kctl_startup_boot(void)
2987c478bd9Sstevel@tonic-gate {
2997c478bd9Sstevel@tonic-gate 	struct modctl_list *lp, **lpp;
3007c478bd9Sstevel@tonic-gate 	int rc;
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	if (kctl_wr_process() < 0) {
3037c478bd9Sstevel@tonic-gate 		kctl_warn("kmdb: failed to load modules");
3047c478bd9Sstevel@tonic-gate 		return (-1);
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	mutex_enter(&mod_lock);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	for (lpp = kobj_linkmaps; *lpp != NULL; lpp++) {
3107c478bd9Sstevel@tonic-gate 		for (lp = *lpp; lp != NULL; lp = lp->modl_next) {
3117c478bd9Sstevel@tonic-gate 			if ((rc = kctl_mod_decompress(lp->modl_modp)) != 0) {
3127c478bd9Sstevel@tonic-gate 				kctl_warn("kmdb: failed to decompress CTF data "
3137c478bd9Sstevel@tonic-gate 				    "for %s: %s", lp->modl_modp->mod_modname,
3147c478bd9Sstevel@tonic-gate 				    ctf_errmsg(rc));
3157c478bd9Sstevel@tonic-gate 			}
3167c478bd9Sstevel@tonic-gate 		}
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	mutex_exit(&mod_lock);
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	return (0);
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate static int
kctl_startup_preactivate(void * romp,const char * cfg,const char ** argv)3257c478bd9Sstevel@tonic-gate kctl_startup_preactivate(void *romp, const char *cfg, const char **argv)
3267c478bd9Sstevel@tonic-gate {
3277c478bd9Sstevel@tonic-gate 	kmdb_auxv_t kav;
3287c478bd9Sstevel@tonic-gate 	int rc;
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	kctl_auxv_init(&kav, cfg, argv, romp);
3317c478bd9Sstevel@tonic-gate 	KCTL_PROM_LOCK;
3327c478bd9Sstevel@tonic-gate 	rc = kmdb_init(kctl.kctl_execname, &kav);
3337c478bd9Sstevel@tonic-gate 	KCTL_PROM_UNLOCK;
3347c478bd9Sstevel@tonic-gate 	kctl_auxv_fini(&kav);
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	if (rc < 0)
3377c478bd9Sstevel@tonic-gate 		return (EMDB_KNOLOAD);
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_INITIALIZED);
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	if (kctl_preactivate_isadep() != 0)
3427c478bd9Sstevel@tonic-gate 		return (EIO);
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_KCTL_PREACTIVATED);
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	return (0);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate static int
kctl_startup_activate(uint_t flags)3507c478bd9Sstevel@tonic-gate kctl_startup_activate(uint_t flags)
3517c478bd9Sstevel@tonic-gate {
3527c478bd9Sstevel@tonic-gate 	kdi_debugvec_t *dvec;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	KCTL_PROM_LOCK;
3557c478bd9Sstevel@tonic-gate 	kmdb_activate(&dvec, flags);
3567c478bd9Sstevel@tonic-gate 	KCTL_PROM_UNLOCK;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_DBG_ACTIVATED);
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	/*
3617c478bd9Sstevel@tonic-gate 	 * fill in a few remaining debugvec entries.
3627c478bd9Sstevel@tonic-gate 	 */
3637c478bd9Sstevel@tonic-gate 	dvec->dv_kctl_modavail = kctl_startup_modules;
3647c478bd9Sstevel@tonic-gate 	dvec->dv_kctl_thravail = kctl_startup_thread;
3657c478bd9Sstevel@tonic-gate 	dvec->dv_kctl_memavail = kctl_memavail;
3667c478bd9Sstevel@tonic-gate 
367ae115bc7Smrj 	kctl_activate_isadep(dvec);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	kdi_dvec = dvec;
3707c478bd9Sstevel@tonic-gate 	membar_producer();
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	boothowto |= RB_DEBUG;
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_ACTIVE);
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	return (0);
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate static int
kctl_state_check(uint_t state,uint_t ok_state)3807c478bd9Sstevel@tonic-gate kctl_state_check(uint_t state, uint_t ok_state)
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate 	if (state == ok_state)
3837c478bd9Sstevel@tonic-gate 		return (0);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	if (state == KCTL_ST_INACTIVE)
3867c478bd9Sstevel@tonic-gate 		return (EMDB_KINACTIVE);
3877c478bd9Sstevel@tonic-gate 	else if (kctl.kctl_state > KCTL_ST_INACTIVE &&
3887c478bd9Sstevel@tonic-gate 	    kctl.kctl_state < KCTL_ST_ACTIVE)
3897c478bd9Sstevel@tonic-gate 		return (EMDB_KACTIVATING);
3907c478bd9Sstevel@tonic-gate 	else if (kctl.kctl_state == KCTL_ST_ACTIVE)
3917c478bd9Sstevel@tonic-gate 		return (EMDB_KACTIVE);
3927c478bd9Sstevel@tonic-gate 	else if (kctl.kctl_state == KCTL_ST_DEACTIVATING)
3937c478bd9Sstevel@tonic-gate 		return (EMDB_KDEACTIVATING);
3947c478bd9Sstevel@tonic-gate 	else
3957c478bd9Sstevel@tonic-gate 		return (EINVAL);
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate int
kctl_deactivate(void)3997c478bd9Sstevel@tonic-gate kctl_deactivate(void)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate 	int rc;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	mutex_enter(&kctl.kctl_lock);
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	if (kctl.kctl_boot_loaded) {
4067c478bd9Sstevel@tonic-gate 		rc = EMDB_KNOUNLOAD;
4077c478bd9Sstevel@tonic-gate 		goto deactivate_done;
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	if ((rc = kctl_state_check(kctl.kctl_state, KCTL_ST_ACTIVE)) != 0)
4117c478bd9Sstevel@tonic-gate 		goto deactivate_done;
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	kmdb_kdi_set_unload_request();
414ae115bc7Smrj 	kmdb_kdi_kmdb_enter();
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	/*
4177c478bd9Sstevel@tonic-gate 	 * The debugger will pass the request to the work thread, which will
4187c478bd9Sstevel@tonic-gate 	 * stop itself.
4197c478bd9Sstevel@tonic-gate 	 */
4207c478bd9Sstevel@tonic-gate 	kctl_wr_thr_join();
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate deactivate_done:
4237c478bd9Sstevel@tonic-gate 	mutex_exit(&kctl.kctl_lock);
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	return (rc);
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate /*
4297c478bd9Sstevel@tonic-gate  * Called from krtld, this indicates that the user loaded kmdb at boot.  We
4307c478bd9Sstevel@tonic-gate  * track activation states, but we don't attempt to clean up if activation
4317c478bd9Sstevel@tonic-gate  * fails, because boot debugger load failures are fatal.
4327c478bd9Sstevel@tonic-gate  *
4337c478bd9Sstevel@tonic-gate  * Further complicating matters, various kernel routines, such as bcopy and
4347c478bd9Sstevel@tonic-gate  * mutex_enter, assume the presence of some basic state.  On SPARC, it's the
4357c478bd9Sstevel@tonic-gate  * presence of a valid curthread pointer.  On AMD64, it's a valid curcpu
4367c478bd9Sstevel@tonic-gate  * pointer in GSBASE.  We set up temporary versions of these before beginning
4377c478bd9Sstevel@tonic-gate  * activation, and tear them down when we're done.
4387c478bd9Sstevel@tonic-gate  */
4397c478bd9Sstevel@tonic-gate int
kctl_boot_activate(struct bootops * ops,void * romp,size_t memsz,const char ** argv)4407c478bd9Sstevel@tonic-gate kctl_boot_activate(struct bootops *ops, void *romp, size_t memsz,
4417c478bd9Sstevel@tonic-gate     const char **argv)
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate 	void *old;
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate #ifdef __lint
4467c478bd9Sstevel@tonic-gate 	{
4477c478bd9Sstevel@tonic-gate 	/*
4487c478bd9Sstevel@tonic-gate 	 * krtld does a name-based symbol lookup to find this routine.  It then
4497c478bd9Sstevel@tonic-gate 	 * casts the address it gets, calling the result.  We want to make sure
4507c478bd9Sstevel@tonic-gate 	 * that the call in krtld stays in sync with the prototype for this
4517c478bd9Sstevel@tonic-gate 	 * function, so we define a type (kctl_boot_activate_f) that matches the
4527c478bd9Sstevel@tonic-gate 	 * current prototype.  The following assignment ensures that the type
4537c478bd9Sstevel@tonic-gate 	 * still matches the declaration, with lint as the enforcer.
4547c478bd9Sstevel@tonic-gate 	 */
4557c478bd9Sstevel@tonic-gate 	kctl_boot_activate_f *kba = kctl_boot_activate;
4567c478bd9Sstevel@tonic-gate 	if (kba == NULL)	/* Make lint think kba is actually used */
4577c478bd9Sstevel@tonic-gate 		return (0);
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate #endif
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	old = kctl_boot_tmpinit();	/* Set up temporary state */
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	ASSERT(ops != NULL);
4647c478bd9Sstevel@tonic-gate 	kctl.kctl_boot_ops = ops;	/* must be set before kctl_init */
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	if (kctl_init() < 0)
4677c478bd9Sstevel@tonic-gate 		return (-1);
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	kctl.kctl_boot_loaded = 1;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	kctl_dprintf("beginning kmdb initialization");
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	if (memsz == 0)
4747c478bd9Sstevel@tonic-gate 		memsz = KCTL_MEM_GOALSZ;
4757c478bd9Sstevel@tonic-gate 
476ae115bc7Smrj 	kctl.kctl_dseg = kdi_segdebugbase;
477ae115bc7Smrj 	kctl.kctl_dseg_size =
478ae115bc7Smrj 	    memsz > kdi_segdebugsize ? kdi_segdebugsize : memsz;
4797c478bd9Sstevel@tonic-gate 	kctl.kctl_memgoalsz = memsz;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if (kctl_boot_dseg_alloc(kctl.kctl_dseg, kctl.kctl_dseg_size) < 0) {
482ae115bc7Smrj 		kctl_warn("kmdb: failed to allocate %lu-byte debugger area at "
483ae115bc7Smrj 		    "%p", kctl.kctl_dseg_size, (void *)kctl.kctl_dseg);
4847c478bd9Sstevel@tonic-gate 		return (-1);
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_DSEG_ALLOCED);
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	if (kctl_startup_preactivate(romp, NULL, argv) != 0 ||
4907c478bd9Sstevel@tonic-gate 	    kctl_startup_activate(KMDB_ACT_F_BOOT)) {
4917c478bd9Sstevel@tonic-gate 		kctl_warn("kmdb: failed to activate");
4927c478bd9Sstevel@tonic-gate 		return (-1);
4937c478bd9Sstevel@tonic-gate 	}
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	if (kctl_startup_boot() < 0)
4967c478bd9Sstevel@tonic-gate 		return (-1);
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	kctl_dprintf("finished with kmdb initialization");
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 	kctl_boot_tmpfini(old);
5017c478bd9Sstevel@tonic-gate 
502ae115bc7Smrj 	kctl.kctl_boot_ops = NULL;
503ae115bc7Smrj 
5047c478bd9Sstevel@tonic-gate 	return (0);
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate int
kctl_modload_activate(size_t memsz,const char * cfg,uint_t flags)5087c478bd9Sstevel@tonic-gate kctl_modload_activate(size_t memsz, const char *cfg, uint_t flags)
5097c478bd9Sstevel@tonic-gate {
5107c478bd9Sstevel@tonic-gate 	int rc;
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	mutex_enter(&kctl.kctl_lock);
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	if ((rc = kctl_state_check(kctl.kctl_state, KCTL_ST_INACTIVE)) != 0) {
5157c478bd9Sstevel@tonic-gate 		if ((flags & KMDB_F_AUTO_ENTRY) && rc == EMDB_KACTIVE) {
516ae115bc7Smrj 			kmdb_kdi_kmdb_enter();
5177c478bd9Sstevel@tonic-gate 			rc = 0;
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 		mutex_exit(&kctl.kctl_lock);
5217c478bd9Sstevel@tonic-gate 		return (rc);
5227c478bd9Sstevel@tonic-gate 	}
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	kctl.kctl_flags = flags;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	if (memsz == 0)
5277c478bd9Sstevel@tonic-gate 		memsz = KCTL_MEM_GOALSZ;
5287c478bd9Sstevel@tonic-gate 
529ae115bc7Smrj 	kctl.kctl_dseg = kdi_segdebugbase;
530ae115bc7Smrj 	kctl.kctl_dseg_size =
531ae115bc7Smrj 	    memsz > kdi_segdebugsize ? kdi_segdebugsize : memsz;
5327c478bd9Sstevel@tonic-gate 	kctl.kctl_memgoalsz = memsz;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	if ((rc = kctl_dseg_alloc(kctl.kctl_dseg, kctl.kctl_dseg_size)) != 0)
5357c478bd9Sstevel@tonic-gate 		goto activate_fail;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	(void) kctl_set_state(KCTL_ST_DSEG_ALLOCED);
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	if ((rc = kctl_startup_preactivate(NULL, cfg, NULL)) != 0)
5407c478bd9Sstevel@tonic-gate 		goto activate_fail;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	kctl_startup_modules();
5437c478bd9Sstevel@tonic-gate 	kctl_startup_thread();
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	if ((rc = kctl_startup_activate(0)) != 0)
5467c478bd9Sstevel@tonic-gate 		goto activate_fail;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	kctl_memavail();	/* Must be after kdi_dvec is set */
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	if (kctl.kctl_flags & KMDB_F_AUTO_ENTRY)
551ae115bc7Smrj 		kmdb_kdi_kmdb_enter();
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	mutex_exit(&kctl.kctl_lock);
5547c478bd9Sstevel@tonic-gate 	return (0);
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate activate_fail:
5577c478bd9Sstevel@tonic-gate 	kctl_cleanup();
5587c478bd9Sstevel@tonic-gate 	mutex_exit(&kctl.kctl_lock);
5597c478bd9Sstevel@tonic-gate 	return (rc);
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate /*
5637c478bd9Sstevel@tonic-gate  * This interface will be called when drv/kmdb loads.  When we get the call, one
5647c478bd9Sstevel@tonic-gate  * of two things will have happened:
5657c478bd9Sstevel@tonic-gate  *
5667c478bd9Sstevel@tonic-gate  *  1. The debugger was loaded at boot.  We've progressed far enough into boot
5677c478bd9Sstevel@tonic-gate  *     as to allow drv/kmdb to be loaded as a non-primary.  Invocation of this
5687c478bd9Sstevel@tonic-gate  *     interface is the signal to the debugger that it can start allowing things
5697c478bd9Sstevel@tonic-gate  *     like dmod loading and automatic CTF decompression - things which require
5707c478bd9Sstevel@tonic-gate  *     the system services that have now been started.
5717c478bd9Sstevel@tonic-gate  *
5727c478bd9Sstevel@tonic-gate  *  2. The debugger was loaded after boot.  mdb opened /dev/kmdb, causing
5737c478bd9Sstevel@tonic-gate  *     drv/kmdb to load, followed by misc/kmdb.  Nothing has been set up yet,
5747c478bd9Sstevel@tonic-gate  *     so we need to initialize.  Activation will occur separately, so we don't
5757c478bd9Sstevel@tonic-gate  *     have to worry about that.
5767c478bd9Sstevel@tonic-gate  */
5777c478bd9Sstevel@tonic-gate int
kctl_attach(dev_info_t * dip)5787c478bd9Sstevel@tonic-gate kctl_attach(dev_info_t *dip)
5797c478bd9Sstevel@tonic-gate {
5807c478bd9Sstevel@tonic-gate 	kctl.kctl_drv_dip = dip;
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	return (0);
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate int
kctl_detach(void)5867c478bd9Sstevel@tonic-gate kctl_detach(void)
5877c478bd9Sstevel@tonic-gate {
5887c478bd9Sstevel@tonic-gate 	return (kctl.kctl_state == KCTL_ST_INACTIVE ? 0 : EBUSY);
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = {
5927c478bd9Sstevel@tonic-gate 	&mod_miscops,
5937c478bd9Sstevel@tonic-gate 	KMDB_VERSION
5947c478bd9Sstevel@tonic-gate };
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
5977c478bd9Sstevel@tonic-gate 	MODREV_1,
5987c478bd9Sstevel@tonic-gate 	(void *)&modlmisc,
5997c478bd9Sstevel@tonic-gate 	NULL
6007c478bd9Sstevel@tonic-gate };
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate /*
6037c478bd9Sstevel@tonic-gate  * Invoked only when debugger is loaded via modload - not invoked when debugger
6047c478bd9Sstevel@tonic-gate  * is loaded at boot.  kctl_boot_activate needs to call anything (aside from
6057c478bd9Sstevel@tonic-gate  * mod_install) this function does.
6067c478bd9Sstevel@tonic-gate  */
6077c478bd9Sstevel@tonic-gate int
_init(void)6087c478bd9Sstevel@tonic-gate _init(void)
6097c478bd9Sstevel@tonic-gate {
6107c478bd9Sstevel@tonic-gate 	if (kctl_init() < 0)
6117c478bd9Sstevel@tonic-gate 		return (EINVAL);
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)6177c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
6187c478bd9Sstevel@tonic-gate {
6197c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
6207c478bd9Sstevel@tonic-gate }
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate int
_fini(void)6237c478bd9Sstevel@tonic-gate _fini(void)
6247c478bd9Sstevel@tonic-gate {
6257c478bd9Sstevel@tonic-gate 	kctl_fini();
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
6287c478bd9Sstevel@tonic-gate }
629