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 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 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