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 * 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
kaif_enter_mon(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 *
kaif_cpuid2save(int cpuid)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
kaif_get_cpu_state(int cpuid)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
kaif_get_master_cpuid(void)164 kaif_get_master_cpuid(void)
165 {
166 return (kaif_master_cpuid);
167 }
168
169 static mdb_tgt_gregset_t *
kaif_kdi_to_gregs(int cpuid)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 *
kaif_get_gregs(int cpuid)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 *
kaif_find_regp(const char * regname)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 (®s->kregs[rd->rd_num]);
226 }
227
228 (void) set_errno(ENOENT);
229 return (NULL);
230 }
231
232 /*ARGSUSED*/
233 static int
kaif_get_register(const char * regname,kreg_t * valp)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
kaif_set_register(const char * regname,kreg_t val)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
kaif_brkpt_arm(uintptr_t addr,mdb_instr_t * instrp)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
kaif_brkpt_disarm(uintptr_t addr,mdb_instr_t instrp)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
kaif_wapt_validate(kmdb_wapt_t * wp)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
kaif_wapt_reserve(kmdb_wapt_t * wp)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
kaif_wapt_release(kmdb_wapt_t * wp)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
kaif_wapt_arm(kmdb_wapt_t * wp)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
kaif_wapt_disarm(kmdb_wapt_t * wp)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
kaif_wapt_match(kmdb_wapt_t * wp)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
kaif_step(void)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 /*
607 * The target has already configured the chip for branch step, leaving us to
608 * actually make the machine go. Due to a number of issues involving
609 * the potential alteration of system state via instructions like sti, cli,
610 * pushfl, and popfl, we're going to treat this like a normal system resume.
611 * All CPUs will be released, on the kernel's IDT. Our primary concern is
612 * the alteration/storage of our TF'd EFLAGS via pushfl and popfl. There's no
613 * real workaround - we don't have opcode breakpoints - so the best we can do is
614 * to ensure that the world won't end if someone does bad things to EFLAGS.
615 *
616 * Two things can happen:
617 * 1. EFLAGS.TF may be cleared, either maliciously or via a popfl from saved
618 * state. The CPU will continue execution beyond the branch, and will not
619 * reenter the debugger unless brought/sent in by other means.
620 * 2. Someone may pushlf the TF'd EFLAGS, and may stash a copy of it somewhere.
621 * When the saved version is popfl'd back into place, the debugger will be
622 * re-entered on a single-step trap.
623 */
624 static void
kaif_step_branch(void)625 kaif_step_branch(void)
626 {
627 kreg_t fl;
628
629 (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl);
630 (void) kmdb_dpi_set_register(FLAGS_REG_NAME,
631 (fl | (1 << KREG_EFLAGS_TF_SHIFT)));
632
633 kmdb_dpi_resume_master();
634
635 (void) kmdb_dpi_set_register(FLAGS_REG_NAME, fl);
636 }
637
638 /*ARGSUSED*/
639 static uintptr_t
kaif_call(uintptr_t funcva,uint_t argc,const uintptr_t argv[])640 kaif_call(uintptr_t funcva, uint_t argc, const uintptr_t argv[])
641 {
642 return (kaif_invoke(funcva, argc, argv));
643 }
644
645 static void
dump_crumb(kdi_crumb_t * krmp)646 dump_crumb(kdi_crumb_t *krmp)
647 {
648 kdi_crumb_t krm;
649
650 if (mdb_vread(&krm, sizeof (kdi_crumb_t), (uintptr_t)krmp) !=
651 sizeof (kdi_crumb_t)) {
652 warn("failed to read crumb at %p", krmp);
653 return;
654 }
655
656 mdb_printf("state: ");
657 switch (krm.krm_cpu_state) {
658 case KAIF_CPU_STATE_MASTER:
659 mdb_printf("M");
660 break;
661 case KAIF_CPU_STATE_SLAVE:
662 mdb_printf("S");
663 break;
664 default:
665 mdb_printf("%d", krm.krm_cpu_state);
666 }
667
668 mdb_printf(" trapno %3d sp %08x flag %d pc %p %A\n",
669 krm.krm_trapno, krm.krm_sp, krm.krm_flag, krm.krm_pc, krm.krm_pc);
670 }
671
672 static void
dump_crumbs(kaif_cpusave_t * save)673 dump_crumbs(kaif_cpusave_t *save)
674 {
675 int i;
676
677 for (i = KDI_NCRUMBS; i > 0; i--) {
678 uint_t idx = (save->krs_curcrumbidx + i) % KDI_NCRUMBS;
679 dump_crumb(&save->krs_crumbs[idx]);
680 }
681 }
682
683 static void
kaif_dump_crumbs(uintptr_t addr,int cpuid)684 kaif_dump_crumbs(uintptr_t addr, int cpuid)
685 {
686 int i;
687
688 if (addr != NULL) {
689 /* dump_crumb will protect us against bogus addresses */
690 dump_crumb((kdi_crumb_t *)addr);
691
692 } else if (cpuid != -1) {
693 if (cpuid < 0 || cpuid >= kaif_ncpusave)
694 return;
695
696 dump_crumbs(&kaif_cpusave[cpuid]);
697
698 } else {
699 for (i = 0; i < kaif_ncpusave; i++) {
700 kaif_cpusave_t *save = &kaif_cpusave[i];
701
702 if (save->krs_cpu_state == KAIF_CPU_STATE_NONE)
703 continue;
704
705 mdb_printf("%sCPU %d crumbs: (curidx %d)\n",
706 (i == 0 ? "" : "\n"), i, save->krs_curcrumbidx);
707
708 dump_crumbs(save);
709 }
710 }
711 }
712
713 static void
kaif_modchg_register(void (* func)(struct modctl *,int))714 kaif_modchg_register(void (*func)(struct modctl *, int))
715 {
716 kaif_modchg_cb = func;
717 }
718
719 static void
kaif_modchg_cancel(void)720 kaif_modchg_cancel(void)
721 {
722 ASSERT(kaif_modchg_cb != NULL);
723
724 kaif_modchg_cb = NULL;
725 }
726
727 static void
kaif_msr_add(const kdi_msr_t * msrs)728 kaif_msr_add(const kdi_msr_t *msrs)
729 {
730 kdi_msr_t *save;
731 size_t nr_msrs = 0;
732 size_t i;
733
734 while (msrs[nr_msrs].msr_num != 0)
735 nr_msrs++;
736 /* we want to copy the terminating kdi_msr_t too */
737 nr_msrs++;
738
739 save = mdb_zalloc(sizeof (kdi_msr_t) * nr_msrs * kaif_ncpusave,
740 UM_SLEEP);
741
742 for (i = 0; i < kaif_ncpusave; i++)
743 bcopy(msrs, &save[nr_msrs * i], sizeof (kdi_msr_t) * nr_msrs);
744
745 kmdb_kdi_set_debug_msrs(save);
746 }
747
748 static uint64_t
kaif_msr_get(int cpuid,uint_t num)749 kaif_msr_get(int cpuid, uint_t num)
750 {
751 kdi_cpusave_t *save;
752 kdi_msr_t *msr;
753 int i;
754
755 if ((save = kaif_cpuid2save(cpuid)) == NULL)
756 return (-1); /* errno is set for us */
757
758 msr = save->krs_msr;
759
760 for (i = 0; msr[i].msr_num != 0; i++) {
761 if (msr[i].msr_num == num && (msr[i].msr_type & KDI_MSR_READ))
762 return (msr[i].kdi_msr_val);
763 }
764
765 return (0);
766 }
767
768 void
kaif_trap_set_debugger(void)769 kaif_trap_set_debugger(void)
770 {
771 kmdb_kdi_idt_switch(NULL);
772 }
773
774 void
kaif_trap_set_saved(kaif_cpusave_t * cpusave)775 kaif_trap_set_saved(kaif_cpusave_t *cpusave)
776 {
777 kmdb_kdi_idt_switch(cpusave);
778 }
779
780 static void
kaif_vmready(void)781 kaif_vmready(void)
782 {
783 }
784
785 void
kaif_memavail(caddr_t base,size_t len)786 kaif_memavail(caddr_t base, size_t len)
787 {
788 int ret;
789 /*
790 * In the unlikely event that someone is stepping through this routine,
791 * we need to make sure that the KDI knows about the new range before
792 * umem gets it. That way the entry code can recognize stacks
793 * allocated from the new region.
794 */
795 kmdb_kdi_memrange_add(base, len);
796 ret = mdb_umem_add(base, len);
797 ASSERT(ret == 0);
798 }
799
800 void
kaif_mod_loaded(struct modctl * modp)801 kaif_mod_loaded(struct modctl *modp)
802 {
803 if (kaif_modchg_cb != NULL)
804 kaif_modchg_cb(modp, 1);
805 }
806
807 void
kaif_mod_unloading(struct modctl * modp)808 kaif_mod_unloading(struct modctl *modp)
809 {
810 if (kaif_modchg_cb != NULL)
811 kaif_modchg_cb(modp, 0);
812 }
813
814 void
kaif_handle_fault(greg_t trapno,greg_t pc,greg_t sp,int cpuid)815 kaif_handle_fault(greg_t trapno, greg_t pc, greg_t sp, int cpuid)
816 {
817 kmdb_dpi_handle_fault((kreg_t)trapno, (kreg_t)pc,
818 (kreg_t)sp, cpuid);
819 }
820
821 static kdi_debugvec_t kaif_dvec = {
822 NULL, /* dv_kctl_vmready */
823 NULL, /* dv_kctl_memavail */
824 NULL, /* dv_kctl_modavail */
825 NULL, /* dv_kctl_thravail */
826 kaif_vmready,
827 kaif_memavail,
828 kaif_mod_loaded,
829 kaif_mod_unloading,
830 kaif_handle_fault
831 };
832
833 void
kaif_kdi_entry(kdi_cpusave_t * cpusave)834 kaif_kdi_entry(kdi_cpusave_t *cpusave)
835 {
836 int ret = kaif_main_loop(cpusave);
837 ASSERT(ret == KAIF_CPU_CMD_RESUME ||
838 ret == KAIF_CPU_CMD_RESUME_MASTER);
839 }
840
841 /*ARGSUSED*/
842 void
kaif_activate(kdi_debugvec_t ** dvecp,uint_t flags)843 kaif_activate(kdi_debugvec_t **dvecp, uint_t flags)
844 {
845 kmdb_kdi_activate(kaif_kdi_entry, kaif_cpusave, kaif_ncpusave);
846 *dvecp = &kaif_dvec;
847 }
848
849 static int
kaif_init(kmdb_auxv_t * kav)850 kaif_init(kmdb_auxv_t *kav)
851 {
852 /* Allocate the per-CPU save areas */
853 kaif_cpusave = mdb_zalloc(sizeof (kaif_cpusave_t) * kav->kav_ncpu,
854 UM_SLEEP);
855 kaif_ncpusave = kav->kav_ncpu;
856
857 kaif_modchg_cb = NULL;
858
859 kaif_waptmap = 0;
860
861 kaif_trap_switch = (kav->kav_flags & KMDB_AUXV_FL_NOTRPSWTCH) == 0;
862
863 return (0);
864 }
865
866 dpi_ops_t kmdb_dpi_ops = {
867 kaif_init,
868 kaif_activate,
869 kmdb_kdi_deactivate,
870 kaif_enter_mon,
871 kaif_modchg_register,
872 kaif_modchg_cancel,
873 kaif_get_cpu_state,
874 kaif_get_master_cpuid,
875 kaif_get_gregs,
876 kaif_get_register,
877 kaif_set_register,
878 kaif_brkpt_arm,
879 kaif_brkpt_disarm,
880 kaif_wapt_validate,
881 kaif_wapt_reserve,
882 kaif_wapt_release,
883 kaif_wapt_arm,
884 kaif_wapt_disarm,
885 kaif_wapt_match,
886 kaif_step,
887 kaif_step_branch,
888 kaif_call,
889 kaif_dump_crumbs,
890 kaif_msr_add,
891 kaif_msr_get,
892 };
893