xref: /illumos-gate/usr/src/cmd/mdb/intel/mdb/kvm_isadep.c (revision 843e19887f64dde75055cf8842fc4db2171eff45)
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, &regs) != 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, &regs) != 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)&regs, flags, argc, argv));
191 }
192