xref: /illumos-gate/usr/src/cmd/mdb/intel/mdb/kvm_isadep.c (revision 0a47c91c895e274dd0990009919e30e984364a8b)
1843e1988Sjohnlev /*
2843e1988Sjohnlev  * CDDL HEADER START
3843e1988Sjohnlev  *
4843e1988Sjohnlev  * The contents of this file are subject to the terms of the
5843e1988Sjohnlev  * Common Development and Distribution License (the "License").
6843e1988Sjohnlev  * You may not use this file except in compliance with the License.
7843e1988Sjohnlev  *
8843e1988Sjohnlev  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9843e1988Sjohnlev  * or http://www.opensolaris.org/os/licensing.
10843e1988Sjohnlev  * See the License for the specific language governing permissions
11843e1988Sjohnlev  * and limitations under the License.
12843e1988Sjohnlev  *
13843e1988Sjohnlev  * When distributing Covered Code, include this CDDL HEADER in each
14843e1988Sjohnlev  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15843e1988Sjohnlev  * If applicable, add the following below this CDDL HEADER, with the
16843e1988Sjohnlev  * fields enclosed by brackets "[]" replaced with your own identifying
17843e1988Sjohnlev  * information: Portions Copyright [yyyy] [name of copyright owner]
18843e1988Sjohnlev  *
19843e1988Sjohnlev  * CDDL HEADER END
20843e1988Sjohnlev  */
21843e1988Sjohnlev /*
22843e1988Sjohnlev  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23843e1988Sjohnlev  * Use is subject to license terms.
24843e1988Sjohnlev  */
25*0a47c91cSRobert Mustacchi /*
26*0a47c91cSRobert Mustacchi  * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
27*0a47c91cSRobert Mustacchi  */
28843e1988Sjohnlev 
29843e1988Sjohnlev /*
30843e1988Sjohnlev  * Libkvm Kernel Target Intel component
31843e1988Sjohnlev  *
32843e1988Sjohnlev  * This file provides the Intel-dependent portion of the libkvm kernel target.
33843e1988Sjohnlev  * For more details on the implementation refer to mdb_kvm.c.
34843e1988Sjohnlev  */
35843e1988Sjohnlev 
36843e1988Sjohnlev #include <mdb/mdb_target_impl.h>
37843e1988Sjohnlev #include <mdb/mdb_kreg_impl.h>
38843e1988Sjohnlev #include <mdb/mdb_errno.h>
39843e1988Sjohnlev #include <mdb/mdb_err.h>
40843e1988Sjohnlev #include <mdb/mdb_kvm.h>
41843e1988Sjohnlev #include <mdb/mdb_ks.h>
42843e1988Sjohnlev #include <mdb/mdb.h>
43843e1988Sjohnlev #include <mdb/kvm_isadep.h>
44843e1988Sjohnlev 
45843e1988Sjohnlev #include <sys/cpuvar.h>
46843e1988Sjohnlev #include <sys/privmregs.h>
47843e1988Sjohnlev 
48843e1988Sjohnlev int
49843e1988Sjohnlev kt_getareg(mdb_tgt_t *t, mdb_tgt_tid_t tid,
50843e1988Sjohnlev     const char *rname, mdb_tgt_reg_t *rp)
51843e1988Sjohnlev {
52843e1988Sjohnlev 	const mdb_tgt_regdesc_t *rdp;
53843e1988Sjohnlev 	kt_data_t *kt = t->t_data;
54843e1988Sjohnlev 
55843e1988Sjohnlev 	if (tid != kt->k_tid)
56843e1988Sjohnlev 		return (set_errno(EMDB_NOREGS));
57843e1988Sjohnlev 
58843e1988Sjohnlev 	for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) {
59843e1988Sjohnlev 		if (strcmp(rname, rdp->rd_name) == 0) {
60843e1988Sjohnlev 			*rp = kt->k_regs->kregs[rdp->rd_num];
61*0a47c91cSRobert Mustacchi 			if (rdp->rd_flags & MDB_TGT_R_32)
62*0a47c91cSRobert Mustacchi 				*rp &= 0xffffffffULL;
63*0a47c91cSRobert Mustacchi 			else if (rdp->rd_flags & MDB_TGT_R_16)
64*0a47c91cSRobert Mustacchi 				*rp &= 0xffffULL;
65*0a47c91cSRobert Mustacchi 			else if (rdp->rd_flags & MDB_TGT_R_8H)
66*0a47c91cSRobert Mustacchi 				*rp = (*rp & 0xff00ULL) >> 8;
67*0a47c91cSRobert Mustacchi 			else if (rdp->rd_flags & MDB_TGT_R_8L)
68*0a47c91cSRobert Mustacchi 				*rp &= 0xffULL;
69843e1988Sjohnlev 			return (0);
70843e1988Sjohnlev 		}
71843e1988Sjohnlev 	}
72843e1988Sjohnlev 
73843e1988Sjohnlev 	return (set_errno(EMDB_BADREG));
74843e1988Sjohnlev }
75843e1988Sjohnlev 
76843e1988Sjohnlev int
77843e1988Sjohnlev kt_putareg(mdb_tgt_t *t, mdb_tgt_tid_t tid, const char *rname, mdb_tgt_reg_t r)
78843e1988Sjohnlev {
79843e1988Sjohnlev 	const mdb_tgt_regdesc_t *rdp;
80843e1988Sjohnlev 	kt_data_t *kt = t->t_data;
81843e1988Sjohnlev 
82843e1988Sjohnlev 	if (tid != kt->k_tid)
83843e1988Sjohnlev 		return (set_errno(EMDB_NOREGS));
84843e1988Sjohnlev 
85843e1988Sjohnlev 	for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) {
86843e1988Sjohnlev 		if (strcmp(rname, rdp->rd_name) == 0) {
87*0a47c91cSRobert Mustacchi 			if (rdp->rd_flags & MDB_TGT_R_32)
88*0a47c91cSRobert Mustacchi 				r &= 0xffffffffULL;
89*0a47c91cSRobert Mustacchi 			else if (rdp->rd_flags & MDB_TGT_R_16)
90*0a47c91cSRobert Mustacchi 				r &= 0xffffULL;
91*0a47c91cSRobert Mustacchi 			else if (rdp->rd_flags & MDB_TGT_R_8H)
92*0a47c91cSRobert Mustacchi 				r = (r & 0xffULL) << 8;
93*0a47c91cSRobert Mustacchi 			else if (rdp->rd_flags & MDB_TGT_R_8L)
94*0a47c91cSRobert Mustacchi 				r &= 0xffULL;
95*0a47c91cSRobert Mustacchi 
96843e1988Sjohnlev 			kt->k_regs->kregs[rdp->rd_num] = (kreg_t)r;
97843e1988Sjohnlev 			return (0);
98843e1988Sjohnlev 		}
99843e1988Sjohnlev 	}
100843e1988Sjohnlev 
101843e1988Sjohnlev 	return (set_errno(EMDB_BADREG));
102843e1988Sjohnlev }
103843e1988Sjohnlev 
104843e1988Sjohnlev int
105843e1988Sjohnlev kt_kvmregs(mdb_tgt_t *t, uint_t cpuid, mdb_tgt_gregset_t *kregs)
106843e1988Sjohnlev {
107843e1988Sjohnlev 	kt_data_t *kt = t->t_data;
108843e1988Sjohnlev 	privmregs_t mregs;
109843e1988Sjohnlev 	int ret;
110843e1988Sjohnlev 
111843e1988Sjohnlev 	if ((ret = kt->k_kb_ops->kb_getmregs(kt->k_cookie, cpuid, &mregs)) != 0)
112843e1988Sjohnlev 		return (ret);
113843e1988Sjohnlev 
114843e1988Sjohnlev 	kt_regs_to_kregs(&mregs.pm_gregs, kregs);
115843e1988Sjohnlev 	return (0);
116843e1988Sjohnlev }
117843e1988Sjohnlev 
118843e1988Sjohnlev static int
119843e1988Sjohnlev kt_cpu2cpuid(uintptr_t cpup)
120843e1988Sjohnlev {
121843e1988Sjohnlev 	cpu_t cpu;
122843e1988Sjohnlev 
123843e1988Sjohnlev 	if (mdb_vread(&cpu, sizeof (cpu_t), cpup) != sizeof (cpu_t))
124843e1988Sjohnlev 		return (-1);
125843e1988Sjohnlev 
126843e1988Sjohnlev 	return (cpu.cpu_id);
127843e1988Sjohnlev }
128843e1988Sjohnlev 
129843e1988Sjohnlev int
130843e1988Sjohnlev kt_cpustack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
131843e1988Sjohnlev {
132843e1988Sjohnlev 	mdb_tgt_t *t = mdb.m_target;
133843e1988Sjohnlev 	mdb_tgt_gregset_t regs;
134843e1988Sjohnlev 	intptr_t cpuid = 0;
135843e1988Sjohnlev 	uint_t verbose = 0;
136843e1988Sjohnlev 	int i;
137843e1988Sjohnlev 
138843e1988Sjohnlev 	if (flags & DCMD_ADDRSPEC) {
139843e1988Sjohnlev 		if ((cpuid = kt_cpu2cpuid(addr)) < 0) {
140843e1988Sjohnlev 			(void) set_errno(EMDB_NOMAP);
141843e1988Sjohnlev 			mdb_warn("failed to find cpuid for cpu at %p", addr);
142843e1988Sjohnlev 			return (DCMD_ERR);
143843e1988Sjohnlev 		}
144843e1988Sjohnlev 		flags &= ~DCMD_ADDRSPEC;
145843e1988Sjohnlev 	}
146843e1988Sjohnlev 
147843e1988Sjohnlev 
148843e1988Sjohnlev 	i = mdb_getopts(argc, argv,
149843e1988Sjohnlev 	    'c', MDB_OPT_UINTPTR, &cpuid,
150843e1988Sjohnlev 	    'v', MDB_OPT_SETBITS, 1, &verbose,
151843e1988Sjohnlev 	    NULL);
152843e1988Sjohnlev 
153843e1988Sjohnlev 	argc -= i;
154843e1988Sjohnlev 	argv += i;
155843e1988Sjohnlev 
156843e1988Sjohnlev 	if (kt_kvmregs(t, cpuid, &regs) != 0) {
157843e1988Sjohnlev 		mdb_warn("failed to get regs for cpu %d\n", cpuid);
158843e1988Sjohnlev 		return (DCMD_ERR);
159843e1988Sjohnlev 	}
160843e1988Sjohnlev 
161843e1988Sjohnlev 	/*
162843e1988Sjohnlev 	 * Tell the stack walker that we have regs.
163843e1988Sjohnlev 	 */
164843e1988Sjohnlev 	flags |= DCMD_ADDRSPEC;
165843e1988Sjohnlev 	addr = regs.kregs[KREG_FP];
166843e1988Sjohnlev 
167843e1988Sjohnlev 	if (verbose)
168843e1988Sjohnlev 		return (kt_stackv(addr, flags, argc, argv));
169843e1988Sjohnlev 	else
170843e1988Sjohnlev 		return (kt_stack(addr, flags, argc, argv));
171843e1988Sjohnlev }
172843e1988Sjohnlev 
173843e1988Sjohnlev /*ARGSUSED*/
174843e1988Sjohnlev int
175843e1988Sjohnlev kt_cpuregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
176843e1988Sjohnlev {
177843e1988Sjohnlev 	mdb_tgt_t *t = mdb.m_target;
178843e1988Sjohnlev 	mdb_tgt_gregset_t regs;
179843e1988Sjohnlev 	intptr_t cpuid = 0;
180843e1988Sjohnlev 	int i;
181843e1988Sjohnlev 
182843e1988Sjohnlev 	if (flags & DCMD_ADDRSPEC) {
183843e1988Sjohnlev 		if (argc != 0)
184843e1988Sjohnlev 			return (DCMD_USAGE);
185843e1988Sjohnlev 		if ((cpuid = kt_cpu2cpuid(addr)) < 0) {
186843e1988Sjohnlev 			(void) set_errno(EMDB_NOMAP);
187843e1988Sjohnlev 			mdb_warn("failed to find cpuid for cpu at %p", addr);
188843e1988Sjohnlev 			return (DCMD_ERR);
189843e1988Sjohnlev 		}
190843e1988Sjohnlev 	}
191843e1988Sjohnlev 
192843e1988Sjohnlev 
193843e1988Sjohnlev 	i = mdb_getopts(argc, argv,
194843e1988Sjohnlev 	    'c', MDB_OPT_UINTPTR, &cpuid,
195843e1988Sjohnlev 	    NULL);
196843e1988Sjohnlev 
197843e1988Sjohnlev 	argc -= i;
198843e1988Sjohnlev 	argv += i;
199843e1988Sjohnlev 
200843e1988Sjohnlev 	if (argc != 0)
201843e1988Sjohnlev 		return (DCMD_USAGE);
202843e1988Sjohnlev 
203843e1988Sjohnlev 	if (kt_kvmregs(t, cpuid, &regs) != 0) {
204843e1988Sjohnlev 		mdb_warn("failed to get regs for cpu %d\n", cpuid);
205843e1988Sjohnlev 		return (DCMD_ERR);
206843e1988Sjohnlev 	}
207843e1988Sjohnlev 
208843e1988Sjohnlev 	return (kt_regs((uintptr_t)&regs, flags, argc, argv));
209843e1988Sjohnlev }
210