1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2009 Cisco Systems, Inc. All Rights Reserved.
4*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2009 FUJITSU LIMITED. All Rights Reserved.
5*49cdfc7eSAndroid Build Coastguard Worker * Author: Liu Bo <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker * Author: Ngie Cooper <[email protected]>
7*49cdfc7eSAndroid Build Coastguard Worker */
8*49cdfc7eSAndroid Build Coastguard Worker
9*49cdfc7eSAndroid Build Coastguard Worker #ifndef LAPI_RT_SIGACTION_H__
10*49cdfc7eSAndroid Build Coastguard Worker #define LAPI_RT_SIGACTION_H__
11*49cdfc7eSAndroid Build Coastguard Worker
12*49cdfc7eSAndroid Build Coastguard Worker #include "ltp_signal.h"
13*49cdfc7eSAndroid Build Coastguard Worker
14*49cdfc7eSAndroid Build Coastguard Worker #define INVAL_SA_PTR ((void *)-1)
15*49cdfc7eSAndroid Build Coastguard Worker
16*49cdfc7eSAndroid Build Coastguard Worker #if defined(__mips__)
17*49cdfc7eSAndroid Build Coastguard Worker struct kernel_sigaction {
18*49cdfc7eSAndroid Build Coastguard Worker unsigned int sa_flags;
19*49cdfc7eSAndroid Build Coastguard Worker void (* k_sa_handler)(int);
20*49cdfc7eSAndroid Build Coastguard Worker sigset_t sa_mask;
21*49cdfc7eSAndroid Build Coastguard Worker };
22*49cdfc7eSAndroid Build Coastguard Worker #else
23*49cdfc7eSAndroid Build Coastguard Worker struct kernel_sigaction {
24*49cdfc7eSAndroid Build Coastguard Worker void (* k_sa_handler)(int);
25*49cdfc7eSAndroid Build Coastguard Worker unsigned long sa_flags;
26*49cdfc7eSAndroid Build Coastguard Worker void (*sa_restorer) (void);
27*49cdfc7eSAndroid Build Coastguard Worker sigset_t sa_mask;
28*49cdfc7eSAndroid Build Coastguard Worker };
29*49cdfc7eSAndroid Build Coastguard Worker #endif
30*49cdfc7eSAndroid Build Coastguard Worker
31*49cdfc7eSAndroid Build Coastguard Worker /* This macro marks if (struct sigaction) has .sa_restorer member */
32*49cdfc7eSAndroid Build Coastguard Worker #if !defined(__ia64__) && !defined(__alpha__) && !defined(__hppa__) && !defined(__mips__)
33*49cdfc7eSAndroid Build Coastguard Worker # define HAVE_SA_RESTORER
34*49cdfc7eSAndroid Build Coastguard Worker #endif
35*49cdfc7eSAndroid Build Coastguard Worker
36*49cdfc7eSAndroid Build Coastguard Worker #ifdef __x86_64__
37*49cdfc7eSAndroid Build Coastguard Worker
38*49cdfc7eSAndroid Build Coastguard Worker /*
39*49cdfc7eSAndroid Build Coastguard Worker * From asm/signal.h -- this value isn't exported anywhere outside of glibc and
40*49cdfc7eSAndroid Build Coastguard Worker * asm/signal.h and is only required for the rt_sig* function family because
41*49cdfc7eSAndroid Build Coastguard Worker * sigaction(2), et all, appends this if necessary to
42*49cdfc7eSAndroid Build Coastguard Worker * (struct sigaction).sa_flags. HEH.
43*49cdfc7eSAndroid Build Coastguard Worker *
44*49cdfc7eSAndroid Build Coastguard Worker * I do #undef though, just in case...
45*49cdfc7eSAndroid Build Coastguard Worker *
46*49cdfc7eSAndroid Build Coastguard Worker * Also, from .../arch/x86/kernel/signal.c:448 for v2.6.30 (something or
47*49cdfc7eSAndroid Build Coastguard Worker * other):
48*49cdfc7eSAndroid Build Coastguard Worker *
49*49cdfc7eSAndroid Build Coastguard Worker * x86-64 should always use SA_RESTORER.
50*49cdfc7eSAndroid Build Coastguard Worker *
51*49cdfc7eSAndroid Build Coastguard Worker * -- thus SA_RESTORER must always be defined along with
52*49cdfc7eSAndroid Build Coastguard Worker * (struct sigaction).sa_restorer for this architecture.
53*49cdfc7eSAndroid Build Coastguard Worker */
54*49cdfc7eSAndroid Build Coastguard Worker #undef SA_RESTORER
55*49cdfc7eSAndroid Build Coastguard Worker #define SA_RESTORER 0x04000000
56*49cdfc7eSAndroid Build Coastguard Worker
57*49cdfc7eSAndroid Build Coastguard Worker void (*restore_rt)(void);
58*49cdfc7eSAndroid Build Coastguard Worker
handler_h(int signal)59*49cdfc7eSAndroid Build Coastguard Worker static void handler_h(int signal)
60*49cdfc7eSAndroid Build Coastguard Worker {
61*49cdfc7eSAndroid Build Coastguard Worker return;
62*49cdfc7eSAndroid Build Coastguard Worker }
63*49cdfc7eSAndroid Build Coastguard Worker
64*49cdfc7eSAndroid Build Coastguard Worker /* Setup an initial signal handler for signal number = sig for x86_64. */
sig_initial(int sig)65*49cdfc7eSAndroid Build Coastguard Worker static inline int sig_initial(int sig)
66*49cdfc7eSAndroid Build Coastguard Worker {
67*49cdfc7eSAndroid Build Coastguard Worker int ret_code = -1;
68*49cdfc7eSAndroid Build Coastguard Worker struct sigaction act, oact;
69*49cdfc7eSAndroid Build Coastguard Worker
70*49cdfc7eSAndroid Build Coastguard Worker act.sa_handler = handler_h;
71*49cdfc7eSAndroid Build Coastguard Worker act.sa_flags = 0;
72*49cdfc7eSAndroid Build Coastguard Worker /* Clear out the signal set. */
73*49cdfc7eSAndroid Build Coastguard Worker if (sigemptyset(&act.sa_mask) < 0) {
74*49cdfc7eSAndroid Build Coastguard Worker /* Add the signal to the mask set. */
75*49cdfc7eSAndroid Build Coastguard Worker } else if (sigaddset(&act.sa_mask, sig) < 0) {
76*49cdfc7eSAndroid Build Coastguard Worker /* Set act.sa_restorer via syscall(2) */
77*49cdfc7eSAndroid Build Coastguard Worker } else if (sigaction(sig, &act, &oact) < 0) {
78*49cdfc7eSAndroid Build Coastguard Worker /* Copy oact.sa_restorer via syscall(2) */
79*49cdfc7eSAndroid Build Coastguard Worker } else if (sigaction(sig, &act, &oact) < 0) {
80*49cdfc7eSAndroid Build Coastguard Worker /* And voila -- we just tricked the kernel into giving us our
81*49cdfc7eSAndroid Build Coastguard Worker * restorer function! */
82*49cdfc7eSAndroid Build Coastguard Worker } else {
83*49cdfc7eSAndroid Build Coastguard Worker restore_rt = oact.sa_restorer;
84*49cdfc7eSAndroid Build Coastguard Worker ret_code = 0;
85*49cdfc7eSAndroid Build Coastguard Worker }
86*49cdfc7eSAndroid Build Coastguard Worker
87*49cdfc7eSAndroid Build Coastguard Worker return ret_code;
88*49cdfc7eSAndroid Build Coastguard Worker }
89*49cdfc7eSAndroid Build Coastguard Worker
90*49cdfc7eSAndroid Build Coastguard Worker #endif /* __x86_64__ */
91*49cdfc7eSAndroid Build Coastguard Worker
92*49cdfc7eSAndroid Build Coastguard Worker #ifdef __sparc__
93*49cdfc7eSAndroid Build Coastguard Worker # if defined __arch64__ || defined __sparcv9
94*49cdfc7eSAndroid Build Coastguard Worker
95*49cdfc7eSAndroid Build Coastguard Worker /*
96*49cdfc7eSAndroid Build Coastguard Worker * Based on glibc/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
97*49cdfc7eSAndroid Build Coastguard Worker */
98*49cdfc7eSAndroid Build Coastguard Worker
99*49cdfc7eSAndroid Build Coastguard Worker extern char *__rt_sig_stub;
100*49cdfc7eSAndroid Build Coastguard Worker
__rt_sigreturn_stub(void)101*49cdfc7eSAndroid Build Coastguard Worker static void __attribute__((used)) __rt_sigreturn_stub(void)
102*49cdfc7eSAndroid Build Coastguard Worker {
103*49cdfc7eSAndroid Build Coastguard Worker __asm__ ("__rt_sig_stub: mov %0, %%g1\n\t"
104*49cdfc7eSAndroid Build Coastguard Worker "ta 0x6d\n\t"
105*49cdfc7eSAndroid Build Coastguard Worker : /* no outputs */
106*49cdfc7eSAndroid Build Coastguard Worker : "i" (__NR_rt_sigreturn));
107*49cdfc7eSAndroid Build Coastguard Worker }
108*49cdfc7eSAndroid Build Coastguard Worker
109*49cdfc7eSAndroid Build Coastguard Worker # else /* sparc32 */
110*49cdfc7eSAndroid Build Coastguard Worker
111*49cdfc7eSAndroid Build Coastguard Worker /*
112*49cdfc7eSAndroid Build Coastguard Worker * Based on glibc/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
113*49cdfc7eSAndroid Build Coastguard Worker */
114*49cdfc7eSAndroid Build Coastguard Worker
115*49cdfc7eSAndroid Build Coastguard Worker extern char *__rt_sig_stub, *__sig_stub;
116*49cdfc7eSAndroid Build Coastguard Worker
__rt_sigreturn_stub(void)117*49cdfc7eSAndroid Build Coastguard Worker static void __attribute__((used)) __rt_sigreturn_stub(void)
118*49cdfc7eSAndroid Build Coastguard Worker {
119*49cdfc7eSAndroid Build Coastguard Worker __asm__ ("__rt_sig_stub: mov %0, %%g1\n\t"
120*49cdfc7eSAndroid Build Coastguard Worker "ta 0x10\n\t"
121*49cdfc7eSAndroid Build Coastguard Worker : /* no outputs */
122*49cdfc7eSAndroid Build Coastguard Worker : "i" (__NR_rt_sigreturn));
123*49cdfc7eSAndroid Build Coastguard Worker }
124*49cdfc7eSAndroid Build Coastguard Worker
__sigreturn_stub(void)125*49cdfc7eSAndroid Build Coastguard Worker static void __attribute__((used)) __sigreturn_stub(void)
126*49cdfc7eSAndroid Build Coastguard Worker {
127*49cdfc7eSAndroid Build Coastguard Worker __asm__ ("__sig_stub: mov %0, %%g1\n\t"
128*49cdfc7eSAndroid Build Coastguard Worker "ta 0x10\n\t"
129*49cdfc7eSAndroid Build Coastguard Worker : /* no outputs */
130*49cdfc7eSAndroid Build Coastguard Worker : "i" (__NR_sigreturn));
131*49cdfc7eSAndroid Build Coastguard Worker }
132*49cdfc7eSAndroid Build Coastguard Worker
133*49cdfc7eSAndroid Build Coastguard Worker # endif
134*49cdfc7eSAndroid Build Coastguard Worker #endif /* __sparc__ */
135*49cdfc7eSAndroid Build Coastguard Worker
136*49cdfc7eSAndroid Build Coastguard Worker #ifdef __arc__
137*49cdfc7eSAndroid Build Coastguard Worker
138*49cdfc7eSAndroid Build Coastguard Worker #undef SA_RESTORER
139*49cdfc7eSAndroid Build Coastguard Worker #define SA_RESTORER 0x04000000
140*49cdfc7eSAndroid Build Coastguard Worker
141*49cdfc7eSAndroid Build Coastguard Worker /*
142*49cdfc7eSAndroid Build Coastguard Worker * based on uClibc/libc/sysdeps/linux/arc/sigaction.c
143*49cdfc7eSAndroid Build Coastguard Worker */
144*49cdfc7eSAndroid Build Coastguard Worker static void
restore_rt(void)145*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((optimize("Os"))) __attribute__((used)) restore_rt(void)
146*49cdfc7eSAndroid Build Coastguard Worker {
147*49cdfc7eSAndroid Build Coastguard Worker __asm__ (
148*49cdfc7eSAndroid Build Coastguard Worker "mov r8, %0 \n\t"
149*49cdfc7eSAndroid Build Coastguard Worker #ifdef __ARCHS__
150*49cdfc7eSAndroid Build Coastguard Worker "trap_s 0 \n\t"
151*49cdfc7eSAndroid Build Coastguard Worker #else
152*49cdfc7eSAndroid Build Coastguard Worker "trap0 \n\t"
153*49cdfc7eSAndroid Build Coastguard Worker #endif
154*49cdfc7eSAndroid Build Coastguard Worker : /* no outputs */
155*49cdfc7eSAndroid Build Coastguard Worker : "i" (__NR_rt_sigreturn)
156*49cdfc7eSAndroid Build Coastguard Worker : "r8");
157*49cdfc7eSAndroid Build Coastguard Worker }
158*49cdfc7eSAndroid Build Coastguard Worker #endif
159*49cdfc7eSAndroid Build Coastguard Worker
160*49cdfc7eSAndroid Build Coastguard Worker /* This is a wrapper for __NR_rt_sigaction syscall.
161*49cdfc7eSAndroid Build Coastguard Worker * act/oact values of INVAL_SA_PTR is used to pass
162*49cdfc7eSAndroid Build Coastguard Worker * an invalid pointer to syscall(__NR_rt_sigaction)
163*49cdfc7eSAndroid Build Coastguard Worker *
164*49cdfc7eSAndroid Build Coastguard Worker * Based on glibc/sysdeps/unix/sysv/linux/{...}/sigaction.c
165*49cdfc7eSAndroid Build Coastguard Worker */
166*49cdfc7eSAndroid Build Coastguard Worker
ltp_rt_sigaction(int signum,const struct sigaction * act,struct sigaction * oact,size_t sigsetsize)167*49cdfc7eSAndroid Build Coastguard Worker static int ltp_rt_sigaction(int signum, const struct sigaction *act,
168*49cdfc7eSAndroid Build Coastguard Worker struct sigaction *oact, size_t sigsetsize)
169*49cdfc7eSAndroid Build Coastguard Worker {
170*49cdfc7eSAndroid Build Coastguard Worker int ret;
171*49cdfc7eSAndroid Build Coastguard Worker struct kernel_sigaction kact, koact;
172*49cdfc7eSAndroid Build Coastguard Worker struct kernel_sigaction *kact_p = NULL;
173*49cdfc7eSAndroid Build Coastguard Worker struct kernel_sigaction *koact_p = NULL;
174*49cdfc7eSAndroid Build Coastguard Worker
175*49cdfc7eSAndroid Build Coastguard Worker if (act == INVAL_SA_PTR) {
176*49cdfc7eSAndroid Build Coastguard Worker kact_p = INVAL_SA_PTR;
177*49cdfc7eSAndroid Build Coastguard Worker } else if (act) {
178*49cdfc7eSAndroid Build Coastguard Worker kact.k_sa_handler = act->sa_handler;
179*49cdfc7eSAndroid Build Coastguard Worker memcpy(&kact.sa_mask, &act->sa_mask, sizeof(sigset_t));
180*49cdfc7eSAndroid Build Coastguard Worker kact.sa_flags = act->sa_flags;
181*49cdfc7eSAndroid Build Coastguard Worker #ifndef __mips__
182*49cdfc7eSAndroid Build Coastguard Worker kact.sa_restorer = NULL;
183*49cdfc7eSAndroid Build Coastguard Worker #endif
184*49cdfc7eSAndroid Build Coastguard Worker kact_p = &kact;
185*49cdfc7eSAndroid Build Coastguard Worker }
186*49cdfc7eSAndroid Build Coastguard Worker
187*49cdfc7eSAndroid Build Coastguard Worker if (oact == INVAL_SA_PTR)
188*49cdfc7eSAndroid Build Coastguard Worker koact_p = INVAL_SA_PTR;
189*49cdfc7eSAndroid Build Coastguard Worker else if (oact)
190*49cdfc7eSAndroid Build Coastguard Worker koact_p = &koact;
191*49cdfc7eSAndroid Build Coastguard Worker
192*49cdfc7eSAndroid Build Coastguard Worker #ifdef __x86_64__
193*49cdfc7eSAndroid Build Coastguard Worker sig_initial(signum);
194*49cdfc7eSAndroid Build Coastguard Worker #endif
195*49cdfc7eSAndroid Build Coastguard Worker
196*49cdfc7eSAndroid Build Coastguard Worker #if defined __x86_64__ || defined __arc__
197*49cdfc7eSAndroid Build Coastguard Worker kact.sa_flags |= SA_RESTORER;
198*49cdfc7eSAndroid Build Coastguard Worker kact.sa_restorer = restore_rt;
199*49cdfc7eSAndroid Build Coastguard Worker #endif
200*49cdfc7eSAndroid Build Coastguard Worker
201*49cdfc7eSAndroid Build Coastguard Worker #ifdef __sparc__
202*49cdfc7eSAndroid Build Coastguard Worker unsigned long stub = 0;
203*49cdfc7eSAndroid Build Coastguard Worker # if defined __arch64__ || defined __sparcv9
204*49cdfc7eSAndroid Build Coastguard Worker stub = ((unsigned long) &__rt_sig_stub) - 8;
205*49cdfc7eSAndroid Build Coastguard Worker # else /* sparc32 */
206*49cdfc7eSAndroid Build Coastguard Worker if ((kact.sa_flags & SA_SIGINFO) != 0)
207*49cdfc7eSAndroid Build Coastguard Worker stub = ((unsigned long) &__rt_sig_stub) - 8;
208*49cdfc7eSAndroid Build Coastguard Worker else
209*49cdfc7eSAndroid Build Coastguard Worker stub = ((unsigned long) &__sig_stub) - 8;
210*49cdfc7eSAndroid Build Coastguard Worker # endif
211*49cdfc7eSAndroid Build Coastguard Worker #endif
212*49cdfc7eSAndroid Build Coastguard Worker
213*49cdfc7eSAndroid Build Coastguard Worker
214*49cdfc7eSAndroid Build Coastguard Worker #ifdef __sparc__
215*49cdfc7eSAndroid Build Coastguard Worker ret = tst_syscall(__NR_rt_sigaction, signum,
216*49cdfc7eSAndroid Build Coastguard Worker kact_p, koact_p,
217*49cdfc7eSAndroid Build Coastguard Worker stub, sigsetsize);
218*49cdfc7eSAndroid Build Coastguard Worker #else
219*49cdfc7eSAndroid Build Coastguard Worker ret = tst_syscall(__NR_rt_sigaction, signum,
220*49cdfc7eSAndroid Build Coastguard Worker kact_p, koact_p,
221*49cdfc7eSAndroid Build Coastguard Worker sigsetsize);
222*49cdfc7eSAndroid Build Coastguard Worker #endif
223*49cdfc7eSAndroid Build Coastguard Worker
224*49cdfc7eSAndroid Build Coastguard Worker if (ret >= 0) {
225*49cdfc7eSAndroid Build Coastguard Worker if (oact && (oact != INVAL_SA_PTR)) {
226*49cdfc7eSAndroid Build Coastguard Worker oact->sa_handler = koact.k_sa_handler;
227*49cdfc7eSAndroid Build Coastguard Worker memcpy(&oact->sa_mask, &koact.sa_mask,
228*49cdfc7eSAndroid Build Coastguard Worker sizeof(sigset_t));
229*49cdfc7eSAndroid Build Coastguard Worker oact->sa_flags = koact.sa_flags;
230*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_SA_RESTORER
231*49cdfc7eSAndroid Build Coastguard Worker oact->sa_restorer = koact.sa_restorer;
232*49cdfc7eSAndroid Build Coastguard Worker #endif
233*49cdfc7eSAndroid Build Coastguard Worker }
234*49cdfc7eSAndroid Build Coastguard Worker }
235*49cdfc7eSAndroid Build Coastguard Worker
236*49cdfc7eSAndroid Build Coastguard Worker return ret;
237*49cdfc7eSAndroid Build Coastguard Worker }
238*49cdfc7eSAndroid Build Coastguard Worker
239*49cdfc7eSAndroid Build Coastguard Worker #endif /* LAPI_RT_SIGACTION_H__ */
240