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 * Copyright 2018 Joyent, Inc.
26 */
27
28/*
29 * The debugger/"PROM" interface layer
30 *
31 * It makes more sense on SPARC. In reality, these interfaces deal with three
32 * things: setting break/watchpoints, stepping, and interfacing with the KDI to
33 * set up kmdb's IDT handlers.
34 */
35
36#include <kmdb/kmdb_dpi_impl.h>
37#include <kmdb/kmdb_kdi.h>
38#include <kmdb/kmdb_umemglue.h>
39#include <kmdb/kaif.h>
40#include <kmdb/kmdb_io.h>
41#include <kmdb/kaif_start.h>
42#include <mdb/mdb_err.h>
43#include <mdb/mdb_debug.h>
44#include <mdb/mdb_isautil.h>
45#include <mdb/mdb_io_impl.h>
46#include <mdb/mdb_kreg_impl.h>
47#include <mdb/mdb.h>
48
49#include <sys/types.h>
50#include <sys/bitmap.h>
51#include <sys/termios.h>
52#include <sys/kdi_impl.h>
53#include <sys/sysmacros.h>
54
55/*
56 * This is the area containing the saved state when we enter
57 * via kmdb's IDT entries.
58 */
59kdi_cpusave_t	*kaif_cpusave;
60int		kaif_ncpusave;
61kdi_drreg_t	kaif_drreg;
62
63uint32_t	kaif_waptmap;
64
65int		kaif_trap_switch;
66
67void (*kaif_modchg_cb)(struct modctl *, int);
68
69enum {
70	M_SYSRET	= 0x07, /* after M_ESC */
71	M_ESC		= 0x0f,
72	M_SYSEXIT	= 0x35, /* after M_ESC */
73	M_REX_LO	= 0x40, /* first REX prefix */
74	M_REX_HI	= 0x4f, /* last REX prefix */
75	M_PUSHF		= 0x9c,	/* pushfl and pushfq */
76	M_POPF		= 0x9d,	/* popfl and popfq */
77	M_INT3		= 0xcc,
78	M_INTX		= 0xcd,
79	M_INTO		= 0xce,
80	M_IRET		= 0xcf,
81	M_CLI		= 0xfa,
82	M_STI		= 0xfb
83};
84
85#define	KAIF_BREAKPOINT_INSTR	M_INT3
86
87#define	KAIF_WPPRIV2ID(wp)	(int)(uintptr_t)((wp)->wp_priv)
88
89#ifdef __amd64
90#define	FLAGS_REG_NAME		"rflags"
91#else
92#define	FLAGS_REG_NAME		"eflags"
93#endif
94
95/*
96 * Called during normal debugger operation and during debugger faults.
97 */
98static void
99kaif_enter_mon(void)
100{
101	char c;
102
103	for (;;) {
104		mdb_iob_printf(mdb.m_out,
105		    "%s: Do you really want to reboot? (y/n) ",
106		    mdb.m_pname);
107		mdb_iob_flush(mdb.m_out);
108		mdb_iob_clearlines(mdb.m_out);
109
110		c = kmdb_getchar();
111
112		if (c == 'n' || c == 'N' || c == CTRL('c'))
113			return;
114		else if (c == 'y' || c == 'Y') {
115			mdb_iob_printf(mdb.m_out, "Rebooting...\n");
116
117			kmdb_dpi_reboot();
118		}
119	}
120}
121
122static kaif_cpusave_t *
123kaif_cpuid2save(int cpuid)
124{
125	kaif_cpusave_t *save;
126
127	if (cpuid == DPI_MASTER_CPUID)
128		return (&kaif_cpusave[kaif_master_cpuid]);
129
130	if (cpuid < 0 || cpuid >= kaif_ncpusave) {
131		(void) set_errno(EINVAL);
132		return (NULL);
133	}
134
135	save = &kaif_cpusave[cpuid];
136
137	if (save->krs_cpu_state != KAIF_CPU_STATE_MASTER &&
138	    save->krs_cpu_state != KAIF_CPU_STATE_SLAVE) {
139		(void) set_errno(EINVAL);
140		return (NULL);
141	}
142
143	return (save);
144}
145
146static int
147kaif_get_cpu_state(int cpuid)
148{
149	kaif_cpusave_t *save;
150
151	if ((save = kaif_cpuid2save(cpuid)) == NULL)
152		return (-1); /* errno is set for us */
153
154	switch (save->krs_cpu_state) {
155	case KAIF_CPU_STATE_MASTER:
156		return (DPI_CPU_STATE_MASTER);
157	case KAIF_CPU_STATE_SLAVE:
158		return (DPI_CPU_STATE_SLAVE);
159	default:
160		return (set_errno(EINVAL));
161	}
162}
163
164static int
165kaif_get_master_cpuid(void)
166{
167	return (kaif_master_cpuid);
168}
169
170static mdb_tgt_gregset_t *
171kaif_kdi_to_gregs(int cpuid)
172{
173	kaif_cpusave_t *save;
174
175	if ((save = kaif_cpuid2save(cpuid)) == NULL)
176		return (NULL); /* errno is set for us */
177
178	/*
179	 * The saved registers are actually identical to an mdb_tgt_gregset,
180	 * so we can directly cast here.
181	 */
182	return ((mdb_tgt_gregset_t *)save->krs_gregs);
183}
184
185static const mdb_tgt_gregset_t *
186kaif_get_gregs(int cpuid)
187{
188	return (kaif_kdi_to_gregs(cpuid));
189}
190
191typedef struct kaif_reg_synonyms {
192	const char *rs_syn;
193	const char *rs_name;
194} kaif_reg_synonyms_t;
195
196static kreg_t *
197kaif_find_regp(const char *regname)
198{
199	static const kaif_reg_synonyms_t synonyms[] = {
200#ifdef __amd64
201	    { "pc", "rip" },
202	    { "sp", "rsp" },
203	    { "fp", "rbp" },
204#else
205	    { "pc", "eip" },
206	    { "sp", "esp" },
207	    { "fp", "ebp" },
208#endif
209	    { "tt", "trapno" }
210	};
211	mdb_tgt_gregset_t *regs;
212	int i;
213
214	if ((regs = kaif_kdi_to_gregs(DPI_MASTER_CPUID)) == NULL)
215		return (NULL);
216
217	for (i = 0; i < sizeof (synonyms) / sizeof (synonyms[0]); i++) {
218		if (strcmp(synonyms[i].rs_syn, regname) == 0)
219			regname = synonyms[i].rs_name;
220	}
221
222	for (i = 0; mdb_isa_kregs[i].rd_name != NULL; i++) {
223		const mdb_tgt_regdesc_t *rd = &mdb_isa_kregs[i];
224
225		if (strcmp(rd->rd_name, regname) == 0)
226			return (&regs->kregs[rd->rd_num]);
227	}
228
229	(void) set_errno(ENOENT);
230	return (NULL);
231}
232
233/*ARGSUSED*/
234static int
235kaif_get_register(const char *regname, kreg_t *valp)
236{
237	kreg_t *regp;
238
239	if ((regp = kaif_find_regp(regname)) == NULL)
240		return (-1);
241
242	*valp = *regp;
243
244	return (0);
245}
246
247static int
248kaif_set_register(const char *regname, kreg_t val)
249{
250	kreg_t *regp;
251
252	if ((regp = kaif_find_regp(regname)) == NULL)
253		return (-1);
254
255	*regp = val;
256
257	return (0);
258}
259
260/*
261 * Refuse to single-step or break within any stub that loads a user %cr3 value.
262 * As the KDI traps are not careful to restore such a %cr3, this can all go
263 * wrong, both spectacularly and subtly.
264 */
265static boolean_t
266kaif_toxic_text(uintptr_t addr)
267{
268	static GElf_Sym toxic_syms[2] = { 0, };
269	size_t i;
270
271	if (toxic_syms[0].st_name == 0) {
272		if (mdb_tgt_lookup_by_name(mdb.m_target, MDB_TGT_OBJ_EXEC,
273		    "tr_iret_user", &toxic_syms[0], NULL) != 0)
274			warn("couldn't find tr_iret_user\n");
275		if (mdb_tgt_lookup_by_name(mdb.m_target, MDB_TGT_OBJ_EXEC,
276		    "tr_mmu_flush_user_range", &toxic_syms[1], NULL) != 0)
277			warn("couldn't find tr_mmu_flush_user_range\n");
278	}
279
280	for (i = 0; i < ARRAY_SIZE(toxic_syms); i++) {
281		if (addr >= toxic_syms[i].st_value &&
282		    addr - toxic_syms[i].st_value < toxic_syms[i].st_size)
283			return (B_TRUE);
284	}
285
286	return (B_FALSE);
287}
288
289static int
290kaif_brkpt_arm(uintptr_t addr, mdb_instr_t *instrp)
291{
292	mdb_instr_t bkpt = KAIF_BREAKPOINT_INSTR;
293
294	if (kaif_toxic_text(addr)) {
295		warn("%a cannot be a breakpoint target\n", addr);
296		return (set_errno(EMDB_TGTNOTSUP));
297	}
298
299	if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_I, instrp,
300	    sizeof (mdb_instr_t), addr) != sizeof (mdb_instr_t))
301		return (-1); /* errno is set for us */
302
303	if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_I, &bkpt,
304	    sizeof (mdb_instr_t), addr) != sizeof (mdb_instr_t))
305		return (-1); /* errno is set for us */
306
307	return (0);
308}
309
310static int
311kaif_brkpt_disarm(uintptr_t addr, mdb_instr_t instrp)
312{
313	if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_I, &instrp,
314	    sizeof (mdb_instr_t), addr) != sizeof (mdb_instr_t))
315		return (-1); /* errno is set for us */
316
317	return (0);
318}
319
320/*
321 * Intel watchpoints are even more fun than SPARC ones.  The Intel architecture
322 * manuals refer to watchpoints as breakpoints.  For consistency  with the
323 * terminology used in other portions of kmdb, we will, however, refer to them
324 * as watchpoints.
325 *
326 * Execute, data write, I/O read/write, and data read/write watchpoints are
327 * supported by the hardware.  Execute watchpoints must be one byte in length,
328 * and must be placed on the first byte of the instruction to be watched.
329 * Lengths of other watchpoints are more varied.
330 *
331 * Given that we already have a breakpoint facility, and given the restrictions
332 * placed on execute watchpoints, we're going to disallow the creation of
333 * execute watchpoints.  The others will be fully supported.  See the Debugging
334 * chapter in both the IA32 and AMD64 System Programming books for more details.
335 */
336
337#ifdef __amd64
338#define	WAPT_DATA_MAX_SIZE	8
339#define	WAPT_DATA_SIZES_MSG	"1, 2, 4, or 8"
340#else
341#define	WAPT_DATA_MAX_SIZE	4
342#define	WAPT_DATA_SIZES_MSG	"1, 2, or 4"
343#endif
344
345static int
346kaif_wapt_validate(kmdb_wapt_t *wp)
347{
348	if (wp->wp_type == DPI_WAPT_TYPE_IO) {
349		if (wp->wp_wflags != (MDB_TGT_WA_R | MDB_TGT_WA_W)) {
350			warn("I/O port watchpoints must be read/write\n");
351			return (set_errno(EINVAL));
352		}
353
354		if (wp->wp_size != 1 && wp->wp_size != 2 && wp->wp_size != 4) {
355			warn("I/O watchpoint size must be 1, 2, or 4 bytes\n");
356			return (set_errno(EINVAL));
357		}
358
359	} else if (wp->wp_type == DPI_WAPT_TYPE_PHYS) {
360		warn("physical address watchpoints are not supported on this "
361		    "platform\n");
362		return (set_errno(EMDB_TGTHWNOTSUP));
363
364	} else {
365		if (wp->wp_wflags != (MDB_TGT_WA_R | MDB_TGT_WA_W) &&
366		    wp->wp_wflags != MDB_TGT_WA_W) {
367			warn("watchpoints must be read/write or write-only\n");
368			return (set_errno(EINVAL));
369		}
370
371		if ((wp->wp_size & -(wp->wp_size)) != wp->wp_size ||
372		    wp->wp_size > WAPT_DATA_MAX_SIZE) {
373			warn("data watchpoint size must be " WAPT_DATA_SIZES_MSG
374			    " bytes\n");
375			return (set_errno(EINVAL));
376		}
377
378	}
379
380	if (wp->wp_addr & (wp->wp_size - 1)) {
381		warn("%lu-byte watchpoints must be %lu-byte aligned\n",
382		    (ulong_t)wp->wp_size, (ulong_t)wp->wp_size);
383		return (set_errno(EINVAL));
384	}
385
386	return (0);
387}
388
389static int
390kaif_wapt_reserve(kmdb_wapt_t *wp)
391{
392	int id;
393
394	for (id = 0; id <= KDI_MAXWPIDX; id++) {
395		if (!BT_TEST(&kaif_waptmap, id)) {
396			/* found one */
397			BT_SET(&kaif_waptmap, id);
398			wp->wp_priv = (void *)(uintptr_t)id;
399			return (0);
400		}
401	}
402
403	return (set_errno(EMDB_WPTOOMANY));
404}
405
406static void
407kaif_wapt_release(kmdb_wapt_t *wp)
408{
409	int id = KAIF_WPPRIV2ID(wp);
410
411	ASSERT(BT_TEST(&kaif_waptmap, id));
412	BT_CLEAR(&kaif_waptmap, id);
413}
414
415/*ARGSUSED*/
416static void
417kaif_wapt_arm(kmdb_wapt_t *wp)
418{
419	uint_t rw;
420	int hwid = KAIF_WPPRIV2ID(wp);
421
422	ASSERT(BT_TEST(&kaif_waptmap, hwid));
423
424	if (wp->wp_type == DPI_WAPT_TYPE_IO)
425		rw = KREG_DRCTL_WP_IORW;
426	else if (wp->wp_wflags & MDB_TGT_WA_R)
427		rw = KREG_DRCTL_WP_RW;
428	else if (wp->wp_wflags & MDB_TGT_WA_X)
429		rw = KREG_DRCTL_WP_EXEC;
430	else
431		rw = KREG_DRCTL_WP_WONLY;
432
433	kaif_drreg.dr_addr[hwid] = wp->wp_addr;
434
435	kaif_drreg.dr_ctl &= ~KREG_DRCTL_WP_MASK(hwid);
436	kaif_drreg.dr_ctl |= KREG_DRCTL_WP_LENRW(hwid, wp->wp_size - 1, rw);
437	kaif_drreg.dr_ctl |= KREG_DRCTL_WPEN(hwid);
438	kmdb_kdi_update_drreg(&kaif_drreg);
439}
440
441/*ARGSUSED*/
442static void
443kaif_wapt_disarm(kmdb_wapt_t *wp)
444{
445	int hwid = KAIF_WPPRIV2ID(wp);
446
447	ASSERT(BT_TEST(&kaif_waptmap, hwid));
448
449	kaif_drreg.dr_addr[hwid] = 0;
450	kaif_drreg.dr_ctl &= ~(KREG_DRCTL_WP_MASK(hwid) |
451	    KREG_DRCTL_WPEN_MASK(hwid));
452	kmdb_kdi_update_drreg(&kaif_drreg);
453}
454
455/*ARGSUSED*/
456static int
457kaif_wapt_match(kmdb_wapt_t *wp)
458{
459	int hwid = KAIF_WPPRIV2ID(wp);
460	uint32_t mask = KREG_DRSTAT_WP_MASK(hwid);
461	int n = 0;
462	int i;
463
464	ASSERT(BT_TEST(&kaif_waptmap, hwid));
465
466	for (i = 0; i < kaif_ncpusave; i++)
467		n += (kaif_cpusave[i].krs_dr.dr_stat & mask) != 0;
468
469	return (n);
470}
471
472static int
473kaif_step(void)
474{
475	kreg_t pc, fl, oldfl, newfl, sp;
476	mdb_tgt_addr_t npc;
477	mdb_instr_t instr;
478	int emulated = 0, rchk = 0;
479	size_t pcoff = 0;
480
481	(void) kmdb_dpi_get_register("pc", &pc);
482
483	if (kaif_toxic_text(pc)) {
484		warn("%a cannot be stepped\n", pc);
485		return (set_errno(EMDB_TGTNOTSUP));
486	}
487
488	if ((npc = mdb_dis_nextins(mdb.m_disasm, mdb.m_target,
489	    MDB_TGT_AS_VIRT_I, pc)) == pc) {
490		warn("failed to decode instruction at %a for step\n", pc);
491		return (set_errno(EINVAL));
492	}
493
494	/*
495	 * Stepping behavior depends on the type of instruction.  It does not
496	 * depend on the presence of a REX prefix, as the action we take for a
497	 * given instruction doesn't currently vary for 32-bit instructions
498	 * versus their 64-bit counterparts.
499	 */
500	do {
501		if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_I, &instr,
502		    sizeof (mdb_instr_t), pc + pcoff) != sizeof (mdb_instr_t)) {
503			warn("failed to read at %p for step",
504			    (void *)(pc + pcoff));
505			return (-1);
506		}
507	} while (pcoff++, (instr >= M_REX_LO && instr <= M_REX_HI && !rchk++));
508
509	switch (instr) {
510	case M_IRET:
511		warn("iret cannot be stepped\n");
512		return (set_errno(EMDB_TGTNOTSUP));
513
514	case M_INT3:
515	case M_INTX:
516	case M_INTO:
517		warn("int cannot be stepped\n");
518		return (set_errno(EMDB_TGTNOTSUP));
519
520	case M_ESC:
521		if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_I, &instr,
522		    sizeof (mdb_instr_t), pc + pcoff) != sizeof (mdb_instr_t)) {
523			warn("failed to read at %p for step",
524			    (void *)(pc + pcoff));
525			return (-1);
526		}
527
528		switch (instr) {
529		case M_SYSRET:
530			warn("sysret cannot be stepped\n");
531			return (set_errno(EMDB_TGTNOTSUP));
532		case M_SYSEXIT:
533			warn("sysexit cannot be stepped\n");
534			return (set_errno(EMDB_TGTNOTSUP));
535		}
536		break;
537
538	/*
539	 * Some instructions need to be emulated.  We need to prevent direct
540	 * manipulations of EFLAGS, so we'll emulate cli, sti.  pushfl and
541	 * popfl also receive special handling, as they manipulate both EFLAGS
542	 * and %esp.
543	 */
544	case M_CLI:
545		(void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl);
546		fl &= ~KREG_EFLAGS_IF_MASK;
547		(void) kmdb_dpi_set_register(FLAGS_REG_NAME, fl);
548
549		emulated = 1;
550		break;
551
552	case M_STI:
553		(void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl);
554		fl |= (1 << KREG_EFLAGS_IF_SHIFT);
555		(void) kmdb_dpi_set_register(FLAGS_REG_NAME, fl);
556
557		emulated = 1;
558		break;
559
560	case M_POPF:
561		/*
562		 * popfl will restore a pushed EFLAGS from the stack, and could
563		 * in so doing cause IF to be turned on, if only for a brief
564		 * period.  To avoid this, we'll secretly replace the stack's
565		 * EFLAGS with our decaffeinated brand.  We'll then manually
566		 * load our EFLAGS copy with the real verion after the step.
567		 */
568		(void) kmdb_dpi_get_register("sp", &sp);
569		(void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl);
570
571		if (mdb_tgt_aread(mdb.m_target, MDB_TGT_AS_VIRT_S, &newfl,
572		    sizeof (kreg_t), sp) != sizeof (kreg_t)) {
573			warn("failed to read " FLAGS_REG_NAME
574			    " at %p for popfl step\n", (void *)sp);
575			return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */
576		}
577
578		fl = (fl & ~KREG_EFLAGS_IF_MASK) | KREG_EFLAGS_TF_MASK;
579
580		if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_S, &fl,
581		    sizeof (kreg_t), sp) != sizeof (kreg_t)) {
582			warn("failed to update " FLAGS_REG_NAME
583			    " at %p for popfl step\n", (void *)sp);
584			return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */
585		}
586		break;
587	}
588
589	if (emulated) {
590		(void) kmdb_dpi_set_register("pc", npc);
591		return (0);
592	}
593
594	/* Do the step with IF off, and TF (step) on */
595	(void) kmdb_dpi_get_register(FLAGS_REG_NAME, &oldfl);
596	(void) kmdb_dpi_set_register(FLAGS_REG_NAME,
597	    ((oldfl | (1 << KREG_EFLAGS_TF_SHIFT)) & ~KREG_EFLAGS_IF_MASK));
598
599	kmdb_dpi_resume_master(); /* ... there and back again ... */
600
601	/* EFLAGS has now changed, and may require tuning */
602
603	switch (instr) {
604	case M_POPF:
605		/*
606		 * Use the EFLAGS we grabbed before the pop - see the pre-step
607		 * M_POPFL comment.
608		 */
609		(void) kmdb_dpi_set_register(FLAGS_REG_NAME, newfl);
610		return (0);
611
612	case M_PUSHF:
613		/*
614		 * We pushed our modified EFLAGS (with IF and TF turned off)
615		 * onto the stack.  Replace the pushed version with our
616		 * unmodified one.
617		 */
618		(void) kmdb_dpi_get_register("sp", &sp);
619
620		if (mdb_tgt_awrite(mdb.m_target, MDB_TGT_AS_VIRT_S, &oldfl,
621		    sizeof (kreg_t), sp) != sizeof (kreg_t)) {
622			warn("failed to update pushed " FLAGS_REG_NAME
623			    " at %p after pushfl step\n", (void *)sp);
624			return (set_errno(EMDB_TGTNOTSUP)); /* XXX ? */
625		}
626
627		/* Go back to using the EFLAGS we were using before the step */
628		(void) kmdb_dpi_set_register(FLAGS_REG_NAME, oldfl);
629		return (0);
630
631	default:
632		/*
633		 * The stepped instruction may have altered EFLAGS.  We only
634		 * really care about the value of IF, and we know the stepped
635		 * instruction didn't alter it, so we can simply copy the
636		 * pre-step value.  We'll also need to turn TF back off.
637		 */
638		(void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl);
639		(void) kmdb_dpi_set_register(FLAGS_REG_NAME,
640		    ((fl & ~(KREG_EFLAGS_TF_MASK|KREG_EFLAGS_IF_MASK)) |
641		    (oldfl & KREG_EFLAGS_IF_MASK)));
642		return (0);
643	}
644}
645
646/*ARGSUSED*/
647static uintptr_t
648kaif_call(uintptr_t funcva, uint_t argc, const uintptr_t argv[])
649{
650	return (kaif_invoke(funcva, argc, argv));
651}
652
653static void
654dump_crumb(kdi_crumb_t *krmp)
655{
656	kdi_crumb_t krm;
657
658	if (mdb_vread(&krm, sizeof (kdi_crumb_t), (uintptr_t)krmp) !=
659	    sizeof (kdi_crumb_t)) {
660		warn("failed to read crumb at %p", krmp);
661		return;
662	}
663
664	mdb_printf("state: ");
665	switch (krm.krm_cpu_state) {
666	case KAIF_CPU_STATE_MASTER:
667		mdb_printf("M");
668		break;
669	case KAIF_CPU_STATE_SLAVE:
670		mdb_printf("S");
671		break;
672	default:
673		mdb_printf("%d", krm.krm_cpu_state);
674	}
675
676	mdb_printf(" trapno %3d sp %08x flag %d pc %p %A\n",
677	    krm.krm_trapno, krm.krm_sp, krm.krm_flag, krm.krm_pc, krm.krm_pc);
678}
679
680static void
681dump_crumbs(kaif_cpusave_t *save)
682{
683	int i;
684
685	for (i = KDI_NCRUMBS; i > 0; i--) {
686		uint_t idx = (save->krs_curcrumbidx + i) % KDI_NCRUMBS;
687		dump_crumb(&save->krs_crumbs[idx]);
688	}
689}
690
691static void
692kaif_dump_crumbs(uintptr_t addr, int cpuid)
693{
694	int i;
695
696	if (addr != 0) {
697		/* dump_crumb will protect us against bogus addresses */
698		dump_crumb((kdi_crumb_t *)addr);
699
700	} else if (cpuid != -1) {
701		if (cpuid < 0 || cpuid >= kaif_ncpusave)
702			return;
703
704		dump_crumbs(&kaif_cpusave[cpuid]);
705
706	} else {
707		for (i = 0; i < kaif_ncpusave; i++) {
708			kaif_cpusave_t *save = &kaif_cpusave[i];
709
710			if (save->krs_cpu_state == KAIF_CPU_STATE_NONE)
711				continue;
712
713			mdb_printf("%sCPU %d crumbs: (curidx %d)\n",
714			    (i == 0 ? "" : "\n"), i, save->krs_curcrumbidx);
715
716			dump_crumbs(save);
717		}
718	}
719}
720
721static void
722kaif_modchg_register(void (*func)(struct modctl *, int))
723{
724	kaif_modchg_cb = func;
725}
726
727static void
728kaif_modchg_cancel(void)
729{
730	ASSERT(kaif_modchg_cb != NULL);
731
732	kaif_modchg_cb = NULL;
733}
734
735void
736kaif_trap_set_debugger(void)
737{
738	kmdb_kdi_idt_switch(NULL);
739}
740
741void
742kaif_trap_set_saved(kaif_cpusave_t *cpusave)
743{
744	kmdb_kdi_idt_switch(cpusave);
745}
746
747static void
748kaif_vmready(void)
749{
750}
751
752void
753kaif_memavail(caddr_t base, size_t len)
754{
755	int ret;
756	/*
757	 * In the unlikely event that someone is stepping through this routine,
758	 * we need to make sure that the KDI knows about the new range before
759	 * umem gets it.  That way the entry code can recognize stacks
760	 * allocated from the new region.
761	 */
762	kmdb_kdi_memrange_add(base, len);
763	ret = mdb_umem_add(base, len);
764	ASSERT(ret == 0);
765}
766
767void
768kaif_mod_loaded(struct modctl *modp)
769{
770	if (kaif_modchg_cb != NULL)
771		kaif_modchg_cb(modp, 1);
772}
773
774void
775kaif_mod_unloading(struct modctl *modp)
776{
777	if (kaif_modchg_cb != NULL)
778		kaif_modchg_cb(modp, 0);
779}
780
781void
782kaif_handle_fault(greg_t trapno, greg_t pc, greg_t sp, int cpuid)
783{
784	kmdb_dpi_handle_fault((kreg_t)trapno, (kreg_t)pc,
785	    (kreg_t)sp, cpuid);
786}
787
788static kdi_debugvec_t kaif_dvec = {
789	NULL,			/* dv_kctl_vmready */
790	NULL,			/* dv_kctl_memavail */
791	NULL,			/* dv_kctl_modavail */
792	NULL,			/* dv_kctl_thravail */
793	kaif_vmready,
794	kaif_memavail,
795	kaif_mod_loaded,
796	kaif_mod_unloading,
797	kaif_handle_fault
798};
799
800void
801kaif_kdi_entry(kdi_cpusave_t *cpusave)
802{
803	int ret = kaif_main_loop(cpusave);
804	ASSERT(ret == KAIF_CPU_CMD_RESUME ||
805	    ret == KAIF_CPU_CMD_RESUME_MASTER);
806}
807
808/*ARGSUSED*/
809void
810kaif_activate(kdi_debugvec_t **dvecp, uint_t flags)
811{
812	kmdb_kdi_activate(kaif_kdi_entry, kaif_cpusave, kaif_ncpusave);
813	*dvecp = &kaif_dvec;
814}
815
816static int
817kaif_init(kmdb_auxv_t *kav)
818{
819	/* Allocate the per-CPU save areas */
820	kaif_cpusave = mdb_zalloc(sizeof (kaif_cpusave_t) * kav->kav_ncpu,
821	    UM_SLEEP);
822	kaif_ncpusave = kav->kav_ncpu;
823
824	kaif_modchg_cb = NULL;
825
826	kaif_waptmap = 0;
827
828	kaif_trap_switch = (kav->kav_flags & KMDB_AUXV_FL_NOTRPSWTCH) == 0;
829
830	return (0);
831}
832
833dpi_ops_t kmdb_dpi_ops = {
834	kaif_init,
835	kaif_activate,
836	kmdb_kdi_deactivate,
837	kaif_enter_mon,
838	kaif_modchg_register,
839	kaif_modchg_cancel,
840	kaif_get_cpu_state,
841	kaif_get_master_cpuid,
842	kaif_get_gregs,
843	kaif_get_register,
844	kaif_set_register,
845	kaif_brkpt_arm,
846	kaif_brkpt_disarm,
847	kaif_wapt_validate,
848	kaif_wapt_reserve,
849	kaif_wapt_release,
850	kaif_wapt_arm,
851	kaif_wapt_disarm,
852	kaif_wapt_match,
853	kaif_step,
854	kaif_call,
855	kaif_dump_crumbs,
856};
857