blob: 9e8555096a7a503a2a495973e78df8581a4a706b [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
bellard31e31b82003-02-18 22:55:36 +000020#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030021#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000022
bellard3ef693a2003-03-23 20:17:16 +000023#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000024#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000025#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010026#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000027
blueswir1249c4c32008-10-05 11:09:37 +000028static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000029 .ss_sp = 0,
30 .ss_size = 0,
31 .ss_flags = TARGET_SS_DISABLE,
32};
33
pbrook624f7972008-05-31 16:11:38 +000034static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000035
ths5fafdf22007-09-16 21:08:06 +000036static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000037 void *puc);
38
Arnaud Patard3ca05582009-03-30 01:18:20 +020039static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000040 [SIGHUP] = TARGET_SIGHUP,
41 [SIGINT] = TARGET_SIGINT,
42 [SIGQUIT] = TARGET_SIGQUIT,
43 [SIGILL] = TARGET_SIGILL,
44 [SIGTRAP] = TARGET_SIGTRAP,
45 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000046/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000047 [SIGBUS] = TARGET_SIGBUS,
48 [SIGFPE] = TARGET_SIGFPE,
49 [SIGKILL] = TARGET_SIGKILL,
50 [SIGUSR1] = TARGET_SIGUSR1,
51 [SIGSEGV] = TARGET_SIGSEGV,
52 [SIGUSR2] = TARGET_SIGUSR2,
53 [SIGPIPE] = TARGET_SIGPIPE,
54 [SIGALRM] = TARGET_SIGALRM,
55 [SIGTERM] = TARGET_SIGTERM,
56#ifdef SIGSTKFLT
57 [SIGSTKFLT] = TARGET_SIGSTKFLT,
58#endif
59 [SIGCHLD] = TARGET_SIGCHLD,
60 [SIGCONT] = TARGET_SIGCONT,
61 [SIGSTOP] = TARGET_SIGSTOP,
62 [SIGTSTP] = TARGET_SIGTSTP,
63 [SIGTTIN] = TARGET_SIGTTIN,
64 [SIGTTOU] = TARGET_SIGTTOU,
65 [SIGURG] = TARGET_SIGURG,
66 [SIGXCPU] = TARGET_SIGXCPU,
67 [SIGXFSZ] = TARGET_SIGXFSZ,
68 [SIGVTALRM] = TARGET_SIGVTALRM,
69 [SIGPROF] = TARGET_SIGPROF,
70 [SIGWINCH] = TARGET_SIGWINCH,
71 [SIGIO] = TARGET_SIGIO,
72 [SIGPWR] = TARGET_SIGPWR,
73 [SIGSYS] = TARGET_SIGSYS,
74 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000075 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080076 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000077 To fix this properly we need to do manual signal delivery multiplexed
78 over a single host signal. */
79 [__SIGRTMIN] = __SIGRTMAX,
80 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000081};
Arnaud Patard3ca05582009-03-30 01:18:20 +020082static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000083
thsa04e1342007-09-27 13:57:58 +000084static inline int on_sig_stack(unsigned long sp)
85{
86 return (sp - target_sigaltstack_used.ss_sp
87 < target_sigaltstack_used.ss_size);
88}
89
90static inline int sas_ss_flags(unsigned long sp)
91{
92 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
93 : on_sig_stack(sp) ? SS_ONSTACK : 0);
94}
95
pbrook1d9d8b52009-04-16 15:17:02 +000096int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000097{
Andreas Schwab167c50d2013-07-02 14:04:12 +010098 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +000099 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000100 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000101}
102
pbrook4cb05962008-05-30 18:05:19 +0000103int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000104{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100105 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000106 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000107 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000108}
109
Anthony Liguoric227f092009-10-01 16:12:16 -0500110static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000111{
112 memset(set, 0, sizeof(*set));
113}
114
Anthony Liguoric227f092009-10-01 16:12:16 -0500115static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000116{
117 signum--;
118 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
119 set->sig[signum / TARGET_NSIG_BPW] |= mask;
120}
121
Anthony Liguoric227f092009-10-01 16:12:16 -0500122static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000123{
124 signum--;
125 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
126 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
127}
128
Anthony Liguoric227f092009-10-01 16:12:16 -0500129static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000130 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000131{
132 int i;
pbrookf5545b52008-05-30 22:37:07 +0000133 target_sigemptyset(d);
134 for (i = 1; i <= TARGET_NSIG; i++) {
135 if (sigismember(s, i)) {
136 target_sigaddset(d, host_to_target_signal(i));
137 }
bellard9e5f5282003-07-13 17:33:54 +0000138 }
bellard66fb9762003-03-23 01:06:05 +0000139}
140
Anthony Liguoric227f092009-10-01 16:12:16 -0500141void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000142{
Anthony Liguoric227f092009-10-01 16:12:16 -0500143 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000144 int i;
145
146 host_to_target_sigset_internal(&d1, s);
147 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200148 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000149}
150
blueswir18fcd3692008-08-17 20:26:25 +0000151static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500152 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000153{
154 int i;
pbrookf5545b52008-05-30 22:37:07 +0000155 sigemptyset(d);
156 for (i = 1; i <= TARGET_NSIG; i++) {
157 if (target_sigismember(s, i)) {
158 sigaddset(d, target_to_host_signal(i));
159 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100160 }
bellard66fb9762003-03-23 01:06:05 +0000161}
162
Anthony Liguoric227f092009-10-01 16:12:16 -0500163void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000164{
Anthony Liguoric227f092009-10-01 16:12:16 -0500165 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000166 int i;
167
168 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200169 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000170 target_to_host_sigset_internal(d, &s1);
171}
ths3b46e622007-09-17 08:09:54 +0000172
blueswir1992f48a2007-10-14 16:27:31 +0000173void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000174 const sigset_t *sigset)
175{
Anthony Liguoric227f092009-10-01 16:12:16 -0500176 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000177 host_to_target_sigset(&d, sigset);
178 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000179}
180
ths5fafdf22007-09-16 21:08:06 +0000181void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000182 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000183{
Anthony Liguoric227f092009-10-01 16:12:16 -0500184 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000185 int i;
186
187 d.sig[0] = *old_sigset;
188 for(i = 1;i < TARGET_NSIG_WORDS; i++)
189 d.sig[i] = 0;
190 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000191}
192
Alex Barcelo1c275922014-03-14 14:36:55 +0000193/* Wrapper for sigprocmask function
194 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
195 * are host signal set, not guest ones. This wraps the sigprocmask host calls
196 * that should be protected (calls originated from guest)
197 */
198int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
199{
Peter Maydella7ec0f92014-03-14 14:36:56 +0000200 int ret;
201 sigset_t val;
202 sigset_t *temp = NULL;
203 CPUState *cpu = thread_cpu;
204 TaskState *ts = (TaskState *)cpu->opaque;
205 bool segv_was_blocked = ts->sigsegv_blocked;
206
207 if (set) {
208 bool has_sigsegv = sigismember(set, SIGSEGV);
209 val = *set;
210 temp = &val;
211
212 sigdelset(temp, SIGSEGV);
213
214 switch (how) {
215 case SIG_BLOCK:
216 if (has_sigsegv) {
217 ts->sigsegv_blocked = true;
218 }
219 break;
220 case SIG_UNBLOCK:
221 if (has_sigsegv) {
222 ts->sigsegv_blocked = false;
223 }
224 break;
225 case SIG_SETMASK:
226 ts->sigsegv_blocked = has_sigsegv;
227 break;
228 default:
229 g_assert_not_reached();
230 }
231 }
232
233 ret = sigprocmask(how, temp, oldset);
234
235 if (oldset && segv_was_blocked) {
236 sigaddset(oldset, SIGSEGV);
237 }
238
239 return ret;
Alex Barcelo1c275922014-03-14 14:36:55 +0000240}
241
bellard9de5e442003-03-23 16:49:39 +0000242/* siginfo conversion */
243
Anthony Liguoric227f092009-10-01 16:12:16 -0500244static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000245 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000246{
Richard Hendersona05c6402012-09-15 11:34:20 -0700247 int sig = host_to_target_signal(info->si_signo);
bellard9de5e442003-03-23 16:49:39 +0000248 tinfo->si_signo = sig;
249 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000250 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700251
252 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100253 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
Richard Hendersona05c6402012-09-15 11:34:20 -0700254 /* Should never come here, but who knows. The information for
255 the target is irrelevant. */
bellard9de5e442003-03-23 16:49:39 +0000256 tinfo->_sifields._sigfault._addr = 0;
Richard Hendersona05c6402012-09-15 11:34:20 -0700257 } else if (sig == TARGET_SIGIO) {
258 tinfo->_sifields._sigpoll._band = info->si_band;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100259 tinfo->_sifields._sigpoll._fd = info->si_fd;
Richard Hendersona05c6402012-09-15 11:34:20 -0700260 } else if (sig == TARGET_SIGCHLD) {
261 tinfo->_sifields._sigchld._pid = info->si_pid;
262 tinfo->_sifields._sigchld._uid = info->si_uid;
263 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100264 = host_to_target_waitstatus(info->si_status);
Richard Hendersona05c6402012-09-15 11:34:20 -0700265 tinfo->_sifields._sigchld._utime = info->si_utime;
266 tinfo->_sifields._sigchld._stime = info->si_stime;
bellard9de5e442003-03-23 16:49:39 +0000267 } else if (sig >= TARGET_SIGRTMIN) {
268 tinfo->_sifields._rt._pid = info->si_pid;
269 tinfo->_sifields._rt._uid = info->si_uid;
270 /* XXX: potential problem if 64 bit */
Richard Hendersona05c6402012-09-15 11:34:20 -0700271 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100272 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
bellard9de5e442003-03-23 16:49:39 +0000273 }
bellard66fb9762003-03-23 01:06:05 +0000274}
275
Anthony Liguoric227f092009-10-01 16:12:16 -0500276static void tswap_siginfo(target_siginfo_t *tinfo,
277 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000278{
Richard Hendersona05c6402012-09-15 11:34:20 -0700279 int sig = info->si_signo;
bellard9de5e442003-03-23 16:49:39 +0000280 tinfo->si_signo = tswap32(sig);
281 tinfo->si_errno = tswap32(info->si_errno);
282 tinfo->si_code = tswap32(info->si_code);
Richard Hendersona05c6402012-09-15 11:34:20 -0700283
284 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
285 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
286 tinfo->_sifields._sigfault._addr
287 = tswapal(info->_sifields._sigfault._addr);
288 } else if (sig == TARGET_SIGIO) {
289 tinfo->_sifields._sigpoll._band
290 = tswap32(info->_sifields._sigpoll._band);
291 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
292 } else if (sig == TARGET_SIGCHLD) {
293 tinfo->_sifields._sigchld._pid
294 = tswap32(info->_sifields._sigchld._pid);
295 tinfo->_sifields._sigchld._uid
296 = tswap32(info->_sifields._sigchld._uid);
297 tinfo->_sifields._sigchld._status
298 = tswap32(info->_sifields._sigchld._status);
299 tinfo->_sifields._sigchld._utime
300 = tswapal(info->_sifields._sigchld._utime);
301 tinfo->_sifields._sigchld._stime
302 = tswapal(info->_sifields._sigchld._stime);
bellard9de5e442003-03-23 16:49:39 +0000303 } else if (sig >= TARGET_SIGRTMIN) {
304 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
305 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
Richard Hendersona05c6402012-09-15 11:34:20 -0700306 tinfo->_sifields._rt._sigval.sival_ptr
307 = tswapal(info->_sifields._rt._sigval.sival_ptr);
bellard9de5e442003-03-23 16:49:39 +0000308 }
309}
310
311
Anthony Liguoric227f092009-10-01 16:12:16 -0500312void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000313{
314 host_to_target_siginfo_noswap(tinfo, info);
315 tswap_siginfo(tinfo, tinfo);
316}
317
318/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000319/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500320void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000321{
322 info->si_signo = tswap32(tinfo->si_signo);
323 info->si_errno = tswap32(tinfo->si_errno);
324 info->si_code = tswap32(tinfo->si_code);
bellard9de5e442003-03-23 16:49:39 +0000325 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
326 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
ths5fafdf22007-09-16 21:08:06 +0000327 info->si_value.sival_ptr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200328 (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr);
bellard66fb9762003-03-23 01:06:05 +0000329}
330
aurel32ca587a82008-12-18 22:44:13 +0000331static int fatal_signal (int sig)
332{
333 switch (sig) {
334 case TARGET_SIGCHLD:
335 case TARGET_SIGURG:
336 case TARGET_SIGWINCH:
337 /* Ignored by default. */
338 return 0;
339 case TARGET_SIGCONT:
340 case TARGET_SIGSTOP:
341 case TARGET_SIGTSTP:
342 case TARGET_SIGTTIN:
343 case TARGET_SIGTTOU:
344 /* Job control signals. */
345 return 0;
346 default:
347 return 1;
348 }
349}
350
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300351/* returns 1 if given signal should dump core if not handled */
352static int core_dump_signal(int sig)
353{
354 switch (sig) {
355 case TARGET_SIGABRT:
356 case TARGET_SIGFPE:
357 case TARGET_SIGILL:
358 case TARGET_SIGQUIT:
359 case TARGET_SIGSEGV:
360 case TARGET_SIGTRAP:
361 case TARGET_SIGBUS:
362 return (1);
363 default:
364 return (0);
365 }
366}
367
bellard31e31b82003-02-18 22:55:36 +0000368void signal_init(void)
369{
370 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000371 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000372 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000373 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000374
bellard9e5f5282003-07-13 17:33:54 +0000375 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200376 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000377 if (host_to_target_signal_table[i] == 0)
378 host_to_target_signal_table[i] = i;
379 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200380 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000381 j = host_to_target_signal_table[i];
382 target_to_host_signal_table[j] = i;
383 }
ths3b46e622007-09-17 08:09:54 +0000384
bellard9de5e442003-03-23 16:49:39 +0000385 /* set all host signal handlers. ALL signals are blocked during
386 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000387 memset(sigact_table, 0, sizeof(sigact_table));
388
bellard9de5e442003-03-23 16:49:39 +0000389 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000390 act.sa_flags = SA_SIGINFO;
391 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000392 for(i = 1; i <= TARGET_NSIG; i++) {
393 host_sig = target_to_host_signal(i);
394 sigaction(host_sig, NULL, &oact);
395 if (oact.sa_sigaction == (void *)SIG_IGN) {
396 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
397 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
398 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
399 }
400 /* If there's already a handler installed then something has
401 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000402 /* Install some handlers for our own use. We need at least
403 SIGSEGV and SIGBUS, to detect exceptions. We can not just
404 trap all signals because it affects syscall interrupt
405 behavior. But do trap all default-fatal signals. */
406 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000407 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000408 }
bellard31e31b82003-02-18 22:55:36 +0000409}
410
bellard66fb9762003-03-23 01:06:05 +0000411/* signal queue handling */
412
Andreas Färber9349b4f2012-03-14 01:38:32 +0100413static inline struct sigqueue *alloc_sigqueue(CPUArchState *env)
bellard66fb9762003-03-23 01:06:05 +0000414{
Andreas Färber0429a972013-08-26 18:14:44 +0200415 CPUState *cpu = ENV_GET_CPU(env);
416 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000417 struct sigqueue *q = ts->first_free;
bellard66fb9762003-03-23 01:06:05 +0000418 if (!q)
419 return NULL;
pbrook624f7972008-05-31 16:11:38 +0000420 ts->first_free = q->next;
bellard66fb9762003-03-23 01:06:05 +0000421 return q;
422}
423
Andreas Färber9349b4f2012-03-14 01:38:32 +0100424static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
bellard66fb9762003-03-23 01:06:05 +0000425{
Andreas Färber0429a972013-08-26 18:14:44 +0200426 CPUState *cpu = ENV_GET_CPU(env);
427 TaskState *ts = cpu->opaque;
428
pbrook624f7972008-05-31 16:11:38 +0000429 q->next = ts->first_free;
430 ts->first_free = q;
bellard66fb9762003-03-23 01:06:05 +0000431}
432
bellard9de5e442003-03-23 16:49:39 +0000433/* abort execution with signal */
Riku Voipio66393fb2009-12-04 15:16:32 +0200434static void QEMU_NORETURN force_sig(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000435{
Andreas Färber0429a972013-08-26 18:14:44 +0200436 CPUState *cpu = thread_cpu;
437 CPUArchState *env = cpu->env_ptr;
438 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300439 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000440 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100441
Riku Voipio66393fb2009-12-04 15:16:32 +0200442 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100443 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200444 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000445
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300446 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200447 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300448 stop_all_tasks();
449 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200450 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300451 }
452 if (core_dumped) {
453 /* we already dumped the core of target process, we don't want
454 * a coredump of qemu itself */
455 struct rlimit nodump;
456 getrlimit(RLIMIT_CORE, &nodump);
457 nodump.rlim_cur=0;
458 setrlimit(RLIMIT_CORE, &nodump);
459 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200460 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300461 }
462
Stefan Weil0c587512011-04-28 17:20:32 +0200463 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000464 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
465 * a negative value. To get the proper exit code we need to
466 * actually die from an uncaught signal. Here the default signal
467 * handler is installed, we send ourself a signal and we wait for
468 * it to arrive. */
469 sigfillset(&act.sa_mask);
470 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000471 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000472 sigaction(host_sig, &act, NULL);
473
474 /* For some reason raise(host_sig) doesn't send the signal when
475 * statically linked on x86-64. */
476 kill(getpid(), host_sig);
477
478 /* Make sure the signal isn't masked (just reuse the mask inside
479 of act) */
480 sigdelset(&act.sa_mask, host_sig);
481 sigsuspend(&act.sa_mask);
482
483 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000484 abort();
bellard66fb9762003-03-23 01:06:05 +0000485}
486
bellard9de5e442003-03-23 16:49:39 +0000487/* queue a signal so that it will be send to the virtual CPU as soon
488 as possible */
Andreas Färber9349b4f2012-03-14 01:38:32 +0100489int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000490{
Andreas Färber0429a972013-08-26 18:14:44 +0200491 CPUState *cpu = ENV_GET_CPU(env);
492 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000493 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000494 struct sigqueue *q, **pq;
blueswir1992f48a2007-10-14 16:27:31 +0000495 abi_ulong handler;
aurel32ca587a82008-12-18 22:44:13 +0000496 int queue;
bellard66fb9762003-03-23 01:06:05 +0000497
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100498 trace_user_queue_signal(env, sig);
pbrook624f7972008-05-31 16:11:38 +0000499 k = &ts->sigtab[sig - 1];
aurel32ca587a82008-12-18 22:44:13 +0000500 queue = gdb_queuesig ();
pbrook624f7972008-05-31 16:11:38 +0000501 handler = sigact_table[sig - 1]._sa_handler;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000502
503 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
504 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
505 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
506 * because it got a real MMU fault). A blocked SIGSEGV in that
507 * situation is treated as if using the default handler. This is
508 * not correct if some other process has randomly sent us a SIGSEGV
509 * via kill(), but that is not easy to distinguish at this point,
510 * so we assume it doesn't happen.
511 */
512 handler = TARGET_SIG_DFL;
513 }
514
aurel32ca587a82008-12-18 22:44:13 +0000515 if (!queue && handler == TARGET_SIG_DFL) {
ths60b19692008-11-27 15:47:15 +0000516 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
517 kill(getpid(),SIGSTOP);
518 return 0;
519 } else
bellard66fb9762003-03-23 01:06:05 +0000520 /* default handler : ignore some signal. The other are fatal */
ths5fafdf22007-09-16 21:08:06 +0000521 if (sig != TARGET_SIGCHLD &&
522 sig != TARGET_SIGURG &&
ths60b19692008-11-27 15:47:15 +0000523 sig != TARGET_SIGWINCH &&
524 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +0000525 force_sig(sig);
bellard9de5e442003-03-23 16:49:39 +0000526 } else {
527 return 0; /* indicate ignored */
bellard66fb9762003-03-23 01:06:05 +0000528 }
aurel32ca587a82008-12-18 22:44:13 +0000529 } else if (!queue && handler == TARGET_SIG_IGN) {
bellard66fb9762003-03-23 01:06:05 +0000530 /* ignore signal */
bellard9de5e442003-03-23 16:49:39 +0000531 return 0;
aurel32ca587a82008-12-18 22:44:13 +0000532 } else if (!queue && handler == TARGET_SIG_ERR) {
bellard66fb9762003-03-23 01:06:05 +0000533 force_sig(sig);
534 } else {
bellard9de5e442003-03-23 16:49:39 +0000535 pq = &k->first;
536 if (sig < TARGET_SIGRTMIN) {
537 /* if non real time signal, we queue exactly one signal */
538 if (!k->pending)
539 q = &k->info;
540 else
541 return 0;
542 } else {
543 if (!k->pending) {
544 /* first signal */
545 q = &k->info;
546 } else {
pbrook624f7972008-05-31 16:11:38 +0000547 q = alloc_sigqueue(env);
bellard9de5e442003-03-23 16:49:39 +0000548 if (!q)
549 return -EAGAIN;
550 while (*pq != NULL)
551 pq = &(*pq)->next;
552 }
553 }
554 *pq = q;
555 q->info = *info;
556 q->next = NULL;
557 k->pending = 1;
558 /* signal that a new signal is pending */
pbrook624f7972008-05-31 16:11:38 +0000559 ts->signal_pending = 1;
bellard9de5e442003-03-23 16:49:39 +0000560 return 1; /* indicates that the signal was queued */
561 }
562}
563
ths5fafdf22007-09-16 21:08:06 +0000564static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000565 void *puc)
566{
Andreas Färbera2247f82013-06-09 19:47:04 +0200567 CPUArchState *env = thread_cpu->env_ptr;
bellard9de5e442003-03-23 16:49:39 +0000568 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500569 target_siginfo_t tinfo;
bellard9de5e442003-03-23 16:49:39 +0000570
571 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000572 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000573 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000574 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000575 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000576 return;
577 }
578
579 /* get target signal number */
580 sig = host_to_target_signal(host_signum);
581 if (sig < 1 || sig > TARGET_NSIG)
582 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100583 trace_user_host_signal(env, host_signum, sig);
bellard9de5e442003-03-23 16:49:39 +0000584 host_to_target_siginfo_noswap(&tinfo, info);
Andreas Färbera2247f82013-06-09 19:47:04 +0200585 if (queue_signal(env, sig, &tinfo) == 1) {
bellard9de5e442003-03-23 16:49:39 +0000586 /* interrupt the virtual CPU as soon as possible */
Andreas Färbera2247f82013-06-09 19:47:04 +0200587 cpu_exit(thread_cpu);
bellard66fb9762003-03-23 01:06:05 +0000588 }
bellard31e31b82003-02-18 22:55:36 +0000589}
590
ths0da46a62007-10-20 20:23:07 +0000591/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000592/* compare linux/kernel/signal.c:do_sigaltstack() */
593abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000594{
595 int ret;
596 struct target_sigaltstack oss;
597
598 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000599 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000600 {
601 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
602 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
603 __put_user(sas_ss_flags(sp), &oss.ss_flags);
604 }
605
bellard579a97f2007-11-11 14:26:47 +0000606 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000607 {
bellard579a97f2007-11-11 14:26:47 +0000608 struct target_sigaltstack *uss;
609 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500610 size_t minstacksize = TARGET_MINSIGSTKSZ;
611
612#if defined(TARGET_PPC64)
613 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
614 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
615 if (get_ppc64_abi(image) > 1) {
616 minstacksize = 4096;
617 }
618#endif
thsa04e1342007-09-27 13:57:58 +0000619
ths0da46a62007-10-20 20:23:07 +0000620 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300621 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000622 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300623 }
624 __get_user(ss.ss_sp, &uss->ss_sp);
625 __get_user(ss.ss_size, &uss->ss_size);
626 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000627 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000628
ths0da46a62007-10-20 20:23:07 +0000629 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000630 if (on_sig_stack(sp))
631 goto out;
632
ths0da46a62007-10-20 20:23:07 +0000633 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000634 if (ss.ss_flags != TARGET_SS_DISABLE
635 && ss.ss_flags != TARGET_SS_ONSTACK
636 && ss.ss_flags != 0)
637 goto out;
638
639 if (ss.ss_flags == TARGET_SS_DISABLE) {
640 ss.ss_size = 0;
641 ss.ss_sp = 0;
642 } else {
ths0da46a62007-10-20 20:23:07 +0000643 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500644 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000645 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500646 }
thsa04e1342007-09-27 13:57:58 +0000647 }
648
649 target_sigaltstack_used.ss_sp = ss.ss_sp;
650 target_sigaltstack_used.ss_size = ss.ss_size;
651 }
652
bellard579a97f2007-11-11 14:26:47 +0000653 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000654 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000655 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000656 goto out;
thsa04e1342007-09-27 13:57:58 +0000657 }
658
659 ret = 0;
660out:
661 return ret;
662}
663
ths0da46a62007-10-20 20:23:07 +0000664/* do_sigaction() return host values and errnos */
bellard66fb9762003-03-23 01:06:05 +0000665int do_sigaction(int sig, const struct target_sigaction *act,
666 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000667{
pbrook624f7972008-05-31 16:11:38 +0000668 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000669 struct sigaction act1;
670 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000671 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000672
ths2a913eb2008-11-27 15:46:25 +0000673 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
bellard66fb9762003-03-23 01:06:05 +0000674 return -EINVAL;
675 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000676 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800677 __put_user(k->_sa_handler, &oact->_sa_handler);
678 __put_user(k->sa_flags, &oact->sa_flags);
ths388bb212007-05-13 13:58:00 +0000679#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800680 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000681#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800682 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000683 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000684 }
685 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000686 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800687 __get_user(k->_sa_handler, &act->_sa_handler);
688 __get_user(k->sa_flags, &act->sa_flags);
ths388bb212007-05-13 13:58:00 +0000689#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800690 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000691#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800692 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000693 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000694
695 /* we update the host linux signal state */
696 host_sig = target_to_host_signal(sig);
697 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
698 sigfillset(&act1.sa_mask);
699 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000700 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000701 act1.sa_flags |= SA_RESTART;
702 /* NOTE: it is important to update the host kernel signal
703 ignore state to avoid getting unexpected interrupted
704 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000705 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000706 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000707 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000708 if (fatal_signal (sig))
709 act1.sa_sigaction = host_signal_handler;
710 else
711 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000712 } else {
713 act1.sa_sigaction = host_signal_handler;
714 }
ths0da46a62007-10-20 20:23:07 +0000715 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000716 }
bellard66fb9762003-03-23 01:06:05 +0000717 }
ths0da46a62007-10-20 20:23:07 +0000718 return ret;
bellard66fb9762003-03-23 01:06:05 +0000719}
bellard31e31b82003-02-18 22:55:36 +0000720
bellard459a4012007-11-11 19:45:10 +0000721#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
bellard66fb9762003-03-23 01:06:05 +0000722
723/* from the Linux kernel */
724
725struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100726 uint16_t significand[4];
727 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000728};
729
730struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100731 uint16_t significand[4];
732 uint16_t exponent;
733 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000734};
735
736struct target_xmmreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100737 abi_ulong element[4];
bellard66fb9762003-03-23 01:06:05 +0000738};
739
740struct target_fpstate {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100741 /* Regular FPU environment */
742 abi_ulong cw;
743 abi_ulong sw;
744 abi_ulong tag;
745 abi_ulong ipoff;
746 abi_ulong cssel;
747 abi_ulong dataoff;
748 abi_ulong datasel;
749 struct target_fpreg _st[8];
750 uint16_t status;
751 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000752
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100753 /* FXSR FPU environment */
754 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
755 abi_ulong mxcsr;
756 abi_ulong reserved;
757 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
758 struct target_xmmreg _xmm[8];
759 abi_ulong padding[56];
bellard66fb9762003-03-23 01:06:05 +0000760};
761
762#define X86_FXSR_MAGIC 0x0000
763
764struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100765 uint16_t gs, __gsh;
766 uint16_t fs, __fsh;
767 uint16_t es, __esh;
768 uint16_t ds, __dsh;
769 abi_ulong edi;
770 abi_ulong esi;
771 abi_ulong ebp;
772 abi_ulong esp;
773 abi_ulong ebx;
774 abi_ulong edx;
775 abi_ulong ecx;
776 abi_ulong eax;
777 abi_ulong trapno;
778 abi_ulong err;
779 abi_ulong eip;
780 uint16_t cs, __csh;
781 abi_ulong eflags;
782 abi_ulong esp_at_signal;
783 uint16_t ss, __ssh;
784 abi_ulong fpstate; /* pointer */
785 abi_ulong oldmask;
786 abi_ulong cr2;
bellard66fb9762003-03-23 01:06:05 +0000787};
788
bellard66fb9762003-03-23 01:06:05 +0000789struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100790 abi_ulong tuc_flags;
791 abi_ulong tuc_link;
792 target_stack_t tuc_stack;
793 struct target_sigcontext tuc_mcontext;
794 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000795};
796
797struct sigframe
798{
blueswir1992f48a2007-10-14 16:27:31 +0000799 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000800 int sig;
801 struct target_sigcontext sc;
802 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000803 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000804 char retcode[8];
805};
806
807struct rt_sigframe
808{
blueswir1992f48a2007-10-14 16:27:31 +0000809 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000810 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000811 abi_ulong pinfo;
812 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000813 struct target_siginfo info;
814 struct target_ucontext uc;
815 struct target_fpstate fpstate;
816 char retcode[8];
817};
818
819/*
820 * Set up a signal frame.
821 */
822
bellard66fb9762003-03-23 01:06:05 +0000823/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300824static void setup_sigcontext(struct target_sigcontext *sc,
825 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
826 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000827{
Andreas Färber27103422013-08-26 08:31:06 +0200828 CPUState *cs = CPU(x86_env_get_cpu(env));
Andreas Färber27103422013-08-26 08:31:06 +0200829 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +0000830
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100831 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300832 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
833 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
834 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
835 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
836 __put_user(env->regs[R_EDI], &sc->edi);
837 __put_user(env->regs[R_ESI], &sc->esi);
838 __put_user(env->regs[R_EBP], &sc->ebp);
839 __put_user(env->regs[R_ESP], &sc->esp);
840 __put_user(env->regs[R_EBX], &sc->ebx);
841 __put_user(env->regs[R_EDX], &sc->edx);
842 __put_user(env->regs[R_ECX], &sc->ecx);
843 __put_user(env->regs[R_EAX], &sc->eax);
844 __put_user(cs->exception_index, &sc->trapno);
845 __put_user(env->error_code, &sc->err);
846 __put_user(env->eip, &sc->eip);
847 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
848 __put_user(env->eflags, &sc->eflags);
849 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
850 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +0000851
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100852 cpu_x86_fsave(env, fpstate_addr, 1);
853 fpstate->status = fpstate->sw;
854 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300855 __put_user(magic, &fpstate->magic);
856 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +0000857
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100858 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300859 __put_user(mask, &sc->oldmask);
860 __put_user(env->cr[2], &sc->cr2);
bellard66fb9762003-03-23 01:06:05 +0000861}
862
863/*
864 * Determine which stack to use..
865 */
866
bellard579a97f2007-11-11 14:26:47 +0000867static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +0000868get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +0000869{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100870 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +0000871
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100872 /* Default to using normal stack */
873 esp = env->regs[R_ESP];
874 /* This is the X/Open sanctioned signal stack switching. */
875 if (ka->sa_flags & TARGET_SA_ONSTACK) {
876 if (sas_ss_flags(esp) == 0) {
877 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +0000878 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100879 } else {
bellard66fb9762003-03-23 01:06:05 +0000880
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100881 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +0000882 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100883 !(ka->sa_flags & TARGET_SA_RESTORER) &&
884 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +0000885 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100886 }
887 }
888 return (esp - frame_size) & -8ul;
bellard66fb9762003-03-23 01:06:05 +0000889}
890
bellard579a97f2007-11-11 14:26:47 +0000891/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +0000892static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100893 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000894{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100895 abi_ulong frame_addr;
896 struct sigframe *frame;
897 int i;
bellard66fb9762003-03-23 01:06:05 +0000898
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100899 frame_addr = get_sigframe(ka, env, sizeof(*frame));
900 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +0000901
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100902 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
903 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +0000904
Peter Maydellb6e2c932015-01-08 12:19:43 +0000905 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +0000906
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100907 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
908 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +0000909
Riku Voipio7df2fa32014-04-23 10:34:53 +0300910 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
911 __put_user(set->sig[i], &frame->extramask[i - 1]);
912 }
bellard66fb9762003-03-23 01:06:05 +0000913
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100914 /* Set up to return from userspace. If provided, use a stub
915 already in userspace. */
916 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +0300917 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100918 } else {
919 uint16_t val16;
920 abi_ulong retcode_addr;
921 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300922 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100923 /* This is popl %eax ; movl $,%eax ; int $0x80 */
924 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300925 __put_user(val16, (uint16_t *)(frame->retcode+0));
926 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100927 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300928 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100929 }
bellard66fb9762003-03-23 01:06:05 +0000930
bellard66fb9762003-03-23 01:06:05 +0000931
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100932 /* Set up registers for signal handler */
933 env->regs[R_ESP] = frame_addr;
934 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +0000935
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100936 cpu_x86_load_seg(env, R_DS, __USER_DS);
937 cpu_x86_load_seg(env, R_ES, __USER_DS);
938 cpu_x86_load_seg(env, R_SS, __USER_DS);
939 cpu_x86_load_seg(env, R_CS, __USER_CS);
940 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +0000941
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100942 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000943
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100944 return;
bellard66fb9762003-03-23 01:06:05 +0000945
946give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100947 if (sig == TARGET_SIGSEGV) {
948 ka->_sa_handler = TARGET_SIG_DFL;
949 }
950 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +0000951}
952
bellard579a97f2007-11-11 14:26:47 +0000953/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +0000954static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -0500955 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100956 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000957{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100958 abi_ulong frame_addr, addr;
959 struct rt_sigframe *frame;
960 int i;
bellard66fb9762003-03-23 01:06:05 +0000961
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100962 frame_addr = get_sigframe(ka, env, sizeof(*frame));
963 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +0000964
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100965 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
966 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +0000967
Peter Maydellb6e2c932015-01-08 12:19:43 +0000968 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100969 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300970 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100971 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300972 __put_user(addr, &frame->puc);
Peter Maydellf6c7a052015-01-08 12:19:48 +0000973 tswap_siginfo(&frame->info, info);
bellard66fb9762003-03-23 01:06:05 +0000974
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100975 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300976 __put_user(0, &frame->uc.tuc_flags);
977 __put_user(0, &frame->uc.tuc_link);
978 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
979 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
980 &frame->uc.tuc_stack.ss_flags);
981 __put_user(target_sigaltstack_used.ss_size,
982 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +0300983 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
984 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
985
Riku Voipio0188fad2014-04-23 13:34:15 +0300986 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
987 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
988 }
bellard66fb9762003-03-23 01:06:05 +0000989
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100990 /* Set up to return from userspace. If provided, use a stub
991 already in userspace. */
992 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +0300993 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100994 } else {
995 uint16_t val16;
996 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300997 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100998 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300999 __put_user(0xb8, (char *)(frame->retcode+0));
1000 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001001 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001002 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001003 }
bellard66fb9762003-03-23 01:06:05 +00001004
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001005 /* Set up registers for signal handler */
1006 env->regs[R_ESP] = frame_addr;
1007 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001008
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001009 cpu_x86_load_seg(env, R_DS, __USER_DS);
1010 cpu_x86_load_seg(env, R_ES, __USER_DS);
1011 cpu_x86_load_seg(env, R_SS, __USER_DS);
1012 cpu_x86_load_seg(env, R_CS, __USER_CS);
1013 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001014
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001015 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001016
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001017 return;
bellard66fb9762003-03-23 01:06:05 +00001018
1019give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001020 if (sig == TARGET_SIGSEGV) {
1021 ka->_sa_handler = TARGET_SIG_DFL;
1022 }
1023 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +00001024}
1025
1026static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001027restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001028{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001029 unsigned int err = 0;
1030 abi_ulong fpstate_addr;
1031 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001032
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001033 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1034 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1035 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1036 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001037
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001038 env->regs[R_EDI] = tswapl(sc->edi);
1039 env->regs[R_ESI] = tswapl(sc->esi);
1040 env->regs[R_EBP] = tswapl(sc->ebp);
1041 env->regs[R_ESP] = tswapl(sc->esp);
1042 env->regs[R_EBX] = tswapl(sc->ebx);
1043 env->regs[R_EDX] = tswapl(sc->edx);
1044 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001045 env->regs[R_EAX] = tswapl(sc->eax);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001046 env->eip = tswapl(sc->eip);
bellard66fb9762003-03-23 01:06:05 +00001047
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001048 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1049 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001050
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001051 tmpflags = tswapl(sc->eflags);
1052 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1053 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001054
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001055 fpstate_addr = tswapl(sc->fpstate);
1056 if (fpstate_addr != 0) {
1057 if (!access_ok(VERIFY_READ, fpstate_addr,
1058 sizeof(struct target_fpstate)))
1059 goto badframe;
1060 cpu_x86_frstor(env, fpstate_addr, 1);
1061 }
bellard66fb9762003-03-23 01:06:05 +00001062
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001063 return err;
bellard66fb9762003-03-23 01:06:05 +00001064badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001065 return 1;
bellard66fb9762003-03-23 01:06:05 +00001066}
1067
1068long do_sigreturn(CPUX86State *env)
1069{
bellard579a97f2007-11-11 14:26:47 +00001070 struct sigframe *frame;
1071 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001072 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001073 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001074 int i;
bellard66fb9762003-03-23 01:06:05 +00001075
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001076 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001077 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1078 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001079 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001080 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001081 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001082 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001083 }
bellard66fb9762003-03-23 01:06:05 +00001084
bellard92319442004-06-19 16:58:13 +00001085 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00001086 do_sigprocmask(SIG_SETMASK, &set, NULL);
ths3b46e622007-09-17 08:09:54 +00001087
bellard66fb9762003-03-23 01:06:05 +00001088 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001089 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001090 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001091 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001092 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001093
1094badframe:
bellard579a97f2007-11-11 14:26:47 +00001095 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001096 force_sig(TARGET_SIGSEGV);
1097 return 0;
1098}
1099
1100long do_rt_sigreturn(CPUX86State *env)
1101{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001102 abi_ulong frame_addr;
1103 struct rt_sigframe *frame;
1104 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001105
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001106 frame_addr = env->regs[R_ESP] - 4;
1107 trace_user_do_rt_sigreturn(env, frame_addr);
1108 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1109 goto badframe;
1110 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
1111 do_sigprocmask(SIG_SETMASK, &set, NULL);
ths5fafdf22007-09-16 21:08:06 +00001112
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001113 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001114 goto badframe;
1115 }
bellard66fb9762003-03-23 01:06:05 +00001116
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001117 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1118 get_sp_from_cpustate(env)) == -EFAULT) {
1119 goto badframe;
1120 }
thsa04e1342007-09-27 13:57:58 +00001121
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001122 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001123 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001124
1125badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001126 unlock_user_struct(frame, frame_addr, 0);
1127 force_sig(TARGET_SIGSEGV);
1128 return 0;
bellard66fb9762003-03-23 01:06:05 +00001129}
1130
Andreas Schwab1744aea2013-09-03 20:12:16 +01001131#elif defined(TARGET_AARCH64)
1132
1133struct target_sigcontext {
1134 uint64_t fault_address;
1135 /* AArch64 registers */
1136 uint64_t regs[31];
1137 uint64_t sp;
1138 uint64_t pc;
1139 uint64_t pstate;
1140 /* 4K reserved for FP/SIMD state and future expansion */
1141 char __reserved[4096] __attribute__((__aligned__(16)));
1142};
1143
1144struct target_ucontext {
1145 abi_ulong tuc_flags;
1146 abi_ulong tuc_link;
1147 target_stack_t tuc_stack;
1148 target_sigset_t tuc_sigmask;
1149 /* glibc uses a 1024-bit sigset_t */
1150 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1151 /* last for future expansion */
1152 struct target_sigcontext tuc_mcontext;
1153};
1154
1155/*
1156 * Header to be used at the beginning of structures extending the user
1157 * context. Such structures must be placed after the rt_sigframe on the stack
1158 * and be 16-byte aligned. The last structure must be a dummy one with the
1159 * magic and size set to 0.
1160 */
1161struct target_aarch64_ctx {
1162 uint32_t magic;
1163 uint32_t size;
1164};
1165
1166#define TARGET_FPSIMD_MAGIC 0x46508001
1167
1168struct target_fpsimd_context {
1169 struct target_aarch64_ctx head;
1170 uint32_t fpsr;
1171 uint32_t fpcr;
1172 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1173};
1174
1175/*
1176 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1177 * user space as it will change with the addition of new context. User space
1178 * should check the magic/size information.
1179 */
1180struct target_aux_context {
1181 struct target_fpsimd_context fpsimd;
1182 /* additional context to be added before "end" */
1183 struct target_aarch64_ctx end;
1184};
1185
1186struct target_rt_sigframe {
1187 struct target_siginfo info;
1188 struct target_ucontext uc;
1189 uint64_t fp;
1190 uint64_t lr;
1191 uint32_t tramp[2];
1192};
1193
1194static int target_setup_sigframe(struct target_rt_sigframe *sf,
1195 CPUARMState *env, target_sigset_t *set)
1196{
1197 int i;
1198 struct target_aux_context *aux =
1199 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1200
1201 /* set up the stack frame for unwinding */
1202 __put_user(env->xregs[29], &sf->fp);
1203 __put_user(env->xregs[30], &sf->lr);
1204
1205 for (i = 0; i < 31; i++) {
1206 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1207 }
1208 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1209 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001210 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001211
Peter Maydell7af03922014-05-01 18:36:17 +01001212 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001213
1214 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1215 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1216 }
1217
1218 for (i = 0; i < 32; i++) {
1219#ifdef TARGET_WORDS_BIGENDIAN
1220 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1221 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1222#else
1223 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1224 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1225#endif
1226 }
Will Newtone0ee1382014-01-04 22:15:48 +00001227 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1228 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001229 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1230 __put_user(sizeof(struct target_fpsimd_context),
1231 &aux->fpsimd.head.size);
1232
1233 /* set the "end" magic */
1234 __put_user(0, &aux->end.magic);
1235 __put_user(0, &aux->end.size);
1236
1237 return 0;
1238}
1239
1240static int target_restore_sigframe(CPUARMState *env,
1241 struct target_rt_sigframe *sf)
1242{
1243 sigset_t set;
1244 int i;
1245 struct target_aux_context *aux =
1246 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
Will Newtone0ee1382014-01-04 22:15:48 +00001247 uint32_t magic, size, fpsr, fpcr;
Peter Maydelld3563122013-12-17 19:42:30 +00001248 uint64_t pstate;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001249
1250 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001251 do_sigprocmask(SIG_SETMASK, &set, NULL);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001252
1253 for (i = 0; i < 31; i++) {
1254 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1255 }
1256
1257 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1258 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001259 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1260 pstate_write(env, pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001261
1262 __get_user(magic, &aux->fpsimd.head.magic);
1263 __get_user(size, &aux->fpsimd.head.size);
1264
1265 if (magic != TARGET_FPSIMD_MAGIC
1266 || size != sizeof(struct target_fpsimd_context)) {
1267 return 1;
1268 }
1269
Peter Maydell4cf23482014-03-02 19:36:38 +00001270 for (i = 0; i < 32; i++) {
1271#ifdef TARGET_WORDS_BIGENDIAN
1272 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1273 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1274#else
1275 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1276 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1277#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001278 }
Will Newtone0ee1382014-01-04 22:15:48 +00001279 __get_user(fpsr, &aux->fpsimd.fpsr);
1280 vfp_set_fpsr(env, fpsr);
1281 __get_user(fpcr, &aux->fpsimd.fpcr);
1282 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001283
1284 return 0;
1285}
1286
1287static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1288{
1289 abi_ulong sp;
1290
1291 sp = env->xregs[31];
1292
1293 /*
1294 * This is the X/Open sanctioned signal stack switching.
1295 */
Riku Voipiob545f632014-07-15 17:01:55 +03001296 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001297 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1298 }
1299
1300 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1301
1302 return sp;
1303}
1304
1305static void target_setup_frame(int usig, struct target_sigaction *ka,
1306 target_siginfo_t *info, target_sigset_t *set,
1307 CPUARMState *env)
1308{
1309 struct target_rt_sigframe *frame;
Michael Matz8a3ae912014-03-02 19:36:39 +00001310 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001311
1312 frame_addr = get_sigframe(ka, env);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001313 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001314 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1315 goto give_sigsegv;
1316 }
1317
1318 __put_user(0, &frame->uc.tuc_flags);
1319 __put_user(0, &frame->uc.tuc_link);
1320
1321 __put_user(target_sigaltstack_used.ss_sp,
1322 &frame->uc.tuc_stack.ss_sp);
1323 __put_user(sas_ss_flags(env->xregs[31]),
1324 &frame->uc.tuc_stack.ss_flags);
1325 __put_user(target_sigaltstack_used.ss_size,
1326 &frame->uc.tuc_stack.ss_size);
1327 target_setup_sigframe(frame, env, set);
Michael Matz8a3ae912014-03-02 19:36:39 +00001328 if (ka->sa_flags & TARGET_SA_RESTORER) {
1329 return_addr = ka->sa_restorer;
1330 } else {
1331 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1332 __put_user(0xd2801168, &frame->tramp[0]);
1333 __put_user(0xd4000001, &frame->tramp[1]);
1334 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1335 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001336 env->xregs[0] = usig;
1337 env->xregs[31] = frame_addr;
1338 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1339 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001340 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001341 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001342 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001343 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1344 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1345 }
1346
1347 unlock_user_struct(frame, frame_addr, 1);
1348 return;
1349
1350 give_sigsegv:
1351 unlock_user_struct(frame, frame_addr, 1);
1352 force_sig(TARGET_SIGSEGV);
1353}
1354
1355static void setup_rt_frame(int sig, struct target_sigaction *ka,
1356 target_siginfo_t *info, target_sigset_t *set,
1357 CPUARMState *env)
1358{
1359 target_setup_frame(sig, ka, info, set, env);
1360}
1361
1362static void setup_frame(int sig, struct target_sigaction *ka,
1363 target_sigset_t *set, CPUARMState *env)
1364{
1365 target_setup_frame(sig, ka, 0, set, env);
1366}
1367
1368long do_rt_sigreturn(CPUARMState *env)
1369{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001370 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001371 abi_ulong frame_addr = env->xregs[31];
1372
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001373 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001374 if (frame_addr & 15) {
1375 goto badframe;
1376 }
1377
1378 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1379 goto badframe;
1380 }
1381
1382 if (target_restore_sigframe(env, frame)) {
1383 goto badframe;
1384 }
1385
1386 if (do_sigaltstack(frame_addr +
1387 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1388 0, get_sp_from_cpustate(env)) == -EFAULT) {
1389 goto badframe;
1390 }
1391
1392 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001393 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001394
1395 badframe:
1396 unlock_user_struct(frame, frame_addr, 0);
1397 force_sig(TARGET_SIGSEGV);
1398 return 0;
1399}
1400
1401long do_sigreturn(CPUARMState *env)
1402{
1403 return do_rt_sigreturn(env);
1404}
1405
bellard43fff232003-07-09 19:31:39 +00001406#elif defined(TARGET_ARM)
1407
1408struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001409 abi_ulong trap_no;
1410 abi_ulong error_code;
1411 abi_ulong oldmask;
1412 abi_ulong arm_r0;
1413 abi_ulong arm_r1;
1414 abi_ulong arm_r2;
1415 abi_ulong arm_r3;
1416 abi_ulong arm_r4;
1417 abi_ulong arm_r5;
1418 abi_ulong arm_r6;
1419 abi_ulong arm_r7;
1420 abi_ulong arm_r8;
1421 abi_ulong arm_r9;
1422 abi_ulong arm_r10;
1423 abi_ulong arm_fp;
1424 abi_ulong arm_ip;
1425 abi_ulong arm_sp;
1426 abi_ulong arm_lr;
1427 abi_ulong arm_pc;
1428 abi_ulong arm_cpsr;
1429 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001430};
1431
pbrooka745ec62008-05-06 15:36:17 +00001432struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001433 abi_ulong tuc_flags;
1434 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001435 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001436 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001437 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001438};
1439
pbrooka745ec62008-05-06 15:36:17 +00001440struct target_ucontext_v2 {
1441 abi_ulong tuc_flags;
1442 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001443 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001444 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001445 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001446 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001447 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1448};
1449
Peter Maydell0d871bd2010-11-24 15:20:05 +00001450struct target_user_vfp {
1451 uint64_t fpregs[32];
1452 abi_ulong fpscr;
1453};
1454
1455struct target_user_vfp_exc {
1456 abi_ulong fpexc;
1457 abi_ulong fpinst;
1458 abi_ulong fpinst2;
1459};
1460
1461struct target_vfp_sigframe {
1462 abi_ulong magic;
1463 abi_ulong size;
1464 struct target_user_vfp ufp;
1465 struct target_user_vfp_exc ufp_exc;
1466} __attribute__((__aligned__(8)));
1467
Peter Maydell08e11252010-11-24 15:20:07 +00001468struct target_iwmmxt_sigframe {
1469 abi_ulong magic;
1470 abi_ulong size;
1471 uint64_t regs[16];
1472 /* Note that not all the coprocessor control registers are stored here */
1473 uint32_t wcssf;
1474 uint32_t wcasf;
1475 uint32_t wcgr0;
1476 uint32_t wcgr1;
1477 uint32_t wcgr2;
1478 uint32_t wcgr3;
1479} __attribute__((__aligned__(8)));
1480
Peter Maydell0d871bd2010-11-24 15:20:05 +00001481#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001482#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001483
pbrooka8c33202008-05-07 23:22:46 +00001484struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001485{
1486 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001487 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1488 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001489};
1490
pbrooka8c33202008-05-07 23:22:46 +00001491struct sigframe_v2
1492{
1493 struct target_ucontext_v2 uc;
1494 abi_ulong retcode;
1495};
1496
pbrooka745ec62008-05-06 15:36:17 +00001497struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001498{
bellardf8b0aa22007-11-11 23:03:42 +00001499 abi_ulong pinfo;
1500 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001501 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001502 struct target_ucontext_v1 uc;
1503 abi_ulong retcode;
1504};
1505
1506struct rt_sigframe_v2
1507{
1508 struct target_siginfo info;
1509 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001510 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001511};
1512
1513#define TARGET_CONFIG_CPU_32 1
1514
1515/*
1516 * For ARM syscalls, we encode the syscall number into the instruction.
1517 */
1518#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1519#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1520
1521/*
1522 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1523 * need two 16-bit instructions.
1524 */
1525#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1526#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1527
blueswir1992f48a2007-10-14 16:27:31 +00001528static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001529 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1530 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1531};
1532
1533
Andreas Färber05390242012-02-25 03:37:53 +01001534static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001535{
1536 return 1;
1537}
1538
pbrooka8c33202008-05-07 23:22:46 +00001539static void
bellard43fff232003-07-09 19:31:39 +00001540setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001541 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001542{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001543 __put_user(env->regs[0], &sc->arm_r0);
1544 __put_user(env->regs[1], &sc->arm_r1);
1545 __put_user(env->regs[2], &sc->arm_r2);
1546 __put_user(env->regs[3], &sc->arm_r3);
1547 __put_user(env->regs[4], &sc->arm_r4);
1548 __put_user(env->regs[5], &sc->arm_r5);
1549 __put_user(env->regs[6], &sc->arm_r6);
1550 __put_user(env->regs[7], &sc->arm_r7);
1551 __put_user(env->regs[8], &sc->arm_r8);
1552 __put_user(env->regs[9], &sc->arm_r9);
1553 __put_user(env->regs[10], &sc->arm_r10);
1554 __put_user(env->regs[11], &sc->arm_fp);
1555 __put_user(env->regs[12], &sc->arm_ip);
1556 __put_user(env->regs[13], &sc->arm_sp);
1557 __put_user(env->regs[14], &sc->arm_lr);
1558 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001559#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001560 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001561#endif
1562
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001563 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1564 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1565 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1566 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001567}
1568
bellard579a97f2007-11-11 14:26:47 +00001569static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001570get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001571{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001572 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00001573
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001574 /*
1575 * This is the X/Open sanctioned signal stack switching.
1576 */
1577 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1578 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1579 }
1580 /*
1581 * ATPCS B01 mandates 8-byte alignment
1582 */
1583 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001584}
1585
Riku Voipio0188fad2014-04-23 13:34:15 +03001586static void
Andreas Färber05390242012-02-25 03:37:53 +01001587setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001588 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001589{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001590 abi_ulong handler = ka->_sa_handler;
1591 abi_ulong retcode;
1592 int thumb = handler & 1;
1593 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01001594
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001595 cpsr &= ~CPSR_IT;
1596 if (thumb) {
1597 cpsr |= CPSR_T;
1598 } else {
1599 cpsr &= ~CPSR_T;
1600 }
bellard43fff232003-07-09 19:31:39 +00001601
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001602 if (ka->sa_flags & TARGET_SA_RESTORER) {
1603 retcode = ka->sa_restorer;
1604 } else {
1605 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00001606
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001607 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1608 idx += 2;
1609 }
bellard43fff232003-07-09 19:31:39 +00001610
Riku Voipio0188fad2014-04-23 13:34:15 +03001611 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001612
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001613 retcode = rc_addr + thumb;
1614 }
bellard43fff232003-07-09 19:31:39 +00001615
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001616 env->regs[0] = usig;
1617 env->regs[13] = frame_addr;
1618 env->regs[14] = retcode;
1619 env->regs[15] = handler & (thumb ? ~1 : ~3);
1620 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001621}
1622
Andreas Färber05390242012-02-25 03:37:53 +01001623static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001624{
1625 int i;
1626 struct target_vfp_sigframe *vfpframe;
1627 vfpframe = (struct target_vfp_sigframe *)regspace;
1628 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1629 __put_user(sizeof(*vfpframe), &vfpframe->size);
1630 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001631 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001632 }
1633 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1634 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1635 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1636 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1637 return (abi_ulong*)(vfpframe+1);
1638}
1639
Andreas Färber05390242012-02-25 03:37:53 +01001640static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1641 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001642{
1643 int i;
1644 struct target_iwmmxt_sigframe *iwmmxtframe;
1645 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1646 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1647 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1648 for (i = 0; i < 16; i++) {
1649 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1650 }
1651 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1652 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1653 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1654 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1655 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1656 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1657 return (abi_ulong*)(iwmmxtframe+1);
1658}
1659
pbrooka8c33202008-05-07 23:22:46 +00001660static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001661 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001662{
pbrooka8c33202008-05-07 23:22:46 +00001663 struct target_sigaltstack stack;
1664 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001665 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001666
1667 /* Clear all the bits of the ucontext we don't use. */
1668 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1669
1670 memset(&stack, 0, sizeof(stack));
1671 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1672 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1673 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1674 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1675
1676 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001677 /* Save coprocessor signal frame. */
1678 regspace = uc->tuc_regspace;
1679 if (arm_feature(env, ARM_FEATURE_VFP)) {
1680 regspace = setup_sigframe_v2_vfp(regspace, env);
1681 }
Peter Maydell08e11252010-11-24 15:20:07 +00001682 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1683 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1684 }
1685
Peter Maydell0d871bd2010-11-24 15:20:05 +00001686 /* Write terminating magic word */
1687 __put_user(0, regspace);
1688
pbrooka8c33202008-05-07 23:22:46 +00001689 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1690 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1691 }
1692}
1693
1694/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001695static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001696 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001697{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001698 struct sigframe_v1 *frame;
1699 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1700 int i;
bellard43fff232003-07-09 19:31:39 +00001701
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001702 trace_user_setup_frame(regs, frame_addr);
1703 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1704 return;
1705 }
bellard579a97f2007-11-11 14:26:47 +00001706
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001707 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00001708
Riku Voipio0188fad2014-04-23 13:34:15 +03001709 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1710 __put_user(set->sig[i], &frame->extramask[i - 1]);
1711 }
bellard43fff232003-07-09 19:31:39 +00001712
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001713 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1714 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00001715
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001716 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001717}
1718
pbrook624f7972008-05-31 16:11:38 +00001719static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001720 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001721{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001722 struct sigframe_v2 *frame;
1723 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00001724
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001725 trace_user_setup_frame(regs, frame_addr);
1726 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1727 return;
1728 }
pbrooka8c33202008-05-07 23:22:46 +00001729
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001730 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00001731
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001732 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1733 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00001734
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001735 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001736}
1737
pbrook624f7972008-05-31 16:11:38 +00001738static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001739 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001740{
1741 if (get_osversion() >= 0x020612) {
1742 setup_frame_v2(usig, ka, set, regs);
1743 } else {
1744 setup_frame_v1(usig, ka, set, regs);
1745 }
bellard43fff232003-07-09 19:31:39 +00001746}
1747
bellard579a97f2007-11-11 14:26:47 +00001748/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001749static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001750 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001751 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001752{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001753 struct rt_sigframe_v1 *frame;
1754 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1755 struct target_sigaltstack stack;
1756 int i;
1757 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00001758
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001759 trace_user_setup_rt_frame(env, frame_addr);
1760 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1761 return /* 1 */;
1762 }
bellardedf779f2004-02-22 13:40:13 +00001763
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001764 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1765 __put_user(info_addr, &frame->pinfo);
1766 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1767 __put_user(uc_addr, &frame->puc);
1768 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00001769
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001770 /* Clear all the bits of the ucontext we don't use. */
1771 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00001772
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001773 memset(&stack, 0, sizeof(stack));
1774 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1775 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1776 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1777 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00001778
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001779 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1780 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1781 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1782 }
bellard43fff232003-07-09 19:31:39 +00001783
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001784 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1785 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001786
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001787 env->regs[1] = info_addr;
1788 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001789
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001790 unlock_user_struct(frame, frame_addr, 1);
pbrooka745ec62008-05-06 15:36:17 +00001791}
1792
pbrook624f7972008-05-31 16:11:38 +00001793static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001794 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001795 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001796{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001797 struct rt_sigframe_v2 *frame;
1798 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1799 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001800
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001801 trace_user_setup_rt_frame(env, frame_addr);
1802 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1803 return /* 1 */;
1804 }
pbrooka745ec62008-05-06 15:36:17 +00001805
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001806 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1807 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1808 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00001809
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001810 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00001811
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001812 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1813 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001814
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001815 env->regs[1] = info_addr;
1816 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001817
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001818 unlock_user_struct(frame, frame_addr, 1);
bellard43fff232003-07-09 19:31:39 +00001819}
1820
pbrook624f7972008-05-31 16:11:38 +00001821static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001822 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001823 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001824{
1825 if (get_osversion() >= 0x020612) {
1826 setup_rt_frame_v2(usig, ka, info, set, env);
1827 } else {
1828 setup_rt_frame_v1(usig, ka, info, set, env);
1829 }
1830}
1831
bellard43fff232003-07-09 19:31:39 +00001832static int
Andreas Färber05390242012-02-25 03:37:53 +01001833restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00001834{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001835 int err = 0;
1836 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00001837
Riku Voipio1d8b5122014-04-23 10:26:05 +03001838 __get_user(env->regs[0], &sc->arm_r0);
1839 __get_user(env->regs[1], &sc->arm_r1);
1840 __get_user(env->regs[2], &sc->arm_r2);
1841 __get_user(env->regs[3], &sc->arm_r3);
1842 __get_user(env->regs[4], &sc->arm_r4);
1843 __get_user(env->regs[5], &sc->arm_r5);
1844 __get_user(env->regs[6], &sc->arm_r6);
1845 __get_user(env->regs[7], &sc->arm_r7);
1846 __get_user(env->regs[8], &sc->arm_r8);
1847 __get_user(env->regs[9], &sc->arm_r9);
1848 __get_user(env->regs[10], &sc->arm_r10);
1849 __get_user(env->regs[11], &sc->arm_fp);
1850 __get_user(env->regs[12], &sc->arm_ip);
1851 __get_user(env->regs[13], &sc->arm_sp);
1852 __get_user(env->regs[14], &sc->arm_lr);
1853 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001854#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03001855 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00001856 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001857#endif
1858
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001859 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00001860
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001861 return err;
bellard43fff232003-07-09 19:31:39 +00001862}
1863
Andreas Färber05390242012-02-25 03:37:53 +01001864static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001865{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001866 abi_ulong frame_addr;
1867 struct sigframe_v1 *frame = NULL;
1868 target_sigset_t set;
1869 sigset_t host_set;
1870 int i;
bellard43fff232003-07-09 19:31:39 +00001871
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001872 /*
1873 * Since we stacked the signal on a 64-bit boundary,
1874 * then 'sp' should be word aligned here. If it's
1875 * not, then the user is trying to mess with us.
1876 */
1877 frame_addr = env->regs[13];
1878 trace_user_do_sigreturn(env, frame_addr);
1879 if (frame_addr & 7) {
1880 goto badframe;
1881 }
Peter Maydell978fae92013-07-29 12:00:32 +01001882
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001883 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1884 goto badframe;
1885 }
bellard43fff232003-07-09 19:31:39 +00001886
Riku Voipiof5f601a2014-04-23 13:00:17 +03001887 __get_user(set.sig[0], &frame->sc.oldmask);
1888 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1889 __get_user(set.sig[i], &frame->extramask[i - 1]);
1890 }
bellard43fff232003-07-09 19:31:39 +00001891
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001892 target_to_host_sigset_internal(&host_set, &set);
1893 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard43fff232003-07-09 19:31:39 +00001894
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001895 if (restore_sigcontext(env, &frame->sc)) {
1896 goto badframe;
1897 }
bellard43fff232003-07-09 19:31:39 +00001898
1899#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001900 /* Send SIGTRAP if we're single-stepping */
1901 if (ptrace_cancel_bpt(current))
1902 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00001903#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001904 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001905 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00001906
1907badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001908 force_sig(TARGET_SIGSEGV /* , current */);
1909 return 0;
bellard43fff232003-07-09 19:31:39 +00001910}
1911
Andreas Färber05390242012-02-25 03:37:53 +01001912static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00001913{
1914 int i;
1915 abi_ulong magic, sz;
1916 uint32_t fpscr, fpexc;
1917 struct target_vfp_sigframe *vfpframe;
1918 vfpframe = (struct target_vfp_sigframe *)regspace;
1919
1920 __get_user(magic, &vfpframe->magic);
1921 __get_user(sz, &vfpframe->size);
1922 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1923 return 0;
1924 }
1925 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001926 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00001927 }
1928 __get_user(fpscr, &vfpframe->ufp.fpscr);
1929 vfp_set_fpscr(env, fpscr);
1930 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1931 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1932 * and the exception flag is cleared
1933 */
1934 fpexc |= (1 << 30);
1935 fpexc &= ~((1 << 31) | (1 << 28));
1936 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1937 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1938 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1939 return (abi_ulong*)(vfpframe + 1);
1940}
1941
Andreas Färber05390242012-02-25 03:37:53 +01001942static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
1943 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00001944{
1945 int i;
1946 abi_ulong magic, sz;
1947 struct target_iwmmxt_sigframe *iwmmxtframe;
1948 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1949
1950 __get_user(magic, &iwmmxtframe->magic);
1951 __get_user(sz, &iwmmxtframe->size);
1952 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
1953 return 0;
1954 }
1955 for (i = 0; i < 16; i++) {
1956 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1957 }
1958 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1959 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1960 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1961 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1962 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1963 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1964 return (abi_ulong*)(iwmmxtframe + 1);
1965}
1966
Andreas Färber05390242012-02-25 03:37:53 +01001967static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
pbrooka8c33202008-05-07 23:22:46 +00001968 struct target_ucontext_v2 *uc)
1969{
1970 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00001971 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001972
1973 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001974 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
pbrooka8c33202008-05-07 23:22:46 +00001975
1976 if (restore_sigcontext(env, &uc->tuc_mcontext))
1977 return 1;
1978
Peter Maydell5f9099d2010-11-24 15:20:06 +00001979 /* Restore coprocessor signal frame */
1980 regspace = uc->tuc_regspace;
1981 if (arm_feature(env, ARM_FEATURE_VFP)) {
1982 regspace = restore_sigframe_v2_vfp(env, regspace);
1983 if (!regspace) {
1984 return 1;
1985 }
1986 }
Peter Maydella59d69d2010-11-24 15:20:08 +00001987 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1988 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
1989 if (!regspace) {
1990 return 1;
1991 }
1992 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00001993
pbrooka8c33202008-05-07 23:22:46 +00001994 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1995 return 1;
1996
1997#if 0
1998 /* Send SIGTRAP if we're single-stepping */
1999 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002000 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002001#endif
2002
2003 return 0;
2004}
2005
Andreas Färber05390242012-02-25 03:37:53 +01002006static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002007{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002008 abi_ulong frame_addr;
2009 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002010
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002011 /*
2012 * Since we stacked the signal on a 64-bit boundary,
2013 * then 'sp' should be word aligned here. If it's
2014 * not, then the user is trying to mess with us.
2015 */
2016 frame_addr = env->regs[13];
2017 trace_user_do_sigreturn(env, frame_addr);
2018 if (frame_addr & 7) {
2019 goto badframe;
2020 }
Peter Maydell978fae92013-07-29 12:00:32 +01002021
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002022 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2023 goto badframe;
2024 }
pbrooka8c33202008-05-07 23:22:46 +00002025
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002026 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2027 goto badframe;
2028 }
pbrooka8c33202008-05-07 23:22:46 +00002029
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002030 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002031 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002032
2033badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002034 unlock_user_struct(frame, frame_addr, 0);
2035 force_sig(TARGET_SIGSEGV /* , current */);
2036 return 0;
pbrooka8c33202008-05-07 23:22:46 +00002037}
2038
Andreas Färber05390242012-02-25 03:37:53 +01002039long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002040{
2041 if (get_osversion() >= 0x020612) {
2042 return do_sigreturn_v2(env);
2043 } else {
2044 return do_sigreturn_v1(env);
2045 }
2046}
2047
Andreas Färber05390242012-02-25 03:37:53 +01002048static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002049{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002050 abi_ulong frame_addr;
2051 struct rt_sigframe_v1 *frame = NULL;
2052 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002053
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002054 /*
2055 * Since we stacked the signal on a 64-bit boundary,
2056 * then 'sp' should be word aligned here. If it's
2057 * not, then the user is trying to mess with us.
2058 */
2059 frame_addr = env->regs[13];
2060 trace_user_do_rt_sigreturn(env, frame_addr);
2061 if (frame_addr & 7) {
2062 goto badframe;
2063 }
Peter Maydell978fae92013-07-29 12:00:32 +01002064
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002065 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2066 goto badframe;
2067 }
bellard43fff232003-07-09 19:31:39 +00002068
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002069 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
2070 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard43fff232003-07-09 19:31:39 +00002071
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002072 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2073 goto badframe;
2074 }
bellard43fff232003-07-09 19:31:39 +00002075
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002076 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2077 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002078
bellard43fff232003-07-09 19:31:39 +00002079#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002080 /* Send SIGTRAP if we're single-stepping */
2081 if (ptrace_cancel_bpt(current))
2082 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002083#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002084 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002085 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002086
2087badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002088 unlock_user_struct(frame, frame_addr, 0);
2089 force_sig(TARGET_SIGSEGV /* , current */);
2090 return 0;
bellard43fff232003-07-09 19:31:39 +00002091}
2092
Andreas Färber05390242012-02-25 03:37:53 +01002093static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002094{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002095 abi_ulong frame_addr;
2096 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002097
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002098 /*
2099 * Since we stacked the signal on a 64-bit boundary,
2100 * then 'sp' should be word aligned here. If it's
2101 * not, then the user is trying to mess with us.
2102 */
2103 frame_addr = env->regs[13];
2104 trace_user_do_rt_sigreturn(env, frame_addr);
2105 if (frame_addr & 7) {
2106 goto badframe;
2107 }
Peter Maydell978fae92013-07-29 12:00:32 +01002108
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002109 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2110 goto badframe;
2111 }
pbrooka745ec62008-05-06 15:36:17 +00002112
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002113 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2114 goto badframe;
2115 }
pbrooka745ec62008-05-06 15:36:17 +00002116
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002117 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002118 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002119
2120badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002121 unlock_user_struct(frame, frame_addr, 0);
2122 force_sig(TARGET_SIGSEGV /* , current */);
2123 return 0;
pbrooka745ec62008-05-06 15:36:17 +00002124}
2125
Andreas Färber05390242012-02-25 03:37:53 +01002126long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002127{
2128 if (get_osversion() >= 0x020612) {
2129 return do_rt_sigreturn_v2(env);
2130 } else {
2131 return do_rt_sigreturn_v1(env);
2132 }
2133}
2134
bellard6d5e2162004-09-30 22:04:13 +00002135#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002136
bellard6d5e2162004-09-30 22:04:13 +00002137#define __SUNOS_MAXWIN 31
2138
2139/* This is what SunOS does, so shall I. */
2140struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002141 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002142
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002143 abi_ulong sigc_mask; /* sigmask to restore */
2144 abi_ulong sigc_sp; /* stack pointer */
2145 abi_ulong sigc_pc; /* program counter */
2146 abi_ulong sigc_npc; /* next program counter */
2147 abi_ulong sigc_psr; /* for condition codes etc */
2148 abi_ulong sigc_g1; /* User uses these two registers */
2149 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002150
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002151 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002152 * at the time of the signal.
2153 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002154 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002155
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002156 /* stack ptrs for each regwin buf */
2157 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002158
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002159 /* Windows to restore after signal */
2160 struct {
2161 abi_ulong locals[8];
2162 abi_ulong ins[8];
2163 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002164};
2165/* A Sparc stack frame */
2166struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002167 abi_ulong locals[8];
2168 abi_ulong ins[8];
2169 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002170 * since we never need to access them ourselves.
2171 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002172 char *structptr;
2173 abi_ulong xargs[6];
2174 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002175};
2176
2177typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002178 struct {
2179 abi_ulong psr;
2180 abi_ulong pc;
2181 abi_ulong npc;
2182 abi_ulong y;
2183 abi_ulong u_regs[16]; /* globals and ins */
2184 } si_regs;
2185 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002186} __siginfo_t;
2187
2188typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002189 abi_ulong si_float_regs[32];
2190 unsigned long si_fsr;
2191 unsigned long si_fpqdepth;
2192 struct {
2193 unsigned long *insn_addr;
2194 unsigned long insn;
2195 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002196} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002197
2198
2199struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002200 struct sparc_stackf ss;
2201 __siginfo_t info;
2202 abi_ulong fpu_save;
2203 abi_ulong insns[2] __attribute__ ((aligned (8)));
2204 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2205 abi_ulong extra_size; /* Should be 0 */
2206 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002207};
2208struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002209 struct sparc_stackf ss;
2210 siginfo_t info;
2211 abi_ulong regs[20];
2212 sigset_t mask;
2213 abi_ulong fpu_save;
2214 unsigned int insns[2];
2215 stack_t stack;
2216 unsigned int extra_size; /* Should be 0 */
2217 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002218};
2219
bellarde80cfcf2004-12-19 23:18:01 +00002220#define UREG_O0 16
2221#define UREG_O6 22
2222#define UREG_I0 0
2223#define UREG_I1 1
2224#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002225#define UREG_I3 3
2226#define UREG_I4 4
2227#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002228#define UREG_I6 6
2229#define UREG_I7 7
2230#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002231#define UREG_FP UREG_I6
2232#define UREG_SP UREG_O6
2233
pbrook624f7972008-05-31 16:11:38 +00002234static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002235 CPUSPARCState *env,
2236 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002237{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002238 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002239
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002240 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002241
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002242 /* This is the X/Open sanctioned signal stack switching. */
2243 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2244 if (!on_sig_stack(sp)
2245 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2246 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2247 }
2248 }
2249 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002250}
2251
2252static int
Andreas Färber05390242012-02-25 03:37:53 +01002253setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002254{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002255 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002256
Riku Voipio1d8b5122014-04-23 10:26:05 +03002257 __put_user(env->psr, &si->si_regs.psr);
2258 __put_user(env->pc, &si->si_regs.pc);
2259 __put_user(env->npc, &si->si_regs.npc);
2260 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002261 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002262 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002263 }
2264 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002265 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002266 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002267 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002268 return err;
bellard6d5e2162004-09-30 22:04:13 +00002269}
bellarde80cfcf2004-12-19 23:18:01 +00002270
bellard80a9d032005-01-03 23:31:27 +00002271#if 0
bellard6d5e2162004-09-30 22:04:13 +00002272static int
2273setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002274 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002275{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002276 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002277
Riku Voipio1d8b5122014-04-23 10:26:05 +03002278 __put_user(mask, &sc->sigc_mask);
2279 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2280 __put_user(env->pc, &sc->sigc_pc);
2281 __put_user(env->npc, &sc->sigc_npc);
2282 __put_user(env->psr, &sc->sigc_psr);
2283 __put_user(env->gregs[1], &sc->sigc_g1);
2284 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002285
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002286 return err;
bellard6d5e2162004-09-30 22:04:13 +00002287}
bellard80a9d032005-01-03 23:31:27 +00002288#endif
bellard6d5e2162004-09-30 22:04:13 +00002289#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2290
pbrook624f7972008-05-31 16:11:38 +00002291static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002292 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002293{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002294 abi_ulong sf_addr;
2295 struct target_signal_frame *sf;
2296 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002297
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002298 /* 1. Make sure everything is clean */
2299 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002300
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002301 sigframe_size = NF_ALIGNEDSZ;
2302 sf_addr = get_sigframe(ka, env, sigframe_size);
2303 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002304
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002305 sf = lock_user(VERIFY_WRITE, sf_addr,
2306 sizeof(struct target_signal_frame), 0);
2307 if (!sf) {
2308 goto sigsegv;
2309 }
bellard6d5e2162004-09-30 22:04:13 +00002310#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002311 if (invalid_frame_pointer(sf, sigframe_size))
2312 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002313#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002314 /* 2. Save the current process state */
2315 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002316 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002317
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002318 //save_fpu_state(regs, &sf->fpu_state);
2319 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002320
Riku Voipio1d8b5122014-04-23 10:26:05 +03002321 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002322 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002323 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002324 }
bellard6d5e2162004-09-30 22:04:13 +00002325
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002326 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002327 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002328 }
2329 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002330 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002331 }
2332 if (err)
2333 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002334
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002335 /* 3. signal handler back-trampoline and parameters */
2336 env->regwptr[UREG_FP] = sf_addr;
2337 env->regwptr[UREG_I0] = sig;
2338 env->regwptr[UREG_I1] = sf_addr +
2339 offsetof(struct target_signal_frame, info);
2340 env->regwptr[UREG_I2] = sf_addr +
2341 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002342
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002343 /* 4. signal handler */
2344 env->pc = ka->_sa_handler;
2345 env->npc = (env->pc + 4);
2346 /* 5. return to kernel instructions */
2347 if (ka->sa_restorer) {
2348 env->regwptr[UREG_I7] = ka->sa_restorer;
2349 } else {
2350 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002351
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002352 env->regwptr[UREG_I7] = sf_addr +
2353 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002354
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002355 /* mov __NR_sigreturn, %g1 */
2356 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002357 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002358
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002359 /* t 0x10 */
2360 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002361 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002362 if (err)
2363 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002364
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002365 /* Flush instruction space. */
2366 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2367 // tb_flush(env);
2368 }
2369 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2370 return;
bellard459a4012007-11-11 19:45:10 +00002371#if 0
2372sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002373 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002374#endif
bellard6d5e2162004-09-30 22:04:13 +00002375sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002376 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2377 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002378}
bellard6d5e2162004-09-30 22:04:13 +00002379
pbrook624f7972008-05-31 16:11:38 +00002380static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002381 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002382 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002383{
2384 fprintf(stderr, "setup_rt_frame: not implemented\n");
2385}
2386
Andreas Färber05390242012-02-25 03:37:53 +01002387long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002388{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002389 abi_ulong sf_addr;
2390 struct target_signal_frame *sf;
2391 uint32_t up_psr, pc, npc;
2392 target_sigset_t set;
2393 sigset_t host_set;
2394 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002395
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002396 sf_addr = env->regwptr[UREG_FP];
2397 trace_user_do_sigreturn(env, sf_addr);
2398 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2399 goto segv_and_exit;
2400 }
bellard6d5e2162004-09-30 22:04:13 +00002401
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002402 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002403
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002404 if (sf_addr & 3)
2405 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002406
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002407 __get_user(pc, &sf->info.si_regs.pc);
2408 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002409
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002410 if ((pc | npc) & 3) {
2411 goto segv_and_exit;
2412 }
bellard6d5e2162004-09-30 22:04:13 +00002413
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002414 /* 2. Restore the state */
2415 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002416
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002417 /* User can only change condition codes and FPU enabling in %psr. */
2418 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2419 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002420
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002421 env->pc = pc;
2422 env->npc = npc;
2423 __get_user(env->y, &sf->info.si_regs.y);
2424 for (i=0; i < 8; i++) {
2425 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2426 }
2427 for (i=0; i < 8; i++) {
2428 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2429 }
bellard6d5e2162004-09-30 22:04:13 +00002430
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002431 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002432 * __get_user(fpu_save, &sf->fpu_save);
2433 * if (fpu_save)
2434 * err |= restore_fpu_state(env, fpu_save);
2435 */
bellard6d5e2162004-09-30 22:04:13 +00002436
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002437 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00002438 * the races which exist anyways.
2439 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002440 __get_user(set.sig[0], &sf->info.si_mask);
2441 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2442 __get_user(set.sig[i], &sf->extramask[i - 1]);
2443 }
bellarde80cfcf2004-12-19 23:18:01 +00002444
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002445 target_to_host_sigset_internal(&host_set, &set);
2446 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard6d5e2162004-09-30 22:04:13 +00002447
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002448 if (err) {
2449 goto segv_and_exit;
2450 }
2451 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01002452 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002453
2454segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002455 unlock_user_struct(sf, sf_addr, 0);
2456 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002457}
2458
Andreas Färber05390242012-02-25 03:37:53 +01002459long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002460{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002461 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00002462 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002463 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002464}
2465
bellard459a4012007-11-11 19:45:10 +00002466#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
blueswir15bfb56b2007-10-05 17:01:51 +00002467#define MC_TSTATE 0
2468#define MC_PC 1
2469#define MC_NPC 2
2470#define MC_Y 3
2471#define MC_G1 4
2472#define MC_G2 5
2473#define MC_G3 6
2474#define MC_G4 7
2475#define MC_G5 8
2476#define MC_G6 9
2477#define MC_G7 10
2478#define MC_O0 11
2479#define MC_O1 12
2480#define MC_O2 13
2481#define MC_O3 14
2482#define MC_O4 15
2483#define MC_O5 16
2484#define MC_O6 17
2485#define MC_O7 18
2486#define MC_NGREG 19
2487
Anthony Liguoric227f092009-10-01 16:12:16 -05002488typedef abi_ulong target_mc_greg_t;
2489typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002490
2491struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002492 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002493 uint32_t mcfq_insn;
2494};
2495
2496struct target_mc_fpu {
2497 union {
2498 uint32_t sregs[32];
2499 uint64_t dregs[32];
2500 //uint128_t qregs[16];
2501 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002502 abi_ulong mcfpu_fsr;
2503 abi_ulong mcfpu_fprs;
2504 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002505 struct target_mc_fq *mcfpu_fq;
2506 unsigned char mcfpu_qcnt;
2507 unsigned char mcfpu_qentsz;
2508 unsigned char mcfpu_enab;
2509};
Anthony Liguoric227f092009-10-01 16:12:16 -05002510typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002511
2512typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002513 target_mc_gregset_t mc_gregs;
2514 target_mc_greg_t mc_fp;
2515 target_mc_greg_t mc_i7;
2516 target_mc_fpu_t mc_fpregs;
2517} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002518
2519struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002520 struct target_ucontext *tuc_link;
2521 abi_ulong tuc_flags;
2522 target_sigset_t tuc_sigmask;
2523 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002524};
2525
2526/* A V9 register window */
2527struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002528 abi_ulong locals[8];
2529 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002530};
2531
2532#define TARGET_STACK_BIAS 2047
2533
2534/* {set, get}context() needed for 64-bit SparcLinux userland. */
2535void sparc64_set_context(CPUSPARCState *env)
2536{
bellard459a4012007-11-11 19:45:10 +00002537 abi_ulong ucp_addr;
2538 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002539 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002540 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002541 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002542 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002543
bellard459a4012007-11-11 19:45:10 +00002544 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002545 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00002546 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002547 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02002548 grp = &ucp->tuc_mcontext.mc_gregs;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002549 __get_user(pc, &((*grp)[MC_PC]));
2550 __get_user(npc, &((*grp)[MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002551 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00002552 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002553 }
blueswir15bfb56b2007-10-05 17:01:51 +00002554 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002555 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002556 sigset_t set;
2557
2558 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002559 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002560 } else {
bellard459a4012007-11-11 19:45:10 +00002561 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002562 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002563 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002564 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002565 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002566 }
blueswir15bfb56b2007-10-05 17:01:51 +00002567 }
2568 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002569 do_sigprocmask(SIG_SETMASK, &set, NULL);
blueswir15bfb56b2007-10-05 17:01:51 +00002570 }
2571 env->pc = pc;
2572 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002573 __get_user(env->y, &((*grp)[MC_Y]));
2574 __get_user(tstate, &((*grp)[MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002575 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002576 cpu_put_ccr(env, tstate >> 32);
2577 cpu_put_cwp64(env, tstate & 0x1f);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002578 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2579 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2580 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2581 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2582 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2583 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2584 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2585 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2586 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2587 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2588 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2589 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2590 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2591 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2592 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002593
Riku Voipio1d8b5122014-04-23 10:26:05 +03002594 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2595 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002596
bellard459a4012007-11-11 19:45:10 +00002597 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002598 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2599 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002600 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002601 }
2602 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2603 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002604 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002605 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01002606 /* FIXME this does not match how the kernel handles the FPU in
2607 * its sparc64_set_context implementation. In particular the FPU
2608 * is only restored if fenab is non-zero in:
2609 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2610 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002611 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002612 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002613 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2614 for (i = 0; i < 64; i++, src++) {
2615 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002616 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002617 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002618 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002619 }
2620 }
bellard459a4012007-11-11 19:45:10 +00002621 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002622 __get_user(env->fsr,
2623 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2624 __get_user(env->gsr,
2625 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002626 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002627 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002628do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002629 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002630 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002631}
2632
2633void sparc64_get_context(CPUSPARCState *env)
2634{
bellard459a4012007-11-11 19:45:10 +00002635 abi_ulong ucp_addr;
2636 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002637 target_mc_gregset_t *grp;
2638 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002639 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002640 int err;
2641 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002642 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002643 sigset_t set;
2644
bellard459a4012007-11-11 19:45:10 +00002645 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002646 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00002647 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002648 }
bellard459a4012007-11-11 19:45:10 +00002649
Aurelien Jarno60e99242010-03-29 02:12:51 +02002650 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002651 grp = &mcp->mc_gregs;
2652
2653 /* Skip over the trap instruction, first. */
2654 env->pc = env->npc;
2655 env->npc += 4;
2656
2657 err = 0;
2658
Alex Barcelo1c275922014-03-14 14:36:55 +00002659 do_sigprocmask(0, NULL, &set);
blueswir15bfb56b2007-10-05 17:01:51 +00002660 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00002661 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002662 __put_user(target_set.sig[0],
2663 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00002664 } else {
2665 abi_ulong *src, *dst;
2666 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002667 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002668 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002669 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002670 }
blueswir15bfb56b2007-10-05 17:01:51 +00002671 if (err)
2672 goto do_sigsegv;
2673 }
2674
bellard459a4012007-11-11 19:45:10 +00002675 /* XXX: tstate must be saved properly */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002676 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2677 __put_user(env->pc, &((*grp)[MC_PC]));
2678 __put_user(env->npc, &((*grp)[MC_NPC]));
2679 __put_user(env->y, &((*grp)[MC_Y]));
2680 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2681 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2682 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2683 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2684 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2685 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2686 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2687 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2688 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2689 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2690 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2691 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2692 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2693 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2694 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002695
bellard459a4012007-11-11 19:45:10 +00002696 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2697 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002698 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2699 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002700 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002701 }
2702 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2703 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002704 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002705 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002706 __put_user(fp, &(mcp->mc_fp));
2707 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002708
bellard459a4012007-11-11 19:45:10 +00002709 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002710 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2711 for (i = 0; i < 64; i++, dst++) {
2712 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002713 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002714 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002715 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002716 }
2717 }
bellard459a4012007-11-11 19:45:10 +00002718 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002719 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2720 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2721 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00002722
2723 if (err)
2724 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00002725 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00002726 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002727do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002728 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02002729 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002730}
2731#endif
Richard Hendersonff970902013-02-10 10:30:42 -08002732#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00002733
Richard Hendersonff970902013-02-10 10:30:42 -08002734# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00002735struct target_sigcontext {
2736 uint32_t sc_regmask; /* Unused */
2737 uint32_t sc_status;
2738 uint64_t sc_pc;
2739 uint64_t sc_regs[32];
2740 uint64_t sc_fpregs[32];
2741 uint32_t sc_ownedfp; /* Unused */
2742 uint32_t sc_fpc_csr;
2743 uint32_t sc_fpc_eir; /* Unused */
2744 uint32_t sc_used_math;
2745 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01002746 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00002747 uint64_t sc_mdhi;
2748 uint64_t sc_mdlo;
2749 target_ulong sc_hi1; /* Was sc_cause */
2750 target_ulong sc_lo1; /* Was sc_badvaddr */
2751 target_ulong sc_hi2; /* Was sc_sigset[4] */
2752 target_ulong sc_lo2;
2753 target_ulong sc_hi3;
2754 target_ulong sc_lo3;
2755};
Richard Hendersonff970902013-02-10 10:30:42 -08002756# else /* N32 || N64 */
2757struct target_sigcontext {
2758 uint64_t sc_regs[32];
2759 uint64_t sc_fpregs[32];
2760 uint64_t sc_mdhi;
2761 uint64_t sc_hi1;
2762 uint64_t sc_hi2;
2763 uint64_t sc_hi3;
2764 uint64_t sc_mdlo;
2765 uint64_t sc_lo1;
2766 uint64_t sc_lo2;
2767 uint64_t sc_lo3;
2768 uint64_t sc_pc;
2769 uint32_t sc_fpc_csr;
2770 uint32_t sc_used_math;
2771 uint32_t sc_dsp;
2772 uint32_t sc_reserved;
2773};
2774# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00002775
2776struct sigframe {
2777 uint32_t sf_ass[4]; /* argument save space for o32 */
2778 uint32_t sf_code[2]; /* signal trampoline */
2779 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002780 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00002781};
2782
pbrook0b1bcb02009-04-21 01:41:10 +00002783struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002784 target_ulong tuc_flags;
2785 target_ulong tuc_link;
2786 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01002787 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002788 struct target_sigcontext tuc_mcontext;
2789 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00002790};
2791
2792struct target_rt_sigframe {
2793 uint32_t rs_ass[4]; /* argument save space for o32 */
2794 uint32_t rs_code[2]; /* signal trampoline */
2795 struct target_siginfo rs_info;
2796 struct target_ucontext rs_uc;
2797};
2798
bellard106ec872006-06-27 21:08:10 +00002799/* Install trampoline to jump back from signal handler */
2800static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2801{
Richard Henderson084d0492013-02-10 10:30:44 -08002802 int err = 0;
bellard106ec872006-06-27 21:08:10 +00002803
2804 /*
Richard Henderson084d0492013-02-10 10:30:44 -08002805 * Set up the return code ...
2806 *
2807 * li v0, __NR__foo_sigreturn
2808 * syscall
2809 */
bellard106ec872006-06-27 21:08:10 +00002810
Riku Voipio1d8b5122014-04-23 10:26:05 +03002811 __put_user(0x24020000 + syscall, tramp + 0);
2812 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00002813 return err;
2814}
2815
Riku Voipio41ecc722014-04-23 11:01:00 +03002816static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002817 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002818{
Richard Henderson084d0492013-02-10 10:30:44 -08002819 int i;
bellard106ec872006-06-27 21:08:10 +00002820
Riku Voipio1d8b5122014-04-23 10:26:05 +03002821 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07002822 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00002823
Richard Henderson084d0492013-02-10 10:30:44 -08002824 __put_user(0, &sc->sc_regs[0]);
2825 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002826 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002827 }
bellard106ec872006-06-27 21:08:10 +00002828
Riku Voipio1d8b5122014-04-23 10:26:05 +03002829 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2830 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002831
Richard Henderson084d0492013-02-10 10:30:44 -08002832 /* Rather than checking for dsp existence, always copy. The storage
2833 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002834 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2835 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2836 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2837 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2838 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2839 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002840 {
2841 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002842 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00002843 }
Richard Henderson084d0492013-02-10 10:30:44 -08002844
Riku Voipio1d8b5122014-04-23 10:26:05 +03002845 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08002846
2847 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002848 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00002849 }
bellard106ec872006-06-27 21:08:10 +00002850}
2851
Riku Voipio016d2e12014-04-23 11:19:48 +03002852static inline void
Andreas Färber05390242012-02-25 03:37:53 +01002853restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002854{
Richard Henderson084d0492013-02-10 10:30:44 -08002855 int i;
bellard106ec872006-06-27 21:08:10 +00002856
Riku Voipio1d8b5122014-04-23 10:26:05 +03002857 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00002858
Riku Voipio1d8b5122014-04-23 10:26:05 +03002859 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2860 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002861
Richard Henderson084d0492013-02-10 10:30:44 -08002862 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002863 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00002864 }
2865
Riku Voipio1d8b5122014-04-23 10:26:05 +03002866 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2867 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2868 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2869 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2870 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2871 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002872 {
2873 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002874 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08002875 cpu_wrdsp(dsp, 0x3ff, regs);
2876 }
2877
2878 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002879 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002880 }
bellard106ec872006-06-27 21:08:10 +00002881}
Richard Hendersonff970902013-02-10 10:30:42 -08002882
bellard106ec872006-06-27 21:08:10 +00002883/*
2884 * Determine which stack to use..
2885 */
bellard579a97f2007-11-11 14:26:47 +00002886static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002887get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00002888{
2889 unsigned long sp;
2890
2891 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00002892 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00002893
2894 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01002895 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00002896 * above the user stack, 16-bytes before the next lowest
2897 * 16 byte boundary. Try to avoid trashing it.
2898 */
2899 sp -= 32;
2900
bellard106ec872006-06-27 21:08:10 +00002901 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00002902 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00002903 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2904 }
bellard106ec872006-06-27 21:08:10 +00002905
bellard579a97f2007-11-11 14:26:47 +00002906 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00002907}
2908
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002909static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
2910{
2911 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
2912 env->hflags &= ~MIPS_HFLAG_M16;
2913 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
2914 env->active_tc.PC &= ~(target_ulong) 1;
2915 }
2916}
2917
Richard Hendersonff970902013-02-10 10:30:42 -08002918# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00002919/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002920static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01002921 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002922{
2923 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002924 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00002925 int i;
2926
bellard579a97f2007-11-11 14:26:47 +00002927 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002928 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002929 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
2930 goto give_sigsegv;
2931 }
bellard106ec872006-06-27 21:08:10 +00002932
2933 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2934
Riku Voipio41ecc722014-04-23 11:01:00 +03002935 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002936
2937 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03002938 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00002939 }
2940
2941 /*
2942 * Arguments to signal handler:
2943 *
2944 * a0 = signal number
2945 * a1 = 0 (should be cause)
2946 * a2 = pointer to struct sigcontext
2947 *
2948 * $25 and PC point to the signal handler, $29 points to the
2949 * struct sigframe.
2950 */
thsb5dc7732008-06-27 10:02:35 +00002951 regs->active_tc.gpr[ 4] = sig;
2952 regs->active_tc.gpr[ 5] = 0;
2953 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2954 regs->active_tc.gpr[29] = frame_addr;
2955 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00002956 /* The original kernel code sets CP0_EPC to the handler
2957 * since it returns to userland using eret
2958 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00002959 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002960 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00002961 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00002962 return;
2963
2964give_sigsegv:
2965 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00002966}
2967
Andreas Färber05390242012-02-25 03:37:53 +01002968long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002969{
ths388bb212007-05-13 13:58:00 +00002970 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002971 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00002972 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05002973 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00002974 int i;
bellard106ec872006-06-27 21:08:10 +00002975
thsb5dc7732008-06-27 10:02:35 +00002976 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002977 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00002978 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002979 goto badframe;
bellard106ec872006-06-27 21:08:10 +00002980
ths388bb212007-05-13 13:58:00 +00002981 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03002982 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00002983 }
bellard106ec872006-06-27 21:08:10 +00002984
ths388bb212007-05-13 13:58:00 +00002985 target_to_host_sigset_internal(&blocked, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002986 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
bellard106ec872006-06-27 21:08:10 +00002987
Riku Voipio016d2e12014-04-23 11:19:48 +03002988 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002989
2990#if 0
ths388bb212007-05-13 13:58:00 +00002991 /*
2992 * Don't let your children do this ...
2993 */
2994 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00002995 "move\t$29, %0\n\t"
2996 "j\tsyscall_exit"
2997 :/* no outputs */
2998 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00002999 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003000#endif
ths3b46e622007-09-17 08:09:54 +00003001
thsb5dc7732008-06-27 10:02:35 +00003002 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003003 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003004 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003005 * maybe a problem with nested signals ? */
3006 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003007 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003008
3009badframe:
ths388bb212007-05-13 13:58:00 +00003010 force_sig(TARGET_SIGSEGV/*, current*/);
3011 return 0;
bellard106ec872006-06-27 21:08:10 +00003012}
Richard Hendersonff970902013-02-10 10:30:42 -08003013# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003014
pbrook624f7972008-05-31 16:11:38 +00003015static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003016 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003017 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003018{
pbrook0b1bcb02009-04-21 01:41:10 +00003019 struct target_rt_sigframe *frame;
3020 abi_ulong frame_addr;
3021 int i;
3022
3023 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003024 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003025 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3026 goto give_sigsegv;
3027 }
pbrook0b1bcb02009-04-21 01:41:10 +00003028
3029 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3030
Peter Maydellf6c7a052015-01-08 12:19:48 +00003031 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003032
Aurelien Jarno60e99242010-03-29 02:12:51 +02003033 __put_user(0, &frame->rs_uc.tuc_flags);
3034 __put_user(0, &frame->rs_uc.tuc_link);
3035 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3036 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003037 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003038 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003039
Aurelien Jarno60e99242010-03-29 02:12:51 +02003040 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003041
3042 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003043 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003044 }
3045
3046 /*
3047 * Arguments to signal handler:
3048 *
3049 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003050 * a1 = pointer to siginfo_t
pbrook0b1bcb02009-04-21 01:41:10 +00003051 * a2 = pointer to struct ucontext
3052 *
3053 * $25 and PC point to the signal handler, $29 points to the
3054 * struct sigframe.
3055 */
3056 env->active_tc.gpr[ 4] = sig;
3057 env->active_tc.gpr[ 5] = frame_addr
3058 + offsetof(struct target_rt_sigframe, rs_info);
3059 env->active_tc.gpr[ 6] = frame_addr
3060 + offsetof(struct target_rt_sigframe, rs_uc);
3061 env->active_tc.gpr[29] = frame_addr;
3062 env->active_tc.gpr[31] = frame_addr
3063 + offsetof(struct target_rt_sigframe, rs_code);
3064 /* The original kernel code sets CP0_EPC to the handler
3065 * since it returns to userland using eret
3066 * we cannot do this here, and we must set PC directly */
3067 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003068 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003069 unlock_user_struct(frame, frame_addr, 1);
3070 return;
3071
3072give_sigsegv:
3073 unlock_user_struct(frame, frame_addr, 1);
3074 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00003075}
3076
Andreas Färber05390242012-02-25 03:37:53 +01003077long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003078{
pbrook0b1bcb02009-04-21 01:41:10 +00003079 struct target_rt_sigframe *frame;
3080 abi_ulong frame_addr;
3081 sigset_t blocked;
3082
pbrook0b1bcb02009-04-21 01:41:10 +00003083 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003084 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003085 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3086 goto badframe;
3087 }
pbrook0b1bcb02009-04-21 01:41:10 +00003088
Aurelien Jarno60e99242010-03-29 02:12:51 +02003089 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00003090 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
pbrook0b1bcb02009-04-21 01:41:10 +00003091
Riku Voipio016d2e12014-04-23 11:19:48 +03003092 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003093
3094 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003095 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3096 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003097 goto badframe;
3098
3099 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003100 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003101 /* I am not sure this is right, but it seems to work
3102 * maybe a problem with nested signals ? */
3103 env->CP0_EPC = 0;
3104 return -TARGET_QEMU_ESIGRETURN;
3105
3106badframe:
3107 force_sig(TARGET_SIGSEGV/*, current*/);
3108 return 0;
bellard106ec872006-06-27 21:08:10 +00003109}
bellard6d5e2162004-09-30 22:04:13 +00003110
thsc3b5bc82007-12-02 06:31:25 +00003111#elif defined(TARGET_SH4)
3112
3113/*
3114 * code and data structures from linux kernel:
3115 * include/asm-sh/sigcontext.h
3116 * arch/sh/kernel/signal.c
3117 */
3118
3119struct target_sigcontext {
3120 target_ulong oldmask;
3121
3122 /* CPU registers */
3123 target_ulong sc_gregs[16];
3124 target_ulong sc_pc;
3125 target_ulong sc_pr;
3126 target_ulong sc_sr;
3127 target_ulong sc_gbr;
3128 target_ulong sc_mach;
3129 target_ulong sc_macl;
3130
3131 /* FPU registers */
3132 target_ulong sc_fpregs[16];
3133 target_ulong sc_xfpregs[16];
3134 unsigned int sc_fpscr;
3135 unsigned int sc_fpul;
3136 unsigned int sc_ownedfp;
3137};
3138
3139struct target_sigframe
3140{
3141 struct target_sigcontext sc;
3142 target_ulong extramask[TARGET_NSIG_WORDS-1];
3143 uint16_t retcode[3];
3144};
3145
3146
3147struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003148 target_ulong tuc_flags;
3149 struct target_ucontext *tuc_link;
3150 target_stack_t tuc_stack;
3151 struct target_sigcontext tuc_mcontext;
3152 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003153};
3154
3155struct target_rt_sigframe
3156{
3157 struct target_siginfo info;
3158 struct target_ucontext uc;
3159 uint16_t retcode[3];
3160};
3161
3162
3163#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3164#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3165
pbrook624f7972008-05-31 16:11:38 +00003166static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003167 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003168{
pbrook624f7972008-05-31 16:11:38 +00003169 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003170 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3171 }
3172
3173 return (sp - frame_size) & -8ul;
3174}
3175
Riku Voipio41ecc722014-04-23 11:01:00 +03003176static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003177 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003178{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003179 int i;
thsc3b5bc82007-12-02 06:31:25 +00003180
Riku Voipio1d8b5122014-04-23 10:26:05 +03003181#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003182 COPY(gregs[0]); COPY(gregs[1]);
3183 COPY(gregs[2]); COPY(gregs[3]);
3184 COPY(gregs[4]); COPY(gregs[5]);
3185 COPY(gregs[6]); COPY(gregs[7]);
3186 COPY(gregs[8]); COPY(gregs[9]);
3187 COPY(gregs[10]); COPY(gregs[11]);
3188 COPY(gregs[12]); COPY(gregs[13]);
3189 COPY(gregs[14]); COPY(gregs[15]);
3190 COPY(gbr); COPY(mach);
3191 COPY(macl); COPY(pr);
3192 COPY(sr); COPY(pc);
3193#undef COPY
3194
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003195 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003196 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003197 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003198 __put_user(regs->fpscr, &sc->sc_fpscr);
3199 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003200
3201 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003202 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003203}
3204
Timothy E Baldwinba412492016-05-12 18:47:35 +01003205static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003206{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003207 int i;
thsc3b5bc82007-12-02 06:31:25 +00003208
Riku Voipio1d8b5122014-04-23 10:26:05 +03003209#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003210 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003211 COPY(gregs[2]); COPY(gregs[3]);
3212 COPY(gregs[4]); COPY(gregs[5]);
3213 COPY(gregs[6]); COPY(gregs[7]);
3214 COPY(gregs[8]); COPY(gregs[9]);
3215 COPY(gregs[10]); COPY(gregs[11]);
3216 COPY(gregs[12]); COPY(gregs[13]);
3217 COPY(gregs[14]); COPY(gregs[15]);
3218 COPY(gbr); COPY(mach);
3219 COPY(macl); COPY(pr);
3220 COPY(sr); COPY(pc);
3221#undef COPY
3222
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003223 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003224 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003225 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003226 __get_user(regs->fpscr, &sc->sc_fpscr);
3227 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003228
3229 regs->tra = -1; /* disable syscall checks */
thsc3b5bc82007-12-02 06:31:25 +00003230}
3231
pbrook624f7972008-05-31 16:11:38 +00003232static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003233 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003234{
3235 struct target_sigframe *frame;
3236 abi_ulong frame_addr;
3237 int i;
thsc3b5bc82007-12-02 06:31:25 +00003238
3239 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003240 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003241 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3242 goto give_sigsegv;
3243 }
thsc3b5bc82007-12-02 06:31:25 +00003244
Riku Voipio41ecc722014-04-23 11:01:00 +03003245 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003246
3247 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003248 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003249 }
3250
3251 /* Set up to return from userspace. If provided, use a stub
3252 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003253 if (ka->sa_flags & TARGET_SA_RESTORER) {
3254 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003255 } else {
3256 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003257 abi_ulong retcode_addr = frame_addr +
3258 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003259 __put_user(MOVW(2), &frame->retcode[0]);
3260 __put_user(TRAP_NOARG, &frame->retcode[1]);
3261 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003262 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003263 }
3264
thsc3b5bc82007-12-02 06:31:25 +00003265 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003266 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003267 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003268 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003269 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003270 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003271
3272 unlock_user_struct(frame, frame_addr, 1);
3273 return;
3274
3275give_sigsegv:
3276 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003277 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003278}
3279
pbrook624f7972008-05-31 16:11:38 +00003280static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003281 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003282 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003283{
3284 struct target_rt_sigframe *frame;
3285 abi_ulong frame_addr;
3286 int i;
thsc3b5bc82007-12-02 06:31:25 +00003287
3288 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003289 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003290 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3291 goto give_sigsegv;
3292 }
thsc3b5bc82007-12-02 06:31:25 +00003293
Peter Maydellf6c7a052015-01-08 12:19:48 +00003294 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003295
3296 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003297 __put_user(0, &frame->uc.tuc_flags);
3298 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3299 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3300 &frame->uc.tuc_stack.ss_sp);
3301 __put_user(sas_ss_flags(regs->gregs[15]),
3302 &frame->uc.tuc_stack.ss_flags);
3303 __put_user(target_sigaltstack_used.ss_size,
3304 &frame->uc.tuc_stack.ss_size);
3305 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003306 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003307 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003308 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003309 }
3310
3311 /* Set up to return from userspace. If provided, use a stub
3312 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003313 if (ka->sa_flags & TARGET_SA_RESTORER) {
3314 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003315 } else {
3316 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003317 abi_ulong retcode_addr = frame_addr +
3318 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003319 __put_user(MOVW(2), &frame->retcode[0]);
3320 __put_user(TRAP_NOARG, &frame->retcode[1]);
3321 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003322 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003323 }
3324
thsc3b5bc82007-12-02 06:31:25 +00003325 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003326 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003327 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003328 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3329 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003330 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003331
3332 unlock_user_struct(frame, frame_addr, 1);
3333 return;
3334
3335give_sigsegv:
3336 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003337 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003338}
3339
Andreas Färber05390242012-02-25 03:37:53 +01003340long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003341{
3342 struct target_sigframe *frame;
3343 abi_ulong frame_addr;
3344 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003345 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003346 int i;
3347 int err = 0;
3348
thsc3b5bc82007-12-02 06:31:25 +00003349 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003350 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003351 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3352 goto badframe;
3353 }
thsc3b5bc82007-12-02 06:31:25 +00003354
Riku Voipio1d8b5122014-04-23 10:26:05 +03003355 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003356 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003357 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003358 }
3359
3360 if (err)
3361 goto badframe;
3362
3363 target_to_host_sigset_internal(&blocked, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00003364 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
thsc3b5bc82007-12-02 06:31:25 +00003365
Timothy E Baldwinba412492016-05-12 18:47:35 +01003366 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003367
3368 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003369 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003370
3371badframe:
3372 unlock_user_struct(frame, frame_addr, 0);
3373 force_sig(TARGET_SIGSEGV);
3374 return 0;
3375}
3376
Andreas Färber05390242012-02-25 03:37:53 +01003377long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003378{
3379 struct target_rt_sigframe *frame;
3380 abi_ulong frame_addr;
3381 sigset_t blocked;
3382
thsc3b5bc82007-12-02 06:31:25 +00003383 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003384 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003385 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3386 goto badframe;
3387 }
thsc3b5bc82007-12-02 06:31:25 +00003388
Aurelien Jarno60e99242010-03-29 02:12:51 +02003389 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00003390 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
thsc3b5bc82007-12-02 06:31:25 +00003391
Timothy E Baldwinba412492016-05-12 18:47:35 +01003392 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003393
3394 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003395 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3396 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00003397 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003398 }
thsc3b5bc82007-12-02 06:31:25 +00003399
3400 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003401 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003402
3403badframe:
3404 unlock_user_struct(frame, frame_addr, 0);
3405 force_sig(TARGET_SIGSEGV);
3406 return 0;
3407}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003408#elif defined(TARGET_MICROBLAZE)
3409
3410struct target_sigcontext {
3411 struct target_pt_regs regs; /* needs to be first */
3412 uint32_t oldmask;
3413};
3414
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003415struct target_stack_t {
3416 abi_ulong ss_sp;
3417 int ss_flags;
3418 unsigned int ss_size;
3419};
3420
3421struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003422 abi_ulong tuc_flags;
3423 abi_ulong tuc_link;
3424 struct target_stack_t tuc_stack;
3425 struct target_sigcontext tuc_mcontext;
3426 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003427};
3428
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003429/* Signal frames. */
3430struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003431 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003432 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3433 uint32_t tramp[2];
3434};
3435
3436struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003437 siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003438 struct ucontext uc;
3439 uint32_t tramp[2];
3440};
3441
Andreas Färber05390242012-02-25 03:37:53 +01003442static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003443{
3444 __put_user(env->regs[0], &sc->regs.r0);
3445 __put_user(env->regs[1], &sc->regs.r1);
3446 __put_user(env->regs[2], &sc->regs.r2);
3447 __put_user(env->regs[3], &sc->regs.r3);
3448 __put_user(env->regs[4], &sc->regs.r4);
3449 __put_user(env->regs[5], &sc->regs.r5);
3450 __put_user(env->regs[6], &sc->regs.r6);
3451 __put_user(env->regs[7], &sc->regs.r7);
3452 __put_user(env->regs[8], &sc->regs.r8);
3453 __put_user(env->regs[9], &sc->regs.r9);
3454 __put_user(env->regs[10], &sc->regs.r10);
3455 __put_user(env->regs[11], &sc->regs.r11);
3456 __put_user(env->regs[12], &sc->regs.r12);
3457 __put_user(env->regs[13], &sc->regs.r13);
3458 __put_user(env->regs[14], &sc->regs.r14);
3459 __put_user(env->regs[15], &sc->regs.r15);
3460 __put_user(env->regs[16], &sc->regs.r16);
3461 __put_user(env->regs[17], &sc->regs.r17);
3462 __put_user(env->regs[18], &sc->regs.r18);
3463 __put_user(env->regs[19], &sc->regs.r19);
3464 __put_user(env->regs[20], &sc->regs.r20);
3465 __put_user(env->regs[21], &sc->regs.r21);
3466 __put_user(env->regs[22], &sc->regs.r22);
3467 __put_user(env->regs[23], &sc->regs.r23);
3468 __put_user(env->regs[24], &sc->regs.r24);
3469 __put_user(env->regs[25], &sc->regs.r25);
3470 __put_user(env->regs[26], &sc->regs.r26);
3471 __put_user(env->regs[27], &sc->regs.r27);
3472 __put_user(env->regs[28], &sc->regs.r28);
3473 __put_user(env->regs[29], &sc->regs.r29);
3474 __put_user(env->regs[30], &sc->regs.r30);
3475 __put_user(env->regs[31], &sc->regs.r31);
3476 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3477}
3478
Andreas Färber05390242012-02-25 03:37:53 +01003479static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003480{
3481 __get_user(env->regs[0], &sc->regs.r0);
3482 __get_user(env->regs[1], &sc->regs.r1);
3483 __get_user(env->regs[2], &sc->regs.r2);
3484 __get_user(env->regs[3], &sc->regs.r3);
3485 __get_user(env->regs[4], &sc->regs.r4);
3486 __get_user(env->regs[5], &sc->regs.r5);
3487 __get_user(env->regs[6], &sc->regs.r6);
3488 __get_user(env->regs[7], &sc->regs.r7);
3489 __get_user(env->regs[8], &sc->regs.r8);
3490 __get_user(env->regs[9], &sc->regs.r9);
3491 __get_user(env->regs[10], &sc->regs.r10);
3492 __get_user(env->regs[11], &sc->regs.r11);
3493 __get_user(env->regs[12], &sc->regs.r12);
3494 __get_user(env->regs[13], &sc->regs.r13);
3495 __get_user(env->regs[14], &sc->regs.r14);
3496 __get_user(env->regs[15], &sc->regs.r15);
3497 __get_user(env->regs[16], &sc->regs.r16);
3498 __get_user(env->regs[17], &sc->regs.r17);
3499 __get_user(env->regs[18], &sc->regs.r18);
3500 __get_user(env->regs[19], &sc->regs.r19);
3501 __get_user(env->regs[20], &sc->regs.r20);
3502 __get_user(env->regs[21], &sc->regs.r21);
3503 __get_user(env->regs[22], &sc->regs.r22);
3504 __get_user(env->regs[23], &sc->regs.r23);
3505 __get_user(env->regs[24], &sc->regs.r24);
3506 __get_user(env->regs[25], &sc->regs.r25);
3507 __get_user(env->regs[26], &sc->regs.r26);
3508 __get_user(env->regs[27], &sc->regs.r27);
3509 __get_user(env->regs[28], &sc->regs.r28);
3510 __get_user(env->regs[29], &sc->regs.r29);
3511 __get_user(env->regs[30], &sc->regs.r30);
3512 __get_user(env->regs[31], &sc->regs.r31);
3513 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3514}
3515
3516static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003517 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003518{
3519 abi_ulong sp = env->regs[1];
3520
Riku Voipiob545f632014-07-15 17:01:55 +03003521 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003522 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003523 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003524
3525 return ((sp - frame_size) & -8UL);
3526}
3527
3528static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003529 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003530{
3531 struct target_signal_frame *frame;
3532 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003533 int i;
3534
3535 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003536 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003537 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3538 goto badframe;
3539
3540 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003541 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003542
3543 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003544 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003545 }
3546
Richard Hendersonf711df62010-11-22 14:57:52 -08003547 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003548
3549 /* Set up to return from userspace. If provided, use a stub
3550 already in userspace. */
3551 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3552 if (ka->sa_flags & TARGET_SA_RESTORER) {
3553 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3554 } else {
3555 uint32_t t;
3556 /* Note, these encodings are _big endian_! */
3557 /* addi r12, r0, __NR_sigreturn */
3558 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003559 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003560 /* brki r14, 0x8 */
3561 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003562 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003563
3564 /* Return from sighandler will jump to the tramp.
3565 Negative 8 offset because return is rtsd r15, 8 */
3566 env->regs[15] = ((unsigned long)frame->tramp) - 8;
3567 }
3568
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003569 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003570 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003571 /* Signal handler args: */
3572 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02003573 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003574 /* arg 1: sigcontext */
3575 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003576
3577 /* Offset of 4 to handle microblaze rtid r14, 0 */
3578 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3579
3580 unlock_user_struct(frame, frame_addr, 1);
3581 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003582badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003583 force_sig(TARGET_SIGSEGV);
3584}
3585
3586static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003587 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003588 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003589{
3590 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3591}
3592
Andreas Färber05390242012-02-25 03:37:53 +01003593long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003594{
3595 struct target_signal_frame *frame;
3596 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003597 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003598 sigset_t set;
3599 int i;
3600
3601 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003602 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003603 /* Make sure the guest isn't playing games. */
3604 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3605 goto badframe;
3606
3607 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003608 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003609 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003610 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003611 }
3612 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00003613 do_sigprocmask(SIG_SETMASK, &set, NULL);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003614
Richard Hendersonf711df62010-11-22 14:57:52 -08003615 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003616 /* We got here through a sigreturn syscall, our path back is via an
3617 rtb insn so setup r14 for that. */
3618 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003619
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003620 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01003621 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003622badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003623 force_sig(TARGET_SIGSEGV);
3624}
3625
Andreas Färber05390242012-02-25 03:37:53 +01003626long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003627{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003628 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003629 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3630 return -TARGET_ENOSYS;
3631}
3632
edgar_iglb6d3abd2008-02-28 11:29:27 +00003633#elif defined(TARGET_CRIS)
3634
3635struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003636 struct target_pt_regs regs; /* needs to be first */
3637 uint32_t oldmask;
3638 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003639};
3640
3641/* Signal frames. */
3642struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003643 struct target_sigcontext sc;
3644 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3645 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003646};
3647
3648struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003649 siginfo_t *pinfo;
3650 void *puc;
3651 siginfo_t info;
3652 struct ucontext uc;
3653 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003654};
3655
Andreas Färber05390242012-02-25 03:37:53 +01003656static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003657{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003658 __put_user(env->regs[0], &sc->regs.r0);
3659 __put_user(env->regs[1], &sc->regs.r1);
3660 __put_user(env->regs[2], &sc->regs.r2);
3661 __put_user(env->regs[3], &sc->regs.r3);
3662 __put_user(env->regs[4], &sc->regs.r4);
3663 __put_user(env->regs[5], &sc->regs.r5);
3664 __put_user(env->regs[6], &sc->regs.r6);
3665 __put_user(env->regs[7], &sc->regs.r7);
3666 __put_user(env->regs[8], &sc->regs.r8);
3667 __put_user(env->regs[9], &sc->regs.r9);
3668 __put_user(env->regs[10], &sc->regs.r10);
3669 __put_user(env->regs[11], &sc->regs.r11);
3670 __put_user(env->regs[12], &sc->regs.r12);
3671 __put_user(env->regs[13], &sc->regs.r13);
3672 __put_user(env->regs[14], &sc->usp);
3673 __put_user(env->regs[15], &sc->regs.acr);
3674 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3675 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3676 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003677}
edgar_igl9664d922008-03-03 22:23:53 +00003678
Andreas Färber05390242012-02-25 03:37:53 +01003679static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003680{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003681 __get_user(env->regs[0], &sc->regs.r0);
3682 __get_user(env->regs[1], &sc->regs.r1);
3683 __get_user(env->regs[2], &sc->regs.r2);
3684 __get_user(env->regs[3], &sc->regs.r3);
3685 __get_user(env->regs[4], &sc->regs.r4);
3686 __get_user(env->regs[5], &sc->regs.r5);
3687 __get_user(env->regs[6], &sc->regs.r6);
3688 __get_user(env->regs[7], &sc->regs.r7);
3689 __get_user(env->regs[8], &sc->regs.r8);
3690 __get_user(env->regs[9], &sc->regs.r9);
3691 __get_user(env->regs[10], &sc->regs.r10);
3692 __get_user(env->regs[11], &sc->regs.r11);
3693 __get_user(env->regs[12], &sc->regs.r12);
3694 __get_user(env->regs[13], &sc->regs.r13);
3695 __get_user(env->regs[14], &sc->usp);
3696 __get_user(env->regs[15], &sc->regs.acr);
3697 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3698 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3699 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003700}
3701
Andreas Färber05390242012-02-25 03:37:53 +01003702static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003703{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003704 abi_ulong sp;
3705 /* Align the stack downwards to 4. */
3706 sp = (env->regs[R_SP] & ~3);
3707 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003708}
3709
pbrook624f7972008-05-31 16:11:38 +00003710static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003711 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003712{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003713 struct target_signal_frame *frame;
3714 abi_ulong frame_addr;
3715 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003716
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003717 frame_addr = get_sigframe(env, sizeof *frame);
3718 trace_user_setup_frame(env, frame_addr);
3719 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3720 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003721
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003722 /*
3723 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3724 * use this trampoline anymore but it sets it up for GDB.
3725 * In QEMU, using the trampoline simplifies things a bit so we use it.
3726 *
3727 * This is movu.w __NR_sigreturn, r9; break 13;
3728 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003729 __put_user(0x9c5f, frame->retcode+0);
3730 __put_user(TARGET_NR_sigreturn,
3731 frame->retcode + 1);
3732 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003733
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003734 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003735 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003736
Riku Voipio0188fad2014-04-23 13:34:15 +03003737 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3738 __put_user(set->sig[i], &frame->extramask[i - 1]);
3739 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003740
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003741 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003742
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003743 /* Move the stack and setup the arguments for the handler. */
3744 env->regs[R_SP] = frame_addr;
3745 env->regs[10] = sig;
3746 env->pc = (unsigned long) ka->_sa_handler;
3747 /* Link SRP so the guest returns through the trampoline. */
3748 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003749
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003750 unlock_user_struct(frame, frame_addr, 1);
3751 return;
3752badframe:
3753 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003754}
3755
pbrook624f7972008-05-31 16:11:38 +00003756static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003757 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003758 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003759{
3760 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3761}
3762
Andreas Färber05390242012-02-25 03:37:53 +01003763long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003764{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003765 struct target_signal_frame *frame;
3766 abi_ulong frame_addr;
3767 target_sigset_t target_set;
3768 sigset_t set;
3769 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003770
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003771 frame_addr = env->regs[R_SP];
3772 trace_user_do_sigreturn(env, frame_addr);
3773 /* Make sure the guest isn't playing games. */
3774 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
3775 goto badframe;
3776 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003777
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003778 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003779 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003780 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003781 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003782 }
3783 target_to_host_sigset_internal(&set, &target_set);
3784 do_sigprocmask(SIG_SETMASK, &set, NULL);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003785
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003786 restore_sigcontext(&frame->sc, env);
3787 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01003788 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003789badframe:
3790 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003791}
3792
Andreas Färber05390242012-02-25 03:37:53 +01003793long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003794{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003795 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003796 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3797 return -TARGET_ENOSYS;
3798}
thsc3b5bc82007-12-02 06:31:25 +00003799
Jia Liud9627832012-07-20 15:50:52 +08003800#elif defined(TARGET_OPENRISC)
3801
3802struct target_sigcontext {
3803 struct target_pt_regs regs;
3804 abi_ulong oldmask;
3805 abi_ulong usp;
3806};
3807
3808struct target_ucontext {
3809 abi_ulong tuc_flags;
3810 abi_ulong tuc_link;
3811 target_stack_t tuc_stack;
3812 struct target_sigcontext tuc_mcontext;
3813 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3814};
3815
3816struct target_rt_sigframe {
3817 abi_ulong pinfo;
3818 uint64_t puc;
3819 struct target_siginfo info;
3820 struct target_sigcontext sc;
3821 struct target_ucontext uc;
3822 unsigned char retcode[16]; /* trampoline code */
3823};
3824
3825/* This is the asm-generic/ucontext.h version */
3826#if 0
3827static int restore_sigcontext(CPUOpenRISCState *regs,
3828 struct target_sigcontext *sc)
3829{
3830 unsigned int err = 0;
3831 unsigned long old_usp;
3832
3833 /* Alwys make any pending restarted system call return -EINTR */
3834 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3835
3836 /* restore the regs from &sc->regs (same as sc, since regs is first)
3837 * (sc is already checked for VERIFY_READ since the sigframe was
3838 * checked in sys_sigreturn previously)
3839 */
3840
3841 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3842 goto badframe;
3843 }
3844
3845 /* make sure the U-flag is set so user-mode cannot fool us */
3846
3847 regs->sr &= ~SR_SM;
3848
3849 /* restore the old USP as it was before we stacked the sc etc.
3850 * (we cannot just pop the sigcontext since we aligned the sp and
3851 * stuff after pushing it)
3852 */
3853
Riku Voipio1d8b5122014-04-23 10:26:05 +03003854 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003855 phx_signal("old_usp 0x%lx", old_usp);
3856
3857 __PHX__ REALLY /* ??? */
3858 wrusp(old_usp);
3859 regs->gpr[1] = old_usp;
3860
3861 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3862 * after this completes, but we don't use that mechanism. maybe we can
3863 * use it now ?
3864 */
3865
3866 return err;
3867
3868badframe:
3869 return 1;
3870}
3871#endif
3872
3873/* Set up a signal frame. */
3874
Riku Voipio41ecc722014-04-23 11:01:00 +03003875static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003876 CPUOpenRISCState *regs,
3877 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08003878{
Jia Liud9627832012-07-20 15:50:52 +08003879 unsigned long usp = regs->gpr[1];
3880
3881 /* copy the regs. they are first in sc so we can use sc directly */
3882
Riku Voipio1d8b5122014-04-23 10:26:05 +03003883 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08003884
3885 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3886 the signal handler. The frametype will be restored to its previous
3887 value in restore_sigcontext. */
3888 /*regs->frametype = CRIS_FRAME_NORMAL;*/
3889
3890 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003891 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03003892 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003893}
3894
3895static inline unsigned long align_sigframe(unsigned long sp)
3896{
3897 unsigned long i;
3898 i = sp & ~3UL;
3899 return i;
3900}
3901
3902static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3903 CPUOpenRISCState *regs,
3904 size_t frame_size)
3905{
3906 unsigned long sp = regs->gpr[1];
3907 int onsigstack = on_sig_stack(sp);
3908
3909 /* redzone */
3910 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03003911 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08003912 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3913 }
3914
3915 sp = align_sigframe(sp - frame_size);
3916
3917 /*
3918 * If we are on the alternate signal stack and would overflow it, don't.
3919 * Return an always-bogus address instead so we will die with SIGSEGV.
3920 */
3921
3922 if (onsigstack && !likely(on_sig_stack(sp))) {
3923 return -1L;
3924 }
3925
3926 return sp;
3927}
3928
Jia Liud9627832012-07-20 15:50:52 +08003929static void setup_rt_frame(int sig, struct target_sigaction *ka,
3930 target_siginfo_t *info,
3931 target_sigset_t *set, CPUOpenRISCState *env)
3932{
3933 int err = 0;
3934 abi_ulong frame_addr;
3935 unsigned long return_ip;
3936 struct target_rt_sigframe *frame;
3937 abi_ulong info_addr, uc_addr;
3938
Jia Liud9627832012-07-20 15:50:52 +08003939 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003940 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08003941 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3942 goto give_sigsegv;
3943 }
3944
3945 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003946 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08003947 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003948 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08003949
3950 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00003951 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08003952 }
3953
3954 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03003955 __put_user(0, &frame->uc.tuc_flags);
3956 __put_user(0, &frame->uc.tuc_link);
3957 __put_user(target_sigaltstack_used.ss_sp,
3958 &frame->uc.tuc_stack.ss_sp);
3959 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
3960 __put_user(target_sigaltstack_used.ss_size,
3961 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03003962 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08003963
3964 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
3965
Jia Liud9627832012-07-20 15:50:52 +08003966 /* trampoline - the desired return ip is the retcode itself */
3967 return_ip = (unsigned long)&frame->retcode;
3968 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003969 __put_user(0xa960, (short *)(frame->retcode + 0));
3970 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
3971 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
3972 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08003973
3974 if (err) {
3975 goto give_sigsegv;
3976 }
3977
3978 /* TODO what is the current->exec_domain stuff and invmap ? */
3979
3980 /* Set up registers for signal handler */
3981 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
3982 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
3983 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
3984 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
3985 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
3986
3987 /* actually move the usp to reflect the stacked frame */
3988 env->gpr[1] = (unsigned long)frame;
3989
3990 return;
3991
3992give_sigsegv:
3993 unlock_user_struct(frame, frame_addr, 1);
3994 if (sig == TARGET_SIGSEGV) {
3995 ka->_sa_handler = TARGET_SIG_DFL;
3996 }
3997 force_sig(TARGET_SIGSEGV);
3998}
3999
4000long do_sigreturn(CPUOpenRISCState *env)
4001{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004002 trace_user_do_sigreturn(env, 0);
4003 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004004 return -TARGET_ENOSYS;
4005}
4006
4007long do_rt_sigreturn(CPUOpenRISCState *env)
4008{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004009 trace_user_do_rt_sigreturn(env, 0);
4010 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004011 return -TARGET_ENOSYS;
4012}
4013/* TARGET_OPENRISC */
4014
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004015#elif defined(TARGET_S390X)
4016
4017#define __NUM_GPRS 16
4018#define __NUM_FPRS 16
4019#define __NUM_ACRS 16
4020
4021#define S390_SYSCALL_SIZE 2
4022#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4023
4024#define _SIGCONTEXT_NSIG 64
4025#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4026#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4027#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4028#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4029#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4030
4031typedef struct {
4032 target_psw_t psw;
4033 target_ulong gprs[__NUM_GPRS];
4034 unsigned int acrs[__NUM_ACRS];
4035} target_s390_regs_common;
4036
4037typedef struct {
4038 unsigned int fpc;
4039 double fprs[__NUM_FPRS];
4040} target_s390_fp_regs;
4041
4042typedef struct {
4043 target_s390_regs_common regs;
4044 target_s390_fp_regs fpregs;
4045} target_sigregs;
4046
4047struct target_sigcontext {
4048 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4049 target_sigregs *sregs;
4050};
4051
4052typedef struct {
4053 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4054 struct target_sigcontext sc;
4055 target_sigregs sregs;
4056 int signo;
4057 uint8_t retcode[S390_SYSCALL_SIZE];
4058} sigframe;
4059
4060struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004061 target_ulong tuc_flags;
4062 struct target_ucontext *tuc_link;
4063 target_stack_t tuc_stack;
4064 target_sigregs tuc_mcontext;
4065 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004066};
4067
4068typedef struct {
4069 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4070 uint8_t retcode[S390_SYSCALL_SIZE];
4071 struct target_siginfo info;
4072 struct target_ucontext uc;
4073} rt_sigframe;
4074
4075static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004076get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004077{
4078 abi_ulong sp;
4079
4080 /* Default to using normal stack */
4081 sp = env->regs[15];
4082
4083 /* This is the X/Open sanctioned signal stack switching. */
4084 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4085 if (!sas_ss_flags(sp)) {
4086 sp = target_sigaltstack_used.ss_sp +
4087 target_sigaltstack_used.ss_size;
4088 }
4089 }
4090
4091 /* This is the legacy signal stack switching. */
4092 else if (/* FIXME !user_mode(regs) */ 0 &&
4093 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4094 ka->sa_restorer) {
4095 sp = (abi_ulong) ka->sa_restorer;
4096 }
4097
4098 return (sp - frame_size) & -8ul;
4099}
4100
Andreas Färber05390242012-02-25 03:37:53 +01004101static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004102{
4103 int i;
4104 //save_access_regs(current->thread.acrs); FIXME
4105
4106 /* Copy a 'clean' PSW mask to the user to avoid leaking
4107 information about whether PER is currently on. */
4108 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4109 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4110 for (i = 0; i < 16; i++) {
4111 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4112 }
4113 for (i = 0; i < 16; i++) {
4114 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4115 }
4116 /*
4117 * We have to store the fp registers to current->thread.fp_regs
4118 * to merge them with the emulated registers.
4119 */
4120 //save_fp_regs(&current->thread.fp_regs); FIXME
4121 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004122 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004123 }
4124}
4125
4126static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004127 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004128{
4129 sigframe *frame;
4130 abi_ulong frame_addr;
4131
4132 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004133 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004134 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004135 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004136 }
4137
Riku Voipio0188fad2014-04-23 13:34:15 +03004138 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004139
4140 save_sigregs(env, &frame->sregs);
4141
4142 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4143 (abi_ulong *)&frame->sc.sregs);
4144
4145 /* Set up to return from userspace. If provided, use a stub
4146 already in userspace. */
4147 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004148 env->regs[14] = (unsigned long)
4149 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004150 } else {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004151 env->regs[14] = (unsigned long)
4152 frame->retcode | PSW_ADDR_AMODE;
4153 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4154 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004155 }
4156
4157 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004158 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004159
4160 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004161 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004162 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4163
4164 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004165 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004166
4167 /* We forgot to include these in the sigcontext.
4168 To avoid breaking binary compatibility, they are passed as args. */
4169 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4170 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4171
4172 /* Place signal number on stack to allow backtrace from handler. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004173 __put_user(env->regs[2], (int *) &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004174 unlock_user_struct(frame, frame_addr, 1);
4175 return;
4176
4177give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004178 force_sig(TARGET_SIGSEGV);
4179}
4180
4181static void setup_rt_frame(int sig, struct target_sigaction *ka,
4182 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004183 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004184{
4185 int i;
4186 rt_sigframe *frame;
4187 abi_ulong frame_addr;
4188
4189 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004190 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004191 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4192 goto give_sigsegv;
4193 }
4194
Peter Maydellf6c7a052015-01-08 12:19:48 +00004195 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004196
4197 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004198 __put_user(0, &frame->uc.tuc_flags);
4199 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4200 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004201 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004202 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004203 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4204 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004205 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4206 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004207 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004208 }
4209
4210 /* Set up to return from userspace. If provided, use a stub
4211 already in userspace. */
4212 if (ka->sa_flags & TARGET_SA_RESTORER) {
4213 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4214 } else {
4215 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004216 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4217 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004218 }
4219
4220 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004221 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004222
4223 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004224 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004225 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4226
4227 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004228 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4229 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004230 return;
4231
4232give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004233 force_sig(TARGET_SIGSEGV);
4234}
4235
4236static int
Andreas Färber05390242012-02-25 03:37:53 +01004237restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004238{
4239 int err = 0;
4240 int i;
4241
4242 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004243 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004244 }
4245
Riku Voipio1d8b5122014-04-23 10:26:05 +03004246 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004247 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4248 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004249 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004250 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4251
4252 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004253 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004254 }
4255 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004256 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004257 }
4258
4259 return err;
4260}
4261
Andreas Färber05390242012-02-25 03:37:53 +01004262long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004263{
4264 sigframe *frame;
4265 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004266 target_sigset_t target_set;
4267 sigset_t set;
4268
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004269 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004270 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4271 goto badframe;
4272 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004273 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004274
4275 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004276 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004277
4278 if (restore_sigregs(env, &frame->sregs)) {
4279 goto badframe;
4280 }
4281
4282 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004283 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004284
4285badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004286 force_sig(TARGET_SIGSEGV);
4287 return 0;
4288}
4289
Andreas Färber05390242012-02-25 03:37:53 +01004290long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004291{
4292 rt_sigframe *frame;
4293 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004294 sigset_t set;
4295
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004296 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004297 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4298 goto badframe;
4299 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004300 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004301
Alex Barcelo1c275922014-03-14 14:36:55 +00004302 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004303
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004304 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004305 goto badframe;
4306 }
4307
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004308 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004309 get_sp_from_cpustate(env)) == -EFAULT) {
4310 goto badframe;
4311 }
4312 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004313 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004314
4315badframe:
4316 unlock_user_struct(frame, frame_addr, 0);
4317 force_sig(TARGET_SIGSEGV);
4318 return 0;
4319}
4320
Tom Musta61e75fe2014-06-30 08:13:38 -05004321#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004322
4323/* Size of dummy stack frame allocated when calling signal handler.
4324 See arch/powerpc/include/asm/ptrace.h. */
4325#if defined(TARGET_PPC64)
4326#define SIGNAL_FRAMESIZE 128
4327#else
4328#define SIGNAL_FRAMESIZE 64
4329#endif
4330
Tom Musta61e75fe2014-06-30 08:13:38 -05004331/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4332 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4333struct target_mcontext {
4334 target_ulong mc_gregs[48];
4335 /* Includes fpscr. */
4336 uint64_t mc_fregs[33];
4337 target_ulong mc_pad[2];
4338 /* We need to handle Altivec and SPE at the same time, which no
4339 kernel needs to do. Fortunately, the kernel defines this bit to
4340 be Altivec-register-large all the time, rather than trying to
4341 twiddle it based on the specific platform. */
4342 union {
4343 /* SPE vector registers. One extra for SPEFSCR. */
4344 uint32_t spe[33];
4345 /* Altivec vector registers. The packing of VSCR and VRSAVE
4346 varies depending on whether we're PPC64 or not: PPC64 splits
4347 them apart; PPC32 stuffs them together. */
4348#if defined(TARGET_PPC64)
4349#define QEMU_NVRREG 34
4350#else
4351#define QEMU_NVRREG 33
4352#endif
4353 ppc_avr_t altivec[QEMU_NVRREG];
4354#undef QEMU_NVRREG
4355 } mc_vregs __attribute__((__aligned__(16)));
4356};
4357
Nathan Froydbcd49332009-05-12 19:13:18 -07004358/* See arch/powerpc/include/asm/sigcontext.h. */
4359struct target_sigcontext {
4360 target_ulong _unused[4];
4361 int32_t signal;
4362#if defined(TARGET_PPC64)
4363 int32_t pad0;
4364#endif
4365 target_ulong handler;
4366 target_ulong oldmask;
4367 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05004368#if defined(TARGET_PPC64)
4369 struct target_mcontext mcontext;
4370#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004371};
4372
4373/* Indices for target_mcontext.mc_gregs, below.
4374 See arch/powerpc/include/asm/ptrace.h for details. */
4375enum {
4376 TARGET_PT_R0 = 0,
4377 TARGET_PT_R1 = 1,
4378 TARGET_PT_R2 = 2,
4379 TARGET_PT_R3 = 3,
4380 TARGET_PT_R4 = 4,
4381 TARGET_PT_R5 = 5,
4382 TARGET_PT_R6 = 6,
4383 TARGET_PT_R7 = 7,
4384 TARGET_PT_R8 = 8,
4385 TARGET_PT_R9 = 9,
4386 TARGET_PT_R10 = 10,
4387 TARGET_PT_R11 = 11,
4388 TARGET_PT_R12 = 12,
4389 TARGET_PT_R13 = 13,
4390 TARGET_PT_R14 = 14,
4391 TARGET_PT_R15 = 15,
4392 TARGET_PT_R16 = 16,
4393 TARGET_PT_R17 = 17,
4394 TARGET_PT_R18 = 18,
4395 TARGET_PT_R19 = 19,
4396 TARGET_PT_R20 = 20,
4397 TARGET_PT_R21 = 21,
4398 TARGET_PT_R22 = 22,
4399 TARGET_PT_R23 = 23,
4400 TARGET_PT_R24 = 24,
4401 TARGET_PT_R25 = 25,
4402 TARGET_PT_R26 = 26,
4403 TARGET_PT_R27 = 27,
4404 TARGET_PT_R28 = 28,
4405 TARGET_PT_R29 = 29,
4406 TARGET_PT_R30 = 30,
4407 TARGET_PT_R31 = 31,
4408 TARGET_PT_NIP = 32,
4409 TARGET_PT_MSR = 33,
4410 TARGET_PT_ORIG_R3 = 34,
4411 TARGET_PT_CTR = 35,
4412 TARGET_PT_LNK = 36,
4413 TARGET_PT_XER = 37,
4414 TARGET_PT_CCR = 38,
4415 /* Yes, there are two registers with #39. One is 64-bit only. */
4416 TARGET_PT_MQ = 39,
4417 TARGET_PT_SOFTE = 39,
4418 TARGET_PT_TRAP = 40,
4419 TARGET_PT_DAR = 41,
4420 TARGET_PT_DSISR = 42,
4421 TARGET_PT_RESULT = 43,
4422 TARGET_PT_REGS_COUNT = 44
4423};
4424
Nathan Froydbcd49332009-05-12 19:13:18 -07004425
4426struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004427 target_ulong tuc_flags;
4428 target_ulong tuc_link; /* struct ucontext __user * */
4429 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07004430#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02004431 int32_t tuc_pad[7];
4432 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07004433 points to uc_mcontext field */
4434#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02004435 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07004436#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05004437 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05004438 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004439#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02004440 int32_t tuc_maskext[30];
4441 int32_t tuc_pad2[3];
4442 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004443#endif
4444};
4445
4446/* See arch/powerpc/kernel/signal_32.c. */
4447struct target_sigframe {
4448 struct target_sigcontext sctx;
4449 struct target_mcontext mctx;
4450 int32_t abigap[56];
4451};
4452
Tom Musta61e75fe2014-06-30 08:13:38 -05004453#if defined(TARGET_PPC64)
4454
4455#define TARGET_TRAMP_SIZE 6
4456
4457struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004458 /* sys_rt_sigreturn requires the ucontext be the first field */
4459 struct target_ucontext uc;
4460 target_ulong _unused[2];
4461 uint32_t trampoline[TARGET_TRAMP_SIZE];
4462 target_ulong pinfo; /* struct siginfo __user * */
4463 target_ulong puc; /* void __user * */
4464 struct target_siginfo info;
4465 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
4466 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05004467} __attribute__((aligned(16)));
4468
4469#else
4470
Nathan Froydbcd49332009-05-12 19:13:18 -07004471struct target_rt_sigframe {
4472 struct target_siginfo info;
4473 struct target_ucontext uc;
4474 int32_t abigap[56];
4475};
4476
Tom Musta61e75fe2014-06-30 08:13:38 -05004477#endif
4478
Tom Musta8d6ab332014-06-30 08:13:39 -05004479#if defined(TARGET_PPC64)
4480
4481struct target_func_ptr {
4482 target_ulong entry;
4483 target_ulong toc;
4484};
4485
4486#endif
4487
Nathan Froydbcd49332009-05-12 19:13:18 -07004488/* We use the mc_pad field for the signal return trampoline. */
4489#define tramp mc_pad
4490
4491/* See arch/powerpc/kernel/signal.c. */
4492static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004493 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07004494 int frame_size)
4495{
4496 target_ulong oldsp, newsp;
4497
4498 oldsp = env->gpr[1];
4499
4500 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004501 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07004502 oldsp = (target_sigaltstack_used.ss_sp
4503 + target_sigaltstack_used.ss_size);
4504 }
4505
4506 newsp = (oldsp - frame_size) & ~0xFUL;
4507
4508 return newsp;
4509}
4510
Tom Musta76781082014-06-30 08:13:37 -05004511static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07004512{
4513 target_ulong msr = env->msr;
4514 int i;
4515 target_ulong ccr = 0;
4516
4517 /* In general, the kernel attempts to be intelligent about what it
4518 needs to save for Altivec/FP/SPE registers. We don't care that
4519 much, so we just go ahead and save everything. */
4520
4521 /* Save general registers. */
4522 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004523 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004524 }
Riku Voipioc650c002014-04-23 13:53:45 +03004525 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4526 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4527 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4528 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004529
4530 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4531 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4532 }
Riku Voipioc650c002014-04-23 13:53:45 +03004533 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004534
4535 /* Save Altivec registers if necessary. */
4536 if (env->insns_flags & PPC_ALTIVEC) {
4537 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004538 ppc_avr_t *avr = &env->avr[i];
4539 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004540
Riku Voipioc650c002014-04-23 13:53:45 +03004541 __put_user(avr->u64[0], &vreg->u64[0]);
4542 __put_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004543 }
4544 /* Set MSR_VR in the saved MSR value to indicate that
4545 frame->mc_vregs contains valid data. */
4546 msr |= MSR_VR;
Riku Voipioc650c002014-04-23 13:53:45 +03004547 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4548 &frame->mc_vregs.altivec[32].u32[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004549 }
4550
4551 /* Save floating point registers. */
4552 if (env->insns_flags & PPC_FLOAT) {
4553 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004554 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004555 }
Riku Voipioc650c002014-04-23 13:53:45 +03004556 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004557 }
4558
4559 /* Save SPE registers. The kernel only saves the high half. */
4560 if (env->insns_flags & PPC_SPE) {
4561#if defined(TARGET_PPC64)
4562 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004563 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004564 }
4565#else
4566 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004567 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004568 }
4569#endif
4570 /* Set MSR_SPE in the saved MSR value to indicate that
4571 frame->mc_vregs contains valid data. */
4572 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03004573 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004574 }
4575
4576 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004577 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05004578}
Nathan Froydbcd49332009-05-12 19:13:18 -07004579
Tom Musta76781082014-06-30 08:13:37 -05004580static void encode_trampoline(int sigret, uint32_t *tramp)
4581{
Nathan Froydbcd49332009-05-12 19:13:18 -07004582 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4583 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05004584 __put_user(0x38000000 | sigret, &tramp[0]);
4585 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004586 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004587}
4588
Riku Voipioc650c002014-04-23 13:53:45 +03004589static void restore_user_regs(CPUPPCState *env,
4590 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004591{
4592 target_ulong save_r2 = 0;
4593 target_ulong msr;
4594 target_ulong ccr;
4595
4596 int i;
4597
4598 if (!sig) {
4599 save_r2 = env->gpr[2];
4600 }
4601
4602 /* Restore general registers. */
4603 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004604 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004605 }
Riku Voipioc650c002014-04-23 13:53:45 +03004606 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4607 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4608 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4609 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4610 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004611
4612 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4613 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4614 }
4615
4616 if (!sig) {
4617 env->gpr[2] = save_r2;
4618 }
4619 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004620 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004621
4622 /* If doing signal return, restore the previous little-endian mode. */
4623 if (sig)
4624 env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
4625
4626 /* Restore Altivec registers if necessary. */
4627 if (env->insns_flags & PPC_ALTIVEC) {
4628 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004629 ppc_avr_t *avr = &env->avr[i];
4630 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004631
Riku Voipioc650c002014-04-23 13:53:45 +03004632 __get_user(avr->u64[0], &vreg->u64[0]);
4633 __get_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004634 }
4635 /* Set MSR_VEC in the saved MSR value to indicate that
4636 frame->mc_vregs contains valid data. */
Riku Voipioc650c002014-04-23 13:53:45 +03004637 __get_user(env->spr[SPR_VRSAVE],
4638 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
Nathan Froydbcd49332009-05-12 19:13:18 -07004639 }
4640
4641 /* Restore floating point registers. */
4642 if (env->insns_flags & PPC_FLOAT) {
4643 uint64_t fpscr;
4644 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004645 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004646 }
Riku Voipioc650c002014-04-23 13:53:45 +03004647 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004648 env->fpscr = (uint32_t) fpscr;
4649 }
4650
4651 /* Save SPE registers. The kernel only saves the high half. */
4652 if (env->insns_flags & PPC_SPE) {
4653#if defined(TARGET_PPC64)
4654 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4655 uint32_t hi;
4656
Riku Voipioc650c002014-04-23 13:53:45 +03004657 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004658 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4659 }
4660#else
4661 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004662 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004663 }
4664#endif
Riku Voipioc650c002014-04-23 13:53:45 +03004665 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004666 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004667}
4668
4669static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004670 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004671{
4672 struct target_sigframe *frame;
4673 struct target_sigcontext *sc;
4674 target_ulong frame_addr, newsp;
4675 int err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004676#if defined(TARGET_PPC64)
4677 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4678#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004679
4680 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004681 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004682 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4683 goto sigsegv;
4684 sc = &frame->sctx;
4685
Riku Voipio1d8b5122014-04-23 10:26:05 +03004686 __put_user(ka->_sa_handler, &sc->handler);
4687 __put_user(set->sig[0], &sc->oldmask);
Tom Musta61e75fe2014-06-30 08:13:38 -05004688#if TARGET_ABI_BITS == 64
Riku Voipio1d8b5122014-04-23 10:26:05 +03004689 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004690#else
Riku Voipio1d8b5122014-04-23 10:26:05 +03004691 __put_user(set->sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004692#endif
Riku Voipio1d8b5122014-04-23 10:26:05 +03004693 __put_user(h2g(&frame->mctx), &sc->regs);
4694 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07004695
4696 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05004697 save_user_regs(env, &frame->mctx);
4698
4699 /* Construct the trampoline code on the stack. */
4700 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07004701
4702 /* The kernel checks for the presence of a VDSO here. We don't
4703 emulate a vdso, so use a sigreturn system call. */
4704 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4705
4706 /* Turn off all fp exceptions. */
4707 env->fpscr = 0;
4708
4709 /* Create a stack frame for the caller of the handler. */
4710 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00004711 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004712
4713 if (err)
4714 goto sigsegv;
4715
4716 /* Set up registers for signal handler. */
4717 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004718 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00004719 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05004720
4721#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004722 if (get_ppc64_abi(image) < 2) {
4723 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4724 struct target_func_ptr *handler =
4725 (struct target_func_ptr *)g2h(ka->_sa_handler);
4726 env->nip = tswapl(handler->entry);
4727 env->gpr[2] = tswapl(handler->toc);
4728 } else {
4729 /* ELFv2 PPC64 function pointers are entry points, but R12
4730 * must also be set */
4731 env->nip = tswapl((target_ulong) ka->_sa_handler);
4732 env->gpr[12] = env->nip;
4733 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004734#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004735 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004736#endif
4737
Nathan Froydbcd49332009-05-12 19:13:18 -07004738 /* Signal handlers are entered in big-endian mode. */
4739 env->msr &= ~MSR_LE;
4740
4741 unlock_user_struct(frame, frame_addr, 1);
4742 return;
4743
4744sigsegv:
4745 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004746 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004747}
4748
4749static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004750 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004751 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004752{
4753 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05004754 uint32_t *trampptr = 0;
4755 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004756 target_ulong rt_sf_addr, newsp = 0;
4757 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004758#if defined(TARGET_PPC64)
4759 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4760#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004761
4762 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4763 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4764 goto sigsegv;
4765
Peter Maydellf6c7a052015-01-08 12:19:48 +00004766 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07004767
Riku Voipio1d8b5122014-04-23 10:26:05 +03004768 __put_user(0, &rt_sf->uc.tuc_flags);
4769 __put_user(0, &rt_sf->uc.tuc_link);
4770 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4771 &rt_sf->uc.tuc_stack.ss_sp);
4772 __put_user(sas_ss_flags(env->gpr[1]),
4773 &rt_sf->uc.tuc_stack.ss_flags);
4774 __put_user(target_sigaltstack_used.ss_size,
4775 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05004776#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03004777 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4778 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05004779#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004780 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004781 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004782 }
4783
Tom Musta61e75fe2014-06-30 08:13:38 -05004784#if defined(TARGET_PPC64)
4785 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
4786 trampptr = &rt_sf->trampoline[0];
4787#else
4788 mctx = &rt_sf->uc.tuc_mcontext;
4789 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
4790#endif
4791
4792 save_user_regs(env, mctx);
4793 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004794
4795 /* The kernel checks for the presence of a VDSO here. We don't
4796 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05004797 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004798
4799 /* Turn off all fp exceptions. */
4800 env->fpscr = 0;
4801
4802 /* Create a stack frame for the caller of the handler. */
4803 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05004804 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004805
4806 if (err)
4807 goto sigsegv;
4808
4809 /* Set up registers for signal handler. */
4810 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004811 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07004812 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4813 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4814 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05004815
4816#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004817 if (get_ppc64_abi(image) < 2) {
4818 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4819 struct target_func_ptr *handler =
4820 (struct target_func_ptr *)g2h(ka->_sa_handler);
4821 env->nip = tswapl(handler->entry);
4822 env->gpr[2] = tswapl(handler->toc);
4823 } else {
4824 /* ELFv2 PPC64 function pointers are entry points, but R12
4825 * must also be set */
4826 env->nip = tswapl((target_ulong) ka->_sa_handler);
4827 env->gpr[12] = env->nip;
4828 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004829#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004830 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004831#endif
4832
Nathan Froydbcd49332009-05-12 19:13:18 -07004833 /* Signal handlers are entered in big-endian mode. */
4834 env->msr &= ~MSR_LE;
4835
4836 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4837 return;
4838
4839sigsegv:
4840 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004841 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004842
4843}
4844
Andreas Färber05390242012-02-25 03:37:53 +01004845long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004846{
4847 struct target_sigcontext *sc = NULL;
4848 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01004849 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07004850 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004851 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004852
4853 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4854 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4855 goto sigsegv;
4856
4857#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05004858 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07004859#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03004860 __get_user(set.sig[0], &sc->oldmask);
4861 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004862#endif
4863 target_to_host_sigset_internal(&blocked, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004864 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
Nathan Froydbcd49332009-05-12 19:13:18 -07004865
Riku Voipiof5f601a2014-04-23 13:00:17 +03004866 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004867 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4868 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03004869 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07004870
4871 unlock_user_struct(sr, sr_addr, 1);
4872 unlock_user_struct(sc, sc_addr, 1);
4873 return -TARGET_QEMU_ESIGRETURN;
4874
4875sigsegv:
4876 unlock_user_struct(sr, sr_addr, 1);
4877 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004878 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004879 return 0;
4880}
4881
4882/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01004883static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004884{
4885 struct target_mcontext *mcp;
4886 target_ulong mcp_addr;
4887 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004888 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004889
Aurelien Jarno60e99242010-03-29 02:12:51 +02004890 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07004891 sizeof (set)))
4892 return 1;
4893
Tom Musta19774ec2014-06-30 08:13:40 -05004894#if defined(TARGET_PPC64)
4895 mcp_addr = h2g(ucp) +
4896 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
4897#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03004898 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05004899#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004900
4901 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4902 return 1;
4903
4904 target_to_host_sigset_internal(&blocked, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004905 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
Riku Voipioc650c002014-04-23 13:53:45 +03004906 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07004907
4908 unlock_user_struct(mcp, mcp_addr, 1);
4909 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004910}
4911
Andreas Färber05390242012-02-25 03:37:53 +01004912long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004913{
4914 struct target_rt_sigframe *rt_sf = NULL;
4915 target_ulong rt_sf_addr;
4916
4917 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4918 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4919 goto sigsegv;
4920
4921 if (do_setcontext(&rt_sf->uc, env, 1))
4922 goto sigsegv;
4923
4924 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02004925 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07004926 0, env->gpr[1]);
4927
4928 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4929 return -TARGET_QEMU_ESIGRETURN;
4930
4931sigsegv:
4932 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004933 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004934 return 0;
4935}
4936
Laurent Vivier492a8742009-08-03 16:12:17 +02004937#elif defined(TARGET_M68K)
4938
4939struct target_sigcontext {
4940 abi_ulong sc_mask;
4941 abi_ulong sc_usp;
4942 abi_ulong sc_d0;
4943 abi_ulong sc_d1;
4944 abi_ulong sc_a0;
4945 abi_ulong sc_a1;
4946 unsigned short sc_sr;
4947 abi_ulong sc_pc;
4948};
4949
4950struct target_sigframe
4951{
4952 abi_ulong pretcode;
4953 int sig;
4954 int code;
4955 abi_ulong psc;
4956 char retcode[8];
4957 abi_ulong extramask[TARGET_NSIG_WORDS-1];
4958 struct target_sigcontext sc;
4959};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004960
Anthony Liguoric227f092009-10-01 16:12:16 -05004961typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004962#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05004963typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02004964
4965typedef struct target_fpregset {
4966 int f_fpcntl[3];
4967 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05004968} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004969
4970struct target_mcontext {
4971 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05004972 target_gregset_t gregs;
4973 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02004974};
4975
4976#define TARGET_MCONTEXT_VERSION 2
4977
4978struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004979 abi_ulong tuc_flags;
4980 abi_ulong tuc_link;
4981 target_stack_t tuc_stack;
4982 struct target_mcontext tuc_mcontext;
4983 abi_long tuc_filler[80];
4984 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02004985};
4986
4987struct target_rt_sigframe
4988{
4989 abi_ulong pretcode;
4990 int sig;
4991 abi_ulong pinfo;
4992 abi_ulong puc;
4993 char retcode[8];
4994 struct target_siginfo info;
4995 struct target_ucontext uc;
4996};
Laurent Vivier492a8742009-08-03 16:12:17 +02004997
Riku Voipio41ecc722014-04-23 11:01:00 +03004998static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004999 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005000{
Riku Voipio1d8b5122014-04-23 10:26:05 +03005001 __put_user(mask, &sc->sc_mask);
5002 __put_user(env->aregs[7], &sc->sc_usp);
5003 __put_user(env->dregs[0], &sc->sc_d0);
5004 __put_user(env->dregs[1], &sc->sc_d1);
5005 __put_user(env->aregs[0], &sc->sc_a0);
5006 __put_user(env->aregs[1], &sc->sc_a1);
5007 __put_user(env->sr, &sc->sc_sr);
5008 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005009}
5010
Riku Voipio016d2e12014-04-23 11:19:48 +03005011static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005012restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005013{
Laurent Vivier492a8742009-08-03 16:12:17 +02005014 int temp;
5015
Riku Voipio1d8b5122014-04-23 10:26:05 +03005016 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005017 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005018 __get_user(env->dregs[1], &sc->sc_d1);
5019 __get_user(env->aregs[0], &sc->sc_a0);
5020 __get_user(env->aregs[1], &sc->sc_a1);
5021 __get_user(env->pc, &sc->sc_pc);
5022 __get_user(temp, &sc->sc_sr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005023 env->sr = (env->sr & 0xff00) | (temp & 0xff);
Laurent Vivier492a8742009-08-03 16:12:17 +02005024}
5025
5026/*
5027 * Determine which stack to use..
5028 */
5029static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005030get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5031 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005032{
5033 unsigned long sp;
5034
5035 sp = regs->aregs[7];
5036
5037 /* This is the X/Open sanctioned signal stack switching. */
5038 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5039 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5040 }
5041
5042 return ((sp - frame_size) & -8UL);
5043}
5044
5045static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005046 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005047{
5048 struct target_sigframe *frame;
5049 abi_ulong frame_addr;
5050 abi_ulong retcode_addr;
5051 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005052 int i;
5053
5054 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005055 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005056 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5057 goto give_sigsegv;
5058 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005059
Riku Voipio1d8b5122014-04-23 10:26:05 +03005060 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005061
5062 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005063 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005064
Riku Voipio41ecc722014-04-23 11:01:00 +03005065 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005066
5067 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005068 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005069 }
5070
5071 /* Set up to return from userspace. */
5072
5073 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005074 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005075
5076 /* moveq #,d0; trap #0 */
5077
Riku Voipio1d8b5122014-04-23 10:26:05 +03005078 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005079 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005080
Laurent Vivier492a8742009-08-03 16:12:17 +02005081 /* Set up to return from userspace */
5082
5083 env->aregs[7] = frame_addr;
5084 env->pc = ka->_sa_handler;
5085
5086 unlock_user_struct(frame, frame_addr, 1);
5087 return;
5088
5089give_sigsegv:
Riku Voipio66393fb2009-12-04 15:16:32 +02005090 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005091}
5092
Laurent Vivier71811552009-08-03 16:12:18 +02005093static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005094 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005095{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005096 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005097
Riku Voipio1d8b5122014-04-23 10:26:05 +03005098 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5099 __put_user(env->dregs[0], &gregs[0]);
5100 __put_user(env->dregs[1], &gregs[1]);
5101 __put_user(env->dregs[2], &gregs[2]);
5102 __put_user(env->dregs[3], &gregs[3]);
5103 __put_user(env->dregs[4], &gregs[4]);
5104 __put_user(env->dregs[5], &gregs[5]);
5105 __put_user(env->dregs[6], &gregs[6]);
5106 __put_user(env->dregs[7], &gregs[7]);
5107 __put_user(env->aregs[0], &gregs[8]);
5108 __put_user(env->aregs[1], &gregs[9]);
5109 __put_user(env->aregs[2], &gregs[10]);
5110 __put_user(env->aregs[3], &gregs[11]);
5111 __put_user(env->aregs[4], &gregs[12]);
5112 __put_user(env->aregs[5], &gregs[13]);
5113 __put_user(env->aregs[6], &gregs[14]);
5114 __put_user(env->aregs[7], &gregs[15]);
5115 __put_user(env->pc, &gregs[16]);
5116 __put_user(env->sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005117
Riku Voipio1d8b5122014-04-23 10:26:05 +03005118 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005119}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005120
Andreas Färber05390242012-02-25 03:37:53 +01005121static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005122 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02005123{
5124 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005125 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005126
Riku Voipio1d8b5122014-04-23 10:26:05 +03005127 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005128 if (temp != TARGET_MCONTEXT_VERSION)
5129 goto badframe;
5130
5131 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005132 __get_user(env->dregs[0], &gregs[0]);
5133 __get_user(env->dregs[1], &gregs[1]);
5134 __get_user(env->dregs[2], &gregs[2]);
5135 __get_user(env->dregs[3], &gregs[3]);
5136 __get_user(env->dregs[4], &gregs[4]);
5137 __get_user(env->dregs[5], &gregs[5]);
5138 __get_user(env->dregs[6], &gregs[6]);
5139 __get_user(env->dregs[7], &gregs[7]);
5140 __get_user(env->aregs[0], &gregs[8]);
5141 __get_user(env->aregs[1], &gregs[9]);
5142 __get_user(env->aregs[2], &gregs[10]);
5143 __get_user(env->aregs[3], &gregs[11]);
5144 __get_user(env->aregs[4], &gregs[12]);
5145 __get_user(env->aregs[5], &gregs[13]);
5146 __get_user(env->aregs[6], &gregs[14]);
5147 __get_user(env->aregs[7], &gregs[15]);
5148 __get_user(env->pc, &gregs[16]);
5149 __get_user(temp, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005150 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5151
Riku Voipio1d8b5122014-04-23 10:26:05 +03005152 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005153
5154badframe:
5155 return 1;
5156}
5157
Laurent Vivier492a8742009-08-03 16:12:17 +02005158static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005159 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005160 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005161{
Laurent Vivier71811552009-08-03 16:12:18 +02005162 struct target_rt_sigframe *frame;
5163 abi_ulong frame_addr;
5164 abi_ulong retcode_addr;
5165 abi_ulong info_addr;
5166 abi_ulong uc_addr;
5167 int err = 0;
5168 int i;
5169
5170 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005171 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005172 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5173 goto give_sigsegv;
5174 }
Laurent Vivier71811552009-08-03 16:12:18 +02005175
Riku Voipio1d8b5122014-04-23 10:26:05 +03005176 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005177
5178 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005179 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005180
5181 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005182 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005183
Peter Maydellf6c7a052015-01-08 12:19:48 +00005184 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005185
5186 /* Create the ucontext */
5187
Riku Voipio1d8b5122014-04-23 10:26:05 +03005188 __put_user(0, &frame->uc.tuc_flags);
5189 __put_user(0, &frame->uc.tuc_link);
5190 __put_user(target_sigaltstack_used.ss_sp,
5191 &frame->uc.tuc_stack.ss_sp);
5192 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005193 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005194 __put_user(target_sigaltstack_used.ss_size,
5195 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005196 err |= target_rt_setup_ucontext(&frame->uc, env);
5197
5198 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005199 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02005200
5201 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005202 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005203 }
5204
5205 /* Set up to return from userspace. */
5206
5207 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005208 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005209
5210 /* moveq #,d0; notb d0; trap #0 */
5211
Riku Voipio1d8b5122014-04-23 10:26:05 +03005212 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005213 (uint32_t *)(frame->retcode + 0));
5214 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005215
5216 if (err)
5217 goto give_sigsegv;
5218
5219 /* Set up to return from userspace */
5220
5221 env->aregs[7] = frame_addr;
5222 env->pc = ka->_sa_handler;
5223
5224 unlock_user_struct(frame, frame_addr, 1);
5225 return;
5226
5227give_sigsegv:
5228 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005229 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005230}
5231
Andreas Färber05390242012-02-25 03:37:53 +01005232long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005233{
5234 struct target_sigframe *frame;
5235 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005236 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005237 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005238 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02005239
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005240 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005241 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5242 goto badframe;
5243
5244 /* set blocked signals */
5245
Riku Voipiof5f601a2014-04-23 13:00:17 +03005246 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005247
5248 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005249 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005250 }
5251
5252 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005253 do_sigprocmask(SIG_SETMASK, &set, NULL);
Laurent Vivier492a8742009-08-03 16:12:17 +02005254
5255 /* restore registers */
5256
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005257 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005258
5259 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005260 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005261
5262badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005263 force_sig(TARGET_SIGSEGV);
5264 return 0;
5265}
5266
Andreas Färber05390242012-02-25 03:37:53 +01005267long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005268{
Laurent Vivier71811552009-08-03 16:12:18 +02005269 struct target_rt_sigframe *frame;
5270 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005271 target_sigset_t target_set;
Laurent Vivier71811552009-08-03 16:12:18 +02005272 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02005273
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005274 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02005275 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5276 goto badframe;
5277
5278 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005279 do_sigprocmask(SIG_SETMASK, &set, NULL);
Laurent Vivier71811552009-08-03 16:12:18 +02005280
5281 /* restore registers */
5282
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005283 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02005284 goto badframe;
5285
5286 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02005287 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02005288 0, get_sp_from_cpustate(env)) == -EFAULT)
5289 goto badframe;
5290
5291 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005292 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02005293
5294badframe:
5295 unlock_user_struct(frame, frame_addr, 0);
5296 force_sig(TARGET_SIGSEGV);
5297 return 0;
Laurent Vivier492a8742009-08-03 16:12:17 +02005298}
5299
Richard Henderson6049f4f2009-12-27 18:30:03 -08005300#elif defined(TARGET_ALPHA)
5301
5302struct target_sigcontext {
5303 abi_long sc_onstack;
5304 abi_long sc_mask;
5305 abi_long sc_pc;
5306 abi_long sc_ps;
5307 abi_long sc_regs[32];
5308 abi_long sc_ownedfp;
5309 abi_long sc_fpregs[32];
5310 abi_ulong sc_fpcr;
5311 abi_ulong sc_fp_control;
5312 abi_ulong sc_reserved1;
5313 abi_ulong sc_reserved2;
5314 abi_ulong sc_ssize;
5315 abi_ulong sc_sbase;
5316 abi_ulong sc_traparg_a0;
5317 abi_ulong sc_traparg_a1;
5318 abi_ulong sc_traparg_a2;
5319 abi_ulong sc_fp_trap_pc;
5320 abi_ulong sc_fp_trigger_sum;
5321 abi_ulong sc_fp_trigger_inst;
5322};
5323
5324struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005325 abi_ulong tuc_flags;
5326 abi_ulong tuc_link;
5327 abi_ulong tuc_osf_sigmask;
5328 target_stack_t tuc_stack;
5329 struct target_sigcontext tuc_mcontext;
5330 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005331};
5332
5333struct target_sigframe {
5334 struct target_sigcontext sc;
5335 unsigned int retcode[3];
5336};
5337
5338struct target_rt_sigframe {
5339 target_siginfo_t info;
5340 struct target_ucontext uc;
5341 unsigned int retcode[3];
5342};
5343
5344#define INSN_MOV_R30_R16 0x47fe0410
5345#define INSN_LDI_R0 0x201f0000
5346#define INSN_CALLSYS 0x00000083
5347
Riku Voipio41ecc722014-04-23 11:01:00 +03005348static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005349 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005350{
Riku Voipio41ecc722014-04-23 11:01:00 +03005351 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005352
Riku Voipio1d8b5122014-04-23 10:26:05 +03005353 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5354 __put_user(set->sig[0], &sc->sc_mask);
5355 __put_user(env->pc, &sc->sc_pc);
5356 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005357
5358 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005359 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005360 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005361 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005362
5363 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005364 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005365 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005366 __put_user(0, &sc->sc_fpregs[31]);
5367 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005368
Riku Voipio1d8b5122014-04-23 10:26:05 +03005369 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5370 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5371 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08005372}
5373
Riku Voipio016d2e12014-04-23 11:19:48 +03005374static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005375 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005376{
5377 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03005378 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005379
Riku Voipio1d8b5122014-04-23 10:26:05 +03005380 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005381
5382 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005383 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005384 }
5385 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005386 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005387 }
5388
Riku Voipio1d8b5122014-04-23 10:26:05 +03005389 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005390 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005391}
5392
5393static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01005394 CPUAlphaState *env,
5395 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005396{
5397 abi_ulong sp = env->ir[IR_SP];
5398
5399 /* This is the X/Open sanctioned signal stack switching. */
5400 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5401 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5402 }
5403 return (sp - framesize) & -32;
5404}
5405
5406static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005407 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005408{
5409 abi_ulong frame_addr, r26;
5410 struct target_sigframe *frame;
5411 int err = 0;
5412
5413 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005414 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005415 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5416 goto give_sigsegv;
5417 }
5418
Riku Voipio41ecc722014-04-23 11:01:00 +03005419 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005420
5421 if (ka->sa_restorer) {
5422 r26 = ka->sa_restorer;
5423 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005424 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5425 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5426 &frame->retcode[1]);
5427 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005428 /* imb() */
5429 r26 = frame_addr;
5430 }
5431
5432 unlock_user_struct(frame, frame_addr, 1);
5433
5434 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005435give_sigsegv:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005436 if (sig == TARGET_SIGSEGV) {
5437 ka->_sa_handler = TARGET_SIG_DFL;
5438 }
5439 force_sig(TARGET_SIGSEGV);
5440 }
5441
5442 env->ir[IR_RA] = r26;
5443 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5444 env->ir[IR_A0] = sig;
5445 env->ir[IR_A1] = 0;
5446 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5447 env->ir[IR_SP] = frame_addr;
5448}
5449
5450static void setup_rt_frame(int sig, struct target_sigaction *ka,
5451 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005452 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005453{
5454 abi_ulong frame_addr, r26;
5455 struct target_rt_sigframe *frame;
5456 int i, err = 0;
5457
5458 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005459 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005460 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5461 goto give_sigsegv;
5462 }
5463
Peter Maydellf6c7a052015-01-08 12:19:48 +00005464 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005465
Riku Voipio1d8b5122014-04-23 10:26:05 +03005466 __put_user(0, &frame->uc.tuc_flags);
5467 __put_user(0, &frame->uc.tuc_link);
5468 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5469 __put_user(target_sigaltstack_used.ss_sp,
5470 &frame->uc.tuc_stack.ss_sp);
5471 __put_user(sas_ss_flags(env->ir[IR_SP]),
5472 &frame->uc.tuc_stack.ss_flags);
5473 __put_user(target_sigaltstack_used.ss_size,
5474 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03005475 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005476 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005477 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005478 }
5479
5480 if (ka->sa_restorer) {
5481 r26 = ka->sa_restorer;
5482 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005483 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5484 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5485 &frame->retcode[1]);
5486 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005487 /* imb(); */
5488 r26 = frame_addr;
5489 }
5490
5491 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005492give_sigsegv:
5493 if (sig == TARGET_SIGSEGV) {
Richard Henderson6049f4f2009-12-27 18:30:03 -08005494 ka->_sa_handler = TARGET_SIG_DFL;
5495 }
5496 force_sig(TARGET_SIGSEGV);
5497 }
5498
5499 env->ir[IR_RA] = r26;
5500 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5501 env->ir[IR_A0] = sig;
5502 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5503 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5504 env->ir[IR_SP] = frame_addr;
5505}
5506
Andreas Färber05390242012-02-25 03:37:53 +01005507long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005508{
5509 struct target_sigcontext *sc;
5510 abi_ulong sc_addr = env->ir[IR_A0];
5511 target_sigset_t target_set;
5512 sigset_t set;
5513
5514 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5515 goto badframe;
5516 }
5517
5518 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03005519 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005520
5521 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005522 do_sigprocmask(SIG_SETMASK, &set, NULL);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005523
Riku Voipio016d2e12014-04-23 11:19:48 +03005524 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005525 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005526 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005527
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005528badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005529 force_sig(TARGET_SIGSEGV);
5530}
5531
Andreas Färber05390242012-02-25 03:37:53 +01005532long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005533{
5534 abi_ulong frame_addr = env->ir[IR_A0];
5535 struct target_rt_sigframe *frame;
5536 sigset_t set;
5537
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005538 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005539 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5540 goto badframe;
5541 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02005542 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00005543 do_sigprocmask(SIG_SETMASK, &set, NULL);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005544
Riku Voipio016d2e12014-04-23 11:19:48 +03005545 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005546 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02005547 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08005548 0, env->ir[IR_SP]) == -EFAULT) {
5549 goto badframe;
5550 }
5551
5552 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005553 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005554
5555
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005556badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005557 unlock_user_struct(frame, frame_addr, 0);
5558 force_sig(TARGET_SIGSEGV);
5559}
5560
Chen Gangbf0f60a2015-09-27 08:10:18 +08005561#elif defined(TARGET_TILEGX)
5562
5563struct target_sigcontext {
5564 union {
5565 /* General-purpose registers. */
5566 abi_ulong gregs[56];
5567 struct {
5568 abi_ulong __gregs[53];
5569 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
5570 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
5571 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
5572 };
5573 };
5574 abi_ulong pc; /* Program counter. */
5575 abi_ulong ics; /* In Interrupt Critical Section? */
5576 abi_ulong faultnum; /* Fault number. */
5577 abi_ulong pad[5];
5578};
5579
5580struct target_ucontext {
5581 abi_ulong tuc_flags;
5582 abi_ulong tuc_link;
5583 target_stack_t tuc_stack;
5584 struct target_sigcontext tuc_mcontext;
5585 target_sigset_t tuc_sigmask; /* mask last for extensibility */
5586};
5587
5588struct target_rt_sigframe {
5589 unsigned char save_area[16]; /* caller save area */
5590 struct target_siginfo info;
5591 struct target_ucontext uc;
5592};
5593
5594static void setup_sigcontext(struct target_sigcontext *sc,
5595 CPUArchState *env, int signo)
5596{
5597 int i;
5598
5599 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5600 __put_user(env->regs[i], &sc->gregs[i]);
5601 }
5602
5603 __put_user(env->pc, &sc->pc);
5604 __put_user(0, &sc->ics);
5605 __put_user(signo, &sc->faultnum);
5606}
5607
5608static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
5609{
5610 int i;
5611
5612 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5613 __get_user(env->regs[i], &sc->gregs[i]);
5614 }
5615
5616 __get_user(env->pc, &sc->pc);
5617}
5618
5619static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
5620 size_t frame_size)
5621{
5622 unsigned long sp = env->regs[TILEGX_R_SP];
5623
5624 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
5625 return -1UL;
5626 }
5627
5628 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
5629 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5630 }
5631
5632 sp -= frame_size;
5633 sp &= -16UL;
5634 return sp;
5635}
5636
5637static void setup_rt_frame(int sig, struct target_sigaction *ka,
5638 target_siginfo_t *info,
5639 target_sigset_t *set, CPUArchState *env)
5640{
5641 abi_ulong frame_addr;
5642 struct target_rt_sigframe *frame;
5643 unsigned long restorer;
5644
5645 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005646 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005647 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5648 goto give_sigsegv;
5649 }
5650
5651 /* Always write at least the signal number for the stack backtracer. */
5652 if (ka->sa_flags & TARGET_SA_SIGINFO) {
5653 /* At sigreturn time, restore the callee-save registers too. */
5654 tswap_siginfo(&frame->info, info);
5655 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
5656 } else {
5657 __put_user(info->si_signo, &frame->info.si_signo);
5658 }
5659
5660 /* Create the ucontext. */
5661 __put_user(0, &frame->uc.tuc_flags);
5662 __put_user(0, &frame->uc.tuc_link);
5663 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
5664 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
5665 &frame->uc.tuc_stack.ss_flags);
5666 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5667 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
5668
5669 restorer = (unsigned long) do_rt_sigreturn;
5670 if (ka->sa_flags & TARGET_SA_RESTORER) {
5671 restorer = (unsigned long) ka->sa_restorer;
5672 }
5673 env->pc = (unsigned long) ka->_sa_handler;
5674 env->regs[TILEGX_R_SP] = (unsigned long) frame;
5675 env->regs[TILEGX_R_LR] = restorer;
5676 env->regs[0] = (unsigned long) sig;
5677 env->regs[1] = (unsigned long) &frame->info;
5678 env->regs[2] = (unsigned long) &frame->uc;
5679 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
5680
5681 unlock_user_struct(frame, frame_addr, 1);
5682 return;
5683
5684give_sigsegv:
5685 if (sig == TARGET_SIGSEGV) {
5686 ka->_sa_handler = TARGET_SIG_DFL;
5687 }
5688 force_sig(TARGET_SIGSEGV /* , current */);
5689}
5690
5691long do_rt_sigreturn(CPUTLGState *env)
5692{
5693 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
5694 struct target_rt_sigframe *frame;
5695 sigset_t set;
5696
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005697 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005698 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5699 goto badframe;
5700 }
5701 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
5702 do_sigprocmask(SIG_SETMASK, &set, NULL);
5703
5704 restore_sigcontext(env, &frame->uc.tuc_mcontext);
5705 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
5706 uc.tuc_stack),
5707 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
5708 goto badframe;
5709 }
5710
5711 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01005712 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08005713
5714
5715 badframe:
5716 unlock_user_struct(frame, frame_addr, 0);
5717 force_sig(TARGET_SIGSEGV);
5718}
5719
bellardb346ff42003-06-15 20:05:50 +00005720#else
5721
pbrook624f7972008-05-31 16:11:38 +00005722static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005723 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005724{
5725 fprintf(stderr, "setup_frame: not implemented\n");
5726}
5727
pbrook624f7972008-05-31 16:11:38 +00005728static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005729 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005730 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005731{
5732 fprintf(stderr, "setup_rt_frame: not implemented\n");
5733}
5734
Andreas Färber9349b4f2012-03-14 01:38:32 +01005735long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005736{
5737 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005738 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005739}
5740
Andreas Färber9349b4f2012-03-14 01:38:32 +01005741long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005742{
5743 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005744 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005745}
5746
bellard66fb9762003-03-23 01:06:05 +00005747#endif
5748
Andreas Färber9349b4f2012-03-14 01:38:32 +01005749void process_pending_signals(CPUArchState *cpu_env)
bellard66fb9762003-03-23 01:06:05 +00005750{
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005751 CPUState *cpu = ENV_GET_CPU(cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005752 int sig;
blueswir1992f48a2007-10-14 16:27:31 +00005753 abi_ulong handler;
bellard9de5e442003-03-23 16:49:39 +00005754 sigset_t set, old_set;
Anthony Liguoric227f092009-10-01 16:12:16 -05005755 target_sigset_t target_old_set;
pbrook624f7972008-05-31 16:11:38 +00005756 struct emulated_sigtable *k;
5757 struct target_sigaction *sa;
bellard66fb9762003-03-23 01:06:05 +00005758 struct sigqueue *q;
Andreas Färber0429a972013-08-26 18:14:44 +02005759 TaskState *ts = cpu->opaque;
ths3b46e622007-09-17 08:09:54 +00005760
pbrook624f7972008-05-31 16:11:38 +00005761 if (!ts->signal_pending)
bellard31e31b82003-02-18 22:55:36 +00005762 return;
5763
pbrook624f7972008-05-31 16:11:38 +00005764 /* FIXME: This is not threadsafe. */
5765 k = ts->sigtab;
bellard66fb9762003-03-23 01:06:05 +00005766 for(sig = 1; sig <= TARGET_NSIG; sig++) {
5767 if (k->pending)
bellard31e31b82003-02-18 22:55:36 +00005768 goto handle_signal;
bellard66fb9762003-03-23 01:06:05 +00005769 k++;
bellard31e31b82003-02-18 22:55:36 +00005770 }
5771 /* if no signal is pending, just return */
pbrook624f7972008-05-31 16:11:38 +00005772 ts->signal_pending = 0;
bellard31e31b82003-02-18 22:55:36 +00005773 return;
bellard66fb9762003-03-23 01:06:05 +00005774
bellard31e31b82003-02-18 22:55:36 +00005775 handle_signal:
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005776 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00005777 /* dequeue signal */
5778 q = k->first;
5779 k->first = q->next;
5780 if (!k->first)
5781 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00005782
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005783 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00005784 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00005785 sa = NULL;
5786 handler = TARGET_SIG_IGN;
5787 } else {
5788 sa = &sigact_table[sig - 1];
5789 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00005790 }
bellard66fb9762003-03-23 01:06:05 +00005791
Peter Maydella7ec0f92014-03-14 14:36:56 +00005792 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
5793 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
5794 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
5795 * because it got a real MMU fault), and treat as if default handler.
5796 */
5797 handler = TARGET_SIG_DFL;
5798 }
5799
bellard66fb9762003-03-23 01:06:05 +00005800 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00005801 /* default handler : ignore some signal. The other are job control or fatal */
5802 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5803 kill(getpid(),SIGSTOP);
5804 } else if (sig != TARGET_SIGCHLD &&
5805 sig != TARGET_SIGURG &&
5806 sig != TARGET_SIGWINCH &&
5807 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +00005808 force_sig(sig);
5809 }
5810 } else if (handler == TARGET_SIG_IGN) {
5811 /* ignore sig */
5812 } else if (handler == TARGET_SIG_ERR) {
5813 force_sig(sig);
5814 } else {
bellard9de5e442003-03-23 16:49:39 +00005815 /* compute the blocked signals during the handler execution */
pbrook624f7972008-05-31 16:11:38 +00005816 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00005817 /* SA_NODEFER indicates that the current signal should not be
5818 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00005819 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00005820 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00005821
bellard9de5e442003-03-23 16:49:39 +00005822 /* block signals in the handler using Linux */
Alex Barcelo1c275922014-03-14 14:36:55 +00005823 do_sigprocmask(SIG_BLOCK, &set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005824 /* save the previous blocked signal state to restore it at the
5825 end of the signal execution (see do_sigreturn) */
bellard92319442004-06-19 16:58:13 +00005826 host_to_target_sigset_internal(&target_old_set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005827
bellardbc8a22c2003-03-30 21:02:40 +00005828 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00005829#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00005830 {
5831 CPUX86State *env = cpu_env;
5832 if (env->eflags & VM_MASK)
5833 save_v86_state(env);
5834 }
5835#endif
bellard9de5e442003-03-23 16:49:39 +00005836 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08005837#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Chen Gangbf0f60a2015-09-27 08:10:18 +08005838 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX)
Richard Hendersonff970902013-02-10 10:30:42 -08005839 /* These targets do not have traditional signals. */
5840 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
5841#else
pbrook624f7972008-05-31 16:11:38 +00005842 if (sa->sa_flags & TARGET_SA_SIGINFO)
5843 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005844 else
pbrook624f7972008-05-31 16:11:38 +00005845 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005846#endif
pbrook624f7972008-05-31 16:11:38 +00005847 if (sa->sa_flags & TARGET_SA_RESETHAND)
5848 sa->_sa_handler = TARGET_SIG_DFL;
bellard31e31b82003-02-18 22:55:36 +00005849 }
bellard66fb9762003-03-23 01:06:05 +00005850 if (q != &k->info)
pbrook624f7972008-05-31 16:11:38 +00005851 free_sigqueue(cpu_env, q);
bellard31e31b82003-02-18 22:55:36 +00005852}