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