xref: /illumos-gate/usr/src/test/os-tests/tests/xsave/signal_restore.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 Comptuer Company
14*ed093b41SRobert Mustacchi  */
15*ed093b41SRobert Mustacchi 
16*ed093b41SRobert Mustacchi /*
17*ed093b41SRobert Mustacchi  * Verify that the FPU contents are correctly restored after taking a signal. We
18*ed093b41SRobert Mustacchi  * do this by going through and setting up a signal handler for SIGINFO and then
19*ed093b41SRobert Mustacchi  * we do the following as tightly as possible: overwriting the FPU contents and
20*ed093b41SRobert Mustacchi  * then calling thr_kill(). As part of the regression for #15254, we also
21*ed093b41SRobert Mustacchi  * purposefully go off CPU in the signal handler to try to wreak havoc.
22*ed093b41SRobert Mustacchi  */
23*ed093b41SRobert Mustacchi 
24*ed093b41SRobert Mustacchi #include <err.h>
25*ed093b41SRobert Mustacchi #include <stdlib.h>
26*ed093b41SRobert Mustacchi #include <ucontext.h>
27*ed093b41SRobert Mustacchi #include <limits.h>
28*ed093b41SRobert Mustacchi #include <signal.h>
29*ed093b41SRobert Mustacchi #include <thread.h>
30*ed093b41SRobert Mustacchi #include <string.h>
31*ed093b41SRobert Mustacchi #include <time.h>
32*ed093b41SRobert Mustacchi #include <unistd.h>
33*ed093b41SRobert Mustacchi 
34*ed093b41SRobert Mustacchi #include "xsave_util.h"
35*ed093b41SRobert Mustacchi 
36*ed093b41SRobert Mustacchi static xsu_fpu_t init_vals, signal_vals, found;
37*ed093b41SRobert Mustacchi static volatile int exit_status = EXIT_SUCCESS;
38*ed093b41SRobert Mustacchi static volatile int took_sig = 0;
39*ed093b41SRobert Mustacchi static uint32_t sr_hwsup;
40*ed093b41SRobert Mustacchi 
41*ed093b41SRobert Mustacchi static void
signal_restore_siginfo(int sig,siginfo_t * sip,void * ucp)42*ed093b41SRobert Mustacchi signal_restore_siginfo(int sig, siginfo_t *sip, void *ucp)
43*ed093b41SRobert Mustacchi {
44*ed093b41SRobert Mustacchi 	struct timespec ts;
45*ed093b41SRobert Mustacchi 	took_sig = 1;
46*ed093b41SRobert Mustacchi 
47*ed093b41SRobert Mustacchi 	ts.tv_sec = 0;
48*ed093b41SRobert Mustacchi 	ts.tv_nsec = 10 * MILLISEC;
49*ed093b41SRobert Mustacchi 
50*ed093b41SRobert Mustacchi 	/*
51*ed093b41SRobert Mustacchi 	 * yield doesn't guarantee that we go off CPU, but try a few anyways.
52*ed093b41SRobert Mustacchi 	 * There's a slight chance that nanosleep will modify the FPU state, but
53*ed093b41SRobert Mustacchi 	 * we can hope we're lucky and that the libc function won't.
54*ed093b41SRobert Mustacchi 	 */
55*ed093b41SRobert Mustacchi 	xsu_setfpu(&signal_vals, sr_hwsup);
56*ed093b41SRobert Mustacchi 	yield();
57*ed093b41SRobert Mustacchi 	yield();
58*ed093b41SRobert Mustacchi 	(void) nanosleep(&ts, NULL);
59*ed093b41SRobert Mustacchi 	xsu_getfpu(&found, sr_hwsup);
60*ed093b41SRobert Mustacchi 
61*ed093b41SRobert Mustacchi 	if (xsu_same(&signal_vals, &found, sr_hwsup)) {
62*ed093b41SRobert Mustacchi 		(void) printf("TEST PASSED: FPU contents didn't change in "
63*ed093b41SRobert Mustacchi 		    "signal handler\n");
64*ed093b41SRobert Mustacchi 	} else {
65*ed093b41SRobert Mustacchi 		warnx("TEST FAILED: FPU contents changed in signal handler!");
66*ed093b41SRobert Mustacchi 		exit_status = EXIT_FAILURE;
67*ed093b41SRobert Mustacchi 	}
68*ed093b41SRobert Mustacchi 
69*ed093b41SRobert Mustacchi }
70*ed093b41SRobert Mustacchi 
71*ed093b41SRobert Mustacchi int
main(void)72*ed093b41SRobert Mustacchi main(void)
73*ed093b41SRobert Mustacchi {
74*ed093b41SRobert Mustacchi 	int ret;
75*ed093b41SRobert Mustacchi 	thread_t self = thr_self();
76*ed093b41SRobert Mustacchi 	uint32_t start = arc4random();
77*ed093b41SRobert Mustacchi 	uint32_t hwsup = xsu_hwsupport();
78*ed093b41SRobert Mustacchi 	struct sigaction sa;
79*ed093b41SRobert Mustacchi 
80*ed093b41SRobert Mustacchi 	sr_hwsup = hwsup;
81*ed093b41SRobert Mustacchi 	sa.sa_sigaction = signal_restore_siginfo;
82*ed093b41SRobert Mustacchi 	sa.sa_flags = SA_RESETHAND;
83*ed093b41SRobert Mustacchi 
84*ed093b41SRobert Mustacchi 	if (sigaction(SIGINFO, &sa, NULL) != 0) {
85*ed093b41SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: failed to set up signal "
86*ed093b41SRobert Mustacchi 		    "handler");
87*ed093b41SRobert Mustacchi 	}
88*ed093b41SRobert Mustacchi 
89*ed093b41SRobert Mustacchi 	(void) printf("filling starting at 0x%x\n", start);
90*ed093b41SRobert Mustacchi 	xsu_fill(&init_vals, hwsup, start);
91*ed093b41SRobert Mustacchi 	xsu_fill(&signal_vals, hwsup, start + INT_MAX);
92*ed093b41SRobert Mustacchi 
93*ed093b41SRobert Mustacchi 	(void) memset(&sa, 0, sizeof (struct sigaction));
94*ed093b41SRobert Mustacchi 
95*ed093b41SRobert Mustacchi 	xsu_setfpu(&init_vals, hwsup);
96*ed093b41SRobert Mustacchi 	ret = thr_kill(self, SIGINFO);
97*ed093b41SRobert Mustacchi 	xsu_getfpu(&found, hwsup);
98*ed093b41SRobert Mustacchi 
99*ed093b41SRobert Mustacchi 	if (ret != 0) {
100*ed093b41SRobert Mustacchi 		errc(EXIT_FAILURE, ret, "TEST FAILED: failed to deliver "
101*ed093b41SRobert Mustacchi 		    "signal");
102*ed093b41SRobert Mustacchi 	}
103*ed093b41SRobert Mustacchi 
104*ed093b41SRobert Mustacchi 	if (took_sig == 0) {
105*ed093b41SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: signal handler did not run");
106*ed093b41SRobert Mustacchi 	}
107*ed093b41SRobert Mustacchi 
108*ed093b41SRobert Mustacchi 	(void) printf("TEST PASSED: SIGINFO successfully delivered\n");
109*ed093b41SRobert Mustacchi 
110*ed093b41SRobert Mustacchi 	if (xsu_same(&init_vals, &found, hwsup)) {
111*ed093b41SRobert Mustacchi 		(void) printf("TEST PASSED: FPU contents successfully "
112*ed093b41SRobert Mustacchi 		    "restored\n");
113*ed093b41SRobert Mustacchi 	} else {
114*ed093b41SRobert Mustacchi 		warnx("TEST FAILED: FPU contents were not restored!");
115*ed093b41SRobert Mustacchi 		exit_status = EXIT_FAILURE;
116*ed093b41SRobert Mustacchi 	}
117*ed093b41SRobert Mustacchi 
118*ed093b41SRobert Mustacchi 	return (exit_status);
119*ed093b41SRobert Mustacchi }
120