10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53446Smrj * Common Development and Distribution License (the "License").
63446Smrj * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*11053SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * This plugin supports debugging functionality unique to Intel processors based
280Sstevel@tonic-gate * on the NetBurst (P4) microarchitecture. It also supports the Pentium M, a
290Sstevel@tonic-gate * processor which uses the P6 family code but provides a P4-style branch
300Sstevel@tonic-gate * tracing stack.
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
330Sstevel@tonic-gate #include <kmdb/kvm_cpu_impl.h>
340Sstevel@tonic-gate #include <kmdb/kmdb_dpi.h>
350Sstevel@tonic-gate #include <kmdb/kmdb_kdi.h>
360Sstevel@tonic-gate #include <kmdb/kvm.h>
370Sstevel@tonic-gate #include <mdb/mdb_err.h>
380Sstevel@tonic-gate #include <mdb/mdb_debug.h>
390Sstevel@tonic-gate #include <mdb/mdb.h>
400Sstevel@tonic-gate
410Sstevel@tonic-gate #include <sys/x86_archext.h>
420Sstevel@tonic-gate
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate * As of this writing, Intel has three different flavors of branch stack.
450Sstevel@tonic-gate * They're essentially the same, but the MSR addresses, stack size, and access
460Sstevel@tonic-gate * methods differ. We've got one kmt_p4_flavor_t for each type of branch
470Sstevel@tonic-gate * stack.
480Sstevel@tonic-gate */
490Sstevel@tonic-gate typedef struct kmt_p4_flavor {
500Sstevel@tonic-gate const char *p4f_name; /* name for CPU support */
513446Smrj const kdi_msr_t *p4f_msrs; /* MSR r/w list */
520Sstevel@tonic-gate int (*p4f_branches)(const struct kmt_p4_flavor *, uint_t,
530Sstevel@tonic-gate intptr_t, int); /* dumper for CPU branch stk */
540Sstevel@tonic-gate uint_t p4f_msr_tos; /* branch stk index MSR */
550Sstevel@tonic-gate uint_t p4f_lbrstk_from_base; /* low "from" branch stk MSR */
560Sstevel@tonic-gate uint_t p4f_lbrstk_to_base; /* low "to" branch stk MSR */
570Sstevel@tonic-gate size_t p4f_lbrstk_num; /* number of entries in stk */
580Sstevel@tonic-gate } kmt_p4_flavor_t;
590Sstevel@tonic-gate
600Sstevel@tonic-gate typedef struct kmt_cpu_p4 {
610Sstevel@tonic-gate uint64_t p4_debugctl; /* value for debugctl MSR */
620Sstevel@tonic-gate const kmt_p4_flavor_t *p4_flavor; /* parameters for this proc */
630Sstevel@tonic-gate uint_t p4_model; /* CPUID model */
640Sstevel@tonic-gate } kmt_cpu_p4_t;
650Sstevel@tonic-gate
660Sstevel@tonic-gate /* See 07/04 AP-485 Intel Processor Identification and the CPUID Instruction */
670Sstevel@tonic-gate #define KMT_CPU_FAMILY_P6 0x6 /* For this plugin, the Pentium M */
680Sstevel@tonic-gate #define KMT_CPU_FAMILY_P4 0xf /* "Netburst" CPUs (P4s) */
690Sstevel@tonic-gate #define KMT_CPU_MODEL_PM_9 0x9 /* Pentium M, model 9 */
700Sstevel@tonic-gate #define KMT_CPU_MODEL_PM_D 0xd /* Pentium M, model d */
710Sstevel@tonic-gate
720Sstevel@tonic-gate
730Sstevel@tonic-gate static kmt_cpu_p4_t kmt_cpu_p4;
740Sstevel@tonic-gate
750Sstevel@tonic-gate static void
kmt_p4_branch(uintptr_t from,uintptr_t to,int verbose)760Sstevel@tonic-gate kmt_p4_branch(uintptr_t from, uintptr_t to, int verbose)
770Sstevel@tonic-gate {
780Sstevel@tonic-gate if (verbose) {
790Sstevel@tonic-gate uintptr_t addr = mdb_dis_previns(mdb.m_disasm, mdb.m_target,
800Sstevel@tonic-gate MDB_TGT_AS_VIRT, from, 3);
810Sstevel@tonic-gate
820Sstevel@tonic-gate mdb_printf("%<b>%-39a %-39a%</b>\n", from, to);
830Sstevel@tonic-gate
840Sstevel@tonic-gate while (addr <= from) {
850Sstevel@tonic-gate char buf[80];
860Sstevel@tonic-gate uintptr_t next;
870Sstevel@tonic-gate char *c;
880Sstevel@tonic-gate
890Sstevel@tonic-gate if ((next = mdb_dis_ins2str(mdb.m_disasm, mdb.m_target,
900Sstevel@tonic-gate MDB_TGT_AS_VIRT, buf, sizeof (buf), addr)) == addr)
91*11053SSurya.Prakki@Sun.COM (void) strcpy(buf, "???");
920Sstevel@tonic-gate
930Sstevel@tonic-gate for (c = buf + strlen(buf) - 1;
940Sstevel@tonic-gate c > buf && (*c == ' ' || *c == '\t');
95*11053SSurya.Prakki@Sun.COM c--)
96*11053SSurya.Prakki@Sun.COM ;
970Sstevel@tonic-gate
980Sstevel@tonic-gate if (*c == '>') {
990Sstevel@tonic-gate while (c > buf && *c != '<')
1000Sstevel@tonic-gate c--;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate if (*c == '<')
1030Sstevel@tonic-gate *c = '\0';
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate if (addr == from) {
1070Sstevel@tonic-gate mdb_printf("\t%<b>%-#32a%8T%s%</b>\n",
1080Sstevel@tonic-gate addr, buf);
1090Sstevel@tonic-gate } else {
1100Sstevel@tonic-gate mdb_printf("\t%-#32a%8T%s\n", addr, buf);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate if (next == addr)
1140Sstevel@tonic-gate break;
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate addr = next;
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate mdb_printf("\n");
1190Sstevel@tonic-gate } else {
1200Sstevel@tonic-gate mdb_printf("%-39a %-39a\n", from, to);
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate #ifndef __amd64
1250Sstevel@tonic-gate static int
kmt_p4_branches_unified(const kmt_p4_flavor_t * p4f,uint_t tos,intptr_t cpuid,int verbose)1260Sstevel@tonic-gate kmt_p4_branches_unified(const kmt_p4_flavor_t *p4f, uint_t tos, intptr_t cpuid,
1270Sstevel@tonic-gate int verbose)
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate uint_t cur;
1300Sstevel@tonic-gate int i;
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate for (cur = tos, i = 0; i < p4f->p4f_lbrstk_num;
1330Sstevel@tonic-gate i++, cur = (cur + p4f->p4f_lbrstk_num - 1) % p4f->p4f_lbrstk_num) {
1340Sstevel@tonic-gate uint64_t rec = kmdb_dpi_msr_get_by_cpu(cpuid,
1350Sstevel@tonic-gate p4f->p4f_lbrstk_from_base + cur);
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate kmt_p4_branch((rec & 0xffffffff), rec >> 32, verbose);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate return (0);
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate #endif /* !__amd64 */
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate static int
kmt_p4_branches_split(const kmt_p4_flavor_t * p4f,uint_t tos,intptr_t cpuid,int verbose)1450Sstevel@tonic-gate kmt_p4_branches_split(const kmt_p4_flavor_t *p4f, uint_t tos, intptr_t cpuid,
1460Sstevel@tonic-gate int verbose)
1470Sstevel@tonic-gate {
1480Sstevel@tonic-gate uint_t cur;
1490Sstevel@tonic-gate int i;
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate for (cur = tos, i = 0; i < p4f->p4f_lbrstk_num;
1520Sstevel@tonic-gate i++, cur = (cur + p4f->p4f_lbrstk_num - 1) % p4f->p4f_lbrstk_num) {
1530Sstevel@tonic-gate uintptr_t from = (uintptr_t)kmdb_dpi_msr_get_by_cpu(cpuid,
1540Sstevel@tonic-gate p4f->p4f_lbrstk_from_base + cur);
1550Sstevel@tonic-gate uintptr_t to = (uintptr_t)kmdb_dpi_msr_get_by_cpu(cpuid,
1560Sstevel@tonic-gate p4f->p4f_lbrstk_to_base + cur);
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate kmt_p4_branch(from, to, verbose);
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate return (0);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate #ifndef __amd64
1653446Smrj static const kdi_msr_t kmt_p4orig_msrs[] = {
1663446Smrj { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY },
1673446Smrj { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl },
1683446Smrj { MSR_P4_LBSTK_TOS, KDI_MSR_READ },
1693446Smrj { MSR_P4_LBSTK_0, KDI_MSR_READ },
1703446Smrj { MSR_P4_LBSTK_1, KDI_MSR_READ },
1713446Smrj { MSR_P4_LBSTK_2, KDI_MSR_READ },
1723446Smrj { MSR_P4_LBSTK_3, KDI_MSR_READ },
1730Sstevel@tonic-gate { NULL }
1740Sstevel@tonic-gate };
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate static const kmt_p4_flavor_t kmt_p4_original = {
1770Sstevel@tonic-gate "Intel Pentium 4 (pre-Prescott)",
1780Sstevel@tonic-gate kmt_p4orig_msrs, kmt_p4_branches_unified, MSR_P4_LBSTK_TOS,
1790Sstevel@tonic-gate MSR_P4_LBSTK_0, MSR_P4_LBSTK_0, 4
1800Sstevel@tonic-gate };
1810Sstevel@tonic-gate
1823446Smrj static const kdi_msr_t kmt_p6m_msrs[] = {
1833446Smrj { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY },
1843446Smrj { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl },
1853446Smrj { MSR_P6M_LBSTK_TOS, KDI_MSR_READ },
1863446Smrj { MSR_P6M_LBSTK_0, KDI_MSR_READ },
1873446Smrj { MSR_P6M_LBSTK_1, KDI_MSR_READ },
1883446Smrj { MSR_P6M_LBSTK_2, KDI_MSR_READ },
1893446Smrj { MSR_P6M_LBSTK_3, KDI_MSR_READ },
1903446Smrj { MSR_P6M_LBSTK_4, KDI_MSR_READ },
1913446Smrj { MSR_P6M_LBSTK_5, KDI_MSR_READ },
1923446Smrj { MSR_P6M_LBSTK_6, KDI_MSR_READ },
1933446Smrj { MSR_P6M_LBSTK_7, KDI_MSR_READ },
1940Sstevel@tonic-gate { NULL }
1950Sstevel@tonic-gate };
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate static const kmt_p4_flavor_t kmt_p6_m = {
1980Sstevel@tonic-gate "Intel Pentium M",
1990Sstevel@tonic-gate kmt_p6m_msrs, kmt_p4_branches_unified, MSR_P6M_LBSTK_TOS,
2000Sstevel@tonic-gate MSR_P6M_LBSTK_0, MSR_P6M_LBSTK_0, 8
2010Sstevel@tonic-gate };
2020Sstevel@tonic-gate #endif /* __amd64 */
2030Sstevel@tonic-gate
2043446Smrj static const kdi_msr_t kmt_prp4_msrs[] = {
2053446Smrj { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY },
2063446Smrj { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl },
2073446Smrj { MSR_PRP4_LBSTK_TOS, KDI_MSR_READ },
2083446Smrj { MSR_PRP4_LBSTK_FROM_0, KDI_MSR_READ },
2093446Smrj { MSR_PRP4_LBSTK_FROM_1, KDI_MSR_READ },
2103446Smrj { MSR_PRP4_LBSTK_FROM_2, KDI_MSR_READ },
2113446Smrj { MSR_PRP4_LBSTK_FROM_3, KDI_MSR_READ },
2123446Smrj { MSR_PRP4_LBSTK_FROM_4, KDI_MSR_READ },
2133446Smrj { MSR_PRP4_LBSTK_FROM_5, KDI_MSR_READ },
2143446Smrj { MSR_PRP4_LBSTK_FROM_6, KDI_MSR_READ },
2153446Smrj { MSR_PRP4_LBSTK_FROM_7, KDI_MSR_READ },
2163446Smrj { MSR_PRP4_LBSTK_FROM_8, KDI_MSR_READ },
2173446Smrj { MSR_PRP4_LBSTK_FROM_9, KDI_MSR_READ },
2183446Smrj { MSR_PRP4_LBSTK_FROM_10, KDI_MSR_READ },
2193446Smrj { MSR_PRP4_LBSTK_FROM_11, KDI_MSR_READ },
2203446Smrj { MSR_PRP4_LBSTK_FROM_12, KDI_MSR_READ },
2213446Smrj { MSR_PRP4_LBSTK_FROM_13, KDI_MSR_READ },
2223446Smrj { MSR_PRP4_LBSTK_FROM_14, KDI_MSR_READ },
2233446Smrj { MSR_PRP4_LBSTK_FROM_15, KDI_MSR_READ },
2243446Smrj { MSR_PRP4_LBSTK_TO_0, KDI_MSR_READ },
2253446Smrj { MSR_PRP4_LBSTK_TO_1, KDI_MSR_READ },
2263446Smrj { MSR_PRP4_LBSTK_TO_2, KDI_MSR_READ },
2273446Smrj { MSR_PRP4_LBSTK_TO_3, KDI_MSR_READ },
2283446Smrj { MSR_PRP4_LBSTK_TO_4, KDI_MSR_READ },
2293446Smrj { MSR_PRP4_LBSTK_TO_5, KDI_MSR_READ },
2303446Smrj { MSR_PRP4_LBSTK_TO_6, KDI_MSR_READ },
2313446Smrj { MSR_PRP4_LBSTK_TO_7, KDI_MSR_READ },
2323446Smrj { MSR_PRP4_LBSTK_TO_8, KDI_MSR_READ },
2333446Smrj { MSR_PRP4_LBSTK_TO_9, KDI_MSR_READ },
2343446Smrj { MSR_PRP4_LBSTK_TO_10, KDI_MSR_READ },
2353446Smrj { MSR_PRP4_LBSTK_TO_11, KDI_MSR_READ },
2363446Smrj { MSR_PRP4_LBSTK_TO_12, KDI_MSR_READ },
2373446Smrj { MSR_PRP4_LBSTK_TO_13, KDI_MSR_READ },
2383446Smrj { MSR_PRP4_LBSTK_TO_14, KDI_MSR_READ },
2393446Smrj { MSR_PRP4_LBSTK_TO_15, KDI_MSR_READ },
2400Sstevel@tonic-gate { NULL }
2410Sstevel@tonic-gate };
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate static const kmt_p4_flavor_t kmt_p4_prescott = {
2440Sstevel@tonic-gate "Intel Pentium 4 (Prescott)",
2450Sstevel@tonic-gate kmt_prp4_msrs, kmt_p4_branches_split, MSR_PRP4_LBSTK_TOS,
2460Sstevel@tonic-gate MSR_PRP4_LBSTK_FROM_0, MSR_PRP4_LBSTK_TO_0, 16
2470Sstevel@tonic-gate };
2480Sstevel@tonic-gate
2493446Smrj static const kdi_msr_t kmt_p4unk_msrs[] = {
2503446Smrj { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY },
2513446Smrj { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl },
2520Sstevel@tonic-gate { NULL }
2530Sstevel@tonic-gate };
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate static const kmt_p4_flavor_t kmt_p4_unknown = {
2560Sstevel@tonic-gate "Unrecognized Intel Pentium 4",
2570Sstevel@tonic-gate kmt_p4unk_msrs, NULL, 0,
2580Sstevel@tonic-gate 0, 0, 0
2590Sstevel@tonic-gate };
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate /*ARGSUSED*/
2620Sstevel@tonic-gate static void
kmt_p4_destroy(kmt_cpu_t * cpu)2630Sstevel@tonic-gate kmt_p4_destroy(kmt_cpu_t *cpu)
2640Sstevel@tonic-gate {
2650Sstevel@tonic-gate /* Leave LBR on */
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate mdb_free(cpu, sizeof (kmt_cpu_t));
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate /*ARGSUSED*/
2710Sstevel@tonic-gate static const char *
kmt_p4_name(kmt_cpu_t * cpu)2720Sstevel@tonic-gate kmt_p4_name(kmt_cpu_t *cpu)
2730Sstevel@tonic-gate {
2740Sstevel@tonic-gate return (kmt_cpu_p4.p4_flavor->p4f_name);
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate /*ARGSUSED*/
2780Sstevel@tonic-gate static void
kmt_p4_btf_clear(mdb_tgt_t * t,int id,void * arg)2790Sstevel@tonic-gate kmt_p4_btf_clear(mdb_tgt_t *t, int id, void *arg)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate kmt_cpu_p4_t *p4 = arg;
2820Sstevel@tonic-gate kreg_t efl;
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate p4->p4_debugctl &= ~DEBUGCTL_BTF;
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate (void) kmdb_dpi_get_register("eflags", &efl);
2870Sstevel@tonic-gate efl &= ~(1 << KREG_EFLAGS_TF_SHIFT);
2880Sstevel@tonic-gate (void) kmdb_dpi_set_register("eflags", efl);
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate static int
kmt_p4_step_branch(kmt_cpu_t * cpu,mdb_tgt_t * t)2920Sstevel@tonic-gate kmt_p4_step_branch(kmt_cpu_t *cpu, mdb_tgt_t *t)
2930Sstevel@tonic-gate {
2940Sstevel@tonic-gate kmt_cpu_p4_t *p4 = cpu->kmt_cpu_data;
2950Sstevel@tonic-gate kreg_t efl;
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate (void) kmdb_dpi_get_register("eflags", &efl);
2980Sstevel@tonic-gate (void) kmdb_dpi_set_register("eflags",
2990Sstevel@tonic-gate (efl | (1 << KREG_EFLAGS_TF_SHIFT)));
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate p4->p4_debugctl |= DEBUGCTL_BTF;
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate return (mdb_tgt_add_fault(t, KMT_TRAP_ALL,
3040Sstevel@tonic-gate MDB_TGT_SPEC_HIDDEN | MDB_TGT_SPEC_TEMPORARY,
3050Sstevel@tonic-gate kmt_p4_btf_clear, p4));
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate static kmt_cpu_ops_t kmt_p4_ops = {
3090Sstevel@tonic-gate kmt_p4_destroy,
3100Sstevel@tonic-gate kmt_p4_name,
3110Sstevel@tonic-gate kmt_p4_step_branch
3120Sstevel@tonic-gate };
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate /*ARGSUSED*/
3150Sstevel@tonic-gate static int
kmt_p4_branches(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3160Sstevel@tonic-gate kmt_p4_branches(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3170Sstevel@tonic-gate {
3180Sstevel@tonic-gate const kmt_p4_flavor_t *p4f = kmt_cpu_p4.p4_flavor;
3190Sstevel@tonic-gate intptr_t cpuid = DPI_MASTER_CPUID;
3200Sstevel@tonic-gate uint_t tos;
3210Sstevel@tonic-gate int verbose = FALSE;
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate if (p4f->p4f_branches == NULL) {
3240Sstevel@tonic-gate warn("branch tracing unavailable on unknown P4 CPU "
3250Sstevel@tonic-gate "(model %x)\n", kmt_cpu_p4.p4_model);
3260Sstevel@tonic-gate return (DCMD_ERR);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate if (mdb_getopts(argc, argv,
3300Sstevel@tonic-gate 'c', MDB_OPT_UINTPTR, &cpuid,
3310Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose,
3320Sstevel@tonic-gate NULL) != argc)
3330Sstevel@tonic-gate return (DCMD_USAGE);
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate ASSERT(!(p4f->p4f_lbrstk_num & (p4f->p4f_lbrstk_num - 1)));
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate tos = (uintptr_t)kmdb_dpi_msr_get_by_cpu(cpuid, p4f->p4f_msr_tos);
3380Sstevel@tonic-gate tos &= p4f->p4f_lbrstk_num - 1;
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate mdb_printf("%<u>%-39s %-39s%</u>\n", "FROM", "TO");
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate return (p4f->p4f_branches(p4f, tos, cpuid, verbose));
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate static const mdb_dcmd_t kmt_p4_dcmds[] = {
3460Sstevel@tonic-gate { "branches", NULL, "describe the recently-taken branches",
3470Sstevel@tonic-gate kmt_p4_branches },
3480Sstevel@tonic-gate { NULL }
3490Sstevel@tonic-gate };
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate /*ARGSUSED*/
3520Sstevel@tonic-gate const kmt_p4_flavor_t *
cpu2flavor(uint_t vendor,uint_t family,uint_t model)3530Sstevel@tonic-gate cpu2flavor(uint_t vendor, uint_t family, uint_t model)
3540Sstevel@tonic-gate {
3550Sstevel@tonic-gate if (vendor != X86_VENDOR_Intel)
3560Sstevel@tonic-gate return (NULL);
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate #ifndef __amd64
3590Sstevel@tonic-gate if (family == KMT_CPU_FAMILY_P6) {
3600Sstevel@tonic-gate if (model == KMT_CPU_MODEL_PM_9 || model == KMT_CPU_MODEL_PM_D)
3610Sstevel@tonic-gate return (&kmt_p6_m);
3620Sstevel@tonic-gate else
3630Sstevel@tonic-gate return (NULL);
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate if (family == KMT_CPU_FAMILY_P4 && model < 3)
3670Sstevel@tonic-gate return (&kmt_p4_original);
3680Sstevel@tonic-gate #endif /* !__amd64 */
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate if (family == KMT_CPU_FAMILY_P4) {
3710Sstevel@tonic-gate /*
3720Sstevel@tonic-gate * If this is a model 3, then we've got a Prescott. On the
3730Sstevel@tonic-gate * other hand, this could be the future, and Intel could have
3740Sstevel@tonic-gate * released a whizzy new processor. Users shouldn't have to
3750Sstevel@tonic-gate * wait for us to patch the debugger for each new P4 model,
3760Sstevel@tonic-gate * so we'll try to use this CPU as a Prescott. In the past,
3770Sstevel@tonic-gate * when Intel has changed the branch stack, they've done it by
3780Sstevel@tonic-gate * moving the MSRs, returning #gp's for the old ones. Our
3790Sstevel@tonic-gate * Prescott check will therefore be an attempt to read the
3800Sstevel@tonic-gate * Prescott MSRs. This attempt should fail if Intel has changed
3810Sstevel@tonic-gate * the branch stack again.
3820Sstevel@tonic-gate */
3830Sstevel@tonic-gate if (kmt_msr_validate(kmt_prp4_msrs))
3840Sstevel@tonic-gate return (&kmt_p4_prescott);
3850Sstevel@tonic-gate else
3860Sstevel@tonic-gate return (&kmt_p4_unknown);
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate return (NULL);
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate kmt_cpu_t *
kmt_cpu_p4_create(mdb_tgt_t * t)3930Sstevel@tonic-gate kmt_cpu_p4_create(mdb_tgt_t *t)
3940Sstevel@tonic-gate {
3950Sstevel@tonic-gate uint_t vendor, family, model;
3960Sstevel@tonic-gate kmt_cpu_t *cpu;
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate if (kmdb_kdi_get_cpuinfo(&vendor, &family, &model) < 0)
3990Sstevel@tonic-gate return (NULL); /* errno is set for us */
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate if ((kmt_cpu_p4.p4_flavor = cpu2flavor(vendor, family, model)) ==
4020Sstevel@tonic-gate NULL) {
4030Sstevel@tonic-gate (void) set_errno(ENOTSUP);
4040Sstevel@tonic-gate return (NULL);
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate kmt_cpu_p4.p4_model = model;
4080Sstevel@tonic-gate kmt_cpu_p4.p4_debugctl = DEBUGCTL_LBR; /* enable LBR on resume */
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate cpu = mdb_zalloc(sizeof (kmt_cpu_t), UM_SLEEP);
4110Sstevel@tonic-gate cpu->kmt_cpu_ops = &kmt_p4_ops;
4120Sstevel@tonic-gate cpu->kmt_cpu_data = &kmt_cpu_p4;
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate kmdb_dpi_msr_add(kmt_cpu_p4.p4_flavor->p4f_msrs);
4150Sstevel@tonic-gate (void) mdb_tgt_register_dcmds(t, kmt_p4_dcmds, MDB_MOD_FORCE);
4160Sstevel@tonic-gate
4170Sstevel@tonic-gate return (cpu);
4180Sstevel@tonic-gate }
419