1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28/*
29 * SPARC-specific portions of the KDI
30 */
31
32#include <sys/types.h>
33#include <sys/kdi_impl.h>
34
35#include <kmdb/kaif.h>
36#include <kmdb/kmdb_dpi.h>
37#include <kmdb/kmdb_promif.h>
38#include <mdb/mdb_debug.h>
39#include <mdb/mdb_err.h>
40#include <mdb/mdb.h>
41
42#define	KDI_XC_RETRIES			10
43
44static size_t kdi_dcache_size;
45static size_t kdi_dcache_linesize;
46static size_t kdi_icache_size;
47static size_t kdi_icache_linesize;
48
49static uint_t kdi_max_cpu_freq;
50static uint_t kdi_sticks_per_usec;
51
52/* XXX	needs to go into a header */
53
54void
55kdi_usecwait(clock_t n)
56{
57	mdb.m_kdi->mkdi_tickwait(n * kdi_sticks_per_usec);
58}
59
60static int
61kdi_cpu_ready_iter(int (*cb)(int, void *), void *arg)
62{
63	return (mdb.m_kdi->mkdi_cpu_ready_iter(cb, arg));
64}
65
66static int
67kdi_xc_one(int cpuid, void (*cb)(void))
68{
69	return (mdb.m_kdi->mkdi_xc_one(cpuid, (void (*)())cb, NULL, NULL));
70}
71
72/*ARGSUSED1*/
73static int
74kdi_init_cpus_cb(pnode_t node, void *arg, void *result)
75{
76	/*
77	 * Sun4v dosen't support virtual address cache
78	 */
79#ifndef	sun4v
80	int dcache_size, dcache_linesize;
81	int icache_size, icache_linesize;
82#endif
83	int cpu_freq;
84
85#ifndef	sun4v
86	/* Get the real cpu property node if needed */
87	node = kmdb_prom_getcpu_propnode(node);
88
89	/*
90	 * data cache
91	 */
92
93	if (kmdb_prom_getprop(node, "dcache-size",
94	    (caddr_t)&dcache_size) == -1 &&
95	    kmdb_prom_getprop(node, "l1-dcache-size",
96	    (caddr_t)&dcache_size) == -1)
97		fail("can't get dcache size for node %x\n", node);
98
99	if (kdi_dcache_size == 0 || dcache_size > kdi_dcache_size)
100		kdi_dcache_size = dcache_size;
101
102	if (kmdb_prom_getprop(node, "dcache-line-size",
103	    (caddr_t)&dcache_linesize) == -1 &&
104	    kmdb_prom_getprop(node, "l1-dcache-line-size",
105	    (caddr_t)&dcache_linesize) == -1)
106		fail("can't get dcache line size for node %x\n", node);
107
108	if (kdi_dcache_linesize == 0 || dcache_linesize < kdi_dcache_linesize)
109		kdi_dcache_linesize = dcache_linesize;
110
111	/*
112	 * instruction cache
113	 */
114
115	if (kmdb_prom_getprop(node, "icache-size",
116	    (caddr_t)&icache_size) == -1 &&
117	    kmdb_prom_getprop(node, "l1-icache-size",
118	    (caddr_t)&icache_size) == -1)
119		fail("can't get icache size for node %x\n", node);
120
121	if (kdi_icache_size == 0 || icache_size > kdi_icache_size)
122		kdi_icache_size = icache_size;
123
124	if (kmdb_prom_getprop(node, "icache-line-size",
125	    (caddr_t)&icache_linesize) == -1 &&
126	    kmdb_prom_getprop(node, "l1-icache-line-size",
127	    (caddr_t)&icache_linesize) == -1)
128		fail("can't get icache size for node %x\n", node);
129
130	if (kdi_icache_linesize == 0 || icache_linesize < kdi_icache_linesize)
131		kdi_icache_linesize = icache_linesize;
132#endif
133
134	if (kmdb_prom_getprop(node, "clock-frequency",
135	    (caddr_t)&cpu_freq) == -1) {
136		fail("can't get cpu frequency for node %x\n", node);
137	}
138
139	kdi_max_cpu_freq = MAX(kdi_max_cpu_freq, cpu_freq);
140
141	return (0);
142}
143
144/*
145 * Called on an individual CPU.  Tries to send it off to the state saver if it
146 * hasn't already entered the debugger.  Returns non-zero if it *fails* to stop
147 * the CPU.
148 */
149static int
150kdi_halt_cpu(int cpuid, void *state_saverp)
151{
152	void (*state_saver)(void) = (void (*)(void))state_saverp;
153	int state = kmdb_dpi_get_cpu_state(cpuid);
154	const char *msg;
155	int rc = 0;
156	int res;
157
158	if (state != DPI_CPU_STATE_MASTER && state != DPI_CPU_STATE_SLAVE) {
159		res = kdi_xc_one(cpuid, state_saver);
160			rc = 1;
161
162		if (res == KDI_XC_RES_OK)
163			msg = "accepted the";
164		else {
165			if (res == KDI_XC_RES_BUSY)
166				msg = "too busy for";
167			else if (res == KDI_XC_RES_NACK)
168				msg = "NACKED the";
169			else
170				msg = "errored the";
171		}
172		mdb_dprintf(MDB_DBG_KDI, "CPU %d %s halt\n", cpuid, msg);
173	}
174
175	return (rc);
176}
177
178/*ARGSUSED1*/
179static int
180kdi_report_unhalted(int cpuid, void *junk)
181{
182	int state = kmdb_dpi_get_cpu_state(cpuid);
183
184	if (state != DPI_CPU_STATE_MASTER && state != DPI_CPU_STATE_SLAVE)
185		mdb_warn("CPU %d: stop failed\n", cpuid);
186
187	return (0);
188}
189
190/*ARGSUSED*/
191void
192kmdb_kdi_stop_slaves(int my_cpuid, int doxc)
193{
194	int i;
195
196	for (i = 0; i < KDI_XC_RETRIES; i++) {
197		if (kdi_cpu_ready_iter(kdi_halt_cpu,
198		    (void *)kaif_slave_entry) == 0)
199			break;
200
201		kdi_usecwait(2000);
202	}
203	(void) kdi_cpu_ready_iter(kdi_report_unhalted, NULL);
204}
205
206void
207kmdb_kdi_start_slaves(void)
208{
209}
210
211void
212kmdb_kdi_slave_wait(void)
213{
214}
215
216int
217kmdb_kdi_get_stick(uint64_t *stickp)
218{
219	return (mdb.m_kdi->mkdi_get_stick(stickp));
220}
221
222caddr_t
223kmdb_kdi_get_trap_vatotte(void)
224{
225	return ((caddr_t)mdb.m_kdi->mkdi_trap_vatotte);
226}
227
228void
229kmdb_kdi_kernpanic(struct regs *regs, uint_t tt)
230{
231	uintptr_t args[2];
232
233	args[0] = (uintptr_t)regs;
234	args[1] = tt;
235
236	(void) kmdb_dpi_call((uintptr_t)mdb.m_kdi->mkdi_kernpanic, 2, args);
237}
238
239/*ARGSUSED*/
240void
241kmdb_kdi_init_isadep(kdi_t *kdi, kmdb_auxv_t *kav)
242{
243	kdi_dcache_size = kdi_dcache_linesize =
244	    kdi_icache_size = kdi_icache_linesize = 0;
245
246	kdi_max_cpu_freq = kdi_sticks_per_usec = 0;
247
248	mdb_dprintf(MDB_DBG_KDI, "Initializing CPUs\n");
249
250	kmdb_prom_walk_cpus(kdi_init_cpus_cb, NULL, NULL);
251
252	/*
253	 * If we can't find one, guess high.  The CPU frequency is going to be
254	 * used to determine the length of various delays, such as the mondo
255	 * interrupt retry delay.  Too long is generally better than too short.
256	 */
257	if (kdi_max_cpu_freq == 0) {
258		mdb_dprintf(MDB_DBG_KDI, "No CPU freq found - assuming "
259		    "500MHz\n");
260		kdi_max_cpu_freq = 500 * MICROSEC;
261	}
262
263	kdi_sticks_per_usec =
264	    MAX((kdi_max_cpu_freq + (MICROSEC - 1)) / MICROSEC, 1);
265
266	mdb.m_kdi->mkdi_cpu_init(kdi_dcache_size, kdi_dcache_linesize,
267	    kdi_icache_size, kdi_icache_linesize);
268
269#ifndef sun4v
270	kmdb_prom_preserve_kctx_init();
271#endif /* sun4v */
272
273}
274