1*ed093b41SRobert Mustacchi /*
2*ed093b41SRobert Mustacchi  * CDDL HEADER START
3*ed093b41SRobert Mustacchi  *
4*ed093b41SRobert Mustacchi  * The contents of this file are subject to the terms of the
5*ed093b41SRobert Mustacchi  * Common Development and Distribution License, Version 1.0 only
6*ed093b41SRobert Mustacchi  * (the "License").  You may not use this file except in compliance
7*ed093b41SRobert Mustacchi  * with the License.
8*ed093b41SRobert Mustacchi  *
9*ed093b41SRobert Mustacchi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*ed093b41SRobert Mustacchi  * or http://www.opensolaris.org/os/licensing.
11*ed093b41SRobert Mustacchi  * See the License for the specific language governing permissions
12*ed093b41SRobert Mustacchi  * and limitations under the License.
13*ed093b41SRobert Mustacchi  *
14*ed093b41SRobert Mustacchi  * When distributing Covered Code, include this CDDL HEADER in each
15*ed093b41SRobert Mustacchi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*ed093b41SRobert Mustacchi  * If applicable, add the following below this CDDL HEADER, with the
17*ed093b41SRobert Mustacchi  * fields enclosed by brackets "[]" replaced with your own identifying
18*ed093b41SRobert Mustacchi  * information: Portions Copyright [yyyy] [name of copyright owner]
19*ed093b41SRobert Mustacchi  *
20*ed093b41SRobert Mustacchi  * CDDL HEADER END
21*ed093b41SRobert Mustacchi  */
22*ed093b41SRobert Mustacchi /*
23*ed093b41SRobert Mustacchi  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*ed093b41SRobert Mustacchi  * Use is subject to license terms.
25*ed093b41SRobert Mustacchi  */
26*ed093b41SRobert Mustacchi /*
27*ed093b41SRobert Mustacchi  * Copyright 2019 Doma Gergő Mihály <doma.gergo.mihaly@gmail.com>
28*ed093b41SRobert Mustacchi  * Copyright 2023 Oxide Computer Company
29*ed093b41SRobert Mustacchi  */
30*ed093b41SRobert Mustacchi 
31*ed093b41SRobert Mustacchi /*
32*ed093b41SRobert Mustacchi  * Consolidated routines that are shared between the 32-bit and 64-bit x86 mdb
33*ed093b41SRobert Mustacchi  * proc targets.
34*ed093b41SRobert Mustacchi  */
35*ed093b41SRobert Mustacchi 
36*ed093b41SRobert Mustacchi #include <mdb/mdb_proc.h>
37*ed093b41SRobert Mustacchi #include <mdb/mdb_err.h>
38*ed093b41SRobert Mustacchi #include <mdb/proc_x86util.h>
39*ed093b41SRobert Mustacchi #include <mdb/mdb.h>
40*ed093b41SRobert Mustacchi 
41*ed093b41SRobert Mustacchi #include <libproc.h>
42*ed093b41SRobert Mustacchi #include <sys/fp.h>
43*ed093b41SRobert Mustacchi #include <ieeefp.h>
44*ed093b41SRobert Mustacchi #include <sys/sysmacros.h>
45*ed093b41SRobert Mustacchi 
46*ed093b41SRobert Mustacchi const char *
fpcw2str(uint32_t cw,char * buf,size_t nbytes)47*ed093b41SRobert Mustacchi fpcw2str(uint32_t cw, char *buf, size_t nbytes)
48*ed093b41SRobert Mustacchi {
49*ed093b41SRobert Mustacchi 	char *end = buf + nbytes;
50*ed093b41SRobert Mustacchi 	char *p = buf;
51*ed093b41SRobert Mustacchi 
52*ed093b41SRobert Mustacchi 	buf[0] = '\0';
53*ed093b41SRobert Mustacchi 
54*ed093b41SRobert Mustacchi 	/*
55*ed093b41SRobert Mustacchi 	 * Decode all exception masks in the x87 FPU Control Word.
56*ed093b41SRobert Mustacchi 	 *
57*ed093b41SRobert Mustacchi 	 * See here:
58*ed093b41SRobert Mustacchi 	 * Intel® 64 and IA-32 Architectures Software Developer’s Manual,
59*ed093b41SRobert Mustacchi 	 * Volume 1: Basic Architecture, 8.1.5 x87 FPU Control Word
60*ed093b41SRobert Mustacchi 	 */
61*ed093b41SRobert Mustacchi 	if (cw & FPIM)	/* Invalid operation mask. */
62*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|IM");
63*ed093b41SRobert Mustacchi 	if (cw & FPDM)	/* Denormalized operand mask. */
64*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|DM");
65*ed093b41SRobert Mustacchi 	if (cw & FPZM)	/* Zero divide mask. */
66*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|ZM");
67*ed093b41SRobert Mustacchi 	if (cw & FPOM)	/* Overflow mask. */
68*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|OM");
69*ed093b41SRobert Mustacchi 	if (cw & FPUM)	/* Underflow mask. */
70*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|UM");
71*ed093b41SRobert Mustacchi 	if (cw & FPPM)	/* Precision mask. */
72*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|PM");
73*ed093b41SRobert Mustacchi 
74*ed093b41SRobert Mustacchi 	/*
75*ed093b41SRobert Mustacchi 	 * Decode precision control options.
76*ed093b41SRobert Mustacchi 	 */
77*ed093b41SRobert Mustacchi 	switch (cw & FPPC) {
78*ed093b41SRobert Mustacchi 	case FPSIG24:
79*ed093b41SRobert Mustacchi 		/* 24-bit significand, single precision. */
80*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|SIG24");
81*ed093b41SRobert Mustacchi 		break;
82*ed093b41SRobert Mustacchi 	case FPSIG53:
83*ed093b41SRobert Mustacchi 		/* 53-bit significand, double precision. */
84*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|SIG53");
85*ed093b41SRobert Mustacchi 		break;
86*ed093b41SRobert Mustacchi 	case FPSIG64:
87*ed093b41SRobert Mustacchi 		/* 64-bit significand, double extended precision. */
88*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|SIG64");
89*ed093b41SRobert Mustacchi 		break;
90*ed093b41SRobert Mustacchi 	default:
91*ed093b41SRobert Mustacchi 		/*
92*ed093b41SRobert Mustacchi 		 * Should never happen.
93*ed093b41SRobert Mustacchi 		 * Value 0x00000100 is 'Reserved'.
94*ed093b41SRobert Mustacchi 		 */
95*ed093b41SRobert Mustacchi 		break;
96*ed093b41SRobert Mustacchi 	}
97*ed093b41SRobert Mustacchi 
98*ed093b41SRobert Mustacchi 	/*
99*ed093b41SRobert Mustacchi 	 * Decode rounding control options.
100*ed093b41SRobert Mustacchi 	 */
101*ed093b41SRobert Mustacchi 	switch (cw & FPRC) {
102*ed093b41SRobert Mustacchi 	case FPRTN:
103*ed093b41SRobert Mustacchi 		/* Round to nearest, or to even if equidistant. */
104*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|RTN");
105*ed093b41SRobert Mustacchi 		break;
106*ed093b41SRobert Mustacchi 	case FPRD:
107*ed093b41SRobert Mustacchi 		/* Round down. */
108*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|RD");
109*ed093b41SRobert Mustacchi 		break;
110*ed093b41SRobert Mustacchi 	case FPRU:
111*ed093b41SRobert Mustacchi 		/* Round up. */
112*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|RU");
113*ed093b41SRobert Mustacchi 		break;
114*ed093b41SRobert Mustacchi 	case FPCHOP:
115*ed093b41SRobert Mustacchi 		/* Truncate. */
116*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|RTZ");
117*ed093b41SRobert Mustacchi 		break;
118*ed093b41SRobert Mustacchi 	default:
119*ed093b41SRobert Mustacchi 		/*
120*ed093b41SRobert Mustacchi 		 * This is a two-bit field.
121*ed093b41SRobert Mustacchi 		 * No other options left.
122*ed093b41SRobert Mustacchi 		 */
123*ed093b41SRobert Mustacchi 		break;
124*ed093b41SRobert Mustacchi 	}
125*ed093b41SRobert Mustacchi 
126*ed093b41SRobert Mustacchi 	/*
127*ed093b41SRobert Mustacchi 	 * Decode infinity control options.
128*ed093b41SRobert Mustacchi 	 *
129*ed093b41SRobert Mustacchi 	 * This field has been retained for compatibility with
130*ed093b41SRobert Mustacchi 	 * the 287 and earlier co-processors.
131*ed093b41SRobert Mustacchi 	 * In the more modern FPUs, this bit is disregarded and
132*ed093b41SRobert Mustacchi 	 * both -infinity and +infinity are respected.
133*ed093b41SRobert Mustacchi 	 * Comment source: SIMPLY FPU by Raymond Filiatreault
134*ed093b41SRobert Mustacchi 	 */
135*ed093b41SRobert Mustacchi 	switch (cw & FPIC) {
136*ed093b41SRobert Mustacchi 	case FPP:
137*ed093b41SRobert Mustacchi 		/*
138*ed093b41SRobert Mustacchi 		 * Projective infinity.
139*ed093b41SRobert Mustacchi 		 * Both -infinity and +infinity are treated as
140*ed093b41SRobert Mustacchi 		 * unsigned infinity.
141*ed093b41SRobert Mustacchi 		 */
142*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|P");
143*ed093b41SRobert Mustacchi 		break;
144*ed093b41SRobert Mustacchi 	case FPA:
145*ed093b41SRobert Mustacchi 		/*
146*ed093b41SRobert Mustacchi 		 * Affine infinity.
147*ed093b41SRobert Mustacchi 		 * Respects both -infinity and +infinity.
148*ed093b41SRobert Mustacchi 		 */
149*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|A");
150*ed093b41SRobert Mustacchi 		break;
151*ed093b41SRobert Mustacchi 	default:
152*ed093b41SRobert Mustacchi 		/*
153*ed093b41SRobert Mustacchi 		 * This is a one-bit field.
154*ed093b41SRobert Mustacchi 		 * No other options left.
155*ed093b41SRobert Mustacchi 		 */
156*ed093b41SRobert Mustacchi 		break;
157*ed093b41SRobert Mustacchi 	}
158*ed093b41SRobert Mustacchi 
159*ed093b41SRobert Mustacchi 	if (cw & WFPB17)
160*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|WFPB17");
161*ed093b41SRobert Mustacchi 	if (cw & WFPB24)
162*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|WFPB24");
163*ed093b41SRobert Mustacchi 
164*ed093b41SRobert Mustacchi 	if (buf[0] == '|')
165*ed093b41SRobert Mustacchi 		return (buf + 1);
166*ed093b41SRobert Mustacchi 
167*ed093b41SRobert Mustacchi 	return ("0");
168*ed093b41SRobert Mustacchi }
169*ed093b41SRobert Mustacchi 
170*ed093b41SRobert Mustacchi const char *
fpsw2str(uint32_t cw,char * buf,size_t nbytes)171*ed093b41SRobert Mustacchi fpsw2str(uint32_t cw, char *buf, size_t nbytes)
172*ed093b41SRobert Mustacchi {
173*ed093b41SRobert Mustacchi 	char *end = buf + nbytes;
174*ed093b41SRobert Mustacchi 	char *p = buf;
175*ed093b41SRobert Mustacchi 
176*ed093b41SRobert Mustacchi 	buf[0] = '\0';
177*ed093b41SRobert Mustacchi 
178*ed093b41SRobert Mustacchi 	/*
179*ed093b41SRobert Mustacchi 	 * Decode all masks in the 80387 status word.
180*ed093b41SRobert Mustacchi 	 */
181*ed093b41SRobert Mustacchi 	if (cw & FPS_IE)
182*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|IE");
183*ed093b41SRobert Mustacchi 	if (cw & FPS_DE)
184*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|DE");
185*ed093b41SRobert Mustacchi 	if (cw & FPS_ZE)
186*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|ZE");
187*ed093b41SRobert Mustacchi 	if (cw & FPS_OE)
188*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|OE");
189*ed093b41SRobert Mustacchi 	if (cw & FPS_UE)
190*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|UE");
191*ed093b41SRobert Mustacchi 	if (cw & FPS_PE)
192*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|PE");
193*ed093b41SRobert Mustacchi 	if (cw & FPS_SF)
194*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|SF");
195*ed093b41SRobert Mustacchi 	if (cw & FPS_ES)
196*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|ES");
197*ed093b41SRobert Mustacchi 	if (cw & FPS_C0)
198*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|C0");
199*ed093b41SRobert Mustacchi 	if (cw & FPS_C1)
200*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|C1");
201*ed093b41SRobert Mustacchi 	if (cw & FPS_C2)
202*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|C2");
203*ed093b41SRobert Mustacchi 	if (cw & FPS_C3)
204*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|C3");
205*ed093b41SRobert Mustacchi 	if (cw & FPS_B)
206*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|B");
207*ed093b41SRobert Mustacchi 
208*ed093b41SRobert Mustacchi 	if (buf[0] == '|')
209*ed093b41SRobert Mustacchi 		return (buf + 1);
210*ed093b41SRobert Mustacchi 
211*ed093b41SRobert Mustacchi 	return ("0");
212*ed093b41SRobert Mustacchi }
213*ed093b41SRobert Mustacchi 
214*ed093b41SRobert Mustacchi const char *
fpmxcsr2str(uint32_t mxcsr,char * buf,size_t nbytes)215*ed093b41SRobert Mustacchi fpmxcsr2str(uint32_t mxcsr, char *buf, size_t nbytes)
216*ed093b41SRobert Mustacchi {
217*ed093b41SRobert Mustacchi 	char *end = buf + nbytes;
218*ed093b41SRobert Mustacchi 	char *p = buf;
219*ed093b41SRobert Mustacchi 
220*ed093b41SRobert Mustacchi 	buf[0] = '\0';
221*ed093b41SRobert Mustacchi 
222*ed093b41SRobert Mustacchi 	/*
223*ed093b41SRobert Mustacchi 	 * Decode the MXCSR word
224*ed093b41SRobert Mustacchi 	 */
225*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_IE)
226*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|IE");
227*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_DE)
228*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|DE");
229*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_ZE)
230*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|ZE");
231*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_OE)
232*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|OE");
233*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_UE)
234*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|UE");
235*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_PE)
236*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|PE");
237*ed093b41SRobert Mustacchi 
238*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_DAZ)
239*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|DAZ");
240*ed093b41SRobert Mustacchi 
241*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_IM)
242*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|IM");
243*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_DM)
244*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|DM");
245*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_ZM)
246*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|ZM");
247*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_OM)
248*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|OM");
249*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_UM)
250*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|UM");
251*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_PM)
252*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|PM");
253*ed093b41SRobert Mustacchi 
254*ed093b41SRobert Mustacchi 	if ((mxcsr & SSE_RC) == (SSE_RD|SSE_RU))
255*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|RTZ");
256*ed093b41SRobert Mustacchi 	else if (mxcsr & SSE_RD)
257*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|RD");
258*ed093b41SRobert Mustacchi 	else if (mxcsr & SSE_RU)
259*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|RU");
260*ed093b41SRobert Mustacchi 	else
261*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|RTN");
262*ed093b41SRobert Mustacchi 
263*ed093b41SRobert Mustacchi 	if (mxcsr & SSE_FZ)
264*ed093b41SRobert Mustacchi 		p += mdb_snprintf(p, (size_t)(end - p), "|FZ");
265*ed093b41SRobert Mustacchi 
266*ed093b41SRobert Mustacchi 	if (buf[0] == '|')
267*ed093b41SRobert Mustacchi 		return (buf + 1);
268*ed093b41SRobert Mustacchi 	return ("0");
269*ed093b41SRobert Mustacchi }
270*ed093b41SRobert Mustacchi 
271*ed093b41SRobert Mustacchi const char *
fptag2str(uint32_t val)272*ed093b41SRobert Mustacchi fptag2str(uint32_t val)
273*ed093b41SRobert Mustacchi {
274*ed093b41SRobert Mustacchi 	/*
275*ed093b41SRobert Mustacchi 	 * Array of strings corresponding to FPU tag word values (see
276*ed093b41SRobert Mustacchi 	 * section 7.3.6 of the Intel Programmer's Reference Manual).
277*ed093b41SRobert Mustacchi 	 */
278*ed093b41SRobert Mustacchi 	const char *tag_strings[] = { "valid", "zero", "special", "empty" };
279*ed093b41SRobert Mustacchi 
280*ed093b41SRobert Mustacchi 	if (val >= ARRAY_SIZE(tag_strings)) {
281*ed093b41SRobert Mustacchi 		return ("unknown");
282*ed093b41SRobert Mustacchi 	}
283*ed093b41SRobert Mustacchi 
284*ed093b41SRobert Mustacchi 	return (tag_strings[val]);
285*ed093b41SRobert Mustacchi }
286*ed093b41SRobert Mustacchi 
287*ed093b41SRobert Mustacchi static uintptr_t
xregs_data_ptr(const prxregset_hdr_t * prx,const prxregset_info_t * info)288*ed093b41SRobert Mustacchi xregs_data_ptr(const prxregset_hdr_t *prx, const prxregset_info_t *info)
289*ed093b41SRobert Mustacchi {
290*ed093b41SRobert Mustacchi 	uintptr_t base = (uintptr_t)prx;
291*ed093b41SRobert Mustacchi 	return (base + info->pri_offset);
292*ed093b41SRobert Mustacchi }
293*ed093b41SRobert Mustacchi 
294*ed093b41SRobert Mustacchi static boolean_t
xregs_valid_data(const prxregset_hdr_t * prx,const prxregset_info_t * info,size_t exp_size,const char * type)295*ed093b41SRobert Mustacchi xregs_valid_data(const prxregset_hdr_t *prx, const prxregset_info_t *info,
296*ed093b41SRobert Mustacchi     size_t exp_size, const char *type)
297*ed093b41SRobert Mustacchi {
298*ed093b41SRobert Mustacchi 	size_t last_byte;
299*ed093b41SRobert Mustacchi 
300*ed093b41SRobert Mustacchi 	if (info->pri_size != exp_size) {
301*ed093b41SRobert Mustacchi 		mdb_warn("%s has unexpeced size 0x%lx, expected 0x%lx -- "
302*ed093b41SRobert Mustacchi 		    "cannot use\n", type, info->pri_size, exp_size);
303*ed093b41SRobert Mustacchi 		return (B_FALSE);
304*ed093b41SRobert Mustacchi 	}
305*ed093b41SRobert Mustacchi 
306*ed093b41SRobert Mustacchi 	last_byte = (size_t)info->pri_size + (size_t)info->pri_offset;
307*ed093b41SRobert Mustacchi 	if (last_byte < MIN(info->pri_size, info->pri_offset)) {
308*ed093b41SRobert Mustacchi 		mdb_warn("%s size 0x%lx and offset 0x%lx appear to overflow -- "
309*ed093b41SRobert Mustacchi 		    "canot use\n", type, info->pri_size, info->pri_offset);
310*ed093b41SRobert Mustacchi 		return (B_FALSE);
311*ed093b41SRobert Mustacchi 	}
312*ed093b41SRobert Mustacchi 
313*ed093b41SRobert Mustacchi 	return (B_TRUE);
314*ed093b41SRobert Mustacchi }
315*ed093b41SRobert Mustacchi 
316*ed093b41SRobert Mustacchi static const char *
fp_type_to_str(x86_vector_type_t type)317*ed093b41SRobert Mustacchi fp_type_to_str(x86_vector_type_t type)
318*ed093b41SRobert Mustacchi {
319*ed093b41SRobert Mustacchi 	switch (type) {
320*ed093b41SRobert Mustacchi 	case XMM:
321*ed093b41SRobert Mustacchi 		return ("128-bit %xmm");
322*ed093b41SRobert Mustacchi 	case YMM:
323*ed093b41SRobert Mustacchi 		return ("256-bit %ymm");
324*ed093b41SRobert Mustacchi 	case ZMM:
325*ed093b41SRobert Mustacchi 		return ("512-bit %zmm");
326*ed093b41SRobert Mustacchi 	default:
327*ed093b41SRobert Mustacchi 		return ("unknown");
328*ed093b41SRobert Mustacchi 	}
329*ed093b41SRobert Mustacchi }
330*ed093b41SRobert Mustacchi 
331*ed093b41SRobert Mustacchi /*
332*ed093b41SRobert Mustacchi  * Go through the xregs data that we have and make sure that it makes sense for
333*ed093b41SRobert Mustacchi  * printing. In particular we need to make sure:
334*ed093b41SRobert Mustacchi  *
335*ed093b41SRobert Mustacchi  *  o The structure type is what we expect
336*ed093b41SRobert Mustacchi  *  o That its overall size is correct
337*ed093b41SRobert Mustacchi  *  o That we can find the expected set of data pointers that should be here
338*ed093b41SRobert Mustacchi  *  o That the information pointers actually make sense and their contents are
339*ed093b41SRobert Mustacchi  *    both the correct size and within the overall structure. Note, we do not
340*ed093b41SRobert Mustacchi  *    check for overlapping data regions right now, meaning that some weird
341*ed093b41SRobert Mustacchi  *    notes may still lead to weird data.
342*ed093b41SRobert Mustacchi  */
343*ed093b41SRobert Mustacchi static boolean_t
pt_xregs_process(const prxregset_hdr_t * prx,size_t found_size,x86_xregs_info_t * xinfo)344*ed093b41SRobert Mustacchi pt_xregs_process(const prxregset_hdr_t *prx, size_t found_size,
345*ed093b41SRobert Mustacchi     x86_xregs_info_t *xinfo)
346*ed093b41SRobert Mustacchi {
347*ed093b41SRobert Mustacchi 	bzero(xinfo, sizeof (*xinfo));
348*ed093b41SRobert Mustacchi 
349*ed093b41SRobert Mustacchi 	if (prx->pr_type != PR_TYPE_XSAVE) {
350*ed093b41SRobert Mustacchi 		mdb_warn("prxregset has unknown type: 0x%x -- falling back "
351*ed093b41SRobert Mustacchi 		    "to fpregset_t\n", prx->pr_type);
352*ed093b41SRobert Mustacchi 		return (B_FALSE);
353*ed093b41SRobert Mustacchi 	}
354*ed093b41SRobert Mustacchi 
355*ed093b41SRobert Mustacchi 	if (prx->pr_size < found_size) {
356*ed093b41SRobert Mustacchi 		mdb_warn("prxregset has greater size than we were given: "
357*ed093b41SRobert Mustacchi 		    "found 0x%lx, have 0x%lx -- falling back to fpregset_t\n",
358*ed093b41SRobert Mustacchi 		    prx->pr_size, found_size);
359*ed093b41SRobert Mustacchi 		return (B_FALSE);
360*ed093b41SRobert Mustacchi 	}
361*ed093b41SRobert Mustacchi 
362*ed093b41SRobert Mustacchi 	for (uint32_t i = 0; i < prx->pr_ninfo; i++) {
363*ed093b41SRobert Mustacchi 		switch (prx->pr_info[i].pri_type) {
364*ed093b41SRobert Mustacchi 		case PRX_INFO_XCR:
365*ed093b41SRobert Mustacchi 			if (xregs_valid_data(prx, &prx->pr_info[i],
366*ed093b41SRobert Mustacchi 			    sizeof (prxregset_xcr_t), "xcr")) {
367*ed093b41SRobert Mustacchi 				xinfo->xri_xcr = (void *)xregs_data_ptr(prx,
368*ed093b41SRobert Mustacchi 				    &prx->pr_info[i]);
369*ed093b41SRobert Mustacchi 			}
370*ed093b41SRobert Mustacchi 			break;
371*ed093b41SRobert Mustacchi 		case PRX_INFO_XSAVE:
372*ed093b41SRobert Mustacchi 			if (xregs_valid_data(prx, &prx->pr_info[i],
373*ed093b41SRobert Mustacchi 			    sizeof (prxregset_xsave_t), "xsave")) {
374*ed093b41SRobert Mustacchi 				xinfo->xri_xsave = (void *)xregs_data_ptr(prx,
375*ed093b41SRobert Mustacchi 				    &prx->pr_info[i]);
376*ed093b41SRobert Mustacchi 			}
377*ed093b41SRobert Mustacchi 			break;
378*ed093b41SRobert Mustacchi 		case PRX_INFO_YMM:
379*ed093b41SRobert Mustacchi 			if (xregs_valid_data(prx, &prx->pr_info[i],
380*ed093b41SRobert Mustacchi 			    sizeof (prxregset_ymm_t), "ymm")) {
381*ed093b41SRobert Mustacchi 				xinfo->xri_ymm = (void *)xregs_data_ptr(prx,
382*ed093b41SRobert Mustacchi 				    &prx->pr_info[i]);
383*ed093b41SRobert Mustacchi 			}
384*ed093b41SRobert Mustacchi 			break;
385*ed093b41SRobert Mustacchi 		case PRX_INFO_OPMASK:
386*ed093b41SRobert Mustacchi 			if (xregs_valid_data(prx, &prx->pr_info[i],
387*ed093b41SRobert Mustacchi 			    sizeof (prxregset_opmask_t), "opmask")) {
388*ed093b41SRobert Mustacchi 				xinfo->xri_opmask = (void *)xregs_data_ptr(prx,
389*ed093b41SRobert Mustacchi 				    &prx->pr_info[i]);
390*ed093b41SRobert Mustacchi 			}
391*ed093b41SRobert Mustacchi 			break;
392*ed093b41SRobert Mustacchi 		case PRX_INFO_ZMM:
393*ed093b41SRobert Mustacchi 			if (xregs_valid_data(prx, &prx->pr_info[i],
394*ed093b41SRobert Mustacchi 			    sizeof (prxregset_zmm_t), "zmm")) {
395*ed093b41SRobert Mustacchi 				xinfo->xri_zmm = (void *)xregs_data_ptr(prx,
396*ed093b41SRobert Mustacchi 				    &prx->pr_info[i]);
397*ed093b41SRobert Mustacchi 			}
398*ed093b41SRobert Mustacchi 			break;
399*ed093b41SRobert Mustacchi 		case PRX_INFO_HI_ZMM:
400*ed093b41SRobert Mustacchi 			if (xregs_valid_data(prx, &prx->pr_info[i],
401*ed093b41SRobert Mustacchi 			    sizeof (prxregset_hi_zmm_t), "hi_zmm")) {
402*ed093b41SRobert Mustacchi 				xinfo->xri_hi_zmm = (void *)xregs_data_ptr(prx,
403*ed093b41SRobert Mustacchi 				    &prx->pr_info[i]);
404*ed093b41SRobert Mustacchi 			}
405*ed093b41SRobert Mustacchi 			break;
406*ed093b41SRobert Mustacchi 		default:
407*ed093b41SRobert Mustacchi 			mdb_warn("ignoring unexpected xreg info type: 0x%x\n",
408*ed093b41SRobert Mustacchi 			    prx->pr_info[i].pri_type);
409*ed093b41SRobert Mustacchi 			break;
410*ed093b41SRobert Mustacchi 		}
411*ed093b41SRobert Mustacchi 	}
412*ed093b41SRobert Mustacchi 
413*ed093b41SRobert Mustacchi 	/*
414*ed093b41SRobert Mustacchi 	 * Now that we have gotten this far, we go and figure out what the
415*ed093b41SRobert Mustacchi 	 * largest type of information we actually have is. We check from the
416*ed093b41SRobert Mustacchi 	 * simplest to the most complex as to see the more complex state
417*ed093b41SRobert Mustacchi 	 * requires having the more basic state, due to how Intel designed the
418*ed093b41SRobert Mustacchi 	 * xsave state.
419*ed093b41SRobert Mustacchi 	 */
420*ed093b41SRobert Mustacchi 	if (xinfo->xri_xsave == NULL) {
421*ed093b41SRobert Mustacchi 		mdb_warn("missing required xsave information: xregs not "
422*ed093b41SRobert Mustacchi 		    "usable -- falling back to fpregset_t\n");
423*ed093b41SRobert Mustacchi 		return (B_FALSE);
424*ed093b41SRobert Mustacchi 	}
425*ed093b41SRobert Mustacchi 
426*ed093b41SRobert Mustacchi 	xinfo->xri_type = XMM;
427*ed093b41SRobert Mustacchi 	if (xinfo->xri_ymm != NULL) {
428*ed093b41SRobert Mustacchi 		xinfo->xri_type = YMM;
429*ed093b41SRobert Mustacchi 		uint_t nzmm = 0;
430*ed093b41SRobert Mustacchi 		if (xinfo->xri_opmask != NULL)
431*ed093b41SRobert Mustacchi 			nzmm++;
432*ed093b41SRobert Mustacchi 		if (xinfo->xri_zmm != NULL)
433*ed093b41SRobert Mustacchi 			nzmm++;
434*ed093b41SRobert Mustacchi 		if (xinfo->xri_hi_zmm != NULL)
435*ed093b41SRobert Mustacchi 			nzmm++;
436*ed093b41SRobert Mustacchi 		if (nzmm == 3) {
437*ed093b41SRobert Mustacchi 			xinfo->xri_type = ZMM;
438*ed093b41SRobert Mustacchi 		} else if (nzmm != 0) {
439*ed093b41SRobert Mustacchi 			mdb_warn("encountered mismatched AVX-512 components, "
440*ed093b41SRobert Mustacchi 			    "defaulting back to YMM\n");
441*ed093b41SRobert Mustacchi 			mdb_warn("found opmask %s, zmm %s, hi zmm %s\n",
442*ed093b41SRobert Mustacchi 			    xinfo->xri_opmask != NULL ? "present" : "missing",
443*ed093b41SRobert Mustacchi 			    xinfo->xri_zmm != NULL ? "present" : "missing",
444*ed093b41SRobert Mustacchi 			    xinfo->xri_hi_zmm != NULL ? "present" : "missing");
445*ed093b41SRobert Mustacchi 		}
446*ed093b41SRobert Mustacchi 	}
447*ed093b41SRobert Mustacchi 
448*ed093b41SRobert Mustacchi 	return (B_TRUE);
449*ed093b41SRobert Mustacchi }
450*ed093b41SRobert Mustacchi 
451*ed093b41SRobert Mustacchi static void
pt_xreg_single_vector(const upad128_t * xmm,const upad128_t * ymm,const upad256_t * zmm,uint32_t num)452*ed093b41SRobert Mustacchi pt_xreg_single_vector(const upad128_t *xmm, const upad128_t *ymm,
453*ed093b41SRobert Mustacchi     const upad256_t *zmm, uint32_t num)
454*ed093b41SRobert Mustacchi {
455*ed093b41SRobert Mustacchi 
456*ed093b41SRobert Mustacchi 	if (zmm != NULL) {
457*ed093b41SRobert Mustacchi 		mdb_printf("%%zmm%u%s[511:384] 0x%08x %08x %08x %08x\n"
458*ed093b41SRobert Mustacchi 		    "       [383:256] 0x%08x %08x %08x %08x\n", num,
459*ed093b41SRobert Mustacchi 		    num >= 10 ? " " : "  ",
460*ed093b41SRobert Mustacchi 		    zmm->_l[7], zmm->_l[6], zmm->_l[5], zmm->_l[4],
461*ed093b41SRobert Mustacchi 		    zmm->_l[3], zmm->_l[2], zmm->_l[1], zmm->_l[0]);
462*ed093b41SRobert Mustacchi 	}
463*ed093b41SRobert Mustacchi 
464*ed093b41SRobert Mustacchi 	if (ymm != NULL) {
465*ed093b41SRobert Mustacchi 		mdb_printf("%%ymm%u%s[255:128] 0x%08x %08x %08x %08x\n",
466*ed093b41SRobert Mustacchi 		    num, num >= 10 ? " " : "  ",
467*ed093b41SRobert Mustacchi 		    ymm->_l[3], ymm->_l[2], ymm->_l[1], ymm->_l[0]);
468*ed093b41SRobert Mustacchi 	}
469*ed093b41SRobert Mustacchi 
470*ed093b41SRobert Mustacchi 	if (xmm != NULL) {
471*ed093b41SRobert Mustacchi 		mdb_printf("%%xmm%u%s[127:0]   0x%08x %08x %08x %08x\n",
472*ed093b41SRobert Mustacchi 		    num, num >= 10 ? " " : "  ",
473*ed093b41SRobert Mustacchi 		    xmm->_l[3], xmm->_l[2], xmm->_l[1], xmm->_l[0]);
474*ed093b41SRobert Mustacchi 	}
475*ed093b41SRobert Mustacchi 
476*ed093b41SRobert Mustacchi 	/*
477*ed093b41SRobert Mustacchi 	 * Insert output spacing if we exceed more than one line which happens
478*ed093b41SRobert Mustacchi 	 * if ymm state is present.
479*ed093b41SRobert Mustacchi 	 */
480*ed093b41SRobert Mustacchi 	if (ymm != NULL) {
481*ed093b41SRobert Mustacchi 		mdb_printf("\n");
482*ed093b41SRobert Mustacchi 	}
483*ed093b41SRobert Mustacchi }
484*ed093b41SRobert Mustacchi 
485*ed093b41SRobert Mustacchi /*
486*ed093b41SRobert Mustacchi  * Variant of the above, but all of the data is one single register. This is
487*ed093b41SRobert Mustacchi  * only used for the high zmm registers which are only present on amd64.
488*ed093b41SRobert Mustacchi  */
489*ed093b41SRobert Mustacchi #ifdef __amd64
490*ed093b41SRobert Mustacchi static void
pt_xreg_single_u512(const upad512_t * zmm,uint32_t num)491*ed093b41SRobert Mustacchi pt_xreg_single_u512(const upad512_t *zmm, uint32_t num)
492*ed093b41SRobert Mustacchi {
493*ed093b41SRobert Mustacchi 	mdb_printf("%%zmm%u%s[511:384] 0x%08x %08x %08x %08x\n"
494*ed093b41SRobert Mustacchi 	    "       [383:256] 0x%08x %08x %08x %08x\n", num,
495*ed093b41SRobert Mustacchi 	    num >= 10 ? " " : "  ",
496*ed093b41SRobert Mustacchi 	    zmm->_l[15], zmm->_l[14], zmm->_l[13], zmm->_l[12],
497*ed093b41SRobert Mustacchi 	    zmm->_l[11], zmm->_l[10], zmm->_l[9], zmm->_l[8]);
498*ed093b41SRobert Mustacchi 
499*ed093b41SRobert Mustacchi 	mdb_printf("%%zmm%u%s[255:128] 0x%08x %08x %08x %08x\n",
500*ed093b41SRobert Mustacchi 	    num, num >= 10 ? " " : "  ",
501*ed093b41SRobert Mustacchi 	    zmm->_l[7], zmm->_l[6], zmm->_l[5], zmm->_l[4]);
502*ed093b41SRobert Mustacchi 
503*ed093b41SRobert Mustacchi 	mdb_printf("%%zmm%u%s[127:0]   0x%08x %08x %08x %08x\n",
504*ed093b41SRobert Mustacchi 	    num, num >= 10 ? " " : "  ",
505*ed093b41SRobert Mustacchi 	    zmm->_l[3], zmm->_l[2], zmm->_l[1], zmm->_l[0]);
506*ed093b41SRobert Mustacchi 
507*ed093b41SRobert Mustacchi 	mdb_printf("\n");
508*ed093b41SRobert Mustacchi }
509*ed093b41SRobert Mustacchi #endif	/* __amd64 */
510*ed093b41SRobert Mustacchi 
511*ed093b41SRobert Mustacchi /*
512*ed093b41SRobert Mustacchi  * There are two different cases that we need to consider for vector printing.
513*ed093b41SRobert Mustacchi  * The first 16 FPU registers are shadowed as the low bits of xmm0 overlap with
514*ed093b41SRobert Mustacchi  * ymm0, overlap with zmm0.
515*ed093b41SRobert Mustacchi  */
516*ed093b41SRobert Mustacchi static void
pt_xregs_vectors(const x86_xregs_info_t * xinfo)517*ed093b41SRobert Mustacchi pt_xregs_vectors(const x86_xregs_info_t *xinfo)
518*ed093b41SRobert Mustacchi {
519*ed093b41SRobert Mustacchi 	size_t nregs = ARRAY_SIZE(xinfo->xri_xsave->prx_fx_xmm);
520*ed093b41SRobert Mustacchi 	for (size_t i = 0; i < nregs; i++) {
521*ed093b41SRobert Mustacchi 		switch (xinfo->xri_type) {
522*ed093b41SRobert Mustacchi 		case XMM:
523*ed093b41SRobert Mustacchi 			pt_xreg_single_vector(&xinfo->xri_xsave->prx_fx_xmm[i],
524*ed093b41SRobert Mustacchi 			    NULL, NULL, i);
525*ed093b41SRobert Mustacchi 			break;
526*ed093b41SRobert Mustacchi 		case YMM:
527*ed093b41SRobert Mustacchi 			pt_xreg_single_vector(&xinfo->xri_xsave->prx_fx_xmm[i],
528*ed093b41SRobert Mustacchi 			    &xinfo->xri_ymm->prx_ymm[i], NULL, i);
529*ed093b41SRobert Mustacchi 			break;
530*ed093b41SRobert Mustacchi 		case ZMM:
531*ed093b41SRobert Mustacchi 			pt_xreg_single_vector(&xinfo->xri_xsave->prx_fx_xmm[i],
532*ed093b41SRobert Mustacchi 			    &xinfo->xri_ymm->prx_ymm[i],
533*ed093b41SRobert Mustacchi 			    &xinfo->xri_zmm->prx_zmm[i], i);
534*ed093b41SRobert Mustacchi 			break;
535*ed093b41SRobert Mustacchi 		}
536*ed093b41SRobert Mustacchi 	}
537*ed093b41SRobert Mustacchi 
538*ed093b41SRobert Mustacchi 	/*
539*ed093b41SRobert Mustacchi 	 * If we have ZMM state, next print the remaining 16 registers and then
540*ed093b41SRobert Mustacchi 	 * the 8 opmask registers. Note, we only have the high ZMM registers on
541*ed093b41SRobert Mustacchi 	 * 64-bit processes.
542*ed093b41SRobert Mustacchi 	 */
543*ed093b41SRobert Mustacchi 	if (xinfo->xri_type == ZMM) {
544*ed093b41SRobert Mustacchi #ifdef __amd64
545*ed093b41SRobert Mustacchi 		nregs = ARRAY_SIZE(xinfo->xri_hi_zmm->prx_hi_zmm);
546*ed093b41SRobert Mustacchi 		for (size_t i = 0; i < nregs; i++) {
547*ed093b41SRobert Mustacchi 			pt_xreg_single_u512(&xinfo->xri_hi_zmm->prx_hi_zmm[i],
548*ed093b41SRobert Mustacchi 			    i + 16);
549*ed093b41SRobert Mustacchi 		}
550*ed093b41SRobert Mustacchi #endif	/* __amd64 */
551*ed093b41SRobert Mustacchi 
552*ed093b41SRobert Mustacchi 		mdb_printf("%%k0  0x%016x\t\t%%k1  0x%016x\n",
553*ed093b41SRobert Mustacchi 		    xinfo->xri_opmask->prx_opmask[0],
554*ed093b41SRobert Mustacchi 		    xinfo->xri_opmask->prx_opmask[1]);
555*ed093b41SRobert Mustacchi 		mdb_printf("%%k2  0x%016x\t\t%%k3  0x%016x\n",
556*ed093b41SRobert Mustacchi 		    xinfo->xri_opmask->prx_opmask[2],
557*ed093b41SRobert Mustacchi 		    xinfo->xri_opmask->prx_opmask[3]);
558*ed093b41SRobert Mustacchi 		mdb_printf("%%k4  0x%016x\t\t%%k5  0x%016x\n",
559*ed093b41SRobert Mustacchi 		    xinfo->xri_opmask->prx_opmask[4],
560*ed093b41SRobert Mustacchi 		    xinfo->xri_opmask->prx_opmask[5]);
561*ed093b41SRobert Mustacchi 		mdb_printf("%%k6  0x%016x\t\t%%k7  0x%016x\n",
562*ed093b41SRobert Mustacchi 		    xinfo->xri_opmask->prx_opmask[6],
563*ed093b41SRobert Mustacchi 		    xinfo->xri_opmask->prx_opmask[7]);
564*ed093b41SRobert Mustacchi 
565*ed093b41SRobert Mustacchi 		mdb_printf("\n");
566*ed093b41SRobert Mustacchi 	}
567*ed093b41SRobert Mustacchi }
568*ed093b41SRobert Mustacchi 
569*ed093b41SRobert Mustacchi int
x86_pt_fpregs_common(uintptr_t addr,uint_t flags,int argc,prfpregset_t * fprsp)570*ed093b41SRobert Mustacchi x86_pt_fpregs_common(uintptr_t addr, uint_t flags, int argc,
571*ed093b41SRobert Mustacchi     prfpregset_t *fprsp)
572*ed093b41SRobert Mustacchi {
573*ed093b41SRobert Mustacchi 	mdb_tgt_t *t = mdb.m_target;
574*ed093b41SRobert Mustacchi 	mdb_tgt_tid_t tid;
575*ed093b41SRobert Mustacchi 	prxregset_t *xregs = NULL;
576*ed093b41SRobert Mustacchi 	size_t xregsize = 0;
577*ed093b41SRobert Mustacchi 	x86_xregs_info_t xinfo;
578*ed093b41SRobert Mustacchi 	x86_vector_type_t vector_type = XMM;
579*ed093b41SRobert Mustacchi 
580*ed093b41SRobert Mustacchi 	if (argc != 0)
581*ed093b41SRobert Mustacchi 		return (DCMD_USAGE);
582*ed093b41SRobert Mustacchi 
583*ed093b41SRobert Mustacchi 	if (t->t_pshandle == NULL || Pstate(t->t_pshandle) == PS_UNDEAD) {
584*ed093b41SRobert Mustacchi 		mdb_warn("no process active\n");
585*ed093b41SRobert Mustacchi 		return (DCMD_ERR);
586*ed093b41SRobert Mustacchi 	}
587*ed093b41SRobert Mustacchi 
588*ed093b41SRobert Mustacchi 	if (Pstate(t->t_pshandle) == PS_LOST) {
589*ed093b41SRobert Mustacchi 		mdb_warn("debugger has lost control of process\n");
590*ed093b41SRobert Mustacchi 		return (DCMD_ERR);
591*ed093b41SRobert Mustacchi 	}
592*ed093b41SRobert Mustacchi 
593*ed093b41SRobert Mustacchi 	if (flags & DCMD_ADDRSPEC)
594*ed093b41SRobert Mustacchi 		tid = (mdb_tgt_tid_t)addr;
595*ed093b41SRobert Mustacchi 	else
596*ed093b41SRobert Mustacchi 		tid = PTL_TID(t);
597*ed093b41SRobert Mustacchi 
598*ed093b41SRobert Mustacchi 	/*
599*ed093b41SRobert Mustacchi 	 * We ultimately need both the xregs and the fpregs. The fpregs have
600*ed093b41SRobert Mustacchi 	 * included synthetic-kernel created state that is not part of the FPU
601*ed093b41SRobert Mustacchi 	 * (the status / xstatus bits). If we find the xregs state, then we
602*ed093b41SRobert Mustacchi 	 * focus on using its data in lieu of the standard fxsave piece.
603*ed093b41SRobert Mustacchi 	 */
604*ed093b41SRobert Mustacchi 	if (PTL_GETFPREGS(t, tid, fprsp) != 0) {
605*ed093b41SRobert Mustacchi 		mdb_warn("failed to get floating point registers");
606*ed093b41SRobert Mustacchi 		return (DCMD_ERR);
607*ed093b41SRobert Mustacchi 	}
608*ed093b41SRobert Mustacchi 
609*ed093b41SRobert Mustacchi 	bzero(&xinfo, sizeof (x86_xregs_info_t));
610*ed093b41SRobert Mustacchi 	if (PTL_GETXREGS(t, tid, &xregs, &xregsize) == 0) {
611*ed093b41SRobert Mustacchi 		prxregset_hdr_t *prx = (prxregset_hdr_t *)xregs;
612*ed093b41SRobert Mustacchi 		if (!pt_xregs_process(prx, xregsize, &xinfo)) {
613*ed093b41SRobert Mustacchi 			PTL_FREEXREGS(t, xregs, xregsize);
614*ed093b41SRobert Mustacchi 			xregs = NULL;
615*ed093b41SRobert Mustacchi 		} else {
616*ed093b41SRobert Mustacchi 			vector_type = xinfo.xri_type;
617*ed093b41SRobert Mustacchi 		}
618*ed093b41SRobert Mustacchi 	} else if (errno != ENOENT && errno != ENODATA && errno != ENOTSUP) {
619*ed093b41SRobert Mustacchi 		mdb_warn("failed to get xregs");
620*ed093b41SRobert Mustacchi 	}
621*ed093b41SRobert Mustacchi 
622*ed093b41SRobert Mustacchi 	/*
623*ed093b41SRobert Mustacchi 	 * As we only support the amd64 kernel, we basically phrase the FPU the
624*ed093b41SRobert Mustacchi 	 * same way regardless of whether it is a 32-bit or 64-bit process.
625*ed093b41SRobert Mustacchi 	 */
626*ed093b41SRobert Mustacchi 	mdb_printf("x86 FPU with %s registers\n", fp_type_to_str(vector_type));
627*ed093b41SRobert Mustacchi 	if (xinfo.xri_xcr != NULL) {
628*ed093b41SRobert Mustacchi 		mdb_printf("xcr0\t\t0x%lx\n", xinfo.xri_xcr->prx_xcr_xcr0);
629*ed093b41SRobert Mustacchi 		mdb_printf("xfd\t\t0x%lx\n", xinfo.xri_xcr->prx_xcr_xfd);
630*ed093b41SRobert Mustacchi 	}
631*ed093b41SRobert Mustacchi 
632*ed093b41SRobert Mustacchi 	if (xinfo.xri_xsave != NULL) {
633*ed093b41SRobert Mustacchi 		mdb_printf("xstate_bv\t0x%lx\n",
634*ed093b41SRobert Mustacchi 		    xinfo.xri_xsave->prx_xsh_xstate_bv);
635*ed093b41SRobert Mustacchi 		mdb_printf("xcomp_bv\t0x%lx\n",
636*ed093b41SRobert Mustacchi 		    xinfo.xri_xsave->prx_xsh_xcomp_bv);
637*ed093b41SRobert Mustacchi 
638*ed093b41SRobert Mustacchi 		mdb_printf("\n");
639*ed093b41SRobert Mustacchi 		/*
640*ed093b41SRobert Mustacchi 		 * xsave is required for us to use the xregset, so from here as
641*ed093b41SRobert Mustacchi 		 * it to print vectors.
642*ed093b41SRobert Mustacchi 		 */
643*ed093b41SRobert Mustacchi 		pt_xregs_vectors(&xinfo);
644*ed093b41SRobert Mustacchi 	} else {
645*ed093b41SRobert Mustacchi 		size_t nregs = ARRAY_SIZE(fprsp->fp_reg_set.fpchip_state.xmm);
646*ed093b41SRobert Mustacchi 		for (uint32_t i = 0; i < nregs; i++) {
647*ed093b41SRobert Mustacchi 			const upad128_t *u128 =
648*ed093b41SRobert Mustacchi 			    &fprsp->fp_reg_set.fpchip_state.xmm[i];
649*ed093b41SRobert Mustacchi 			pt_xreg_single_vector(u128, NULL, NULL, i);
650*ed093b41SRobert Mustacchi 		}
651*ed093b41SRobert Mustacchi 
652*ed093b41SRobert Mustacchi 		mdb_printf("\n");
653*ed093b41SRobert Mustacchi 	}
654*ed093b41SRobert Mustacchi 
655*ed093b41SRobert Mustacchi 	if (xregs != NULL) {
656*ed093b41SRobert Mustacchi 		PTL_FREEXREGS(t, xregs, xregsize);
657*ed093b41SRobert Mustacchi 	}
658*ed093b41SRobert Mustacchi 
659*ed093b41SRobert Mustacchi 	return (DCMD_OK);
660*ed093b41SRobert Mustacchi }
661*ed093b41SRobert Mustacchi 
662*ed093b41SRobert Mustacchi void
x86_pt_fpregs_sse_ctl(uint32_t mxcsr,uint32_t xstatus,char * buf,size_t buflen)663*ed093b41SRobert Mustacchi x86_pt_fpregs_sse_ctl(uint32_t mxcsr, uint32_t xstatus, char *buf,
664*ed093b41SRobert Mustacchi     size_t buflen)
665*ed093b41SRobert Mustacchi {
666*ed093b41SRobert Mustacchi 	mdb_printf("\nSSE Control State\n");
667*ed093b41SRobert Mustacchi 	mdb_printf("mxcsr  0x%04x (%s)\n", mxcsr,
668*ed093b41SRobert Mustacchi 	    fpmxcsr2str(mxcsr, buf, buflen));
669*ed093b41SRobert Mustacchi 	mdb_printf("xcp    0x%04x (%s)\n", xstatus,
670*ed093b41SRobert Mustacchi 	    fpmxcsr2str(xstatus, buf, buflen));
671*ed093b41SRobert Mustacchi }
672