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 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 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 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 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 * 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 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 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 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 * 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 * 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