xref: /illumos-gate/usr/src/test/os-tests/tests/xsave/fpregs_xbv.c (revision ed093b41a93e8563e6e1e5dae0768dda2a7bcc27)
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  * In illumos#15367 we noted that on some CPUs it was possible to get the xsave
18*ed093b41SRobert Mustacchi  * state into a place where it has not set components that are used for the x87
19*ed093b41SRobert Mustacchi  * and XMM state in the xsave component bit-vector (what we call the
20*ed093b41SRobert Mustacchi  * xsh_xstate_bv or xbv for short). This test attempts to create those
21*ed093b41SRobert Mustacchi  * situations and then get a ucontext_t to see that we actually have cleared it
22*ed093b41SRobert Mustacchi  * out. Because this behavior varies from CPU to CPU (e.g. in the original case
23*ed093b41SRobert Mustacchi  * we only saw this on AMD and not Intel), it can be tricky to guarantee we've
24*ed093b41SRobert Mustacchi  * recreated this.
25*ed093b41SRobert Mustacchi  */
26*ed093b41SRobert Mustacchi 
27*ed093b41SRobert Mustacchi #include <err.h>
28*ed093b41SRobert Mustacchi #include <stdio.h>
29*ed093b41SRobert Mustacchi #include <sys/types.h>
30*ed093b41SRobert Mustacchi #include <ucontext.h>
31*ed093b41SRobert Mustacchi #include <stdlib.h>
32*ed093b41SRobert Mustacchi 
33*ed093b41SRobert Mustacchi int
main(void)34*ed093b41SRobert Mustacchi main(void)
35*ed093b41SRobert Mustacchi {
36*ed093b41SRobert Mustacchi 	ucontext_t ctx;
37*ed093b41SRobert Mustacchi 	upad128_t u, *up;
38*ed093b41SRobert Mustacchi 
39*ed093b41SRobert Mustacchi 	u._l[0] = 0x1;
40*ed093b41SRobert Mustacchi 	u._l[1] = 0x2;
41*ed093b41SRobert Mustacchi 	u._l[2] = 0x3;
42*ed093b41SRobert Mustacchi 	u._l[3] = 0x4;
43*ed093b41SRobert Mustacchi 
44*ed093b41SRobert Mustacchi 	/*
45*ed093b41SRobert Mustacchi 	 * Load %xmm0 and then lock in the data into the pcb with a call to
46*ed093b41SRobert Mustacchi 	 * getcontext(2) which will force an FPU save.
47*ed093b41SRobert Mustacchi 	 */
48*ed093b41SRobert Mustacchi 	/* BEGIN CSTYLED */
49*ed093b41SRobert Mustacchi 	__asm__ __volatile__ ("movdqu %0, %%xmm0" : : "m" (u));
50*ed093b41SRobert Mustacchi 	__asm__ __volatile__ ("fldl %0" : : "m" (u));
51*ed093b41SRobert Mustacchi 	/* END CSTYLED */
52*ed093b41SRobert Mustacchi 	if (getcontext(&ctx) != 0) {
53*ed093b41SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST_FAILED: failed to get initial "
54*ed093b41SRobert Mustacchi 		    "ucontext");
55*ed093b41SRobert Mustacchi 	}
56*ed093b41SRobert Mustacchi 
57*ed093b41SRobert Mustacchi 	/*
58*ed093b41SRobert Mustacchi 	 * Attempt to reset the FPU at this point and then call getcontext. The
59*ed093b41SRobert Mustacchi 	 * fninit is for the x87 part. The vzeroall covers all the higher
60*ed093b41SRobert Mustacchi 	 * registers and this combined should reset the x87 and xmm regions back
61*ed093b41SRobert Mustacchi 	 * to 0. It appears that on some Intel processors, the vzeroall is
62*ed093b41SRobert Mustacchi 	 * required to get the XMM set to not be written out as opposed to just
63*ed093b41SRobert Mustacchi 	 * doing a pxor or similar.
64*ed093b41SRobert Mustacchi 	 */
65*ed093b41SRobert Mustacchi 	/* BEGIN CSTYLED */
66*ed093b41SRobert Mustacchi         __asm__ __volatile__ ("fninit" : : :);
67*ed093b41SRobert Mustacchi         __asm__ __volatile__ ("vzeroall" : : :);
68*ed093b41SRobert Mustacchi 	/* END CSTYLED */
69*ed093b41SRobert Mustacchi 	if (getcontext(&ctx) != 0) {
70*ed093b41SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST_FAILED: failed to get second "
71*ed093b41SRobert Mustacchi 		    "ucontext");
72*ed093b41SRobert Mustacchi 	}
73*ed093b41SRobert Mustacchi 	up = &ctx.uc_mcontext.fpregs.fp_reg_set.fpchip_state.xmm[0];
74*ed093b41SRobert Mustacchi 	if (up->_l[0] != 0 || up->_l[1] != 0 || up->_l[2] != 0 ||
75*ed093b41SRobert Mustacchi 	    up->_l[3] != 0) {
76*ed093b41SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: %%xmm0 was not zero, found: "
77*ed093b41SRobert Mustacchi 		    "0x%x 0x%x 0x%x 0x%x", up->_l[3], up->_l[2],
78*ed093b41SRobert Mustacchi 		    up->_l[1], up->_l[0]);
79*ed093b41SRobert Mustacchi 	}
80*ed093b41SRobert Mustacchi 
81*ed093b41SRobert Mustacchi 	(void) printf("TEST PASSED: successfully got zeored %%xmm0\n");
82*ed093b41SRobert Mustacchi 	return (EXIT_SUCCESS);
83*ed093b41SRobert Mustacchi }
84