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