19c3024a3SHans Rosenfeld /*
29c3024a3SHans Rosenfeld  * This file and its contents are supplied under the terms of the
39c3024a3SHans Rosenfeld  * Common Development and Distribution License ("CDDL"), version 1.0.
49c3024a3SHans Rosenfeld  * You may only use this file in accordance with the terms of version
59c3024a3SHans Rosenfeld  * 1.0 of the CDDL.
69c3024a3SHans Rosenfeld  *
79c3024a3SHans Rosenfeld  * A full copy of the text of the CDDL should have accompanied this
89c3024a3SHans Rosenfeld  * source.  A copy of the CDDL is also available via the Internet at
99c3024a3SHans Rosenfeld  * http://www.illumos.org/license/CDDL.
109c3024a3SHans Rosenfeld  */
119c3024a3SHans Rosenfeld 
129c3024a3SHans Rosenfeld /*
139c3024a3SHans Rosenfeld  * Copyright 2019 Joyent, Inc.
14e3092845SStuart Maybee  * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
15*651a12cbSRobert Mustacchi  * Copyright 2023 Oxide Computer Company
169c3024a3SHans Rosenfeld  */
179c3024a3SHans Rosenfeld 
189c3024a3SHans Rosenfeld /*
199c3024a3SHans Rosenfeld  * ISA-independent utility functions for the x86 architecture
209c3024a3SHans Rosenfeld  */
219c3024a3SHans Rosenfeld 
229c3024a3SHans Rosenfeld #include <mdb/mdb_modapi.h>
239c3024a3SHans Rosenfeld #include <mdb/mdb_x86util.h>
249c3024a3SHans Rosenfeld 
259c3024a3SHans Rosenfeld #include <sys/controlregs.h>
269c3024a3SHans Rosenfeld #include <inttypes.h>
279c3024a3SHans Rosenfeld 
289c3024a3SHans Rosenfeld #define	MMU_PAGESHIFT	12
299c3024a3SHans Rosenfeld #define	MMU_PAGESIZE	(1 << MMU_PAGESHIFT)
309c3024a3SHans Rosenfeld #define	MMU_PAGEOFFSET	(MMU_PAGESIZE - 1)
319c3024a3SHans Rosenfeld #define	MMU_PAGEMASK	(~MMU_PAGEOFFSET)
329c3024a3SHans Rosenfeld 
339c3024a3SHans Rosenfeld #ifndef _KMDB
349c3024a3SHans Rosenfeld static void
mdb_x86_print_desc(const char * name,const mdb_x86_desc_t * desc,uint_t width)359c3024a3SHans Rosenfeld mdb_x86_print_desc(const char *name, const mdb_x86_desc_t *desc, uint_t width)
369c3024a3SHans Rosenfeld {
379c3024a3SHans Rosenfeld 	const char *type;
389c3024a3SHans Rosenfeld 	const mdb_bitmask_t *bits;
399c3024a3SHans Rosenfeld 
409c3024a3SHans Rosenfeld 	static const mdb_bitmask_t mem_desc_flag_bits[] = {
419c3024a3SHans Rosenfeld 		{ "P",		0x80,	0x80 },
429c3024a3SHans Rosenfeld 		{ "16b",	0x6000, 0x0 },
439c3024a3SHans Rosenfeld 		{ "32b",	0x6000, 0x4000 },
449c3024a3SHans Rosenfeld 		{ "64b",	0x6000,	0x2000 },
459c3024a3SHans Rosenfeld 		{ "G",		0x8000,	0x8000 },
469c3024a3SHans Rosenfeld 		{ "A",		0x1,	0x1 },
479c3024a3SHans Rosenfeld 		{ NULL,		0,	0 },
489c3024a3SHans Rosenfeld 	};
499c3024a3SHans Rosenfeld 
509c3024a3SHans Rosenfeld 	static const char *mem_desc_types[] = {
519c3024a3SHans Rosenfeld 		"data, up, read-only",
529c3024a3SHans Rosenfeld 		"data, up, read-write",
539c3024a3SHans Rosenfeld 		"data, down, read-only",
549c3024a3SHans Rosenfeld 		"data, down, read-write",
559c3024a3SHans Rosenfeld 		"code, non-conforming, execute-only",
569c3024a3SHans Rosenfeld 		"code, non-conforming, execute-read",
579c3024a3SHans Rosenfeld 		"code, conforming, execute-only",
589c3024a3SHans Rosenfeld 		"code, conforming, execute-read"
599c3024a3SHans Rosenfeld 	};
609c3024a3SHans Rosenfeld 
619c3024a3SHans Rosenfeld 	static const mdb_bitmask_t sys_desc_flag_bits[] = {
629c3024a3SHans Rosenfeld 		{ "P",		0x80,	0x80 },
639c3024a3SHans Rosenfeld 		{ "16b",	0x6000, 0x0 },
649c3024a3SHans Rosenfeld 		{ "32b",	0x6000, 0x4000 },
659c3024a3SHans Rosenfeld 		{ "64b",	0x6000,	0x2000 },
669c3024a3SHans Rosenfeld 		{ "G",		0x8000,	0x8000 },
679c3024a3SHans Rosenfeld 		{ NULL,		0,	0 },
689c3024a3SHans Rosenfeld 	};
699c3024a3SHans Rosenfeld 
709c3024a3SHans Rosenfeld 	static const char *sys_desc_types[] = {
719c3024a3SHans Rosenfeld 		"reserved",
729c3024a3SHans Rosenfeld 		"16b TSS, available",
739c3024a3SHans Rosenfeld 		"LDT",
749c3024a3SHans Rosenfeld 		"16b TSS, busy",
759c3024a3SHans Rosenfeld 		"16b call gate",
769c3024a3SHans Rosenfeld 		"task gate",
779c3024a3SHans Rosenfeld 		"16b interrupt gate",
789c3024a3SHans Rosenfeld 		"16b trap gate",
799c3024a3SHans Rosenfeld 		"reserved",
809c3024a3SHans Rosenfeld 		"32b/64b TSS, available",
819c3024a3SHans Rosenfeld 		"reserved",
829c3024a3SHans Rosenfeld 		"32b/64b TSS, busy",
839c3024a3SHans Rosenfeld 		"32b/64b call gate",
849c3024a3SHans Rosenfeld 		"reserved",
859c3024a3SHans Rosenfeld 		"32b/64b interrupt gate"
869c3024a3SHans Rosenfeld 		"32b/64b trap gate",
879c3024a3SHans Rosenfeld 	};
889c3024a3SHans Rosenfeld 
899c3024a3SHans Rosenfeld 	if (desc->d_acc & 0x10) {
909c3024a3SHans Rosenfeld 		type = mem_desc_types[(desc->d_acc >> 1) & 7];
919c3024a3SHans Rosenfeld 		bits = mem_desc_flag_bits;
929c3024a3SHans Rosenfeld 	} else {
939c3024a3SHans Rosenfeld 		type = sys_desc_types[desc->d_acc & 0xf];
949c3024a3SHans Rosenfeld 		bits = sys_desc_flag_bits;
959c3024a3SHans Rosenfeld 	}
969c3024a3SHans Rosenfeld 
979c3024a3SHans Rosenfeld 	mdb_printf("%%%s = 0x%0*lx/0x%0*x 0x%05x "
989c3024a3SHans Rosenfeld 	    "<%susable, %s, dpl %d, flags: %b>\n",
999c3024a3SHans Rosenfeld 	    name, width, desc->d_base, width / 2, desc->d_lim, desc->d_acc,
1009c3024a3SHans Rosenfeld 	    (desc->d_acc >> 16) & 1 ? "un" : "", type,
1019c3024a3SHans Rosenfeld 	    (desc->d_acc >> 5) & 3, desc->d_acc, bits);
1029c3024a3SHans Rosenfeld }
1039c3024a3SHans Rosenfeld #endif
1049c3024a3SHans Rosenfeld 
1059c3024a3SHans Rosenfeld void
mdb_x86_print_sysregs(struct sysregs * sregs,boolean_t long_mode)1069c3024a3SHans Rosenfeld mdb_x86_print_sysregs(struct sysregs *sregs, boolean_t long_mode)
1079c3024a3SHans Rosenfeld {
1089c3024a3SHans Rosenfeld 	const uint_t width =
1099c3024a3SHans Rosenfeld 	    2 * (long_mode ? sizeof (uint64_t) : sizeof (uint32_t));
1109c3024a3SHans Rosenfeld 
1119c3024a3SHans Rosenfeld 
1129c3024a3SHans Rosenfeld #ifndef _KMDB
1139c3024a3SHans Rosenfeld 	static const mdb_bitmask_t efer_flag_bits[] = {
1149c3024a3SHans Rosenfeld 		{ "SCE",	AMD_EFER_SCE,	AMD_EFER_SCE },
1159c3024a3SHans Rosenfeld 		{ "LME",	AMD_EFER_LME,	AMD_EFER_LME },
1169c3024a3SHans Rosenfeld 		{ "LMA",	AMD_EFER_LMA,	AMD_EFER_LMA },
1179c3024a3SHans Rosenfeld 		{ "NXE",	AMD_EFER_NXE,	AMD_EFER_NXE },
1189c3024a3SHans Rosenfeld 		{ "SVME",	AMD_EFER_SVME,	AMD_EFER_SVME },
1199c3024a3SHans Rosenfeld 		{ "LMSLE",	AMD_EFER_LMSLE,	AMD_EFER_LMSLE },
1209c3024a3SHans Rosenfeld 		{ "FFXSR",	AMD_EFER_FFXSR,	AMD_EFER_FFXSR },
1219c3024a3SHans Rosenfeld 		{ "TCE",	AMD_EFER_TCE,	AMD_EFER_TCE },
122*651a12cbSRobert Mustacchi 		{ "MCOMMIT",	AMD_EFER_MCOMMIT, AMD_EFER_MCOMMIT },
123*651a12cbSRobert Mustacchi 		{ "INTWB",	AMD_EFER_INTWB,	AMD_EFER_INTWB },
124*651a12cbSRobert Mustacchi 		{ "UAIE",	AMD_EFER_UAIE,	AMD_EFER_UAIE },
125*651a12cbSRobert Mustacchi 		{ "AIRBRSE",	AMD_EFER_AIBRSE, AMD_EFER_AIBRSE },
1269c3024a3SHans Rosenfeld 		{ NULL,		0,		0 }
1279c3024a3SHans Rosenfeld 	};
1289c3024a3SHans Rosenfeld #endif
1299c3024a3SHans Rosenfeld 
1309c3024a3SHans Rosenfeld 	static const mdb_bitmask_t cr0_flag_bits[] = {
1319c3024a3SHans Rosenfeld 		{ "PE",		CR0_PE,		CR0_PE },
1329c3024a3SHans Rosenfeld 		{ "MP",		CR0_MP,		CR0_MP },
1339c3024a3SHans Rosenfeld 		{ "EM",		CR0_EM,		CR0_EM },
1349c3024a3SHans Rosenfeld 		{ "TS",		CR0_TS,		CR0_TS },
1359c3024a3SHans Rosenfeld 		{ "ET",		CR0_ET,		CR0_ET },
1369c3024a3SHans Rosenfeld 		{ "NE",		CR0_NE,		CR0_NE },
1379c3024a3SHans Rosenfeld 		{ "WP",		CR0_WP,		CR0_WP },
1389c3024a3SHans Rosenfeld 		{ "AM",		CR0_AM,		CR0_AM },
1399c3024a3SHans Rosenfeld 		{ "NW",		CR0_NW,		CR0_NW },
1409c3024a3SHans Rosenfeld 		{ "CD",		CR0_CD,		CR0_CD },
1419c3024a3SHans Rosenfeld 		{ "PG",		CR0_PG,		CR0_PG },
1429c3024a3SHans Rosenfeld 		{ NULL,		0,		0 }
1439c3024a3SHans Rosenfeld 	};
1449c3024a3SHans Rosenfeld 
1459c3024a3SHans Rosenfeld 	static const mdb_bitmask_t cr3_flag_bits[] = {
1469c3024a3SHans Rosenfeld 		{ "PCD",	CR3_PCD,	CR3_PCD },
1479c3024a3SHans Rosenfeld 		{ "PWT",	CR3_PWT,	CR3_PWT },
1489c3024a3SHans Rosenfeld 		{ NULL,		0,		0, }
1499c3024a3SHans Rosenfeld 	};
1509c3024a3SHans Rosenfeld 
1519c3024a3SHans Rosenfeld 	static const mdb_bitmask_t cr4_flag_bits[] = {
1529c3024a3SHans Rosenfeld 		{ "VME",	CR4_VME,	CR4_VME },
1539c3024a3SHans Rosenfeld 		{ "PVI",	CR4_PVI,	CR4_PVI },
1549c3024a3SHans Rosenfeld 		{ "TSD",	CR4_TSD,	CR4_TSD },
1559c3024a3SHans Rosenfeld 		{ "DE",		CR4_DE,		CR4_DE },
1569c3024a3SHans Rosenfeld 		{ "PSE",	CR4_PSE,	CR4_PSE },
1579c3024a3SHans Rosenfeld 		{ "PAE",	CR4_PAE,	CR4_PAE },
1589c3024a3SHans Rosenfeld 		{ "MCE",	CR4_MCE,	CR4_MCE },
1599c3024a3SHans Rosenfeld 		{ "PGE",	CR4_PGE,	CR4_PGE },
1609c3024a3SHans Rosenfeld 		{ "PCE",	CR4_PCE,	CR4_PCE },
1619c3024a3SHans Rosenfeld 		{ "OSFXSR",	CR4_OSFXSR,	CR4_OSFXSR },
1629c3024a3SHans Rosenfeld 		{ "OSXMMEXCPT",	CR4_OSXMMEXCPT,	CR4_OSXMMEXCPT },
1639c3024a3SHans Rosenfeld 		{ "UMIP",	CR4_UMIP,	CR4_UMIP },
164e3092845SStuart Maybee 		{ "LA57",	CR4_LA57,	CR4_LA57 },
1659c3024a3SHans Rosenfeld 		{ "VMXE",	CR4_VMXE,	CR4_VMXE },
1669c3024a3SHans Rosenfeld 		{ "SMXE",	CR4_SMXE,	CR4_SMXE },
1679c3024a3SHans Rosenfeld 		{ "FSGSBASE",	CR4_FSGSBASE,	CR4_FSGSBASE },
1689c3024a3SHans Rosenfeld 		{ "PCIDE",	CR4_PCIDE,	CR4_PCIDE },
1699c3024a3SHans Rosenfeld 		{ "OSXSAVE",	CR4_OSXSAVE,	CR4_OSXSAVE },
1709c3024a3SHans Rosenfeld 		{ "SMEP",	CR4_SMEP,	CR4_SMEP },
1719c3024a3SHans Rosenfeld 		{ "SMAP",	CR4_SMAP,	CR4_SMAP },
1729c3024a3SHans Rosenfeld 		{ "PKE",	CR4_PKE,	CR4_PKE },
1739c3024a3SHans Rosenfeld 		{ NULL,		0,		0 }
1749c3024a3SHans Rosenfeld 	};
1759c3024a3SHans Rosenfeld 
1769c3024a3SHans Rosenfeld #ifndef _KMDB
1779c3024a3SHans Rosenfeld 	mdb_printf("%%efer = 0x%0lx <%b>\n",
1789c3024a3SHans Rosenfeld 	    sregs->sr_efer, sregs->sr_efer, efer_flag_bits);
1799c3024a3SHans Rosenfeld #endif
1809c3024a3SHans Rosenfeld 	mdb_printf("%%cr0 = 0x%0lx <%b>\n",
1819c3024a3SHans Rosenfeld 	    sregs->sr_cr0, sregs->sr_cr0, cr0_flag_bits);
1829c3024a3SHans Rosenfeld 	mdb_printf("%%cr2 = 0x%0*x <%a>\n", width,
1839c3024a3SHans Rosenfeld 	    sregs->sr_cr2, sregs->sr_cr2);
1849c3024a3SHans Rosenfeld 	mdb_printf("%%cr3 = 0x%0lx <pfn:0x%lx ",
1859c3024a3SHans Rosenfeld 	    sregs->sr_cr3, sregs->sr_cr3 >> MMU_PAGESHIFT);
1869c3024a3SHans Rosenfeld 	if (sregs->sr_cr4 & CR4_PCIDE)
1879c3024a3SHans Rosenfeld 		mdb_printf("pcid:%lu>\n", sregs->sr_cr3 & MMU_PAGEOFFSET);
1889c3024a3SHans Rosenfeld 	else
1899c3024a3SHans Rosenfeld 		mdb_printf("flags:%b>\n", sregs->sr_cr3, cr3_flag_bits);
1909c3024a3SHans Rosenfeld 	mdb_printf("%%cr4 = 0x%0lx <%b>\n",
1919c3024a3SHans Rosenfeld 	    sregs->sr_cr4, sregs->sr_cr4, cr4_flag_bits);
1929c3024a3SHans Rosenfeld 
1939c3024a3SHans Rosenfeld #ifndef _KMDB
1949c3024a3SHans Rosenfeld 	mdb_printf("\n");
1959c3024a3SHans Rosenfeld 	mdb_printf("%%pdpte0 = 0x%0?lx\t%%pdpte2 = 0x%0?lx\n",
1969c3024a3SHans Rosenfeld 	    sregs->sr_pdpte0, sregs->sr_pdpte2);
1979c3024a3SHans Rosenfeld 	mdb_printf("%%pdpte1 = 0x%0?lx\t%%pdpte3 = 0x%0?lx\n",
1989c3024a3SHans Rosenfeld 	    sregs->sr_pdpte1, sregs->sr_pdpte3);
1999c3024a3SHans Rosenfeld 	mdb_printf("\n");
2009c3024a3SHans Rosenfeld 
2019c3024a3SHans Rosenfeld 	mdb_printf("%%gdtr = 0x%0*lx/0x%hx\n",
2029c3024a3SHans Rosenfeld 	    width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim);
2039c3024a3SHans Rosenfeld #else
2049c3024a3SHans Rosenfeld 	mdb_printf("%%gdtr.base = 0x%0*lx, %%gdtr.limit = 0x%hx\n",
2059c3024a3SHans Rosenfeld 	    width, sregs->sr_gdtr.d_base, sregs->sr_gdtr.d_lim);
2069c3024a3SHans Rosenfeld #endif
2079c3024a3SHans Rosenfeld #ifndef _KMDB
2089c3024a3SHans Rosenfeld 	mdb_printf("%%idtr = 0x%0*lx/0x%hx\n",
2099c3024a3SHans Rosenfeld 	    width, sregs->sr_idtr.d_base, sregs->sr_idtr.d_lim);
2109c3024a3SHans Rosenfeld 	mdb_x86_print_desc("ldtr", &sregs->sr_ldtr, width);
2119c3024a3SHans Rosenfeld 	mdb_x86_print_desc("tr  ", &sregs->sr_tr, width);
2129c3024a3SHans Rosenfeld 	mdb_x86_print_desc("cs  ", &sregs->sr_cs, width);
2139c3024a3SHans Rosenfeld 	mdb_x86_print_desc("ss  ", &sregs->sr_ss, width);
2149c3024a3SHans Rosenfeld 	mdb_x86_print_desc("ds  ", &sregs->sr_ds, width);
2159c3024a3SHans Rosenfeld 	mdb_x86_print_desc("es  ", &sregs->sr_es, width);
2169c3024a3SHans Rosenfeld 	mdb_x86_print_desc("fs  ", &sregs->sr_fs, width);
2179c3024a3SHans Rosenfeld 	mdb_x86_print_desc("gs  ", &sregs->sr_gs, width);
2189c3024a3SHans Rosenfeld 
2199c3024a3SHans Rosenfeld 	mdb_printf("%%intr_shadow = 0x%lx\n",
2209c3024a3SHans Rosenfeld 	    sregs->sr_intr_shadow);
2219c3024a3SHans Rosenfeld #endif
2229c3024a3SHans Rosenfeld }
223