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