1*ed093b41SRobert Mustacchi /*
2*ed093b41SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*ed093b41SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*ed093b41SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*ed093b41SRobert Mustacchi * 1.0 of the CDDL.
6*ed093b41SRobert Mustacchi *
7*ed093b41SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*ed093b41SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*ed093b41SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*ed093b41SRobert Mustacchi */
11*ed093b41SRobert Mustacchi
12*ed093b41SRobert Mustacchi /*
13*ed093b41SRobert Mustacchi * Copyright 2023 Oxide Computer Company
14*ed093b41SRobert Mustacchi */
15*ed093b41SRobert Mustacchi
16*ed093b41SRobert Mustacchi /*
17*ed093b41SRobert Mustacchi * This attempts to do a series of writes to the /proc control file that have
18*ed093b41SRobert Mustacchi * invalid data for the xregs state. The way that this works is that we create a
19*ed093b41SRobert Mustacchi * thread that will be detached and just sleeps whenever it wakes up. We direct
20*ed093b41SRobert Mustacchi * this thread to stop with a directed PCSTOP via libproc.
21*ed093b41SRobert Mustacchi */
22*ed093b41SRobert Mustacchi
23*ed093b41SRobert Mustacchi #include <err.h>
24*ed093b41SRobert Mustacchi #include <stdlib.h>
25*ed093b41SRobert Mustacchi #include <libproc.h>
26*ed093b41SRobert Mustacchi #include <thread.h>
27*ed093b41SRobert Mustacchi #include <errno.h>
28*ed093b41SRobert Mustacchi #include <string.h>
29*ed093b41SRobert Mustacchi #include <sys/sysmacros.h>
30*ed093b41SRobert Mustacchi #include <sys/debug.h>
31*ed093b41SRobert Mustacchi #include <sys/x86_archext.h>
32*ed093b41SRobert Mustacchi
33*ed093b41SRobert Mustacchi #include "xsave_util.h"
34*ed093b41SRobert Mustacchi
35*ed093b41SRobert Mustacchi static prxregset_t *bad_xregs_pxr;
36*ed093b41SRobert Mustacchi static size_t bad_xregs_size;
37*ed093b41SRobert Mustacchi
38*ed093b41SRobert Mustacchi typedef struct bad_xregs_test {
39*ed093b41SRobert Mustacchi const char *bxt_desc;
40*ed093b41SRobert Mustacchi int bxt_errno;
41*ed093b41SRobert Mustacchi uint32_t bxt_min;
42*ed093b41SRobert Mustacchi void (*bxt_setup)(void **, size_t *);
43*ed093b41SRobert Mustacchi } bad_xregs_test_t;
44*ed093b41SRobert Mustacchi
45*ed093b41SRobert Mustacchi static void
bad_xregs_no_data(void ** bufp,size_t * sizep)46*ed093b41SRobert Mustacchi bad_xregs_no_data(void **bufp, size_t *sizep)
47*ed093b41SRobert Mustacchi {
48*ed093b41SRobert Mustacchi *bufp = NULL;
49*ed093b41SRobert Mustacchi *sizep = 0;
50*ed093b41SRobert Mustacchi }
51*ed093b41SRobert Mustacchi
52*ed093b41SRobert Mustacchi static void
bad_xregs_null_buf(void ** bufp,size_t * sizep)53*ed093b41SRobert Mustacchi bad_xregs_null_buf(void **bufp, size_t *sizep)
54*ed093b41SRobert Mustacchi {
55*ed093b41SRobert Mustacchi *bufp = NULL;
56*ed093b41SRobert Mustacchi *sizep = sizeof (prxregset_hdr_t);
57*ed093b41SRobert Mustacchi }
58*ed093b41SRobert Mustacchi
59*ed093b41SRobert Mustacchi static void
bad_xregs_short_hdr(void ** bufp,size_t * sizep)60*ed093b41SRobert Mustacchi bad_xregs_short_hdr(void **bufp, size_t *sizep)
61*ed093b41SRobert Mustacchi {
62*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = calloc(1, sizeof (prxregset_hdr_t));
63*ed093b41SRobert Mustacchi if (hdr == NULL) {
64*ed093b41SRobert Mustacchi err(EXIT_FAILURE, "failed to allocate header");
65*ed093b41SRobert Mustacchi }
66*ed093b41SRobert Mustacchi
67*ed093b41SRobert Mustacchi hdr->pr_type = PR_TYPE_XSAVE;
68*ed093b41SRobert Mustacchi hdr->pr_size = sizeof (prxregset_hdr_t);
69*ed093b41SRobert Mustacchi
70*ed093b41SRobert Mustacchi *bufp = hdr;
71*ed093b41SRobert Mustacchi *sizep = sizeof (prxregset_hdr_t) - 4;
72*ed093b41SRobert Mustacchi }
73*ed093b41SRobert Mustacchi
74*ed093b41SRobert Mustacchi static void
bad_xregs_hdr_too_large(void ** bufp,size_t * sizep)75*ed093b41SRobert Mustacchi bad_xregs_hdr_too_large(void **bufp, size_t *sizep)
76*ed093b41SRobert Mustacchi {
77*ed093b41SRobert Mustacchi uint32_t large = 32 * 1024 * 1024; /* 4 MiB */
78*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = malloc(32 * 1024 * 1024);
79*ed093b41SRobert Mustacchi if (hdr == NULL) {
80*ed093b41SRobert Mustacchi err(EXIT_FAILURE, "failed to allocate regset");
81*ed093b41SRobert Mustacchi }
82*ed093b41SRobert Mustacchi
83*ed093b41SRobert Mustacchi (void) memcpy(hdr, bad_xregs_pxr, bad_xregs_size);
84*ed093b41SRobert Mustacchi hdr->pr_size = large;
85*ed093b41SRobert Mustacchi
86*ed093b41SRobert Mustacchi *bufp = hdr;
87*ed093b41SRobert Mustacchi *sizep = large;
88*ed093b41SRobert Mustacchi }
89*ed093b41SRobert Mustacchi
90*ed093b41SRobert Mustacchi static prxregset_hdr_t *
bad_xregs_std_init(void ** bufp,size_t * sizep)91*ed093b41SRobert Mustacchi bad_xregs_std_init(void **bufp, size_t *sizep)
92*ed093b41SRobert Mustacchi {
93*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = malloc(bad_xregs_size);
94*ed093b41SRobert Mustacchi if (hdr == NULL) {
95*ed093b41SRobert Mustacchi err(EXIT_FAILURE, "failed to allocate regset");
96*ed093b41SRobert Mustacchi }
97*ed093b41SRobert Mustacchi
98*ed093b41SRobert Mustacchi (void) memcpy(hdr, bad_xregs_pxr, bad_xregs_size);
99*ed093b41SRobert Mustacchi
100*ed093b41SRobert Mustacchi *bufp = hdr;
101*ed093b41SRobert Mustacchi *sizep = bad_xregs_size;
102*ed093b41SRobert Mustacchi return (hdr);
103*ed093b41SRobert Mustacchi }
104*ed093b41SRobert Mustacchi
105*ed093b41SRobert Mustacchi static void
bad_xregs_missing_data(void ** bufp,size_t * sizep)106*ed093b41SRobert Mustacchi bad_xregs_missing_data(void **bufp, size_t *sizep)
107*ed093b41SRobert Mustacchi {
108*ed093b41SRobert Mustacchi (void) bad_xregs_std_init(bufp, sizep);
109*ed093b41SRobert Mustacchi *sizep /= 2;
110*ed093b41SRobert Mustacchi }
111*ed093b41SRobert Mustacchi
112*ed093b41SRobert Mustacchi static void
bad_xregs_hdr_bad_type(void ** bufp,size_t * sizep)113*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_type(void **bufp, size_t *sizep)
114*ed093b41SRobert Mustacchi {
115*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
116*ed093b41SRobert Mustacchi hdr->pr_type = PR_TYPE_XSAVE + 167;
117*ed093b41SRobert Mustacchi }
118*ed093b41SRobert Mustacchi
119*ed093b41SRobert Mustacchi static void
bad_xregs_hdr_bad_flags(void ** bufp,size_t * sizep)120*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_flags(void **bufp, size_t *sizep)
121*ed093b41SRobert Mustacchi {
122*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
123*ed093b41SRobert Mustacchi hdr->pr_flags = 0x123;
124*ed093b41SRobert Mustacchi }
125*ed093b41SRobert Mustacchi
126*ed093b41SRobert Mustacchi static void
bad_xregs_hdr_bad_pad0(void ** bufp,size_t * sizep)127*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_pad0(void **bufp, size_t *sizep)
128*ed093b41SRobert Mustacchi {
129*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
130*ed093b41SRobert Mustacchi hdr->pr_pad[0] = 0x456;
131*ed093b41SRobert Mustacchi }
132*ed093b41SRobert Mustacchi
133*ed093b41SRobert Mustacchi static void
bad_xregs_hdr_bad_pad1(void ** bufp,size_t * sizep)134*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_pad1(void **bufp, size_t *sizep)
135*ed093b41SRobert Mustacchi {
136*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
137*ed093b41SRobert Mustacchi hdr->pr_pad[1] = 0x789;
138*ed093b41SRobert Mustacchi }
139*ed093b41SRobert Mustacchi
140*ed093b41SRobert Mustacchi static void
bad_xregs_hdr_bad_pad2(void ** bufp,size_t * sizep)141*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_pad2(void **bufp, size_t *sizep)
142*ed093b41SRobert Mustacchi {
143*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
144*ed093b41SRobert Mustacchi hdr->pr_pad[2] = 0xabc;
145*ed093b41SRobert Mustacchi }
146*ed093b41SRobert Mustacchi
147*ed093b41SRobert Mustacchi static void
bad_xregs_hdr_bad_pad3(void ** bufp,size_t * sizep)148*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_pad3(void **bufp, size_t *sizep)
149*ed093b41SRobert Mustacchi {
150*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
151*ed093b41SRobert Mustacchi hdr->pr_pad[3] = 0xdef;
152*ed093b41SRobert Mustacchi }
153*ed093b41SRobert Mustacchi
154*ed093b41SRobert Mustacchi static void
bad_xregs_hdr_no_info(void ** bufp,size_t * sizep)155*ed093b41SRobert Mustacchi bad_xregs_hdr_no_info(void **bufp, size_t *sizep)
156*ed093b41SRobert Mustacchi {
157*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
158*ed093b41SRobert Mustacchi hdr->pr_ninfo = 0;
159*ed093b41SRobert Mustacchi }
160*ed093b41SRobert Mustacchi
161*ed093b41SRobert Mustacchi static void
bad_xregs_hdr_no_info_len(void ** bufp,size_t * sizep)162*ed093b41SRobert Mustacchi bad_xregs_hdr_no_info_len(void **bufp, size_t *sizep)
163*ed093b41SRobert Mustacchi {
164*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
165*ed093b41SRobert Mustacchi uint32_t len = sizeof (prxregset_hdr_t) + sizeof (prxregset_info_t) *
166*ed093b41SRobert Mustacchi hdr->pr_ninfo;
167*ed093b41SRobert Mustacchi hdr->pr_size = len - 4;
168*ed093b41SRobert Mustacchi }
169*ed093b41SRobert Mustacchi
170*ed093b41SRobert Mustacchi static void
bad_xregs_info_type(void ** bufp,size_t * sizep)171*ed093b41SRobert Mustacchi bad_xregs_info_type(void **bufp, size_t *sizep)
172*ed093b41SRobert Mustacchi {
173*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
174*ed093b41SRobert Mustacchi hdr->pr_info[0].pri_type = 0xbaddcafe;
175*ed093b41SRobert Mustacchi }
176*ed093b41SRobert Mustacchi
177*ed093b41SRobert Mustacchi static void
bad_xregs_info_flags(void ** bufp,size_t * sizep)178*ed093b41SRobert Mustacchi bad_xregs_info_flags(void **bufp, size_t *sizep)
179*ed093b41SRobert Mustacchi {
180*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
181*ed093b41SRobert Mustacchi VERIFY3U(hdr->pr_ninfo, >=, 2);
182*ed093b41SRobert Mustacchi hdr->pr_info[1].pri_flags = 0x120b0;
183*ed093b41SRobert Mustacchi }
184*ed093b41SRobert Mustacchi
185*ed093b41SRobert Mustacchi static prxregset_info_t *
bad_xregs_find_info(prxregset_hdr_t * hdr,uint32_t type)186*ed093b41SRobert Mustacchi bad_xregs_find_info(prxregset_hdr_t *hdr, uint32_t type)
187*ed093b41SRobert Mustacchi {
188*ed093b41SRobert Mustacchi for (uint32_t i = 0; i < hdr->pr_ninfo; i++) {
189*ed093b41SRobert Mustacchi if (hdr->pr_info[i].pri_type == type) {
190*ed093b41SRobert Mustacchi return (&hdr->pr_info[i]);
191*ed093b41SRobert Mustacchi }
192*ed093b41SRobert Mustacchi }
193*ed093b41SRobert Mustacchi
194*ed093b41SRobert Mustacchi return (NULL);
195*ed093b41SRobert Mustacchi }
196*ed093b41SRobert Mustacchi
197*ed093b41SRobert Mustacchi static void
bad_xregs_info_xcr_len(void ** bufp,size_t * sizep)198*ed093b41SRobert Mustacchi bad_xregs_info_xcr_len(void **bufp, size_t *sizep)
199*ed093b41SRobert Mustacchi {
200*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
201*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XCR);
202*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
203*ed093b41SRobert Mustacchi info->pri_size--;
204*ed093b41SRobert Mustacchi }
205*ed093b41SRobert Mustacchi
206*ed093b41SRobert Mustacchi static void
bad_xregs_info_xcr_off(void ** bufp,size_t * sizep)207*ed093b41SRobert Mustacchi bad_xregs_info_xcr_off(void **bufp, size_t *sizep)
208*ed093b41SRobert Mustacchi {
209*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
210*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XCR);
211*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
212*ed093b41SRobert Mustacchi info->pri_offset++;
213*ed093b41SRobert Mustacchi }
214*ed093b41SRobert Mustacchi
215*ed093b41SRobert Mustacchi static void
bad_xregs_info_xsave_len(void ** bufp,size_t * sizep)216*ed093b41SRobert Mustacchi bad_xregs_info_xsave_len(void **bufp, size_t *sizep)
217*ed093b41SRobert Mustacchi {
218*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
219*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
220*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
221*ed093b41SRobert Mustacchi info->pri_size--;
222*ed093b41SRobert Mustacchi }
223*ed093b41SRobert Mustacchi
224*ed093b41SRobert Mustacchi static void
bad_xregs_info_xsave_off(void ** bufp,size_t * sizep)225*ed093b41SRobert Mustacchi bad_xregs_info_xsave_off(void **bufp, size_t *sizep)
226*ed093b41SRobert Mustacchi {
227*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
228*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
229*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
230*ed093b41SRobert Mustacchi info->pri_offset--;
231*ed093b41SRobert Mustacchi }
232*ed093b41SRobert Mustacchi
233*ed093b41SRobert Mustacchi static void
bad_xregs_info_ymm_len(void ** bufp,size_t * sizep)234*ed093b41SRobert Mustacchi bad_xregs_info_ymm_len(void **bufp, size_t *sizep)
235*ed093b41SRobert Mustacchi {
236*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
237*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_YMM);
238*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
239*ed093b41SRobert Mustacchi info->pri_size--;
240*ed093b41SRobert Mustacchi }
241*ed093b41SRobert Mustacchi
242*ed093b41SRobert Mustacchi static void
bad_xregs_info_ymm_off(void ** bufp,size_t * sizep)243*ed093b41SRobert Mustacchi bad_xregs_info_ymm_off(void **bufp, size_t *sizep)
244*ed093b41SRobert Mustacchi {
245*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
246*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_YMM);
247*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
248*ed093b41SRobert Mustacchi info->pri_offset--;
249*ed093b41SRobert Mustacchi }
250*ed093b41SRobert Mustacchi
251*ed093b41SRobert Mustacchi static void
bad_xregs_info_opmask_len(void ** bufp,size_t * sizep)252*ed093b41SRobert Mustacchi bad_xregs_info_opmask_len(void **bufp, size_t *sizep)
253*ed093b41SRobert Mustacchi {
254*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
255*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_OPMASK);
256*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
257*ed093b41SRobert Mustacchi info->pri_size--;
258*ed093b41SRobert Mustacchi }
259*ed093b41SRobert Mustacchi
260*ed093b41SRobert Mustacchi static void
bad_xregs_info_opmask_off(void ** bufp,size_t * sizep)261*ed093b41SRobert Mustacchi bad_xregs_info_opmask_off(void **bufp, size_t *sizep)
262*ed093b41SRobert Mustacchi {
263*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
264*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_OPMASK);
265*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
266*ed093b41SRobert Mustacchi info->pri_offset--;
267*ed093b41SRobert Mustacchi }
268*ed093b41SRobert Mustacchi
269*ed093b41SRobert Mustacchi static void
bad_xregs_info_zmm_len(void ** bufp,size_t * sizep)270*ed093b41SRobert Mustacchi bad_xregs_info_zmm_len(void **bufp, size_t *sizep)
271*ed093b41SRobert Mustacchi {
272*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
273*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_ZMM);
274*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
275*ed093b41SRobert Mustacchi info->pri_size--;
276*ed093b41SRobert Mustacchi }
277*ed093b41SRobert Mustacchi
278*ed093b41SRobert Mustacchi static void
bad_xregs_info_zmm_off(void ** bufp,size_t * sizep)279*ed093b41SRobert Mustacchi bad_xregs_info_zmm_off(void **bufp, size_t *sizep)
280*ed093b41SRobert Mustacchi {
281*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
282*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_ZMM);
283*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
284*ed093b41SRobert Mustacchi info->pri_offset--;
285*ed093b41SRobert Mustacchi }
286*ed093b41SRobert Mustacchi
287*ed093b41SRobert Mustacchi static void
bad_xregs_info_hi_zmm_len(void ** bufp,size_t * sizep)288*ed093b41SRobert Mustacchi bad_xregs_info_hi_zmm_len(void **bufp, size_t *sizep)
289*ed093b41SRobert Mustacchi {
290*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
291*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_HI_ZMM);
292*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
293*ed093b41SRobert Mustacchi info->pri_size--;
294*ed093b41SRobert Mustacchi }
295*ed093b41SRobert Mustacchi
296*ed093b41SRobert Mustacchi static void
bad_xregs_info_hi_zmm_off(void ** bufp,size_t * sizep)297*ed093b41SRobert Mustacchi bad_xregs_info_hi_zmm_off(void **bufp, size_t *sizep)
298*ed093b41SRobert Mustacchi {
299*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
300*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_HI_ZMM);
301*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
302*ed093b41SRobert Mustacchi info->pri_offset--;
303*ed093b41SRobert Mustacchi }
304*ed093b41SRobert Mustacchi
305*ed093b41SRobert Mustacchi static void
bad_xregs_info_exceeds_len0(void ** bufp,size_t * sizep)306*ed093b41SRobert Mustacchi bad_xregs_info_exceeds_len0(void **bufp, size_t *sizep)
307*ed093b41SRobert Mustacchi {
308*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
309*ed093b41SRobert Mustacchi hdr->pr_info[0].pri_offset = hdr->pr_size + 4;
310*ed093b41SRobert Mustacchi }
311*ed093b41SRobert Mustacchi
312*ed093b41SRobert Mustacchi static void
bad_xregs_info_exceeds_len1(void ** bufp,size_t * sizep)313*ed093b41SRobert Mustacchi bad_xregs_info_exceeds_len1(void **bufp, size_t *sizep)
314*ed093b41SRobert Mustacchi {
315*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
316*ed093b41SRobert Mustacchi hdr->pr_info[0].pri_offset = hdr->pr_size - hdr->pr_info[0].pri_size +
317*ed093b41SRobert Mustacchi 8;
318*ed093b41SRobert Mustacchi }
319*ed093b41SRobert Mustacchi
320*ed093b41SRobert Mustacchi static void
bad_xregs_info_overlaps(void ** bufp,size_t * sizep)321*ed093b41SRobert Mustacchi bad_xregs_info_overlaps(void **bufp, size_t *sizep)
322*ed093b41SRobert Mustacchi {
323*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
324*ed093b41SRobert Mustacchi hdr->pr_info[0].pri_offset = sizeof (prxregset_hdr_t) + 8;
325*ed093b41SRobert Mustacchi }
326*ed093b41SRobert Mustacchi
327*ed093b41SRobert Mustacchi static void
bad_xregs_trim_entry(prxregset_hdr_t * hdr,uint32_t type)328*ed093b41SRobert Mustacchi bad_xregs_trim_entry(prxregset_hdr_t *hdr, uint32_t type)
329*ed093b41SRobert Mustacchi {
330*ed093b41SRobert Mustacchi boolean_t found = B_FALSE;
331*ed093b41SRobert Mustacchi /*
332*ed093b41SRobert Mustacchi * Walk the info structures and clip out everything after the xsave
333*ed093b41SRobert Mustacchi * entry. This almost suggets it'd be nice to have a nop type that was
334*ed093b41SRobert Mustacchi * ignored.
335*ed093b41SRobert Mustacchi */
336*ed093b41SRobert Mustacchi for (uint32_t i = 0; i < hdr->pr_ninfo; i++) {
337*ed093b41SRobert Mustacchi if (hdr->pr_info[i].pri_type == type) {
338*ed093b41SRobert Mustacchi found = B_TRUE;
339*ed093b41SRobert Mustacchi }
340*ed093b41SRobert Mustacchi
341*ed093b41SRobert Mustacchi if (found && i + 1 != hdr->pr_ninfo) {
342*ed093b41SRobert Mustacchi hdr->pr_info[i] = hdr->pr_info[i + 1];
343*ed093b41SRobert Mustacchi }
344*ed093b41SRobert Mustacchi }
345*ed093b41SRobert Mustacchi
346*ed093b41SRobert Mustacchi VERIFY3U(found, ==, B_TRUE);
347*ed093b41SRobert Mustacchi hdr->pr_ninfo--;
348*ed093b41SRobert Mustacchi }
349*ed093b41SRobert Mustacchi
350*ed093b41SRobert Mustacchi static void
bad_xregs_no_xsave(void ** bufp,size_t * sizep)351*ed093b41SRobert Mustacchi bad_xregs_no_xsave(void **bufp, size_t *sizep)
352*ed093b41SRobert Mustacchi {
353*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
354*ed093b41SRobert Mustacchi bad_xregs_trim_entry(hdr, PRX_INFO_XSAVE);
355*ed093b41SRobert Mustacchi }
356*ed093b41SRobert Mustacchi
357*ed093b41SRobert Mustacchi static void
bad_xregs_missing_xstate(void ** bufp,size_t * sizep)358*ed093b41SRobert Mustacchi bad_xregs_missing_xstate(void **bufp, size_t *sizep)
359*ed093b41SRobert Mustacchi {
360*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
361*ed093b41SRobert Mustacchi bad_xregs_trim_entry(hdr, PRX_INFO_YMM);
362*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
363*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
364*ed093b41SRobert Mustacchi prxregset_xsave_t *xsave = (void *)((uintptr_t)*bufp +
365*ed093b41SRobert Mustacchi info->pri_offset);
366*ed093b41SRobert Mustacchi
367*ed093b41SRobert Mustacchi xsave->prx_xsh_xstate_bv |= XFEATURE_AVX;
368*ed093b41SRobert Mustacchi }
369*ed093b41SRobert Mustacchi
370*ed093b41SRobert Mustacchi static void
bad_xregs_xcr_bad_xcr0(void ** bufp,size_t * sizep)371*ed093b41SRobert Mustacchi bad_xregs_xcr_bad_xcr0(void **bufp, size_t *sizep)
372*ed093b41SRobert Mustacchi {
373*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
374*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XCR);
375*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
376*ed093b41SRobert Mustacchi prxregset_xcr_t *xcr = (void *)((uintptr_t)*bufp + info->pri_offset);
377*ed093b41SRobert Mustacchi xcr->prx_xcr_xcr0 = ~xcr->prx_xcr_xcr0;
378*ed093b41SRobert Mustacchi }
379*ed093b41SRobert Mustacchi
380*ed093b41SRobert Mustacchi static void
bad_xregs_xcr_bad_xfd(void ** bufp,size_t * sizep)381*ed093b41SRobert Mustacchi bad_xregs_xcr_bad_xfd(void **bufp, size_t *sizep)
382*ed093b41SRobert Mustacchi {
383*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
384*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XCR);
385*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
386*ed093b41SRobert Mustacchi prxregset_xcr_t *xcr = (void *)((uintptr_t)*bufp + info->pri_offset);
387*ed093b41SRobert Mustacchi xcr->prx_xcr_xfd = ~xcr->prx_xcr_xfd;
388*ed093b41SRobert Mustacchi }
389*ed093b41SRobert Mustacchi
390*ed093b41SRobert Mustacchi static void
bad_xregs_xcr_bad_pad0(void ** bufp,size_t * sizep)391*ed093b41SRobert Mustacchi bad_xregs_xcr_bad_pad0(void **bufp, size_t *sizep)
392*ed093b41SRobert Mustacchi {
393*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
394*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XCR);
395*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
396*ed093b41SRobert Mustacchi prxregset_xcr_t *xcr = (void *)((uintptr_t)*bufp + info->pri_offset);
397*ed093b41SRobert Mustacchi xcr->prx_xcr_pad[0] = 0xdeadbeef;
398*ed093b41SRobert Mustacchi }
399*ed093b41SRobert Mustacchi
400*ed093b41SRobert Mustacchi static void
bad_xregs_xcr_bad_pad1(void ** bufp,size_t * sizep)401*ed093b41SRobert Mustacchi bad_xregs_xcr_bad_pad1(void **bufp, size_t *sizep)
402*ed093b41SRobert Mustacchi {
403*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
404*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XCR);
405*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
406*ed093b41SRobert Mustacchi prxregset_xcr_t *xcr = (void *)((uintptr_t)*bufp + info->pri_offset);
407*ed093b41SRobert Mustacchi xcr->prx_xcr_pad[1] = 0xf00b412;
408*ed093b41SRobert Mustacchi }
409*ed093b41SRobert Mustacchi
410*ed093b41SRobert Mustacchi static void
bad_xregs_xsave_bad_xbv(void ** bufp,size_t * sizep)411*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_xbv(void **bufp, size_t *sizep)
412*ed093b41SRobert Mustacchi {
413*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
414*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
415*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
416*ed093b41SRobert Mustacchi prxregset_xsave_t *xsave = (void *)((uintptr_t)*bufp +
417*ed093b41SRobert Mustacchi info->pri_offset);
418*ed093b41SRobert Mustacchi /*
419*ed093b41SRobert Mustacchi * bit 8 is a supervisor state that we don't currently have defined in
420*ed093b41SRobert Mustacchi * <sys/x86_archext.h> and should always end up being something we don't
421*ed093b41SRobert Mustacchi * see in userland.
422*ed093b41SRobert Mustacchi */
423*ed093b41SRobert Mustacchi xsave->prx_xsh_xstate_bv |= (1 << 8);
424*ed093b41SRobert Mustacchi }
425*ed093b41SRobert Mustacchi
426*ed093b41SRobert Mustacchi static void
bad_xregs_xsave_bad_xcomp(void ** bufp,size_t * sizep)427*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_xcomp(void **bufp, size_t *sizep)
428*ed093b41SRobert Mustacchi {
429*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
430*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
431*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
432*ed093b41SRobert Mustacchi prxregset_xsave_t *xsave = (void *)((uintptr_t)*bufp +
433*ed093b41SRobert Mustacchi info->pri_offset);
434*ed093b41SRobert Mustacchi /*
435*ed093b41SRobert Mustacchi * bit 63 is used to say that this is valid. Given that we don't support
436*ed093b41SRobert Mustacchi * it, we just set that bit as the most realistic example of what could
437*ed093b41SRobert Mustacchi * happen.
438*ed093b41SRobert Mustacchi */
439*ed093b41SRobert Mustacchi xsave->prx_xsh_xcomp_bv |= (1ULL << 63);
440*ed093b41SRobert Mustacchi }
441*ed093b41SRobert Mustacchi
442*ed093b41SRobert Mustacchi static void
bad_xregs_xsave_bad_rsvd0(void ** bufp,size_t * sizep)443*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd0(void **bufp, size_t *sizep)
444*ed093b41SRobert Mustacchi {
445*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
446*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
447*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
448*ed093b41SRobert Mustacchi prxregset_xsave_t *xsave = (void *)((uintptr_t)*bufp +
449*ed093b41SRobert Mustacchi info->pri_offset);
450*ed093b41SRobert Mustacchi xsave->prx_xsh_reserved[0] = 0xff10;
451*ed093b41SRobert Mustacchi }
452*ed093b41SRobert Mustacchi
453*ed093b41SRobert Mustacchi static void
bad_xregs_xsave_bad_rsvd1(void ** bufp,size_t * sizep)454*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd1(void **bufp, size_t *sizep)
455*ed093b41SRobert Mustacchi {
456*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
457*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
458*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
459*ed093b41SRobert Mustacchi prxregset_xsave_t *xsave = (void *)((uintptr_t)*bufp +
460*ed093b41SRobert Mustacchi info->pri_offset);
461*ed093b41SRobert Mustacchi xsave->prx_xsh_reserved[1] = 0x87654321;
462*ed093b41SRobert Mustacchi }
463*ed093b41SRobert Mustacchi
464*ed093b41SRobert Mustacchi static void
bad_xregs_xsave_bad_rsvd2(void ** bufp,size_t * sizep)465*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd2(void **bufp, size_t *sizep)
466*ed093b41SRobert Mustacchi {
467*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
468*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
469*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
470*ed093b41SRobert Mustacchi prxregset_xsave_t *xsave = (void *)((uintptr_t)*bufp +
471*ed093b41SRobert Mustacchi info->pri_offset);
472*ed093b41SRobert Mustacchi xsave->prx_xsh_reserved[2] = 0x167169;
473*ed093b41SRobert Mustacchi }
474*ed093b41SRobert Mustacchi
475*ed093b41SRobert Mustacchi static void
bad_xregs_xsave_bad_rsvd3(void ** bufp,size_t * sizep)476*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd3(void **bufp, size_t *sizep)
477*ed093b41SRobert Mustacchi {
478*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
479*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
480*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
481*ed093b41SRobert Mustacchi prxregset_xsave_t *xsave = (void *)((uintptr_t)*bufp +
482*ed093b41SRobert Mustacchi info->pri_offset);
483*ed093b41SRobert Mustacchi xsave->prx_xsh_reserved[3] = 0xff7;
484*ed093b41SRobert Mustacchi }
485*ed093b41SRobert Mustacchi
486*ed093b41SRobert Mustacchi static void
bad_xregs_xsave_bad_rsvd4(void ** bufp,size_t * sizep)487*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd4(void **bufp, size_t *sizep)
488*ed093b41SRobert Mustacchi {
489*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
490*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
491*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
492*ed093b41SRobert Mustacchi prxregset_xsave_t *xsave = (void *)((uintptr_t)*bufp +
493*ed093b41SRobert Mustacchi info->pri_offset);
494*ed093b41SRobert Mustacchi xsave->prx_xsh_reserved[4] = 0x00f00;
495*ed093b41SRobert Mustacchi }
496*ed093b41SRobert Mustacchi
497*ed093b41SRobert Mustacchi static void
bad_xregs_xsave_bad_rsvd5(void ** bufp,size_t * sizep)498*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd5(void **bufp, size_t *sizep)
499*ed093b41SRobert Mustacchi {
500*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
501*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_XSAVE);
502*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
503*ed093b41SRobert Mustacchi prxregset_xsave_t *xsave = (void *)((uintptr_t)*bufp +
504*ed093b41SRobert Mustacchi info->pri_offset);
505*ed093b41SRobert Mustacchi xsave->prx_xsh_reserved[5] = 0x2374013;
506*ed093b41SRobert Mustacchi }
507*ed093b41SRobert Mustacchi
508*ed093b41SRobert Mustacchi /*
509*ed093b41SRobert Mustacchi * The following tests are all 32-bit specific.
510*ed093b41SRobert Mustacchi */
511*ed093b41SRobert Mustacchi #ifdef __i386
512*ed093b41SRobert Mustacchi static void
bad_xregs_ymm_ilp32(void ** bufp,size_t * sizep)513*ed093b41SRobert Mustacchi bad_xregs_ymm_ilp32(void **bufp, size_t *sizep)
514*ed093b41SRobert Mustacchi {
515*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
516*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_YMM);
517*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
518*ed093b41SRobert Mustacchi prxregset_ymm_t *ymm = (void *)((uintptr_t)*bufp + info->pri_offset);
519*ed093b41SRobert Mustacchi ymm->prx_rsvd[4]._l[3] = 0x12345;
520*ed093b41SRobert Mustacchi }
521*ed093b41SRobert Mustacchi
522*ed093b41SRobert Mustacchi static void
bad_xregs_zmm_ilp32(void ** bufp,size_t * sizep)523*ed093b41SRobert Mustacchi bad_xregs_zmm_ilp32(void **bufp, size_t *sizep)
524*ed093b41SRobert Mustacchi {
525*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
526*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_ZMM);
527*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
528*ed093b41SRobert Mustacchi prxregset_zmm_t *zmm = (void *)((uintptr_t)*bufp + info->pri_offset);
529*ed093b41SRobert Mustacchi zmm->prx_rsvd[2]._l[5] = 0x23456;
530*ed093b41SRobert Mustacchi }
531*ed093b41SRobert Mustacchi
532*ed093b41SRobert Mustacchi static void
bad_xregs_hi_zmm_ilp32(void ** bufp,size_t * sizep)533*ed093b41SRobert Mustacchi bad_xregs_hi_zmm_ilp32(void **bufp, size_t *sizep)
534*ed093b41SRobert Mustacchi {
535*ed093b41SRobert Mustacchi prxregset_hdr_t *hdr = bad_xregs_std_init(bufp, sizep);
536*ed093b41SRobert Mustacchi prxregset_info_t *info = bad_xregs_find_info(hdr, PRX_INFO_HI_ZMM);
537*ed093b41SRobert Mustacchi VERIFY3P(info, !=, NULL);
538*ed093b41SRobert Mustacchi prxregset_hi_zmm_t *hi_zmm = (void *)((uintptr_t)*bufp +
539*ed093b41SRobert Mustacchi info->pri_offset);
540*ed093b41SRobert Mustacchi hi_zmm->prx_rsvd[1]._l[9] = 0x34567;
541*ed093b41SRobert Mustacchi }
542*ed093b41SRobert Mustacchi #endif /* __i386 */
543*ed093b41SRobert Mustacchi
544*ed093b41SRobert Mustacchi static const bad_xregs_test_t bad_tests[] = {
545*ed093b41SRobert Mustacchi { "no data (NULL buffer)", EINVAL, XSU_YMM, bad_xregs_no_data },
546*ed093b41SRobert Mustacchi { "NULL buffer, non-zero count", EFAULT, XSU_YMM, bad_xregs_null_buf },
547*ed093b41SRobert Mustacchi { "incomplete prxregset_hdr_t", EINVAL, XSU_YMM, bad_xregs_short_hdr },
548*ed093b41SRobert Mustacchi { "prxregset_hdr_t has wrong type", EINVAL, XSU_YMM,
549*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_type },
550*ed093b41SRobert Mustacchi { "prxregset_hdr_t size is too large", EINVAL, XSU_YMM,
551*ed093b41SRobert Mustacchi bad_xregs_hdr_too_large },
552*ed093b41SRobert Mustacchi { "prxregset_hdr_t size bigger than /proc write", EINVAL, XSU_YMM,
553*ed093b41SRobert Mustacchi bad_xregs_missing_data },
554*ed093b41SRobert Mustacchi { "prxregset_hdr_t invalid flags", EINVAL, XSU_YMM,
555*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_flags },
556*ed093b41SRobert Mustacchi { "prxregset_hdr_t invalid pad[0]", EINVAL, XSU_YMM,
557*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_pad0 },
558*ed093b41SRobert Mustacchi { "prxregset_hdr_t invalid pad[1]", EINVAL, XSU_YMM,
559*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_pad1 },
560*ed093b41SRobert Mustacchi { "prxregset_hdr_t invalid pad[2]", EINVAL, XSU_YMM,
561*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_pad2 },
562*ed093b41SRobert Mustacchi { "prxregset_hdr_t invalid pad[3]", EINVAL, XSU_YMM,
563*ed093b41SRobert Mustacchi bad_xregs_hdr_bad_pad3 },
564*ed093b41SRobert Mustacchi { "prxregset_hdr_t no info structures", EINVAL, XSU_YMM,
565*ed093b41SRobert Mustacchi bad_xregs_hdr_no_info },
566*ed093b41SRobert Mustacchi { "prxregset_hdr_t len doesn't cover info structures", EINVAL, XSU_YMM,
567*ed093b41SRobert Mustacchi bad_xregs_hdr_no_info_len },
568*ed093b41SRobert Mustacchi { "prxregset_info_t has bad flags", EINVAL, XSU_YMM,
569*ed093b41SRobert Mustacchi bad_xregs_info_flags },
570*ed093b41SRobert Mustacchi { "prxregset_info_t has bad type", EINVAL, XSU_YMM,
571*ed093b41SRobert Mustacchi bad_xregs_info_type },
572*ed093b41SRobert Mustacchi { "prxregset_info_t has bad len (XCR)", EINVAL, XSU_YMM,
573*ed093b41SRobert Mustacchi bad_xregs_info_xcr_len },
574*ed093b41SRobert Mustacchi { "prxregset_info_t has bad align (XCR)", EINVAL, XSU_YMM,
575*ed093b41SRobert Mustacchi bad_xregs_info_xcr_off },
576*ed093b41SRobert Mustacchi { "prxregset_info_t has bad len (XSAVE)", EINVAL, XSU_YMM,
577*ed093b41SRobert Mustacchi bad_xregs_info_xsave_len },
578*ed093b41SRobert Mustacchi { "prxregset_info_t has bad align (XSAVE)", EINVAL, XSU_YMM,
579*ed093b41SRobert Mustacchi bad_xregs_info_xsave_off },
580*ed093b41SRobert Mustacchi { "prxregset_info_t has bad len (YMM)", EINVAL, XSU_YMM,
581*ed093b41SRobert Mustacchi bad_xregs_info_ymm_len },
582*ed093b41SRobert Mustacchi { "prxregset_info_t has bad align (YMM)", EINVAL, XSU_YMM,
583*ed093b41SRobert Mustacchi bad_xregs_info_ymm_off },
584*ed093b41SRobert Mustacchi { "prxregset_info_t has bad len (OPMASK)", EINVAL, XSU_ZMM,
585*ed093b41SRobert Mustacchi bad_xregs_info_opmask_len },
586*ed093b41SRobert Mustacchi { "prxregset_info_t has bad align (OPMASK)", EINVAL, XSU_ZMM,
587*ed093b41SRobert Mustacchi bad_xregs_info_opmask_off },
588*ed093b41SRobert Mustacchi { "prxregset_info_t has bad len (ZMM)", EINVAL, XSU_ZMM,
589*ed093b41SRobert Mustacchi bad_xregs_info_zmm_len },
590*ed093b41SRobert Mustacchi { "prxregset_info_t has bad align (ZMM)", EINVAL, XSU_ZMM,
591*ed093b41SRobert Mustacchi bad_xregs_info_zmm_off },
592*ed093b41SRobert Mustacchi { "prxregset_info_t has bad len (HI ZMM)", EINVAL, XSU_ZMM,
593*ed093b41SRobert Mustacchi bad_xregs_info_hi_zmm_len },
594*ed093b41SRobert Mustacchi { "prxregset_info_t has bad align (HI ZMM)", EINVAL, XSU_ZMM,
595*ed093b41SRobert Mustacchi bad_xregs_info_hi_zmm_off },
596*ed093b41SRobert Mustacchi { "prxregset_info_t offset exceeds total len (offset beyond len)",
597*ed093b41SRobert Mustacchi EINVAL, XSU_YMM, bad_xregs_info_exceeds_len0 },
598*ed093b41SRobert Mustacchi { "prxregset_info_t offset exceeds total len (size+offset beyond len)",
599*ed093b41SRobert Mustacchi EINVAL, XSU_YMM, bad_xregs_info_exceeds_len1 },
600*ed093b41SRobert Mustacchi { "prxregset_info_t offset overlaps info", EINVAL, XSU_YMM,
601*ed093b41SRobert Mustacchi bad_xregs_info_overlaps },
602*ed093b41SRobert Mustacchi { "prxregset_t missing xsave struct", EINVAL, XSU_YMM,
603*ed093b41SRobert Mustacchi bad_xregs_no_xsave },
604*ed093b41SRobert Mustacchi { "prxregset_t missing xstate bit-vector entry", EINVAL, XSU_YMM,
605*ed093b41SRobert Mustacchi bad_xregs_missing_xstate },
606*ed093b41SRobert Mustacchi { "prxregset_xcr_t modified xcr0", EINVAL, XSU_YMM,
607*ed093b41SRobert Mustacchi bad_xregs_xcr_bad_xcr0 },
608*ed093b41SRobert Mustacchi { "prxregset_xcr_t modified xfd", EINVAL, XSU_YMM,
609*ed093b41SRobert Mustacchi bad_xregs_xcr_bad_xfd },
610*ed093b41SRobert Mustacchi { "prxregset_xcr_t modified pad[0]", EINVAL, XSU_YMM,
611*ed093b41SRobert Mustacchi bad_xregs_xcr_bad_pad0 },
612*ed093b41SRobert Mustacchi { "prxregset_xcr_t modified pad[1]", EINVAL, XSU_YMM,
613*ed093b41SRobert Mustacchi bad_xregs_xcr_bad_pad1 },
614*ed093b41SRobert Mustacchi { "prxregset_xsave_t illegal xbv comp", EINVAL, XSU_YMM,
615*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_xbv },
616*ed093b41SRobert Mustacchi { "prxregset_xsave_t illegal compressed comp", EINVAL, XSU_YMM,
617*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_xcomp },
618*ed093b41SRobert Mustacchi { "prxregset_xsave_t illegal rsvd[0]", EINVAL, XSU_YMM,
619*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd0 },
620*ed093b41SRobert Mustacchi { "prxregset_xsave_t illegal rsvd[1]", EINVAL, XSU_YMM,
621*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd1 },
622*ed093b41SRobert Mustacchi { "prxregset_xsave_t illegal rsvd[2]", EINVAL, XSU_YMM,
623*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd2 },
624*ed093b41SRobert Mustacchi { "prxregset_xsave_t illegal rsvd[3]", EINVAL, XSU_YMM,
625*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd3 },
626*ed093b41SRobert Mustacchi { "prxregset_xsave_t illegal rsvd[4]", EINVAL, XSU_YMM,
627*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd4 },
628*ed093b41SRobert Mustacchi { "prxregset_xsave_t illegal rsvd[5]", EINVAL, XSU_YMM,
629*ed093b41SRobert Mustacchi bad_xregs_xsave_bad_rsvd5 },
630*ed093b41SRobert Mustacchi /*
631*ed093b41SRobert Mustacchi * These next sets of tests are specific to 32-bit binaries as they're not
632*ed093b41SRobert Mustacchi * allowed to access a bunch of the additional registers that exist.
633*ed093b41SRobert Mustacchi */
634*ed093b41SRobert Mustacchi #ifdef __i386
635*ed093b41SRobert Mustacchi { "prxregset_ymm_t has non-zero reserved i386 reg", EINVAL, XSU_YMM,
636*ed093b41SRobert Mustacchi bad_xregs_ymm_ilp32 },
637*ed093b41SRobert Mustacchi { "prxregset_zmm_t has non-zero reserved i386 reg", EINVAL, XSU_ZMM,
638*ed093b41SRobert Mustacchi bad_xregs_zmm_ilp32 },
639*ed093b41SRobert Mustacchi { "prxregset_hi_zmm_t has non-zero reserved i386 reg", EINVAL, XSU_ZMM,
640*ed093b41SRobert Mustacchi bad_xregs_hi_zmm_ilp32 },
641*ed093b41SRobert Mustacchi #endif
642*ed093b41SRobert Mustacchi };
643*ed093b41SRobert Mustacchi
644*ed093b41SRobert Mustacchi int
main(void)645*ed093b41SRobert Mustacchi main(void)
646*ed093b41SRobert Mustacchi {
647*ed093b41SRobert Mustacchi int ret;
648*ed093b41SRobert Mustacchi int estatus = EXIT_SUCCESS;
649*ed093b41SRobert Mustacchi struct ps_prochandle *P;
650*ed093b41SRobert Mustacchi struct ps_lwphandle *L;
651*ed093b41SRobert Mustacchi thread_t targ;
652*ed093b41SRobert Mustacchi uint32_t hwsup;
653*ed093b41SRobert Mustacchi uint32_t nskip = 0;
654*ed093b41SRobert Mustacchi
655*ed093b41SRobert Mustacchi hwsup = xsu_hwsupport();
656*ed093b41SRobert Mustacchi P = Pgrab(getpid(), PGRAB_RDONLY, &ret);
657*ed093b41SRobert Mustacchi if (P == NULL) {
658*ed093b41SRobert Mustacchi errx(EXIT_FAILURE, "failed to grab ourself: %s",
659*ed093b41SRobert Mustacchi Pgrab_error(ret));
660*ed093b41SRobert Mustacchi }
661*ed093b41SRobert Mustacchi
662*ed093b41SRobert Mustacchi ret = thr_create(NULL, 0, xsu_sleeper_thread, NULL, THR_DETACHED,
663*ed093b41SRobert Mustacchi &targ);
664*ed093b41SRobert Mustacchi if (ret != 0) {
665*ed093b41SRobert Mustacchi errc(EXIT_FAILURE, ret, "failed to create sleeper thread");
666*ed093b41SRobert Mustacchi }
667*ed093b41SRobert Mustacchi
668*ed093b41SRobert Mustacchi L = Lgrab(P, targ, &ret);
669*ed093b41SRobert Mustacchi if (L == NULL) {
670*ed093b41SRobert Mustacchi errx(EXIT_FAILURE, "failed to grab our sleeper thread: %s",
671*ed093b41SRobert Mustacchi Lgrab_error(ret));
672*ed093b41SRobert Mustacchi }
673*ed093b41SRobert Mustacchi
674*ed093b41SRobert Mustacchi ret = Lstop(L, 0);
675*ed093b41SRobert Mustacchi if (ret != 0) {
676*ed093b41SRobert Mustacchi err(EXIT_FAILURE, "failed to stop the sleeper thread");
677*ed093b41SRobert Mustacchi }
678*ed093b41SRobert Mustacchi
679*ed093b41SRobert Mustacchi if (Lgetxregs(L, &bad_xregs_pxr, &bad_xregs_size) != 0) {
680*ed093b41SRobert Mustacchi err(EXIT_FAILURE, "failed to get basic xregs");
681*ed093b41SRobert Mustacchi }
682*ed093b41SRobert Mustacchi
683*ed093b41SRobert Mustacchi if (bad_xregs_size < sizeof (prxregset_hdr_t)) {
684*ed093b41SRobert Mustacchi errx(EXIT_FAILURE, "found bad regset size: %zu",
685*ed093b41SRobert Mustacchi bad_xregs_size);
686*ed093b41SRobert Mustacchi }
687*ed093b41SRobert Mustacchi
688*ed093b41SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(bad_tests); i++) {
689*ed093b41SRobert Mustacchi void *buf = NULL;
690*ed093b41SRobert Mustacchi size_t len = 0;
691*ed093b41SRobert Mustacchi
692*ed093b41SRobert Mustacchi if (bad_tests[i].bxt_min > hwsup) {
693*ed093b41SRobert Mustacchi warnx("TEST SKIPPED: %s: requires greater hwsup than "
694*ed093b41SRobert Mustacchi "supported (0x%x)", bad_tests[i].bxt_desc,
695*ed093b41SRobert Mustacchi bad_tests[i].bxt_min);
696*ed093b41SRobert Mustacchi nskip++;
697*ed093b41SRobert Mustacchi continue;
698*ed093b41SRobert Mustacchi }
699*ed093b41SRobert Mustacchi
700*ed093b41SRobert Mustacchi bad_tests[i].bxt_setup(&buf, &len);
701*ed093b41SRobert Mustacchi if (Lsetxregs(L, buf, len) != -1) {
702*ed093b41SRobert Mustacchi warnx("TEST FAILED: %s: Lsetxregs returned 0, not -1!",
703*ed093b41SRobert Mustacchi bad_tests[i].bxt_desc);
704*ed093b41SRobert Mustacchi estatus = EXIT_FAILURE;
705*ed093b41SRobert Mustacchi } else if (errno != bad_tests[i].bxt_errno) {
706*ed093b41SRobert Mustacchi warnx("TEST FAILED: %s: Lsetxregs errno was %d, "
707*ed093b41SRobert Mustacchi "expected %d", bad_tests[i].bxt_desc, errno,
708*ed093b41SRobert Mustacchi bad_tests[i].bxt_errno);
709*ed093b41SRobert Mustacchi estatus = EXIT_FAILURE;
710*ed093b41SRobert Mustacchi } else {
711*ed093b41SRobert Mustacchi (void) printf("TEST PASSED: %s\n",
712*ed093b41SRobert Mustacchi bad_tests[i].bxt_desc);
713*ed093b41SRobert Mustacchi }
714*ed093b41SRobert Mustacchi free(buf);
715*ed093b41SRobert Mustacchi }
716*ed093b41SRobert Mustacchi
717*ed093b41SRobert Mustacchi if (estatus == EXIT_SUCCESS && nskip > 0) {
718*ed093b41SRobert Mustacchi warnx("While tests were successful, %u tests were skipped "
719*ed093b41SRobert Mustacchi "due to missing hardware support", nskip);
720*ed093b41SRobert Mustacchi }
721*ed093b41SRobert Mustacchi
722*ed093b41SRobert Mustacchi exit(estatus);
723*ed093b41SRobert Mustacchi }
724