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