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