blob: 29529563ea4540240f218d6237c440900fe33079 [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 */
19#include <stdlib.h>
20#include <stdio.h>
bellard66fb9762003-03-23 01:06:05 +000021#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000022#include <stdarg.h>
bellard2677e102003-04-10 00:03:27 +000023#include <unistd.h>
bellard66fb9762003-03-23 01:06:05 +000024#include <errno.h>
aurel32603e4fd2009-04-15 16:18:38 +000025#include <assert.h>
bellard31e31b82003-02-18 22:55:36 +000026#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030027#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000028
bellard3ef693a2003-03-23 20:17:16 +000029#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000030#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000031#include "target_signal.h"
bellard66fb9762003-03-23 01:06:05 +000032
33//#define DEBUG_SIGNAL
34
blueswir1249c4c32008-10-05 11:09:37 +000035static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000036 .ss_sp = 0,
37 .ss_size = 0,
38 .ss_flags = TARGET_SS_DISABLE,
39};
40
pbrook624f7972008-05-31 16:11:38 +000041static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000042
ths5fafdf22007-09-16 21:08:06 +000043static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000044 void *puc);
45
Arnaud Patard3ca05582009-03-30 01:18:20 +020046static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000047 [SIGHUP] = TARGET_SIGHUP,
48 [SIGINT] = TARGET_SIGINT,
49 [SIGQUIT] = TARGET_SIGQUIT,
50 [SIGILL] = TARGET_SIGILL,
51 [SIGTRAP] = TARGET_SIGTRAP,
52 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000053/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000054 [SIGBUS] = TARGET_SIGBUS,
55 [SIGFPE] = TARGET_SIGFPE,
56 [SIGKILL] = TARGET_SIGKILL,
57 [SIGUSR1] = TARGET_SIGUSR1,
58 [SIGSEGV] = TARGET_SIGSEGV,
59 [SIGUSR2] = TARGET_SIGUSR2,
60 [SIGPIPE] = TARGET_SIGPIPE,
61 [SIGALRM] = TARGET_SIGALRM,
62 [SIGTERM] = TARGET_SIGTERM,
63#ifdef SIGSTKFLT
64 [SIGSTKFLT] = TARGET_SIGSTKFLT,
65#endif
66 [SIGCHLD] = TARGET_SIGCHLD,
67 [SIGCONT] = TARGET_SIGCONT,
68 [SIGSTOP] = TARGET_SIGSTOP,
69 [SIGTSTP] = TARGET_SIGTSTP,
70 [SIGTTIN] = TARGET_SIGTTIN,
71 [SIGTTOU] = TARGET_SIGTTOU,
72 [SIGURG] = TARGET_SIGURG,
73 [SIGXCPU] = TARGET_SIGXCPU,
74 [SIGXFSZ] = TARGET_SIGXFSZ,
75 [SIGVTALRM] = TARGET_SIGVTALRM,
76 [SIGPROF] = TARGET_SIGPROF,
77 [SIGWINCH] = TARGET_SIGWINCH,
78 [SIGIO] = TARGET_SIGIO,
79 [SIGPWR] = TARGET_SIGPWR,
80 [SIGSYS] = TARGET_SIGSYS,
81 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000082 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080083 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000084 To fix this properly we need to do manual signal delivery multiplexed
85 over a single host signal. */
86 [__SIGRTMIN] = __SIGRTMAX,
87 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000088};
Arnaud Patard3ca05582009-03-30 01:18:20 +020089static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000090
thsa04e1342007-09-27 13:57:58 +000091static inline int on_sig_stack(unsigned long sp)
92{
93 return (sp - target_sigaltstack_used.ss_sp
94 < target_sigaltstack_used.ss_size);
95}
96
97static inline int sas_ss_flags(unsigned long sp)
98{
99 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
100 : on_sig_stack(sp) ? SS_ONSTACK : 0);
101}
102
pbrook1d9d8b52009-04-16 15:17:02 +0000103int host_to_target_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 host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000108}
109
pbrook4cb05962008-05-30 18:05:19 +0000110int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000111{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100112 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000113 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000114 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000115}
116
Anthony Liguoric227f092009-10-01 16:12:16 -0500117static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000118{
119 memset(set, 0, sizeof(*set));
120}
121
Anthony Liguoric227f092009-10-01 16:12:16 -0500122static inline void target_sigaddset(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 set->sig[signum / TARGET_NSIG_BPW] |= mask;
127}
128
Anthony Liguoric227f092009-10-01 16:12:16 -0500129static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000130{
131 signum--;
132 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
133 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
134}
135
Anthony Liguoric227f092009-10-01 16:12:16 -0500136static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000137 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000138{
139 int i;
pbrookf5545b52008-05-30 22:37:07 +0000140 target_sigemptyset(d);
141 for (i = 1; i <= TARGET_NSIG; i++) {
142 if (sigismember(s, i)) {
143 target_sigaddset(d, host_to_target_signal(i));
144 }
bellard9e5f5282003-07-13 17:33:54 +0000145 }
bellard66fb9762003-03-23 01:06:05 +0000146}
147
Anthony Liguoric227f092009-10-01 16:12:16 -0500148void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000149{
Anthony Liguoric227f092009-10-01 16:12:16 -0500150 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000151 int i;
152
153 host_to_target_sigset_internal(&d1, s);
154 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200155 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000156}
157
blueswir18fcd3692008-08-17 20:26:25 +0000158static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500159 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000160{
161 int i;
pbrookf5545b52008-05-30 22:37:07 +0000162 sigemptyset(d);
163 for (i = 1; i <= TARGET_NSIG; i++) {
164 if (target_sigismember(s, i)) {
165 sigaddset(d, target_to_host_signal(i));
166 }
167 }
bellard66fb9762003-03-23 01:06:05 +0000168}
169
Anthony Liguoric227f092009-10-01 16:12:16 -0500170void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000171{
Anthony Liguoric227f092009-10-01 16:12:16 -0500172 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000173 int i;
174
175 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200176 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000177 target_to_host_sigset_internal(d, &s1);
178}
ths3b46e622007-09-17 08:09:54 +0000179
blueswir1992f48a2007-10-14 16:27:31 +0000180void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000181 const sigset_t *sigset)
182{
Anthony Liguoric227f092009-10-01 16:12:16 -0500183 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000184 host_to_target_sigset(&d, sigset);
185 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000186}
187
ths5fafdf22007-09-16 21:08:06 +0000188void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000189 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000190{
Anthony Liguoric227f092009-10-01 16:12:16 -0500191 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000192 int i;
193
194 d.sig[0] = *old_sigset;
195 for(i = 1;i < TARGET_NSIG_WORDS; i++)
196 d.sig[i] = 0;
197 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000198}
199
Alex Barcelo1c275922014-03-14 14:36:55 +0000200/* Wrapper for sigprocmask function
201 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
202 * are host signal set, not guest ones. This wraps the sigprocmask host calls
203 * that should be protected (calls originated from guest)
204 */
205int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
206{
Peter Maydella7ec0f92014-03-14 14:36:56 +0000207 int ret;
208 sigset_t val;
209 sigset_t *temp = NULL;
210 CPUState *cpu = thread_cpu;
211 TaskState *ts = (TaskState *)cpu->opaque;
212 bool segv_was_blocked = ts->sigsegv_blocked;
213
214 if (set) {
215 bool has_sigsegv = sigismember(set, SIGSEGV);
216 val = *set;
217 temp = &val;
218
219 sigdelset(temp, SIGSEGV);
220
221 switch (how) {
222 case SIG_BLOCK:
223 if (has_sigsegv) {
224 ts->sigsegv_blocked = true;
225 }
226 break;
227 case SIG_UNBLOCK:
228 if (has_sigsegv) {
229 ts->sigsegv_blocked = false;
230 }
231 break;
232 case SIG_SETMASK:
233 ts->sigsegv_blocked = has_sigsegv;
234 break;
235 default:
236 g_assert_not_reached();
237 }
238 }
239
240 ret = sigprocmask(how, temp, oldset);
241
242 if (oldset && segv_was_blocked) {
243 sigaddset(oldset, SIGSEGV);
244 }
245
246 return ret;
Alex Barcelo1c275922014-03-14 14:36:55 +0000247}
248
bellard9de5e442003-03-23 16:49:39 +0000249/* siginfo conversion */
250
Anthony Liguoric227f092009-10-01 16:12:16 -0500251static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000252 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000253{
Richard Hendersona05c6402012-09-15 11:34:20 -0700254 int sig = host_to_target_signal(info->si_signo);
bellard9de5e442003-03-23 16:49:39 +0000255 tinfo->si_signo = sig;
256 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000257 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700258
259 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
260 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
261 /* Should never come here, but who knows. The information for
262 the target is irrelevant. */
bellard9de5e442003-03-23 16:49:39 +0000263 tinfo->_sifields._sigfault._addr = 0;
Richard Hendersona05c6402012-09-15 11:34:20 -0700264 } else if (sig == TARGET_SIGIO) {
265 tinfo->_sifields._sigpoll._band = info->si_band;
ths7f7f7c82007-07-12 11:02:46 +0000266 tinfo->_sifields._sigpoll._fd = info->si_fd;
Richard Hendersona05c6402012-09-15 11:34:20 -0700267 } else if (sig == TARGET_SIGCHLD) {
268 tinfo->_sifields._sigchld._pid = info->si_pid;
269 tinfo->_sifields._sigchld._uid = info->si_uid;
270 tinfo->_sifields._sigchld._status
271 = host_to_target_waitstatus(info->si_status);
272 tinfo->_sifields._sigchld._utime = info->si_utime;
273 tinfo->_sifields._sigchld._stime = info->si_stime;
bellard9de5e442003-03-23 16:49:39 +0000274 } else if (sig >= TARGET_SIGRTMIN) {
275 tinfo->_sifields._rt._pid = info->si_pid;
276 tinfo->_sifields._rt._uid = info->si_uid;
277 /* XXX: potential problem if 64 bit */
Richard Hendersona05c6402012-09-15 11:34:20 -0700278 tinfo->_sifields._rt._sigval.sival_ptr
279 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
bellard9de5e442003-03-23 16:49:39 +0000280 }
bellard66fb9762003-03-23 01:06:05 +0000281}
282
Anthony Liguoric227f092009-10-01 16:12:16 -0500283static void tswap_siginfo(target_siginfo_t *tinfo,
284 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000285{
Richard Hendersona05c6402012-09-15 11:34:20 -0700286 int sig = info->si_signo;
bellard9de5e442003-03-23 16:49:39 +0000287 tinfo->si_signo = tswap32(sig);
288 tinfo->si_errno = tswap32(info->si_errno);
289 tinfo->si_code = tswap32(info->si_code);
Richard Hendersona05c6402012-09-15 11:34:20 -0700290
291 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
292 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
293 tinfo->_sifields._sigfault._addr
294 = tswapal(info->_sifields._sigfault._addr);
295 } else if (sig == TARGET_SIGIO) {
296 tinfo->_sifields._sigpoll._band
297 = tswap32(info->_sifields._sigpoll._band);
298 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
299 } else if (sig == TARGET_SIGCHLD) {
300 tinfo->_sifields._sigchld._pid
301 = tswap32(info->_sifields._sigchld._pid);
302 tinfo->_sifields._sigchld._uid
303 = tswap32(info->_sifields._sigchld._uid);
304 tinfo->_sifields._sigchld._status
305 = tswap32(info->_sifields._sigchld._status);
306 tinfo->_sifields._sigchld._utime
307 = tswapal(info->_sifields._sigchld._utime);
308 tinfo->_sifields._sigchld._stime
309 = tswapal(info->_sifields._sigchld._stime);
bellard9de5e442003-03-23 16:49:39 +0000310 } else if (sig >= TARGET_SIGRTMIN) {
311 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
312 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
Richard Hendersona05c6402012-09-15 11:34:20 -0700313 tinfo->_sifields._rt._sigval.sival_ptr
314 = tswapal(info->_sifields._rt._sigval.sival_ptr);
bellard9de5e442003-03-23 16:49:39 +0000315 }
316}
317
318
Anthony Liguoric227f092009-10-01 16:12:16 -0500319void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000320{
321 host_to_target_siginfo_noswap(tinfo, info);
322 tswap_siginfo(tinfo, tinfo);
323}
324
325/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000326/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500327void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000328{
329 info->si_signo = tswap32(tinfo->si_signo);
330 info->si_errno = tswap32(tinfo->si_errno);
331 info->si_code = tswap32(tinfo->si_code);
bellard9de5e442003-03-23 16:49:39 +0000332 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
333 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
ths5fafdf22007-09-16 21:08:06 +0000334 info->si_value.sival_ptr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200335 (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr);
bellard66fb9762003-03-23 01:06:05 +0000336}
337
aurel32ca587a82008-12-18 22:44:13 +0000338static int fatal_signal (int sig)
339{
340 switch (sig) {
341 case TARGET_SIGCHLD:
342 case TARGET_SIGURG:
343 case TARGET_SIGWINCH:
344 /* Ignored by default. */
345 return 0;
346 case TARGET_SIGCONT:
347 case TARGET_SIGSTOP:
348 case TARGET_SIGTSTP:
349 case TARGET_SIGTTIN:
350 case TARGET_SIGTTOU:
351 /* Job control signals. */
352 return 0;
353 default:
354 return 1;
355 }
356}
357
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300358/* returns 1 if given signal should dump core if not handled */
359static int core_dump_signal(int sig)
360{
361 switch (sig) {
362 case TARGET_SIGABRT:
363 case TARGET_SIGFPE:
364 case TARGET_SIGILL:
365 case TARGET_SIGQUIT:
366 case TARGET_SIGSEGV:
367 case TARGET_SIGTRAP:
368 case TARGET_SIGBUS:
369 return (1);
370 default:
371 return (0);
372 }
373}
374
bellard31e31b82003-02-18 22:55:36 +0000375void signal_init(void)
376{
377 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000378 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000379 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000380 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000381
bellard9e5f5282003-07-13 17:33:54 +0000382 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200383 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000384 if (host_to_target_signal_table[i] == 0)
385 host_to_target_signal_table[i] = i;
386 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200387 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000388 j = host_to_target_signal_table[i];
389 target_to_host_signal_table[j] = i;
390 }
ths3b46e622007-09-17 08:09:54 +0000391
bellard9de5e442003-03-23 16:49:39 +0000392 /* set all host signal handlers. ALL signals are blocked during
393 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000394 memset(sigact_table, 0, sizeof(sigact_table));
395
bellard9de5e442003-03-23 16:49:39 +0000396 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000397 act.sa_flags = SA_SIGINFO;
398 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000399 for(i = 1; i <= TARGET_NSIG; i++) {
400 host_sig = target_to_host_signal(i);
401 sigaction(host_sig, NULL, &oact);
402 if (oact.sa_sigaction == (void *)SIG_IGN) {
403 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
404 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
405 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
406 }
407 /* If there's already a handler installed then something has
408 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000409 /* Install some handlers for our own use. We need at least
410 SIGSEGV and SIGBUS, to detect exceptions. We can not just
411 trap all signals because it affects syscall interrupt
412 behavior. But do trap all default-fatal signals. */
413 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000414 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000415 }
bellard31e31b82003-02-18 22:55:36 +0000416}
417
bellard66fb9762003-03-23 01:06:05 +0000418/* signal queue handling */
419
Andreas Färber9349b4f2012-03-14 01:38:32 +0100420static inline struct sigqueue *alloc_sigqueue(CPUArchState *env)
bellard66fb9762003-03-23 01:06:05 +0000421{
Andreas Färber0429a972013-08-26 18:14:44 +0200422 CPUState *cpu = ENV_GET_CPU(env);
423 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000424 struct sigqueue *q = ts->first_free;
bellard66fb9762003-03-23 01:06:05 +0000425 if (!q)
426 return NULL;
pbrook624f7972008-05-31 16:11:38 +0000427 ts->first_free = q->next;
bellard66fb9762003-03-23 01:06:05 +0000428 return q;
429}
430
Andreas Färber9349b4f2012-03-14 01:38:32 +0100431static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
bellard66fb9762003-03-23 01:06:05 +0000432{
Andreas Färber0429a972013-08-26 18:14:44 +0200433 CPUState *cpu = ENV_GET_CPU(env);
434 TaskState *ts = cpu->opaque;
435
pbrook624f7972008-05-31 16:11:38 +0000436 q->next = ts->first_free;
437 ts->first_free = q;
bellard66fb9762003-03-23 01:06:05 +0000438}
439
bellard9de5e442003-03-23 16:49:39 +0000440/* abort execution with signal */
Riku Voipio66393fb2009-12-04 15:16:32 +0200441static void QEMU_NORETURN force_sig(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000442{
Andreas Färber0429a972013-08-26 18:14:44 +0200443 CPUState *cpu = thread_cpu;
444 CPUArchState *env = cpu->env_ptr;
445 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300446 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000447 struct sigaction act;
Riku Voipio66393fb2009-12-04 15:16:32 +0200448 host_sig = target_to_host_signal(target_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200449 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000450
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300451 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200452 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300453 stop_all_tasks();
454 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200455 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300456 }
457 if (core_dumped) {
458 /* we already dumped the core of target process, we don't want
459 * a coredump of qemu itself */
460 struct rlimit nodump;
461 getrlimit(RLIMIT_CORE, &nodump);
462 nodump.rlim_cur=0;
463 setrlimit(RLIMIT_CORE, &nodump);
464 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200465 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300466 }
467
Stefan Weil0c587512011-04-28 17:20:32 +0200468 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000469 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
470 * a negative value. To get the proper exit code we need to
471 * actually die from an uncaught signal. Here the default signal
472 * handler is installed, we send ourself a signal and we wait for
473 * it to arrive. */
474 sigfillset(&act.sa_mask);
475 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000476 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000477 sigaction(host_sig, &act, NULL);
478
479 /* For some reason raise(host_sig) doesn't send the signal when
480 * statically linked on x86-64. */
481 kill(getpid(), host_sig);
482
483 /* Make sure the signal isn't masked (just reuse the mask inside
484 of act) */
485 sigdelset(&act.sa_mask, host_sig);
486 sigsuspend(&act.sa_mask);
487
488 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000489 abort();
bellard66fb9762003-03-23 01:06:05 +0000490}
491
bellard9de5e442003-03-23 16:49:39 +0000492/* queue a signal so that it will be send to the virtual CPU as soon
493 as possible */
Andreas Färber9349b4f2012-03-14 01:38:32 +0100494int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000495{
Andreas Färber0429a972013-08-26 18:14:44 +0200496 CPUState *cpu = ENV_GET_CPU(env);
497 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000498 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000499 struct sigqueue *q, **pq;
blueswir1992f48a2007-10-14 16:27:31 +0000500 abi_ulong handler;
aurel32ca587a82008-12-18 22:44:13 +0000501 int queue;
bellard66fb9762003-03-23 01:06:05 +0000502
bellard9de5e442003-03-23 16:49:39 +0000503#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000504 fprintf(stderr, "queue_signal: sig=%d\n",
bellard9de5e442003-03-23 16:49:39 +0000505 sig);
bellard66fb9762003-03-23 01:06:05 +0000506#endif
pbrook624f7972008-05-31 16:11:38 +0000507 k = &ts->sigtab[sig - 1];
aurel32ca587a82008-12-18 22:44:13 +0000508 queue = gdb_queuesig ();
pbrook624f7972008-05-31 16:11:38 +0000509 handler = sigact_table[sig - 1]._sa_handler;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000510
511 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
512 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
513 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
514 * because it got a real MMU fault). A blocked SIGSEGV in that
515 * situation is treated as if using the default handler. This is
516 * not correct if some other process has randomly sent us a SIGSEGV
517 * via kill(), but that is not easy to distinguish at this point,
518 * so we assume it doesn't happen.
519 */
520 handler = TARGET_SIG_DFL;
521 }
522
aurel32ca587a82008-12-18 22:44:13 +0000523 if (!queue && handler == TARGET_SIG_DFL) {
ths60b19692008-11-27 15:47:15 +0000524 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
525 kill(getpid(),SIGSTOP);
526 return 0;
527 } else
bellard66fb9762003-03-23 01:06:05 +0000528 /* default handler : ignore some signal. The other are fatal */
ths5fafdf22007-09-16 21:08:06 +0000529 if (sig != TARGET_SIGCHLD &&
530 sig != TARGET_SIGURG &&
ths60b19692008-11-27 15:47:15 +0000531 sig != TARGET_SIGWINCH &&
532 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +0000533 force_sig(sig);
bellard9de5e442003-03-23 16:49:39 +0000534 } else {
535 return 0; /* indicate ignored */
bellard66fb9762003-03-23 01:06:05 +0000536 }
aurel32ca587a82008-12-18 22:44:13 +0000537 } else if (!queue && handler == TARGET_SIG_IGN) {
bellard66fb9762003-03-23 01:06:05 +0000538 /* ignore signal */
bellard9de5e442003-03-23 16:49:39 +0000539 return 0;
aurel32ca587a82008-12-18 22:44:13 +0000540 } else if (!queue && handler == TARGET_SIG_ERR) {
bellard66fb9762003-03-23 01:06:05 +0000541 force_sig(sig);
542 } else {
bellard9de5e442003-03-23 16:49:39 +0000543 pq = &k->first;
544 if (sig < TARGET_SIGRTMIN) {
545 /* if non real time signal, we queue exactly one signal */
546 if (!k->pending)
547 q = &k->info;
548 else
549 return 0;
550 } else {
551 if (!k->pending) {
552 /* first signal */
553 q = &k->info;
554 } else {
pbrook624f7972008-05-31 16:11:38 +0000555 q = alloc_sigqueue(env);
bellard9de5e442003-03-23 16:49:39 +0000556 if (!q)
557 return -EAGAIN;
558 while (*pq != NULL)
559 pq = &(*pq)->next;
560 }
561 }
562 *pq = q;
563 q->info = *info;
564 q->next = NULL;
565 k->pending = 1;
566 /* signal that a new signal is pending */
pbrook624f7972008-05-31 16:11:38 +0000567 ts->signal_pending = 1;
bellard9de5e442003-03-23 16:49:39 +0000568 return 1; /* indicates that the signal was queued */
569 }
570}
571
ths5fafdf22007-09-16 21:08:06 +0000572static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000573 void *puc)
574{
Andreas Färbera2247f82013-06-09 19:47:04 +0200575 CPUArchState *env = thread_cpu->env_ptr;
bellard9de5e442003-03-23 16:49:39 +0000576 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500577 target_siginfo_t tinfo;
bellard9de5e442003-03-23 16:49:39 +0000578
579 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000580 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000581 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000582 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000583 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000584 return;
585 }
586
587 /* get target signal number */
588 sig = host_to_target_signal(host_signum);
589 if (sig < 1 || sig > TARGET_NSIG)
590 return;
591#if defined(DEBUG_SIGNAL)
bellardbc8a22c2003-03-30 21:02:40 +0000592 fprintf(stderr, "qemu: got signal %d\n", sig);
bellard9de5e442003-03-23 16:49:39 +0000593#endif
594 host_to_target_siginfo_noswap(&tinfo, info);
Andreas Färbera2247f82013-06-09 19:47:04 +0200595 if (queue_signal(env, sig, &tinfo) == 1) {
bellard9de5e442003-03-23 16:49:39 +0000596 /* interrupt the virtual CPU as soon as possible */
Andreas Färbera2247f82013-06-09 19:47:04 +0200597 cpu_exit(thread_cpu);
bellard66fb9762003-03-23 01:06:05 +0000598 }
bellard31e31b82003-02-18 22:55:36 +0000599}
600
ths0da46a62007-10-20 20:23:07 +0000601/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000602/* compare linux/kernel/signal.c:do_sigaltstack() */
603abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000604{
605 int ret;
606 struct target_sigaltstack oss;
607
608 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000609 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000610 {
611 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
612 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
613 __put_user(sas_ss_flags(sp), &oss.ss_flags);
614 }
615
bellard579a97f2007-11-11 14:26:47 +0000616 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000617 {
bellard579a97f2007-11-11 14:26:47 +0000618 struct target_sigaltstack *uss;
619 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500620 size_t minstacksize = TARGET_MINSIGSTKSZ;
621
622#if defined(TARGET_PPC64)
623 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
624 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
625 if (get_ppc64_abi(image) > 1) {
626 minstacksize = 4096;
627 }
628#endif
thsa04e1342007-09-27 13:57:58 +0000629
ths0da46a62007-10-20 20:23:07 +0000630 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300631 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000632 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300633 }
634 __get_user(ss.ss_sp, &uss->ss_sp);
635 __get_user(ss.ss_size, &uss->ss_size);
636 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000637 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000638
ths0da46a62007-10-20 20:23:07 +0000639 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000640 if (on_sig_stack(sp))
641 goto out;
642
ths0da46a62007-10-20 20:23:07 +0000643 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000644 if (ss.ss_flags != TARGET_SS_DISABLE
645 && ss.ss_flags != TARGET_SS_ONSTACK
646 && ss.ss_flags != 0)
647 goto out;
648
649 if (ss.ss_flags == TARGET_SS_DISABLE) {
650 ss.ss_size = 0;
651 ss.ss_sp = 0;
652 } else {
ths0da46a62007-10-20 20:23:07 +0000653 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500654 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000655 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500656 }
thsa04e1342007-09-27 13:57:58 +0000657 }
658
659 target_sigaltstack_used.ss_sp = ss.ss_sp;
660 target_sigaltstack_used.ss_size = ss.ss_size;
661 }
662
bellard579a97f2007-11-11 14:26:47 +0000663 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000664 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000665 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000666 goto out;
thsa04e1342007-09-27 13:57:58 +0000667 }
668
669 ret = 0;
670out:
671 return ret;
672}
673
ths0da46a62007-10-20 20:23:07 +0000674/* do_sigaction() return host values and errnos */
bellard66fb9762003-03-23 01:06:05 +0000675int do_sigaction(int sig, const struct target_sigaction *act,
676 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000677{
pbrook624f7972008-05-31 16:11:38 +0000678 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000679 struct sigaction act1;
680 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000681 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000682
ths2a913eb2008-11-27 15:46:25 +0000683 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
bellard66fb9762003-03-23 01:06:05 +0000684 return -EINVAL;
685 k = &sigact_table[sig - 1];
bellard773b93e2004-01-04 17:15:59 +0000686#if defined(DEBUG_SIGNAL)
Blue Swirl0bf9e312009-07-20 17:19:25 +0000687 fprintf(stderr, "sigaction sig=%d act=0x%p, oact=0x%p\n",
688 sig, act, oact);
bellard66fb9762003-03-23 01:06:05 +0000689#endif
690 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800691 __put_user(k->_sa_handler, &oact->_sa_handler);
692 __put_user(k->sa_flags, &oact->sa_flags);
ths388bb212007-05-13 13:58:00 +0000693#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800694 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000695#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800696 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000697 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000698 }
699 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000700 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800701 __get_user(k->_sa_handler, &act->_sa_handler);
702 __get_user(k->sa_flags, &act->sa_flags);
ths388bb212007-05-13 13:58:00 +0000703#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800704 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000705#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800706 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000707 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000708
709 /* we update the host linux signal state */
710 host_sig = target_to_host_signal(sig);
711 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
712 sigfillset(&act1.sa_mask);
713 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000714 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000715 act1.sa_flags |= SA_RESTART;
716 /* NOTE: it is important to update the host kernel signal
717 ignore state to avoid getting unexpected interrupted
718 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000719 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000720 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000721 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000722 if (fatal_signal (sig))
723 act1.sa_sigaction = host_signal_handler;
724 else
725 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000726 } else {
727 act1.sa_sigaction = host_signal_handler;
728 }
ths0da46a62007-10-20 20:23:07 +0000729 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000730 }
bellard66fb9762003-03-23 01:06:05 +0000731 }
ths0da46a62007-10-20 20:23:07 +0000732 return ret;
bellard66fb9762003-03-23 01:06:05 +0000733}
bellard31e31b82003-02-18 22:55:36 +0000734
Riku Voipiob0fd8d12014-04-23 10:46:13 +0300735static inline void copy_siginfo_to_user(target_siginfo_t *tinfo,
Anthony Liguoric227f092009-10-01 16:12:16 -0500736 const target_siginfo_t *info)
bellard43fff232003-07-09 19:31:39 +0000737{
738 tswap_siginfo(tinfo, info);
bellard43fff232003-07-09 19:31:39 +0000739}
740
thsc3b5bc82007-12-02 06:31:25 +0000741static inline int current_exec_domain_sig(int sig)
742{
743 return /* current->exec_domain && current->exec_domain->signal_invmap
744 && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig;
745}
746
bellard459a4012007-11-11 19:45:10 +0000747#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
bellard66fb9762003-03-23 01:06:05 +0000748
749/* from the Linux kernel */
750
751struct target_fpreg {
752 uint16_t significand[4];
753 uint16_t exponent;
754};
755
756struct target_fpxreg {
757 uint16_t significand[4];
758 uint16_t exponent;
759 uint16_t padding[3];
760};
761
762struct target_xmmreg {
blueswir1992f48a2007-10-14 16:27:31 +0000763 abi_ulong element[4];
bellard66fb9762003-03-23 01:06:05 +0000764};
765
766struct target_fpstate {
767 /* Regular FPU environment */
blueswir1992f48a2007-10-14 16:27:31 +0000768 abi_ulong cw;
769 abi_ulong sw;
770 abi_ulong tag;
771 abi_ulong ipoff;
772 abi_ulong cssel;
773 abi_ulong dataoff;
774 abi_ulong datasel;
bellard66fb9762003-03-23 01:06:05 +0000775 struct target_fpreg _st[8];
776 uint16_t status;
777 uint16_t magic; /* 0xffff = regular FPU data only */
778
779 /* FXSR FPU environment */
blueswir1992f48a2007-10-14 16:27:31 +0000780 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
781 abi_ulong mxcsr;
782 abi_ulong reserved;
bellard66fb9762003-03-23 01:06:05 +0000783 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
784 struct target_xmmreg _xmm[8];
blueswir1992f48a2007-10-14 16:27:31 +0000785 abi_ulong padding[56];
bellard66fb9762003-03-23 01:06:05 +0000786};
787
788#define X86_FXSR_MAGIC 0x0000
789
790struct target_sigcontext {
791 uint16_t gs, __gsh;
792 uint16_t fs, __fsh;
793 uint16_t es, __esh;
794 uint16_t ds, __dsh;
blueswir1992f48a2007-10-14 16:27:31 +0000795 abi_ulong edi;
796 abi_ulong esi;
797 abi_ulong ebp;
798 abi_ulong esp;
799 abi_ulong ebx;
800 abi_ulong edx;
801 abi_ulong ecx;
802 abi_ulong eax;
803 abi_ulong trapno;
804 abi_ulong err;
805 abi_ulong eip;
bellard66fb9762003-03-23 01:06:05 +0000806 uint16_t cs, __csh;
blueswir1992f48a2007-10-14 16:27:31 +0000807 abi_ulong eflags;
808 abi_ulong esp_at_signal;
bellard66fb9762003-03-23 01:06:05 +0000809 uint16_t ss, __ssh;
blueswir1992f48a2007-10-14 16:27:31 +0000810 abi_ulong fpstate; /* pointer */
811 abi_ulong oldmask;
812 abi_ulong cr2;
bellard66fb9762003-03-23 01:06:05 +0000813};
814
bellard66fb9762003-03-23 01:06:05 +0000815struct target_ucontext {
blueswir1992f48a2007-10-14 16:27:31 +0000816 abi_ulong tuc_flags;
817 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -0500818 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +0000819 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -0500820 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000821};
822
823struct sigframe
824{
blueswir1992f48a2007-10-14 16:27:31 +0000825 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000826 int sig;
827 struct target_sigcontext sc;
828 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000829 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000830 char retcode[8];
831};
832
833struct rt_sigframe
834{
blueswir1992f48a2007-10-14 16:27:31 +0000835 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000836 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000837 abi_ulong pinfo;
838 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000839 struct target_siginfo info;
840 struct target_ucontext uc;
841 struct target_fpstate fpstate;
842 char retcode[8];
843};
844
845/*
846 * Set up a signal frame.
847 */
848
bellard66fb9762003-03-23 01:06:05 +0000849/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300850static void setup_sigcontext(struct target_sigcontext *sc,
851 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
852 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000853{
Andreas Färber27103422013-08-26 08:31:06 +0200854 CPUState *cs = CPU(x86_env_get_cpu(env));
Andreas Färber27103422013-08-26 08:31:06 +0200855 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +0000856
bellard579a97f2007-11-11 14:26:47 +0000857 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300858 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
859 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
860 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
861 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
862 __put_user(env->regs[R_EDI], &sc->edi);
863 __put_user(env->regs[R_ESI], &sc->esi);
864 __put_user(env->regs[R_EBP], &sc->ebp);
865 __put_user(env->regs[R_ESP], &sc->esp);
866 __put_user(env->regs[R_EBX], &sc->ebx);
867 __put_user(env->regs[R_EDX], &sc->edx);
868 __put_user(env->regs[R_ECX], &sc->ecx);
869 __put_user(env->regs[R_EAX], &sc->eax);
870 __put_user(cs->exception_index, &sc->trapno);
871 __put_user(env->error_code, &sc->err);
872 __put_user(env->eip, &sc->eip);
873 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
874 __put_user(env->eflags, &sc->eflags);
875 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
876 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +0000877
bellard28be6232007-11-11 22:23:38 +0000878 cpu_x86_fsave(env, fpstate_addr, 1);
bellarded2dcdf2003-05-29 20:06:27 +0000879 fpstate->status = fpstate->sw;
bellard775b58d2007-11-11 16:22:17 +0000880 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300881 __put_user(magic, &fpstate->magic);
882 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +0000883
bellard66fb9762003-03-23 01:06:05 +0000884 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300885 __put_user(mask, &sc->oldmask);
886 __put_user(env->cr[2], &sc->cr2);
bellard66fb9762003-03-23 01:06:05 +0000887}
888
889/*
890 * Determine which stack to use..
891 */
892
bellard579a97f2007-11-11 14:26:47 +0000893static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +0000894get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +0000895{
896 unsigned long esp;
897
898 /* Default to using normal stack */
899 esp = env->regs[R_ESP];
bellard66fb9762003-03-23 01:06:05 +0000900 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +0000901 if (ka->sa_flags & TARGET_SA_ONSTACK) {
thsa04e1342007-09-27 13:57:58 +0000902 if (sas_ss_flags(esp) == 0)
903 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
904 }
bellard66fb9762003-03-23 01:06:05 +0000905
906 /* This is the legacy signal stack switching. */
ths5fafdf22007-09-16 21:08:06 +0000907 else
bellarda52c7572003-06-21 13:14:12 +0000908 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
pbrook624f7972008-05-31 16:11:38 +0000909 !(ka->sa_flags & TARGET_SA_RESTORER) &&
910 ka->sa_restorer) {
911 esp = (unsigned long) ka->sa_restorer;
bellarda52c7572003-06-21 13:14:12 +0000912 }
bellard579a97f2007-11-11 14:26:47 +0000913 return (esp - frame_size) & -8ul;
bellard66fb9762003-03-23 01:06:05 +0000914}
915
bellard579a97f2007-11-11 14:26:47 +0000916/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +0000917static void setup_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -0500918 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000919{
bellard579a97f2007-11-11 14:26:47 +0000920 abi_ulong frame_addr;
bellard66fb9762003-03-23 01:06:05 +0000921 struct sigframe *frame;
Riku Voipio7df2fa32014-04-23 10:34:53 +0300922 int i;
bellard66fb9762003-03-23 01:06:05 +0000923
bellard579a97f2007-11-11 14:26:47 +0000924 frame_addr = get_sigframe(ka, env, sizeof(*frame));
bellard66fb9762003-03-23 01:06:05 +0000925
bellard579a97f2007-11-11 14:26:47 +0000926 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
bellard66fb9762003-03-23 01:06:05 +0000927 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +0000928
Riku Voipio1d8b5122014-04-23 10:26:05 +0300929 __put_user(current_exec_domain_sig(sig),
930 &frame->sig);
bellard66fb9762003-03-23 01:06:05 +0000931
bellard28be6232007-11-11 22:23:38 +0000932 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
933 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +0000934
Riku Voipio7df2fa32014-04-23 10:34:53 +0300935 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
936 __put_user(set->sig[i], &frame->extramask[i - 1]);
937 }
bellard66fb9762003-03-23 01:06:05 +0000938
939 /* Set up to return from userspace. If provided, use a stub
940 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +0000941 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +0300942 __put_user(ka->sa_restorer, &frame->pretcode);
bellard66fb9762003-03-23 01:06:05 +0000943 } else {
bellard775b58d2007-11-11 16:22:17 +0000944 uint16_t val16;
bellard28be6232007-11-11 22:23:38 +0000945 abi_ulong retcode_addr;
946 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300947 __put_user(retcode_addr, &frame->pretcode);
bellard66fb9762003-03-23 01:06:05 +0000948 /* This is popl %eax ; movl $,%eax ; int $0x80 */
bellard775b58d2007-11-11 16:22:17 +0000949 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300950 __put_user(val16, (uint16_t *)(frame->retcode+0));
951 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
bellard775b58d2007-11-11 16:22:17 +0000952 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300953 __put_user(val16, (uint16_t *)(frame->retcode+6));
bellard66fb9762003-03-23 01:06:05 +0000954 }
955
bellard66fb9762003-03-23 01:06:05 +0000956
957 /* Set up registers for signal handler */
bellard28be6232007-11-11 22:23:38 +0000958 env->regs[R_ESP] = frame_addr;
pbrook624f7972008-05-31 16:11:38 +0000959 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +0000960
961 cpu_x86_load_seg(env, R_DS, __USER_DS);
962 cpu_x86_load_seg(env, R_ES, __USER_DS);
963 cpu_x86_load_seg(env, R_SS, __USER_DS);
964 cpu_x86_load_seg(env, R_CS, __USER_CS);
965 env->eflags &= ~TF_MASK;
966
bellard579a97f2007-11-11 14:26:47 +0000967 unlock_user_struct(frame, frame_addr, 1);
968
bellard66fb9762003-03-23 01:06:05 +0000969 return;
970
971give_sigsegv:
972 if (sig == TARGET_SIGSEGV)
pbrook624f7972008-05-31 16:11:38 +0000973 ka->_sa_handler = TARGET_SIG_DFL;
bellard66fb9762003-03-23 01:06:05 +0000974 force_sig(TARGET_SIGSEGV /* , current */);
975}
976
bellard579a97f2007-11-11 14:26:47 +0000977/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +0000978static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -0500979 target_siginfo_t *info,
980 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000981{
bellard28be6232007-11-11 22:23:38 +0000982 abi_ulong frame_addr, addr;
bellard66fb9762003-03-23 01:06:05 +0000983 struct rt_sigframe *frame;
Riku Voipio0188fad2014-04-23 13:34:15 +0300984 int i;
bellard66fb9762003-03-23 01:06:05 +0000985
bellard579a97f2007-11-11 14:26:47 +0000986 frame_addr = get_sigframe(ka, env, sizeof(*frame));
bellard66fb9762003-03-23 01:06:05 +0000987
bellard579a97f2007-11-11 14:26:47 +0000988 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
bellard66fb9762003-03-23 01:06:05 +0000989 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +0000990
Riku Voipio1d8b5122014-04-23 10:26:05 +0300991 __put_user(current_exec_domain_sig(sig), &frame->sig);
bellard28be6232007-11-11 22:23:38 +0000992 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300993 __put_user(addr, &frame->pinfo);
bellard28be6232007-11-11 22:23:38 +0000994 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300995 __put_user(addr, &frame->puc);
Riku Voipiob0fd8d12014-04-23 10:46:13 +0300996 copy_siginfo_to_user(&frame->info, info);
bellard66fb9762003-03-23 01:06:05 +0000997
998 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300999 __put_user(0, &frame->uc.tuc_flags);
1000 __put_user(0, &frame->uc.tuc_link);
1001 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1002 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1003 &frame->uc.tuc_stack.ss_flags);
1004 __put_user(target_sigaltstack_used.ss_size,
1005 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001006 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1007 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1008
Riku Voipio0188fad2014-04-23 13:34:15 +03001009 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1010 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1011 }
bellard66fb9762003-03-23 01:06:05 +00001012
1013 /* Set up to return from userspace. If provided, use a stub
1014 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00001015 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001016 __put_user(ka->sa_restorer, &frame->pretcode);
bellard66fb9762003-03-23 01:06:05 +00001017 } else {
bellard775b58d2007-11-11 16:22:17 +00001018 uint16_t val16;
bellard28be6232007-11-11 22:23:38 +00001019 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001020 __put_user(addr, &frame->pretcode);
bellard66fb9762003-03-23 01:06:05 +00001021 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001022 __put_user(0xb8, (char *)(frame->retcode+0));
1023 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
bellard775b58d2007-11-11 16:22:17 +00001024 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001025 __put_user(val16, (uint16_t *)(frame->retcode+5));
bellard66fb9762003-03-23 01:06:05 +00001026 }
1027
bellard66fb9762003-03-23 01:06:05 +00001028 /* Set up registers for signal handler */
bellard28be6232007-11-11 22:23:38 +00001029 env->regs[R_ESP] = frame_addr;
pbrook624f7972008-05-31 16:11:38 +00001030 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001031
1032 cpu_x86_load_seg(env, R_DS, __USER_DS);
1033 cpu_x86_load_seg(env, R_ES, __USER_DS);
1034 cpu_x86_load_seg(env, R_SS, __USER_DS);
1035 cpu_x86_load_seg(env, R_CS, __USER_CS);
1036 env->eflags &= ~TF_MASK;
1037
bellard579a97f2007-11-11 14:26:47 +00001038 unlock_user_struct(frame, frame_addr, 1);
1039
bellard66fb9762003-03-23 01:06:05 +00001040 return;
1041
1042give_sigsegv:
1043 if (sig == TARGET_SIGSEGV)
pbrook624f7972008-05-31 16:11:38 +00001044 ka->_sa_handler = TARGET_SIG_DFL;
bellard66fb9762003-03-23 01:06:05 +00001045 force_sig(TARGET_SIGSEGV /* , current */);
1046}
1047
1048static int
1049restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
1050{
1051 unsigned int err = 0;
bellard28be6232007-11-11 22:23:38 +00001052 abi_ulong fpstate_addr;
1053 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001054
bellard28be6232007-11-11 22:23:38 +00001055 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1056 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1057 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1058 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001059
bellard28be6232007-11-11 22:23:38 +00001060 env->regs[R_EDI] = tswapl(sc->edi);
1061 env->regs[R_ESI] = tswapl(sc->esi);
1062 env->regs[R_EBP] = tswapl(sc->ebp);
1063 env->regs[R_ESP] = tswapl(sc->esp);
1064 env->regs[R_EBX] = tswapl(sc->ebx);
1065 env->regs[R_EDX] = tswapl(sc->edx);
1066 env->regs[R_ECX] = tswapl(sc->ecx);
1067 env->eip = tswapl(sc->eip);
bellard66fb9762003-03-23 01:06:05 +00001068
Mike McCormack9a826d72011-06-01 15:14:37 +09001069 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1070 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001071
bellard28be6232007-11-11 22:23:38 +00001072 tmpflags = tswapl(sc->eflags);
1073 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1074 // regs->orig_eax = -1; /* disable syscall checks */
1075
1076 fpstate_addr = tswapl(sc->fpstate);
1077 if (fpstate_addr != 0) {
1078 if (!access_ok(VERIFY_READ, fpstate_addr,
1079 sizeof(struct target_fpstate)))
1080 goto badframe;
1081 cpu_x86_frstor(env, fpstate_addr, 1);
bellard66fb9762003-03-23 01:06:05 +00001082 }
1083
bellard28be6232007-11-11 22:23:38 +00001084 *peax = tswapl(sc->eax);
bellard66fb9762003-03-23 01:06:05 +00001085 return err;
bellard66fb9762003-03-23 01:06:05 +00001086badframe:
1087 return 1;
bellard66fb9762003-03-23 01:06:05 +00001088}
1089
1090long do_sigreturn(CPUX86State *env)
1091{
bellard579a97f2007-11-11 14:26:47 +00001092 struct sigframe *frame;
1093 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001094 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001095 sigset_t set;
1096 int eax, i;
1097
bellard447db212003-05-10 15:10:36 +00001098#if defined(DEBUG_SIGNAL)
1099 fprintf(stderr, "do_sigreturn\n");
1100#endif
bellard579a97f2007-11-11 14:26:47 +00001101 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1102 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001103 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001104 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001105 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001106 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001107 }
bellard66fb9762003-03-23 01:06:05 +00001108
bellard92319442004-06-19 16:58:13 +00001109 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00001110 do_sigprocmask(SIG_SETMASK, &set, NULL);
ths3b46e622007-09-17 08:09:54 +00001111
bellard66fb9762003-03-23 01:06:05 +00001112 /* restore registers */
1113 if (restore_sigcontext(env, &frame->sc, &eax))
1114 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001115 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001116 return eax;
1117
1118badframe:
bellard579a97f2007-11-11 14:26:47 +00001119 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001120 force_sig(TARGET_SIGSEGV);
1121 return 0;
1122}
1123
1124long do_rt_sigreturn(CPUX86State *env)
1125{
bellard28be6232007-11-11 22:23:38 +00001126 abi_ulong frame_addr;
1127 struct rt_sigframe *frame;
bellard66fb9762003-03-23 01:06:05 +00001128 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001129 int eax;
1130
bellard28be6232007-11-11 22:23:38 +00001131 frame_addr = env->regs[R_ESP] - 4;
1132 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1133 goto badframe;
bellardb8076a72005-04-07 22:20:31 +00001134 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001135 do_sigprocmask(SIG_SETMASK, &set, NULL);
ths5fafdf22007-09-16 21:08:06 +00001136
bellardb8076a72005-04-07 22:20:31 +00001137 if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
bellard66fb9762003-03-23 01:06:05 +00001138 goto badframe;
1139
bellard28be6232007-11-11 22:23:38 +00001140 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1141 get_sp_from_cpustate(env)) == -EFAULT)
bellard66fb9762003-03-23 01:06:05 +00001142 goto badframe;
thsa04e1342007-09-27 13:57:58 +00001143
bellard28be6232007-11-11 22:23:38 +00001144 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001145 return eax;
1146
1147badframe:
bellard28be6232007-11-11 22:23:38 +00001148 unlock_user_struct(frame, frame_addr, 0);
1149 force_sig(TARGET_SIGSEGV);
bellard66fb9762003-03-23 01:06:05 +00001150 return 0;
1151}
1152
Andreas Schwab1744aea2013-09-03 20:12:16 +01001153#elif defined(TARGET_AARCH64)
1154
1155struct target_sigcontext {
1156 uint64_t fault_address;
1157 /* AArch64 registers */
1158 uint64_t regs[31];
1159 uint64_t sp;
1160 uint64_t pc;
1161 uint64_t pstate;
1162 /* 4K reserved for FP/SIMD state and future expansion */
1163 char __reserved[4096] __attribute__((__aligned__(16)));
1164};
1165
1166struct target_ucontext {
1167 abi_ulong tuc_flags;
1168 abi_ulong tuc_link;
1169 target_stack_t tuc_stack;
1170 target_sigset_t tuc_sigmask;
1171 /* glibc uses a 1024-bit sigset_t */
1172 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1173 /* last for future expansion */
1174 struct target_sigcontext tuc_mcontext;
1175};
1176
1177/*
1178 * Header to be used at the beginning of structures extending the user
1179 * context. Such structures must be placed after the rt_sigframe on the stack
1180 * and be 16-byte aligned. The last structure must be a dummy one with the
1181 * magic and size set to 0.
1182 */
1183struct target_aarch64_ctx {
1184 uint32_t magic;
1185 uint32_t size;
1186};
1187
1188#define TARGET_FPSIMD_MAGIC 0x46508001
1189
1190struct target_fpsimd_context {
1191 struct target_aarch64_ctx head;
1192 uint32_t fpsr;
1193 uint32_t fpcr;
1194 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1195};
1196
1197/*
1198 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1199 * user space as it will change with the addition of new context. User space
1200 * should check the magic/size information.
1201 */
1202struct target_aux_context {
1203 struct target_fpsimd_context fpsimd;
1204 /* additional context to be added before "end" */
1205 struct target_aarch64_ctx end;
1206};
1207
1208struct target_rt_sigframe {
1209 struct target_siginfo info;
1210 struct target_ucontext uc;
1211 uint64_t fp;
1212 uint64_t lr;
1213 uint32_t tramp[2];
1214};
1215
1216static int target_setup_sigframe(struct target_rt_sigframe *sf,
1217 CPUARMState *env, target_sigset_t *set)
1218{
1219 int i;
1220 struct target_aux_context *aux =
1221 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1222
1223 /* set up the stack frame for unwinding */
1224 __put_user(env->xregs[29], &sf->fp);
1225 __put_user(env->xregs[30], &sf->lr);
1226
1227 for (i = 0; i < 31; i++) {
1228 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1229 }
1230 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1231 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001232 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001233
Peter Maydell7af03922014-05-01 18:36:17 +01001234 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001235
1236 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1237 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1238 }
1239
1240 for (i = 0; i < 32; i++) {
1241#ifdef TARGET_WORDS_BIGENDIAN
1242 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1243 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1244#else
1245 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1246 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1247#endif
1248 }
Will Newtone0ee1382014-01-04 22:15:48 +00001249 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1250 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001251 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1252 __put_user(sizeof(struct target_fpsimd_context),
1253 &aux->fpsimd.head.size);
1254
1255 /* set the "end" magic */
1256 __put_user(0, &aux->end.magic);
1257 __put_user(0, &aux->end.size);
1258
1259 return 0;
1260}
1261
1262static int target_restore_sigframe(CPUARMState *env,
1263 struct target_rt_sigframe *sf)
1264{
1265 sigset_t set;
1266 int i;
1267 struct target_aux_context *aux =
1268 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
Will Newtone0ee1382014-01-04 22:15:48 +00001269 uint32_t magic, size, fpsr, fpcr;
Peter Maydelld3563122013-12-17 19:42:30 +00001270 uint64_t pstate;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001271
1272 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001273 do_sigprocmask(SIG_SETMASK, &set, NULL);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001274
1275 for (i = 0; i < 31; i++) {
1276 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1277 }
1278
1279 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1280 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001281 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1282 pstate_write(env, pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001283
1284 __get_user(magic, &aux->fpsimd.head.magic);
1285 __get_user(size, &aux->fpsimd.head.size);
1286
1287 if (magic != TARGET_FPSIMD_MAGIC
1288 || size != sizeof(struct target_fpsimd_context)) {
1289 return 1;
1290 }
1291
Peter Maydell4cf23482014-03-02 19:36:38 +00001292 for (i = 0; i < 32; i++) {
1293#ifdef TARGET_WORDS_BIGENDIAN
1294 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1295 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1296#else
1297 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1298 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1299#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001300 }
Will Newtone0ee1382014-01-04 22:15:48 +00001301 __get_user(fpsr, &aux->fpsimd.fpsr);
1302 vfp_set_fpsr(env, fpsr);
1303 __get_user(fpcr, &aux->fpsimd.fpcr);
1304 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001305
1306 return 0;
1307}
1308
1309static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1310{
1311 abi_ulong sp;
1312
1313 sp = env->xregs[31];
1314
1315 /*
1316 * This is the X/Open sanctioned signal stack switching.
1317 */
Riku Voipiob545f632014-07-15 17:01:55 +03001318 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001319 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1320 }
1321
1322 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1323
1324 return sp;
1325}
1326
1327static void target_setup_frame(int usig, struct target_sigaction *ka,
1328 target_siginfo_t *info, target_sigset_t *set,
1329 CPUARMState *env)
1330{
1331 struct target_rt_sigframe *frame;
Michael Matz8a3ae912014-03-02 19:36:39 +00001332 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001333
1334 frame_addr = get_sigframe(ka, env);
1335 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1336 goto give_sigsegv;
1337 }
1338
1339 __put_user(0, &frame->uc.tuc_flags);
1340 __put_user(0, &frame->uc.tuc_link);
1341
1342 __put_user(target_sigaltstack_used.ss_sp,
1343 &frame->uc.tuc_stack.ss_sp);
1344 __put_user(sas_ss_flags(env->xregs[31]),
1345 &frame->uc.tuc_stack.ss_flags);
1346 __put_user(target_sigaltstack_used.ss_size,
1347 &frame->uc.tuc_stack.ss_size);
1348 target_setup_sigframe(frame, env, set);
Michael Matz8a3ae912014-03-02 19:36:39 +00001349 if (ka->sa_flags & TARGET_SA_RESTORER) {
1350 return_addr = ka->sa_restorer;
1351 } else {
1352 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1353 __put_user(0xd2801168, &frame->tramp[0]);
1354 __put_user(0xd4000001, &frame->tramp[1]);
1355 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1356 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001357 env->xregs[0] = usig;
1358 env->xregs[31] = frame_addr;
1359 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1360 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001361 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001362 if (info) {
Riku Voipiob0fd8d12014-04-23 10:46:13 +03001363 copy_siginfo_to_user(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001364 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1365 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1366 }
1367
1368 unlock_user_struct(frame, frame_addr, 1);
1369 return;
1370
1371 give_sigsegv:
1372 unlock_user_struct(frame, frame_addr, 1);
1373 force_sig(TARGET_SIGSEGV);
1374}
1375
1376static void setup_rt_frame(int sig, struct target_sigaction *ka,
1377 target_siginfo_t *info, target_sigset_t *set,
1378 CPUARMState *env)
1379{
1380 target_setup_frame(sig, ka, info, set, env);
1381}
1382
1383static void setup_frame(int sig, struct target_sigaction *ka,
1384 target_sigset_t *set, CPUARMState *env)
1385{
1386 target_setup_frame(sig, ka, 0, set, env);
1387}
1388
1389long do_rt_sigreturn(CPUARMState *env)
1390{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001391 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001392 abi_ulong frame_addr = env->xregs[31];
1393
1394 if (frame_addr & 15) {
1395 goto badframe;
1396 }
1397
1398 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1399 goto badframe;
1400 }
1401
1402 if (target_restore_sigframe(env, frame)) {
1403 goto badframe;
1404 }
1405
1406 if (do_sigaltstack(frame_addr +
1407 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1408 0, get_sp_from_cpustate(env)) == -EFAULT) {
1409 goto badframe;
1410 }
1411
1412 unlock_user_struct(frame, frame_addr, 0);
1413 return env->xregs[0];
1414
1415 badframe:
1416 unlock_user_struct(frame, frame_addr, 0);
1417 force_sig(TARGET_SIGSEGV);
1418 return 0;
1419}
1420
1421long do_sigreturn(CPUARMState *env)
1422{
1423 return do_rt_sigreturn(env);
1424}
1425
bellard43fff232003-07-09 19:31:39 +00001426#elif defined(TARGET_ARM)
1427
1428struct target_sigcontext {
blueswir1992f48a2007-10-14 16:27:31 +00001429 abi_ulong trap_no;
1430 abi_ulong error_code;
1431 abi_ulong oldmask;
1432 abi_ulong arm_r0;
1433 abi_ulong arm_r1;
1434 abi_ulong arm_r2;
1435 abi_ulong arm_r3;
1436 abi_ulong arm_r4;
1437 abi_ulong arm_r5;
1438 abi_ulong arm_r6;
1439 abi_ulong arm_r7;
1440 abi_ulong arm_r8;
1441 abi_ulong arm_r9;
1442 abi_ulong arm_r10;
1443 abi_ulong arm_fp;
1444 abi_ulong arm_ip;
1445 abi_ulong arm_sp;
1446 abi_ulong arm_lr;
1447 abi_ulong arm_pc;
1448 abi_ulong arm_cpsr;
1449 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001450};
1451
pbrooka745ec62008-05-06 15:36:17 +00001452struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001453 abi_ulong tuc_flags;
1454 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001455 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001456 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001457 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001458};
1459
pbrooka745ec62008-05-06 15:36:17 +00001460struct target_ucontext_v2 {
1461 abi_ulong tuc_flags;
1462 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001463 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001464 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001465 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001466 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001467 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1468};
1469
Peter Maydell0d871bd2010-11-24 15:20:05 +00001470struct target_user_vfp {
1471 uint64_t fpregs[32];
1472 abi_ulong fpscr;
1473};
1474
1475struct target_user_vfp_exc {
1476 abi_ulong fpexc;
1477 abi_ulong fpinst;
1478 abi_ulong fpinst2;
1479};
1480
1481struct target_vfp_sigframe {
1482 abi_ulong magic;
1483 abi_ulong size;
1484 struct target_user_vfp ufp;
1485 struct target_user_vfp_exc ufp_exc;
1486} __attribute__((__aligned__(8)));
1487
Peter Maydell08e11252010-11-24 15:20:07 +00001488struct target_iwmmxt_sigframe {
1489 abi_ulong magic;
1490 abi_ulong size;
1491 uint64_t regs[16];
1492 /* Note that not all the coprocessor control registers are stored here */
1493 uint32_t wcssf;
1494 uint32_t wcasf;
1495 uint32_t wcgr0;
1496 uint32_t wcgr1;
1497 uint32_t wcgr2;
1498 uint32_t wcgr3;
1499} __attribute__((__aligned__(8)));
1500
Peter Maydell0d871bd2010-11-24 15:20:05 +00001501#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001502#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001503
pbrooka8c33202008-05-07 23:22:46 +00001504struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001505{
1506 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001507 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1508 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001509};
1510
pbrooka8c33202008-05-07 23:22:46 +00001511struct sigframe_v2
1512{
1513 struct target_ucontext_v2 uc;
1514 abi_ulong retcode;
1515};
1516
pbrooka745ec62008-05-06 15:36:17 +00001517struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001518{
bellardf8b0aa22007-11-11 23:03:42 +00001519 abi_ulong pinfo;
1520 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001521 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001522 struct target_ucontext_v1 uc;
1523 abi_ulong retcode;
1524};
1525
1526struct rt_sigframe_v2
1527{
1528 struct target_siginfo info;
1529 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001530 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001531};
1532
1533#define TARGET_CONFIG_CPU_32 1
1534
1535/*
1536 * For ARM syscalls, we encode the syscall number into the instruction.
1537 */
1538#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1539#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1540
1541/*
1542 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1543 * need two 16-bit instructions.
1544 */
1545#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1546#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1547
blueswir1992f48a2007-10-14 16:27:31 +00001548static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001549 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1550 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1551};
1552
1553
Andreas Färber05390242012-02-25 03:37:53 +01001554static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001555{
1556 return 1;
1557}
1558
pbrooka8c33202008-05-07 23:22:46 +00001559static void
bellard43fff232003-07-09 19:31:39 +00001560setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001561 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001562{
pbrooka8c33202008-05-07 23:22:46 +00001563 __put_user(env->regs[0], &sc->arm_r0);
1564 __put_user(env->regs[1], &sc->arm_r1);
1565 __put_user(env->regs[2], &sc->arm_r2);
1566 __put_user(env->regs[3], &sc->arm_r3);
1567 __put_user(env->regs[4], &sc->arm_r4);
1568 __put_user(env->regs[5], &sc->arm_r5);
1569 __put_user(env->regs[6], &sc->arm_r6);
1570 __put_user(env->regs[7], &sc->arm_r7);
1571 __put_user(env->regs[8], &sc->arm_r8);
1572 __put_user(env->regs[9], &sc->arm_r9);
1573 __put_user(env->regs[10], &sc->arm_r10);
1574 __put_user(env->regs[11], &sc->arm_fp);
1575 __put_user(env->regs[12], &sc->arm_ip);
1576 __put_user(env->regs[13], &sc->arm_sp);
1577 __put_user(env->regs[14], &sc->arm_lr);
1578 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001579#ifdef TARGET_CONFIG_CPU_32
pbrooka8c33202008-05-07 23:22:46 +00001580 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001581#endif
1582
pbrooka8c33202008-05-07 23:22:46 +00001583 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1584 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1585 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1586 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001587}
1588
bellard579a97f2007-11-11 14:26:47 +00001589static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001590get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001591{
1592 unsigned long sp = regs->regs[13];
1593
bellard43fff232003-07-09 19:31:39 +00001594 /*
1595 * This is the X/Open sanctioned signal stack switching.
1596 */
pbrook624f7972008-05-31 16:11:38 +00001597 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
thsa04e1342007-09-27 13:57:58 +00001598 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
bellard43fff232003-07-09 19:31:39 +00001599 /*
1600 * ATPCS B01 mandates 8-byte alignment
1601 */
bellard579a97f2007-11-11 14:26:47 +00001602 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001603}
1604
Riku Voipio0188fad2014-04-23 13:34:15 +03001605static void
Andreas Färber05390242012-02-25 03:37:53 +01001606setup_return(CPUARMState *env, struct target_sigaction *ka,
bellardf8b0aa22007-11-11 23:03:42 +00001607 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001608{
pbrook624f7972008-05-31 16:11:38 +00001609 abi_ulong handler = ka->_sa_handler;
blueswir1992f48a2007-10-14 16:27:31 +00001610 abi_ulong retcode;
pbrook75b680e2008-03-21 16:07:30 +00001611 int thumb = handler & 1;
Peter Maydell964413d2011-01-14 20:39:19 +01001612 uint32_t cpsr = cpsr_read(env);
1613
1614 cpsr &= ~CPSR_IT;
1615 if (thumb) {
1616 cpsr |= CPSR_T;
1617 } else {
1618 cpsr &= ~CPSR_T;
1619 }
bellard43fff232003-07-09 19:31:39 +00001620
pbrook624f7972008-05-31 16:11:38 +00001621 if (ka->sa_flags & TARGET_SA_RESTORER) {
1622 retcode = ka->sa_restorer;
bellard43fff232003-07-09 19:31:39 +00001623 } else {
1624 unsigned int idx = thumb;
1625
pbrook624f7972008-05-31 16:11:38 +00001626 if (ka->sa_flags & TARGET_SA_SIGINFO)
bellard43fff232003-07-09 19:31:39 +00001627 idx += 2;
1628
Riku Voipio0188fad2014-04-23 13:34:15 +03001629 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001630
bellardf8b0aa22007-11-11 23:03:42 +00001631 retcode = rc_addr + thumb;
bellard43fff232003-07-09 19:31:39 +00001632 }
1633
1634 env->regs[0] = usig;
bellardf8b0aa22007-11-11 23:03:42 +00001635 env->regs[13] = frame_addr;
bellard43fff232003-07-09 19:31:39 +00001636 env->regs[14] = retcode;
1637 env->regs[15] = handler & (thumb ? ~1 : ~3);
Peter Maydell964413d2011-01-14 20:39:19 +01001638 cpsr_write(env, cpsr, 0xffffffff);
bellard43fff232003-07-09 19:31:39 +00001639}
1640
Andreas Färber05390242012-02-25 03:37:53 +01001641static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001642{
1643 int i;
1644 struct target_vfp_sigframe *vfpframe;
1645 vfpframe = (struct target_vfp_sigframe *)regspace;
1646 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1647 __put_user(sizeof(*vfpframe), &vfpframe->size);
1648 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001649 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001650 }
1651 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1652 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1653 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1654 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1655 return (abi_ulong*)(vfpframe+1);
1656}
1657
Andreas Färber05390242012-02-25 03:37:53 +01001658static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1659 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001660{
1661 int i;
1662 struct target_iwmmxt_sigframe *iwmmxtframe;
1663 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1664 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1665 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1666 for (i = 0; i < 16; i++) {
1667 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1668 }
1669 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1670 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1671 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1672 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1673 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1674 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1675 return (abi_ulong*)(iwmmxtframe+1);
1676}
1677
pbrooka8c33202008-05-07 23:22:46 +00001678static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001679 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001680{
pbrooka8c33202008-05-07 23:22:46 +00001681 struct target_sigaltstack stack;
1682 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001683 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001684
1685 /* Clear all the bits of the ucontext we don't use. */
1686 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1687
1688 memset(&stack, 0, sizeof(stack));
1689 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1690 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1691 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1692 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1693
1694 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001695 /* Save coprocessor signal frame. */
1696 regspace = uc->tuc_regspace;
1697 if (arm_feature(env, ARM_FEATURE_VFP)) {
1698 regspace = setup_sigframe_v2_vfp(regspace, env);
1699 }
Peter Maydell08e11252010-11-24 15:20:07 +00001700 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1701 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1702 }
1703
Peter Maydell0d871bd2010-11-24 15:20:05 +00001704 /* Write terminating magic word */
1705 __put_user(0, regspace);
1706
pbrooka8c33202008-05-07 23:22:46 +00001707 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1708 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1709 }
1710}
1711
1712/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001713static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001714 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001715{
1716 struct sigframe_v1 *frame;
bellard579a97f2007-11-11 14:26:47 +00001717 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00001718 int i;
bellard43fff232003-07-09 19:31:39 +00001719
bellard579a97f2007-11-11 14:26:47 +00001720 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1721 return;
1722
pbrooka8c33202008-05-07 23:22:46 +00001723 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00001724
Riku Voipio0188fad2014-04-23 13:34:15 +03001725 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1726 __put_user(set->sig[i], &frame->extramask[i - 1]);
1727 }
bellard43fff232003-07-09 19:31:39 +00001728
pbrooka8c33202008-05-07 23:22:46 +00001729 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1730 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00001731
bellard579a97f2007-11-11 14:26:47 +00001732 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001733}
1734
pbrook624f7972008-05-31 16:11:38 +00001735static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001736 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001737{
1738 struct sigframe_v2 *frame;
1739 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1740
1741 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1742 return;
1743
1744 setup_sigframe_v2(&frame->uc, set, regs);
1745
1746 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1747 frame_addr + offsetof(struct sigframe_v2, retcode));
1748
1749 unlock_user_struct(frame, frame_addr, 1);
1750}
1751
pbrook624f7972008-05-31 16:11:38 +00001752static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001753 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001754{
1755 if (get_osversion() >= 0x020612) {
1756 setup_frame_v2(usig, ka, set, regs);
1757 } else {
1758 setup_frame_v1(usig, ka, set, regs);
1759 }
bellard43fff232003-07-09 19:31:39 +00001760}
1761
bellard579a97f2007-11-11 14:26:47 +00001762/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001763static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001764 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001765 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001766{
pbrooka745ec62008-05-06 15:36:17 +00001767 struct rt_sigframe_v1 *frame;
bellard579a97f2007-11-11 14:26:47 +00001768 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
thsa04e1342007-09-27 13:57:58 +00001769 struct target_sigaltstack stack;
pbrooka8c33202008-05-07 23:22:46 +00001770 int i;
bellardf8b0aa22007-11-11 23:03:42 +00001771 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00001772
bellard579a97f2007-11-11 14:26:47 +00001773 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
bellardedf779f2004-02-22 13:40:13 +00001774 return /* 1 */;
1775
pbrooka745ec62008-05-06 15:36:17 +00001776 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
pbrooka8c33202008-05-07 23:22:46 +00001777 __put_user(info_addr, &frame->pinfo);
pbrooka745ec62008-05-06 15:36:17 +00001778 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
pbrooka8c33202008-05-07 23:22:46 +00001779 __put_user(uc_addr, &frame->puc);
1780 copy_siginfo_to_user(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00001781
1782 /* Clear all the bits of the ucontext we don't use. */
pbrooka745ec62008-05-06 15:36:17 +00001783 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00001784
thsa04e1342007-09-27 13:57:58 +00001785 memset(&stack, 0, sizeof(stack));
1786 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1787 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1788 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
bellard775b58d2007-11-11 16:22:17 +00001789 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00001790
pbrooka8c33202008-05-07 23:22:46 +00001791 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
bellard92319442004-06-19 16:58:13 +00001792 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03001793 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
bellard92319442004-06-19 16:58:13 +00001794 }
bellard43fff232003-07-09 19:31:39 +00001795
pbrooka8c33202008-05-07 23:22:46 +00001796 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1797 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001798
pbrooka8c33202008-05-07 23:22:46 +00001799 env->regs[1] = info_addr;
1800 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001801
pbrooka745ec62008-05-06 15:36:17 +00001802 unlock_user_struct(frame, frame_addr, 1);
pbrooka745ec62008-05-06 15:36:17 +00001803}
1804
pbrook624f7972008-05-31 16:11:38 +00001805static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001806 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001807 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001808{
1809 struct rt_sigframe_v2 *frame;
1810 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
pbrooka745ec62008-05-06 15:36:17 +00001811 abi_ulong info_addr, uc_addr;
1812
1813 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1814 return /* 1 */;
1815
1816 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1817 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
pbrooka8c33202008-05-07 23:22:46 +00001818 copy_siginfo_to_user(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00001819
pbrooka8c33202008-05-07 23:22:46 +00001820 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00001821
pbrooka8c33202008-05-07 23:22:46 +00001822 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1823 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001824
pbrooka8c33202008-05-07 23:22:46 +00001825 env->regs[1] = info_addr;
1826 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001827
bellard579a97f2007-11-11 14:26:47 +00001828 unlock_user_struct(frame, frame_addr, 1);
bellard43fff232003-07-09 19:31:39 +00001829}
1830
pbrook624f7972008-05-31 16:11:38 +00001831static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001832 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001833 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001834{
1835 if (get_osversion() >= 0x020612) {
1836 setup_rt_frame_v2(usig, ka, info, set, env);
1837 } else {
1838 setup_rt_frame_v1(usig, ka, info, set, env);
1839 }
1840}
1841
bellard43fff232003-07-09 19:31:39 +00001842static int
Andreas Färber05390242012-02-25 03:37:53 +01001843restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00001844{
1845 int err = 0;
bellardb5ff1b32005-11-26 10:38:39 +00001846 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00001847
Riku Voipio1d8b5122014-04-23 10:26:05 +03001848 __get_user(env->regs[0], &sc->arm_r0);
1849 __get_user(env->regs[1], &sc->arm_r1);
1850 __get_user(env->regs[2], &sc->arm_r2);
1851 __get_user(env->regs[3], &sc->arm_r3);
1852 __get_user(env->regs[4], &sc->arm_r4);
1853 __get_user(env->regs[5], &sc->arm_r5);
1854 __get_user(env->regs[6], &sc->arm_r6);
1855 __get_user(env->regs[7], &sc->arm_r7);
1856 __get_user(env->regs[8], &sc->arm_r8);
1857 __get_user(env->regs[9], &sc->arm_r9);
1858 __get_user(env->regs[10], &sc->arm_r10);
1859 __get_user(env->regs[11], &sc->arm_fp);
1860 __get_user(env->regs[12], &sc->arm_ip);
1861 __get_user(env->regs[13], &sc->arm_sp);
1862 __get_user(env->regs[14], &sc->arm_lr);
1863 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001864#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03001865 __get_user(cpsr, &sc->arm_cpsr);
pbrook75b680e2008-03-21 16:07:30 +00001866 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
bellard43fff232003-07-09 19:31:39 +00001867#endif
1868
1869 err |= !valid_user_regs(env);
1870
1871 return err;
1872}
1873
Andreas Färber05390242012-02-25 03:37:53 +01001874static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001875{
bellardf8b0aa22007-11-11 23:03:42 +00001876 abi_ulong frame_addr;
Peter Maydell978fae92013-07-29 12:00:32 +01001877 struct sigframe_v1 *frame = NULL;
Anthony Liguoric227f092009-10-01 16:12:16 -05001878 target_sigset_t set;
bellard43fff232003-07-09 19:31:39 +00001879 sigset_t host_set;
bellard92319442004-06-19 16:58:13 +00001880 int i;
bellard43fff232003-07-09 19:31:39 +00001881
1882 /*
1883 * Since we stacked the signal on a 64-bit boundary,
1884 * then 'sp' should be word aligned here. If it's
1885 * not, then the user is trying to mess with us.
1886 */
bellardf8b0aa22007-11-11 23:03:42 +00001887 frame_addr = env->regs[13];
Peter Maydell978fae92013-07-29 12:00:32 +01001888 if (frame_addr & 7) {
1889 goto badframe;
1890 }
1891
bellardf8b0aa22007-11-11 23:03:42 +00001892 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1893 goto badframe;
bellard43fff232003-07-09 19:31:39 +00001894
Riku Voipiof5f601a2014-04-23 13:00:17 +03001895 __get_user(set.sig[0], &frame->sc.oldmask);
1896 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1897 __get_user(set.sig[i], &frame->extramask[i - 1]);
1898 }
bellard43fff232003-07-09 19:31:39 +00001899
bellard92319442004-06-19 16:58:13 +00001900 target_to_host_sigset_internal(&host_set, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00001901 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard43fff232003-07-09 19:31:39 +00001902
1903 if (restore_sigcontext(env, &frame->sc))
1904 goto badframe;
1905
1906#if 0
1907 /* Send SIGTRAP if we're single-stepping */
1908 if (ptrace_cancel_bpt(current))
1909 send_sig(SIGTRAP, current, 1);
1910#endif
bellardf8b0aa22007-11-11 23:03:42 +00001911 unlock_user_struct(frame, frame_addr, 0);
1912 return env->regs[0];
bellard43fff232003-07-09 19:31:39 +00001913
1914badframe:
Riku Voipio66393fb2009-12-04 15:16:32 +02001915 force_sig(TARGET_SIGSEGV /* , current */);
bellard43fff232003-07-09 19:31:39 +00001916 return 0;
1917}
1918
Andreas Färber05390242012-02-25 03:37:53 +01001919static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00001920{
1921 int i;
1922 abi_ulong magic, sz;
1923 uint32_t fpscr, fpexc;
1924 struct target_vfp_sigframe *vfpframe;
1925 vfpframe = (struct target_vfp_sigframe *)regspace;
1926
1927 __get_user(magic, &vfpframe->magic);
1928 __get_user(sz, &vfpframe->size);
1929 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1930 return 0;
1931 }
1932 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001933 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00001934 }
1935 __get_user(fpscr, &vfpframe->ufp.fpscr);
1936 vfp_set_fpscr(env, fpscr);
1937 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1938 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1939 * and the exception flag is cleared
1940 */
1941 fpexc |= (1 << 30);
1942 fpexc &= ~((1 << 31) | (1 << 28));
1943 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1944 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1945 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1946 return (abi_ulong*)(vfpframe + 1);
1947}
1948
Andreas Färber05390242012-02-25 03:37:53 +01001949static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
1950 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00001951{
1952 int i;
1953 abi_ulong magic, sz;
1954 struct target_iwmmxt_sigframe *iwmmxtframe;
1955 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1956
1957 __get_user(magic, &iwmmxtframe->magic);
1958 __get_user(sz, &iwmmxtframe->size);
1959 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
1960 return 0;
1961 }
1962 for (i = 0; i < 16; i++) {
1963 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1964 }
1965 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1966 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1967 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1968 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1969 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1970 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1971 return (abi_ulong*)(iwmmxtframe + 1);
1972}
1973
Andreas Färber05390242012-02-25 03:37:53 +01001974static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
pbrooka8c33202008-05-07 23:22:46 +00001975 struct target_ucontext_v2 *uc)
1976{
1977 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00001978 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001979
1980 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001981 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
pbrooka8c33202008-05-07 23:22:46 +00001982
1983 if (restore_sigcontext(env, &uc->tuc_mcontext))
1984 return 1;
1985
Peter Maydell5f9099d2010-11-24 15:20:06 +00001986 /* Restore coprocessor signal frame */
1987 regspace = uc->tuc_regspace;
1988 if (arm_feature(env, ARM_FEATURE_VFP)) {
1989 regspace = restore_sigframe_v2_vfp(env, regspace);
1990 if (!regspace) {
1991 return 1;
1992 }
1993 }
Peter Maydella59d69d2010-11-24 15:20:08 +00001994 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1995 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
1996 if (!regspace) {
1997 return 1;
1998 }
1999 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002000
pbrooka8c33202008-05-07 23:22:46 +00002001 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2002 return 1;
2003
2004#if 0
2005 /* Send SIGTRAP if we're single-stepping */
2006 if (ptrace_cancel_bpt(current))
2007 send_sig(SIGTRAP, current, 1);
2008#endif
2009
2010 return 0;
2011}
2012
Andreas Färber05390242012-02-25 03:37:53 +01002013static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002014{
2015 abi_ulong frame_addr;
Peter Maydell978fae92013-07-29 12:00:32 +01002016 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002017
2018 /*
2019 * Since we stacked the signal on a 64-bit boundary,
2020 * then 'sp' should be word aligned here. If it's
2021 * not, then the user is trying to mess with us.
2022 */
pbrooka8c33202008-05-07 23:22:46 +00002023 frame_addr = env->regs[13];
Peter Maydell978fae92013-07-29 12:00:32 +01002024 if (frame_addr & 7) {
2025 goto badframe;
2026 }
2027
pbrooka8c33202008-05-07 23:22:46 +00002028 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2029 goto badframe;
2030
2031 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
2032 goto badframe;
2033
2034 unlock_user_struct(frame, frame_addr, 0);
2035 return env->regs[0];
2036
2037badframe:
2038 unlock_user_struct(frame, frame_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002039 force_sig(TARGET_SIGSEGV /* , current */);
pbrooka8c33202008-05-07 23:22:46 +00002040 return 0;
2041}
2042
Andreas Färber05390242012-02-25 03:37:53 +01002043long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002044{
2045 if (get_osversion() >= 0x020612) {
2046 return do_sigreturn_v2(env);
2047 } else {
2048 return do_sigreturn_v1(env);
2049 }
2050}
2051
Andreas Färber05390242012-02-25 03:37:53 +01002052static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002053{
bellardf8b0aa22007-11-11 23:03:42 +00002054 abi_ulong frame_addr;
Peter Maydell978fae92013-07-29 12:00:32 +01002055 struct rt_sigframe_v1 *frame = NULL;
bellard43fff232003-07-09 19:31:39 +00002056 sigset_t host_set;
2057
2058 /*
2059 * Since we stacked the signal on a 64-bit boundary,
2060 * then 'sp' should be word aligned here. If it's
2061 * not, then the user is trying to mess with us.
2062 */
bellardf8b0aa22007-11-11 23:03:42 +00002063 frame_addr = env->regs[13];
Peter Maydell978fae92013-07-29 12:00:32 +01002064 if (frame_addr & 7) {
2065 goto badframe;
2066 }
2067
bellardf8b0aa22007-11-11 23:03:42 +00002068 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2069 goto badframe;
bellard43fff232003-07-09 19:31:39 +00002070
bellardb8076a72005-04-07 22:20:31 +00002071 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00002072 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard43fff232003-07-09 19:31:39 +00002073
bellardb8076a72005-04-07 22:20:31 +00002074 if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
bellard43fff232003-07-09 19:31:39 +00002075 goto badframe;
2076
pbrooka745ec62008-05-06 15:36:17 +00002077 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
thsa04e1342007-09-27 13:57:58 +00002078 goto badframe;
2079
bellard43fff232003-07-09 19:31:39 +00002080#if 0
2081 /* Send SIGTRAP if we're single-stepping */
2082 if (ptrace_cancel_bpt(current))
2083 send_sig(SIGTRAP, current, 1);
2084#endif
bellardf8b0aa22007-11-11 23:03:42 +00002085 unlock_user_struct(frame, frame_addr, 0);
bellard43fff232003-07-09 19:31:39 +00002086 return env->regs[0];
2087
2088badframe:
bellardf8b0aa22007-11-11 23:03:42 +00002089 unlock_user_struct(frame, frame_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002090 force_sig(TARGET_SIGSEGV /* , current */);
bellard43fff232003-07-09 19:31:39 +00002091 return 0;
2092}
2093
Andreas Färber05390242012-02-25 03:37:53 +01002094static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002095{
2096 abi_ulong frame_addr;
Peter Maydell978fae92013-07-29 12:00:32 +01002097 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002098
2099 /*
2100 * Since we stacked the signal on a 64-bit boundary,
2101 * then 'sp' should be word aligned here. If it's
2102 * not, then the user is trying to mess with us.
2103 */
pbrooka745ec62008-05-06 15:36:17 +00002104 frame_addr = env->regs[13];
Peter Maydell978fae92013-07-29 12:00:32 +01002105 if (frame_addr & 7) {
2106 goto badframe;
2107 }
2108
pbrooka745ec62008-05-06 15:36:17 +00002109 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2110 goto badframe;
2111
pbrooka8c33202008-05-07 23:22:46 +00002112 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
2113 goto badframe;
pbrooka745ec62008-05-06 15:36:17 +00002114
pbrooka745ec62008-05-06 15:36:17 +00002115 unlock_user_struct(frame, frame_addr, 0);
2116 return env->regs[0];
2117
2118badframe:
2119 unlock_user_struct(frame, frame_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002120 force_sig(TARGET_SIGSEGV /* , current */);
pbrooka745ec62008-05-06 15:36:17 +00002121 return 0;
2122}
2123
Andreas Färber05390242012-02-25 03:37:53 +01002124long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002125{
2126 if (get_osversion() >= 0x020612) {
2127 return do_rt_sigreturn_v2(env);
2128 } else {
2129 return do_rt_sigreturn_v1(env);
2130 }
2131}
2132
bellard6d5e2162004-09-30 22:04:13 +00002133#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002134
bellard6d5e2162004-09-30 22:04:13 +00002135#define __SUNOS_MAXWIN 31
2136
2137/* This is what SunOS does, so shall I. */
2138struct target_sigcontext {
blueswir1992f48a2007-10-14 16:27:31 +00002139 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002140
blueswir1992f48a2007-10-14 16:27:31 +00002141 abi_ulong sigc_mask; /* sigmask to restore */
2142 abi_ulong sigc_sp; /* stack pointer */
2143 abi_ulong sigc_pc; /* program counter */
2144 abi_ulong sigc_npc; /* next program counter */
2145 abi_ulong sigc_psr; /* for condition codes etc */
2146 abi_ulong sigc_g1; /* User uses these two registers */
2147 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002148
2149 /* Now comes information regarding the users window set
2150 * at the time of the signal.
2151 */
blueswir1992f48a2007-10-14 16:27:31 +00002152 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002153
2154 /* stack ptrs for each regwin buf */
2155 char *sigc_spbuf[__SUNOS_MAXWIN];
2156
2157 /* Windows to restore after signal */
2158 struct {
blueswir1992f48a2007-10-14 16:27:31 +00002159 abi_ulong locals[8];
2160 abi_ulong ins[8];
bellard6d5e2162004-09-30 22:04:13 +00002161 } sigc_wbuf[__SUNOS_MAXWIN];
2162};
2163/* A Sparc stack frame */
2164struct sparc_stackf {
blueswir1992f48a2007-10-14 16:27:31 +00002165 abi_ulong locals[8];
Peter Maydelle321c342011-02-01 15:54:52 +00002166 abi_ulong ins[8];
2167 /* It's simpler to treat fp and callers_pc as elements of ins[]
2168 * since we never need to access them ourselves.
2169 */
bellard6d5e2162004-09-30 22:04:13 +00002170 char *structptr;
blueswir1992f48a2007-10-14 16:27:31 +00002171 abi_ulong xargs[6];
2172 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002173};
2174
2175typedef struct {
2176 struct {
blueswir1992f48a2007-10-14 16:27:31 +00002177 abi_ulong psr;
2178 abi_ulong pc;
2179 abi_ulong npc;
2180 abi_ulong y;
2181 abi_ulong u_regs[16]; /* globals and ins */
bellard6d5e2162004-09-30 22:04:13 +00002182 } si_regs;
2183 int si_mask;
2184} __siginfo_t;
2185
2186typedef struct {
Blue Swirl8954bae2012-07-30 15:29:11 +00002187 abi_ulong si_float_regs[32];
bellard6d5e2162004-09-30 22:04:13 +00002188 unsigned long si_fsr;
2189 unsigned long si_fpqdepth;
2190 struct {
2191 unsigned long *insn_addr;
2192 unsigned long insn;
2193 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002194} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002195
2196
2197struct target_signal_frame {
2198 struct sparc_stackf ss;
2199 __siginfo_t info;
bellardf8b0aa22007-11-11 23:03:42 +00002200 abi_ulong fpu_save;
blueswir1992f48a2007-10-14 16:27:31 +00002201 abi_ulong insns[2] __attribute__ ((aligned (8)));
2202 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2203 abi_ulong extra_size; /* Should be 0 */
Anthony Liguoric227f092009-10-01 16:12:16 -05002204 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002205};
2206struct target_rt_signal_frame {
2207 struct sparc_stackf ss;
2208 siginfo_t info;
blueswir1992f48a2007-10-14 16:27:31 +00002209 abi_ulong regs[20];
bellard6d5e2162004-09-30 22:04:13 +00002210 sigset_t mask;
bellardf8b0aa22007-11-11 23:03:42 +00002211 abi_ulong fpu_save;
bellard6d5e2162004-09-30 22:04:13 +00002212 unsigned int insns[2];
2213 stack_t stack;
2214 unsigned int extra_size; /* Should be 0 */
Anthony Liguoric227f092009-10-01 16:12:16 -05002215 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002216};
2217
bellarde80cfcf2004-12-19 23:18:01 +00002218#define UREG_O0 16
2219#define UREG_O6 22
2220#define UREG_I0 0
2221#define UREG_I1 1
2222#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002223#define UREG_I3 3
2224#define UREG_I4 4
2225#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002226#define UREG_I6 6
2227#define UREG_I7 7
2228#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002229#define UREG_FP UREG_I6
2230#define UREG_SP UREG_O6
2231
pbrook624f7972008-05-31 16:11:38 +00002232static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002233 CPUSPARCState *env,
2234 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002235{
bellard459a4012007-11-11 19:45:10 +00002236 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002237
2238 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002239
2240 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00002241 if (sa->sa_flags & TARGET_SA_ONSTACK) {
thsa04e1342007-09-27 13:57:58 +00002242 if (!on_sig_stack(sp)
2243 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
2244 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
bellard6d5e2162004-09-30 22:04:13 +00002245 }
bellard459a4012007-11-11 19:45:10 +00002246 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002247}
2248
2249static int
Andreas Färber05390242012-02-25 03:37:53 +01002250setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002251{
2252 int err = 0, i;
2253
Riku Voipio1d8b5122014-04-23 10:26:05 +03002254 __put_user(env->psr, &si->si_regs.psr);
2255 __put_user(env->pc, &si->si_regs.pc);
2256 __put_user(env->npc, &si->si_regs.npc);
2257 __put_user(env->y, &si->si_regs.y);
bellarda315a142005-01-30 22:59:18 +00002258 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002259 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
bellard6d5e2162004-09-30 22:04:13 +00002260 }
bellarda315a142005-01-30 22:59:18 +00002261 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002262 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
bellard6d5e2162004-09-30 22:04:13 +00002263 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002264 __put_user(mask, &si->si_mask);
bellard6d5e2162004-09-30 22:04:13 +00002265 return err;
2266}
bellarde80cfcf2004-12-19 23:18:01 +00002267
bellard80a9d032005-01-03 23:31:27 +00002268#if 0
bellard6d5e2162004-09-30 22:04:13 +00002269static int
2270setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002271 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002272{
2273 int err = 0;
2274
Riku Voipio1d8b5122014-04-23 10:26:05 +03002275 __put_user(mask, &sc->sigc_mask);
2276 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2277 __put_user(env->pc, &sc->sigc_pc);
2278 __put_user(env->npc, &sc->sigc_npc);
2279 __put_user(env->psr, &sc->sigc_psr);
2280 __put_user(env->gregs[1], &sc->sigc_g1);
2281 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002282
2283 return err;
2284}
bellard80a9d032005-01-03 23:31:27 +00002285#endif
bellard6d5e2162004-09-30 22:04:13 +00002286#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2287
pbrook624f7972008-05-31 16:11:38 +00002288static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002289 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002290{
bellard459a4012007-11-11 19:45:10 +00002291 abi_ulong sf_addr;
bellard6d5e2162004-09-30 22:04:13 +00002292 struct target_signal_frame *sf;
2293 int sigframe_size, err, i;
2294
2295 /* 1. Make sure everything is clean */
2296 //synchronize_user_stack();
2297
2298 sigframe_size = NF_ALIGNEDSZ;
bellard459a4012007-11-11 19:45:10 +00002299 sf_addr = get_sigframe(ka, env, sigframe_size);
bellard6d5e2162004-09-30 22:04:13 +00002300
bellard459a4012007-11-11 19:45:10 +00002301 sf = lock_user(VERIFY_WRITE, sf_addr,
2302 sizeof(struct target_signal_frame), 0);
2303 if (!sf)
2304 goto sigsegv;
2305
bellarde80cfcf2004-12-19 23:18:01 +00002306 //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
bellard6d5e2162004-09-30 22:04:13 +00002307#if 0
2308 if (invalid_frame_pointer(sf, sigframe_size))
2309 goto sigill_and_return;
2310#endif
2311 /* 2. Save the current process state */
2312 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002313 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002314
Riku Voipio1d8b5122014-04-23 10:26:05 +03002315 //save_fpu_state(regs, &sf->fpu_state);
2316 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002317
Riku Voipio1d8b5122014-04-23 10:26:05 +03002318 __put_user(set->sig[0], &sf->info.si_mask);
bellard6d5e2162004-09-30 22:04:13 +00002319 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002320 __put_user(set->sig[i + 1], &sf->extramask[i]);
bellard6d5e2162004-09-30 22:04:13 +00002321 }
2322
bellarda315a142005-01-30 22:59:18 +00002323 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002324 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
bellard6d5e2162004-09-30 22:04:13 +00002325 }
bellarda315a142005-01-30 22:59:18 +00002326 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002327 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
bellard6d5e2162004-09-30 22:04:13 +00002328 }
bellard6d5e2162004-09-30 22:04:13 +00002329 if (err)
2330 goto sigsegv;
2331
2332 /* 3. signal handler back-trampoline and parameters */
bellard459a4012007-11-11 19:45:10 +00002333 env->regwptr[UREG_FP] = sf_addr;
bellard6d5e2162004-09-30 22:04:13 +00002334 env->regwptr[UREG_I0] = sig;
bellard459a4012007-11-11 19:45:10 +00002335 env->regwptr[UREG_I1] = sf_addr +
2336 offsetof(struct target_signal_frame, info);
2337 env->regwptr[UREG_I2] = sf_addr +
2338 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002339
2340 /* 4. signal handler */
pbrook624f7972008-05-31 16:11:38 +00002341 env->pc = ka->_sa_handler;
bellard6d5e2162004-09-30 22:04:13 +00002342 env->npc = (env->pc + 4);
2343 /* 5. return to kernel instructions */
pbrook624f7972008-05-31 16:11:38 +00002344 if (ka->sa_restorer)
2345 env->regwptr[UREG_I7] = ka->sa_restorer;
bellard6d5e2162004-09-30 22:04:13 +00002346 else {
bellard775b58d2007-11-11 16:22:17 +00002347 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002348
2349 env->regwptr[UREG_I7] = sf_addr +
2350 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002351
2352 /* mov __NR_sigreturn, %g1 */
bellard775b58d2007-11-11 16:22:17 +00002353 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002354 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002355
2356 /* t 0x10 */
bellard775b58d2007-11-11 16:22:17 +00002357 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002358 __put_user(val32, &sf->insns[1]);
bellard6d5e2162004-09-30 22:04:13 +00002359 if (err)
2360 goto sigsegv;
2361
2362 /* Flush instruction space. */
2363 //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
bellard80a9d032005-01-03 23:31:27 +00002364 // tb_flush(env);
bellard6d5e2162004-09-30 22:04:13 +00002365 }
bellard459a4012007-11-11 19:45:10 +00002366 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
bellard6d5e2162004-09-30 22:04:13 +00002367 return;
bellard459a4012007-11-11 19:45:10 +00002368#if 0
2369sigill_and_return:
bellard6d5e2162004-09-30 22:04:13 +00002370 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002371#endif
bellard6d5e2162004-09-30 22:04:13 +00002372sigsegv:
bellarde80cfcf2004-12-19 23:18:01 +00002373 //fprintf(stderr, "force_sig\n");
bellard459a4012007-11-11 19:45:10 +00002374 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
bellard6d5e2162004-09-30 22:04:13 +00002375 force_sig(TARGET_SIGSEGV);
2376}
bellard6d5e2162004-09-30 22:04:13 +00002377
pbrook624f7972008-05-31 16:11:38 +00002378static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002379 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002380 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002381{
2382 fprintf(stderr, "setup_rt_frame: not implemented\n");
2383}
2384
Andreas Färber05390242012-02-25 03:37:53 +01002385long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002386{
bellardf8b0aa22007-11-11 23:03:42 +00002387 abi_ulong sf_addr;
bellard6d5e2162004-09-30 22:04:13 +00002388 struct target_signal_frame *sf;
bellarde80cfcf2004-12-19 23:18:01 +00002389 uint32_t up_psr, pc, npc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002390 target_sigset_t set;
bellarde80cfcf2004-12-19 23:18:01 +00002391 sigset_t host_set;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002392 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002393
bellardf8b0aa22007-11-11 23:03:42 +00002394 sf_addr = env->regwptr[UREG_FP];
2395 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
2396 goto segv_and_exit;
bellard80a9d032005-01-03 23:31:27 +00002397#if 0
bellarde80cfcf2004-12-19 23:18:01 +00002398 fprintf(stderr, "sigreturn\n");
2399 fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
bellard80a9d032005-01-03 23:31:27 +00002400#endif
bellarde80cfcf2004-12-19 23:18:01 +00002401 //cpu_dump_state(env, stderr, fprintf, 0);
bellard6d5e2162004-09-30 22:04:13 +00002402
2403 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002404
bellardf8b0aa22007-11-11 23:03:42 +00002405 if (sf_addr & 3)
bellard6d5e2162004-09-30 22:04:13 +00002406 goto segv_and_exit;
2407
Riku Voipio1d8b5122014-04-23 10:26:05 +03002408 __get_user(pc, &sf->info.si_regs.pc);
2409 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002410
bellard6d5e2162004-09-30 22:04:13 +00002411 if ((pc | npc) & 3)
2412 goto segv_and_exit;
2413
2414 /* 2. Restore the state */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002415 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002416
bellard6d5e2162004-09-30 22:04:13 +00002417 /* User can only change condition codes and FPU enabling in %psr. */
bellarda315a142005-01-30 22:59:18 +00002418 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2419 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
2420
2421 env->pc = pc;
2422 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002423 __get_user(env->y, &sf->info.si_regs.y);
bellarda315a142005-01-30 22:59:18 +00002424 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002425 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
bellarde80cfcf2004-12-19 23:18:01 +00002426 }
bellarda315a142005-01-30 22:59:18 +00002427 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002428 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
bellarde80cfcf2004-12-19 23:18:01 +00002429 }
bellard6d5e2162004-09-30 22:04:13 +00002430
Peter Maydell2aec3a22011-06-16 17:37:14 +01002431 /* FIXME: implement FPU save/restore:
2432 * __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
2437 /* This is pretty much atomic, no amount locking would prevent
2438 * the races which exist anyways.
2439 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002440 __get_user(set.sig[0], &sf->info.si_mask);
bellarde80cfcf2004-12-19 23:18:01 +00002441 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002442 __get_user(set.sig[i], &sf->extramask[i - 1]);
bellarde80cfcf2004-12-19 23:18:01 +00002443 }
2444
2445 target_to_host_sigset_internal(&host_set, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002446 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard6d5e2162004-09-30 22:04:13 +00002447
2448 if (err)
2449 goto segv_and_exit;
bellardf8b0aa22007-11-11 23:03:42 +00002450 unlock_user_struct(sf, sf_addr, 0);
bellard6d5e2162004-09-30 22:04:13 +00002451 return env->regwptr[0];
2452
2453segv_and_exit:
bellardf8b0aa22007-11-11 23:03:42 +00002454 unlock_user_struct(sf, sf_addr, 0);
bellard6d5e2162004-09-30 22:04:13 +00002455 force_sig(TARGET_SIGSEGV);
2456}
2457
Andreas Färber05390242012-02-25 03:37:53 +01002458long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002459{
2460 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002461 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002462}
2463
bellard459a4012007-11-11 19:45:10 +00002464#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
blueswir15bfb56b2007-10-05 17:01:51 +00002465#define MC_TSTATE 0
2466#define MC_PC 1
2467#define MC_NPC 2
2468#define MC_Y 3
2469#define MC_G1 4
2470#define MC_G2 5
2471#define MC_G3 6
2472#define MC_G4 7
2473#define MC_G5 8
2474#define MC_G6 9
2475#define MC_G7 10
2476#define MC_O0 11
2477#define MC_O1 12
2478#define MC_O2 13
2479#define MC_O3 14
2480#define MC_O4 15
2481#define MC_O5 16
2482#define MC_O6 17
2483#define MC_O7 18
2484#define MC_NGREG 19
2485
Anthony Liguoric227f092009-10-01 16:12:16 -05002486typedef abi_ulong target_mc_greg_t;
2487typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002488
2489struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002490 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002491 uint32_t mcfq_insn;
2492};
2493
2494struct target_mc_fpu {
2495 union {
2496 uint32_t sregs[32];
2497 uint64_t dregs[32];
2498 //uint128_t qregs[16];
2499 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002500 abi_ulong mcfpu_fsr;
2501 abi_ulong mcfpu_fprs;
2502 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002503 struct target_mc_fq *mcfpu_fq;
2504 unsigned char mcfpu_qcnt;
2505 unsigned char mcfpu_qentsz;
2506 unsigned char mcfpu_enab;
2507};
Anthony Liguoric227f092009-10-01 16:12:16 -05002508typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002509
2510typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002511 target_mc_gregset_t mc_gregs;
2512 target_mc_greg_t mc_fp;
2513 target_mc_greg_t mc_i7;
2514 target_mc_fpu_t mc_fpregs;
2515} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002516
2517struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002518 struct target_ucontext *tuc_link;
2519 abi_ulong tuc_flags;
2520 target_sigset_t tuc_sigmask;
2521 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002522};
2523
2524/* A V9 register window */
2525struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002526 abi_ulong locals[8];
2527 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002528};
2529
2530#define TARGET_STACK_BIAS 2047
2531
2532/* {set, get}context() needed for 64-bit SparcLinux userland. */
2533void sparc64_set_context(CPUSPARCState *env)
2534{
bellard459a4012007-11-11 19:45:10 +00002535 abi_ulong ucp_addr;
2536 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002537 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002538 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002539 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002540 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002541
bellard459a4012007-11-11 19:45:10 +00002542 ucp_addr = env->regwptr[UREG_I0];
2543 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
2544 goto do_sigsegv;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002545 grp = &ucp->tuc_mcontext.mc_gregs;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002546 __get_user(pc, &((*grp)[MC_PC]));
2547 __get_user(npc, &((*grp)[MC_NPC]));
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002548 if ((pc | npc) & 3)
blueswir15bfb56b2007-10-05 17:01:51 +00002549 goto do_sigsegv;
2550 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002551 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002552 sigset_t set;
2553
2554 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002555 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002556 } else {
bellard459a4012007-11-11 19:45:10 +00002557 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002558 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002559 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002560 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002561 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002562 }
blueswir15bfb56b2007-10-05 17:01:51 +00002563 }
2564 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002565 do_sigprocmask(SIG_SETMASK, &set, NULL);
blueswir15bfb56b2007-10-05 17:01:51 +00002566 }
2567 env->pc = pc;
2568 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002569 __get_user(env->y, &((*grp)[MC_Y]));
2570 __get_user(tstate, &((*grp)[MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002571 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002572 cpu_put_ccr(env, tstate >> 32);
2573 cpu_put_cwp64(env, tstate & 0x1f);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002574 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2575 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2576 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2577 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2578 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2579 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2580 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2581 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2582 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2583 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2584 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2585 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2586 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2587 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2588 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002589
Riku Voipio1d8b5122014-04-23 10:26:05 +03002590 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2591 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002592
bellard459a4012007-11-11 19:45:10 +00002593 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2594 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2595 abi_ulong) != 0)
2596 goto do_sigsegv;
2597 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2598 abi_ulong) != 0)
2599 goto do_sigsegv;
Peter Maydellc7b016b2011-06-16 17:37:15 +01002600 /* FIXME this does not match how the kernel handles the FPU in
2601 * its sparc64_set_context implementation. In particular the FPU
2602 * is only restored if fenab is non-zero in:
2603 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2604 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002605 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002606 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002607 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2608 for (i = 0; i < 64; i++, src++) {
2609 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002610 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002611 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002612 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002613 }
2614 }
bellard459a4012007-11-11 19:45:10 +00002615 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002616 __get_user(env->fsr,
2617 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2618 __get_user(env->gsr,
2619 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002620 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002621 return;
2622 do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002623 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002624 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002625}
2626
2627void sparc64_get_context(CPUSPARCState *env)
2628{
bellard459a4012007-11-11 19:45:10 +00002629 abi_ulong ucp_addr;
2630 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002631 target_mc_gregset_t *grp;
2632 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002633 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002634 int err;
2635 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002636 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002637 sigset_t set;
2638
bellard459a4012007-11-11 19:45:10 +00002639 ucp_addr = env->regwptr[UREG_I0];
2640 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
2641 goto do_sigsegv;
2642
Aurelien Jarno60e99242010-03-29 02:12:51 +02002643 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002644 grp = &mcp->mc_gregs;
2645
2646 /* Skip over the trap instruction, first. */
2647 env->pc = env->npc;
2648 env->npc += 4;
2649
2650 err = 0;
2651
Alex Barcelo1c275922014-03-14 14:36:55 +00002652 do_sigprocmask(0, NULL, &set);
blueswir15bfb56b2007-10-05 17:01:51 +00002653 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00002654 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002655 __put_user(target_set.sig[0],
2656 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00002657 } else {
2658 abi_ulong *src, *dst;
2659 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002660 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002661 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002662 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002663 }
blueswir15bfb56b2007-10-05 17:01:51 +00002664 if (err)
2665 goto do_sigsegv;
2666 }
2667
bellard459a4012007-11-11 19:45:10 +00002668 /* XXX: tstate must be saved properly */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002669 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2670 __put_user(env->pc, &((*grp)[MC_PC]));
2671 __put_user(env->npc, &((*grp)[MC_NPC]));
2672 __put_user(env->y, &((*grp)[MC_Y]));
2673 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2674 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2675 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2676 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2677 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2678 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2679 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2680 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2681 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2682 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2683 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2684 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2685 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2686 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2687 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002688
bellard459a4012007-11-11 19:45:10 +00002689 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2690 fp = i7 = 0;
2691 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2692 abi_ulong) != 0)
2693 goto do_sigsegv;
2694 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2695 abi_ulong) != 0)
2696 goto do_sigsegv;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002697 __put_user(fp, &(mcp->mc_fp));
2698 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002699
bellard459a4012007-11-11 19:45:10 +00002700 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002701 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2702 for (i = 0; i < 64; i++, dst++) {
2703 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002704 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002705 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002706 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002707 }
2708 }
bellard459a4012007-11-11 19:45:10 +00002709 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002710 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2711 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2712 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00002713
2714 if (err)
2715 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00002716 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00002717 return;
2718 do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002719 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02002720 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002721}
2722#endif
Richard Hendersonff970902013-02-10 10:30:42 -08002723#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00002724
Richard Hendersonff970902013-02-10 10:30:42 -08002725# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00002726struct target_sigcontext {
2727 uint32_t sc_regmask; /* Unused */
2728 uint32_t sc_status;
2729 uint64_t sc_pc;
2730 uint64_t sc_regs[32];
2731 uint64_t sc_fpregs[32];
2732 uint32_t sc_ownedfp; /* Unused */
2733 uint32_t sc_fpc_csr;
2734 uint32_t sc_fpc_eir; /* Unused */
2735 uint32_t sc_used_math;
2736 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01002737 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00002738 uint64_t sc_mdhi;
2739 uint64_t sc_mdlo;
2740 target_ulong sc_hi1; /* Was sc_cause */
2741 target_ulong sc_lo1; /* Was sc_badvaddr */
2742 target_ulong sc_hi2; /* Was sc_sigset[4] */
2743 target_ulong sc_lo2;
2744 target_ulong sc_hi3;
2745 target_ulong sc_lo3;
2746};
Richard Hendersonff970902013-02-10 10:30:42 -08002747# else /* N32 || N64 */
2748struct target_sigcontext {
2749 uint64_t sc_regs[32];
2750 uint64_t sc_fpregs[32];
2751 uint64_t sc_mdhi;
2752 uint64_t sc_hi1;
2753 uint64_t sc_hi2;
2754 uint64_t sc_hi3;
2755 uint64_t sc_mdlo;
2756 uint64_t sc_lo1;
2757 uint64_t sc_lo2;
2758 uint64_t sc_lo3;
2759 uint64_t sc_pc;
2760 uint32_t sc_fpc_csr;
2761 uint32_t sc_used_math;
2762 uint32_t sc_dsp;
2763 uint32_t sc_reserved;
2764};
2765# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00002766
2767struct sigframe {
2768 uint32_t sf_ass[4]; /* argument save space for o32 */
2769 uint32_t sf_code[2]; /* signal trampoline */
2770 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002771 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00002772};
2773
pbrook0b1bcb02009-04-21 01:41:10 +00002774struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002775 target_ulong tuc_flags;
2776 target_ulong tuc_link;
2777 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01002778 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002779 struct target_sigcontext tuc_mcontext;
2780 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00002781};
2782
2783struct target_rt_sigframe {
2784 uint32_t rs_ass[4]; /* argument save space for o32 */
2785 uint32_t rs_code[2]; /* signal trampoline */
2786 struct target_siginfo rs_info;
2787 struct target_ucontext rs_uc;
2788};
2789
bellard106ec872006-06-27 21:08:10 +00002790/* Install trampoline to jump back from signal handler */
2791static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2792{
Richard Henderson084d0492013-02-10 10:30:44 -08002793 int err = 0;
bellard106ec872006-06-27 21:08:10 +00002794
2795 /*
Richard Henderson084d0492013-02-10 10:30:44 -08002796 * Set up the return code ...
2797 *
2798 * li v0, __NR__foo_sigreturn
2799 * syscall
2800 */
bellard106ec872006-06-27 21:08:10 +00002801
Riku Voipio1d8b5122014-04-23 10:26:05 +03002802 __put_user(0x24020000 + syscall, tramp + 0);
2803 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00002804 return err;
2805}
2806
Riku Voipio41ecc722014-04-23 11:01:00 +03002807static inline void setup_sigcontext(CPUMIPSState *regs,
2808 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002809{
Richard Henderson084d0492013-02-10 10:30:44 -08002810 int i;
bellard106ec872006-06-27 21:08:10 +00002811
Riku Voipio1d8b5122014-04-23 10:26:05 +03002812 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07002813 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00002814
Richard Henderson084d0492013-02-10 10:30:44 -08002815 __put_user(0, &sc->sc_regs[0]);
2816 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002817 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002818 }
bellard106ec872006-06-27 21:08:10 +00002819
Riku Voipio1d8b5122014-04-23 10:26:05 +03002820 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2821 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002822
Richard Henderson084d0492013-02-10 10:30:44 -08002823 /* Rather than checking for dsp existence, always copy. The storage
2824 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002825 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2826 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2827 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2828 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2829 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2830 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002831 {
2832 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002833 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00002834 }
Richard Henderson084d0492013-02-10 10:30:44 -08002835
Riku Voipio1d8b5122014-04-23 10:26:05 +03002836 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08002837
2838 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002839 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00002840 }
bellard106ec872006-06-27 21:08:10 +00002841}
2842
Riku Voipio016d2e12014-04-23 11:19:48 +03002843static inline void
Andreas Färber05390242012-02-25 03:37:53 +01002844restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002845{
Richard Henderson084d0492013-02-10 10:30:44 -08002846 int i;
bellard106ec872006-06-27 21:08:10 +00002847
Riku Voipio1d8b5122014-04-23 10:26:05 +03002848 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00002849
Riku Voipio1d8b5122014-04-23 10:26:05 +03002850 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2851 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002852
Richard Henderson084d0492013-02-10 10:30:44 -08002853 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002854 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00002855 }
2856
Riku Voipio1d8b5122014-04-23 10:26:05 +03002857 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2858 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2859 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2860 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2861 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2862 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002863 {
2864 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002865 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08002866 cpu_wrdsp(dsp, 0x3ff, regs);
2867 }
2868
2869 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002870 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002871 }
bellard106ec872006-06-27 21:08:10 +00002872}
Richard Hendersonff970902013-02-10 10:30:42 -08002873
bellard106ec872006-06-27 21:08:10 +00002874/*
2875 * Determine which stack to use..
2876 */
bellard579a97f2007-11-11 14:26:47 +00002877static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002878get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00002879{
2880 unsigned long sp;
2881
2882 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00002883 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00002884
2885 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01002886 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00002887 * above the user stack, 16-bytes before the next lowest
2888 * 16 byte boundary. Try to avoid trashing it.
2889 */
2890 sp -= 32;
2891
bellard106ec872006-06-27 21:08:10 +00002892 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00002893 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00002894 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2895 }
bellard106ec872006-06-27 21:08:10 +00002896
bellard579a97f2007-11-11 14:26:47 +00002897 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00002898}
2899
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002900static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
2901{
2902 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
2903 env->hflags &= ~MIPS_HFLAG_M16;
2904 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
2905 env->active_tc.PC &= ~(target_ulong) 1;
2906 }
2907}
2908
Richard Hendersonff970902013-02-10 10:30:42 -08002909# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00002910/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002911static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01002912 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002913{
2914 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002915 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00002916 int i;
2917
bellard579a97f2007-11-11 14:26:47 +00002918 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2919 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
bellard106ec872006-06-27 21:08:10 +00002920 goto give_sigsegv;
2921
2922 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2923
Riku Voipio41ecc722014-04-23 11:01:00 +03002924 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002925
2926 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03002927 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00002928 }
2929
2930 /*
2931 * Arguments to signal handler:
2932 *
2933 * a0 = signal number
2934 * a1 = 0 (should be cause)
2935 * a2 = pointer to struct sigcontext
2936 *
2937 * $25 and PC point to the signal handler, $29 points to the
2938 * struct sigframe.
2939 */
thsb5dc7732008-06-27 10:02:35 +00002940 regs->active_tc.gpr[ 4] = sig;
2941 regs->active_tc.gpr[ 5] = 0;
2942 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2943 regs->active_tc.gpr[29] = frame_addr;
2944 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00002945 /* The original kernel code sets CP0_EPC to the handler
2946 * since it returns to userland using eret
2947 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00002948 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002949 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00002950 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00002951 return;
2952
2953give_sigsegv:
2954 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00002955}
2956
Andreas Färber05390242012-02-25 03:37:53 +01002957long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002958{
ths388bb212007-05-13 13:58:00 +00002959 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002960 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00002961 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05002962 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00002963 int i;
bellard106ec872006-06-27 21:08:10 +00002964
2965#if defined(DEBUG_SIGNAL)
ths388bb212007-05-13 13:58:00 +00002966 fprintf(stderr, "do_sigreturn\n");
bellard106ec872006-06-27 21:08:10 +00002967#endif
thsb5dc7732008-06-27 10:02:35 +00002968 frame_addr = regs->active_tc.gpr[29];
bellard579a97f2007-11-11 14:26:47 +00002969 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
bellard106ec872006-06-27 21:08:10 +00002970 goto badframe;
2971
ths388bb212007-05-13 13:58:00 +00002972 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03002973 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00002974 }
bellard106ec872006-06-27 21:08:10 +00002975
ths388bb212007-05-13 13:58:00 +00002976 target_to_host_sigset_internal(&blocked, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002977 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
bellard106ec872006-06-27 21:08:10 +00002978
Riku Voipio016d2e12014-04-23 11:19:48 +03002979 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002980
2981#if 0
ths388bb212007-05-13 13:58:00 +00002982 /*
2983 * Don't let your children do this ...
2984 */
2985 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00002986 "move\t$29, %0\n\t"
2987 "j\tsyscall_exit"
2988 :/* no outputs */
2989 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00002990 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00002991#endif
ths3b46e622007-09-17 08:09:54 +00002992
thsb5dc7732008-06-27 10:02:35 +00002993 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002994 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00002995 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00002996 * maybe a problem with nested signals ? */
2997 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00002998 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00002999
3000badframe:
ths388bb212007-05-13 13:58:00 +00003001 force_sig(TARGET_SIGSEGV/*, current*/);
3002 return 0;
bellard106ec872006-06-27 21:08:10 +00003003}
Richard Hendersonff970902013-02-10 10:30:42 -08003004# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003005
pbrook624f7972008-05-31 16:11:38 +00003006static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003007 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003008 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003009{
pbrook0b1bcb02009-04-21 01:41:10 +00003010 struct target_rt_sigframe *frame;
3011 abi_ulong frame_addr;
3012 int i;
3013
3014 frame_addr = get_sigframe(ka, env, sizeof(*frame));
3015 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3016 goto give_sigsegv;
3017
3018 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3019
3020 copy_siginfo_to_user(&frame->rs_info, info);
3021
Aurelien Jarno60e99242010-03-29 02:12:51 +02003022 __put_user(0, &frame->rs_uc.tuc_flags);
3023 __put_user(0, &frame->rs_uc.tuc_link);
3024 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3025 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003026 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003027 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003028
Aurelien Jarno60e99242010-03-29 02:12:51 +02003029 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003030
3031 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003032 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003033 }
3034
3035 /*
3036 * Arguments to signal handler:
3037 *
3038 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003039 * a1 = pointer to siginfo_t
pbrook0b1bcb02009-04-21 01:41:10 +00003040 * a2 = pointer to struct ucontext
3041 *
3042 * $25 and PC point to the signal handler, $29 points to the
3043 * struct sigframe.
3044 */
3045 env->active_tc.gpr[ 4] = sig;
3046 env->active_tc.gpr[ 5] = frame_addr
3047 + offsetof(struct target_rt_sigframe, rs_info);
3048 env->active_tc.gpr[ 6] = frame_addr
3049 + offsetof(struct target_rt_sigframe, rs_uc);
3050 env->active_tc.gpr[29] = frame_addr;
3051 env->active_tc.gpr[31] = frame_addr
3052 + offsetof(struct target_rt_sigframe, rs_code);
3053 /* The original kernel code sets CP0_EPC to the handler
3054 * since it returns to userland using eret
3055 * we cannot do this here, and we must set PC directly */
3056 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003057 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003058 unlock_user_struct(frame, frame_addr, 1);
3059 return;
3060
3061give_sigsegv:
3062 unlock_user_struct(frame, frame_addr, 1);
3063 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00003064}
3065
Andreas Färber05390242012-02-25 03:37:53 +01003066long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003067{
pbrook0b1bcb02009-04-21 01:41:10 +00003068 struct target_rt_sigframe *frame;
3069 abi_ulong frame_addr;
3070 sigset_t blocked;
3071
3072#if defined(DEBUG_SIGNAL)
3073 fprintf(stderr, "do_rt_sigreturn\n");
3074#endif
3075 frame_addr = env->active_tc.gpr[29];
3076 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3077 goto badframe;
3078
Aurelien Jarno60e99242010-03-29 02:12:51 +02003079 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00003080 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
pbrook0b1bcb02009-04-21 01:41:10 +00003081
Riku Voipio016d2e12014-04-23 11:19:48 +03003082 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003083
3084 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02003085 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
pbrook0b1bcb02009-04-21 01:41:10 +00003086 0, get_sp_from_cpustate(env)) == -EFAULT)
3087 goto badframe;
3088
3089 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003090 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003091 /* I am not sure this is right, but it seems to work
3092 * maybe a problem with nested signals ? */
3093 env->CP0_EPC = 0;
3094 return -TARGET_QEMU_ESIGRETURN;
3095
3096badframe:
3097 force_sig(TARGET_SIGSEGV/*, current*/);
3098 return 0;
bellard106ec872006-06-27 21:08:10 +00003099}
bellard6d5e2162004-09-30 22:04:13 +00003100
thsc3b5bc82007-12-02 06:31:25 +00003101#elif defined(TARGET_SH4)
3102
3103/*
3104 * code and data structures from linux kernel:
3105 * include/asm-sh/sigcontext.h
3106 * arch/sh/kernel/signal.c
3107 */
3108
3109struct target_sigcontext {
3110 target_ulong oldmask;
3111
3112 /* CPU registers */
3113 target_ulong sc_gregs[16];
3114 target_ulong sc_pc;
3115 target_ulong sc_pr;
3116 target_ulong sc_sr;
3117 target_ulong sc_gbr;
3118 target_ulong sc_mach;
3119 target_ulong sc_macl;
3120
3121 /* FPU registers */
3122 target_ulong sc_fpregs[16];
3123 target_ulong sc_xfpregs[16];
3124 unsigned int sc_fpscr;
3125 unsigned int sc_fpul;
3126 unsigned int sc_ownedfp;
3127};
3128
3129struct target_sigframe
3130{
3131 struct target_sigcontext sc;
3132 target_ulong extramask[TARGET_NSIG_WORDS-1];
3133 uint16_t retcode[3];
3134};
3135
3136
3137struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003138 target_ulong tuc_flags;
3139 struct target_ucontext *tuc_link;
3140 target_stack_t tuc_stack;
3141 struct target_sigcontext tuc_mcontext;
3142 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003143};
3144
3145struct target_rt_sigframe
3146{
3147 struct target_siginfo info;
3148 struct target_ucontext uc;
3149 uint16_t retcode[3];
3150};
3151
3152
3153#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3154#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3155
pbrook624f7972008-05-31 16:11:38 +00003156static abi_ulong get_sigframe(struct target_sigaction *ka,
thsc3b5bc82007-12-02 06:31:25 +00003157 unsigned long sp, size_t frame_size)
3158{
pbrook624f7972008-05-31 16:11:38 +00003159 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003160 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3161 }
3162
3163 return (sp - frame_size) & -8ul;
3164}
3165
Riku Voipio41ecc722014-04-23 11:01:00 +03003166static void setup_sigcontext(struct target_sigcontext *sc,
Andreas Färber05390242012-02-25 03:37:53 +01003167 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003168{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003169 int i;
thsc3b5bc82007-12-02 06:31:25 +00003170
Riku Voipio1d8b5122014-04-23 10:26:05 +03003171#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003172 COPY(gregs[0]); COPY(gregs[1]);
3173 COPY(gregs[2]); COPY(gregs[3]);
3174 COPY(gregs[4]); COPY(gregs[5]);
3175 COPY(gregs[6]); COPY(gregs[7]);
3176 COPY(gregs[8]); COPY(gregs[9]);
3177 COPY(gregs[10]); COPY(gregs[11]);
3178 COPY(gregs[12]); COPY(gregs[13]);
3179 COPY(gregs[14]); COPY(gregs[15]);
3180 COPY(gbr); COPY(mach);
3181 COPY(macl); COPY(pr);
3182 COPY(sr); COPY(pc);
3183#undef COPY
3184
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003185 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003186 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003187 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003188 __put_user(regs->fpscr, &sc->sc_fpscr);
3189 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003190
3191 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003192 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003193}
3194
Riku Voipio016d2e12014-04-23 11:19:48 +03003195static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003196 target_ulong *r0_p)
thsc3b5bc82007-12-02 06:31:25 +00003197{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003198 int i;
thsc3b5bc82007-12-02 06:31:25 +00003199
Riku Voipio1d8b5122014-04-23 10:26:05 +03003200#define COPY(x) __get_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003201 COPY(gregs[1]);
3202 COPY(gregs[2]); COPY(gregs[3]);
3203 COPY(gregs[4]); COPY(gregs[5]);
3204 COPY(gregs[6]); COPY(gregs[7]);
3205 COPY(gregs[8]); COPY(gregs[9]);
3206 COPY(gregs[10]); COPY(gregs[11]);
3207 COPY(gregs[12]); COPY(gregs[13]);
3208 COPY(gregs[14]); COPY(gregs[15]);
3209 COPY(gbr); COPY(mach);
3210 COPY(macl); COPY(pr);
3211 COPY(sr); COPY(pc);
3212#undef COPY
3213
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003214 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003215 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003216 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003217 __get_user(regs->fpscr, &sc->sc_fpscr);
3218 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003219
3220 regs->tra = -1; /* disable syscall checks */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003221 __get_user(*r0_p, &sc->sc_gregs[0]);
thsc3b5bc82007-12-02 06:31:25 +00003222}
3223
pbrook624f7972008-05-31 16:11:38 +00003224static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003225 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003226{
3227 struct target_sigframe *frame;
3228 abi_ulong frame_addr;
3229 int i;
3230 int err = 0;
3231 int signal;
3232
3233 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3234 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3235 goto give_sigsegv;
3236
3237 signal = current_exec_domain_sig(sig);
3238
Riku Voipio41ecc722014-04-23 11:01:00 +03003239 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003240
3241 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003242 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003243 }
3244
3245 /* Set up to return from userspace. If provided, use a stub
3246 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003247 if (ka->sa_flags & TARGET_SA_RESTORER) {
3248 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003249 } else {
3250 /* Generate return code (system call to sigreturn) */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003251 __put_user(MOVW(2), &frame->retcode[0]);
3252 __put_user(TRAP_NOARG, &frame->retcode[1]);
3253 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
thsc3b5bc82007-12-02 06:31:25 +00003254 regs->pr = (unsigned long) frame->retcode;
3255 }
3256
3257 if (err)
3258 goto give_sigsegv;
3259
3260 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003261 regs->gregs[15] = frame_addr;
thsc3b5bc82007-12-02 06:31:25 +00003262 regs->gregs[4] = signal; /* Arg for signal handler */
3263 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003264 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003265 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003266
3267 unlock_user_struct(frame, frame_addr, 1);
3268 return;
3269
3270give_sigsegv:
3271 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003272 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003273}
3274
pbrook624f7972008-05-31 16:11:38 +00003275static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003276 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003277 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003278{
3279 struct target_rt_sigframe *frame;
3280 abi_ulong frame_addr;
3281 int i;
3282 int err = 0;
3283 int signal;
3284
3285 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3286 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3287 goto give_sigsegv;
3288
3289 signal = current_exec_domain_sig(sig);
3290
Riku Voipiob0fd8d12014-04-23 10:46:13 +03003291 copy_siginfo_to_user(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003292
3293 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003294 __put_user(0, &frame->uc.tuc_flags);
3295 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3296 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3297 &frame->uc.tuc_stack.ss_sp);
3298 __put_user(sas_ss_flags(regs->gregs[15]),
3299 &frame->uc.tuc_stack.ss_flags);
3300 __put_user(target_sigaltstack_used.ss_size,
3301 &frame->uc.tuc_stack.ss_size);
3302 setup_sigcontext(&frame->uc.tuc_mcontext,
thsc3b5bc82007-12-02 06:31:25 +00003303 regs, set->sig[0]);
3304 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003305 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003306 }
3307
3308 /* Set up to return from userspace. If provided, use a stub
3309 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003310 if (ka->sa_flags & TARGET_SA_RESTORER) {
3311 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003312 } else {
3313 /* Generate return code (system call to sigreturn) */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003314 __put_user(MOVW(2), &frame->retcode[0]);
3315 __put_user(TRAP_NOARG, &frame->retcode[1]);
3316 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
thsc3b5bc82007-12-02 06:31:25 +00003317 regs->pr = (unsigned long) frame->retcode;
3318 }
3319
3320 if (err)
3321 goto give_sigsegv;
3322
3323 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003324 regs->gregs[15] = frame_addr;
thsc3b5bc82007-12-02 06:31:25 +00003325 regs->gregs[4] = signal; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003326 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3327 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003328 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003329
3330 unlock_user_struct(frame, frame_addr, 1);
3331 return;
3332
3333give_sigsegv:
3334 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003335 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003336}
3337
Andreas Färber05390242012-02-25 03:37:53 +01003338long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003339{
3340 struct target_sigframe *frame;
3341 abi_ulong frame_addr;
3342 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003343 target_sigset_t target_set;
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003344 target_ulong r0;
thsc3b5bc82007-12-02 06:31:25 +00003345 int i;
3346 int err = 0;
3347
3348#if defined(DEBUG_SIGNAL)
3349 fprintf(stderr, "do_sigreturn\n");
3350#endif
3351 frame_addr = regs->gregs[15];
3352 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3353 goto badframe;
3354
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
Riku Voipio016d2e12014-04-23 11:19:48 +03003366 restore_sigcontext(regs, &frame->sc, &r0);
thsc3b5bc82007-12-02 06:31:25 +00003367
3368 unlock_user_struct(frame, frame_addr, 0);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003369 return r0;
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;
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003382 target_ulong r0;
thsc3b5bc82007-12-02 06:31:25 +00003383
3384#if defined(DEBUG_SIGNAL)
3385 fprintf(stderr, "do_rt_sigreturn\n");
3386#endif
3387 frame_addr = regs->gregs[15];
3388 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3389 goto badframe;
3390
Aurelien Jarno60e99242010-03-29 02:12:51 +02003391 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00003392 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
thsc3b5bc82007-12-02 06:31:25 +00003393
Riku Voipio016d2e12014-04-23 11:19:48 +03003394 restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0);
thsc3b5bc82007-12-02 06:31:25 +00003395
3396 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02003397 offsetof(struct target_rt_sigframe, uc.tuc_stack),
thsc3b5bc82007-12-02 06:31:25 +00003398 0, get_sp_from_cpustate(regs)) == -EFAULT)
3399 goto badframe;
3400
3401 unlock_user_struct(frame, frame_addr, 0);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003402 return r0;
thsc3b5bc82007-12-02 06:31:25 +00003403
3404badframe:
3405 unlock_user_struct(frame, frame_addr, 0);
3406 force_sig(TARGET_SIGSEGV);
3407 return 0;
3408}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003409#elif defined(TARGET_MICROBLAZE)
3410
3411struct target_sigcontext {
3412 struct target_pt_regs regs; /* needs to be first */
3413 uint32_t oldmask;
3414};
3415
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003416struct target_stack_t {
3417 abi_ulong ss_sp;
3418 int ss_flags;
3419 unsigned int ss_size;
3420};
3421
3422struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003423 abi_ulong tuc_flags;
3424 abi_ulong tuc_link;
3425 struct target_stack_t tuc_stack;
3426 struct target_sigcontext tuc_mcontext;
3427 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003428};
3429
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003430/* Signal frames. */
3431struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003432 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003433 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3434 uint32_t tramp[2];
3435};
3436
3437struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003438 siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003439 struct ucontext uc;
3440 uint32_t tramp[2];
3441};
3442
Andreas Färber05390242012-02-25 03:37:53 +01003443static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003444{
3445 __put_user(env->regs[0], &sc->regs.r0);
3446 __put_user(env->regs[1], &sc->regs.r1);
3447 __put_user(env->regs[2], &sc->regs.r2);
3448 __put_user(env->regs[3], &sc->regs.r3);
3449 __put_user(env->regs[4], &sc->regs.r4);
3450 __put_user(env->regs[5], &sc->regs.r5);
3451 __put_user(env->regs[6], &sc->regs.r6);
3452 __put_user(env->regs[7], &sc->regs.r7);
3453 __put_user(env->regs[8], &sc->regs.r8);
3454 __put_user(env->regs[9], &sc->regs.r9);
3455 __put_user(env->regs[10], &sc->regs.r10);
3456 __put_user(env->regs[11], &sc->regs.r11);
3457 __put_user(env->regs[12], &sc->regs.r12);
3458 __put_user(env->regs[13], &sc->regs.r13);
3459 __put_user(env->regs[14], &sc->regs.r14);
3460 __put_user(env->regs[15], &sc->regs.r15);
3461 __put_user(env->regs[16], &sc->regs.r16);
3462 __put_user(env->regs[17], &sc->regs.r17);
3463 __put_user(env->regs[18], &sc->regs.r18);
3464 __put_user(env->regs[19], &sc->regs.r19);
3465 __put_user(env->regs[20], &sc->regs.r20);
3466 __put_user(env->regs[21], &sc->regs.r21);
3467 __put_user(env->regs[22], &sc->regs.r22);
3468 __put_user(env->regs[23], &sc->regs.r23);
3469 __put_user(env->regs[24], &sc->regs.r24);
3470 __put_user(env->regs[25], &sc->regs.r25);
3471 __put_user(env->regs[26], &sc->regs.r26);
3472 __put_user(env->regs[27], &sc->regs.r27);
3473 __put_user(env->regs[28], &sc->regs.r28);
3474 __put_user(env->regs[29], &sc->regs.r29);
3475 __put_user(env->regs[30], &sc->regs.r30);
3476 __put_user(env->regs[31], &sc->regs.r31);
3477 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3478}
3479
Andreas Färber05390242012-02-25 03:37:53 +01003480static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003481{
3482 __get_user(env->regs[0], &sc->regs.r0);
3483 __get_user(env->regs[1], &sc->regs.r1);
3484 __get_user(env->regs[2], &sc->regs.r2);
3485 __get_user(env->regs[3], &sc->regs.r3);
3486 __get_user(env->regs[4], &sc->regs.r4);
3487 __get_user(env->regs[5], &sc->regs.r5);
3488 __get_user(env->regs[6], &sc->regs.r6);
3489 __get_user(env->regs[7], &sc->regs.r7);
3490 __get_user(env->regs[8], &sc->regs.r8);
3491 __get_user(env->regs[9], &sc->regs.r9);
3492 __get_user(env->regs[10], &sc->regs.r10);
3493 __get_user(env->regs[11], &sc->regs.r11);
3494 __get_user(env->regs[12], &sc->regs.r12);
3495 __get_user(env->regs[13], &sc->regs.r13);
3496 __get_user(env->regs[14], &sc->regs.r14);
3497 __get_user(env->regs[15], &sc->regs.r15);
3498 __get_user(env->regs[16], &sc->regs.r16);
3499 __get_user(env->regs[17], &sc->regs.r17);
3500 __get_user(env->regs[18], &sc->regs.r18);
3501 __get_user(env->regs[19], &sc->regs.r19);
3502 __get_user(env->regs[20], &sc->regs.r20);
3503 __get_user(env->regs[21], &sc->regs.r21);
3504 __get_user(env->regs[22], &sc->regs.r22);
3505 __get_user(env->regs[23], &sc->regs.r23);
3506 __get_user(env->regs[24], &sc->regs.r24);
3507 __get_user(env->regs[25], &sc->regs.r25);
3508 __get_user(env->regs[26], &sc->regs.r26);
3509 __get_user(env->regs[27], &sc->regs.r27);
3510 __get_user(env->regs[28], &sc->regs.r28);
3511 __get_user(env->regs[29], &sc->regs.r29);
3512 __get_user(env->regs[30], &sc->regs.r30);
3513 __get_user(env->regs[31], &sc->regs.r31);
3514 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3515}
3516
3517static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003518 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003519{
3520 abi_ulong sp = env->regs[1];
3521
Riku Voipiob545f632014-07-15 17:01:55 +03003522 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003523 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003524 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003525
3526 return ((sp - frame_size) & -8UL);
3527}
3528
3529static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003530 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003531{
3532 struct target_signal_frame *frame;
3533 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003534 int i;
3535
3536 frame_addr = get_sigframe(ka, env, sizeof *frame);
3537 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;
3582 badframe:
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];
3602 /* Make sure the guest isn't playing games. */
3603 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3604 goto badframe;
3605
3606 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003607 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003608 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003609 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003610 }
3611 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00003612 do_sigprocmask(SIG_SETMASK, &set, NULL);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003613
Richard Hendersonf711df62010-11-22 14:57:52 -08003614 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003615 /* We got here through a sigreturn syscall, our path back is via an
3616 rtb insn so setup r14 for that. */
3617 env->regs[14] = env->sregs[SR_PC];
3618
3619 unlock_user_struct(frame, frame_addr, 0);
3620 return env->regs[10];
3621 badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003622 force_sig(TARGET_SIGSEGV);
3623}
3624
Andreas Färber05390242012-02-25 03:37:53 +01003625long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003626{
3627 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3628 return -TARGET_ENOSYS;
3629}
3630
edgar_iglb6d3abd2008-02-28 11:29:27 +00003631#elif defined(TARGET_CRIS)
3632
3633struct target_sigcontext {
3634 struct target_pt_regs regs; /* needs to be first */
3635 uint32_t oldmask;
3636 uint32_t usp; /* usp before stacking this gunk on it */
3637};
3638
3639/* Signal frames. */
3640struct target_signal_frame {
3641 struct target_sigcontext sc;
3642 uint32_t extramask[TARGET_NSIG_WORDS - 1];
Stefan Weil8cfc1142014-02-01 09:41:09 +01003643 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003644};
3645
3646struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003647 siginfo_t *pinfo;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003648 void *puc;
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003649 siginfo_t info;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003650 struct ucontext uc;
Stefan Weil8cfc1142014-02-01 09:41:09 +01003651 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003652};
3653
Andreas Färber05390242012-02-25 03:37:53 +01003654static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003655{
edgar_igl9664d922008-03-03 22:23:53 +00003656 __put_user(env->regs[0], &sc->regs.r0);
3657 __put_user(env->regs[1], &sc->regs.r1);
3658 __put_user(env->regs[2], &sc->regs.r2);
3659 __put_user(env->regs[3], &sc->regs.r3);
3660 __put_user(env->regs[4], &sc->regs.r4);
3661 __put_user(env->regs[5], &sc->regs.r5);
3662 __put_user(env->regs[6], &sc->regs.r6);
3663 __put_user(env->regs[7], &sc->regs.r7);
3664 __put_user(env->regs[8], &sc->regs.r8);
3665 __put_user(env->regs[9], &sc->regs.r9);
3666 __put_user(env->regs[10], &sc->regs.r10);
3667 __put_user(env->regs[11], &sc->regs.r11);
3668 __put_user(env->regs[12], &sc->regs.r12);
3669 __put_user(env->regs[13], &sc->regs.r13);
3670 __put_user(env->regs[14], &sc->usp);
3671 __put_user(env->regs[15], &sc->regs.acr);
3672 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3673 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3674 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003675}
edgar_igl9664d922008-03-03 22:23:53 +00003676
Andreas Färber05390242012-02-25 03:37:53 +01003677static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003678{
edgar_igl9664d922008-03-03 22:23:53 +00003679 __get_user(env->regs[0], &sc->regs.r0);
3680 __get_user(env->regs[1], &sc->regs.r1);
3681 __get_user(env->regs[2], &sc->regs.r2);
3682 __get_user(env->regs[3], &sc->regs.r3);
3683 __get_user(env->regs[4], &sc->regs.r4);
3684 __get_user(env->regs[5], &sc->regs.r5);
3685 __get_user(env->regs[6], &sc->regs.r6);
3686 __get_user(env->regs[7], &sc->regs.r7);
3687 __get_user(env->regs[8], &sc->regs.r8);
3688 __get_user(env->regs[9], &sc->regs.r9);
3689 __get_user(env->regs[10], &sc->regs.r10);
3690 __get_user(env->regs[11], &sc->regs.r11);
3691 __get_user(env->regs[12], &sc->regs.r12);
3692 __get_user(env->regs[13], &sc->regs.r13);
3693 __get_user(env->regs[14], &sc->usp);
3694 __get_user(env->regs[15], &sc->regs.acr);
3695 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3696 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3697 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003698}
3699
Andreas Färber05390242012-02-25 03:37:53 +01003700static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003701{
edgar_igl9664d922008-03-03 22:23:53 +00003702 abi_ulong sp;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003703 /* Align the stack downwards to 4. */
edgar_igl9664d922008-03-03 22:23:53 +00003704 sp = (env->regs[R_SP] & ~3);
3705 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003706}
3707
pbrook624f7972008-05-31 16:11:38 +00003708static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003709 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003710{
3711 struct target_signal_frame *frame;
edgar_igl9664d922008-03-03 22:23:53 +00003712 abi_ulong frame_addr;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003713 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003714
edgar_igl9664d922008-03-03 22:23:53 +00003715 frame_addr = get_sigframe(env, sizeof *frame);
3716 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
edgar_iglb6d3abd2008-02-28 11:29:27 +00003717 goto badframe;
3718
3719 /*
3720 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3721 * use this trampoline anymore but it sets it up for GDB.
3722 * In QEMU, using the trampoline simplifies things a bit so we use it.
3723 *
3724 * This is movu.w __NR_sigreturn, r9; break 13;
3725 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003726 __put_user(0x9c5f, frame->retcode+0);
3727 __put_user(TARGET_NR_sigreturn,
3728 frame->retcode + 1);
3729 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003730
3731 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003732 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003733
Riku Voipio0188fad2014-04-23 13:34:15 +03003734 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3735 __put_user(set->sig[i], &frame->extramask[i - 1]);
3736 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003737
3738 setup_sigcontext(&frame->sc, env);
3739
3740 /* Move the stack and setup the arguments for the handler. */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003741 env->regs[R_SP] = frame_addr;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003742 env->regs[10] = sig;
pbrook624f7972008-05-31 16:11:38 +00003743 env->pc = (unsigned long) ka->_sa_handler;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003744 /* Link SRP so the guest returns through the trampoline. */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003745 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003746
edgar_igl9664d922008-03-03 22:23:53 +00003747 unlock_user_struct(frame, frame_addr, 1);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003748 return;
3749 badframe:
edgar_iglb6d3abd2008-02-28 11:29:27 +00003750 force_sig(TARGET_SIGSEGV);
3751}
3752
pbrook624f7972008-05-31 16:11:38 +00003753static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003754 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003755 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003756{
3757 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3758}
3759
Andreas Färber05390242012-02-25 03:37:53 +01003760long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003761{
3762 struct target_signal_frame *frame;
edgar_igl9664d922008-03-03 22:23:53 +00003763 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003764 target_sigset_t target_set;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003765 sigset_t set;
3766 int i;
3767
edgar_igl9664d922008-03-03 22:23:53 +00003768 frame_addr = env->regs[R_SP];
edgar_iglb6d3abd2008-02-28 11:29:27 +00003769 /* Make sure the guest isn't playing games. */
edgar_igl9664d922008-03-03 22:23:53 +00003770 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
edgar_iglb6d3abd2008-02-28 11:29:27 +00003771 goto badframe;
3772
3773 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003774 __get_user(target_set.sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003775 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003776 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003777 }
3778 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00003779 do_sigprocmask(SIG_SETMASK, &set, NULL);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003780
3781 restore_sigcontext(&frame->sc, env);
edgar_igl9664d922008-03-03 22:23:53 +00003782 unlock_user_struct(frame, frame_addr, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003783 return env->regs[10];
3784 badframe:
edgar_iglb6d3abd2008-02-28 11:29:27 +00003785 force_sig(TARGET_SIGSEGV);
3786}
3787
Andreas Färber05390242012-02-25 03:37:53 +01003788long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003789{
3790 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3791 return -TARGET_ENOSYS;
3792}
thsc3b5bc82007-12-02 06:31:25 +00003793
Jia Liud9627832012-07-20 15:50:52 +08003794#elif defined(TARGET_OPENRISC)
3795
3796struct target_sigcontext {
3797 struct target_pt_regs regs;
3798 abi_ulong oldmask;
3799 abi_ulong usp;
3800};
3801
3802struct target_ucontext {
3803 abi_ulong tuc_flags;
3804 abi_ulong tuc_link;
3805 target_stack_t tuc_stack;
3806 struct target_sigcontext tuc_mcontext;
3807 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3808};
3809
3810struct target_rt_sigframe {
3811 abi_ulong pinfo;
3812 uint64_t puc;
3813 struct target_siginfo info;
3814 struct target_sigcontext sc;
3815 struct target_ucontext uc;
3816 unsigned char retcode[16]; /* trampoline code */
3817};
3818
3819/* This is the asm-generic/ucontext.h version */
3820#if 0
3821static int restore_sigcontext(CPUOpenRISCState *regs,
3822 struct target_sigcontext *sc)
3823{
3824 unsigned int err = 0;
3825 unsigned long old_usp;
3826
3827 /* Alwys make any pending restarted system call return -EINTR */
3828 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3829
3830 /* restore the regs from &sc->regs (same as sc, since regs is first)
3831 * (sc is already checked for VERIFY_READ since the sigframe was
3832 * checked in sys_sigreturn previously)
3833 */
3834
3835 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3836 goto badframe;
3837 }
3838
3839 /* make sure the U-flag is set so user-mode cannot fool us */
3840
3841 regs->sr &= ~SR_SM;
3842
3843 /* restore the old USP as it was before we stacked the sc etc.
3844 * (we cannot just pop the sigcontext since we aligned the sp and
3845 * stuff after pushing it)
3846 */
3847
Riku Voipio1d8b5122014-04-23 10:26:05 +03003848 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003849 phx_signal("old_usp 0x%lx", old_usp);
3850
3851 __PHX__ REALLY /* ??? */
3852 wrusp(old_usp);
3853 regs->gpr[1] = old_usp;
3854
3855 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3856 * after this completes, but we don't use that mechanism. maybe we can
3857 * use it now ?
3858 */
3859
3860 return err;
3861
3862badframe:
3863 return 1;
3864}
3865#endif
3866
3867/* Set up a signal frame. */
3868
Riku Voipio41ecc722014-04-23 11:01:00 +03003869static void setup_sigcontext(struct target_sigcontext *sc,
Jia Liud9627832012-07-20 15:50:52 +08003870 CPUOpenRISCState *regs,
3871 unsigned long mask)
3872{
Jia Liud9627832012-07-20 15:50:52 +08003873 unsigned long usp = regs->gpr[1];
3874
3875 /* copy the regs. they are first in sc so we can use sc directly */
3876
Riku Voipio1d8b5122014-04-23 10:26:05 +03003877 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08003878
3879 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3880 the signal handler. The frametype will be restored to its previous
3881 value in restore_sigcontext. */
3882 /*regs->frametype = CRIS_FRAME_NORMAL;*/
3883
3884 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003885 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03003886 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003887}
3888
3889static inline unsigned long align_sigframe(unsigned long sp)
3890{
3891 unsigned long i;
3892 i = sp & ~3UL;
3893 return i;
3894}
3895
3896static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3897 CPUOpenRISCState *regs,
3898 size_t frame_size)
3899{
3900 unsigned long sp = regs->gpr[1];
3901 int onsigstack = on_sig_stack(sp);
3902
3903 /* redzone */
3904 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03003905 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08003906 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3907 }
3908
3909 sp = align_sigframe(sp - frame_size);
3910
3911 /*
3912 * If we are on the alternate signal stack and would overflow it, don't.
3913 * Return an always-bogus address instead so we will die with SIGSEGV.
3914 */
3915
3916 if (onsigstack && !likely(on_sig_stack(sp))) {
3917 return -1L;
3918 }
3919
3920 return sp;
3921}
3922
3923static void setup_frame(int sig, struct target_sigaction *ka,
3924 target_sigset_t *set, CPUOpenRISCState *env)
3925{
3926 qemu_log("Not implement.\n");
3927}
3928
3929static 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));
3940 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3941 goto give_sigsegv;
3942 }
3943
3944 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003945 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08003946 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003947 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08003948
3949 if (ka->sa_flags & SA_SIGINFO) {
Riku Voipiob0fd8d12014-04-23 10:46:13 +03003950 copy_siginfo_to_user(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08003951 }
3952
3953 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03003954 __put_user(0, &frame->uc.tuc_flags);
3955 __put_user(0, &frame->uc.tuc_link);
3956 __put_user(target_sigaltstack_used.ss_sp,
3957 &frame->uc.tuc_stack.ss_sp);
3958 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
3959 __put_user(target_sigaltstack_used.ss_size,
3960 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03003961 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08003962
3963 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
3964
Jia Liud9627832012-07-20 15:50:52 +08003965 /* trampoline - the desired return ip is the retcode itself */
3966 return_ip = (unsigned long)&frame->retcode;
3967 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003968 __put_user(0xa960, (short *)(frame->retcode + 0));
3969 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
3970 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
3971 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08003972
3973 if (err) {
3974 goto give_sigsegv;
3975 }
3976
3977 /* TODO what is the current->exec_domain stuff and invmap ? */
3978
3979 /* Set up registers for signal handler */
3980 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
3981 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
3982 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
3983 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
3984 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
3985
3986 /* actually move the usp to reflect the stacked frame */
3987 env->gpr[1] = (unsigned long)frame;
3988
3989 return;
3990
3991give_sigsegv:
3992 unlock_user_struct(frame, frame_addr, 1);
3993 if (sig == TARGET_SIGSEGV) {
3994 ka->_sa_handler = TARGET_SIG_DFL;
3995 }
3996 force_sig(TARGET_SIGSEGV);
3997}
3998
3999long do_sigreturn(CPUOpenRISCState *env)
4000{
4001
4002 qemu_log("do_sigreturn: not implemented\n");
4003 return -TARGET_ENOSYS;
4004}
4005
4006long do_rt_sigreturn(CPUOpenRISCState *env)
4007{
4008 qemu_log("do_rt_sigreturn: not implemented\n");
4009 return -TARGET_ENOSYS;
4010}
4011/* TARGET_OPENRISC */
4012
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004013#elif defined(TARGET_S390X)
4014
4015#define __NUM_GPRS 16
4016#define __NUM_FPRS 16
4017#define __NUM_ACRS 16
4018
4019#define S390_SYSCALL_SIZE 2
4020#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4021
4022#define _SIGCONTEXT_NSIG 64
4023#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4024#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4025#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4026#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4027#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4028
4029typedef struct {
4030 target_psw_t psw;
4031 target_ulong gprs[__NUM_GPRS];
4032 unsigned int acrs[__NUM_ACRS];
4033} target_s390_regs_common;
4034
4035typedef struct {
4036 unsigned int fpc;
4037 double fprs[__NUM_FPRS];
4038} target_s390_fp_regs;
4039
4040typedef struct {
4041 target_s390_regs_common regs;
4042 target_s390_fp_regs fpregs;
4043} target_sigregs;
4044
4045struct target_sigcontext {
4046 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4047 target_sigregs *sregs;
4048};
4049
4050typedef struct {
4051 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4052 struct target_sigcontext sc;
4053 target_sigregs sregs;
4054 int signo;
4055 uint8_t retcode[S390_SYSCALL_SIZE];
4056} sigframe;
4057
4058struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004059 target_ulong tuc_flags;
4060 struct target_ucontext *tuc_link;
4061 target_stack_t tuc_stack;
4062 target_sigregs tuc_mcontext;
4063 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004064};
4065
4066typedef struct {
4067 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4068 uint8_t retcode[S390_SYSCALL_SIZE];
4069 struct target_siginfo info;
4070 struct target_ucontext uc;
4071} rt_sigframe;
4072
4073static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004074get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004075{
4076 abi_ulong sp;
4077
4078 /* Default to using normal stack */
4079 sp = env->regs[15];
4080
4081 /* This is the X/Open sanctioned signal stack switching. */
4082 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4083 if (!sas_ss_flags(sp)) {
4084 sp = target_sigaltstack_used.ss_sp +
4085 target_sigaltstack_used.ss_size;
4086 }
4087 }
4088
4089 /* This is the legacy signal stack switching. */
4090 else if (/* FIXME !user_mode(regs) */ 0 &&
4091 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4092 ka->sa_restorer) {
4093 sp = (abi_ulong) ka->sa_restorer;
4094 }
4095
4096 return (sp - frame_size) & -8ul;
4097}
4098
Andreas Färber05390242012-02-25 03:37:53 +01004099static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004100{
4101 int i;
4102 //save_access_regs(current->thread.acrs); FIXME
4103
4104 /* Copy a 'clean' PSW mask to the user to avoid leaking
4105 information about whether PER is currently on. */
4106 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4107 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4108 for (i = 0; i < 16; i++) {
4109 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4110 }
4111 for (i = 0; i < 16; i++) {
4112 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4113 }
4114 /*
4115 * We have to store the fp registers to current->thread.fp_regs
4116 * to merge them with the emulated registers.
4117 */
4118 //save_fp_regs(&current->thread.fp_regs); FIXME
4119 for (i = 0; i < 16; i++) {
4120 __put_user(env->fregs[i].ll, &sregs->fpregs.fprs[i]);
4121 }
4122}
4123
4124static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004125 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004126{
4127 sigframe *frame;
4128 abi_ulong frame_addr;
4129
4130 frame_addr = get_sigframe(ka, env, sizeof(*frame));
4131 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4132 (unsigned long long)frame_addr);
4133 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4134 goto give_sigsegv;
4135 }
4136
4137 qemu_log("%s: 1\n", __FUNCTION__);
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) {
4148 env->regs[14] = (unsigned long)
4149 ka->sa_restorer | PSW_ADDR_AMODE;
4150 } else {
4151 env->regs[14] = (unsigned long)
4152 frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004153 __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:
4178 qemu_log("%s: give_sigsegv\n", __FUNCTION__);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004179 force_sig(TARGET_SIGSEGV);
4180}
4181
4182static void setup_rt_frame(int sig, struct target_sigaction *ka,
4183 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004184 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004185{
4186 int i;
4187 rt_sigframe *frame;
4188 abi_ulong frame_addr;
4189
4190 frame_addr = get_sigframe(ka, env, sizeof *frame);
4191 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4192 (unsigned long long)frame_addr);
4193 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4194 goto give_sigsegv;
4195 }
4196
4197 qemu_log("%s: 1\n", __FUNCTION__);
Riku Voipiob0fd8d12014-04-23 10:46:13 +03004198 copy_siginfo_to_user(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004199
4200 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004201 __put_user(0, &frame->uc.tuc_flags);
4202 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4203 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004204 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004205 &frame->uc.tuc_stack.ss_flags);
4206 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4207 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004208 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4209 __put_user((abi_ulong)set->sig[i],
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004210 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004211 }
4212
4213 /* Set up to return from userspace. If provided, use a stub
4214 already in userspace. */
4215 if (ka->sa_flags & TARGET_SA_RESTORER) {
4216 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4217 } else {
4218 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004219 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4220 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004221 }
4222
4223 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004224 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004225
4226 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004227 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004228 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4229
4230 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004231 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4232 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004233 return;
4234
4235give_sigsegv:
4236 qemu_log("%s: give_sigsegv\n", __FUNCTION__);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004237 force_sig(TARGET_SIGSEGV);
4238}
4239
4240static int
Andreas Färber05390242012-02-25 03:37:53 +01004241restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004242{
4243 int err = 0;
4244 int i;
4245
4246 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004247 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004248 }
4249
Riku Voipio1d8b5122014-04-23 10:26:05 +03004250 __get_user(env->psw.mask, &sc->regs.psw.mask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004251 qemu_log("%s: sc->regs.psw.addr 0x%llx env->psw.addr 0x%llx\n",
4252 __FUNCTION__, (unsigned long long)sc->regs.psw.addr,
4253 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004254 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004255 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4256
4257 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004258 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004259 }
4260 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004261 __get_user(env->fregs[i].ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004262 }
4263
4264 return err;
4265}
4266
Andreas Färber05390242012-02-25 03:37:53 +01004267long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004268{
4269 sigframe *frame;
4270 abi_ulong frame_addr = env->regs[15];
4271 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4272 (unsigned long long)frame_addr);
4273 target_sigset_t target_set;
4274 sigset_t set;
4275
4276 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4277 goto badframe;
4278 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004279 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004280
4281 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004282 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004283
4284 if (restore_sigregs(env, &frame->sregs)) {
4285 goto badframe;
4286 }
4287
4288 unlock_user_struct(frame, frame_addr, 0);
4289 return env->regs[2];
4290
4291badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004292 force_sig(TARGET_SIGSEGV);
4293 return 0;
4294}
4295
Andreas Färber05390242012-02-25 03:37:53 +01004296long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004297{
4298 rt_sigframe *frame;
4299 abi_ulong frame_addr = env->regs[15];
4300 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4301 (unsigned long long)frame_addr);
4302 sigset_t set;
4303
4304 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4305 goto badframe;
4306 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004307 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004308
Alex Barcelo1c275922014-03-14 14:36:55 +00004309 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004310
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004311 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004312 goto badframe;
4313 }
4314
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004315 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004316 get_sp_from_cpustate(env)) == -EFAULT) {
4317 goto badframe;
4318 }
4319 unlock_user_struct(frame, frame_addr, 0);
4320 return env->regs[2];
4321
4322badframe:
4323 unlock_user_struct(frame, frame_addr, 0);
4324 force_sig(TARGET_SIGSEGV);
4325 return 0;
4326}
4327
Nathan Froydbcd49332009-05-12 19:13:18 -07004328#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
4329
4330/* FIXME: Many of the structures are defined for both PPC and PPC64, but
4331 the signal handling is different enough that we haven't implemented
4332 support for PPC64 yet. Hence the restriction above.
4333
4334 There are various #if'd blocks for code for TARGET_PPC64. These
4335 blocks should go away so that we can successfully run 32-bit and
4336 64-bit binaries on a QEMU configured for PPC64. */
4337
4338/* Size of dummy stack frame allocated when calling signal handler.
4339 See arch/powerpc/include/asm/ptrace.h. */
4340#if defined(TARGET_PPC64)
4341#define SIGNAL_FRAMESIZE 128
4342#else
4343#define SIGNAL_FRAMESIZE 64
4344#endif
4345
4346/* See arch/powerpc/include/asm/sigcontext.h. */
4347struct target_sigcontext {
4348 target_ulong _unused[4];
4349 int32_t signal;
4350#if defined(TARGET_PPC64)
4351 int32_t pad0;
4352#endif
4353 target_ulong handler;
4354 target_ulong oldmask;
4355 target_ulong regs; /* struct pt_regs __user * */
4356 /* TODO: PPC64 includes extra bits here. */
4357};
4358
4359/* Indices for target_mcontext.mc_gregs, below.
4360 See arch/powerpc/include/asm/ptrace.h for details. */
4361enum {
4362 TARGET_PT_R0 = 0,
4363 TARGET_PT_R1 = 1,
4364 TARGET_PT_R2 = 2,
4365 TARGET_PT_R3 = 3,
4366 TARGET_PT_R4 = 4,
4367 TARGET_PT_R5 = 5,
4368 TARGET_PT_R6 = 6,
4369 TARGET_PT_R7 = 7,
4370 TARGET_PT_R8 = 8,
4371 TARGET_PT_R9 = 9,
4372 TARGET_PT_R10 = 10,
4373 TARGET_PT_R11 = 11,
4374 TARGET_PT_R12 = 12,
4375 TARGET_PT_R13 = 13,
4376 TARGET_PT_R14 = 14,
4377 TARGET_PT_R15 = 15,
4378 TARGET_PT_R16 = 16,
4379 TARGET_PT_R17 = 17,
4380 TARGET_PT_R18 = 18,
4381 TARGET_PT_R19 = 19,
4382 TARGET_PT_R20 = 20,
4383 TARGET_PT_R21 = 21,
4384 TARGET_PT_R22 = 22,
4385 TARGET_PT_R23 = 23,
4386 TARGET_PT_R24 = 24,
4387 TARGET_PT_R25 = 25,
4388 TARGET_PT_R26 = 26,
4389 TARGET_PT_R27 = 27,
4390 TARGET_PT_R28 = 28,
4391 TARGET_PT_R29 = 29,
4392 TARGET_PT_R30 = 30,
4393 TARGET_PT_R31 = 31,
4394 TARGET_PT_NIP = 32,
4395 TARGET_PT_MSR = 33,
4396 TARGET_PT_ORIG_R3 = 34,
4397 TARGET_PT_CTR = 35,
4398 TARGET_PT_LNK = 36,
4399 TARGET_PT_XER = 37,
4400 TARGET_PT_CCR = 38,
4401 /* Yes, there are two registers with #39. One is 64-bit only. */
4402 TARGET_PT_MQ = 39,
4403 TARGET_PT_SOFTE = 39,
4404 TARGET_PT_TRAP = 40,
4405 TARGET_PT_DAR = 41,
4406 TARGET_PT_DSISR = 42,
4407 TARGET_PT_RESULT = 43,
4408 TARGET_PT_REGS_COUNT = 44
4409};
4410
4411/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4412 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4413struct target_mcontext {
4414 target_ulong mc_gregs[48];
4415 /* Includes fpscr. */
4416 uint64_t mc_fregs[33];
4417 target_ulong mc_pad[2];
4418 /* We need to handle Altivec and SPE at the same time, which no
4419 kernel needs to do. Fortunately, the kernel defines this bit to
4420 be Altivec-register-large all the time, rather than trying to
4421 twiddle it based on the specific platform. */
4422 union {
4423 /* SPE vector registers. One extra for SPEFSCR. */
4424 uint32_t spe[33];
4425 /* Altivec vector registers. The packing of VSCR and VRSAVE
4426 varies depending on whether we're PPC64 or not: PPC64 splits
4427 them apart; PPC32 stuffs them together. */
4428#if defined(TARGET_PPC64)
malc3efa9a62009-07-18 13:10:12 +04004429#define QEMU_NVRREG 34
Nathan Froydbcd49332009-05-12 19:13:18 -07004430#else
malc3efa9a62009-07-18 13:10:12 +04004431#define QEMU_NVRREG 33
Nathan Froydbcd49332009-05-12 19:13:18 -07004432#endif
Anthony Liguoric227f092009-10-01 16:12:16 -05004433 ppc_avr_t altivec[QEMU_NVRREG];
malc3efa9a62009-07-18 13:10:12 +04004434#undef QEMU_NVRREG
Nathan Froydbcd49332009-05-12 19:13:18 -07004435 } mc_vregs __attribute__((__aligned__(16)));
4436};
4437
4438struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004439 target_ulong tuc_flags;
4440 target_ulong tuc_link; /* struct ucontext __user * */
4441 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07004442#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02004443 int32_t tuc_pad[7];
4444 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07004445 points to uc_mcontext field */
4446#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02004447 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07004448#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05004449 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Aurelien Jarno60e99242010-03-29 02:12:51 +02004450 struct target_sigcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004451#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02004452 int32_t tuc_maskext[30];
4453 int32_t tuc_pad2[3];
4454 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004455#endif
4456};
4457
4458/* See arch/powerpc/kernel/signal_32.c. */
4459struct target_sigframe {
4460 struct target_sigcontext sctx;
4461 struct target_mcontext mctx;
4462 int32_t abigap[56];
4463};
4464
4465struct target_rt_sigframe {
4466 struct target_siginfo info;
4467 struct target_ucontext uc;
4468 int32_t abigap[56];
4469};
4470
4471/* We use the mc_pad field for the signal return trampoline. */
4472#define tramp mc_pad
4473
4474/* See arch/powerpc/kernel/signal.c. */
4475static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004476 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07004477 int frame_size)
4478{
4479 target_ulong oldsp, newsp;
4480
4481 oldsp = env->gpr[1];
4482
4483 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Alex Barcelo32a20032012-02-09 23:55:46 +00004484 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07004485 oldsp = (target_sigaltstack_used.ss_sp
4486 + target_sigaltstack_used.ss_size);
4487 }
4488
4489 newsp = (oldsp - frame_size) & ~0xFUL;
4490
4491 return newsp;
4492}
4493
Riku Voipioc650c002014-04-23 13:53:45 +03004494static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame,
Nathan Froydbcd49332009-05-12 19:13:18 -07004495 int sigret)
4496{
4497 target_ulong msr = env->msr;
4498 int i;
4499 target_ulong ccr = 0;
4500
4501 /* In general, the kernel attempts to be intelligent about what it
4502 needs to save for Altivec/FP/SPE registers. We don't care that
4503 much, so we just go ahead and save everything. */
4504
4505 /* Save general registers. */
4506 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004507 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004508 }
Riku Voipioc650c002014-04-23 13:53:45 +03004509 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4510 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4511 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4512 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004513
4514 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4515 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4516 }
Riku Voipioc650c002014-04-23 13:53:45 +03004517 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004518
4519 /* Save Altivec registers if necessary. */
4520 if (env->insns_flags & PPC_ALTIVEC) {
4521 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004522 ppc_avr_t *avr = &env->avr[i];
4523 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004524
Riku Voipioc650c002014-04-23 13:53:45 +03004525 __put_user(avr->u64[0], &vreg->u64[0]);
4526 __put_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004527 }
4528 /* Set MSR_VR in the saved MSR value to indicate that
4529 frame->mc_vregs contains valid data. */
4530 msr |= MSR_VR;
Riku Voipioc650c002014-04-23 13:53:45 +03004531 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4532 &frame->mc_vregs.altivec[32].u32[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004533 }
4534
4535 /* Save floating point registers. */
4536 if (env->insns_flags & PPC_FLOAT) {
4537 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004538 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004539 }
Riku Voipioc650c002014-04-23 13:53:45 +03004540 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004541 }
4542
4543 /* Save SPE registers. The kernel only saves the high half. */
4544 if (env->insns_flags & PPC_SPE) {
4545#if defined(TARGET_PPC64)
4546 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004547 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004548 }
4549#else
4550 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004551 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004552 }
4553#endif
4554 /* Set MSR_SPE in the saved MSR value to indicate that
4555 frame->mc_vregs contains valid data. */
4556 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03004557 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004558 }
4559
4560 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004561 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004562
4563 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4564 if (sigret) {
Riku Voipioc650c002014-04-23 13:53:45 +03004565 __put_user(0x38000000UL | sigret, &frame->tramp[0]);
4566 __put_user(0x44000002UL, &frame->tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004567 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004568}
4569
Riku Voipioc650c002014-04-23 13:53:45 +03004570static void restore_user_regs(CPUPPCState *env,
4571 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004572{
4573 target_ulong save_r2 = 0;
4574 target_ulong msr;
4575 target_ulong ccr;
4576
4577 int i;
4578
4579 if (!sig) {
4580 save_r2 = env->gpr[2];
4581 }
4582
4583 /* Restore general registers. */
4584 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004585 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004586 }
Riku Voipioc650c002014-04-23 13:53:45 +03004587 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4588 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4589 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4590 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4591 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004592
4593 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4594 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4595 }
4596
4597 if (!sig) {
4598 env->gpr[2] = save_r2;
4599 }
4600 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004601 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004602
4603 /* If doing signal return, restore the previous little-endian mode. */
4604 if (sig)
4605 env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
4606
4607 /* Restore Altivec registers if necessary. */
4608 if (env->insns_flags & PPC_ALTIVEC) {
4609 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004610 ppc_avr_t *avr = &env->avr[i];
4611 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004612
Riku Voipioc650c002014-04-23 13:53:45 +03004613 __get_user(avr->u64[0], &vreg->u64[0]);
4614 __get_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004615 }
4616 /* Set MSR_VEC in the saved MSR value to indicate that
4617 frame->mc_vregs contains valid data. */
Riku Voipioc650c002014-04-23 13:53:45 +03004618 __get_user(env->spr[SPR_VRSAVE],
4619 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
Nathan Froydbcd49332009-05-12 19:13:18 -07004620 }
4621
4622 /* Restore floating point registers. */
4623 if (env->insns_flags & PPC_FLOAT) {
4624 uint64_t fpscr;
4625 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004626 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004627 }
Riku Voipioc650c002014-04-23 13:53:45 +03004628 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004629 env->fpscr = (uint32_t) fpscr;
4630 }
4631
4632 /* Save SPE registers. The kernel only saves the high half. */
4633 if (env->insns_flags & PPC_SPE) {
4634#if defined(TARGET_PPC64)
4635 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4636 uint32_t hi;
4637
Riku Voipioc650c002014-04-23 13:53:45 +03004638 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004639 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4640 }
4641#else
4642 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004643 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004644 }
4645#endif
Riku Voipioc650c002014-04-23 13:53:45 +03004646 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004647 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004648}
4649
4650static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004651 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004652{
4653 struct target_sigframe *frame;
4654 struct target_sigcontext *sc;
4655 target_ulong frame_addr, newsp;
4656 int err = 0;
4657 int signal;
4658
4659 frame_addr = get_sigframe(ka, env, sizeof(*frame));
4660 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4661 goto sigsegv;
4662 sc = &frame->sctx;
4663
4664 signal = current_exec_domain_sig(sig);
4665
Riku Voipio1d8b5122014-04-23 10:26:05 +03004666 __put_user(ka->_sa_handler, &sc->handler);
4667 __put_user(set->sig[0], &sc->oldmask);
Nathan Froydbcd49332009-05-12 19:13:18 -07004668#if defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03004669 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004670#else
Riku Voipio1d8b5122014-04-23 10:26:05 +03004671 __put_user(set->sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004672#endif
Riku Voipio1d8b5122014-04-23 10:26:05 +03004673 __put_user(h2g(&frame->mctx), &sc->regs);
4674 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07004675
4676 /* Save user regs. */
Riku Voipioc650c002014-04-23 13:53:45 +03004677 save_user_regs(env, &frame->mctx, TARGET_NR_sigreturn);
Nathan Froydbcd49332009-05-12 19:13:18 -07004678
4679 /* The kernel checks for the presence of a VDSO here. We don't
4680 emulate a vdso, so use a sigreturn system call. */
4681 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4682
4683 /* Turn off all fp exceptions. */
4684 env->fpscr = 0;
4685
4686 /* Create a stack frame for the caller of the handler. */
4687 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00004688 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004689
4690 if (err)
4691 goto sigsegv;
4692
4693 /* Set up registers for signal handler. */
4694 env->gpr[1] = newsp;
4695 env->gpr[3] = signal;
Samuel Seay61993a62013-01-04 14:35:48 +00004696 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Nathan Froydbcd49332009-05-12 19:13:18 -07004697 env->nip = (target_ulong) ka->_sa_handler;
4698 /* Signal handlers are entered in big-endian mode. */
4699 env->msr &= ~MSR_LE;
4700
4701 unlock_user_struct(frame, frame_addr, 1);
4702 return;
4703
4704sigsegv:
4705 unlock_user_struct(frame, frame_addr, 1);
Blue Swirleeacee42012-06-03 16:35:32 +00004706 qemu_log("segfaulting from setup_frame\n");
Riku Voipio66393fb2009-12-04 15:16:32 +02004707 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004708}
4709
4710static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004711 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004712 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004713{
4714 struct target_rt_sigframe *rt_sf;
4715 struct target_mcontext *frame;
4716 target_ulong rt_sf_addr, newsp = 0;
4717 int i, err = 0;
4718 int signal;
4719
4720 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4721 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4722 goto sigsegv;
4723
4724 signal = current_exec_domain_sig(sig);
4725
Riku Voipiob0fd8d12014-04-23 10:46:13 +03004726 copy_siginfo_to_user(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07004727
Riku Voipio1d8b5122014-04-23 10:26:05 +03004728 __put_user(0, &rt_sf->uc.tuc_flags);
4729 __put_user(0, &rt_sf->uc.tuc_link);
4730 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4731 &rt_sf->uc.tuc_stack.ss_sp);
4732 __put_user(sas_ss_flags(env->gpr[1]),
4733 &rt_sf->uc.tuc_stack.ss_flags);
4734 __put_user(target_sigaltstack_used.ss_size,
4735 &rt_sf->uc.tuc_stack.ss_size);
4736 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4737 &rt_sf->uc.tuc_regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004738 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004739 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004740 }
4741
Aurelien Jarno60e99242010-03-29 02:12:51 +02004742 frame = &rt_sf->uc.tuc_mcontext;
Riku Voipioc650c002014-04-23 13:53:45 +03004743 save_user_regs(env, frame, TARGET_NR_rt_sigreturn);
Nathan Froydbcd49332009-05-12 19:13:18 -07004744
4745 /* The kernel checks for the presence of a VDSO here. We don't
4746 emulate a vdso, so use a sigreturn system call. */
4747 env->lr = (target_ulong) h2g(frame->tramp);
4748
4749 /* Turn off all fp exceptions. */
4750 env->fpscr = 0;
4751
4752 /* Create a stack frame for the caller of the handler. */
4753 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05004754 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004755
4756 if (err)
4757 goto sigsegv;
4758
4759 /* Set up registers for signal handler. */
4760 env->gpr[1] = newsp;
4761 env->gpr[3] = (target_ulong) signal;
4762 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4763 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4764 env->gpr[6] = (target_ulong) h2g(rt_sf);
4765 env->nip = (target_ulong) ka->_sa_handler;
4766 /* Signal handlers are entered in big-endian mode. */
4767 env->msr &= ~MSR_LE;
4768
4769 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4770 return;
4771
4772sigsegv:
4773 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Blue Swirleeacee42012-06-03 16:35:32 +00004774 qemu_log("segfaulting from setup_rt_frame\n");
Riku Voipio66393fb2009-12-04 15:16:32 +02004775 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004776
4777}
4778
Andreas Färber05390242012-02-25 03:37:53 +01004779long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004780{
4781 struct target_sigcontext *sc = NULL;
4782 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01004783 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07004784 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004785 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004786
4787 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4788 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4789 goto sigsegv;
4790
4791#if defined(TARGET_PPC64)
4792 set.sig[0] = sc->oldmask + ((long)(sc->_unused[3]) << 32);
4793#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03004794 __get_user(set.sig[0], &sc->oldmask);
4795 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004796#endif
4797 target_to_host_sigset_internal(&blocked, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004798 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
Nathan Froydbcd49332009-05-12 19:13:18 -07004799
Riku Voipiof5f601a2014-04-23 13:00:17 +03004800 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004801 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4802 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03004803 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07004804
4805 unlock_user_struct(sr, sr_addr, 1);
4806 unlock_user_struct(sc, sc_addr, 1);
4807 return -TARGET_QEMU_ESIGRETURN;
4808
4809sigsegv:
4810 unlock_user_struct(sr, sr_addr, 1);
4811 unlock_user_struct(sc, sc_addr, 1);
Blue Swirleeacee42012-06-03 16:35:32 +00004812 qemu_log("segfaulting from do_sigreturn\n");
Riku Voipio66393fb2009-12-04 15:16:32 +02004813 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004814 return 0;
4815}
4816
4817/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01004818static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004819{
4820 struct target_mcontext *mcp;
4821 target_ulong mcp_addr;
4822 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004823 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004824
Aurelien Jarno60e99242010-03-29 02:12:51 +02004825 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07004826 sizeof (set)))
4827 return 1;
4828
4829#if defined(TARGET_PPC64)
4830 fprintf (stderr, "do_setcontext: not implemented\n");
4831 return 0;
4832#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03004833 __get_user(mcp_addr, &ucp->tuc_regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004834
4835 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4836 return 1;
4837
4838 target_to_host_sigset_internal(&blocked, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004839 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
Riku Voipioc650c002014-04-23 13:53:45 +03004840 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07004841
4842 unlock_user_struct(mcp, mcp_addr, 1);
4843 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004844#endif
4845}
4846
Andreas Färber05390242012-02-25 03:37:53 +01004847long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004848{
4849 struct target_rt_sigframe *rt_sf = NULL;
4850 target_ulong rt_sf_addr;
4851
4852 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4853 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4854 goto sigsegv;
4855
4856 if (do_setcontext(&rt_sf->uc, env, 1))
4857 goto sigsegv;
4858
4859 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02004860 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07004861 0, env->gpr[1]);
4862
4863 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4864 return -TARGET_QEMU_ESIGRETURN;
4865
4866sigsegv:
4867 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Blue Swirleeacee42012-06-03 16:35:32 +00004868 qemu_log("segfaulting from do_rt_sigreturn\n");
Riku Voipio66393fb2009-12-04 15:16:32 +02004869 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004870 return 0;
4871}
4872
Laurent Vivier492a8742009-08-03 16:12:17 +02004873#elif defined(TARGET_M68K)
4874
4875struct target_sigcontext {
4876 abi_ulong sc_mask;
4877 abi_ulong sc_usp;
4878 abi_ulong sc_d0;
4879 abi_ulong sc_d1;
4880 abi_ulong sc_a0;
4881 abi_ulong sc_a1;
4882 unsigned short sc_sr;
4883 abi_ulong sc_pc;
4884};
4885
4886struct target_sigframe
4887{
4888 abi_ulong pretcode;
4889 int sig;
4890 int code;
4891 abi_ulong psc;
4892 char retcode[8];
4893 abi_ulong extramask[TARGET_NSIG_WORDS-1];
4894 struct target_sigcontext sc;
4895};
Laurent Vivier71811552009-08-03 16:12:18 +02004896
Anthony Liguoric227f092009-10-01 16:12:16 -05004897typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004898#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05004899typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02004900
4901typedef struct target_fpregset {
4902 int f_fpcntl[3];
4903 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05004904} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004905
4906struct target_mcontext {
4907 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05004908 target_gregset_t gregs;
4909 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02004910};
4911
4912#define TARGET_MCONTEXT_VERSION 2
4913
4914struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004915 abi_ulong tuc_flags;
4916 abi_ulong tuc_link;
4917 target_stack_t tuc_stack;
4918 struct target_mcontext tuc_mcontext;
4919 abi_long tuc_filler[80];
4920 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02004921};
4922
4923struct target_rt_sigframe
4924{
4925 abi_ulong pretcode;
4926 int sig;
4927 abi_ulong pinfo;
4928 abi_ulong puc;
4929 char retcode[8];
4930 struct target_siginfo info;
4931 struct target_ucontext uc;
4932};
Laurent Vivier492a8742009-08-03 16:12:17 +02004933
Riku Voipio41ecc722014-04-23 11:01:00 +03004934static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
4935 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02004936{
Riku Voipio1d8b5122014-04-23 10:26:05 +03004937 __put_user(mask, &sc->sc_mask);
4938 __put_user(env->aregs[7], &sc->sc_usp);
4939 __put_user(env->dregs[0], &sc->sc_d0);
4940 __put_user(env->dregs[1], &sc->sc_d1);
4941 __put_user(env->aregs[0], &sc->sc_a0);
4942 __put_user(env->aregs[1], &sc->sc_a1);
4943 __put_user(env->sr, &sc->sc_sr);
4944 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02004945}
4946
Riku Voipio016d2e12014-04-23 11:19:48 +03004947static void
Andreas Färber05390242012-02-25 03:37:53 +01004948restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0)
Laurent Vivier492a8742009-08-03 16:12:17 +02004949{
Laurent Vivier492a8742009-08-03 16:12:17 +02004950 int temp;
4951
Riku Voipio1d8b5122014-04-23 10:26:05 +03004952 __get_user(env->aregs[7], &sc->sc_usp);
4953 __get_user(env->dregs[1], &sc->sc_d1);
4954 __get_user(env->aregs[0], &sc->sc_a0);
4955 __get_user(env->aregs[1], &sc->sc_a1);
4956 __get_user(env->pc, &sc->sc_pc);
4957 __get_user(temp, &sc->sc_sr);
Laurent Vivier492a8742009-08-03 16:12:17 +02004958 env->sr = (env->sr & 0xff00) | (temp & 0xff);
4959
4960 *pd0 = tswapl(sc->sc_d0);
Laurent Vivier492a8742009-08-03 16:12:17 +02004961}
4962
4963/*
4964 * Determine which stack to use..
4965 */
4966static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004967get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
4968 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02004969{
4970 unsigned long sp;
4971
4972 sp = regs->aregs[7];
4973
4974 /* This is the X/Open sanctioned signal stack switching. */
4975 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
4976 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4977 }
4978
4979 return ((sp - frame_size) & -8UL);
4980}
4981
4982static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004983 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02004984{
4985 struct target_sigframe *frame;
4986 abi_ulong frame_addr;
4987 abi_ulong retcode_addr;
4988 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02004989 int i;
4990
4991 frame_addr = get_sigframe(ka, env, sizeof *frame);
4992 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4993 goto give_sigsegv;
4994
Riku Voipio1d8b5122014-04-23 10:26:05 +03004995 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02004996
4997 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004998 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02004999
Riku Voipio41ecc722014-04-23 11:01:00 +03005000 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005001
5002 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005003 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005004 }
5005
5006 /* Set up to return from userspace. */
5007
5008 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005009 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005010
5011 /* moveq #,d0; trap #0 */
5012
Riku Voipio1d8b5122014-04-23 10:26:05 +03005013 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Laurent Vivier492a8742009-08-03 16:12:17 +02005014 (long *)(frame->retcode));
5015
Laurent Vivier492a8742009-08-03 16:12:17 +02005016 /* Set up to return from userspace */
5017
5018 env->aregs[7] = frame_addr;
5019 env->pc = ka->_sa_handler;
5020
5021 unlock_user_struct(frame, frame_addr, 1);
5022 return;
5023
5024give_sigsegv:
Riku Voipio66393fb2009-12-04 15:16:32 +02005025 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005026}
5027
Laurent Vivier71811552009-08-03 16:12:18 +02005028static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005029 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005030{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005031 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005032
Riku Voipio1d8b5122014-04-23 10:26:05 +03005033 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5034 __put_user(env->dregs[0], &gregs[0]);
5035 __put_user(env->dregs[1], &gregs[1]);
5036 __put_user(env->dregs[2], &gregs[2]);
5037 __put_user(env->dregs[3], &gregs[3]);
5038 __put_user(env->dregs[4], &gregs[4]);
5039 __put_user(env->dregs[5], &gregs[5]);
5040 __put_user(env->dregs[6], &gregs[6]);
5041 __put_user(env->dregs[7], &gregs[7]);
5042 __put_user(env->aregs[0], &gregs[8]);
5043 __put_user(env->aregs[1], &gregs[9]);
5044 __put_user(env->aregs[2], &gregs[10]);
5045 __put_user(env->aregs[3], &gregs[11]);
5046 __put_user(env->aregs[4], &gregs[12]);
5047 __put_user(env->aregs[5], &gregs[13]);
5048 __put_user(env->aregs[6], &gregs[14]);
5049 __put_user(env->aregs[7], &gregs[15]);
5050 __put_user(env->pc, &gregs[16]);
5051 __put_user(env->sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005052
Riku Voipio1d8b5122014-04-23 10:26:05 +03005053 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005054}
5055
Andreas Färber05390242012-02-25 03:37:53 +01005056static inline int target_rt_restore_ucontext(CPUM68KState *env,
Laurent Vivier71811552009-08-03 16:12:18 +02005057 struct target_ucontext *uc,
5058 int *pd0)
5059{
5060 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005061 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005062
Riku Voipio1d8b5122014-04-23 10:26:05 +03005063 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005064 if (temp != TARGET_MCONTEXT_VERSION)
5065 goto badframe;
5066
5067 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005068 __get_user(env->dregs[0], &gregs[0]);
5069 __get_user(env->dregs[1], &gregs[1]);
5070 __get_user(env->dregs[2], &gregs[2]);
5071 __get_user(env->dregs[3], &gregs[3]);
5072 __get_user(env->dregs[4], &gregs[4]);
5073 __get_user(env->dregs[5], &gregs[5]);
5074 __get_user(env->dregs[6], &gregs[6]);
5075 __get_user(env->dregs[7], &gregs[7]);
5076 __get_user(env->aregs[0], &gregs[8]);
5077 __get_user(env->aregs[1], &gregs[9]);
5078 __get_user(env->aregs[2], &gregs[10]);
5079 __get_user(env->aregs[3], &gregs[11]);
5080 __get_user(env->aregs[4], &gregs[12]);
5081 __get_user(env->aregs[5], &gregs[13]);
5082 __get_user(env->aregs[6], &gregs[14]);
5083 __get_user(env->aregs[7], &gregs[15]);
5084 __get_user(env->pc, &gregs[16]);
5085 __get_user(temp, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005086 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5087
5088 *pd0 = env->dregs[0];
Riku Voipio1d8b5122014-04-23 10:26:05 +03005089 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005090
5091badframe:
5092 return 1;
5093}
5094
Laurent Vivier492a8742009-08-03 16:12:17 +02005095static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005096 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005097 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005098{
Laurent Vivier71811552009-08-03 16:12:18 +02005099 struct target_rt_sigframe *frame;
5100 abi_ulong frame_addr;
5101 abi_ulong retcode_addr;
5102 abi_ulong info_addr;
5103 abi_ulong uc_addr;
5104 int err = 0;
5105 int i;
5106
5107 frame_addr = get_sigframe(ka, env, sizeof *frame);
5108 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
5109 goto give_sigsegv;
5110
Riku Voipio1d8b5122014-04-23 10:26:05 +03005111 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005112
5113 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005114 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005115
5116 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005117 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005118
Riku Voipiob0fd8d12014-04-23 10:46:13 +03005119 copy_siginfo_to_user(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005120
5121 /* Create the ucontext */
5122
Riku Voipio1d8b5122014-04-23 10:26:05 +03005123 __put_user(0, &frame->uc.tuc_flags);
5124 __put_user(0, &frame->uc.tuc_link);
5125 __put_user(target_sigaltstack_used.ss_sp,
5126 &frame->uc.tuc_stack.ss_sp);
5127 __put_user(sas_ss_flags(env->aregs[7]),
5128 &frame->uc.tuc_stack.ss_flags);
5129 __put_user(target_sigaltstack_used.ss_size,
5130 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005131 err |= target_rt_setup_ucontext(&frame->uc, env);
5132
5133 if (err)
5134 goto give_sigsegv;
5135
5136 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005137 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005138 }
5139
5140 /* Set up to return from userspace. */
5141
5142 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005143 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005144
5145 /* moveq #,d0; notb d0; trap #0 */
5146
Riku Voipio1d8b5122014-04-23 10:26:05 +03005147 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
5148 (long *)(frame->retcode + 0));
5149 __put_user(0x4e40, (short *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005150
5151 if (err)
5152 goto give_sigsegv;
5153
5154 /* Set up to return from userspace */
5155
5156 env->aregs[7] = frame_addr;
5157 env->pc = ka->_sa_handler;
5158
5159 unlock_user_struct(frame, frame_addr, 1);
5160 return;
5161
5162give_sigsegv:
5163 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005164 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005165}
5166
Andreas Färber05390242012-02-25 03:37:53 +01005167long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005168{
5169 struct target_sigframe *frame;
5170 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005171 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005172 sigset_t set;
5173 int d0, i;
5174
5175 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5176 goto badframe;
5177
5178 /* set blocked signals */
5179
Riku Voipiof5f601a2014-04-23 13:00:17 +03005180 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005181
5182 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005183 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005184 }
5185
5186 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005187 do_sigprocmask(SIG_SETMASK, &set, NULL);
Laurent Vivier492a8742009-08-03 16:12:17 +02005188
5189 /* restore registers */
5190
Riku Voipio016d2e12014-04-23 11:19:48 +03005191 restore_sigcontext(env, &frame->sc, &d0);
Laurent Vivier492a8742009-08-03 16:12:17 +02005192
5193 unlock_user_struct(frame, frame_addr, 0);
5194 return d0;
5195
5196badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005197 force_sig(TARGET_SIGSEGV);
5198 return 0;
5199}
5200
Andreas Färber05390242012-02-25 03:37:53 +01005201long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005202{
Laurent Vivier71811552009-08-03 16:12:18 +02005203 struct target_rt_sigframe *frame;
5204 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005205 target_sigset_t target_set;
Laurent Vivier71811552009-08-03 16:12:18 +02005206 sigset_t set;
5207 int d0;
5208
5209 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5210 goto badframe;
5211
5212 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005213 do_sigprocmask(SIG_SETMASK, &set, NULL);
Laurent Vivier71811552009-08-03 16:12:18 +02005214
5215 /* restore registers */
5216
5217 if (target_rt_restore_ucontext(env, &frame->uc, &d0))
5218 goto badframe;
5219
5220 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02005221 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02005222 0, get_sp_from_cpustate(env)) == -EFAULT)
5223 goto badframe;
5224
5225 unlock_user_struct(frame, frame_addr, 0);
5226 return d0;
5227
5228badframe:
5229 unlock_user_struct(frame, frame_addr, 0);
5230 force_sig(TARGET_SIGSEGV);
5231 return 0;
Laurent Vivier492a8742009-08-03 16:12:17 +02005232}
5233
Richard Henderson6049f4f2009-12-27 18:30:03 -08005234#elif defined(TARGET_ALPHA)
5235
5236struct target_sigcontext {
5237 abi_long sc_onstack;
5238 abi_long sc_mask;
5239 abi_long sc_pc;
5240 abi_long sc_ps;
5241 abi_long sc_regs[32];
5242 abi_long sc_ownedfp;
5243 abi_long sc_fpregs[32];
5244 abi_ulong sc_fpcr;
5245 abi_ulong sc_fp_control;
5246 abi_ulong sc_reserved1;
5247 abi_ulong sc_reserved2;
5248 abi_ulong sc_ssize;
5249 abi_ulong sc_sbase;
5250 abi_ulong sc_traparg_a0;
5251 abi_ulong sc_traparg_a1;
5252 abi_ulong sc_traparg_a2;
5253 abi_ulong sc_fp_trap_pc;
5254 abi_ulong sc_fp_trigger_sum;
5255 abi_ulong sc_fp_trigger_inst;
5256};
5257
5258struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005259 abi_ulong tuc_flags;
5260 abi_ulong tuc_link;
5261 abi_ulong tuc_osf_sigmask;
5262 target_stack_t tuc_stack;
5263 struct target_sigcontext tuc_mcontext;
5264 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005265};
5266
5267struct target_sigframe {
5268 struct target_sigcontext sc;
5269 unsigned int retcode[3];
5270};
5271
5272struct target_rt_sigframe {
5273 target_siginfo_t info;
5274 struct target_ucontext uc;
5275 unsigned int retcode[3];
5276};
5277
5278#define INSN_MOV_R30_R16 0x47fe0410
5279#define INSN_LDI_R0 0x201f0000
5280#define INSN_CALLSYS 0x00000083
5281
Riku Voipio41ecc722014-04-23 11:01:00 +03005282static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Richard Henderson6049f4f2009-12-27 18:30:03 -08005283 abi_ulong frame_addr, target_sigset_t *set)
5284{
Riku Voipio41ecc722014-04-23 11:01:00 +03005285 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005286
Riku Voipio1d8b5122014-04-23 10:26:05 +03005287 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5288 __put_user(set->sig[0], &sc->sc_mask);
5289 __put_user(env->pc, &sc->sc_pc);
5290 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005291
5292 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005293 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005294 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005295 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005296
5297 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005298 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005299 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005300 __put_user(0, &sc->sc_fpregs[31]);
5301 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005302
Riku Voipio1d8b5122014-04-23 10:26:05 +03005303 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5304 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5305 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08005306}
5307
Riku Voipio016d2e12014-04-23 11:19:48 +03005308static void restore_sigcontext(CPUAlphaState *env,
Andreas Färber05390242012-02-25 03:37:53 +01005309 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005310{
5311 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03005312 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005313
Riku Voipio1d8b5122014-04-23 10:26:05 +03005314 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005315
5316 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005317 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005318 }
5319 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005320 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005321 }
5322
Riku Voipio1d8b5122014-04-23 10:26:05 +03005323 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005324 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005325}
5326
5327static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01005328 CPUAlphaState *env,
5329 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005330{
5331 abi_ulong sp = env->ir[IR_SP];
5332
5333 /* This is the X/Open sanctioned signal stack switching. */
5334 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5335 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5336 }
5337 return (sp - framesize) & -32;
5338}
5339
5340static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005341 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005342{
5343 abi_ulong frame_addr, r26;
5344 struct target_sigframe *frame;
5345 int err = 0;
5346
5347 frame_addr = get_sigframe(ka, env, sizeof(*frame));
5348 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5349 goto give_sigsegv;
5350 }
5351
Riku Voipio41ecc722014-04-23 11:01:00 +03005352 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005353
5354 if (ka->sa_restorer) {
5355 r26 = ka->sa_restorer;
5356 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005357 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5358 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5359 &frame->retcode[1]);
5360 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005361 /* imb() */
5362 r26 = frame_addr;
5363 }
5364
5365 unlock_user_struct(frame, frame_addr, 1);
5366
5367 if (err) {
5368 give_sigsegv:
5369 if (sig == TARGET_SIGSEGV) {
5370 ka->_sa_handler = TARGET_SIG_DFL;
5371 }
5372 force_sig(TARGET_SIGSEGV);
5373 }
5374
5375 env->ir[IR_RA] = r26;
5376 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5377 env->ir[IR_A0] = sig;
5378 env->ir[IR_A1] = 0;
5379 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5380 env->ir[IR_SP] = frame_addr;
5381}
5382
5383static void setup_rt_frame(int sig, struct target_sigaction *ka,
5384 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005385 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005386{
5387 abi_ulong frame_addr, r26;
5388 struct target_rt_sigframe *frame;
5389 int i, err = 0;
5390
5391 frame_addr = get_sigframe(ka, env, sizeof(*frame));
5392 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5393 goto give_sigsegv;
5394 }
5395
Riku Voipiob0fd8d12014-04-23 10:46:13 +03005396 copy_siginfo_to_user(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005397
Riku Voipio1d8b5122014-04-23 10:26:05 +03005398 __put_user(0, &frame->uc.tuc_flags);
5399 __put_user(0, &frame->uc.tuc_link);
5400 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5401 __put_user(target_sigaltstack_used.ss_sp,
5402 &frame->uc.tuc_stack.ss_sp);
5403 __put_user(sas_ss_flags(env->ir[IR_SP]),
5404 &frame->uc.tuc_stack.ss_flags);
5405 __put_user(target_sigaltstack_used.ss_size,
5406 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03005407 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005408 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005409 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005410 }
5411
5412 if (ka->sa_restorer) {
5413 r26 = ka->sa_restorer;
5414 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005415 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5416 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5417 &frame->retcode[1]);
5418 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005419 /* imb(); */
5420 r26 = frame_addr;
5421 }
5422
5423 if (err) {
5424 give_sigsegv:
5425 if (sig == TARGET_SIGSEGV) {
5426 ka->_sa_handler = TARGET_SIG_DFL;
5427 }
5428 force_sig(TARGET_SIGSEGV);
5429 }
5430
5431 env->ir[IR_RA] = r26;
5432 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5433 env->ir[IR_A0] = sig;
5434 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5435 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5436 env->ir[IR_SP] = frame_addr;
5437}
5438
Andreas Färber05390242012-02-25 03:37:53 +01005439long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005440{
5441 struct target_sigcontext *sc;
5442 abi_ulong sc_addr = env->ir[IR_A0];
5443 target_sigset_t target_set;
5444 sigset_t set;
5445
5446 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5447 goto badframe;
5448 }
5449
5450 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03005451 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005452
5453 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005454 do_sigprocmask(SIG_SETMASK, &set, NULL);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005455
Riku Voipio016d2e12014-04-23 11:19:48 +03005456 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005457 unlock_user_struct(sc, sc_addr, 0);
5458 return env->ir[IR_V0];
5459
5460 badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005461 force_sig(TARGET_SIGSEGV);
5462}
5463
Andreas Färber05390242012-02-25 03:37:53 +01005464long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005465{
5466 abi_ulong frame_addr = env->ir[IR_A0];
5467 struct target_rt_sigframe *frame;
5468 sigset_t set;
5469
5470 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5471 goto badframe;
5472 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02005473 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00005474 do_sigprocmask(SIG_SETMASK, &set, NULL);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005475
Riku Voipio016d2e12014-04-23 11:19:48 +03005476 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005477 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02005478 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08005479 0, env->ir[IR_SP]) == -EFAULT) {
5480 goto badframe;
5481 }
5482
5483 unlock_user_struct(frame, frame_addr, 0);
5484 return env->ir[IR_V0];
5485
5486
5487 badframe:
5488 unlock_user_struct(frame, frame_addr, 0);
5489 force_sig(TARGET_SIGSEGV);
5490}
5491
bellardb346ff42003-06-15 20:05:50 +00005492#else
5493
pbrook624f7972008-05-31 16:11:38 +00005494static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber9349b4f2012-03-14 01:38:32 +01005495 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005496{
5497 fprintf(stderr, "setup_frame: not implemented\n");
5498}
5499
pbrook624f7972008-05-31 16:11:38 +00005500static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005501 target_siginfo_t *info,
Andreas Färber9349b4f2012-03-14 01:38:32 +01005502 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005503{
5504 fprintf(stderr, "setup_rt_frame: not implemented\n");
5505}
5506
Andreas Färber9349b4f2012-03-14 01:38:32 +01005507long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005508{
5509 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005510 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005511}
5512
Andreas Färber9349b4f2012-03-14 01:38:32 +01005513long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005514{
5515 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005516 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005517}
5518
bellard66fb9762003-03-23 01:06:05 +00005519#endif
5520
Andreas Färber9349b4f2012-03-14 01:38:32 +01005521void process_pending_signals(CPUArchState *cpu_env)
bellard66fb9762003-03-23 01:06:05 +00005522{
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005523 CPUState *cpu = ENV_GET_CPU(cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005524 int sig;
blueswir1992f48a2007-10-14 16:27:31 +00005525 abi_ulong handler;
bellard9de5e442003-03-23 16:49:39 +00005526 sigset_t set, old_set;
Anthony Liguoric227f092009-10-01 16:12:16 -05005527 target_sigset_t target_old_set;
pbrook624f7972008-05-31 16:11:38 +00005528 struct emulated_sigtable *k;
5529 struct target_sigaction *sa;
bellard66fb9762003-03-23 01:06:05 +00005530 struct sigqueue *q;
Andreas Färber0429a972013-08-26 18:14:44 +02005531 TaskState *ts = cpu->opaque;
ths3b46e622007-09-17 08:09:54 +00005532
pbrook624f7972008-05-31 16:11:38 +00005533 if (!ts->signal_pending)
bellard31e31b82003-02-18 22:55:36 +00005534 return;
5535
pbrook624f7972008-05-31 16:11:38 +00005536 /* FIXME: This is not threadsafe. */
5537 k = ts->sigtab;
bellard66fb9762003-03-23 01:06:05 +00005538 for(sig = 1; sig <= TARGET_NSIG; sig++) {
5539 if (k->pending)
bellard31e31b82003-02-18 22:55:36 +00005540 goto handle_signal;
bellard66fb9762003-03-23 01:06:05 +00005541 k++;
bellard31e31b82003-02-18 22:55:36 +00005542 }
5543 /* if no signal is pending, just return */
pbrook624f7972008-05-31 16:11:38 +00005544 ts->signal_pending = 0;
bellard31e31b82003-02-18 22:55:36 +00005545 return;
bellard66fb9762003-03-23 01:06:05 +00005546
bellard31e31b82003-02-18 22:55:36 +00005547 handle_signal:
bellard66fb9762003-03-23 01:06:05 +00005548#ifdef DEBUG_SIGNAL
bellardbc8a22c2003-03-30 21:02:40 +00005549 fprintf(stderr, "qemu: process signal %d\n", sig);
bellard66fb9762003-03-23 01:06:05 +00005550#endif
5551 /* dequeue signal */
5552 q = k->first;
5553 k->first = q->next;
5554 if (!k->first)
5555 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00005556
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005557 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00005558 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00005559 sa = NULL;
5560 handler = TARGET_SIG_IGN;
5561 } else {
5562 sa = &sigact_table[sig - 1];
5563 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00005564 }
bellard66fb9762003-03-23 01:06:05 +00005565
Peter Maydella7ec0f92014-03-14 14:36:56 +00005566 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
5567 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
5568 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
5569 * because it got a real MMU fault), and treat as if default handler.
5570 */
5571 handler = TARGET_SIG_DFL;
5572 }
5573
bellard66fb9762003-03-23 01:06:05 +00005574 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00005575 /* default handler : ignore some signal. The other are job control or fatal */
5576 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5577 kill(getpid(),SIGSTOP);
5578 } else if (sig != TARGET_SIGCHLD &&
5579 sig != TARGET_SIGURG &&
5580 sig != TARGET_SIGWINCH &&
5581 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +00005582 force_sig(sig);
5583 }
5584 } else if (handler == TARGET_SIG_IGN) {
5585 /* ignore sig */
5586 } else if (handler == TARGET_SIG_ERR) {
5587 force_sig(sig);
5588 } else {
bellard9de5e442003-03-23 16:49:39 +00005589 /* compute the blocked signals during the handler execution */
pbrook624f7972008-05-31 16:11:38 +00005590 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00005591 /* SA_NODEFER indicates that the current signal should not be
5592 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00005593 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00005594 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00005595
bellard9de5e442003-03-23 16:49:39 +00005596 /* block signals in the handler using Linux */
Alex Barcelo1c275922014-03-14 14:36:55 +00005597 do_sigprocmask(SIG_BLOCK, &set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005598 /* save the previous blocked signal state to restore it at the
5599 end of the signal execution (see do_sigreturn) */
bellard92319442004-06-19 16:58:13 +00005600 host_to_target_sigset_internal(&target_old_set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005601
bellardbc8a22c2003-03-30 21:02:40 +00005602 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00005603#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00005604 {
5605 CPUX86State *env = cpu_env;
5606 if (env->eflags & VM_MASK)
5607 save_v86_state(env);
5608 }
5609#endif
bellard9de5e442003-03-23 16:49:39 +00005610 /* prepare the stack frame of the virtual CPU */
Richard Hendersonff970902013-02-10 10:30:42 -08005611#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
5612 /* These targets do not have traditional signals. */
5613 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
5614#else
pbrook624f7972008-05-31 16:11:38 +00005615 if (sa->sa_flags & TARGET_SA_SIGINFO)
5616 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005617 else
pbrook624f7972008-05-31 16:11:38 +00005618 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005619#endif
pbrook624f7972008-05-31 16:11:38 +00005620 if (sa->sa_flags & TARGET_SA_RESETHAND)
5621 sa->_sa_handler = TARGET_SIG_DFL;
bellard31e31b82003-02-18 22:55:36 +00005622 }
bellard66fb9762003-03-23 01:06:05 +00005623 if (q != &k->info)
pbrook624f7972008-05-31 16:11:38 +00005624 free_sigqueue(cpu_env, q);
bellard31e31b82003-02-18 22:55:36 +00005625}