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