xref: /onnv-gate/usr/src/cmd/mdb/sparc/kmdb/kmdb_kdi_isadep.c (revision 5584:4b4402ef936b)
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
51772Sjl139090  * Common Development and Distribution License (the "License").
61772Sjl139090  * 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 /*
223446Smrj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * SPARC-specific portions of the KDI
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/kdi_impl.h>
340Sstevel@tonic-gate 
353446Smrj #include <kmdb/kaif.h>
360Sstevel@tonic-gate #include <kmdb/kmdb_dpi.h>
370Sstevel@tonic-gate #include <kmdb/kmdb_promif.h>
380Sstevel@tonic-gate #include <mdb/mdb_debug.h>
390Sstevel@tonic-gate #include <mdb/mdb_err.h>
400Sstevel@tonic-gate #include <mdb/mdb.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #define	KDI_XC_RETRIES			10
430Sstevel@tonic-gate 
440Sstevel@tonic-gate static size_t kdi_dcache_size;
450Sstevel@tonic-gate static size_t kdi_dcache_linesize;
460Sstevel@tonic-gate static size_t kdi_icache_size;
470Sstevel@tonic-gate static size_t kdi_icache_linesize;
480Sstevel@tonic-gate 
490Sstevel@tonic-gate static uint_t kdi_max_cpu_freq;
500Sstevel@tonic-gate static uint_t kdi_sticks_per_usec;
510Sstevel@tonic-gate 
523446Smrj /* XXX	needs to go into a header */
533446Smrj 
540Sstevel@tonic-gate void
kdi_usecwait(clock_t n)550Sstevel@tonic-gate kdi_usecwait(clock_t n)
560Sstevel@tonic-gate {
570Sstevel@tonic-gate 	mdb.m_kdi->mkdi_tickwait(n * kdi_sticks_per_usec);
580Sstevel@tonic-gate }
590Sstevel@tonic-gate 
600Sstevel@tonic-gate static int
kdi_cpu_ready_iter(int (* cb)(int,void *),void * arg)610Sstevel@tonic-gate kdi_cpu_ready_iter(int (*cb)(int, void *), void *arg)
620Sstevel@tonic-gate {
630Sstevel@tonic-gate 	return (mdb.m_kdi->mkdi_cpu_ready_iter(cb, arg));
640Sstevel@tonic-gate }
650Sstevel@tonic-gate 
660Sstevel@tonic-gate static int
kdi_xc_one(int cpuid,void (* cb)(void))670Sstevel@tonic-gate kdi_xc_one(int cpuid, void (*cb)(void))
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	return (mdb.m_kdi->mkdi_xc_one(cpuid, (void (*)())cb, NULL, NULL));
700Sstevel@tonic-gate }
710Sstevel@tonic-gate 
720Sstevel@tonic-gate /*ARGSUSED1*/
730Sstevel@tonic-gate static int
kdi_init_cpus_cb(pnode_t node,void * arg,void * result)74789Sahrens kdi_init_cpus_cb(pnode_t node, void *arg, void *result)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate 	/*
770Sstevel@tonic-gate 	 * Sun4v dosen't support virtual address cache
780Sstevel@tonic-gate 	 */
790Sstevel@tonic-gate #ifndef	sun4v
800Sstevel@tonic-gate 	int dcache_size, dcache_linesize;
810Sstevel@tonic-gate 	int icache_size, icache_linesize;
820Sstevel@tonic-gate #endif
830Sstevel@tonic-gate 	int cpu_freq;
840Sstevel@tonic-gate 
850Sstevel@tonic-gate #ifndef	sun4v
861772Sjl139090 	/* Get the real cpu property node if needed */
871772Sjl139090 	node = kmdb_prom_getcpu_propnode(node);
881772Sjl139090 
890Sstevel@tonic-gate 	/*
900Sstevel@tonic-gate 	 * data cache
910Sstevel@tonic-gate 	 */
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	if (kmdb_prom_getprop(node, "dcache-size",
940Sstevel@tonic-gate 	    (caddr_t)&dcache_size) == -1 &&
950Sstevel@tonic-gate 	    kmdb_prom_getprop(node, "l1-dcache-size",
960Sstevel@tonic-gate 	    (caddr_t)&dcache_size) == -1)
970Sstevel@tonic-gate 		fail("can't get dcache size for node %x\n", node);
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	if (kdi_dcache_size == 0 || dcache_size > kdi_dcache_size)
1000Sstevel@tonic-gate 		kdi_dcache_size = dcache_size;
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	if (kmdb_prom_getprop(node, "dcache-line-size",
1030Sstevel@tonic-gate 	    (caddr_t)&dcache_linesize) == -1 &&
1040Sstevel@tonic-gate 	    kmdb_prom_getprop(node, "l1-dcache-line-size",
1050Sstevel@tonic-gate 	    (caddr_t)&dcache_linesize) == -1)
1060Sstevel@tonic-gate 		fail("can't get dcache line size for node %x\n", node);
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	if (kdi_dcache_linesize == 0 || dcache_linesize < kdi_dcache_linesize)
1090Sstevel@tonic-gate 		kdi_dcache_linesize = dcache_linesize;
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	/*
1120Sstevel@tonic-gate 	 * instruction cache
1130Sstevel@tonic-gate 	 */
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	if (kmdb_prom_getprop(node, "icache-size",
1160Sstevel@tonic-gate 	    (caddr_t)&icache_size) == -1 &&
1170Sstevel@tonic-gate 	    kmdb_prom_getprop(node, "l1-icache-size",
1180Sstevel@tonic-gate 	    (caddr_t)&icache_size) == -1)
1190Sstevel@tonic-gate 		fail("can't get icache size for node %x\n", node);
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	if (kdi_icache_size == 0 || icache_size > kdi_icache_size)
1220Sstevel@tonic-gate 		kdi_icache_size = icache_size;
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	if (kmdb_prom_getprop(node, "icache-line-size",
1250Sstevel@tonic-gate 	    (caddr_t)&icache_linesize) == -1 &&
1260Sstevel@tonic-gate 	    kmdb_prom_getprop(node, "l1-icache-line-size",
1270Sstevel@tonic-gate 	    (caddr_t)&icache_linesize) == -1)
1280Sstevel@tonic-gate 		fail("can't get icache size for node %x\n", node);
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	if (kdi_icache_linesize == 0 || icache_linesize < kdi_icache_linesize)
1310Sstevel@tonic-gate 		kdi_icache_linesize = icache_linesize;
1320Sstevel@tonic-gate #endif
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	if (kmdb_prom_getprop(node, "clock-frequency",
1350Sstevel@tonic-gate 	    (caddr_t)&cpu_freq) == -1) {
1360Sstevel@tonic-gate 		fail("can't get cpu frequency for node %x\n", node);
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	kdi_max_cpu_freq = MAX(kdi_max_cpu_freq, cpu_freq);
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	return (0);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate /*
1450Sstevel@tonic-gate  * Called on an individual CPU.  Tries to send it off to the state saver if it
1460Sstevel@tonic-gate  * hasn't already entered the debugger.  Returns non-zero if it *fails* to stop
1470Sstevel@tonic-gate  * the CPU.
1480Sstevel@tonic-gate  */
1490Sstevel@tonic-gate static int
kdi_halt_cpu(int cpuid,void * state_saverp)1500Sstevel@tonic-gate kdi_halt_cpu(int cpuid, void *state_saverp)
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate 	void (*state_saver)(void) = (void (*)(void))state_saverp;
1530Sstevel@tonic-gate 	int state = kmdb_dpi_get_cpu_state(cpuid);
1540Sstevel@tonic-gate 	const char *msg;
1550Sstevel@tonic-gate 	int rc = 0;
1560Sstevel@tonic-gate 	int res;
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	if (state != DPI_CPU_STATE_MASTER && state != DPI_CPU_STATE_SLAVE) {
1590Sstevel@tonic-gate 		res = kdi_xc_one(cpuid, state_saver);
1600Sstevel@tonic-gate 			rc = 1;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 		if (res == KDI_XC_RES_OK)
1630Sstevel@tonic-gate 			msg = "accepted the";
1640Sstevel@tonic-gate 		else {
1650Sstevel@tonic-gate 			if (res == KDI_XC_RES_BUSY)
1660Sstevel@tonic-gate 				msg = "too busy for";
1670Sstevel@tonic-gate 			else if (res == KDI_XC_RES_NACK)
1680Sstevel@tonic-gate 				msg = "NACKED the";
1690Sstevel@tonic-gate 			else
1700Sstevel@tonic-gate 				msg = "errored the";
1710Sstevel@tonic-gate 		}
1720Sstevel@tonic-gate 		mdb_dprintf(MDB_DBG_KDI, "CPU %d %s halt\n", cpuid, msg);
1730Sstevel@tonic-gate 	}
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	return (rc);
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate /*ARGSUSED1*/
1790Sstevel@tonic-gate static int
kdi_report_unhalted(int cpuid,void * junk)1800Sstevel@tonic-gate kdi_report_unhalted(int cpuid, void *junk)
1810Sstevel@tonic-gate {
1820Sstevel@tonic-gate 	int state = kmdb_dpi_get_cpu_state(cpuid);
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	if (state != DPI_CPU_STATE_MASTER && state != DPI_CPU_STATE_SLAVE)
1850Sstevel@tonic-gate 		mdb_warn("CPU %d: stop failed\n", cpuid);
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	return (0);
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate /*ARGSUSED*/
1910Sstevel@tonic-gate void
kmdb_kdi_stop_slaves(int my_cpuid,int doxc)1923446Smrj kmdb_kdi_stop_slaves(int my_cpuid, int doxc)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate 	int i;
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	for (i = 0; i < KDI_XC_RETRIES; i++) {
1973446Smrj 		if (kdi_cpu_ready_iter(kdi_halt_cpu,
1983446Smrj 		    (void *)kaif_slave_entry) == 0)
1990Sstevel@tonic-gate 			break;
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 		kdi_usecwait(2000);
2020Sstevel@tonic-gate 	}
2030Sstevel@tonic-gate 	(void) kdi_cpu_ready_iter(kdi_report_unhalted, NULL);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate 
2063446Smrj void
kmdb_kdi_start_slaves(void)2073446Smrj kmdb_kdi_start_slaves(void)
2083446Smrj {
2093446Smrj }
2103446Smrj 
2113446Smrj void
kmdb_kdi_slave_wait(void)2123446Smrj kmdb_kdi_slave_wait(void)
2133446Smrj {
2143446Smrj }
2153446Smrj 
2160Sstevel@tonic-gate int
kmdb_kdi_get_stick(uint64_t * stickp)2170Sstevel@tonic-gate kmdb_kdi_get_stick(uint64_t *stickp)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate 	return (mdb.m_kdi->mkdi_get_stick(stickp));
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate caddr_t
kmdb_kdi_get_trap_vatotte(void)2230Sstevel@tonic-gate kmdb_kdi_get_trap_vatotte(void)
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate 	return ((caddr_t)mdb.m_kdi->mkdi_trap_vatotte);
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate void
kmdb_kdi_kernpanic(struct regs * regs,uint_t tt)2290Sstevel@tonic-gate kmdb_kdi_kernpanic(struct regs *regs, uint_t tt)
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate 	uintptr_t args[2];
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	args[0] = (uintptr_t)regs;
2340Sstevel@tonic-gate 	args[1] = tt;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	(void) kmdb_dpi_call((uintptr_t)mdb.m_kdi->mkdi_kernpanic, 2, args);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate /*ARGSUSED*/
2400Sstevel@tonic-gate void
kmdb_kdi_init_isadep(kdi_t * kdi,kmdb_auxv_t * kav)2410Sstevel@tonic-gate kmdb_kdi_init_isadep(kdi_t *kdi, kmdb_auxv_t *kav)
2420Sstevel@tonic-gate {
2433446Smrj 	kdi_dcache_size = kdi_dcache_linesize =
2443446Smrj 	    kdi_icache_size = kdi_icache_linesize = 0;
2453446Smrj 
2463446Smrj 	kdi_max_cpu_freq = kdi_sticks_per_usec = 0;
2473446Smrj 
2483446Smrj 	mdb_dprintf(MDB_DBG_KDI, "Initializing CPUs\n");
2493446Smrj 
2503446Smrj 	kmdb_prom_walk_cpus(kdi_init_cpus_cb, NULL, NULL);
2513446Smrj 
2523446Smrj 	/*
2533446Smrj 	 * If we can't find one, guess high.  The CPU frequency is going to be
2543446Smrj 	 * used to determine the length of various delays, such as the mondo
2553446Smrj 	 * interrupt retry delay.  Too long is generally better than too short.
2563446Smrj 	 */
2573446Smrj 	if (kdi_max_cpu_freq == 0) {
2583446Smrj 		mdb_dprintf(MDB_DBG_KDI, "No CPU freq found - assuming "
2593446Smrj 		    "500MHz\n");
2603446Smrj 		kdi_max_cpu_freq = 500 * MICROSEC;
2613446Smrj 	}
2623446Smrj 
2633446Smrj 	kdi_sticks_per_usec =
2643446Smrj 	    MAX((kdi_max_cpu_freq + (MICROSEC - 1)) / MICROSEC, 1);
2653446Smrj 
2663446Smrj 	mdb.m_kdi->mkdi_cpu_init(kdi_dcache_size, kdi_dcache_linesize,
2673446Smrj 	    kdi_icache_size, kdi_icache_linesize);
268*5584Sjimand 
269*5584Sjimand #ifndef sun4v
270*5584Sjimand 	kmdb_prom_preserve_kctx_init();
271*5584Sjimand #endif /* sun4v */
272*5584Sjimand 
2730Sstevel@tonic-gate }
274