xref: /illumos-gate/usr/src/cmd/mdb/intel/kmdb/kvm_isadep.c (revision 3350c9c925acb5854315e9d992703db756886095)
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  * Copyright 2025 Oxide Computer Company
27  */
28 
29 /*
30  * isa-dependent portions of the kmdb target
31  */
32 
33 #include <kmdb/kvm.h>
34 #include <kmdb/kmdb_kdi.h>
35 #include <kmdb/kmdb_asmutil.h>
36 #include <mdb/mdb_debug.h>
37 #include <mdb/mdb_stack.h>
38 #include <mdb/mdb_err.h>
39 #include <mdb/mdb_list.h>
40 #include <mdb/mdb_target_impl.h>
41 #include <mdb/mdb_isautil.h>
42 #include <mdb/mdb_kreg_impl.h>
43 #include <mdb/mdb.h>
44 
45 #include <sys/types.h>
46 #include <sys/frame.h>
47 #include <sys/trap.h>
48 #include <sys/bitmap.h>
49 #include <sys/pci_impl.h>
50 
51 /* Higher than the highest trap number for which we have a defined specifier */
52 #define	KMT_MAXTRAPNO	0x20
53 
54 #define	IOPORTLIMIT	0xffff	/* XXX find a new home for this */
55 
56 const char *
kmt_def_dismode(void)57 kmt_def_dismode(void)
58 {
59 #ifdef	__amd64
60 	return ("amd64");
61 #else
62 	return ("ia32");
63 #endif
64 }
65 
66 int
kmt_step_out_validate(mdb_tgt_t * t,uintptr_t pc)67 kmt_step_out_validate(mdb_tgt_t *t, uintptr_t pc)
68 {
69 	kmt_data_t *kmt = t->t_data;
70 	int i;
71 
72 	for (i = 0; i < sizeof (kmt->kmt_intrsyms) / sizeof (GElf_Sym); i++) {
73 		GElf_Sym *sym = (GElf_Sym *)&kmt->kmt_intrsyms + i;
74 
75 		if (pc >= sym->st_value && pc < sym->st_value + sym->st_size)
76 			return (0);
77 	}
78 
79 	return (1);
80 }
81 
82 /*
83  * Determine the return address for the current frame.
84  */
85 int
kmt_step_out(mdb_tgt_t * t,uintptr_t * p)86 kmt_step_out(mdb_tgt_t *t, uintptr_t *p)
87 {
88 	mdb_instr_t instr;
89 	kreg_t pc, sp, fp;
90 
91 	(void) kmdb_dpi_get_register("pc", &pc);
92 	(void) kmdb_dpi_get_register("sp", &sp);
93 	(void) kmdb_dpi_get_register("fp", &fp);
94 
95 	if (mdb_tgt_vread(t, &instr, sizeof (mdb_instr_t), pc) !=
96 	    sizeof (mdb_instr_t))
97 		return (-1); /* errno is set for us */
98 
99 	if (!kmt_step_out_validate(t, pc))
100 		return (set_errno(EMDB_TGTNOTSUP));
101 
102 	return (mdb_isa_step_out(t, p, pc, fp, sp, instr));
103 }
104 
105 /*
106  * Return the address of the next instruction following a call, or return -1
107  * and set errno to EAGAIN if the target should just single-step.
108  */
109 int
kmt_next(mdb_tgt_t * t,uintptr_t * p)110 kmt_next(mdb_tgt_t *t, uintptr_t *p)
111 {
112 	kreg_t pc;
113 	mdb_instr_t instr;
114 
115 	(void) kmdb_dpi_get_register("pc", &pc);
116 
117 	if (mdb_tgt_vread(t, &instr, sizeof (mdb_instr_t), pc) !=
118 	    sizeof (mdb_instr_t))
119 		return (-1); /* errno is set for us */
120 
121 	return (mdb_isa_next(t, p, pc, instr));
122 }
123 
124 static int
kmt_stack_common(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv,int cpuid,mdb_stack_frame_flags_t sflags,mdb_tgt_stack_f * func)125 kmt_stack_common(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
126     int cpuid, mdb_stack_frame_flags_t sflags, mdb_tgt_stack_f *func)
127 {
128 	mdb_tgt_t *t = mdb.m_target;
129 	const mdb_tgt_gregset_t *grp = NULL;
130 	mdb_tgt_gregset_t gregs;
131 	mdb_stack_frame_hdl_t *hdl;
132 	uint_t arglim = mdb.m_nargs;
133 	int i;
134 
135 	if (flags & DCMD_ADDRSPEC) {
136 		bzero(&gregs, sizeof (gregs));
137 		gregs.kregs[KREG_FP] = addr;
138 		grp = &gregs;
139 	} else {
140 		grp = kmdb_dpi_get_gregs(cpuid);
141 	}
142 
143 	if (grp == NULL) {
144 		warn("failed to retrieve registers for cpu %d", cpuid);
145 		return (DCMD_ERR);
146 	}
147 
148 	i = mdb_getopts(argc, argv,
149 	    'n', MDB_OPT_SETBITS, MSF_ADDR, &sflags,
150 	    's', MDB_OPT_SETBITS, MSF_SIZES, &sflags,
151 	    't', MDB_OPT_SETBITS, MSF_TYPES, &sflags,
152 	    'v', MDB_OPT_SETBITS, MSF_VERBOSE, &sflags,
153 	    NULL);
154 
155 	argc -= i;
156 	argv += i;
157 
158 	if (argc != 0) {
159 		if (argv->a_type == MDB_TYPE_CHAR || argc > 1)
160 			return (DCMD_USAGE);
161 
162 		arglim = mdb_argtoull(argv);
163 	}
164 
165 	if ((hdl = mdb_stack_frame_init(t, arglim, sflags)) == NULL) {
166 		mdb_warn("failed to init stack frame\n");
167 		return (DCMD_ERR);
168 	}
169 
170 	(void) mdb_isa_kvm_stack_iter(t, grp, func, (void *)hdl);
171 
172 	return (DCMD_OK);
173 }
174 
175 int
kmt_cpustack(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv,int cpuid,uint_t verbose)176 kmt_cpustack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
177     int cpuid, uint_t verbose)
178 {
179 	return (kmt_stack_common(addr, flags, argc, argv, cpuid,
180 	    verbose != 0 ? MSF_VERBOSE : 0, mdb_isa_kvm_frame));
181 }
182 
183 int
kmt_stack(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)184 kmt_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
185 {
186 	return (kmt_stack_common(addr, flags, argc, argv, DPI_MASTER_CPUID,
187 	    0, mdb_isa_kvm_frame));
188 }
189 
190 int
kmt_stackv(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)191 kmt_stackv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
192 {
193 	return (kmt_stack_common(addr, flags, argc, argv, DPI_MASTER_CPUID,
194 	    MSF_VERBOSE, mdb_isa_kvm_frame));
195 }
196 
197 int
kmt_stackr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)198 kmt_stackr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
199 {
200 	return (kmt_stack_common(addr, flags, argc, argv, DPI_MASTER_CPUID,
201 	    MSF_VERBOSE, mdb_isa_kvm_frame));
202 }
203 
204 /*ARGSUSED*/
205 void
kmt_printregs(const mdb_tgt_gregset_t * gregs)206 kmt_printregs(const mdb_tgt_gregset_t *gregs)
207 {
208 	mdb_isa_printregs(gregs);
209 }
210 
211 #define	IOCHECK_NOWARN	0
212 #define	IOCHECK_WARN	1
213 
214 static int
kmt_io_check(uint64_t nbytes,uintptr_t addr,int dowarn)215 kmt_io_check(uint64_t nbytes, uintptr_t addr, int dowarn)
216 {
217 	if (addr > IOPORTLIMIT) {
218 		if (dowarn)
219 			warn("port address must be 0-%#x\n", IOPORTLIMIT);
220 		return (set_errno(EINVAL));
221 	}
222 
223 	if (nbytes != 1 && nbytes != 2 && nbytes != 4) {
224 		if (dowarn)
225 			warn("port access must be 1, 2, or 4 bytes\n");
226 		return (set_errno(EINVAL));
227 	}
228 
229 	if ((addr & (nbytes - 1)) != 0) {
230 		if (dowarn) {
231 			warn("address for %llu-byte access must be %llu-byte "
232 			    "aligned\n", (u_longlong_t)nbytes,
233 			    (u_longlong_t)nbytes);
234 		}
235 		return (set_errno(EINVAL));
236 	}
237 
238 	return (0);
239 }
240 
241 /*ARGSUSED1*/
242 int
kmt_in_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)243 kmt_in_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
244 {
245 	uint64_t len = 0;
246 	uint32_t buf;
247 
248 	if (mdb_getopts(argc, argv,
249 	    'L', MDB_OPT_UINT64, &len,
250 	    NULL) != argc)
251 		return (DCMD_USAGE);
252 
253 	if (len == 0)
254 		len = mdb.m_dcount;
255 
256 	if (kmt_io_check(len, addr, IOCHECK_WARN) < 0)
257 		return (DCMD_ERR);
258 
259 	if (mdb_tgt_ioread(mdb.m_target, &buf, len, addr) < 0) {
260 		warn("failed to read from port 0x%llx", (u_longlong_t)addr);
261 		return (DCMD_ERR);
262 	}
263 
264 	mdb_printf("%x\n", buf);
265 
266 	return (DCMD_OK);
267 }
268 
269 /*ARGSUSED1*/
270 int
kmt_out_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)271 kmt_out_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
272 {
273 	uint64_t len = 0;
274 	uint64_t val;
275 
276 	if (mdb_getopts(argc, argv,
277 	    'L', MDB_OPT_UINT64, &len,
278 	    NULL) != argc - 1)
279 		return (DCMD_USAGE);
280 
281 	if (len == 0)
282 		len = mdb.m_dcount;
283 
284 	argv += argc - 1;
285 	val = mdb_argtoull(argv);
286 
287 	if (kmt_io_check(len, addr, IOCHECK_WARN) < 0)
288 		return (DCMD_ERR);
289 
290 	if (val > (1ULL << (len * NBBY)) - 1) {
291 		warn("value is out of range for port size\n");
292 		return (DCMD_ERR);
293 	}
294 
295 	if (mdb_tgt_iowrite(mdb.m_target, &val, len, addr) < 0) {
296 		warn("failed to write to port %llx", (u_longlong_t)addr);
297 		return (DCMD_ERR);
298 	}
299 
300 	return (DCMD_OK);
301 }
302 
303 static int
kmt_rwmsr(uint32_t addr,uint64_t * valp,void (* rw)(uint32_t,uint64_t *))304 kmt_rwmsr(uint32_t addr, uint64_t *valp, void (*rw)(uint32_t, uint64_t *))
305 {
306 	jmp_buf pcb, *oldpcb = NULL;
307 
308 	if (setjmp(pcb) != 0) {
309 		kmdb_dpi_restore_fault_hdlr(oldpcb);
310 		return (-1); /* errno is set for us */
311 	}
312 
313 	oldpcb = kmdb_dpi_set_fault_hdlr(&pcb);
314 	rw(addr, valp);
315 	kmdb_dpi_restore_fault_hdlr(oldpcb);
316 
317 	return (0);
318 }
319 
320 /*ARGSUSED*/
321 int
kmt_rdmsr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)322 kmt_rdmsr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
323 {
324 	uint64_t val;
325 
326 	if (!(flags & DCMD_ADDRSPEC))
327 		return (DCMD_USAGE);
328 
329 	if (kmt_rwmsr(addr, &val, rdmsr) < 0) {
330 		warn("rdmsr failed");
331 		return (DCMD_ERR);
332 	}
333 
334 	mdb_printf("%llx\n", (u_longlong_t)val);
335 
336 	return (DCMD_OK);
337 }
338 
339 /*ARGSUSED*/
340 int
kmt_wrmsr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)341 kmt_wrmsr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
342 {
343 	uint64_t val;
344 
345 	if (!(flags & DCMD_ADDRSPEC) || argc != 1)
346 		return (DCMD_USAGE);
347 
348 	val = mdb_argtoull(argv);
349 
350 	if (kmt_rwmsr(addr, &val, wrmsr)) {
351 		warn("wrmsr failed");
352 		return (DCMD_ERR);
353 	}
354 
355 	return (DCMD_OK);
356 }
357 
358 /*ARGSUSED*/
359 ssize_t
kmt_write(mdb_tgt_t * t,const void * buf,size_t nbytes,uintptr_t addr)360 kmt_write(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
361 {
362 	if (!(t->t_flags & MDB_TGT_F_ALLOWIO) &&
363 	    (nbytes = kmdb_kdi_range_is_nontoxic(addr, nbytes, 1)) == 0)
364 		return (set_errno(EMDB_NOMAP));
365 
366 	/*
367 	 * No writes to user space are allowed.  If we were to allow it, we'd
368 	 * be in the unfortunate situation where kmdb could place a breakpoint
369 	 * on a userspace executable page; this dirty page would end up being
370 	 * flushed back to disk, incurring sadness when it's next executed.
371 	 * Besides, we can't allow trapping in from userspace anyway.
372 	 */
373 	if (addr < kmdb_kdi_get_userlimit())
374 		return (set_errno(EMDB_TGTNOTSUP));
375 
376 	return (kmt_rw(t, (void *)buf, nbytes, addr, kmt_writer));
377 }
378 
379 /*ARGSUSED*/
380 static ssize_t
kmt_iorw(mdb_tgt_t * t,void * buf,size_t nbytes,uint64_t addr,void (* iorw)(void *,size_t,uintptr_t))381 kmt_iorw(mdb_tgt_t *t, void *buf, size_t nbytes, uint64_t addr,
382     void (*iorw)(void *, size_t, uintptr_t))
383 {
384 	jmp_buf pcb, *oldpcb = NULL;
385 
386 	if (kmt_io_check(nbytes, addr, IOCHECK_NOWARN) < 0)
387 		return (-1); /* errno is set for us */
388 
389 	if (setjmp(pcb) != 0) {
390 		kmdb_dpi_restore_fault_hdlr(oldpcb);
391 		return (-1); /* errno is set for us */
392 	}
393 
394 	oldpcb = kmdb_dpi_set_fault_hdlr(&pcb);
395 	iorw(buf, nbytes, addr);
396 	kmdb_dpi_restore_fault_hdlr(oldpcb);
397 
398 	return (nbytes);
399 }
400 
401 /*ARGSUSED*/
402 ssize_t
kmt_ioread(mdb_tgt_t * t,void * buf,size_t nbytes,uintptr_t addr)403 kmt_ioread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
404 {
405 	return (kmt_iorw(t, buf, nbytes, addr, kmt_in));
406 }
407 
408 /*ARGSUSED*/
409 ssize_t
kmt_iowrite(mdb_tgt_t * t,const void * buf,size_t nbytes,uintptr_t addr)410 kmt_iowrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
411 {
412 	return (kmt_iorw(t, (void *)buf, nbytes, addr, kmt_out));
413 }
414 
415 static int
kmt_pcicfg_common(uintptr_t off,uint32_t * valp,const mdb_arg_t * argv,void (* rw)(void *,size_t,uintptr_t))416 kmt_pcicfg_common(uintptr_t off, uint32_t *valp, const mdb_arg_t *argv,
417     void (*rw)(void *, size_t, uintptr_t))
418 {
419 	uint32_t bus, dev, func;
420 	uint32_t addr;
421 
422 	bus = (uint32_t)mdb_argtoull(&argv[0]);
423 	dev = (uint32_t)mdb_argtoull(&argv[1]);
424 	func = (uint32_t)mdb_argtoull(&argv[2]);
425 
426 	if ((bus & 0xffff) != bus) {
427 		warn("invalid bus number (must be 0-0xffff)\n");
428 		return (DCMD_ERR);
429 	}
430 
431 	if ((dev & 0x1f) != dev) {
432 		warn("invalid device number (must be 0-0x1f)\n");
433 		return (DCMD_ERR);
434 	}
435 
436 	if ((func & 0x7) != func) {
437 		warn("invalid function number (must be 0-7)\n");
438 		return (DCMD_ERR);
439 	}
440 
441 	if ((off & 0xfc) != off) {
442 		warn("invalid register number (must be 0-0xff, and 4-byte "
443 		    "aligned\n");
444 		return (DCMD_ERR);
445 	}
446 
447 	addr = PCI_CADDR1(bus, dev, func, off);
448 
449 	if (kmt_iowrite(mdb.m_target, &addr, sizeof (addr), PCI_CONFADD) !=
450 	    sizeof (addr)) {
451 		warn("write of PCI_CONFADD failed");
452 		return (DCMD_ERR);
453 	}
454 
455 	if (kmt_iorw(mdb.m_target, valp, sizeof (*valp), PCI_CONFDATA, rw) !=
456 	    sizeof (*valp)) {
457 		warn("access to PCI_CONFDATA failed");
458 		return (DCMD_ERR);
459 	}
460 
461 	return (DCMD_OK);
462 }
463 
464 /*ARGSUSED*/
465 int
kmt_rdpcicfg(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)466 kmt_rdpcicfg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
467 {
468 	uint32_t val;
469 
470 	if (argc != 3 || !(flags & DCMD_ADDRSPEC))
471 		return (DCMD_USAGE);
472 
473 	if (kmt_pcicfg_common(addr, &val, argv, kmt_in) != DCMD_OK)
474 		return (DCMD_ERR);
475 
476 	mdb_printf("%llx\n", (u_longlong_t)val);
477 
478 	return (DCMD_OK);
479 }
480 
481 /*ARGSUSED*/
482 int
kmt_wrpcicfg(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)483 kmt_wrpcicfg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
484 {
485 	uint32_t val;
486 
487 	if (argc != 4 || !(flags & DCMD_ADDRSPEC))
488 		return (DCMD_USAGE);
489 
490 	val = (uint32_t)mdb_argtoull(&argv[3]);
491 
492 	if (kmt_pcicfg_common(addr, &val, argv, kmt_out) != DCMD_OK)
493 		return (DCMD_ERR);
494 
495 	return (DCMD_OK);
496 }
497 
498 const char *
kmt_trapname(int trapnum)499 kmt_trapname(int trapnum)
500 {
501 	static char trapname[11];
502 
503 	switch (trapnum) {
504 	case T_ZERODIV:
505 		return ("division by zero (#de) trap");
506 	case T_SGLSTP:
507 		return ("single-step (#db) trap");
508 	case T_NMIFLT:
509 		return ("NMI");
510 	case T_BPTFLT:
511 		return ("breakpoint (#bp) trap");
512 	case T_ILLINST:
513 		return ("illegal instruction (#ud) trap");
514 	case T_SEGFLT:
515 		return ("segment not present (#np) trap");
516 	case T_STKFLT:
517 		return ("stack (#ss) trap");
518 	case T_GPFLT:
519 		return ("general protection (#gp) trap");
520 	case T_PGFLT:
521 		return ("page fault (#pf) trap");
522 	case T_ALIGNMENT:
523 		return ("alignment check (#ac) trap");
524 	case T_MCE:
525 		return ("machine check (#mc) trap");
526 	case T_SIMDFPE:
527 		return ("SSE/SSE2 (#xm) trap");
528 	case T_DBGENTR:
529 		return ("debugger entry trap");
530 	default:
531 		(void) mdb_snprintf(trapname, sizeof (trapname), "trap %#x",
532 		    trapnum);
533 		return (trapname);
534 	}
535 }
536 
537 void
kmt_init_isadep(mdb_tgt_t * t)538 kmt_init_isadep(mdb_tgt_t *t)
539 {
540 	kmt_data_t *kmt = t->t_data;
541 
542 	kmt->kmt_rds = mdb_isa_kregs;
543 
544 	kmt->kmt_trapmax = KMT_MAXTRAPNO;
545 	kmt->kmt_trapmap = mdb_zalloc(BT_SIZEOFMAP(kmt->kmt_trapmax), UM_SLEEP);
546 
547 	/* Traps for which we want to provide an explicit message */
548 	(void) mdb_tgt_add_fault(t, T_ZERODIV, MDB_TGT_SPEC_INTERNAL,
549 	    no_se_f, NULL);
550 	(void) mdb_tgt_add_fault(t, T_ILLINST, MDB_TGT_SPEC_INTERNAL,
551 	    no_se_f, NULL);
552 	(void) mdb_tgt_add_fault(t, T_SEGFLT, MDB_TGT_SPEC_INTERNAL,
553 	    no_se_f, NULL);
554 	(void) mdb_tgt_add_fault(t, T_STKFLT, MDB_TGT_SPEC_INTERNAL,
555 	    no_se_f, NULL);
556 	(void) mdb_tgt_add_fault(t, T_GPFLT, MDB_TGT_SPEC_INTERNAL,
557 	    no_se_f, NULL);
558 	(void) mdb_tgt_add_fault(t, T_PGFLT, MDB_TGT_SPEC_INTERNAL,
559 	    no_se_f, NULL);
560 	(void) mdb_tgt_add_fault(t, T_ALIGNMENT, MDB_TGT_SPEC_INTERNAL,
561 	    no_se_f, NULL);
562 	(void) mdb_tgt_add_fault(t, T_MCE, MDB_TGT_SPEC_INTERNAL,
563 	    no_se_f, NULL);
564 	(void) mdb_tgt_add_fault(t, T_SIMDFPE, MDB_TGT_SPEC_INTERNAL,
565 	    no_se_f, NULL);
566 
567 	/*
568 	 * Traps which will be handled elsewhere, and which therefore don't
569 	 * need the trap-based message.
570 	 */
571 	BT_SET(kmt->kmt_trapmap, T_SGLSTP);
572 	BT_SET(kmt->kmt_trapmap, T_BPTFLT);
573 	BT_SET(kmt->kmt_trapmap, T_DBGENTR);
574 
575 	/* Catch-all for traps not explicitly listed here */
576 	(void) mdb_tgt_add_fault(t, KMT_TRAP_NOTENUM, MDB_TGT_SPEC_INTERNAL,
577 	    no_se_f, NULL);
578 }
579 
580 void
kmt_startup_isadep(mdb_tgt_t * t)581 kmt_startup_isadep(mdb_tgt_t *t)
582 {
583 	kmt_data_t *kmt = t->t_data;
584 
585 	/*
586 	 * The stack trace and ::step out code need to detect "interrupt"
587 	 * frames.  The heuristic they use to detect said frames requires the
588 	 * addresses of routines that can generate them.
589 	 */
590 	(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
591 	    "cmnint", &kmt->kmt_intrsyms._kmt_cmnint, NULL);
592 	(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
593 	    "cmntrap", &kmt->kmt_intrsyms._kmt_cmntrap, NULL);
594 	(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
595 	    "sys_sysenter", &kmt->kmt_intrsyms._kmt_sysenter, NULL);
596 	(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
597 	    "brand_sys_sysenter", &kmt->kmt_intrsyms._kmt_brand_sysenter, NULL);
598 #if defined(__amd64)
599 	(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
600 	    "sys_syscall", &kmt->kmt_intrsyms._kmt_syscall, NULL);
601 	(void) mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
602 	    "brand_sys_syscall", &kmt->kmt_intrsyms._kmt_brand_syscall, NULL);
603 #endif
604 }
605