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