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 * Libkvm Kernel Target Intel component 30 * 31 * This file provides the Intel-dependent portion of the libkvm kernel target. 32 * For more details on the implementation refer to mdb_kvm.c. 33 */ 34 35 #include <mdb/mdb_target_impl.h> 36 #include <mdb/mdb_kreg_impl.h> 37 #include <mdb/mdb_errno.h> 38 #include <mdb/mdb_err.h> 39 #include <mdb/mdb_kvm.h> 40 #include <mdb/mdb_ks.h> 41 #include <mdb/mdb.h> 42 #include <mdb/kvm_isadep.h> 43 44 #include <sys/cpuvar.h> 45 #include <sys/privmregs.h> 46 47 int 48 kt_getareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, 49 const char *rname, mdb_tgt_reg_t *rp) 50 { 51 const mdb_tgt_regdesc_t *rdp; 52 kt_data_t *kt = t->t_data; 53 54 if (tid != kt->k_tid) 55 return (set_errno(EMDB_NOREGS)); 56 57 for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) { 58 if (strcmp(rname, rdp->rd_name) == 0) { 59 *rp = kt->k_regs->kregs[rdp->rd_num]; 60 return (0); 61 } 62 } 63 64 return (set_errno(EMDB_BADREG)); 65 } 66 67 int 68 kt_putareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, const char *rname, mdb_tgt_reg_t r) 69 { 70 const mdb_tgt_regdesc_t *rdp; 71 kt_data_t *kt = t->t_data; 72 73 if (tid != kt->k_tid) 74 return (set_errno(EMDB_NOREGS)); 75 76 for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) { 77 if (strcmp(rname, rdp->rd_name) == 0) { 78 kt->k_regs->kregs[rdp->rd_num] = (kreg_t)r; 79 return (0); 80 } 81 } 82 83 return (set_errno(EMDB_BADREG)); 84 } 85 86 int 87 kt_kvmregs(mdb_tgt_t *t, uint_t cpuid, mdb_tgt_gregset_t *kregs) 88 { 89 kt_data_t *kt = t->t_data; 90 privmregs_t mregs; 91 int ret; 92 93 if ((ret = kt->k_kb_ops->kb_getmregs(kt->k_cookie, cpuid, &mregs)) != 0) 94 return (ret); 95 96 kt_regs_to_kregs(&mregs.pm_gregs, kregs); 97 return (0); 98 } 99 100 static int 101 kt_cpu2cpuid(uintptr_t cpup) 102 { 103 cpu_t cpu; 104 105 if (mdb_vread(&cpu, sizeof (cpu_t), cpup) != sizeof (cpu_t)) 106 return (-1); 107 108 return (cpu.cpu_id); 109 } 110 111 int 112 kt_cpustack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 113 { 114 mdb_tgt_t *t = mdb.m_target; 115 mdb_tgt_gregset_t regs; 116 intptr_t cpuid = 0; 117 uint_t verbose = 0; 118 int i; 119 120 if (flags & DCMD_ADDRSPEC) { 121 if ((cpuid = kt_cpu2cpuid(addr)) < 0) { 122 (void) set_errno(EMDB_NOMAP); 123 mdb_warn("failed to find cpuid for cpu at %p", addr); 124 return (DCMD_ERR); 125 } 126 flags &= ~DCMD_ADDRSPEC; 127 } 128 129 130 i = mdb_getopts(argc, argv, 131 'c', MDB_OPT_UINTPTR, &cpuid, 132 'v', MDB_OPT_SETBITS, 1, &verbose, 133 NULL); 134 135 argc -= i; 136 argv += i; 137 138 if (kt_kvmregs(t, cpuid, ®s) != 0) { 139 mdb_warn("failed to get regs for cpu %d\n", cpuid); 140 return (DCMD_ERR); 141 } 142 143 /* 144 * Tell the stack walker that we have regs. 145 */ 146 flags |= DCMD_ADDRSPEC; 147 addr = regs.kregs[KREG_FP]; 148 149 if (verbose) 150 return (kt_stackv(addr, flags, argc, argv)); 151 else 152 return (kt_stack(addr, flags, argc, argv)); 153 } 154 155 /*ARGSUSED*/ 156 int 157 kt_cpuregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 158 { 159 mdb_tgt_t *t = mdb.m_target; 160 mdb_tgt_gregset_t regs; 161 intptr_t cpuid = 0; 162 int i; 163 164 if (flags & DCMD_ADDRSPEC) { 165 if (argc != 0) 166 return (DCMD_USAGE); 167 if ((cpuid = kt_cpu2cpuid(addr)) < 0) { 168 (void) set_errno(EMDB_NOMAP); 169 mdb_warn("failed to find cpuid for cpu at %p", addr); 170 return (DCMD_ERR); 171 } 172 } 173 174 175 i = mdb_getopts(argc, argv, 176 'c', MDB_OPT_UINTPTR, &cpuid, 177 NULL); 178 179 argc -= i; 180 argv += i; 181 182 if (argc != 0) 183 return (DCMD_USAGE); 184 185 if (kt_kvmregs(t, cpuid, ®s) != 0) { 186 mdb_warn("failed to get regs for cpu %d\n", cpuid); 187 return (DCMD_ERR); 188 } 189 190 return (kt_regs((uintptr_t)®s, flags, argc, argv)); 191 } 192