1*9c3024a3SHans Rosenfeld /*
2*9c3024a3SHans Rosenfeld  * This file and its contents are supplied under the terms of the
3*9c3024a3SHans Rosenfeld  * Common Development and Distribution License ("CDDL"), version 1.0.
4*9c3024a3SHans Rosenfeld  * You may only use this file in accordance with the terms of version
5*9c3024a3SHans Rosenfeld  * 1.0 of the CDDL.
6*9c3024a3SHans Rosenfeld  *
7*9c3024a3SHans Rosenfeld  * A full copy of the text of the CDDL should have accompanied this
8*9c3024a3SHans Rosenfeld  * source.  A copy of the CDDL is also available via the Internet at
9*9c3024a3SHans Rosenfeld  * http://www.illumos.org/license/CDDL.
10*9c3024a3SHans Rosenfeld  */
11*9c3024a3SHans Rosenfeld 
12*9c3024a3SHans Rosenfeld /*
13*9c3024a3SHans Rosenfeld  * Copyright 2019 Joyent, Inc.
14*9c3024a3SHans Rosenfeld  */
15*9c3024a3SHans Rosenfeld 
16*9c3024a3SHans Rosenfeld /*
17*9c3024a3SHans Rosenfeld  * ISA-independent utility functions for the x86 architecture
18*9c3024a3SHans Rosenfeld  */
19*9c3024a3SHans Rosenfeld 
20*9c3024a3SHans Rosenfeld #include <mdb/mdb_modapi.h>
21*9c3024a3SHans Rosenfeld #include <mdb/mdb_x86util.h>
22*9c3024a3SHans Rosenfeld 
23*9c3024a3SHans Rosenfeld #include <sys/controlregs.h>
24*9c3024a3SHans Rosenfeld #include <inttypes.h>
25*9c3024a3SHans Rosenfeld 
26*9c3024a3SHans Rosenfeld #define	MMU_PAGESHIFT	12
27*9c3024a3SHans Rosenfeld #define	MMU_PAGESIZE	(1 << MMU_PAGESHIFT)
28*9c3024a3SHans Rosenfeld #define	MMU_PAGEOFFSET	(MMU_PAGESIZE - 1)
29*9c3024a3SHans Rosenfeld #define	MMU_PAGEMASK	(~MMU_PAGEOFFSET)
30*9c3024a3SHans Rosenfeld 
31*9c3024a3SHans Rosenfeld #ifndef _KMDB
32*9c3024a3SHans Rosenfeld static void
mdb_x86_print_desc(const char * name,const mdb_x86_desc_t * desc,uint_t width)33*9c3024a3SHans Rosenfeld mdb_x86_print_desc(const char *name, const mdb_x86_desc_t *desc, uint_t width)
34*9c3024a3SHans Rosenfeld {
35*9c3024a3SHans Rosenfeld 	const char *type;
36*9c3024a3SHans Rosenfeld 	const mdb_bitmask_t *bits;
37*9c3024a3SHans Rosenfeld 
38*9c3024a3SHans Rosenfeld 	static const mdb_bitmask_t mem_desc_flag_bits[] = {
39*9c3024a3SHans Rosenfeld 		{ "P",		0x80,	0x80 },
40*9c3024a3SHans Rosenfeld 		{ "16b",	0x6000, 0x0 },
41*9c3024a3SHans Rosenfeld 		{ "32b",	0x6000, 0x4000 },
42*9c3024a3SHans Rosenfeld 		{ "64b",	0x6000,	0x2000 },
43*9c3024a3SHans Rosenfeld 		{ "G",		0x8000,	0x8000 },
44*9c3024a3SHans Rosenfeld 		{ "A",		0x1,	0x1 },
45*9c3024a3SHans Rosenfeld 		{ NULL,		0,	0 },
46*9c3024a3SHans Rosenfeld 	};
47*9c3024a3SHans Rosenfeld 
48*9c3024a3SHans Rosenfeld 	static const char *mem_desc_types[] = {
49*9c3024a3SHans Rosenfeld 		"data, up, read-only",
50*9c3024a3SHans Rosenfeld 		"data, up, read-write",
51*9c3024a3SHans Rosenfeld 		"data, down, read-only",
52*9c3024a3SHans Rosenfeld 		"data, down, read-write",
53*9c3024a3SHans Rosenfeld 		"code, non-conforming, execute-only",
54*9c3024a3SHans Rosenfeld 		"code, non-conforming, execute-read",
55*9c3024a3SHans Rosenfeld 		"code, conforming, execute-only",
56*9c3024a3SHans Rosenfeld 		"code, conforming, execute-read"
57*9c3024a3SHans Rosenfeld 	};
58*9c3024a3SHans Rosenfeld 
59*9c3024a3SHans Rosenfeld 	static const mdb_bitmask_t sys_desc_flag_bits[] = {
60*9c3024a3SHans Rosenfeld 		{ "P",		0x80,	0x80 },
61*9c3024a3SHans Rosenfeld 		{ "16b",	0x6000, 0x0 },
62*9c3024a3SHans Rosenfeld 		{ "32b",	0x6000, 0x4000 },
63*9c3024a3SHans Rosenfeld 		{ "64b",	0x6000,	0x2000 },
64*9c3024a3SHans Rosenfeld 		{ "G",		0x8000,	0x8000 },
65*9c3024a3SHans Rosenfeld 		{ NULL,		0,	0 },
66*9c3024a3SHans Rosenfeld 	};
67*9c3024a3SHans Rosenfeld 
68*9c3024a3SHans Rosenfeld 	static const char *sys_desc_types[] = {
69*9c3024a3SHans Rosenfeld 		"reserved",
70*9c3024a3SHans Rosenfeld 		"16b TSS, available",
71*9c3024a3SHans Rosenfeld 		"LDT",
72*9c3024a3SHans Rosenfeld 		"16b TSS, busy",
73*9c3024a3SHans Rosenfeld 		"16b call gate",
74*9c3024a3SHans Rosenfeld 		"task gate",
75*9c3024a3SHans Rosenfeld 		"16b interrupt gate",
76*9c3024a3SHans Rosenfeld 		"16b trap gate",
77*9c3024a3SHans Rosenfeld 		"reserved",
78*9c3024a3SHans Rosenfeld 		"32b/64b TSS, available",
79*9c3024a3SHans Rosenfeld 		"reserved",
80*9c3024a3SHans Rosenfeld 		"32b/64b TSS, busy",
81*9c3024a3SHans Rosenfeld 		"32b/64b call gate",
82*9c3024a3SHans Rosenfeld 		"reserved",
83*9c3024a3SHans Rosenfeld 		"32b/64b interrupt gate"
84*9c3024a3SHans Rosenfeld 		"32b/64b trap gate",
85*9c3024a3SHans Rosenfeld 	};
86*9c3024a3SHans Rosenfeld 
87*9c3024a3SHans Rosenfeld 	if (desc->d_acc & 0x10) {
88*9c3024a3SHans Rosenfeld 		type = mem_desc_types[(desc->d_acc >> 1) & 7];
89*9c3024a3SHans Rosenfeld 		bits = mem_desc_flag_bits;
90*9c3024a3SHans Rosenfeld 	} else {
91*9c3024a3SHans Rosenfeld 		type = sys_desc_types[desc->d_acc & 0xf];
92*9c3024a3SHans Rosenfeld 		bits = sys_desc_flag_bits;
93*9c3024a3SHans Rosenfeld 	}
94*9c3024a3SHans Rosenfeld 
95*9c3024a3SHans Rosenfeld 	mdb_printf("%%%s = 0x%0*lx/0x%0*x 0x%05x "
96*9c3024a3SHans Rosenfeld 	    "<%susable, %s, dpl %d, flags: %b>\n",
97*9c3024a3SHans Rosenfeld 	    name, width, desc->d_base, width / 2, desc->d_lim, desc->d_acc,
98*9c3024a3SHans Rosenfeld 	    (desc->d_acc >> 16) & 1 ? "un" : "", type,
99*9c3024a3SHans Rosenfeld 	    (desc->d_acc >> 5) & 3, desc->d_acc, bits);
100*9c3024a3SHans Rosenfeld }
101*9c3024a3SHans Rosenfeld #endif
102*9c3024a3SHans Rosenfeld 
103*9c3024a3SHans Rosenfeld void
mdb_x86_print_sysregs(struct sysregs * sregs,boolean_t long_mode)104*9c3024a3SHans Rosenfeld mdb_x86_print_sysregs(struct sysregs *sregs, boolean_t long_mode)
105*9c3024a3SHans Rosenfeld {
106*9c3024a3SHans Rosenfeld 	const uint_t width =
107*9c3024a3SHans Rosenfeld 	    2 * (long_mode ? sizeof (uint64_t) : sizeof (uint32_t));
108*9c3024a3SHans Rosenfeld 
109*9c3024a3SHans Rosenfeld 
110*9c3024a3SHans Rosenfeld #ifndef _KMDB
111*9c3024a3SHans Rosenfeld 	static const mdb_bitmask_t efer_flag_bits[] = {
112*9c3024a3SHans Rosenfeld 		{ "SCE",	AMD_EFER_SCE,	AMD_EFER_SCE },
113*9c3024a3SHans Rosenfeld 		{ "LME",	AMD_EFER_LME,	AMD_EFER_LME },
114*9c3024a3SHans Rosenfeld 		{ "LMA",	AMD_EFER_LMA,	AMD_EFER_LMA },
115*9c3024a3SHans Rosenfeld 		{ "NXE",	AMD_EFER_NXE,	AMD_EFER_NXE },
116*9c3024a3SHans Rosenfeld 		{ "SVME",	AMD_EFER_SVME,	AMD_EFER_SVME },
117*9c3024a3SHans Rosenfeld 		{ "LMSLE",	AMD_EFER_LMSLE,	AMD_EFER_LMSLE },
118*9c3024a3SHans Rosenfeld 		{ "FFXSR",	AMD_EFER_FFXSR,	AMD_EFER_FFXSR },
119*9c3024a3SHans Rosenfeld 		{ "TCE",	AMD_EFER_TCE,	AMD_EFER_TCE },
120*9c3024a3SHans Rosenfeld 		{ NULL,		0,		0 }
121*9c3024a3SHans Rosenfeld 	};
122*9c3024a3SHans Rosenfeld #endif
123*9c3024a3SHans Rosenfeld 
124*9c3024a3SHans Rosenfeld 	static const mdb_bitmask_t cr0_flag_bits[] = {
125*9c3024a3SHans Rosenfeld 		{ "PE",		CR0_PE,		CR0_PE },
126*9c3024a3SHans Rosenfeld 		{ "MP",		CR0_MP,		CR0_MP },
127*9c3024a3SHans Rosenfeld 		{ "EM",		CR0_EM,		CR0_EM },
128*9c3024a3SHans Rosenfeld 		{ "TS",		CR0_TS,		CR0_TS },
129*9c3024a3SHans Rosenfeld 		{ "ET",		CR0_ET,		CR0_ET },
130*9c3024a3SHans Rosenfeld 		{ "NE",		CR0_NE,		CR0_NE },
131*9c3024a3SHans Rosenfeld 		{ "WP",		CR0_WP,		CR0_WP },
132*9c3024a3SHans Rosenfeld 		{ "AM",		CR0_AM,		CR0_AM },
133*9c3024a3SHans Rosenfeld 		{ "NW",		CR0_NW,		CR0_NW },
134*9c3024a3SHans Rosenfeld 		{ "CD",		CR0_CD,		CR0_CD },
135*9c3024a3SHans Rosenfeld 		{ "PG",		CR0_PG,		CR0_PG },
136*9c3024a3SHans Rosenfeld 		{ NULL,		0,		0 }
137*9c3024a3SHans Rosenfeld 	};
138*9c3024a3SHans Rosenfeld 
139*9c3024a3SHans Rosenfeld 	static const mdb_bitmask_t cr3_flag_bits[] = {
140*9c3024a3SHans Rosenfeld 		{ "PCD",	CR3_PCD,	CR3_PCD },
141*9c3024a3SHans Rosenfeld 		{ "PWT",	CR3_PWT,	CR3_PWT },
142*9c3024a3SHans Rosenfeld 		{ NULL,		0,		0, }
143*9c3024a3SHans Rosenfeld 	};
144*9c3024a3SHans Rosenfeld 
145*9c3024a3SHans Rosenfeld 	static const mdb_bitmask_t cr4_flag_bits[] = {
146*9c3024a3SHans Rosenfeld 		{ "VME",	CR4_VME,	CR4_VME },
147*9c3024a3SHans Rosenfeld 		{ "PVI",	CR4_PVI,	CR4_PVI },
148*9c3024a3SHans Rosenfeld 		{ "TSD",	CR4_TSD,	CR4_TSD },
149*9c3024a3SHans Rosenfeld 		{ "DE",		CR4_DE,		CR4_DE },
150*9c3024a3SHans Rosenfeld 		{ "PSE",	CR4_PSE,	CR4_PSE },
151*9c3024a3SHans Rosenfeld 		{ "PAE",	CR4_PAE,	CR4_PAE },
152*9c3024a3SHans Rosenfeld 		{ "MCE",	CR4_MCE,	CR4_MCE },
153*9c3024a3SHans Rosenfeld 		{ "PGE",	CR4_PGE,	CR4_PGE },
154*9c3024a3SHans Rosenfeld 		{ "PCE",	CR4_PCE,	CR4_PCE },
155*9c3024a3SHans Rosenfeld 		{ "OSFXSR",	CR4_OSFXSR,	CR4_OSFXSR },
156*9c3024a3SHans Rosenfeld 		{ "OSXMMEXCPT",	CR4_OSXMMEXCPT,	CR4_OSXMMEXCPT },
157*9c3024a3SHans Rosenfeld 		{ "UMIP",	CR4_UMIP,	CR4_UMIP },
158*9c3024a3SHans Rosenfeld 		{ "VMXE",	CR4_VMXE,	CR4_VMXE },
159*9c3024a3SHans Rosenfeld 		{ "SMXE",	CR4_SMXE,	CR4_SMXE },
160*9c3024a3SHans Rosenfeld 		{ "FSGSBASE",	CR4_FSGSBASE,	CR4_FSGSBASE },
161*9c3024a3SHans Rosenfeld 		{ "PCIDE",	CR4_PCIDE,	CR4_PCIDE },
162*9c3024a3SHans Rosenfeld 		{ "OSXSAVE",	CR4_OSXSAVE,	CR4_OSXSAVE },
163*9c3024a3SHans Rosenfeld 		{ "SMEP",	CR4_SMEP,	CR4_SMEP },
164*9c3024a3SHans Rosenfeld 		{ "SMAP",	CR4_SMAP,	CR4_SMAP },
165*9c3024a3SHans Rosenfeld 		{ "PKE",	CR4_PKE,	CR4_PKE },
166*9c3024a3SHans Rosenfeld 		{ NULL,		0,		0 }
167*9c3024a3SHans Rosenfeld 	};
168*9c3024a3SHans Rosenfeld 
169*9c3024a3SHans Rosenfeld #ifndef _KMDB
170*9c3024a3SHans Rosenfeld 	mdb_printf("%%efer = 0x%0lx <%b>\n",
171*9c3024a3SHans Rosenfeld 	    sregs->sr_efer, sregs->sr_efer, efer_flag_bits);
172*9c3024a3SHans Rosenfeld #endif
173*9c3024a3SHans Rosenfeld 	mdb_printf("%%cr0 = 0x%0lx <%b>\n",
174*9c3024a3SHans Rosenfeld 	    sregs->sr_cr0, sregs->sr_cr0, cr0_flag_bits);
175*9c3024a3SHans Rosenfeld 	mdb_printf("%%cr2 = 0x%0*x <%a>\n", width,
176*9c3024a3SHans Rosenfeld 	    sregs->sr_cr2, sregs->sr_cr2);
177*9c3024a3SHans Rosenfeld 	mdb_printf("%%cr3 = 0x%0lx <pfn:0x%lx ",
178*9c3024a3SHans Rosenfeld 	    sregs->sr_cr3, sregs->sr_cr3 >> MMU_PAGESHIFT);
179*9c3024a3SHans Rosenfeld 	if (sregs->sr_cr4 & CR4_PCIDE)
180*9c3024a3SHans Rosenfeld 		mdb_printf("pcid:%lu>\n", sregs->sr_cr3 & MMU_PAGEOFFSET);
181*9c3024a3SHans Rosenfeld 	else
182*9c3024a3SHans Rosenfeld 		mdb_printf("flags:%b>\n", sregs->sr_cr3, cr3_flag_bits);
183*9c3024a3SHans Rosenfeld 	mdb_printf("%%cr4 = 0x%0lx <%b>\n",
184*9c3024a3SHans Rosenfeld 	    sregs->sr_cr4, sregs->sr_cr4, cr4_flag_bits);
185*9c3024a3SHans Rosenfeld 
186*9c3024a3SHans Rosenfeld #ifndef _KMDB
187*9c3024a3SHans Rosenfeld 	mdb_printf("\n");
188*9c3024a3SHans Rosenfeld 	mdb_printf("%%pdpte0 = 0x%0?lx\t%%pdpte2 = 0x%0?lx\n",
189*9c3024a3SHans Rosenfeld 	    sregs->sr_pdpte0, sregs->sr_pdpte2);
190*9c3024a3SHans Rosenfeld 	mdb_printf("%%pdpte1 = 0x%0?lx\t%%pdpte3 = 0x%0?lx\n",
191*9c3024a3SHans Rosenfeld 	    sregs->sr_pdpte1, sregs->sr_pdpte3);
192*9c3024a3SHans Rosenfeld 	mdb_printf("\n");
193*9c3024a3SHans Rosenfeld 
194*9c3024a3SHans Rosenfeld 	mdb_printf("%%gdtr = 0x%0*lx/0x%hx\n",
195*9c3024a3SHans Rosenfeld 	    width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim);
196*9c3024a3SHans Rosenfeld #else
197*9c3024a3SHans Rosenfeld 	mdb_printf("%%gdtr.base = 0x%0*lx, %%gdtr.limit = 0x%hx\n",
198*9c3024a3SHans Rosenfeld 	    width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim);
199*9c3024a3SHans Rosenfeld #endif
200*9c3024a3SHans Rosenfeld #ifndef _KMDB
201*9c3024a3SHans Rosenfeld 	mdb_printf("%%idtr = 0x%0*lx/0x%hx\n",
202*9c3024a3SHans Rosenfeld 	    width, sregs->sr_idtr.d_base, sregs->sr_idtr.d_lim);
203*9c3024a3SHans Rosenfeld 	mdb_x86_print_desc("ldtr", &sregs->sr_ldtr, width);
204*9c3024a3SHans Rosenfeld 	mdb_x86_print_desc("tr  ", &sregs->sr_tr, width);
205*9c3024a3SHans Rosenfeld 	mdb_x86_print_desc("cs  ", &sregs->sr_cs, width);
206*9c3024a3SHans Rosenfeld 	mdb_x86_print_desc("ss  ", &sregs->sr_ss, width);
207*9c3024a3SHans Rosenfeld 	mdb_x86_print_desc("ds  ", &sregs->sr_ds, width);
208*9c3024a3SHans Rosenfeld 	mdb_x86_print_desc("es  ", &sregs->sr_es, width);
209*9c3024a3SHans Rosenfeld 	mdb_x86_print_desc("fs  ", &sregs->sr_fs, width);
210*9c3024a3SHans Rosenfeld 	mdb_x86_print_desc("gs  ", &sregs->sr_gs, width);
211*9c3024a3SHans Rosenfeld 
212*9c3024a3SHans Rosenfeld 	mdb_printf("%%intr_shadow = 0x%lx\n",
213*9c3024a3SHans Rosenfeld 	    sregs->sr_intr_shadow);
214*9c3024a3SHans Rosenfeld #endif
215*9c3024a3SHans Rosenfeld }
216