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