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