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