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