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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * This plugin supports debugging functionality unique to Intel processors based
28 * on the NetBurst (P4) microarchitecture. It also supports the Pentium M, a
29 * processor which uses the P6 family code but provides a P4-style branch
30 * tracing stack.
31 */
32
33 #include <kmdb/kvm_cpu_impl.h>
34 #include <kmdb/kmdb_dpi.h>
35 #include <kmdb/kmdb_kdi.h>
36 #include <kmdb/kvm.h>
37 #include <mdb/mdb_err.h>
38 #include <mdb/mdb_debug.h>
39 #include <mdb/mdb.h>
40
41 #include <sys/x86_archext.h>
42
43 /*
44 * As of this writing, Intel has three different flavors of branch stack.
45 * They're essentially the same, but the MSR addresses, stack size, and access
46 * methods differ. We've got one kmt_p4_flavor_t for each type of branch
47 * stack.
48 */
49 typedef struct kmt_p4_flavor {
50 const char *p4f_name; /* name for CPU support */
51 const kdi_msr_t *p4f_msrs; /* MSR r/w list */
52 int (*p4f_branches)(const struct kmt_p4_flavor *, uint_t,
53 intptr_t, int); /* dumper for CPU branch stk */
54 uint_t p4f_msr_tos; /* branch stk index MSR */
55 uint_t p4f_lbrstk_from_base; /* low "from" branch stk MSR */
56 uint_t p4f_lbrstk_to_base; /* low "to" branch stk MSR */
57 size_t p4f_lbrstk_num; /* number of entries in stk */
58 } kmt_p4_flavor_t;
59
60 typedef struct kmt_cpu_p4 {
61 uint64_t p4_debugctl; /* value for debugctl MSR */
62 const kmt_p4_flavor_t *p4_flavor; /* parameters for this proc */
63 uint_t p4_model; /* CPUID model */
64 } kmt_cpu_p4_t;
65
66 /* See 07/04 AP-485 Intel Processor Identification and the CPUID Instruction */
67 #define KMT_CPU_FAMILY_P6 0x6 /* For this plugin, the Pentium M */
68 #define KMT_CPU_FAMILY_P4 0xf /* "Netburst" CPUs (P4s) */
69 #define KMT_CPU_MODEL_PM_9 0x9 /* Pentium M, model 9 */
70 #define KMT_CPU_MODEL_PM_D 0xd /* Pentium M, model d */
71
72
73 static kmt_cpu_p4_t kmt_cpu_p4;
74
75 static void
kmt_p4_branch(uintptr_t from,uintptr_t to,int verbose)76 kmt_p4_branch(uintptr_t from, uintptr_t to, int verbose)
77 {
78 if (verbose) {
79 uintptr_t addr = mdb_dis_previns(mdb.m_disasm, mdb.m_target,
80 MDB_TGT_AS_VIRT, from, 3);
81
82 mdb_printf("%<b>%-39a %-39a%</b>\n", from, to);
83
84 while (addr <= from) {
85 char buf[80];
86 uintptr_t next;
87 char *c;
88
89 if ((next = mdb_dis_ins2str(mdb.m_disasm, mdb.m_target,
90 MDB_TGT_AS_VIRT, buf, sizeof (buf), addr)) == addr)
91 (void) strcpy(buf, "???");
92
93 for (c = buf + strlen(buf) - 1;
94 c > buf && (*c == ' ' || *c == '\t');
95 c--)
96 ;
97
98 if (*c == '>') {
99 while (c > buf && *c != '<')
100 c--;
101
102 if (*c == '<')
103 *c = '\0';
104 }
105
106 if (addr == from) {
107 mdb_printf("\t%<b>%-#32a%8T%s%</b>\n",
108 addr, buf);
109 } else {
110 mdb_printf("\t%-#32a%8T%s\n", addr, buf);
111 }
112
113 if (next == addr)
114 break;
115
116 addr = next;
117 }
118 mdb_printf("\n");
119 } else {
120 mdb_printf("%-39a %-39a\n", from, to);
121 }
122 }
123
124 #ifndef __amd64
125 static int
kmt_p4_branches_unified(const kmt_p4_flavor_t * p4f,uint_t tos,intptr_t cpuid,int verbose)126 kmt_p4_branches_unified(const kmt_p4_flavor_t *p4f, uint_t tos, intptr_t cpuid,
127 int verbose)
128 {
129 uint_t cur;
130 int i;
131
132 for (cur = tos, i = 0; i < p4f->p4f_lbrstk_num;
133 i++, cur = (cur + p4f->p4f_lbrstk_num - 1) % p4f->p4f_lbrstk_num) {
134 uint64_t rec = kmdb_dpi_msr_get_by_cpu(cpuid,
135 p4f->p4f_lbrstk_from_base + cur);
136
137 kmt_p4_branch((rec & 0xffffffff), rec >> 32, verbose);
138 }
139
140 return (0);
141 }
142 #endif /* !__amd64 */
143
144 static int
kmt_p4_branches_split(const kmt_p4_flavor_t * p4f,uint_t tos,intptr_t cpuid,int verbose)145 kmt_p4_branches_split(const kmt_p4_flavor_t *p4f, uint_t tos, intptr_t cpuid,
146 int verbose)
147 {
148 uint_t cur;
149 int i;
150
151 for (cur = tos, i = 0; i < p4f->p4f_lbrstk_num;
152 i++, cur = (cur + p4f->p4f_lbrstk_num - 1) % p4f->p4f_lbrstk_num) {
153 uintptr_t from = (uintptr_t)kmdb_dpi_msr_get_by_cpu(cpuid,
154 p4f->p4f_lbrstk_from_base + cur);
155 uintptr_t to = (uintptr_t)kmdb_dpi_msr_get_by_cpu(cpuid,
156 p4f->p4f_lbrstk_to_base + cur);
157
158 kmt_p4_branch(from, to, verbose);
159 }
160
161 return (0);
162 }
163
164 #ifndef __amd64
165 static const kdi_msr_t kmt_p4orig_msrs[] = {
166 { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY },
167 { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl },
168 { MSR_P4_LBSTK_TOS, KDI_MSR_READ },
169 { MSR_P4_LBSTK_0, KDI_MSR_READ },
170 { MSR_P4_LBSTK_1, KDI_MSR_READ },
171 { MSR_P4_LBSTK_2, KDI_MSR_READ },
172 { MSR_P4_LBSTK_3, KDI_MSR_READ },
173 { NULL }
174 };
175
176 static const kmt_p4_flavor_t kmt_p4_original = {
177 "Intel Pentium 4 (pre-Prescott)",
178 kmt_p4orig_msrs, kmt_p4_branches_unified, MSR_P4_LBSTK_TOS,
179 MSR_P4_LBSTK_0, MSR_P4_LBSTK_0, 4
180 };
181
182 static const kdi_msr_t kmt_p6m_msrs[] = {
183 { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY },
184 { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl },
185 { MSR_P6M_LBSTK_TOS, KDI_MSR_READ },
186 { MSR_P6M_LBSTK_0, KDI_MSR_READ },
187 { MSR_P6M_LBSTK_1, KDI_MSR_READ },
188 { MSR_P6M_LBSTK_2, KDI_MSR_READ },
189 { MSR_P6M_LBSTK_3, KDI_MSR_READ },
190 { MSR_P6M_LBSTK_4, KDI_MSR_READ },
191 { MSR_P6M_LBSTK_5, KDI_MSR_READ },
192 { MSR_P6M_LBSTK_6, KDI_MSR_READ },
193 { MSR_P6M_LBSTK_7, KDI_MSR_READ },
194 { NULL }
195 };
196
197 static const kmt_p4_flavor_t kmt_p6_m = {
198 "Intel Pentium M",
199 kmt_p6m_msrs, kmt_p4_branches_unified, MSR_P6M_LBSTK_TOS,
200 MSR_P6M_LBSTK_0, MSR_P6M_LBSTK_0, 8
201 };
202 #endif /* __amd64 */
203
204 static const kdi_msr_t kmt_prp4_msrs[] = {
205 { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY },
206 { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl },
207 { MSR_PRP4_LBSTK_TOS, KDI_MSR_READ },
208 { MSR_PRP4_LBSTK_FROM_0, KDI_MSR_READ },
209 { MSR_PRP4_LBSTK_FROM_1, KDI_MSR_READ },
210 { MSR_PRP4_LBSTK_FROM_2, KDI_MSR_READ },
211 { MSR_PRP4_LBSTK_FROM_3, KDI_MSR_READ },
212 { MSR_PRP4_LBSTK_FROM_4, KDI_MSR_READ },
213 { MSR_PRP4_LBSTK_FROM_5, KDI_MSR_READ },
214 { MSR_PRP4_LBSTK_FROM_6, KDI_MSR_READ },
215 { MSR_PRP4_LBSTK_FROM_7, KDI_MSR_READ },
216 { MSR_PRP4_LBSTK_FROM_8, KDI_MSR_READ },
217 { MSR_PRP4_LBSTK_FROM_9, KDI_MSR_READ },
218 { MSR_PRP4_LBSTK_FROM_10, KDI_MSR_READ },
219 { MSR_PRP4_LBSTK_FROM_11, KDI_MSR_READ },
220 { MSR_PRP4_LBSTK_FROM_12, KDI_MSR_READ },
221 { MSR_PRP4_LBSTK_FROM_13, KDI_MSR_READ },
222 { MSR_PRP4_LBSTK_FROM_14, KDI_MSR_READ },
223 { MSR_PRP4_LBSTK_FROM_15, KDI_MSR_READ },
224 { MSR_PRP4_LBSTK_TO_0, KDI_MSR_READ },
225 { MSR_PRP4_LBSTK_TO_1, KDI_MSR_READ },
226 { MSR_PRP4_LBSTK_TO_2, KDI_MSR_READ },
227 { MSR_PRP4_LBSTK_TO_3, KDI_MSR_READ },
228 { MSR_PRP4_LBSTK_TO_4, KDI_MSR_READ },
229 { MSR_PRP4_LBSTK_TO_5, KDI_MSR_READ },
230 { MSR_PRP4_LBSTK_TO_6, KDI_MSR_READ },
231 { MSR_PRP4_LBSTK_TO_7, KDI_MSR_READ },
232 { MSR_PRP4_LBSTK_TO_8, KDI_MSR_READ },
233 { MSR_PRP4_LBSTK_TO_9, KDI_MSR_READ },
234 { MSR_PRP4_LBSTK_TO_10, KDI_MSR_READ },
235 { MSR_PRP4_LBSTK_TO_11, KDI_MSR_READ },
236 { MSR_PRP4_LBSTK_TO_12, KDI_MSR_READ },
237 { MSR_PRP4_LBSTK_TO_13, KDI_MSR_READ },
238 { MSR_PRP4_LBSTK_TO_14, KDI_MSR_READ },
239 { MSR_PRP4_LBSTK_TO_15, KDI_MSR_READ },
240 { NULL }
241 };
242
243 static const kmt_p4_flavor_t kmt_p4_prescott = {
244 "Intel Pentium 4 (Prescott)",
245 kmt_prp4_msrs, kmt_p4_branches_split, MSR_PRP4_LBSTK_TOS,
246 MSR_PRP4_LBSTK_FROM_0, MSR_PRP4_LBSTK_TO_0, 16
247 };
248
249 static const kdi_msr_t kmt_p4unk_msrs[] = {
250 { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY },
251 { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl },
252 { NULL }
253 };
254
255 static const kmt_p4_flavor_t kmt_p4_unknown = {
256 "Unrecognized Intel Pentium 4",
257 kmt_p4unk_msrs, NULL, 0,
258 0, 0, 0
259 };
260
261 /*ARGSUSED*/
262 static void
kmt_p4_destroy(kmt_cpu_t * cpu)263 kmt_p4_destroy(kmt_cpu_t *cpu)
264 {
265 /* Leave LBR on */
266
267 mdb_free(cpu, sizeof (kmt_cpu_t));
268 }
269
270 /*ARGSUSED*/
271 static const char *
kmt_p4_name(kmt_cpu_t * cpu)272 kmt_p4_name(kmt_cpu_t *cpu)
273 {
274 return (kmt_cpu_p4.p4_flavor->p4f_name);
275 }
276
277 /*ARGSUSED*/
278 static void
kmt_p4_btf_clear(mdb_tgt_t * t,int id,void * arg)279 kmt_p4_btf_clear(mdb_tgt_t *t, int id, void *arg)
280 {
281 kmt_cpu_p4_t *p4 = arg;
282 kreg_t efl;
283
284 p4->p4_debugctl &= ~DEBUGCTL_BTF;
285
286 (void) kmdb_dpi_get_register("eflags", &efl);
287 efl &= ~(1 << KREG_EFLAGS_TF_SHIFT);
288 (void) kmdb_dpi_set_register("eflags", efl);
289 }
290
291 static int
kmt_p4_step_branch(kmt_cpu_t * cpu,mdb_tgt_t * t)292 kmt_p4_step_branch(kmt_cpu_t *cpu, mdb_tgt_t *t)
293 {
294 kmt_cpu_p4_t *p4 = cpu->kmt_cpu_data;
295 kreg_t efl;
296
297 (void) kmdb_dpi_get_register("eflags", &efl);
298 (void) kmdb_dpi_set_register("eflags",
299 (efl | (1 << KREG_EFLAGS_TF_SHIFT)));
300
301 p4->p4_debugctl |= DEBUGCTL_BTF;
302
303 return (mdb_tgt_add_fault(t, KMT_TRAP_ALL,
304 MDB_TGT_SPEC_HIDDEN | MDB_TGT_SPEC_TEMPORARY,
305 kmt_p4_btf_clear, p4));
306 }
307
308 static kmt_cpu_ops_t kmt_p4_ops = {
309 kmt_p4_destroy,
310 kmt_p4_name,
311 kmt_p4_step_branch
312 };
313
314 /*ARGSUSED*/
315 static int
kmt_p4_branches(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)316 kmt_p4_branches(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
317 {
318 const kmt_p4_flavor_t *p4f = kmt_cpu_p4.p4_flavor;
319 intptr_t cpuid = DPI_MASTER_CPUID;
320 uint_t tos;
321 int verbose = FALSE;
322
323 if (p4f->p4f_branches == NULL) {
324 warn("branch tracing unavailable on unknown P4 CPU "
325 "(model %x)\n", kmt_cpu_p4.p4_model);
326 return (DCMD_ERR);
327 }
328
329 if (mdb_getopts(argc, argv,
330 'c', MDB_OPT_UINTPTR, &cpuid,
331 'v', MDB_OPT_SETBITS, TRUE, &verbose,
332 NULL) != argc)
333 return (DCMD_USAGE);
334
335 ASSERT(!(p4f->p4f_lbrstk_num & (p4f->p4f_lbrstk_num - 1)));
336
337 tos = (uintptr_t)kmdb_dpi_msr_get_by_cpu(cpuid, p4f->p4f_msr_tos);
338 tos &= p4f->p4f_lbrstk_num - 1;
339
340 mdb_printf("%<u>%-39s %-39s%</u>\n", "FROM", "TO");
341
342 return (p4f->p4f_branches(p4f, tos, cpuid, verbose));
343 }
344
345 static const mdb_dcmd_t kmt_p4_dcmds[] = {
346 { "branches", NULL, "describe the recently-taken branches",
347 kmt_p4_branches },
348 { NULL }
349 };
350
351 /*ARGSUSED*/
352 const kmt_p4_flavor_t *
cpu2flavor(uint_t vendor,uint_t family,uint_t model)353 cpu2flavor(uint_t vendor, uint_t family, uint_t model)
354 {
355 if (vendor != X86_VENDOR_Intel)
356 return (NULL);
357
358 #ifndef __amd64
359 if (family == KMT_CPU_FAMILY_P6) {
360 if (model == KMT_CPU_MODEL_PM_9 || model == KMT_CPU_MODEL_PM_D)
361 return (&kmt_p6_m);
362 else
363 return (NULL);
364 }
365
366 if (family == KMT_CPU_FAMILY_P4 && model < 3)
367 return (&kmt_p4_original);
368 #endif /* !__amd64 */
369
370 if (family == KMT_CPU_FAMILY_P4) {
371 /*
372 * If this is a model 3, then we've got a Prescott. On the
373 * other hand, this could be the future, and Intel could have
374 * released a whizzy new processor. Users shouldn't have to
375 * wait for us to patch the debugger for each new P4 model,
376 * so we'll try to use this CPU as a Prescott. In the past,
377 * when Intel has changed the branch stack, they've done it by
378 * moving the MSRs, returning #gp's for the old ones. Our
379 * Prescott check will therefore be an attempt to read the
380 * Prescott MSRs. This attempt should fail if Intel has changed
381 * the branch stack again.
382 */
383 if (kmt_msr_validate(kmt_prp4_msrs))
384 return (&kmt_p4_prescott);
385 else
386 return (&kmt_p4_unknown);
387 }
388
389 return (NULL);
390 }
391
392 kmt_cpu_t *
kmt_cpu_p4_create(mdb_tgt_t * t)393 kmt_cpu_p4_create(mdb_tgt_t *t)
394 {
395 uint_t vendor, family, model;
396 kmt_cpu_t *cpu;
397
398 if (kmdb_kdi_get_cpuinfo(&vendor, &family, &model) < 0)
399 return (NULL); /* errno is set for us */
400
401 if ((kmt_cpu_p4.p4_flavor = cpu2flavor(vendor, family, model)) ==
402 NULL) {
403 (void) set_errno(ENOTSUP);
404 return (NULL);
405 }
406
407 kmt_cpu_p4.p4_model = model;
408 kmt_cpu_p4.p4_debugctl = DEBUGCTL_LBR; /* enable LBR on resume */
409
410 cpu = mdb_zalloc(sizeof (kmt_cpu_t), UM_SLEEP);
411 cpu->kmt_cpu_ops = &kmt_p4_ops;
412 cpu->kmt_cpu_data = &kmt_cpu_p4;
413
414 kmdb_dpi_msr_add(kmt_cpu_p4.p4_flavor->p4f_msrs);
415 (void) mdb_tgt_register_dcmds(t, kmt_p4_dcmds, MDB_MOD_FORCE);
416
417 return (cpu);
418 }
419