1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*
2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Check that a fault signal handler gets the expected info
3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <signal.h>
5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdio.h>
6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdlib.h>
7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <fcntl.h>
8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <setjmp.h>
9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <unistd.h>
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstruct test {
12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   void (*test)(void);
13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int sig;
14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int code;
15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov};
16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic const struct test *curr_test;
18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic jmp_buf escape;
20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic int testsig(int sig, int want)
22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (sig != want) {
24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      fprintf(stderr, "  FAIL: expected signal %d, not %d\n", want, sig);
25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return 0;
26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return 1;
28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic int testcode(int code, int want)
31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (code != want) {
33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      fprintf(stderr, "  FAIL: expected si_code==%d, not %d\n", want, code);
34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return 0;
35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return 1;
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void handler(int sig, siginfo_t *si, void *uc)
40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int ok = 1;
42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ok = ok && testsig(sig, curr_test->sig);
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ok = ok && testcode(si->si_code, curr_test->code);
45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (ok)
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      fprintf(stderr, "  PASS\n");
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   siglongjmp(escape, ok + 1);
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void test1(void)
53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   __asm__ volatile("li $t0, 0x80000000\n\t"
55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "move $t1, $t0\n\t"
56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "add $a0, $t0, $t1\n\t"
57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     : : : "t0", "t1", "a0", "cc", "memory");
58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void test2()
61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   __asm__ volatile("li $t0, 0x7fffffff\n\t"
63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "addi $a0, $t0, 0x7fff\n\t"
64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     : : : "t0", "a0", "cc", "memory");
65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void test3(void)
68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   __asm__ volatile("li $t0, 0xffff0000\n\t"
70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "li $t1, 0x7fffffff\n\t"
71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "sub $a0, $t0, $t1\n\t"
72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     : : : "t0", "t1", "a0", "cc", "memory");
73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovint main()
76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int i;
78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   static const int sigs[] = { SIGFPE };
79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   struct sigaction sa;
80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sa.sa_sigaction = handler;
81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sa.sa_flags = SA_SIGINFO;
82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sigfillset(&sa.sa_mask);
83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++)
85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      sigaction(sigs[i], &sa, NULL);
86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const struct test tests[] = {
88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define T(n, sig, code) { test##n, sig, code }
89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      T(1, SIGFPE, FPE_INTOVF),
90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      T(2, SIGFPE, FPE_INTOVF),
91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      T(3, SIGFPE, FPE_INTOVF),
92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#undef T
93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   };
94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) {
96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      curr_test = &tests[i];
97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (sigsetjmp(escape, 1) == 0) {
98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         fprintf(stderr, "Test %d: ", i+1);
99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tests[i].test();
100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         fprintf(stderr, "  FAIL: no fault, or handler returned\n");
101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return 0;
104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
105