xref: /illumos-gate/usr/src/cmd/mdb/intel/mdb/kvm_isadep.c (revision 843e19887f64dde75055cf8842fc4db2171eff45)
1*843e1988Sjohnlev /*
2*843e1988Sjohnlev  * CDDL HEADER START
3*843e1988Sjohnlev  *
4*843e1988Sjohnlev  * The contents of this file are subject to the terms of the
5*843e1988Sjohnlev  * Common Development and Distribution License (the "License").
6*843e1988Sjohnlev  * You may not use this file except in compliance with the License.
7*843e1988Sjohnlev  *
8*843e1988Sjohnlev  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*843e1988Sjohnlev  * or http://www.opensolaris.org/os/licensing.
10*843e1988Sjohnlev  * See the License for the specific language governing permissions
11*843e1988Sjohnlev  * and limitations under the License.
12*843e1988Sjohnlev  *
13*843e1988Sjohnlev  * When distributing Covered Code, include this CDDL HEADER in each
14*843e1988Sjohnlev  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*843e1988Sjohnlev  * If applicable, add the following below this CDDL HEADER, with the
16*843e1988Sjohnlev  * fields enclosed by brackets "[]" replaced with your own identifying
17*843e1988Sjohnlev  * information: Portions Copyright [yyyy] [name of copyright owner]
18*843e1988Sjohnlev  *
19*843e1988Sjohnlev  * CDDL HEADER END
20*843e1988Sjohnlev  */
21*843e1988Sjohnlev /*
22*843e1988Sjohnlev  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*843e1988Sjohnlev  * Use is subject to license terms.
24*843e1988Sjohnlev  */
25*843e1988Sjohnlev 
26*843e1988Sjohnlev #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*843e1988Sjohnlev 
28*843e1988Sjohnlev /*
29*843e1988Sjohnlev  * Libkvm Kernel Target Intel component
30*843e1988Sjohnlev  *
31*843e1988Sjohnlev  * This file provides the Intel-dependent portion of the libkvm kernel target.
32*843e1988Sjohnlev  * For more details on the implementation refer to mdb_kvm.c.
33*843e1988Sjohnlev  */
34*843e1988Sjohnlev 
35*843e1988Sjohnlev #include <mdb/mdb_target_impl.h>
36*843e1988Sjohnlev #include <mdb/mdb_kreg_impl.h>
37*843e1988Sjohnlev #include <mdb/mdb_errno.h>
38*843e1988Sjohnlev #include <mdb/mdb_err.h>
39*843e1988Sjohnlev #include <mdb/mdb_kvm.h>
40*843e1988Sjohnlev #include <mdb/mdb_ks.h>
41*843e1988Sjohnlev #include <mdb/mdb.h>
42*843e1988Sjohnlev #include <mdb/kvm_isadep.h>
43*843e1988Sjohnlev 
44*843e1988Sjohnlev #include <sys/cpuvar.h>
45*843e1988Sjohnlev #include <sys/privmregs.h>
46*843e1988Sjohnlev 
47*843e1988Sjohnlev int
48*843e1988Sjohnlev kt_getareg(mdb_tgt_t *t, mdb_tgt_tid_t tid,
49*843e1988Sjohnlev     const char *rname, mdb_tgt_reg_t *rp)
50*843e1988Sjohnlev {
51*843e1988Sjohnlev 	const mdb_tgt_regdesc_t *rdp;
52*843e1988Sjohnlev 	kt_data_t *kt = t->t_data;
53*843e1988Sjohnlev 
54*843e1988Sjohnlev 	if (tid != kt->k_tid)
55*843e1988Sjohnlev 		return (set_errno(EMDB_NOREGS));
56*843e1988Sjohnlev 
57*843e1988Sjohnlev 	for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) {
58*843e1988Sjohnlev 		if (strcmp(rname, rdp->rd_name) == 0) {
59*843e1988Sjohnlev 			*rp = kt->k_regs->kregs[rdp->rd_num];
60*843e1988Sjohnlev 			return (0);
61*843e1988Sjohnlev 		}
62*843e1988Sjohnlev 	}
63*843e1988Sjohnlev 
64*843e1988Sjohnlev 	return (set_errno(EMDB_BADREG));
65*843e1988Sjohnlev }
66*843e1988Sjohnlev 
67*843e1988Sjohnlev int
68*843e1988Sjohnlev kt_putareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, const char *rname, mdb_tgt_reg_t r)
69*843e1988Sjohnlev {
70*843e1988Sjohnlev 	const mdb_tgt_regdesc_t *rdp;
71*843e1988Sjohnlev 	kt_data_t *kt = t->t_data;
72*843e1988Sjohnlev 
73*843e1988Sjohnlev 	if (tid != kt->k_tid)
74*843e1988Sjohnlev 		return (set_errno(EMDB_NOREGS));
75*843e1988Sjohnlev 
76*843e1988Sjohnlev 	for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) {
77*843e1988Sjohnlev 		if (strcmp(rname, rdp->rd_name) == 0) {
78*843e1988Sjohnlev 			kt->k_regs->kregs[rdp->rd_num] = (kreg_t)r;
79*843e1988Sjohnlev 			return (0);
80*843e1988Sjohnlev 		}
81*843e1988Sjohnlev 	}
82*843e1988Sjohnlev 
83*843e1988Sjohnlev 	return (set_errno(EMDB_BADREG));
84*843e1988Sjohnlev }
85*843e1988Sjohnlev 
86*843e1988Sjohnlev int
87*843e1988Sjohnlev kt_kvmregs(mdb_tgt_t *t, uint_t cpuid, mdb_tgt_gregset_t *kregs)
88*843e1988Sjohnlev {
89*843e1988Sjohnlev 	kt_data_t *kt = t->t_data;
90*843e1988Sjohnlev 	privmregs_t mregs;
91*843e1988Sjohnlev 	int ret;
92*843e1988Sjohnlev 
93*843e1988Sjohnlev 	if ((ret = kt->k_kb_ops->kb_getmregs(kt->k_cookie, cpuid, &mregs)) != 0)
94*843e1988Sjohnlev 		return (ret);
95*843e1988Sjohnlev 
96*843e1988Sjohnlev 	kt_regs_to_kregs(&mregs.pm_gregs, kregs);
97*843e1988Sjohnlev 	return (0);
98*843e1988Sjohnlev }
99*843e1988Sjohnlev 
100*843e1988Sjohnlev static int
101*843e1988Sjohnlev kt_cpu2cpuid(uintptr_t cpup)
102*843e1988Sjohnlev {
103*843e1988Sjohnlev 	cpu_t cpu;
104*843e1988Sjohnlev 
105*843e1988Sjohnlev 	if (mdb_vread(&cpu, sizeof (cpu_t), cpup) != sizeof (cpu_t))
106*843e1988Sjohnlev 		return (-1);
107*843e1988Sjohnlev 
108*843e1988Sjohnlev 	return (cpu.cpu_id);
109*843e1988Sjohnlev }
110*843e1988Sjohnlev 
111*843e1988Sjohnlev int
112*843e1988Sjohnlev kt_cpustack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
113*843e1988Sjohnlev {
114*843e1988Sjohnlev 	mdb_tgt_t *t = mdb.m_target;
115*843e1988Sjohnlev 	mdb_tgt_gregset_t regs;
116*843e1988Sjohnlev 	intptr_t cpuid = 0;
117*843e1988Sjohnlev 	uint_t verbose = 0;
118*843e1988Sjohnlev 	int i;
119*843e1988Sjohnlev 
120*843e1988Sjohnlev 	if (flags & DCMD_ADDRSPEC) {
121*843e1988Sjohnlev 		if ((cpuid = kt_cpu2cpuid(addr)) < 0) {
122*843e1988Sjohnlev 			(void) set_errno(EMDB_NOMAP);
123*843e1988Sjohnlev 			mdb_warn("failed to find cpuid for cpu at %p", addr);
124*843e1988Sjohnlev 			return (DCMD_ERR);
125*843e1988Sjohnlev 		}
126*843e1988Sjohnlev 		flags &= ~DCMD_ADDRSPEC;
127*843e1988Sjohnlev 	}
128*843e1988Sjohnlev 
129*843e1988Sjohnlev 
130*843e1988Sjohnlev 	i = mdb_getopts(argc, argv,
131*843e1988Sjohnlev 	    'c', MDB_OPT_UINTPTR, &cpuid,
132*843e1988Sjohnlev 	    'v', MDB_OPT_SETBITS, 1, &verbose,
133*843e1988Sjohnlev 	    NULL);
134*843e1988Sjohnlev 
135*843e1988Sjohnlev 	argc -= i;
136*843e1988Sjohnlev 	argv += i;
137*843e1988Sjohnlev 
138*843e1988Sjohnlev 	if (kt_kvmregs(t, cpuid, &regs) != 0) {
139*843e1988Sjohnlev 		mdb_warn("failed to get regs for cpu %d\n", cpuid);
140*843e1988Sjohnlev 		return (DCMD_ERR);
141*843e1988Sjohnlev 	}
142*843e1988Sjohnlev 
143*843e1988Sjohnlev 	/*
144*843e1988Sjohnlev 	 * Tell the stack walker that we have regs.
145*843e1988Sjohnlev 	 */
146*843e1988Sjohnlev 	flags |= DCMD_ADDRSPEC;
147*843e1988Sjohnlev 	addr = regs.kregs[KREG_FP];
148*843e1988Sjohnlev 
149*843e1988Sjohnlev 	if (verbose)
150*843e1988Sjohnlev 		return (kt_stackv(addr, flags, argc, argv));
151*843e1988Sjohnlev 	else
152*843e1988Sjohnlev 		return (kt_stack(addr, flags, argc, argv));
153*843e1988Sjohnlev }
154*843e1988Sjohnlev 
155*843e1988Sjohnlev /*ARGSUSED*/
156*843e1988Sjohnlev int
157*843e1988Sjohnlev kt_cpuregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
158*843e1988Sjohnlev {
159*843e1988Sjohnlev 	mdb_tgt_t *t = mdb.m_target;
160*843e1988Sjohnlev 	mdb_tgt_gregset_t regs;
161*843e1988Sjohnlev 	intptr_t cpuid = 0;
162*843e1988Sjohnlev 	int i;
163*843e1988Sjohnlev 
164*843e1988Sjohnlev 	if (flags & DCMD_ADDRSPEC) {
165*843e1988Sjohnlev 		if (argc != 0)
166*843e1988Sjohnlev 			return (DCMD_USAGE);
167*843e1988Sjohnlev 		if ((cpuid = kt_cpu2cpuid(addr)) < 0) {
168*843e1988Sjohnlev 			(void) set_errno(EMDB_NOMAP);
169*843e1988Sjohnlev 			mdb_warn("failed to find cpuid for cpu at %p", addr);
170*843e1988Sjohnlev 			return (DCMD_ERR);
171*843e1988Sjohnlev 		}
172*843e1988Sjohnlev 	}
173*843e1988Sjohnlev 
174*843e1988Sjohnlev 
175*843e1988Sjohnlev 	i = mdb_getopts(argc, argv,
176*843e1988Sjohnlev 	    'c', MDB_OPT_UINTPTR, &cpuid,
177*843e1988Sjohnlev 	    NULL);
178*843e1988Sjohnlev 
179*843e1988Sjohnlev 	argc -= i;
180*843e1988Sjohnlev 	argv += i;
181*843e1988Sjohnlev 
182*843e1988Sjohnlev 	if (argc != 0)
183*843e1988Sjohnlev 		return (DCMD_USAGE);
184*843e1988Sjohnlev 
185*843e1988Sjohnlev 	if (kt_kvmregs(t, cpuid, &regs) != 0) {
186*843e1988Sjohnlev 		mdb_warn("failed to get regs for cpu %d\n", cpuid);
187*843e1988Sjohnlev 		return (DCMD_ERR);
188*843e1988Sjohnlev 	}
189*843e1988Sjohnlev 
190*843e1988Sjohnlev 	return (kt_regs((uintptr_t)&regs, flags, argc, argv));
191*843e1988Sjohnlev }
192