9210 remove KMDB branch debugging support
[unleashed.git] / usr / src / cmd / mdb / intel / kmdb / kvm_isadep.c
blobcc25f355f1cd20cb5140f7c0161ef1a7af527bd6
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2018 Joyent, Inc.
29 * isa-dependent portions of the kmdb target
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>
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>
49 /* Higher than the highest trap number for which we have a defined specifier */
50 #define KMT_MAXTRAPNO 0x20
52 #define IOPORTLIMIT 0xffff /* XXX find a new home for this */
54 const char *
55 kmt_def_dismode(void)
57 #ifdef __amd64
58 return ("amd64");
59 #else
60 return ("ia32");
61 #endif
64 int
65 kmt_step_out_validate(mdb_tgt_t *t, uintptr_t pc)
67 kmt_data_t *kmt = t->t_data;
68 int i;
70 for (i = 0; i < sizeof (kmt->kmt_intrsyms) / sizeof (GElf_Sym); i++) {
71 GElf_Sym *sym = (GElf_Sym *)&kmt->kmt_intrsyms + i;
73 if (pc >= sym->st_value && pc < sym->st_value + sym->st_size)
74 return (0);
77 return (1);
81 * Determine the return address for the current frame.
83 int
84 kmt_step_out(mdb_tgt_t *t, uintptr_t *p)
86 mdb_instr_t instr;
87 kreg_t pc, sp, fp;
89 (void) kmdb_dpi_get_register("pc", &pc);
90 (void) kmdb_dpi_get_register("sp", &sp);
91 (void) kmdb_dpi_get_register("fp", &fp);
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 */
97 if (!kmt_step_out_validate(t, pc))
98 return (set_errno(EMDB_TGTNOTSUP));
100 return (mdb_isa_step_out(t, p, pc, fp, sp, instr));
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.
108 kmt_next(mdb_tgt_t *t, uintptr_t *p)
110 kreg_t pc;
111 mdb_instr_t instr;
113 (void) kmdb_dpi_get_register("pc", &pc);
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 */
119 return (mdb_isa_next(t, p, pc, instr));
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)
127 const mdb_tgt_gregset_t *grp = NULL;
128 mdb_tgt_gregset_t gregs;
129 void *arg = (void *)(uintptr_t)mdb.m_nargs;
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);
138 if (grp == NULL) {
139 warn("failed to retrieve registers for cpu %d", cpuid);
140 return (DCMD_ERR);
143 if (argc != 0) {
144 if (argv->a_type == MDB_TYPE_CHAR || argc > 1)
145 return (DCMD_USAGE);
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;
153 (void) mdb_isa_kvm_stack_iter(mdb.m_target, grp, func, arg);
155 return (DCMD_OK);
159 kmt_cpustack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
160 int cpuid, int verbose)
162 return (kmt_stack_common(addr, flags, argc, argv, cpuid,
163 (verbose ? mdb_isa_kvm_framev : mdb_isa_kvm_frame)));
167 kmt_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
169 return (kmt_stack_common(addr, flags, argc, argv, DPI_MASTER_CPUID,
170 mdb_isa_kvm_frame));
174 kmt_stackv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
176 return (kmt_stack_common(addr, flags, argc, argv, DPI_MASTER_CPUID,
177 mdb_isa_kvm_framev));
181 kmt_stackr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
183 return (kmt_stack_common(addr, flags, argc, argv, DPI_MASTER_CPUID,
184 mdb_isa_kvm_framev));
187 /*ARGSUSED*/
188 void
189 kmt_printregs(const mdb_tgt_gregset_t *gregs)
191 mdb_isa_printregs(gregs);
194 #define IOCHECK_NOWARN 0
195 #define IOCHECK_WARN 1
197 static int
198 kmt_io_check(uint64_t nbytes, uintptr_t addr, int dowarn)
200 if (addr > IOPORTLIMIT) {
201 if (dowarn)
202 warn("port address must be 0-%#x\n", IOPORTLIMIT);
203 return (set_errno(EINVAL));
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));
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);
218 return (set_errno(EINVAL));
221 return (0);
224 /*ARGSUSED1*/
226 kmt_in_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
228 uint64_t len = 0;
229 uint32_t buf;
231 if (mdb_getopts(argc, argv,
232 'L', MDB_OPT_UINT64, &len,
233 NULL) != argc)
234 return (DCMD_USAGE);
236 if (len == 0)
237 len = mdb.m_dcount;
239 if (kmt_io_check(len, addr, IOCHECK_WARN) < 0)
240 return (DCMD_ERR);
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);
247 mdb_printf("%x\n", buf);
249 return (DCMD_OK);
252 static uint64_t
253 kmt_numarg(const mdb_arg_t *arg)
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);
261 /*ARGSUSED1*/
263 kmt_out_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
265 uint64_t len = 0;
266 uint64_t val;
268 if (mdb_getopts(argc, argv,
269 'L', MDB_OPT_UINT64, &len,
270 NULL) != argc - 1)
271 return (DCMD_USAGE);
273 if (len == 0)
274 len = mdb.m_dcount;
276 argv += argc - 1;
277 val = kmt_numarg(argv);
279 if (kmt_io_check(len, addr, IOCHECK_WARN) < 0)
280 return (DCMD_ERR);
282 if (val > (1ULL << (len * NBBY)) - 1) {
283 warn("value is out of range for port size\n");
284 return (DCMD_ERR);
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);
292 return (DCMD_OK);
295 static int
296 kmt_rwmsr(uint32_t addr, uint64_t *valp, void (*rw)(uint32_t, uint64_t *))
298 jmp_buf pcb, *oldpcb = NULL;
300 if (setjmp(pcb) != 0) {
301 kmdb_dpi_restore_fault_hdlr(oldpcb);
302 return (-1); /* errno is set for us */
305 oldpcb = kmdb_dpi_set_fault_hdlr(&pcb);
306 rw(addr, valp);
307 kmdb_dpi_restore_fault_hdlr(oldpcb);
309 return (0);
312 /*ARGSUSED*/
314 kmt_rdmsr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
316 uint64_t val;
318 if (!(flags & DCMD_ADDRSPEC))
319 return (DCMD_USAGE);
321 if (kmt_rwmsr(addr, &val, rdmsr) < 0) {
322 warn("rdmsr failed");
323 return (DCMD_ERR);
326 mdb_printf("%llx\n", (u_longlong_t)val);
328 return (DCMD_OK);
331 /*ARGSUSED*/
333 kmt_wrmsr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
335 uint64_t val;
337 if (!(flags & DCMD_ADDRSPEC) || argc != 1)
338 return (DCMD_USAGE);
340 val = kmt_numarg(argv);
342 if (kmt_rwmsr(addr, &val, wrmsr)) {
343 warn("wrmsr failed");
344 return (DCMD_ERR);
347 return (DCMD_OK);
350 /*ARGSUSED*/
351 ssize_t
352 kmt_write(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
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));
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.
365 if (addr < kmdb_kdi_get_userlimit())
366 return (set_errno(EMDB_TGTNOTSUP));
368 return (kmt_rw(t, (void *)buf, nbytes, addr, kmt_writer));
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))
376 jmp_buf pcb, *oldpcb = NULL;
378 if (kmt_io_check(nbytes, addr, IOCHECK_NOWARN) < 0)
379 return (-1); /* errno is set for us */
381 if (setjmp(pcb) != 0) {
382 kmdb_dpi_restore_fault_hdlr(oldpcb);
383 return (-1); /* errno is set for us */
386 oldpcb = kmdb_dpi_set_fault_hdlr(&pcb);
387 iorw(buf, nbytes, addr);
388 kmdb_dpi_restore_fault_hdlr(oldpcb);
390 return (nbytes);
393 /*ARGSUSED*/
394 ssize_t
395 kmt_ioread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
397 return (kmt_iorw(t, buf, nbytes, addr, kmt_in));
400 /*ARGSUSED*/
401 ssize_t
402 kmt_iowrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
404 return (kmt_iorw(t, (void *)buf, nbytes, addr, kmt_out));
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))
411 uint32_t bus, dev, func;
412 uint32_t addr;
414 bus = kmt_numarg(&argv[0]);
415 dev = kmt_numarg(&argv[1]);
416 func = kmt_numarg(&argv[2]);
418 if ((bus & 0xffff) != bus) {
419 warn("invalid bus number (must be 0-0xffff)\n");
420 return (DCMD_ERR);
423 if ((dev & 0x1f) != dev) {
424 warn("invalid device number (must be 0-0x1f)\n");
425 return (DCMD_ERR);
428 if ((func & 0x7) != func) {
429 warn("invalid function number (must be 0-7)\n");
430 return (DCMD_ERR);
433 if ((off & 0xfc) != off) {
434 warn("invalid register number (must be 0-0xff, and 4-byte "
435 "aligned\n");
436 return (DCMD_ERR);
439 addr = PCI_CADDR1(bus, dev, func, off);
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);
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);
453 return (DCMD_OK);
456 /*ARGSUSED*/
458 kmt_rdpcicfg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
460 uint32_t val;
462 if (argc != 3 || !(flags & DCMD_ADDRSPEC))
463 return (DCMD_USAGE);
465 if (kmt_pcicfg_common(addr, &val, argv, kmt_in) != DCMD_OK)
466 return (DCMD_ERR);
468 mdb_printf("%llx\n", (u_longlong_t)val);
470 return (DCMD_OK);
473 /*ARGSUSED*/
475 kmt_wrpcicfg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
477 uint32_t val;
479 if (argc != 4 || !(flags & DCMD_ADDRSPEC))
480 return (DCMD_USAGE);
482 val = (uint32_t)kmt_numarg(&argv[3]);
484 if (kmt_pcicfg_common(addr, &val, argv, kmt_out) != DCMD_OK)
485 return (DCMD_ERR);
487 return (DCMD_OK);
490 const char *
491 kmt_trapname(int trapnum)
493 static char trapname[11];
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);
529 void
530 kmt_init_isadep(mdb_tgt_t *t)
532 kmt_data_t *kmt = t->t_data;
534 kmt->kmt_rds = mdb_isa_kregs;
536 kmt->kmt_trapmax = KMT_MAXTRAPNO;
537 kmt->kmt_trapmap = mdb_zalloc(BT_SIZEOFMAP(kmt->kmt_trapmax), UM_SLEEP);
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);
560 * Traps which will be handled elsewhere, and which therefore don't
561 * need the trap-based message.
563 BT_SET(kmt->kmt_trapmap, T_SGLSTP);
564 BT_SET(kmt->kmt_trapmap, T_BPTFLT);
565 BT_SET(kmt->kmt_trapmap, T_DBGENTR);
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);
572 void
573 kmt_startup_isadep(mdb_tgt_t *t)
575 kmt_data_t *kmt = t->t_data;
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.
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