1*433d6423SLionel Sambuc /* FPU state corruption test. This used to be able to crash the kernel. */
2*433d6423SLionel Sambuc #include <stdlib.h>
3*433d6423SLionel Sambuc #include <stdio.h>
4*433d6423SLionel Sambuc #include <string.h>
5*433d6423SLionel Sambuc #include <signal.h>
6*433d6423SLionel Sambuc #include <sys/wait.h>
7*433d6423SLionel Sambuc #include <machine/fpu.h>
8*433d6423SLionel Sambuc
9*433d6423SLionel Sambuc int max_error = 1;
10*433d6423SLionel Sambuc #include "common.h"
11*433d6423SLionel Sambuc
12*433d6423SLionel Sambuc
13*433d6423SLionel Sambuc double state = 2.0;
14*433d6423SLionel Sambuc static int count;
15*433d6423SLionel Sambuc
use_fpu(int n)16*433d6423SLionel Sambuc static void use_fpu(int n)
17*433d6423SLionel Sambuc {
18*433d6423SLionel Sambuc state += (double) n * 0.5;
19*433d6423SLionel Sambuc }
20*433d6423SLionel Sambuc
crashed(int sig)21*433d6423SLionel Sambuc static void crashed(int sig)
22*433d6423SLionel Sambuc {
23*433d6423SLionel Sambuc exit(EXIT_SUCCESS);
24*433d6423SLionel Sambuc }
25*433d6423SLionel Sambuc
handler(int sig,int code,struct sigcontext * sc)26*433d6423SLionel Sambuc static void handler(int sig, int code, struct sigcontext *sc)
27*433d6423SLionel Sambuc {
28*433d6423SLionel Sambuc memset(&sc->sc_fpu_state, count, sizeof(sc->sc_fpu_state));
29*433d6423SLionel Sambuc }
30*433d6423SLionel Sambuc
main(void)31*433d6423SLionel Sambuc int main(void)
32*433d6423SLionel Sambuc {
33*433d6423SLionel Sambuc int status;
34*433d6423SLionel Sambuc
35*433d6423SLionel Sambuc start(62);
36*433d6423SLionel Sambuc subtest = 0;
37*433d6423SLionel Sambuc
38*433d6423SLionel Sambuc signal(SIGUSR1, (void (*)(int)) handler);
39*433d6423SLionel Sambuc
40*433d6423SLionel Sambuc /* Initialize the FPU state. This state is inherited, too. */
41*433d6423SLionel Sambuc use_fpu(-1);
42*433d6423SLionel Sambuc
43*433d6423SLionel Sambuc for (count = 0; count <= 255; count++) {
44*433d6423SLionel Sambuc switch (fork()) {
45*433d6423SLionel Sambuc case -1:
46*433d6423SLionel Sambuc e(1);
47*433d6423SLionel Sambuc
48*433d6423SLionel Sambuc break;
49*433d6423SLionel Sambuc
50*433d6423SLionel Sambuc case 0:
51*433d6423SLionel Sambuc signal(SIGFPE, crashed);
52*433d6423SLionel Sambuc
53*433d6423SLionel Sambuc /* Load bad state into the kernel. */
54*433d6423SLionel Sambuc if (kill(getpid(), SIGUSR1)) e(2);
55*433d6423SLionel Sambuc
56*433d6423SLionel Sambuc /* Let the kernel restore the state. */
57*433d6423SLionel Sambuc use_fpu(count);
58*433d6423SLionel Sambuc
59*433d6423SLionel Sambuc exit(EXIT_SUCCESS);
60*433d6423SLionel Sambuc
61*433d6423SLionel Sambuc default:
62*433d6423SLionel Sambuc /* We cannot tell exactly whether what happened is correct or
63*433d6423SLionel Sambuc * not -- certainly not in a platform-independent way. However,
64*433d6423SLionel Sambuc * if the whole system keeps running, that's good enough.
65*433d6423SLionel Sambuc */
66*433d6423SLionel Sambuc (void) wait(&status);
67*433d6423SLionel Sambuc }
68*433d6423SLionel Sambuc }
69*433d6423SLionel Sambuc
70*433d6423SLionel Sambuc if (state <= 1.4 || state >= 1.6) e(3);
71*433d6423SLionel Sambuc
72*433d6423SLionel Sambuc quit();
73*433d6423SLionel Sambuc
74*433d6423SLionel Sambuc return 0;
75*433d6423SLionel Sambuc }
76