xref: /openbmc/qemu/tests/tcg/s390x/trap.c (revision cb2f4b8750b7e1c954570d19b104d4fdbeb8739a)
1*50e36dd6SJonathan Albrecht /*
2*50e36dd6SJonathan Albrecht  * Copyright 2021 IBM Corp.
3*50e36dd6SJonathan Albrecht  *
4*50e36dd6SJonathan Albrecht  * This work is licensed under the terms of the GNU GPL, version 2 or (at
5*50e36dd6SJonathan Albrecht  * your option) any later version. See the COPYING file in the top-level
6*50e36dd6SJonathan Albrecht  * directory.
7*50e36dd6SJonathan Albrecht  */
8*50e36dd6SJonathan Albrecht 
9*50e36dd6SJonathan Albrecht #include <stdarg.h>
10*50e36dd6SJonathan Albrecht #include <stdint.h>
11*50e36dd6SJonathan Albrecht #include <stdio.h>
12*50e36dd6SJonathan Albrecht #include <stdlib.h>
13*50e36dd6SJonathan Albrecht #include <unistd.h>
14*50e36dd6SJonathan Albrecht #include <errno.h>
15*50e36dd6SJonathan Albrecht #include <string.h>
16*50e36dd6SJonathan Albrecht #include <signal.h>
17*50e36dd6SJonathan Albrecht 
error1(const char * filename,int line,const char * fmt,...)18*50e36dd6SJonathan Albrecht static void error1(const char *filename, int line, const char *fmt, ...)
19*50e36dd6SJonathan Albrecht {
20*50e36dd6SJonathan Albrecht     va_list ap;
21*50e36dd6SJonathan Albrecht     va_start(ap, fmt);
22*50e36dd6SJonathan Albrecht     fprintf(stderr, "%s:%d: ", filename, line);
23*50e36dd6SJonathan Albrecht     vfprintf(stderr, fmt, ap);
24*50e36dd6SJonathan Albrecht     fprintf(stderr, "\n");
25*50e36dd6SJonathan Albrecht     va_end(ap);
26*50e36dd6SJonathan Albrecht     exit(1);
27*50e36dd6SJonathan Albrecht }
28*50e36dd6SJonathan Albrecht 
__chk_error(const char * filename,int line,int ret)29*50e36dd6SJonathan Albrecht static int __chk_error(const char *filename, int line, int ret)
30*50e36dd6SJonathan Albrecht {
31*50e36dd6SJonathan Albrecht     if (ret < 0) {
32*50e36dd6SJonathan Albrecht         error1(filename, line, "%m (ret=%d, errno=%d/%s)",
33*50e36dd6SJonathan Albrecht                ret, errno, strerror(errno));
34*50e36dd6SJonathan Albrecht     }
35*50e36dd6SJonathan Albrecht     return ret;
36*50e36dd6SJonathan Albrecht }
37*50e36dd6SJonathan Albrecht 
38*50e36dd6SJonathan Albrecht #define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__)
39*50e36dd6SJonathan Albrecht 
40*50e36dd6SJonathan Albrecht #define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret))
41*50e36dd6SJonathan Albrecht 
42*50e36dd6SJonathan Albrecht int sigfpe_count;
43*50e36dd6SJonathan Albrecht int sigill_count;
44*50e36dd6SJonathan Albrecht 
sig_handler(int sig,siginfo_t * si,void * puc)45*50e36dd6SJonathan Albrecht static void sig_handler(int sig, siginfo_t *si, void *puc)
46*50e36dd6SJonathan Albrecht {
47*50e36dd6SJonathan Albrecht     if (sig == SIGFPE) {
48*50e36dd6SJonathan Albrecht         if (si->si_code != 0) {
49*50e36dd6SJonathan Albrecht             error("unexpected si_code: 0x%x != 0", si->si_code);
50*50e36dd6SJonathan Albrecht         }
51*50e36dd6SJonathan Albrecht         ++sigfpe_count;
52*50e36dd6SJonathan Albrecht         return;
53*50e36dd6SJonathan Albrecht     }
54*50e36dd6SJonathan Albrecht 
55*50e36dd6SJonathan Albrecht     if (sig == SIGILL) {
56*50e36dd6SJonathan Albrecht         ++sigill_count;
57*50e36dd6SJonathan Albrecht         return;
58*50e36dd6SJonathan Albrecht     }
59*50e36dd6SJonathan Albrecht 
60*50e36dd6SJonathan Albrecht     error("unexpected signal 0x%x\n", sig);
61*50e36dd6SJonathan Albrecht }
62*50e36dd6SJonathan Albrecht 
main(int argc,char ** argv)63*50e36dd6SJonathan Albrecht int main(int argc, char **argv)
64*50e36dd6SJonathan Albrecht {
65*50e36dd6SJonathan Albrecht     sigfpe_count = sigill_count = 0;
66*50e36dd6SJonathan Albrecht 
67*50e36dd6SJonathan Albrecht     struct sigaction act;
68*50e36dd6SJonathan Albrecht 
69*50e36dd6SJonathan Albrecht     /* Set up SIG handler */
70*50e36dd6SJonathan Albrecht     act.sa_sigaction = sig_handler;
71*50e36dd6SJonathan Albrecht     sigemptyset(&act.sa_mask);
72*50e36dd6SJonathan Albrecht     act.sa_flags = SA_SIGINFO;
73*50e36dd6SJonathan Albrecht     chk_error(sigaction(SIGFPE, &act, NULL));
74*50e36dd6SJonathan Albrecht     chk_error(sigaction(SIGILL, &act, NULL));
75*50e36dd6SJonathan Albrecht 
76*50e36dd6SJonathan Albrecht     uint64_t z = 0x0ull;
77*50e36dd6SJonathan Albrecht     uint64_t lz = 0xffffffffffffffffull;
78*50e36dd6SJonathan Albrecht     asm volatile (
79*50e36dd6SJonathan Albrecht         "lg %%r13,%[lz]\n"
80*50e36dd6SJonathan Albrecht         "cgitne %%r13,0\n" /* SIGFPE */
81*50e36dd6SJonathan Albrecht         "lg %%r13,%[z]\n"
82*50e36dd6SJonathan Albrecht         "cgitne %%r13,0\n" /* no trap */
83*50e36dd6SJonathan Albrecht         "nopr\n"
84*50e36dd6SJonathan Albrecht         "lg %%r13,%[lz]\n"
85*50e36dd6SJonathan Albrecht         "citne %%r13,0\n" /* SIGFPE */
86*50e36dd6SJonathan Albrecht         "lg %%r13,%[z]\n"
87*50e36dd6SJonathan Albrecht         "citne %%r13,0\n" /* no trap */
88*50e36dd6SJonathan Albrecht         "nopr\n"
89*50e36dd6SJonathan Albrecht         :
90*50e36dd6SJonathan Albrecht         : [z] "m" (z), [lz] "m" (lz)
91*50e36dd6SJonathan Albrecht         : "memory", "r13");
92*50e36dd6SJonathan Albrecht 
93*50e36dd6SJonathan Albrecht     if (sigfpe_count != 2) {
94*50e36dd6SJonathan Albrecht         error("unexpected SIGFPE count: %d != 2", sigfpe_count);
95*50e36dd6SJonathan Albrecht     }
96*50e36dd6SJonathan Albrecht     if (sigill_count != 0) {
97*50e36dd6SJonathan Albrecht         error("unexpected SIGILL count: %d != 0", sigill_count);
98*50e36dd6SJonathan Albrecht     }
99*50e36dd6SJonathan Albrecht 
100*50e36dd6SJonathan Albrecht     printf("PASS\n");
101*50e36dd6SJonathan Albrecht     return 0;
102*50e36dd6SJonathan Albrecht }
103