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