/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2019 Joyent, Inc. * Copyright 2022 Tintri by DDN, Inc. All rights reserved. * Copyright 2023 Oxide Computer Company */ /* * ISA-independent utility functions for the x86 architecture */ #include #include #include #include #define MMU_PAGESHIFT 12 #define MMU_PAGESIZE (1 << MMU_PAGESHIFT) #define MMU_PAGEOFFSET (MMU_PAGESIZE - 1) #define MMU_PAGEMASK (~MMU_PAGEOFFSET) #ifndef _KMDB static void mdb_x86_print_desc(const char *name, const mdb_x86_desc_t *desc, uint_t width) { const char *type; const mdb_bitmask_t *bits; static const mdb_bitmask_t mem_desc_flag_bits[] = { { "P", 0x80, 0x80 }, { "16b", 0x6000, 0x0 }, { "32b", 0x6000, 0x4000 }, { "64b", 0x6000, 0x2000 }, { "G", 0x8000, 0x8000 }, { "A", 0x1, 0x1 }, { NULL, 0, 0 }, }; static const char *mem_desc_types[] = { "data, up, read-only", "data, up, read-write", "data, down, read-only", "data, down, read-write", "code, non-conforming, execute-only", "code, non-conforming, execute-read", "code, conforming, execute-only", "code, conforming, execute-read" }; static const mdb_bitmask_t sys_desc_flag_bits[] = { { "P", 0x80, 0x80 }, { "16b", 0x6000, 0x0 }, { "32b", 0x6000, 0x4000 }, { "64b", 0x6000, 0x2000 }, { "G", 0x8000, 0x8000 }, { NULL, 0, 0 }, }; static const char *sys_desc_types[] = { "reserved", "16b TSS, available", "LDT", "16b TSS, busy", "16b call gate", "task gate", "16b interrupt gate", "16b trap gate", "reserved", "32b/64b TSS, available", "reserved", "32b/64b TSS, busy", "32b/64b call gate", "reserved", "32b/64b interrupt gate" "32b/64b trap gate", }; if (desc->d_acc & 0x10) { type = mem_desc_types[(desc->d_acc >> 1) & 7]; bits = mem_desc_flag_bits; } else { type = sys_desc_types[desc->d_acc & 0xf]; bits = sys_desc_flag_bits; } mdb_printf("%%%s = 0x%0*lx/0x%0*x 0x%05x " "<%susable, %s, dpl %d, flags: %b>\n", name, width, desc->d_base, width / 2, desc->d_lim, desc->d_acc, (desc->d_acc >> 16) & 1 ? "un" : "", type, (desc->d_acc >> 5) & 3, desc->d_acc, bits); } #endif void mdb_x86_print_sysregs(struct sysregs *sregs, boolean_t long_mode) { const uint_t width = 2 * (long_mode ? sizeof (uint64_t) : sizeof (uint32_t)); #ifndef _KMDB static const mdb_bitmask_t efer_flag_bits[] = { { "SCE", AMD_EFER_SCE, AMD_EFER_SCE }, { "LME", AMD_EFER_LME, AMD_EFER_LME }, { "LMA", AMD_EFER_LMA, AMD_EFER_LMA }, { "NXE", AMD_EFER_NXE, AMD_EFER_NXE }, { "SVME", AMD_EFER_SVME, AMD_EFER_SVME }, { "LMSLE", AMD_EFER_LMSLE, AMD_EFER_LMSLE }, { "FFXSR", AMD_EFER_FFXSR, AMD_EFER_FFXSR }, { "TCE", AMD_EFER_TCE, AMD_EFER_TCE }, { "MCOMMIT", AMD_EFER_MCOMMIT, AMD_EFER_MCOMMIT }, { "INTWB", AMD_EFER_INTWB, AMD_EFER_INTWB }, { "UAIE", AMD_EFER_UAIE, AMD_EFER_UAIE }, { "AIRBRSE", AMD_EFER_AIBRSE, AMD_EFER_AIBRSE }, { NULL, 0, 0 } }; #endif static const mdb_bitmask_t cr0_flag_bits[] = { { "PE", CR0_PE, CR0_PE }, { "MP", CR0_MP, CR0_MP }, { "EM", CR0_EM, CR0_EM }, { "TS", CR0_TS, CR0_TS }, { "ET", CR0_ET, CR0_ET }, { "NE", CR0_NE, CR0_NE }, { "WP", CR0_WP, CR0_WP }, { "AM", CR0_AM, CR0_AM }, { "NW", CR0_NW, CR0_NW }, { "CD", CR0_CD, CR0_CD }, { "PG", CR0_PG, CR0_PG }, { NULL, 0, 0 } }; static const mdb_bitmask_t cr3_flag_bits[] = { { "PCD", CR3_PCD, CR3_PCD }, { "PWT", CR3_PWT, CR3_PWT }, { NULL, 0, 0, } }; static const mdb_bitmask_t cr4_flag_bits[] = { { "VME", CR4_VME, CR4_VME }, { "PVI", CR4_PVI, CR4_PVI }, { "TSD", CR4_TSD, CR4_TSD }, { "DE", CR4_DE, CR4_DE }, { "PSE", CR4_PSE, CR4_PSE }, { "PAE", CR4_PAE, CR4_PAE }, { "MCE", CR4_MCE, CR4_MCE }, { "PGE", CR4_PGE, CR4_PGE }, { "PCE", CR4_PCE, CR4_PCE }, { "OSFXSR", CR4_OSFXSR, CR4_OSFXSR }, { "OSXMMEXCPT", CR4_OSXMMEXCPT, CR4_OSXMMEXCPT }, { "UMIP", CR4_UMIP, CR4_UMIP }, { "LA57", CR4_LA57, CR4_LA57 }, { "VMXE", CR4_VMXE, CR4_VMXE }, { "SMXE", CR4_SMXE, CR4_SMXE }, { "FSGSBASE", CR4_FSGSBASE, CR4_FSGSBASE }, { "PCIDE", CR4_PCIDE, CR4_PCIDE }, { "OSXSAVE", CR4_OSXSAVE, CR4_OSXSAVE }, { "SMEP", CR4_SMEP, CR4_SMEP }, { "SMAP", CR4_SMAP, CR4_SMAP }, { "PKE", CR4_PKE, CR4_PKE }, { NULL, 0, 0 } }; #ifndef _KMDB mdb_printf("%%efer = 0x%0lx <%b>\n", sregs->sr_efer, sregs->sr_efer, efer_flag_bits); #endif mdb_printf("%%cr0 = 0x%0lx <%b>\n", sregs->sr_cr0, sregs->sr_cr0, cr0_flag_bits); mdb_printf("%%cr2 = 0x%0*x <%a>\n", width, sregs->sr_cr2, sregs->sr_cr2); mdb_printf("%%cr3 = 0x%0lx sr_cr3, sregs->sr_cr3 >> MMU_PAGESHIFT); if (sregs->sr_cr4 & CR4_PCIDE) mdb_printf("pcid:%lu>\n", sregs->sr_cr3 & MMU_PAGEOFFSET); else mdb_printf("flags:%b>\n", sregs->sr_cr3, cr3_flag_bits); mdb_printf("%%cr4 = 0x%0lx <%b>\n", sregs->sr_cr4, sregs->sr_cr4, cr4_flag_bits); #ifndef _KMDB mdb_printf("\n"); mdb_printf("%%pdpte0 = 0x%0?lx\t%%pdpte2 = 0x%0?lx\n", sregs->sr_pdpte0, sregs->sr_pdpte2); mdb_printf("%%pdpte1 = 0x%0?lx\t%%pdpte3 = 0x%0?lx\n", sregs->sr_pdpte1, sregs->sr_pdpte3); mdb_printf("\n"); mdb_printf("%%gdtr = 0x%0*lx/0x%hx\n", width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim); #else mdb_printf("%%gdtr.base = 0x%0*lx, %%gdtr.limit = 0x%hx\n", width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim); #endif #ifndef _KMDB mdb_printf("%%idtr = 0x%0*lx/0x%hx\n", width, sregs->sr_idtr.d_base, sregs->sr_idtr.d_lim); mdb_x86_print_desc("ldtr", &sregs->sr_ldtr, width); mdb_x86_print_desc("tr ", &sregs->sr_tr, width); mdb_x86_print_desc("cs ", &sregs->sr_cs, width); mdb_x86_print_desc("ss ", &sregs->sr_ss, width); mdb_x86_print_desc("ds ", &sregs->sr_ds, width); mdb_x86_print_desc("es ", &sregs->sr_es, width); mdb_x86_print_desc("fs ", &sregs->sr_fs, width); mdb_x86_print_desc("gs ", &sregs->sr_gs, width); mdb_printf("%%intr_shadow = 0x%lx\n", sregs->sr_intr_shadow); #endif }