134ff174f3cef6e6058385c0a404572d5e8e5c67cdejanj/*
280e5c17a2a2832793a2d4962fa8264025641e47epetarj   Check that a fault signal handler gets the expected info
380e5c17a2a2832793a2d4962fa8264025641e47epetarj */
480e5c17a2a2832793a2d4962fa8264025641e47epetarj#include <signal.h>
580e5c17a2a2832793a2d4962fa8264025641e47epetarj#include <stdio.h>
680e5c17a2a2832793a2d4962fa8264025641e47epetarj#include <stdlib.h>
780e5c17a2a2832793a2d4962fa8264025641e47epetarj#include <fcntl.h>
880e5c17a2a2832793a2d4962fa8264025641e47epetarj#include <setjmp.h>
980e5c17a2a2832793a2d4962fa8264025641e47epetarj#include <unistd.h>
1080e5c17a2a2832793a2d4962fa8264025641e47epetarj
1180e5c17a2a2832793a2d4962fa8264025641e47epetarjstruct test {
1280e5c17a2a2832793a2d4962fa8264025641e47epetarj   void (*test)(void);
1380e5c17a2a2832793a2d4962fa8264025641e47epetarj   int sig;
1480e5c17a2a2832793a2d4962fa8264025641e47epetarj   int code;
1580e5c17a2a2832793a2d4962fa8264025641e47epetarj};
1680e5c17a2a2832793a2d4962fa8264025641e47epetarj
1780e5c17a2a2832793a2d4962fa8264025641e47epetarjstatic const struct test *curr_test;
1880e5c17a2a2832793a2d4962fa8264025641e47epetarj
1980e5c17a2a2832793a2d4962fa8264025641e47epetarjstatic jmp_buf escape;
2080e5c17a2a2832793a2d4962fa8264025641e47epetarj
2180e5c17a2a2832793a2d4962fa8264025641e47epetarjstatic int testsig(int sig, int want)
2280e5c17a2a2832793a2d4962fa8264025641e47epetarj{
2380e5c17a2a2832793a2d4962fa8264025641e47epetarj   if (sig != want) {
2480e5c17a2a2832793a2d4962fa8264025641e47epetarj      fprintf(stderr, "  FAIL: expected signal %d, not %d\n", want, sig);
2580e5c17a2a2832793a2d4962fa8264025641e47epetarj      return 0;
2680e5c17a2a2832793a2d4962fa8264025641e47epetarj   }
2780e5c17a2a2832793a2d4962fa8264025641e47epetarj   return 1;
2880e5c17a2a2832793a2d4962fa8264025641e47epetarj}
2980e5c17a2a2832793a2d4962fa8264025641e47epetarj
3080e5c17a2a2832793a2d4962fa8264025641e47epetarjstatic int testcode(int code, int want)
3180e5c17a2a2832793a2d4962fa8264025641e47epetarj{
3280e5c17a2a2832793a2d4962fa8264025641e47epetarj   if (code != want) {
3380e5c17a2a2832793a2d4962fa8264025641e47epetarj      fprintf(stderr, "  FAIL: expected si_code==%d, not %d\n", want, code);
3480e5c17a2a2832793a2d4962fa8264025641e47epetarj      return 0;
3580e5c17a2a2832793a2d4962fa8264025641e47epetarj   }
3680e5c17a2a2832793a2d4962fa8264025641e47epetarj   return 1;
3780e5c17a2a2832793a2d4962fa8264025641e47epetarj}
3880e5c17a2a2832793a2d4962fa8264025641e47epetarj
3980e5c17a2a2832793a2d4962fa8264025641e47epetarjstatic void handler(int sig, siginfo_t *si, void *uc)
4080e5c17a2a2832793a2d4962fa8264025641e47epetarj{
4180e5c17a2a2832793a2d4962fa8264025641e47epetarj   int ok = 1;
4280e5c17a2a2832793a2d4962fa8264025641e47epetarj
4380e5c17a2a2832793a2d4962fa8264025641e47epetarj   ok = ok && testsig(sig, curr_test->sig);
4480e5c17a2a2832793a2d4962fa8264025641e47epetarj   ok = ok && testcode(si->si_code, curr_test->code);
4580e5c17a2a2832793a2d4962fa8264025641e47epetarj
4680e5c17a2a2832793a2d4962fa8264025641e47epetarj   if (ok)
4780e5c17a2a2832793a2d4962fa8264025641e47epetarj      fprintf(stderr, "  PASS\n");
4880e5c17a2a2832793a2d4962fa8264025641e47epetarj
4980e5c17a2a2832793a2d4962fa8264025641e47epetarj   siglongjmp(escape, ok + 1);
5080e5c17a2a2832793a2d4962fa8264025641e47epetarj}
5180e5c17a2a2832793a2d4962fa8264025641e47epetarj
5280e5c17a2a2832793a2d4962fa8264025641e47epetarjstatic void test1(void)
5380e5c17a2a2832793a2d4962fa8264025641e47epetarj{
5480e5c17a2a2832793a2d4962fa8264025641e47epetarj   __asm__ volatile("li $t0, 0x80000000\n\t"
5580e5c17a2a2832793a2d4962fa8264025641e47epetarj                    "move $t1, $t0\n\t"
5680e5c17a2a2832793a2d4962fa8264025641e47epetarj                    "add $a0, $t0, $t1\n\t"
5780e5c17a2a2832793a2d4962fa8264025641e47epetarj                     : : : "t0", "t1", "a0", "cc", "memory");
5880e5c17a2a2832793a2d4962fa8264025641e47epetarj}
5980e5c17a2a2832793a2d4962fa8264025641e47epetarj
6080e5c17a2a2832793a2d4962fa8264025641e47epetarjstatic void test2()
6180e5c17a2a2832793a2d4962fa8264025641e47epetarj{
6280e5c17a2a2832793a2d4962fa8264025641e47epetarj   __asm__ volatile("li $t0, 0x7fffffff\n\t"
6380e5c17a2a2832793a2d4962fa8264025641e47epetarj                    "addi $a0, $t0, 0x7fff\n\t"
6480e5c17a2a2832793a2d4962fa8264025641e47epetarj                     : : : "t0", "a0", "cc", "memory");
6580e5c17a2a2832793a2d4962fa8264025641e47epetarj}
6680e5c17a2a2832793a2d4962fa8264025641e47epetarj
6780e5c17a2a2832793a2d4962fa8264025641e47epetarjstatic void test3(void)
6880e5c17a2a2832793a2d4962fa8264025641e47epetarj{
6980e5c17a2a2832793a2d4962fa8264025641e47epetarj   __asm__ volatile("li $t0, 0xffff0000\n\t"
7080e5c17a2a2832793a2d4962fa8264025641e47epetarj                    "li $t1, 0x7fffffff\n\t"
7180e5c17a2a2832793a2d4962fa8264025641e47epetarj                    "sub $a0, $t0, $t1\n\t"
7280e5c17a2a2832793a2d4962fa8264025641e47epetarj                     : : : "t0", "t1", "a0", "cc", "memory");
7380e5c17a2a2832793a2d4962fa8264025641e47epetarj}
7480e5c17a2a2832793a2d4962fa8264025641e47epetarj
7580e5c17a2a2832793a2d4962fa8264025641e47epetarjint main()
7680e5c17a2a2832793a2d4962fa8264025641e47epetarj{
7780e5c17a2a2832793a2d4962fa8264025641e47epetarj   int i;
7880e5c17a2a2832793a2d4962fa8264025641e47epetarj   static const int sigs[] = { SIGFPE };
7980e5c17a2a2832793a2d4962fa8264025641e47epetarj   struct sigaction sa;
8080e5c17a2a2832793a2d4962fa8264025641e47epetarj   sa.sa_sigaction = handler;
8180e5c17a2a2832793a2d4962fa8264025641e47epetarj   sa.sa_flags = SA_SIGINFO;
8280e5c17a2a2832793a2d4962fa8264025641e47epetarj   sigfillset(&sa.sa_mask);
8380e5c17a2a2832793a2d4962fa8264025641e47epetarj
8480e5c17a2a2832793a2d4962fa8264025641e47epetarj   for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++)
8580e5c17a2a2832793a2d4962fa8264025641e47epetarj      sigaction(sigs[i], &sa, NULL);
8680e5c17a2a2832793a2d4962fa8264025641e47epetarj
8780e5c17a2a2832793a2d4962fa8264025641e47epetarj   const struct test tests[] = {
8880e5c17a2a2832793a2d4962fa8264025641e47epetarj#define T(n, sig, code) { test##n, sig, code }
8980e5c17a2a2832793a2d4962fa8264025641e47epetarj      T(1, SIGFPE, FPE_INTOVF),
9080e5c17a2a2832793a2d4962fa8264025641e47epetarj      T(2, SIGFPE, FPE_INTOVF),
9180e5c17a2a2832793a2d4962fa8264025641e47epetarj      T(3, SIGFPE, FPE_INTOVF),
9280e5c17a2a2832793a2d4962fa8264025641e47epetarj#undef T
9380e5c17a2a2832793a2d4962fa8264025641e47epetarj   };
9480e5c17a2a2832793a2d4962fa8264025641e47epetarj
9580e5c17a2a2832793a2d4962fa8264025641e47epetarj   for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) {
9680e5c17a2a2832793a2d4962fa8264025641e47epetarj      curr_test = &tests[i];
9780e5c17a2a2832793a2d4962fa8264025641e47epetarj      if (sigsetjmp(escape, 1) == 0) {
9880e5c17a2a2832793a2d4962fa8264025641e47epetarj         fprintf(stderr, "Test %d: ", i+1);
9980e5c17a2a2832793a2d4962fa8264025641e47epetarj         tests[i].test();
10080e5c17a2a2832793a2d4962fa8264025641e47epetarj         fprintf(stderr, "  FAIL: no fault, or handler returned\n");
10180e5c17a2a2832793a2d4962fa8264025641e47epetarj      }
10280e5c17a2a2832793a2d4962fa8264025641e47epetarj   }
10380e5c17a2a2832793a2d4962fa8264025641e47epetarj   return 0;
10480e5c17a2a2832793a2d4962fa8264025641e47epetarj}
105