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 }