blob: 502efd9fc43b7883aa7a8a9af3e5199bd00f5575 [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>
bellard31e31b82003-02-18 22:55:36 +000025#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030026#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000027
bellard3ef693a2003-03-23 20:17:16 +000028#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000029#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000030#include "target_signal.h"
bellard66fb9762003-03-23 01:06:05 +000031
32//#define DEBUG_SIGNAL
33
blueswir1249c4c32008-10-05 11:09:37 +000034static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000035 .ss_sp = 0,
36 .ss_size = 0,
37 .ss_flags = TARGET_SS_DISABLE,
38};
39
pbrook624f7972008-05-31 16:11:38 +000040static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000041
ths5fafdf22007-09-16 21:08:06 +000042static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000043 void *puc);
44
Arnaud Patard3ca05582009-03-30 01:18:20 +020045static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000046 [SIGHUP] = TARGET_SIGHUP,
47 [SIGINT] = TARGET_SIGINT,
48 [SIGQUIT] = TARGET_SIGQUIT,
49 [SIGILL] = TARGET_SIGILL,
50 [SIGTRAP] = TARGET_SIGTRAP,
51 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000052/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000053 [SIGBUS] = TARGET_SIGBUS,
54 [SIGFPE] = TARGET_SIGFPE,
55 [SIGKILL] = TARGET_SIGKILL,
56 [SIGUSR1] = TARGET_SIGUSR1,
57 [SIGSEGV] = TARGET_SIGSEGV,
58 [SIGUSR2] = TARGET_SIGUSR2,
59 [SIGPIPE] = TARGET_SIGPIPE,
60 [SIGALRM] = TARGET_SIGALRM,
61 [SIGTERM] = TARGET_SIGTERM,
62#ifdef SIGSTKFLT
63 [SIGSTKFLT] = TARGET_SIGSTKFLT,
64#endif
65 [SIGCHLD] = TARGET_SIGCHLD,
66 [SIGCONT] = TARGET_SIGCONT,
67 [SIGSTOP] = TARGET_SIGSTOP,
68 [SIGTSTP] = TARGET_SIGTSTP,
69 [SIGTTIN] = TARGET_SIGTTIN,
70 [SIGTTOU] = TARGET_SIGTTOU,
71 [SIGURG] = TARGET_SIGURG,
72 [SIGXCPU] = TARGET_SIGXCPU,
73 [SIGXFSZ] = TARGET_SIGXFSZ,
74 [SIGVTALRM] = TARGET_SIGVTALRM,
75 [SIGPROF] = TARGET_SIGPROF,
76 [SIGWINCH] = TARGET_SIGWINCH,
77 [SIGIO] = TARGET_SIGIO,
78 [SIGPWR] = TARGET_SIGPWR,
79 [SIGSYS] = TARGET_SIGSYS,
80 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000081 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080082 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000083 To fix this properly we need to do manual signal delivery multiplexed
84 over a single host signal. */
85 [__SIGRTMIN] = __SIGRTMAX,
86 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000087};
Arnaud Patard3ca05582009-03-30 01:18:20 +020088static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000089
thsa04e1342007-09-27 13:57:58 +000090static inline int on_sig_stack(unsigned long sp)
91{
92 return (sp - target_sigaltstack_used.ss_sp
93 < target_sigaltstack_used.ss_size);
94}
95
96static inline int sas_ss_flags(unsigned long sp)
97{
98 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
99 : on_sig_stack(sp) ? SS_ONSTACK : 0);
100}
101
pbrook1d9d8b52009-04-16 15:17:02 +0000102int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000103{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100104 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000105 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000106 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000107}
108
pbrook4cb05962008-05-30 18:05:19 +0000109int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000110{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100111 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000112 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000113 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000114}
115
Anthony Liguoric227f092009-10-01 16:12:16 -0500116static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000117{
118 memset(set, 0, sizeof(*set));
119}
120
Anthony Liguoric227f092009-10-01 16:12:16 -0500121static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000122{
123 signum--;
124 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
125 set->sig[signum / TARGET_NSIG_BPW] |= mask;
126}
127
Anthony Liguoric227f092009-10-01 16:12:16 -0500128static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000129{
130 signum--;
131 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
132 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
133}
134
Anthony Liguoric227f092009-10-01 16:12:16 -0500135static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000136 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000137{
138 int i;
pbrookf5545b52008-05-30 22:37:07 +0000139 target_sigemptyset(d);
140 for (i = 1; i <= TARGET_NSIG; i++) {
141 if (sigismember(s, i)) {
142 target_sigaddset(d, host_to_target_signal(i));
143 }
bellard9e5f5282003-07-13 17:33:54 +0000144 }
bellard66fb9762003-03-23 01:06:05 +0000145}
146
Anthony Liguoric227f092009-10-01 16:12:16 -0500147void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000148{
Anthony Liguoric227f092009-10-01 16:12:16 -0500149 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000150 int i;
151
152 host_to_target_sigset_internal(&d1, s);
153 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200154 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000155}
156
blueswir18fcd3692008-08-17 20:26:25 +0000157static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500158 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000159{
160 int i;
pbrookf5545b52008-05-30 22:37:07 +0000161 sigemptyset(d);
162 for (i = 1; i <= TARGET_NSIG; i++) {
163 if (target_sigismember(s, i)) {
164 sigaddset(d, target_to_host_signal(i));
165 }
166 }
bellard66fb9762003-03-23 01:06:05 +0000167}
168
Anthony Liguoric227f092009-10-01 16:12:16 -0500169void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000170{
Anthony Liguoric227f092009-10-01 16:12:16 -0500171 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000172 int i;
173
174 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200175 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000176 target_to_host_sigset_internal(d, &s1);
177}
ths3b46e622007-09-17 08:09:54 +0000178
blueswir1992f48a2007-10-14 16:27:31 +0000179void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000180 const sigset_t *sigset)
181{
Anthony Liguoric227f092009-10-01 16:12:16 -0500182 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000183 host_to_target_sigset(&d, sigset);
184 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000185}
186
ths5fafdf22007-09-16 21:08:06 +0000187void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000188 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000189{
Anthony Liguoric227f092009-10-01 16:12:16 -0500190 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000191 int i;
192
193 d.sig[0] = *old_sigset;
194 for(i = 1;i < TARGET_NSIG_WORDS; i++)
195 d.sig[i] = 0;
196 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000197}
198
Alex Barcelo1c275922014-03-14 14:36:55 +0000199/* Wrapper for sigprocmask function
200 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
201 * are host signal set, not guest ones. This wraps the sigprocmask host calls
202 * that should be protected (calls originated from guest)
203 */
204int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
205{
Peter Maydella7ec0f92014-03-14 14:36:56 +0000206 int ret;
207 sigset_t val;
208 sigset_t *temp = NULL;
209 CPUState *cpu = thread_cpu;
210 TaskState *ts = (TaskState *)cpu->opaque;
211 bool segv_was_blocked = ts->sigsegv_blocked;
212
213 if (set) {
214 bool has_sigsegv = sigismember(set, SIGSEGV);
215 val = *set;
216 temp = &val;
217
218 sigdelset(temp, SIGSEGV);
219
220 switch (how) {
221 case SIG_BLOCK:
222 if (has_sigsegv) {
223 ts->sigsegv_blocked = true;
224 }
225 break;
226 case SIG_UNBLOCK:
227 if (has_sigsegv) {
228 ts->sigsegv_blocked = false;
229 }
230 break;
231 case SIG_SETMASK:
232 ts->sigsegv_blocked = has_sigsegv;
233 break;
234 default:
235 g_assert_not_reached();
236 }
237 }
238
239 ret = sigprocmask(how, temp, oldset);
240
241 if (oldset && segv_was_blocked) {
242 sigaddset(oldset, SIGSEGV);
243 }
244
245 return ret;
Alex Barcelo1c275922014-03-14 14:36:55 +0000246}
247
bellard9de5e442003-03-23 16:49:39 +0000248/* siginfo conversion */
249
Anthony Liguoric227f092009-10-01 16:12:16 -0500250static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000251 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000252{
Richard Hendersona05c6402012-09-15 11:34:20 -0700253 int sig = host_to_target_signal(info->si_signo);
bellard9de5e442003-03-23 16:49:39 +0000254 tinfo->si_signo = sig;
255 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000256 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700257
258 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
259 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
260 /* Should never come here, but who knows. The information for
261 the target is irrelevant. */
bellard9de5e442003-03-23 16:49:39 +0000262 tinfo->_sifields._sigfault._addr = 0;
Richard Hendersona05c6402012-09-15 11:34:20 -0700263 } else if (sig == TARGET_SIGIO) {
264 tinfo->_sifields._sigpoll._band = info->si_band;
ths7f7f7c82007-07-12 11:02:46 +0000265 tinfo->_sifields._sigpoll._fd = info->si_fd;
Richard Hendersona05c6402012-09-15 11:34:20 -0700266 } else if (sig == TARGET_SIGCHLD) {
267 tinfo->_sifields._sigchld._pid = info->si_pid;
268 tinfo->_sifields._sigchld._uid = info->si_uid;
269 tinfo->_sifields._sigchld._status
270 = host_to_target_waitstatus(info->si_status);
271 tinfo->_sifields._sigchld._utime = info->si_utime;
272 tinfo->_sifields._sigchld._stime = info->si_stime;
bellard9de5e442003-03-23 16:49:39 +0000273 } else if (sig >= TARGET_SIGRTMIN) {
274 tinfo->_sifields._rt._pid = info->si_pid;
275 tinfo->_sifields._rt._uid = info->si_uid;
276 /* XXX: potential problem if 64 bit */
Richard Hendersona05c6402012-09-15 11:34:20 -0700277 tinfo->_sifields._rt._sigval.sival_ptr
278 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
bellard9de5e442003-03-23 16:49:39 +0000279 }
bellard66fb9762003-03-23 01:06:05 +0000280}
281
Anthony Liguoric227f092009-10-01 16:12:16 -0500282static void tswap_siginfo(target_siginfo_t *tinfo,
283 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000284{
Richard Hendersona05c6402012-09-15 11:34:20 -0700285 int sig = info->si_signo;
bellard9de5e442003-03-23 16:49:39 +0000286 tinfo->si_signo = tswap32(sig);
287 tinfo->si_errno = tswap32(info->si_errno);
288 tinfo->si_code = tswap32(info->si_code);
Richard Hendersona05c6402012-09-15 11:34:20 -0700289
290 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
291 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
292 tinfo->_sifields._sigfault._addr
293 = tswapal(info->_sifields._sigfault._addr);
294 } else if (sig == TARGET_SIGIO) {
295 tinfo->_sifields._sigpoll._band
296 = tswap32(info->_sifields._sigpoll._band);
297 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
298 } else if (sig == TARGET_SIGCHLD) {
299 tinfo->_sifields._sigchld._pid
300 = tswap32(info->_sifields._sigchld._pid);
301 tinfo->_sifields._sigchld._uid
302 = tswap32(info->_sifields._sigchld._uid);
303 tinfo->_sifields._sigchld._status
304 = tswap32(info->_sifields._sigchld._status);
305 tinfo->_sifields._sigchld._utime
306 = tswapal(info->_sifields._sigchld._utime);
307 tinfo->_sifields._sigchld._stime
308 = tswapal(info->_sifields._sigchld._stime);
bellard9de5e442003-03-23 16:49:39 +0000309 } else if (sig >= TARGET_SIGRTMIN) {
310 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
311 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
Richard Hendersona05c6402012-09-15 11:34:20 -0700312 tinfo->_sifields._rt._sigval.sival_ptr
313 = tswapal(info->_sifields._rt._sigval.sival_ptr);
bellard9de5e442003-03-23 16:49:39 +0000314 }
315}
316
317
Anthony Liguoric227f092009-10-01 16:12:16 -0500318void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000319{
320 host_to_target_siginfo_noswap(tinfo, info);
321 tswap_siginfo(tinfo, tinfo);
322}
323
324/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000325/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500326void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000327{
328 info->si_signo = tswap32(tinfo->si_signo);
329 info->si_errno = tswap32(tinfo->si_errno);
330 info->si_code = tswap32(tinfo->si_code);
bellard9de5e442003-03-23 16:49:39 +0000331 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
332 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
ths5fafdf22007-09-16 21:08:06 +0000333 info->si_value.sival_ptr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200334 (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr);
bellard66fb9762003-03-23 01:06:05 +0000335}
336
aurel32ca587a82008-12-18 22:44:13 +0000337static int fatal_signal (int sig)
338{
339 switch (sig) {
340 case TARGET_SIGCHLD:
341 case TARGET_SIGURG:
342 case TARGET_SIGWINCH:
343 /* Ignored by default. */
344 return 0;
345 case TARGET_SIGCONT:
346 case TARGET_SIGSTOP:
347 case TARGET_SIGTSTP:
348 case TARGET_SIGTTIN:
349 case TARGET_SIGTTOU:
350 /* Job control signals. */
351 return 0;
352 default:
353 return 1;
354 }
355}
356
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300357/* returns 1 if given signal should dump core if not handled */
358static int core_dump_signal(int sig)
359{
360 switch (sig) {
361 case TARGET_SIGABRT:
362 case TARGET_SIGFPE:
363 case TARGET_SIGILL:
364 case TARGET_SIGQUIT:
365 case TARGET_SIGSEGV:
366 case TARGET_SIGTRAP:
367 case TARGET_SIGBUS:
368 return (1);
369 default:
370 return (0);
371 }
372}
373
bellard31e31b82003-02-18 22:55:36 +0000374void signal_init(void)
375{
376 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000377 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000378 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000379 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000380
bellard9e5f5282003-07-13 17:33:54 +0000381 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200382 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000383 if (host_to_target_signal_table[i] == 0)
384 host_to_target_signal_table[i] = i;
385 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200386 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000387 j = host_to_target_signal_table[i];
388 target_to_host_signal_table[j] = i;
389 }
ths3b46e622007-09-17 08:09:54 +0000390
bellard9de5e442003-03-23 16:49:39 +0000391 /* set all host signal handlers. ALL signals are blocked during
392 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000393 memset(sigact_table, 0, sizeof(sigact_table));
394
bellard9de5e442003-03-23 16:49:39 +0000395 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000396 act.sa_flags = SA_SIGINFO;
397 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000398 for(i = 1; i <= TARGET_NSIG; i++) {
399 host_sig = target_to_host_signal(i);
400 sigaction(host_sig, NULL, &oact);
401 if (oact.sa_sigaction == (void *)SIG_IGN) {
402 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
403 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
404 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
405 }
406 /* If there's already a handler installed then something has
407 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000408 /* Install some handlers for our own use. We need at least
409 SIGSEGV and SIGBUS, to detect exceptions. We can not just
410 trap all signals because it affects syscall interrupt
411 behavior. But do trap all default-fatal signals. */
412 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000413 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000414 }
bellard31e31b82003-02-18 22:55:36 +0000415}
416
bellard66fb9762003-03-23 01:06:05 +0000417/* signal queue handling */
418
Andreas Färber9349b4f2012-03-14 01:38:32 +0100419static inline struct sigqueue *alloc_sigqueue(CPUArchState *env)
bellard66fb9762003-03-23 01:06:05 +0000420{
Andreas Färber0429a972013-08-26 18:14:44 +0200421 CPUState *cpu = ENV_GET_CPU(env);
422 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000423 struct sigqueue *q = ts->first_free;
bellard66fb9762003-03-23 01:06:05 +0000424 if (!q)
425 return NULL;
pbrook624f7972008-05-31 16:11:38 +0000426 ts->first_free = q->next;
bellard66fb9762003-03-23 01:06:05 +0000427 return q;
428}
429
Andreas Färber9349b4f2012-03-14 01:38:32 +0100430static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
bellard66fb9762003-03-23 01:06:05 +0000431{
Andreas Färber0429a972013-08-26 18:14:44 +0200432 CPUState *cpu = ENV_GET_CPU(env);
433 TaskState *ts = cpu->opaque;
434
pbrook624f7972008-05-31 16:11:38 +0000435 q->next = ts->first_free;
436 ts->first_free = q;
bellard66fb9762003-03-23 01:06:05 +0000437}
438
bellard9de5e442003-03-23 16:49:39 +0000439/* abort execution with signal */
Riku Voipio66393fb2009-12-04 15:16:32 +0200440static void QEMU_NORETURN force_sig(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000441{
Andreas Färber0429a972013-08-26 18:14:44 +0200442 CPUState *cpu = thread_cpu;
443 CPUArchState *env = cpu->env_ptr;
444 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300445 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000446 struct sigaction act;
Riku Voipio66393fb2009-12-04 15:16:32 +0200447 host_sig = target_to_host_signal(target_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200448 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000449
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300450 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200451 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300452 stop_all_tasks();
453 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200454 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300455 }
456 if (core_dumped) {
457 /* we already dumped the core of target process, we don't want
458 * a coredump of qemu itself */
459 struct rlimit nodump;
460 getrlimit(RLIMIT_CORE, &nodump);
461 nodump.rlim_cur=0;
462 setrlimit(RLIMIT_CORE, &nodump);
463 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200464 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300465 }
466
Stefan Weil0c587512011-04-28 17:20:32 +0200467 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000468 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
469 * a negative value. To get the proper exit code we need to
470 * actually die from an uncaught signal. Here the default signal
471 * handler is installed, we send ourself a signal and we wait for
472 * it to arrive. */
473 sigfillset(&act.sa_mask);
474 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000475 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000476 sigaction(host_sig, &act, NULL);
477
478 /* For some reason raise(host_sig) doesn't send the signal when
479 * statically linked on x86-64. */
480 kill(getpid(), host_sig);
481
482 /* Make sure the signal isn't masked (just reuse the mask inside
483 of act) */
484 sigdelset(&act.sa_mask, host_sig);
485 sigsuspend(&act.sa_mask);
486
487 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000488 abort();
bellard66fb9762003-03-23 01:06:05 +0000489}
490
bellard9de5e442003-03-23 16:49:39 +0000491/* queue a signal so that it will be send to the virtual CPU as soon
492 as possible */
Andreas Färber9349b4f2012-03-14 01:38:32 +0100493int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000494{
Andreas Färber0429a972013-08-26 18:14:44 +0200495 CPUState *cpu = ENV_GET_CPU(env);
496 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000497 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000498 struct sigqueue *q, **pq;
blueswir1992f48a2007-10-14 16:27:31 +0000499 abi_ulong handler;
aurel32ca587a82008-12-18 22:44:13 +0000500 int queue;
bellard66fb9762003-03-23 01:06:05 +0000501
bellard9de5e442003-03-23 16:49:39 +0000502#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000503 fprintf(stderr, "queue_signal: sig=%d\n",
bellard9de5e442003-03-23 16:49:39 +0000504 sig);
bellard66fb9762003-03-23 01:06:05 +0000505#endif
pbrook624f7972008-05-31 16:11:38 +0000506 k = &ts->sigtab[sig - 1];
aurel32ca587a82008-12-18 22:44:13 +0000507 queue = gdb_queuesig ();
pbrook624f7972008-05-31 16:11:38 +0000508 handler = sigact_table[sig - 1]._sa_handler;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000509
510 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
511 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
512 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
513 * because it got a real MMU fault). A blocked SIGSEGV in that
514 * situation is treated as if using the default handler. This is
515 * not correct if some other process has randomly sent us a SIGSEGV
516 * via kill(), but that is not easy to distinguish at this point,
517 * so we assume it doesn't happen.
518 */
519 handler = TARGET_SIG_DFL;
520 }
521
aurel32ca587a82008-12-18 22:44:13 +0000522 if (!queue && handler == TARGET_SIG_DFL) {
ths60b19692008-11-27 15:47:15 +0000523 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
524 kill(getpid(),SIGSTOP);
525 return 0;
526 } else
bellard66fb9762003-03-23 01:06:05 +0000527 /* default handler : ignore some signal. The other are fatal */
ths5fafdf22007-09-16 21:08:06 +0000528 if (sig != TARGET_SIGCHLD &&
529 sig != TARGET_SIGURG &&
ths60b19692008-11-27 15:47:15 +0000530 sig != TARGET_SIGWINCH &&
531 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +0000532 force_sig(sig);
bellard9de5e442003-03-23 16:49:39 +0000533 } else {
534 return 0; /* indicate ignored */
bellard66fb9762003-03-23 01:06:05 +0000535 }
aurel32ca587a82008-12-18 22:44:13 +0000536 } else if (!queue && handler == TARGET_SIG_IGN) {
bellard66fb9762003-03-23 01:06:05 +0000537 /* ignore signal */
bellard9de5e442003-03-23 16:49:39 +0000538 return 0;
aurel32ca587a82008-12-18 22:44:13 +0000539 } else if (!queue && handler == TARGET_SIG_ERR) {
bellard66fb9762003-03-23 01:06:05 +0000540 force_sig(sig);
541 } else {
bellard9de5e442003-03-23 16:49:39 +0000542 pq = &k->first;
543 if (sig < TARGET_SIGRTMIN) {
544 /* if non real time signal, we queue exactly one signal */
545 if (!k->pending)
546 q = &k->info;
547 else
548 return 0;
549 } else {
550 if (!k->pending) {
551 /* first signal */
552 q = &k->info;
553 } else {
pbrook624f7972008-05-31 16:11:38 +0000554 q = alloc_sigqueue(env);
bellard9de5e442003-03-23 16:49:39 +0000555 if (!q)
556 return -EAGAIN;
557 while (*pq != NULL)
558 pq = &(*pq)->next;
559 }
560 }
561 *pq = q;
562 q->info = *info;
563 q->next = NULL;
564 k->pending = 1;
565 /* signal that a new signal is pending */
pbrook624f7972008-05-31 16:11:38 +0000566 ts->signal_pending = 1;
bellard9de5e442003-03-23 16:49:39 +0000567 return 1; /* indicates that the signal was queued */
568 }
569}
570
ths5fafdf22007-09-16 21:08:06 +0000571static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000572 void *puc)
573{
Andreas Färbera2247f82013-06-09 19:47:04 +0200574 CPUArchState *env = thread_cpu->env_ptr;
bellard9de5e442003-03-23 16:49:39 +0000575 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500576 target_siginfo_t tinfo;
bellard9de5e442003-03-23 16:49:39 +0000577
578 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000579 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000580 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000581 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000582 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000583 return;
584 }
585
586 /* get target signal number */
587 sig = host_to_target_signal(host_signum);
588 if (sig < 1 || sig > TARGET_NSIG)
589 return;
590#if defined(DEBUG_SIGNAL)
bellardbc8a22c2003-03-30 21:02:40 +0000591 fprintf(stderr, "qemu: got signal %d\n", sig);
bellard9de5e442003-03-23 16:49:39 +0000592#endif
593 host_to_target_siginfo_noswap(&tinfo, info);
Andreas Färbera2247f82013-06-09 19:47:04 +0200594 if (queue_signal(env, sig, &tinfo) == 1) {
bellard9de5e442003-03-23 16:49:39 +0000595 /* interrupt the virtual CPU as soon as possible */
Andreas Färbera2247f82013-06-09 19:47:04 +0200596 cpu_exit(thread_cpu);
bellard66fb9762003-03-23 01:06:05 +0000597 }
bellard31e31b82003-02-18 22:55:36 +0000598}
599
ths0da46a62007-10-20 20:23:07 +0000600/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000601/* compare linux/kernel/signal.c:do_sigaltstack() */
602abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000603{
604 int ret;
605 struct target_sigaltstack oss;
606
607 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000608 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000609 {
610 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
611 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
612 __put_user(sas_ss_flags(sp), &oss.ss_flags);
613 }
614
bellard579a97f2007-11-11 14:26:47 +0000615 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000616 {
bellard579a97f2007-11-11 14:26:47 +0000617 struct target_sigaltstack *uss;
618 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500619 size_t minstacksize = TARGET_MINSIGSTKSZ;
620
621#if defined(TARGET_PPC64)
622 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
623 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
624 if (get_ppc64_abi(image) > 1) {
625 minstacksize = 4096;
626 }
627#endif
thsa04e1342007-09-27 13:57:58 +0000628
ths0da46a62007-10-20 20:23:07 +0000629 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300630 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000631 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300632 }
633 __get_user(ss.ss_sp, &uss->ss_sp);
634 __get_user(ss.ss_size, &uss->ss_size);
635 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000636 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000637
ths0da46a62007-10-20 20:23:07 +0000638 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000639 if (on_sig_stack(sp))
640 goto out;
641
ths0da46a62007-10-20 20:23:07 +0000642 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000643 if (ss.ss_flags != TARGET_SS_DISABLE
644 && ss.ss_flags != TARGET_SS_ONSTACK
645 && ss.ss_flags != 0)
646 goto out;
647
648 if (ss.ss_flags == TARGET_SS_DISABLE) {
649 ss.ss_size = 0;
650 ss.ss_sp = 0;
651 } else {
ths0da46a62007-10-20 20:23:07 +0000652 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500653 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000654 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500655 }
thsa04e1342007-09-27 13:57:58 +0000656 }
657
658 target_sigaltstack_used.ss_sp = ss.ss_sp;
659 target_sigaltstack_used.ss_size = ss.ss_size;
660 }
661
bellard579a97f2007-11-11 14:26:47 +0000662 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000663 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000664 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000665 goto out;
thsa04e1342007-09-27 13:57:58 +0000666 }
667
668 ret = 0;
669out:
670 return ret;
671}
672
ths0da46a62007-10-20 20:23:07 +0000673/* do_sigaction() return host values and errnos */
bellard66fb9762003-03-23 01:06:05 +0000674int do_sigaction(int sig, const struct target_sigaction *act,
675 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000676{
pbrook624f7972008-05-31 16:11:38 +0000677 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000678 struct sigaction act1;
679 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000680 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000681
ths2a913eb2008-11-27 15:46:25 +0000682 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
bellard66fb9762003-03-23 01:06:05 +0000683 return -EINVAL;
684 k = &sigact_table[sig - 1];
bellard773b93e2004-01-04 17:15:59 +0000685#if defined(DEBUG_SIGNAL)
Blue Swirl0bf9e312009-07-20 17:19:25 +0000686 fprintf(stderr, "sigaction sig=%d act=0x%p, oact=0x%p\n",
687 sig, act, oact);
bellard66fb9762003-03-23 01:06:05 +0000688#endif
689 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800690 __put_user(k->_sa_handler, &oact->_sa_handler);
691 __put_user(k->sa_flags, &oact->sa_flags);
ths388bb212007-05-13 13:58:00 +0000692#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800693 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000694#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800695 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000696 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000697 }
698 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000699 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800700 __get_user(k->_sa_handler, &act->_sa_handler);
701 __get_user(k->sa_flags, &act->sa_flags);
ths388bb212007-05-13 13:58:00 +0000702#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800703 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000704#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800705 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000706 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000707
708 /* we update the host linux signal state */
709 host_sig = target_to_host_signal(sig);
710 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
711 sigfillset(&act1.sa_mask);
712 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000713 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000714 act1.sa_flags |= SA_RESTART;
715 /* NOTE: it is important to update the host kernel signal
716 ignore state to avoid getting unexpected interrupted
717 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000718 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000719 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000720 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000721 if (fatal_signal (sig))
722 act1.sa_sigaction = host_signal_handler;
723 else
724 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000725 } else {
726 act1.sa_sigaction = host_signal_handler;
727 }
ths0da46a62007-10-20 20:23:07 +0000728 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000729 }
bellard66fb9762003-03-23 01:06:05 +0000730 }
ths0da46a62007-10-20 20:23:07 +0000731 return ret;
bellard66fb9762003-03-23 01:06:05 +0000732}
bellard31e31b82003-02-18 22:55:36 +0000733
bellard459a4012007-11-11 19:45:10 +0000734#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
bellard66fb9762003-03-23 01:06:05 +0000735
736/* from the Linux kernel */
737
738struct target_fpreg {
739 uint16_t significand[4];
740 uint16_t exponent;
741};
742
743struct target_fpxreg {
744 uint16_t significand[4];
745 uint16_t exponent;
746 uint16_t padding[3];
747};
748
749struct target_xmmreg {
blueswir1992f48a2007-10-14 16:27:31 +0000750 abi_ulong element[4];
bellard66fb9762003-03-23 01:06:05 +0000751};
752
753struct target_fpstate {
754 /* Regular FPU environment */
blueswir1992f48a2007-10-14 16:27:31 +0000755 abi_ulong cw;
756 abi_ulong sw;
757 abi_ulong tag;
758 abi_ulong ipoff;
759 abi_ulong cssel;
760 abi_ulong dataoff;
761 abi_ulong datasel;
bellard66fb9762003-03-23 01:06:05 +0000762 struct target_fpreg _st[8];
763 uint16_t status;
764 uint16_t magic; /* 0xffff = regular FPU data only */
765
766 /* FXSR FPU environment */
blueswir1992f48a2007-10-14 16:27:31 +0000767 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
768 abi_ulong mxcsr;
769 abi_ulong reserved;
bellard66fb9762003-03-23 01:06:05 +0000770 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
771 struct target_xmmreg _xmm[8];
blueswir1992f48a2007-10-14 16:27:31 +0000772 abi_ulong padding[56];
bellard66fb9762003-03-23 01:06:05 +0000773};
774
775#define X86_FXSR_MAGIC 0x0000
776
777struct target_sigcontext {
778 uint16_t gs, __gsh;
779 uint16_t fs, __fsh;
780 uint16_t es, __esh;
781 uint16_t ds, __dsh;
blueswir1992f48a2007-10-14 16:27:31 +0000782 abi_ulong edi;
783 abi_ulong esi;
784 abi_ulong ebp;
785 abi_ulong esp;
786 abi_ulong ebx;
787 abi_ulong edx;
788 abi_ulong ecx;
789 abi_ulong eax;
790 abi_ulong trapno;
791 abi_ulong err;
792 abi_ulong eip;
bellard66fb9762003-03-23 01:06:05 +0000793 uint16_t cs, __csh;
blueswir1992f48a2007-10-14 16:27:31 +0000794 abi_ulong eflags;
795 abi_ulong esp_at_signal;
bellard66fb9762003-03-23 01:06:05 +0000796 uint16_t ss, __ssh;
blueswir1992f48a2007-10-14 16:27:31 +0000797 abi_ulong fpstate; /* pointer */
798 abi_ulong oldmask;
799 abi_ulong cr2;
bellard66fb9762003-03-23 01:06:05 +0000800};
801
bellard66fb9762003-03-23 01:06:05 +0000802struct target_ucontext {
blueswir1992f48a2007-10-14 16:27:31 +0000803 abi_ulong tuc_flags;
804 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -0500805 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +0000806 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -0500807 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000808};
809
810struct sigframe
811{
blueswir1992f48a2007-10-14 16:27:31 +0000812 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000813 int sig;
814 struct target_sigcontext sc;
815 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000816 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000817 char retcode[8];
818};
819
820struct rt_sigframe
821{
blueswir1992f48a2007-10-14 16:27:31 +0000822 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000823 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000824 abi_ulong pinfo;
825 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000826 struct target_siginfo info;
827 struct target_ucontext uc;
828 struct target_fpstate fpstate;
829 char retcode[8];
830};
831
832/*
833 * Set up a signal frame.
834 */
835
bellard66fb9762003-03-23 01:06:05 +0000836/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300837static void setup_sigcontext(struct target_sigcontext *sc,
838 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
839 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000840{
Andreas Färber27103422013-08-26 08:31:06 +0200841 CPUState *cs = CPU(x86_env_get_cpu(env));
Andreas Färber27103422013-08-26 08:31:06 +0200842 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +0000843
bellard579a97f2007-11-11 14:26:47 +0000844 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300845 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
846 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
847 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
848 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
849 __put_user(env->regs[R_EDI], &sc->edi);
850 __put_user(env->regs[R_ESI], &sc->esi);
851 __put_user(env->regs[R_EBP], &sc->ebp);
852 __put_user(env->regs[R_ESP], &sc->esp);
853 __put_user(env->regs[R_EBX], &sc->ebx);
854 __put_user(env->regs[R_EDX], &sc->edx);
855 __put_user(env->regs[R_ECX], &sc->ecx);
856 __put_user(env->regs[R_EAX], &sc->eax);
857 __put_user(cs->exception_index, &sc->trapno);
858 __put_user(env->error_code, &sc->err);
859 __put_user(env->eip, &sc->eip);
860 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
861 __put_user(env->eflags, &sc->eflags);
862 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
863 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +0000864
bellard28be6232007-11-11 22:23:38 +0000865 cpu_x86_fsave(env, fpstate_addr, 1);
bellarded2dcdf2003-05-29 20:06:27 +0000866 fpstate->status = fpstate->sw;
bellard775b58d2007-11-11 16:22:17 +0000867 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300868 __put_user(magic, &fpstate->magic);
869 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +0000870
bellard66fb9762003-03-23 01:06:05 +0000871 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300872 __put_user(mask, &sc->oldmask);
873 __put_user(env->cr[2], &sc->cr2);
bellard66fb9762003-03-23 01:06:05 +0000874}
875
876/*
877 * Determine which stack to use..
878 */
879
bellard579a97f2007-11-11 14:26:47 +0000880static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +0000881get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +0000882{
883 unsigned long esp;
884
885 /* Default to using normal stack */
886 esp = env->regs[R_ESP];
bellard66fb9762003-03-23 01:06:05 +0000887 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +0000888 if (ka->sa_flags & TARGET_SA_ONSTACK) {
thsa04e1342007-09-27 13:57:58 +0000889 if (sas_ss_flags(esp) == 0)
890 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
891 }
bellard66fb9762003-03-23 01:06:05 +0000892
893 /* This is the legacy signal stack switching. */
ths5fafdf22007-09-16 21:08:06 +0000894 else
bellarda52c7572003-06-21 13:14:12 +0000895 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
pbrook624f7972008-05-31 16:11:38 +0000896 !(ka->sa_flags & TARGET_SA_RESTORER) &&
897 ka->sa_restorer) {
898 esp = (unsigned long) ka->sa_restorer;
bellarda52c7572003-06-21 13:14:12 +0000899 }
bellard579a97f2007-11-11 14:26:47 +0000900 return (esp - frame_size) & -8ul;
bellard66fb9762003-03-23 01:06:05 +0000901}
902
bellard579a97f2007-11-11 14:26:47 +0000903/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +0000904static void setup_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -0500905 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000906{
bellard579a97f2007-11-11 14:26:47 +0000907 abi_ulong frame_addr;
bellard66fb9762003-03-23 01:06:05 +0000908 struct sigframe *frame;
Riku Voipio7df2fa32014-04-23 10:34:53 +0300909 int i;
bellard66fb9762003-03-23 01:06:05 +0000910
bellard579a97f2007-11-11 14:26:47 +0000911 frame_addr = get_sigframe(ka, env, sizeof(*frame));
bellard66fb9762003-03-23 01:06:05 +0000912
bellard579a97f2007-11-11 14:26:47 +0000913 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
bellard66fb9762003-03-23 01:06:05 +0000914 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +0000915
Peter Maydellb6e2c932015-01-08 12:19:43 +0000916 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +0000917
bellard28be6232007-11-11 22:23:38 +0000918 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
919 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +0000920
Riku Voipio7df2fa32014-04-23 10:34:53 +0300921 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
922 __put_user(set->sig[i], &frame->extramask[i - 1]);
923 }
bellard66fb9762003-03-23 01:06:05 +0000924
925 /* Set up to return from userspace. If provided, use a stub
926 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +0000927 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +0300928 __put_user(ka->sa_restorer, &frame->pretcode);
bellard66fb9762003-03-23 01:06:05 +0000929 } else {
bellard775b58d2007-11-11 16:22:17 +0000930 uint16_t val16;
bellard28be6232007-11-11 22:23:38 +0000931 abi_ulong retcode_addr;
932 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300933 __put_user(retcode_addr, &frame->pretcode);
bellard66fb9762003-03-23 01:06:05 +0000934 /* This is popl %eax ; movl $,%eax ; int $0x80 */
bellard775b58d2007-11-11 16:22:17 +0000935 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300936 __put_user(val16, (uint16_t *)(frame->retcode+0));
937 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
bellard775b58d2007-11-11 16:22:17 +0000938 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300939 __put_user(val16, (uint16_t *)(frame->retcode+6));
bellard66fb9762003-03-23 01:06:05 +0000940 }
941
bellard66fb9762003-03-23 01:06:05 +0000942
943 /* Set up registers for signal handler */
bellard28be6232007-11-11 22:23:38 +0000944 env->regs[R_ESP] = frame_addr;
pbrook624f7972008-05-31 16:11:38 +0000945 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +0000946
947 cpu_x86_load_seg(env, R_DS, __USER_DS);
948 cpu_x86_load_seg(env, R_ES, __USER_DS);
949 cpu_x86_load_seg(env, R_SS, __USER_DS);
950 cpu_x86_load_seg(env, R_CS, __USER_CS);
951 env->eflags &= ~TF_MASK;
952
bellard579a97f2007-11-11 14:26:47 +0000953 unlock_user_struct(frame, frame_addr, 1);
954
bellard66fb9762003-03-23 01:06:05 +0000955 return;
956
957give_sigsegv:
958 if (sig == TARGET_SIGSEGV)
pbrook624f7972008-05-31 16:11:38 +0000959 ka->_sa_handler = TARGET_SIG_DFL;
bellard66fb9762003-03-23 01:06:05 +0000960 force_sig(TARGET_SIGSEGV /* , current */);
961}
962
bellard579a97f2007-11-11 14:26:47 +0000963/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +0000964static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -0500965 target_siginfo_t *info,
966 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000967{
bellard28be6232007-11-11 22:23:38 +0000968 abi_ulong frame_addr, addr;
bellard66fb9762003-03-23 01:06:05 +0000969 struct rt_sigframe *frame;
Riku Voipio0188fad2014-04-23 13:34:15 +0300970 int i;
bellard66fb9762003-03-23 01:06:05 +0000971
bellard579a97f2007-11-11 14:26:47 +0000972 frame_addr = get_sigframe(ka, env, sizeof(*frame));
bellard66fb9762003-03-23 01:06:05 +0000973
bellard579a97f2007-11-11 14:26:47 +0000974 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
bellard66fb9762003-03-23 01:06:05 +0000975 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +0000976
Peter Maydellb6e2c932015-01-08 12:19:43 +0000977 __put_user(sig, &frame->sig);
bellard28be6232007-11-11 22:23:38 +0000978 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300979 __put_user(addr, &frame->pinfo);
bellard28be6232007-11-11 22:23:38 +0000980 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300981 __put_user(addr, &frame->puc);
Peter Maydellf6c7a052015-01-08 12:19:48 +0000982 tswap_siginfo(&frame->info, info);
bellard66fb9762003-03-23 01:06:05 +0000983
984 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300985 __put_user(0, &frame->uc.tuc_flags);
986 __put_user(0, &frame->uc.tuc_link);
987 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
988 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
989 &frame->uc.tuc_stack.ss_flags);
990 __put_user(target_sigaltstack_used.ss_size,
991 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +0300992 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
993 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
994
Riku Voipio0188fad2014-04-23 13:34:15 +0300995 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
996 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
997 }
bellard66fb9762003-03-23 01:06:05 +0000998
999 /* Set up to return from userspace. If provided, use a stub
1000 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00001001 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001002 __put_user(ka->sa_restorer, &frame->pretcode);
bellard66fb9762003-03-23 01:06:05 +00001003 } else {
bellard775b58d2007-11-11 16:22:17 +00001004 uint16_t val16;
bellard28be6232007-11-11 22:23:38 +00001005 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001006 __put_user(addr, &frame->pretcode);
bellard66fb9762003-03-23 01:06:05 +00001007 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001008 __put_user(0xb8, (char *)(frame->retcode+0));
1009 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
bellard775b58d2007-11-11 16:22:17 +00001010 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001011 __put_user(val16, (uint16_t *)(frame->retcode+5));
bellard66fb9762003-03-23 01:06:05 +00001012 }
1013
bellard66fb9762003-03-23 01:06:05 +00001014 /* Set up registers for signal handler */
bellard28be6232007-11-11 22:23:38 +00001015 env->regs[R_ESP] = frame_addr;
pbrook624f7972008-05-31 16:11:38 +00001016 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001017
1018 cpu_x86_load_seg(env, R_DS, __USER_DS);
1019 cpu_x86_load_seg(env, R_ES, __USER_DS);
1020 cpu_x86_load_seg(env, R_SS, __USER_DS);
1021 cpu_x86_load_seg(env, R_CS, __USER_CS);
1022 env->eflags &= ~TF_MASK;
1023
bellard579a97f2007-11-11 14:26:47 +00001024 unlock_user_struct(frame, frame_addr, 1);
1025
bellard66fb9762003-03-23 01:06:05 +00001026 return;
1027
1028give_sigsegv:
1029 if (sig == TARGET_SIGSEGV)
pbrook624f7972008-05-31 16:11:38 +00001030 ka->_sa_handler = TARGET_SIG_DFL;
bellard66fb9762003-03-23 01:06:05 +00001031 force_sig(TARGET_SIGSEGV /* , current */);
1032}
1033
1034static int
1035restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
1036{
1037 unsigned int err = 0;
bellard28be6232007-11-11 22:23:38 +00001038 abi_ulong fpstate_addr;
1039 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001040
bellard28be6232007-11-11 22:23:38 +00001041 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1042 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1043 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1044 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001045
bellard28be6232007-11-11 22:23:38 +00001046 env->regs[R_EDI] = tswapl(sc->edi);
1047 env->regs[R_ESI] = tswapl(sc->esi);
1048 env->regs[R_EBP] = tswapl(sc->ebp);
1049 env->regs[R_ESP] = tswapl(sc->esp);
1050 env->regs[R_EBX] = tswapl(sc->ebx);
1051 env->regs[R_EDX] = tswapl(sc->edx);
1052 env->regs[R_ECX] = tswapl(sc->ecx);
1053 env->eip = tswapl(sc->eip);
bellard66fb9762003-03-23 01:06:05 +00001054
Mike McCormack9a826d72011-06-01 15:14:37 +09001055 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1056 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001057
bellard28be6232007-11-11 22:23:38 +00001058 tmpflags = tswapl(sc->eflags);
1059 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1060 // regs->orig_eax = -1; /* disable syscall checks */
1061
1062 fpstate_addr = tswapl(sc->fpstate);
1063 if (fpstate_addr != 0) {
1064 if (!access_ok(VERIFY_READ, fpstate_addr,
1065 sizeof(struct target_fpstate)))
1066 goto badframe;
1067 cpu_x86_frstor(env, fpstate_addr, 1);
bellard66fb9762003-03-23 01:06:05 +00001068 }
1069
bellard28be6232007-11-11 22:23:38 +00001070 *peax = tswapl(sc->eax);
bellard66fb9762003-03-23 01:06:05 +00001071 return err;
bellard66fb9762003-03-23 01:06:05 +00001072badframe:
1073 return 1;
bellard66fb9762003-03-23 01:06:05 +00001074}
1075
1076long do_sigreturn(CPUX86State *env)
1077{
bellard579a97f2007-11-11 14:26:47 +00001078 struct sigframe *frame;
1079 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001080 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001081 sigset_t set;
1082 int eax, i;
1083
bellard447db212003-05-10 15:10:36 +00001084#if defined(DEBUG_SIGNAL)
1085 fprintf(stderr, "do_sigreturn\n");
1086#endif
bellard579a97f2007-11-11 14:26:47 +00001087 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1088 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001089 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001090 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001091 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001092 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001093 }
bellard66fb9762003-03-23 01:06:05 +00001094
bellard92319442004-06-19 16:58:13 +00001095 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00001096 do_sigprocmask(SIG_SETMASK, &set, NULL);
ths3b46e622007-09-17 08:09:54 +00001097
bellard66fb9762003-03-23 01:06:05 +00001098 /* restore registers */
1099 if (restore_sigcontext(env, &frame->sc, &eax))
1100 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001101 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001102 return eax;
1103
1104badframe:
bellard579a97f2007-11-11 14:26:47 +00001105 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001106 force_sig(TARGET_SIGSEGV);
1107 return 0;
1108}
1109
1110long do_rt_sigreturn(CPUX86State *env)
1111{
bellard28be6232007-11-11 22:23:38 +00001112 abi_ulong frame_addr;
1113 struct rt_sigframe *frame;
bellard66fb9762003-03-23 01:06:05 +00001114 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001115 int eax;
1116
bellard28be6232007-11-11 22:23:38 +00001117 frame_addr = env->regs[R_ESP] - 4;
1118 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1119 goto badframe;
bellardb8076a72005-04-07 22:20:31 +00001120 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001121 do_sigprocmask(SIG_SETMASK, &set, NULL);
ths5fafdf22007-09-16 21:08:06 +00001122
bellardb8076a72005-04-07 22:20:31 +00001123 if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
bellard66fb9762003-03-23 01:06:05 +00001124 goto badframe;
1125
bellard28be6232007-11-11 22:23:38 +00001126 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1127 get_sp_from_cpustate(env)) == -EFAULT)
bellard66fb9762003-03-23 01:06:05 +00001128 goto badframe;
thsa04e1342007-09-27 13:57:58 +00001129
bellard28be6232007-11-11 22:23:38 +00001130 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001131 return eax;
1132
1133badframe:
bellard28be6232007-11-11 22:23:38 +00001134 unlock_user_struct(frame, frame_addr, 0);
1135 force_sig(TARGET_SIGSEGV);
bellard66fb9762003-03-23 01:06:05 +00001136 return 0;
1137}
1138
Andreas Schwab1744aea2013-09-03 20:12:16 +01001139#elif defined(TARGET_AARCH64)
1140
1141struct target_sigcontext {
1142 uint64_t fault_address;
1143 /* AArch64 registers */
1144 uint64_t regs[31];
1145 uint64_t sp;
1146 uint64_t pc;
1147 uint64_t pstate;
1148 /* 4K reserved for FP/SIMD state and future expansion */
1149 char __reserved[4096] __attribute__((__aligned__(16)));
1150};
1151
1152struct target_ucontext {
1153 abi_ulong tuc_flags;
1154 abi_ulong tuc_link;
1155 target_stack_t tuc_stack;
1156 target_sigset_t tuc_sigmask;
1157 /* glibc uses a 1024-bit sigset_t */
1158 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1159 /* last for future expansion */
1160 struct target_sigcontext tuc_mcontext;
1161};
1162
1163/*
1164 * Header to be used at the beginning of structures extending the user
1165 * context. Such structures must be placed after the rt_sigframe on the stack
1166 * and be 16-byte aligned. The last structure must be a dummy one with the
1167 * magic and size set to 0.
1168 */
1169struct target_aarch64_ctx {
1170 uint32_t magic;
1171 uint32_t size;
1172};
1173
1174#define TARGET_FPSIMD_MAGIC 0x46508001
1175
1176struct target_fpsimd_context {
1177 struct target_aarch64_ctx head;
1178 uint32_t fpsr;
1179 uint32_t fpcr;
1180 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1181};
1182
1183/*
1184 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1185 * user space as it will change with the addition of new context. User space
1186 * should check the magic/size information.
1187 */
1188struct target_aux_context {
1189 struct target_fpsimd_context fpsimd;
1190 /* additional context to be added before "end" */
1191 struct target_aarch64_ctx end;
1192};
1193
1194struct target_rt_sigframe {
1195 struct target_siginfo info;
1196 struct target_ucontext uc;
1197 uint64_t fp;
1198 uint64_t lr;
1199 uint32_t tramp[2];
1200};
1201
1202static int target_setup_sigframe(struct target_rt_sigframe *sf,
1203 CPUARMState *env, target_sigset_t *set)
1204{
1205 int i;
1206 struct target_aux_context *aux =
1207 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1208
1209 /* set up the stack frame for unwinding */
1210 __put_user(env->xregs[29], &sf->fp);
1211 __put_user(env->xregs[30], &sf->lr);
1212
1213 for (i = 0; i < 31; i++) {
1214 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1215 }
1216 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1217 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001218 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001219
Peter Maydell7af03922014-05-01 18:36:17 +01001220 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001221
1222 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1223 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1224 }
1225
1226 for (i = 0; i < 32; i++) {
1227#ifdef TARGET_WORDS_BIGENDIAN
1228 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1229 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1230#else
1231 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1232 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1233#endif
1234 }
Will Newtone0ee1382014-01-04 22:15:48 +00001235 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1236 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001237 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1238 __put_user(sizeof(struct target_fpsimd_context),
1239 &aux->fpsimd.head.size);
1240
1241 /* set the "end" magic */
1242 __put_user(0, &aux->end.magic);
1243 __put_user(0, &aux->end.size);
1244
1245 return 0;
1246}
1247
1248static int target_restore_sigframe(CPUARMState *env,
1249 struct target_rt_sigframe *sf)
1250{
1251 sigset_t set;
1252 int i;
1253 struct target_aux_context *aux =
1254 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
Will Newtone0ee1382014-01-04 22:15:48 +00001255 uint32_t magic, size, fpsr, fpcr;
Peter Maydelld3563122013-12-17 19:42:30 +00001256 uint64_t pstate;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001257
1258 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001259 do_sigprocmask(SIG_SETMASK, &set, NULL);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001260
1261 for (i = 0; i < 31; i++) {
1262 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1263 }
1264
1265 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1266 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001267 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1268 pstate_write(env, pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001269
1270 __get_user(magic, &aux->fpsimd.head.magic);
1271 __get_user(size, &aux->fpsimd.head.size);
1272
1273 if (magic != TARGET_FPSIMD_MAGIC
1274 || size != sizeof(struct target_fpsimd_context)) {
1275 return 1;
1276 }
1277
Peter Maydell4cf23482014-03-02 19:36:38 +00001278 for (i = 0; i < 32; i++) {
1279#ifdef TARGET_WORDS_BIGENDIAN
1280 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1281 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1282#else
1283 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1284 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1285#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001286 }
Will Newtone0ee1382014-01-04 22:15:48 +00001287 __get_user(fpsr, &aux->fpsimd.fpsr);
1288 vfp_set_fpsr(env, fpsr);
1289 __get_user(fpcr, &aux->fpsimd.fpcr);
1290 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001291
1292 return 0;
1293}
1294
1295static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1296{
1297 abi_ulong sp;
1298
1299 sp = env->xregs[31];
1300
1301 /*
1302 * This is the X/Open sanctioned signal stack switching.
1303 */
Riku Voipiob545f632014-07-15 17:01:55 +03001304 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001305 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1306 }
1307
1308 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1309
1310 return sp;
1311}
1312
1313static void target_setup_frame(int usig, struct target_sigaction *ka,
1314 target_siginfo_t *info, target_sigset_t *set,
1315 CPUARMState *env)
1316{
1317 struct target_rt_sigframe *frame;
Michael Matz8a3ae912014-03-02 19:36:39 +00001318 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001319
1320 frame_addr = get_sigframe(ka, env);
1321 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1322 goto give_sigsegv;
1323 }
1324
1325 __put_user(0, &frame->uc.tuc_flags);
1326 __put_user(0, &frame->uc.tuc_link);
1327
1328 __put_user(target_sigaltstack_used.ss_sp,
1329 &frame->uc.tuc_stack.ss_sp);
1330 __put_user(sas_ss_flags(env->xregs[31]),
1331 &frame->uc.tuc_stack.ss_flags);
1332 __put_user(target_sigaltstack_used.ss_size,
1333 &frame->uc.tuc_stack.ss_size);
1334 target_setup_sigframe(frame, env, set);
Michael Matz8a3ae912014-03-02 19:36:39 +00001335 if (ka->sa_flags & TARGET_SA_RESTORER) {
1336 return_addr = ka->sa_restorer;
1337 } else {
1338 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1339 __put_user(0xd2801168, &frame->tramp[0]);
1340 __put_user(0xd4000001, &frame->tramp[1]);
1341 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1342 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001343 env->xregs[0] = usig;
1344 env->xregs[31] = frame_addr;
1345 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1346 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001347 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001348 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001349 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001350 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1351 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1352 }
1353
1354 unlock_user_struct(frame, frame_addr, 1);
1355 return;
1356
1357 give_sigsegv:
1358 unlock_user_struct(frame, frame_addr, 1);
1359 force_sig(TARGET_SIGSEGV);
1360}
1361
1362static void setup_rt_frame(int sig, struct target_sigaction *ka,
1363 target_siginfo_t *info, target_sigset_t *set,
1364 CPUARMState *env)
1365{
1366 target_setup_frame(sig, ka, info, set, env);
1367}
1368
1369static void setup_frame(int sig, struct target_sigaction *ka,
1370 target_sigset_t *set, CPUARMState *env)
1371{
1372 target_setup_frame(sig, ka, 0, set, env);
1373}
1374
1375long do_rt_sigreturn(CPUARMState *env)
1376{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001377 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001378 abi_ulong frame_addr = env->xregs[31];
1379
1380 if (frame_addr & 15) {
1381 goto badframe;
1382 }
1383
1384 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1385 goto badframe;
1386 }
1387
1388 if (target_restore_sigframe(env, frame)) {
1389 goto badframe;
1390 }
1391
1392 if (do_sigaltstack(frame_addr +
1393 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1394 0, get_sp_from_cpustate(env)) == -EFAULT) {
1395 goto badframe;
1396 }
1397
1398 unlock_user_struct(frame, frame_addr, 0);
1399 return env->xregs[0];
1400
1401 badframe:
1402 unlock_user_struct(frame, frame_addr, 0);
1403 force_sig(TARGET_SIGSEGV);
1404 return 0;
1405}
1406
1407long do_sigreturn(CPUARMState *env)
1408{
1409 return do_rt_sigreturn(env);
1410}
1411
bellard43fff232003-07-09 19:31:39 +00001412#elif defined(TARGET_ARM)
1413
1414struct target_sigcontext {
blueswir1992f48a2007-10-14 16:27:31 +00001415 abi_ulong trap_no;
1416 abi_ulong error_code;
1417 abi_ulong oldmask;
1418 abi_ulong arm_r0;
1419 abi_ulong arm_r1;
1420 abi_ulong arm_r2;
1421 abi_ulong arm_r3;
1422 abi_ulong arm_r4;
1423 abi_ulong arm_r5;
1424 abi_ulong arm_r6;
1425 abi_ulong arm_r7;
1426 abi_ulong arm_r8;
1427 abi_ulong arm_r9;
1428 abi_ulong arm_r10;
1429 abi_ulong arm_fp;
1430 abi_ulong arm_ip;
1431 abi_ulong arm_sp;
1432 abi_ulong arm_lr;
1433 abi_ulong arm_pc;
1434 abi_ulong arm_cpsr;
1435 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001436};
1437
pbrooka745ec62008-05-06 15:36:17 +00001438struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001439 abi_ulong tuc_flags;
1440 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001441 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001442 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001443 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001444};
1445
pbrooka745ec62008-05-06 15:36:17 +00001446struct target_ucontext_v2 {
1447 abi_ulong tuc_flags;
1448 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001449 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001450 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001451 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001452 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001453 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1454};
1455
Peter Maydell0d871bd2010-11-24 15:20:05 +00001456struct target_user_vfp {
1457 uint64_t fpregs[32];
1458 abi_ulong fpscr;
1459};
1460
1461struct target_user_vfp_exc {
1462 abi_ulong fpexc;
1463 abi_ulong fpinst;
1464 abi_ulong fpinst2;
1465};
1466
1467struct target_vfp_sigframe {
1468 abi_ulong magic;
1469 abi_ulong size;
1470 struct target_user_vfp ufp;
1471 struct target_user_vfp_exc ufp_exc;
1472} __attribute__((__aligned__(8)));
1473
Peter Maydell08e11252010-11-24 15:20:07 +00001474struct target_iwmmxt_sigframe {
1475 abi_ulong magic;
1476 abi_ulong size;
1477 uint64_t regs[16];
1478 /* Note that not all the coprocessor control registers are stored here */
1479 uint32_t wcssf;
1480 uint32_t wcasf;
1481 uint32_t wcgr0;
1482 uint32_t wcgr1;
1483 uint32_t wcgr2;
1484 uint32_t wcgr3;
1485} __attribute__((__aligned__(8)));
1486
Peter Maydell0d871bd2010-11-24 15:20:05 +00001487#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001488#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001489
pbrooka8c33202008-05-07 23:22:46 +00001490struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001491{
1492 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001493 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1494 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001495};
1496
pbrooka8c33202008-05-07 23:22:46 +00001497struct sigframe_v2
1498{
1499 struct target_ucontext_v2 uc;
1500 abi_ulong retcode;
1501};
1502
pbrooka745ec62008-05-06 15:36:17 +00001503struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001504{
bellardf8b0aa22007-11-11 23:03:42 +00001505 abi_ulong pinfo;
1506 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001507 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001508 struct target_ucontext_v1 uc;
1509 abi_ulong retcode;
1510};
1511
1512struct rt_sigframe_v2
1513{
1514 struct target_siginfo info;
1515 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001516 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001517};
1518
1519#define TARGET_CONFIG_CPU_32 1
1520
1521/*
1522 * For ARM syscalls, we encode the syscall number into the instruction.
1523 */
1524#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1525#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1526
1527/*
1528 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1529 * need two 16-bit instructions.
1530 */
1531#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1532#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1533
blueswir1992f48a2007-10-14 16:27:31 +00001534static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001535 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1536 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1537};
1538
1539
Andreas Färber05390242012-02-25 03:37:53 +01001540static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001541{
1542 return 1;
1543}
1544
pbrooka8c33202008-05-07 23:22:46 +00001545static void
bellard43fff232003-07-09 19:31:39 +00001546setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001547 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001548{
pbrooka8c33202008-05-07 23:22:46 +00001549 __put_user(env->regs[0], &sc->arm_r0);
1550 __put_user(env->regs[1], &sc->arm_r1);
1551 __put_user(env->regs[2], &sc->arm_r2);
1552 __put_user(env->regs[3], &sc->arm_r3);
1553 __put_user(env->regs[4], &sc->arm_r4);
1554 __put_user(env->regs[5], &sc->arm_r5);
1555 __put_user(env->regs[6], &sc->arm_r6);
1556 __put_user(env->regs[7], &sc->arm_r7);
1557 __put_user(env->regs[8], &sc->arm_r8);
1558 __put_user(env->regs[9], &sc->arm_r9);
1559 __put_user(env->regs[10], &sc->arm_r10);
1560 __put_user(env->regs[11], &sc->arm_fp);
1561 __put_user(env->regs[12], &sc->arm_ip);
1562 __put_user(env->regs[13], &sc->arm_sp);
1563 __put_user(env->regs[14], &sc->arm_lr);
1564 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001565#ifdef TARGET_CONFIG_CPU_32
pbrooka8c33202008-05-07 23:22:46 +00001566 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001567#endif
1568
pbrooka8c33202008-05-07 23:22:46 +00001569 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1570 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1571 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1572 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001573}
1574
bellard579a97f2007-11-11 14:26:47 +00001575static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001576get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001577{
1578 unsigned long sp = regs->regs[13];
1579
bellard43fff232003-07-09 19:31:39 +00001580 /*
1581 * This is the X/Open sanctioned signal stack switching.
1582 */
pbrook624f7972008-05-31 16:11:38 +00001583 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
thsa04e1342007-09-27 13:57:58 +00001584 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
bellard43fff232003-07-09 19:31:39 +00001585 /*
1586 * ATPCS B01 mandates 8-byte alignment
1587 */
bellard579a97f2007-11-11 14:26:47 +00001588 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001589}
1590
Riku Voipio0188fad2014-04-23 13:34:15 +03001591static void
Andreas Färber05390242012-02-25 03:37:53 +01001592setup_return(CPUARMState *env, struct target_sigaction *ka,
bellardf8b0aa22007-11-11 23:03:42 +00001593 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001594{
pbrook624f7972008-05-31 16:11:38 +00001595 abi_ulong handler = ka->_sa_handler;
blueswir1992f48a2007-10-14 16:27:31 +00001596 abi_ulong retcode;
pbrook75b680e2008-03-21 16:07:30 +00001597 int thumb = handler & 1;
Peter Maydell964413d2011-01-14 20:39:19 +01001598 uint32_t cpsr = cpsr_read(env);
1599
1600 cpsr &= ~CPSR_IT;
1601 if (thumb) {
1602 cpsr |= CPSR_T;
1603 } else {
1604 cpsr &= ~CPSR_T;
1605 }
bellard43fff232003-07-09 19:31:39 +00001606
pbrook624f7972008-05-31 16:11:38 +00001607 if (ka->sa_flags & TARGET_SA_RESTORER) {
1608 retcode = ka->sa_restorer;
bellard43fff232003-07-09 19:31:39 +00001609 } else {
1610 unsigned int idx = thumb;
1611
pbrook624f7972008-05-31 16:11:38 +00001612 if (ka->sa_flags & TARGET_SA_SIGINFO)
bellard43fff232003-07-09 19:31:39 +00001613 idx += 2;
1614
Riku Voipio0188fad2014-04-23 13:34:15 +03001615 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001616
bellardf8b0aa22007-11-11 23:03:42 +00001617 retcode = rc_addr + thumb;
bellard43fff232003-07-09 19:31:39 +00001618 }
1619
1620 env->regs[0] = usig;
bellardf8b0aa22007-11-11 23:03:42 +00001621 env->regs[13] = frame_addr;
bellard43fff232003-07-09 19:31:39 +00001622 env->regs[14] = retcode;
1623 env->regs[15] = handler & (thumb ? ~1 : ~3);
Peter Maydell964413d2011-01-14 20:39:19 +01001624 cpsr_write(env, cpsr, 0xffffffff);
bellard43fff232003-07-09 19:31:39 +00001625}
1626
Andreas Färber05390242012-02-25 03:37:53 +01001627static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001628{
1629 int i;
1630 struct target_vfp_sigframe *vfpframe;
1631 vfpframe = (struct target_vfp_sigframe *)regspace;
1632 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1633 __put_user(sizeof(*vfpframe), &vfpframe->size);
1634 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001635 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001636 }
1637 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1638 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1639 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1640 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1641 return (abi_ulong*)(vfpframe+1);
1642}
1643
Andreas Färber05390242012-02-25 03:37:53 +01001644static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1645 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001646{
1647 int i;
1648 struct target_iwmmxt_sigframe *iwmmxtframe;
1649 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1650 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1651 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1652 for (i = 0; i < 16; i++) {
1653 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1654 }
1655 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1656 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1657 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1658 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1659 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1660 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1661 return (abi_ulong*)(iwmmxtframe+1);
1662}
1663
pbrooka8c33202008-05-07 23:22:46 +00001664static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001665 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001666{
pbrooka8c33202008-05-07 23:22:46 +00001667 struct target_sigaltstack stack;
1668 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001669 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001670
1671 /* Clear all the bits of the ucontext we don't use. */
1672 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1673
1674 memset(&stack, 0, sizeof(stack));
1675 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1676 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1677 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1678 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1679
1680 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001681 /* Save coprocessor signal frame. */
1682 regspace = uc->tuc_regspace;
1683 if (arm_feature(env, ARM_FEATURE_VFP)) {
1684 regspace = setup_sigframe_v2_vfp(regspace, env);
1685 }
Peter Maydell08e11252010-11-24 15:20:07 +00001686 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1687 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1688 }
1689
Peter Maydell0d871bd2010-11-24 15:20:05 +00001690 /* Write terminating magic word */
1691 __put_user(0, regspace);
1692
pbrooka8c33202008-05-07 23:22:46 +00001693 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1694 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1695 }
1696}
1697
1698/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001699static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001700 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001701{
1702 struct sigframe_v1 *frame;
bellard579a97f2007-11-11 14:26:47 +00001703 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00001704 int i;
bellard43fff232003-07-09 19:31:39 +00001705
bellard579a97f2007-11-11 14:26:47 +00001706 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1707 return;
1708
pbrooka8c33202008-05-07 23:22:46 +00001709 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00001710
Riku Voipio0188fad2014-04-23 13:34:15 +03001711 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1712 __put_user(set->sig[i], &frame->extramask[i - 1]);
1713 }
bellard43fff232003-07-09 19:31:39 +00001714
pbrooka8c33202008-05-07 23:22:46 +00001715 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1716 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00001717
bellard579a97f2007-11-11 14:26:47 +00001718 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001719}
1720
pbrook624f7972008-05-31 16:11:38 +00001721static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001722 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001723{
1724 struct sigframe_v2 *frame;
1725 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1726
1727 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1728 return;
1729
1730 setup_sigframe_v2(&frame->uc, set, regs);
1731
1732 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1733 frame_addr + offsetof(struct sigframe_v2, retcode));
1734
1735 unlock_user_struct(frame, frame_addr, 1);
1736}
1737
pbrook624f7972008-05-31 16:11:38 +00001738static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001739 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001740{
1741 if (get_osversion() >= 0x020612) {
1742 setup_frame_v2(usig, ka, set, regs);
1743 } else {
1744 setup_frame_v1(usig, ka, set, regs);
1745 }
bellard43fff232003-07-09 19:31:39 +00001746}
1747
bellard579a97f2007-11-11 14:26:47 +00001748/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001749static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001750 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001751 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001752{
pbrooka745ec62008-05-06 15:36:17 +00001753 struct rt_sigframe_v1 *frame;
bellard579a97f2007-11-11 14:26:47 +00001754 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
thsa04e1342007-09-27 13:57:58 +00001755 struct target_sigaltstack stack;
pbrooka8c33202008-05-07 23:22:46 +00001756 int i;
bellardf8b0aa22007-11-11 23:03:42 +00001757 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00001758
bellard579a97f2007-11-11 14:26:47 +00001759 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
bellardedf779f2004-02-22 13:40:13 +00001760 return /* 1 */;
1761
pbrooka745ec62008-05-06 15:36:17 +00001762 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
pbrooka8c33202008-05-07 23:22:46 +00001763 __put_user(info_addr, &frame->pinfo);
pbrooka745ec62008-05-06 15:36:17 +00001764 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
pbrooka8c33202008-05-07 23:22:46 +00001765 __put_user(uc_addr, &frame->puc);
Peter Maydellf6c7a052015-01-08 12:19:48 +00001766 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00001767
1768 /* Clear all the bits of the ucontext we don't use. */
pbrooka745ec62008-05-06 15:36:17 +00001769 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00001770
thsa04e1342007-09-27 13:57:58 +00001771 memset(&stack, 0, sizeof(stack));
1772 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1773 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1774 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
bellard775b58d2007-11-11 16:22:17 +00001775 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00001776
pbrooka8c33202008-05-07 23:22:46 +00001777 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
bellard92319442004-06-19 16:58:13 +00001778 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03001779 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
bellard92319442004-06-19 16:58:13 +00001780 }
bellard43fff232003-07-09 19:31:39 +00001781
pbrooka8c33202008-05-07 23:22:46 +00001782 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1783 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001784
pbrooka8c33202008-05-07 23:22:46 +00001785 env->regs[1] = info_addr;
1786 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001787
pbrooka745ec62008-05-06 15:36:17 +00001788 unlock_user_struct(frame, frame_addr, 1);
pbrooka745ec62008-05-06 15:36:17 +00001789}
1790
pbrook624f7972008-05-31 16:11:38 +00001791static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001792 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001793 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001794{
1795 struct rt_sigframe_v2 *frame;
1796 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
pbrooka745ec62008-05-06 15:36:17 +00001797 abi_ulong info_addr, uc_addr;
1798
1799 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1800 return /* 1 */;
1801
1802 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1803 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
Peter Maydellf6c7a052015-01-08 12:19:48 +00001804 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00001805
pbrooka8c33202008-05-07 23:22:46 +00001806 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00001807
pbrooka8c33202008-05-07 23:22:46 +00001808 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1809 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001810
pbrooka8c33202008-05-07 23:22:46 +00001811 env->regs[1] = info_addr;
1812 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001813
bellard579a97f2007-11-11 14:26:47 +00001814 unlock_user_struct(frame, frame_addr, 1);
bellard43fff232003-07-09 19:31:39 +00001815}
1816
pbrook624f7972008-05-31 16:11:38 +00001817static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001818 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001819 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001820{
1821 if (get_osversion() >= 0x020612) {
1822 setup_rt_frame_v2(usig, ka, info, set, env);
1823 } else {
1824 setup_rt_frame_v1(usig, ka, info, set, env);
1825 }
1826}
1827
bellard43fff232003-07-09 19:31:39 +00001828static int
Andreas Färber05390242012-02-25 03:37:53 +01001829restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00001830{
1831 int err = 0;
bellardb5ff1b32005-11-26 10:38:39 +00001832 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00001833
Riku Voipio1d8b5122014-04-23 10:26:05 +03001834 __get_user(env->regs[0], &sc->arm_r0);
1835 __get_user(env->regs[1], &sc->arm_r1);
1836 __get_user(env->regs[2], &sc->arm_r2);
1837 __get_user(env->regs[3], &sc->arm_r3);
1838 __get_user(env->regs[4], &sc->arm_r4);
1839 __get_user(env->regs[5], &sc->arm_r5);
1840 __get_user(env->regs[6], &sc->arm_r6);
1841 __get_user(env->regs[7], &sc->arm_r7);
1842 __get_user(env->regs[8], &sc->arm_r8);
1843 __get_user(env->regs[9], &sc->arm_r9);
1844 __get_user(env->regs[10], &sc->arm_r10);
1845 __get_user(env->regs[11], &sc->arm_fp);
1846 __get_user(env->regs[12], &sc->arm_ip);
1847 __get_user(env->regs[13], &sc->arm_sp);
1848 __get_user(env->regs[14], &sc->arm_lr);
1849 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001850#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03001851 __get_user(cpsr, &sc->arm_cpsr);
pbrook75b680e2008-03-21 16:07:30 +00001852 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
bellard43fff232003-07-09 19:31:39 +00001853#endif
1854
1855 err |= !valid_user_regs(env);
1856
1857 return err;
1858}
1859
Andreas Färber05390242012-02-25 03:37:53 +01001860static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001861{
bellardf8b0aa22007-11-11 23:03:42 +00001862 abi_ulong frame_addr;
Peter Maydell978fae92013-07-29 12:00:32 +01001863 struct sigframe_v1 *frame = NULL;
Anthony Liguoric227f092009-10-01 16:12:16 -05001864 target_sigset_t set;
bellard43fff232003-07-09 19:31:39 +00001865 sigset_t host_set;
bellard92319442004-06-19 16:58:13 +00001866 int i;
bellard43fff232003-07-09 19:31:39 +00001867
1868 /*
1869 * Since we stacked the signal on a 64-bit boundary,
1870 * then 'sp' should be word aligned here. If it's
1871 * not, then the user is trying to mess with us.
1872 */
bellardf8b0aa22007-11-11 23:03:42 +00001873 frame_addr = env->regs[13];
Peter Maydell978fae92013-07-29 12:00:32 +01001874 if (frame_addr & 7) {
1875 goto badframe;
1876 }
1877
bellardf8b0aa22007-11-11 23:03:42 +00001878 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1879 goto badframe;
bellard43fff232003-07-09 19:31:39 +00001880
Riku Voipiof5f601a2014-04-23 13:00:17 +03001881 __get_user(set.sig[0], &frame->sc.oldmask);
1882 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1883 __get_user(set.sig[i], &frame->extramask[i - 1]);
1884 }
bellard43fff232003-07-09 19:31:39 +00001885
bellard92319442004-06-19 16:58:13 +00001886 target_to_host_sigset_internal(&host_set, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00001887 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard43fff232003-07-09 19:31:39 +00001888
1889 if (restore_sigcontext(env, &frame->sc))
1890 goto badframe;
1891
1892#if 0
1893 /* Send SIGTRAP if we're single-stepping */
1894 if (ptrace_cancel_bpt(current))
1895 send_sig(SIGTRAP, current, 1);
1896#endif
bellardf8b0aa22007-11-11 23:03:42 +00001897 unlock_user_struct(frame, frame_addr, 0);
1898 return env->regs[0];
bellard43fff232003-07-09 19:31:39 +00001899
1900badframe:
Riku Voipio66393fb2009-12-04 15:16:32 +02001901 force_sig(TARGET_SIGSEGV /* , current */);
bellard43fff232003-07-09 19:31:39 +00001902 return 0;
1903}
1904
Andreas Färber05390242012-02-25 03:37:53 +01001905static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00001906{
1907 int i;
1908 abi_ulong magic, sz;
1909 uint32_t fpscr, fpexc;
1910 struct target_vfp_sigframe *vfpframe;
1911 vfpframe = (struct target_vfp_sigframe *)regspace;
1912
1913 __get_user(magic, &vfpframe->magic);
1914 __get_user(sz, &vfpframe->size);
1915 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1916 return 0;
1917 }
1918 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001919 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00001920 }
1921 __get_user(fpscr, &vfpframe->ufp.fpscr);
1922 vfp_set_fpscr(env, fpscr);
1923 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1924 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1925 * and the exception flag is cleared
1926 */
1927 fpexc |= (1 << 30);
1928 fpexc &= ~((1 << 31) | (1 << 28));
1929 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1930 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1931 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1932 return (abi_ulong*)(vfpframe + 1);
1933}
1934
Andreas Färber05390242012-02-25 03:37:53 +01001935static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
1936 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00001937{
1938 int i;
1939 abi_ulong magic, sz;
1940 struct target_iwmmxt_sigframe *iwmmxtframe;
1941 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1942
1943 __get_user(magic, &iwmmxtframe->magic);
1944 __get_user(sz, &iwmmxtframe->size);
1945 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
1946 return 0;
1947 }
1948 for (i = 0; i < 16; i++) {
1949 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1950 }
1951 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1952 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1953 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1954 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1955 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1956 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1957 return (abi_ulong*)(iwmmxtframe + 1);
1958}
1959
Andreas Färber05390242012-02-25 03:37:53 +01001960static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
pbrooka8c33202008-05-07 23:22:46 +00001961 struct target_ucontext_v2 *uc)
1962{
1963 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00001964 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001965
1966 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001967 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
pbrooka8c33202008-05-07 23:22:46 +00001968
1969 if (restore_sigcontext(env, &uc->tuc_mcontext))
1970 return 1;
1971
Peter Maydell5f9099d2010-11-24 15:20:06 +00001972 /* Restore coprocessor signal frame */
1973 regspace = uc->tuc_regspace;
1974 if (arm_feature(env, ARM_FEATURE_VFP)) {
1975 regspace = restore_sigframe_v2_vfp(env, regspace);
1976 if (!regspace) {
1977 return 1;
1978 }
1979 }
Peter Maydella59d69d2010-11-24 15:20:08 +00001980 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1981 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
1982 if (!regspace) {
1983 return 1;
1984 }
1985 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00001986
pbrooka8c33202008-05-07 23:22:46 +00001987 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1988 return 1;
1989
1990#if 0
1991 /* Send SIGTRAP if we're single-stepping */
1992 if (ptrace_cancel_bpt(current))
1993 send_sig(SIGTRAP, current, 1);
1994#endif
1995
1996 return 0;
1997}
1998
Andreas Färber05390242012-02-25 03:37:53 +01001999static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002000{
2001 abi_ulong frame_addr;
Peter Maydell978fae92013-07-29 12:00:32 +01002002 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002003
2004 /*
2005 * Since we stacked the signal on a 64-bit boundary,
2006 * then 'sp' should be word aligned here. If it's
2007 * not, then the user is trying to mess with us.
2008 */
pbrooka8c33202008-05-07 23:22:46 +00002009 frame_addr = env->regs[13];
Peter Maydell978fae92013-07-29 12:00:32 +01002010 if (frame_addr & 7) {
2011 goto badframe;
2012 }
2013
pbrooka8c33202008-05-07 23:22:46 +00002014 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2015 goto badframe;
2016
2017 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
2018 goto badframe;
2019
2020 unlock_user_struct(frame, frame_addr, 0);
2021 return env->regs[0];
2022
2023badframe:
2024 unlock_user_struct(frame, frame_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002025 force_sig(TARGET_SIGSEGV /* , current */);
pbrooka8c33202008-05-07 23:22:46 +00002026 return 0;
2027}
2028
Andreas Färber05390242012-02-25 03:37:53 +01002029long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002030{
2031 if (get_osversion() >= 0x020612) {
2032 return do_sigreturn_v2(env);
2033 } else {
2034 return do_sigreturn_v1(env);
2035 }
2036}
2037
Andreas Färber05390242012-02-25 03:37:53 +01002038static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002039{
bellardf8b0aa22007-11-11 23:03:42 +00002040 abi_ulong frame_addr;
Peter Maydell978fae92013-07-29 12:00:32 +01002041 struct rt_sigframe_v1 *frame = NULL;
bellard43fff232003-07-09 19:31:39 +00002042 sigset_t host_set;
2043
2044 /*
2045 * Since we stacked the signal on a 64-bit boundary,
2046 * then 'sp' should be word aligned here. If it's
2047 * not, then the user is trying to mess with us.
2048 */
bellardf8b0aa22007-11-11 23:03:42 +00002049 frame_addr = env->regs[13];
Peter Maydell978fae92013-07-29 12:00:32 +01002050 if (frame_addr & 7) {
2051 goto badframe;
2052 }
2053
bellardf8b0aa22007-11-11 23:03:42 +00002054 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2055 goto badframe;
bellard43fff232003-07-09 19:31:39 +00002056
bellardb8076a72005-04-07 22:20:31 +00002057 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00002058 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard43fff232003-07-09 19:31:39 +00002059
bellardb8076a72005-04-07 22:20:31 +00002060 if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
bellard43fff232003-07-09 19:31:39 +00002061 goto badframe;
2062
pbrooka745ec62008-05-06 15:36:17 +00002063 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 +00002064 goto badframe;
2065
bellard43fff232003-07-09 19:31:39 +00002066#if 0
2067 /* Send SIGTRAP if we're single-stepping */
2068 if (ptrace_cancel_bpt(current))
2069 send_sig(SIGTRAP, current, 1);
2070#endif
bellardf8b0aa22007-11-11 23:03:42 +00002071 unlock_user_struct(frame, frame_addr, 0);
bellard43fff232003-07-09 19:31:39 +00002072 return env->regs[0];
2073
2074badframe:
bellardf8b0aa22007-11-11 23:03:42 +00002075 unlock_user_struct(frame, frame_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002076 force_sig(TARGET_SIGSEGV /* , current */);
bellard43fff232003-07-09 19:31:39 +00002077 return 0;
2078}
2079
Andreas Färber05390242012-02-25 03:37:53 +01002080static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002081{
2082 abi_ulong frame_addr;
Peter Maydell978fae92013-07-29 12:00:32 +01002083 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002084
2085 /*
2086 * Since we stacked the signal on a 64-bit boundary,
2087 * then 'sp' should be word aligned here. If it's
2088 * not, then the user is trying to mess with us.
2089 */
pbrooka745ec62008-05-06 15:36:17 +00002090 frame_addr = env->regs[13];
Peter Maydell978fae92013-07-29 12:00:32 +01002091 if (frame_addr & 7) {
2092 goto badframe;
2093 }
2094
pbrooka745ec62008-05-06 15:36:17 +00002095 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2096 goto badframe;
2097
pbrooka8c33202008-05-07 23:22:46 +00002098 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
2099 goto badframe;
pbrooka745ec62008-05-06 15:36:17 +00002100
pbrooka745ec62008-05-06 15:36:17 +00002101 unlock_user_struct(frame, frame_addr, 0);
2102 return env->regs[0];
2103
2104badframe:
2105 unlock_user_struct(frame, frame_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002106 force_sig(TARGET_SIGSEGV /* , current */);
pbrooka745ec62008-05-06 15:36:17 +00002107 return 0;
2108}
2109
Andreas Färber05390242012-02-25 03:37:53 +01002110long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002111{
2112 if (get_osversion() >= 0x020612) {
2113 return do_rt_sigreturn_v2(env);
2114 } else {
2115 return do_rt_sigreturn_v1(env);
2116 }
2117}
2118
bellard6d5e2162004-09-30 22:04:13 +00002119#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002120
bellard6d5e2162004-09-30 22:04:13 +00002121#define __SUNOS_MAXWIN 31
2122
2123/* This is what SunOS does, so shall I. */
2124struct target_sigcontext {
blueswir1992f48a2007-10-14 16:27:31 +00002125 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002126
blueswir1992f48a2007-10-14 16:27:31 +00002127 abi_ulong sigc_mask; /* sigmask to restore */
2128 abi_ulong sigc_sp; /* stack pointer */
2129 abi_ulong sigc_pc; /* program counter */
2130 abi_ulong sigc_npc; /* next program counter */
2131 abi_ulong sigc_psr; /* for condition codes etc */
2132 abi_ulong sigc_g1; /* User uses these two registers */
2133 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002134
2135 /* Now comes information regarding the users window set
2136 * at the time of the signal.
2137 */
blueswir1992f48a2007-10-14 16:27:31 +00002138 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002139
2140 /* stack ptrs for each regwin buf */
2141 char *sigc_spbuf[__SUNOS_MAXWIN];
2142
2143 /* Windows to restore after signal */
2144 struct {
blueswir1992f48a2007-10-14 16:27:31 +00002145 abi_ulong locals[8];
2146 abi_ulong ins[8];
bellard6d5e2162004-09-30 22:04:13 +00002147 } sigc_wbuf[__SUNOS_MAXWIN];
2148};
2149/* A Sparc stack frame */
2150struct sparc_stackf {
blueswir1992f48a2007-10-14 16:27:31 +00002151 abi_ulong locals[8];
Peter Maydelle321c342011-02-01 15:54:52 +00002152 abi_ulong ins[8];
2153 /* It's simpler to treat fp and callers_pc as elements of ins[]
2154 * since we never need to access them ourselves.
2155 */
bellard6d5e2162004-09-30 22:04:13 +00002156 char *structptr;
blueswir1992f48a2007-10-14 16:27:31 +00002157 abi_ulong xargs[6];
2158 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002159};
2160
2161typedef struct {
2162 struct {
blueswir1992f48a2007-10-14 16:27:31 +00002163 abi_ulong psr;
2164 abi_ulong pc;
2165 abi_ulong npc;
2166 abi_ulong y;
2167 abi_ulong u_regs[16]; /* globals and ins */
bellard6d5e2162004-09-30 22:04:13 +00002168 } si_regs;
2169 int si_mask;
2170} __siginfo_t;
2171
2172typedef struct {
Blue Swirl8954bae2012-07-30 15:29:11 +00002173 abi_ulong si_float_regs[32];
bellard6d5e2162004-09-30 22:04:13 +00002174 unsigned long si_fsr;
2175 unsigned long si_fpqdepth;
2176 struct {
2177 unsigned long *insn_addr;
2178 unsigned long insn;
2179 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002180} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002181
2182
2183struct target_signal_frame {
2184 struct sparc_stackf ss;
2185 __siginfo_t info;
bellardf8b0aa22007-11-11 23:03:42 +00002186 abi_ulong fpu_save;
blueswir1992f48a2007-10-14 16:27:31 +00002187 abi_ulong insns[2] __attribute__ ((aligned (8)));
2188 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2189 abi_ulong extra_size; /* Should be 0 */
Anthony Liguoric227f092009-10-01 16:12:16 -05002190 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002191};
2192struct target_rt_signal_frame {
2193 struct sparc_stackf ss;
2194 siginfo_t info;
blueswir1992f48a2007-10-14 16:27:31 +00002195 abi_ulong regs[20];
bellard6d5e2162004-09-30 22:04:13 +00002196 sigset_t mask;
bellardf8b0aa22007-11-11 23:03:42 +00002197 abi_ulong fpu_save;
bellard6d5e2162004-09-30 22:04:13 +00002198 unsigned int insns[2];
2199 stack_t stack;
2200 unsigned int extra_size; /* Should be 0 */
Anthony Liguoric227f092009-10-01 16:12:16 -05002201 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002202};
2203
bellarde80cfcf2004-12-19 23:18:01 +00002204#define UREG_O0 16
2205#define UREG_O6 22
2206#define UREG_I0 0
2207#define UREG_I1 1
2208#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002209#define UREG_I3 3
2210#define UREG_I4 4
2211#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002212#define UREG_I6 6
2213#define UREG_I7 7
2214#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002215#define UREG_FP UREG_I6
2216#define UREG_SP UREG_O6
2217
pbrook624f7972008-05-31 16:11:38 +00002218static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002219 CPUSPARCState *env,
2220 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002221{
bellard459a4012007-11-11 19:45:10 +00002222 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002223
2224 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002225
2226 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00002227 if (sa->sa_flags & TARGET_SA_ONSTACK) {
thsa04e1342007-09-27 13:57:58 +00002228 if (!on_sig_stack(sp)
2229 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
2230 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
bellard6d5e2162004-09-30 22:04:13 +00002231 }
bellard459a4012007-11-11 19:45:10 +00002232 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002233}
2234
2235static int
Andreas Färber05390242012-02-25 03:37:53 +01002236setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002237{
2238 int err = 0, i;
2239
Riku Voipio1d8b5122014-04-23 10:26:05 +03002240 __put_user(env->psr, &si->si_regs.psr);
2241 __put_user(env->pc, &si->si_regs.pc);
2242 __put_user(env->npc, &si->si_regs.npc);
2243 __put_user(env->y, &si->si_regs.y);
bellarda315a142005-01-30 22:59:18 +00002244 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002245 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
bellard6d5e2162004-09-30 22:04:13 +00002246 }
bellarda315a142005-01-30 22:59:18 +00002247 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002248 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
bellard6d5e2162004-09-30 22:04:13 +00002249 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002250 __put_user(mask, &si->si_mask);
bellard6d5e2162004-09-30 22:04:13 +00002251 return err;
2252}
bellarde80cfcf2004-12-19 23:18:01 +00002253
bellard80a9d032005-01-03 23:31:27 +00002254#if 0
bellard6d5e2162004-09-30 22:04:13 +00002255static int
2256setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002257 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002258{
2259 int err = 0;
2260
Riku Voipio1d8b5122014-04-23 10:26:05 +03002261 __put_user(mask, &sc->sigc_mask);
2262 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2263 __put_user(env->pc, &sc->sigc_pc);
2264 __put_user(env->npc, &sc->sigc_npc);
2265 __put_user(env->psr, &sc->sigc_psr);
2266 __put_user(env->gregs[1], &sc->sigc_g1);
2267 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002268
2269 return err;
2270}
bellard80a9d032005-01-03 23:31:27 +00002271#endif
bellard6d5e2162004-09-30 22:04:13 +00002272#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2273
pbrook624f7972008-05-31 16:11:38 +00002274static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002275 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002276{
bellard459a4012007-11-11 19:45:10 +00002277 abi_ulong sf_addr;
bellard6d5e2162004-09-30 22:04:13 +00002278 struct target_signal_frame *sf;
2279 int sigframe_size, err, i;
2280
2281 /* 1. Make sure everything is clean */
2282 //synchronize_user_stack();
2283
2284 sigframe_size = NF_ALIGNEDSZ;
bellard459a4012007-11-11 19:45:10 +00002285 sf_addr = get_sigframe(ka, env, sigframe_size);
bellard6d5e2162004-09-30 22:04:13 +00002286
bellard459a4012007-11-11 19:45:10 +00002287 sf = lock_user(VERIFY_WRITE, sf_addr,
2288 sizeof(struct target_signal_frame), 0);
2289 if (!sf)
2290 goto sigsegv;
2291
bellarde80cfcf2004-12-19 23:18:01 +00002292 //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 +00002293#if 0
2294 if (invalid_frame_pointer(sf, sigframe_size))
2295 goto sigill_and_return;
2296#endif
2297 /* 2. Save the current process state */
2298 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002299 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002300
Riku Voipio1d8b5122014-04-23 10:26:05 +03002301 //save_fpu_state(regs, &sf->fpu_state);
2302 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002303
Riku Voipio1d8b5122014-04-23 10:26:05 +03002304 __put_user(set->sig[0], &sf->info.si_mask);
bellard6d5e2162004-09-30 22:04:13 +00002305 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002306 __put_user(set->sig[i + 1], &sf->extramask[i]);
bellard6d5e2162004-09-30 22:04:13 +00002307 }
2308
bellarda315a142005-01-30 22:59:18 +00002309 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002310 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
bellard6d5e2162004-09-30 22:04:13 +00002311 }
bellarda315a142005-01-30 22:59:18 +00002312 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002313 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
bellard6d5e2162004-09-30 22:04:13 +00002314 }
bellard6d5e2162004-09-30 22:04:13 +00002315 if (err)
2316 goto sigsegv;
2317
2318 /* 3. signal handler back-trampoline and parameters */
bellard459a4012007-11-11 19:45:10 +00002319 env->regwptr[UREG_FP] = sf_addr;
bellard6d5e2162004-09-30 22:04:13 +00002320 env->regwptr[UREG_I0] = sig;
bellard459a4012007-11-11 19:45:10 +00002321 env->regwptr[UREG_I1] = sf_addr +
2322 offsetof(struct target_signal_frame, info);
2323 env->regwptr[UREG_I2] = sf_addr +
2324 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002325
2326 /* 4. signal handler */
pbrook624f7972008-05-31 16:11:38 +00002327 env->pc = ka->_sa_handler;
bellard6d5e2162004-09-30 22:04:13 +00002328 env->npc = (env->pc + 4);
2329 /* 5. return to kernel instructions */
pbrook624f7972008-05-31 16:11:38 +00002330 if (ka->sa_restorer)
2331 env->regwptr[UREG_I7] = ka->sa_restorer;
bellard6d5e2162004-09-30 22:04:13 +00002332 else {
bellard775b58d2007-11-11 16:22:17 +00002333 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002334
2335 env->regwptr[UREG_I7] = sf_addr +
2336 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002337
2338 /* mov __NR_sigreturn, %g1 */
bellard775b58d2007-11-11 16:22:17 +00002339 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002340 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002341
2342 /* t 0x10 */
bellard775b58d2007-11-11 16:22:17 +00002343 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002344 __put_user(val32, &sf->insns[1]);
bellard6d5e2162004-09-30 22:04:13 +00002345 if (err)
2346 goto sigsegv;
2347
2348 /* Flush instruction space. */
2349 //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
Peter Crosthwaitebbd77c12015-06-23 19:31:15 -07002350 // tb_flush(CPU(sparc_env_get_cpu(env)));
bellard6d5e2162004-09-30 22:04:13 +00002351 }
bellard459a4012007-11-11 19:45:10 +00002352 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
bellard6d5e2162004-09-30 22:04:13 +00002353 return;
bellard459a4012007-11-11 19:45:10 +00002354#if 0
2355sigill_and_return:
bellard6d5e2162004-09-30 22:04:13 +00002356 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002357#endif
bellard6d5e2162004-09-30 22:04:13 +00002358sigsegv:
bellarde80cfcf2004-12-19 23:18:01 +00002359 //fprintf(stderr, "force_sig\n");
bellard459a4012007-11-11 19:45:10 +00002360 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
bellard6d5e2162004-09-30 22:04:13 +00002361 force_sig(TARGET_SIGSEGV);
2362}
bellard6d5e2162004-09-30 22:04:13 +00002363
pbrook624f7972008-05-31 16:11:38 +00002364static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002365 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002366 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002367{
2368 fprintf(stderr, "setup_rt_frame: not implemented\n");
2369}
2370
Andreas Färber05390242012-02-25 03:37:53 +01002371long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002372{
bellardf8b0aa22007-11-11 23:03:42 +00002373 abi_ulong sf_addr;
bellard6d5e2162004-09-30 22:04:13 +00002374 struct target_signal_frame *sf;
bellarde80cfcf2004-12-19 23:18:01 +00002375 uint32_t up_psr, pc, npc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002376 target_sigset_t set;
bellarde80cfcf2004-12-19 23:18:01 +00002377 sigset_t host_set;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002378 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002379
bellardf8b0aa22007-11-11 23:03:42 +00002380 sf_addr = env->regwptr[UREG_FP];
2381 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
2382 goto segv_and_exit;
bellard80a9d032005-01-03 23:31:27 +00002383#if 0
bellarde80cfcf2004-12-19 23:18:01 +00002384 fprintf(stderr, "sigreturn\n");
2385 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 +00002386#endif
bellarde80cfcf2004-12-19 23:18:01 +00002387 //cpu_dump_state(env, stderr, fprintf, 0);
bellard6d5e2162004-09-30 22:04:13 +00002388
2389 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002390
bellardf8b0aa22007-11-11 23:03:42 +00002391 if (sf_addr & 3)
bellard6d5e2162004-09-30 22:04:13 +00002392 goto segv_and_exit;
2393
Riku Voipio1d8b5122014-04-23 10:26:05 +03002394 __get_user(pc, &sf->info.si_regs.pc);
2395 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002396
bellard6d5e2162004-09-30 22:04:13 +00002397 if ((pc | npc) & 3)
2398 goto segv_and_exit;
2399
2400 /* 2. Restore the state */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002401 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002402
bellard6d5e2162004-09-30 22:04:13 +00002403 /* User can only change condition codes and FPU enabling in %psr. */
bellarda315a142005-01-30 22:59:18 +00002404 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2405 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
2406
2407 env->pc = pc;
2408 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002409 __get_user(env->y, &sf->info.si_regs.y);
bellarda315a142005-01-30 22:59:18 +00002410 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002411 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
bellarde80cfcf2004-12-19 23:18:01 +00002412 }
bellarda315a142005-01-30 22:59:18 +00002413 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002414 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
bellarde80cfcf2004-12-19 23:18:01 +00002415 }
bellard6d5e2162004-09-30 22:04:13 +00002416
Peter Maydell2aec3a22011-06-16 17:37:14 +01002417 /* FIXME: implement FPU save/restore:
2418 * __get_user(fpu_save, &sf->fpu_save);
2419 * if (fpu_save)
2420 * err |= restore_fpu_state(env, fpu_save);
2421 */
bellard6d5e2162004-09-30 22:04:13 +00002422
2423 /* This is pretty much atomic, no amount locking would prevent
2424 * the races which exist anyways.
2425 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002426 __get_user(set.sig[0], &sf->info.si_mask);
bellarde80cfcf2004-12-19 23:18:01 +00002427 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002428 __get_user(set.sig[i], &sf->extramask[i - 1]);
bellarde80cfcf2004-12-19 23:18:01 +00002429 }
2430
2431 target_to_host_sigset_internal(&host_set, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002432 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard6d5e2162004-09-30 22:04:13 +00002433
2434 if (err)
2435 goto segv_and_exit;
bellardf8b0aa22007-11-11 23:03:42 +00002436 unlock_user_struct(sf, sf_addr, 0);
bellard6d5e2162004-09-30 22:04:13 +00002437 return env->regwptr[0];
2438
2439segv_and_exit:
bellardf8b0aa22007-11-11 23:03:42 +00002440 unlock_user_struct(sf, sf_addr, 0);
bellard6d5e2162004-09-30 22:04:13 +00002441 force_sig(TARGET_SIGSEGV);
2442}
2443
Andreas Färber05390242012-02-25 03:37:53 +01002444long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002445{
2446 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002447 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002448}
2449
bellard459a4012007-11-11 19:45:10 +00002450#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
blueswir15bfb56b2007-10-05 17:01:51 +00002451#define MC_TSTATE 0
2452#define MC_PC 1
2453#define MC_NPC 2
2454#define MC_Y 3
2455#define MC_G1 4
2456#define MC_G2 5
2457#define MC_G3 6
2458#define MC_G4 7
2459#define MC_G5 8
2460#define MC_G6 9
2461#define MC_G7 10
2462#define MC_O0 11
2463#define MC_O1 12
2464#define MC_O2 13
2465#define MC_O3 14
2466#define MC_O4 15
2467#define MC_O5 16
2468#define MC_O6 17
2469#define MC_O7 18
2470#define MC_NGREG 19
2471
Anthony Liguoric227f092009-10-01 16:12:16 -05002472typedef abi_ulong target_mc_greg_t;
2473typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002474
2475struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002476 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002477 uint32_t mcfq_insn;
2478};
2479
2480struct target_mc_fpu {
2481 union {
2482 uint32_t sregs[32];
2483 uint64_t dregs[32];
2484 //uint128_t qregs[16];
2485 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002486 abi_ulong mcfpu_fsr;
2487 abi_ulong mcfpu_fprs;
2488 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002489 struct target_mc_fq *mcfpu_fq;
2490 unsigned char mcfpu_qcnt;
2491 unsigned char mcfpu_qentsz;
2492 unsigned char mcfpu_enab;
2493};
Anthony Liguoric227f092009-10-01 16:12:16 -05002494typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002495
2496typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002497 target_mc_gregset_t mc_gregs;
2498 target_mc_greg_t mc_fp;
2499 target_mc_greg_t mc_i7;
2500 target_mc_fpu_t mc_fpregs;
2501} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002502
2503struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002504 struct target_ucontext *tuc_link;
2505 abi_ulong tuc_flags;
2506 target_sigset_t tuc_sigmask;
2507 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002508};
2509
2510/* A V9 register window */
2511struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002512 abi_ulong locals[8];
2513 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002514};
2515
2516#define TARGET_STACK_BIAS 2047
2517
2518/* {set, get}context() needed for 64-bit SparcLinux userland. */
2519void sparc64_set_context(CPUSPARCState *env)
2520{
bellard459a4012007-11-11 19:45:10 +00002521 abi_ulong ucp_addr;
2522 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002523 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002524 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002525 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002526 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002527
bellard459a4012007-11-11 19:45:10 +00002528 ucp_addr = env->regwptr[UREG_I0];
2529 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
2530 goto do_sigsegv;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002531 grp = &ucp->tuc_mcontext.mc_gregs;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002532 __get_user(pc, &((*grp)[MC_PC]));
2533 __get_user(npc, &((*grp)[MC_NPC]));
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002534 if ((pc | npc) & 3)
blueswir15bfb56b2007-10-05 17:01:51 +00002535 goto do_sigsegv;
2536 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002537 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002538 sigset_t set;
2539
2540 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002541 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002542 } else {
bellard459a4012007-11-11 19:45:10 +00002543 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002544 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002545 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002546 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002547 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002548 }
blueswir15bfb56b2007-10-05 17:01:51 +00002549 }
2550 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002551 do_sigprocmask(SIG_SETMASK, &set, NULL);
blueswir15bfb56b2007-10-05 17:01:51 +00002552 }
2553 env->pc = pc;
2554 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002555 __get_user(env->y, &((*grp)[MC_Y]));
2556 __get_user(tstate, &((*grp)[MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002557 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002558 cpu_put_ccr(env, tstate >> 32);
2559 cpu_put_cwp64(env, tstate & 0x1f);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002560 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2561 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2562 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2563 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2564 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2565 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2566 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2567 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2568 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2569 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2570 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2571 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2572 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2573 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2574 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002575
Riku Voipio1d8b5122014-04-23 10:26:05 +03002576 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2577 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002578
bellard459a4012007-11-11 19:45:10 +00002579 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2580 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2581 abi_ulong) != 0)
2582 goto do_sigsegv;
2583 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2584 abi_ulong) != 0)
2585 goto do_sigsegv;
Peter Maydellc7b016b2011-06-16 17:37:15 +01002586 /* FIXME this does not match how the kernel handles the FPU in
2587 * its sparc64_set_context implementation. In particular the FPU
2588 * is only restored if fenab is non-zero in:
2589 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2590 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002591 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002592 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002593 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2594 for (i = 0; i < 64; i++, src++) {
2595 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002596 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002597 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002598 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002599 }
2600 }
bellard459a4012007-11-11 19:45:10 +00002601 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002602 __get_user(env->fsr,
2603 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2604 __get_user(env->gsr,
2605 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002606 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002607 return;
2608 do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002609 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002610 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002611}
2612
2613void sparc64_get_context(CPUSPARCState *env)
2614{
bellard459a4012007-11-11 19:45:10 +00002615 abi_ulong ucp_addr;
2616 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002617 target_mc_gregset_t *grp;
2618 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002619 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002620 int err;
2621 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002622 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002623 sigset_t set;
2624
bellard459a4012007-11-11 19:45:10 +00002625 ucp_addr = env->regwptr[UREG_I0];
2626 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
2627 goto do_sigsegv;
2628
Aurelien Jarno60e99242010-03-29 02:12:51 +02002629 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002630 grp = &mcp->mc_gregs;
2631
2632 /* Skip over the trap instruction, first. */
2633 env->pc = env->npc;
2634 env->npc += 4;
2635
2636 err = 0;
2637
Alex Barcelo1c275922014-03-14 14:36:55 +00002638 do_sigprocmask(0, NULL, &set);
blueswir15bfb56b2007-10-05 17:01:51 +00002639 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00002640 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002641 __put_user(target_set.sig[0],
2642 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00002643 } else {
2644 abi_ulong *src, *dst;
2645 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002646 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002647 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002648 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002649 }
blueswir15bfb56b2007-10-05 17:01:51 +00002650 if (err)
2651 goto do_sigsegv;
2652 }
2653
bellard459a4012007-11-11 19:45:10 +00002654 /* XXX: tstate must be saved properly */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002655 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2656 __put_user(env->pc, &((*grp)[MC_PC]));
2657 __put_user(env->npc, &((*grp)[MC_NPC]));
2658 __put_user(env->y, &((*grp)[MC_Y]));
2659 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2660 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2661 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2662 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2663 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2664 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2665 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2666 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2667 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2668 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2669 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2670 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2671 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2672 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2673 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002674
bellard459a4012007-11-11 19:45:10 +00002675 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2676 fp = i7 = 0;
2677 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2678 abi_ulong) != 0)
2679 goto do_sigsegv;
2680 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2681 abi_ulong) != 0)
2682 goto do_sigsegv;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002683 __put_user(fp, &(mcp->mc_fp));
2684 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002685
bellard459a4012007-11-11 19:45:10 +00002686 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002687 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2688 for (i = 0; i < 64; i++, dst++) {
2689 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002690 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002691 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002692 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002693 }
2694 }
bellard459a4012007-11-11 19:45:10 +00002695 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002696 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2697 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2698 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00002699
2700 if (err)
2701 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00002702 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00002703 return;
2704 do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002705 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02002706 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002707}
2708#endif
Richard Hendersonff970902013-02-10 10:30:42 -08002709#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00002710
Richard Hendersonff970902013-02-10 10:30:42 -08002711# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00002712struct target_sigcontext {
2713 uint32_t sc_regmask; /* Unused */
2714 uint32_t sc_status;
2715 uint64_t sc_pc;
2716 uint64_t sc_regs[32];
2717 uint64_t sc_fpregs[32];
2718 uint32_t sc_ownedfp; /* Unused */
2719 uint32_t sc_fpc_csr;
2720 uint32_t sc_fpc_eir; /* Unused */
2721 uint32_t sc_used_math;
2722 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01002723 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00002724 uint64_t sc_mdhi;
2725 uint64_t sc_mdlo;
2726 target_ulong sc_hi1; /* Was sc_cause */
2727 target_ulong sc_lo1; /* Was sc_badvaddr */
2728 target_ulong sc_hi2; /* Was sc_sigset[4] */
2729 target_ulong sc_lo2;
2730 target_ulong sc_hi3;
2731 target_ulong sc_lo3;
2732};
Richard Hendersonff970902013-02-10 10:30:42 -08002733# else /* N32 || N64 */
2734struct target_sigcontext {
2735 uint64_t sc_regs[32];
2736 uint64_t sc_fpregs[32];
2737 uint64_t sc_mdhi;
2738 uint64_t sc_hi1;
2739 uint64_t sc_hi2;
2740 uint64_t sc_hi3;
2741 uint64_t sc_mdlo;
2742 uint64_t sc_lo1;
2743 uint64_t sc_lo2;
2744 uint64_t sc_lo3;
2745 uint64_t sc_pc;
2746 uint32_t sc_fpc_csr;
2747 uint32_t sc_used_math;
2748 uint32_t sc_dsp;
2749 uint32_t sc_reserved;
2750};
2751# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00002752
2753struct sigframe {
2754 uint32_t sf_ass[4]; /* argument save space for o32 */
2755 uint32_t sf_code[2]; /* signal trampoline */
2756 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002757 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00002758};
2759
pbrook0b1bcb02009-04-21 01:41:10 +00002760struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002761 target_ulong tuc_flags;
2762 target_ulong tuc_link;
2763 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01002764 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002765 struct target_sigcontext tuc_mcontext;
2766 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00002767};
2768
2769struct target_rt_sigframe {
2770 uint32_t rs_ass[4]; /* argument save space for o32 */
2771 uint32_t rs_code[2]; /* signal trampoline */
2772 struct target_siginfo rs_info;
2773 struct target_ucontext rs_uc;
2774};
2775
bellard106ec872006-06-27 21:08:10 +00002776/* Install trampoline to jump back from signal handler */
2777static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2778{
Richard Henderson084d0492013-02-10 10:30:44 -08002779 int err = 0;
bellard106ec872006-06-27 21:08:10 +00002780
2781 /*
Richard Henderson084d0492013-02-10 10:30:44 -08002782 * Set up the return code ...
2783 *
2784 * li v0, __NR__foo_sigreturn
2785 * syscall
2786 */
bellard106ec872006-06-27 21:08:10 +00002787
Riku Voipio1d8b5122014-04-23 10:26:05 +03002788 __put_user(0x24020000 + syscall, tramp + 0);
2789 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00002790 return err;
2791}
2792
Riku Voipio41ecc722014-04-23 11:01:00 +03002793static inline void setup_sigcontext(CPUMIPSState *regs,
2794 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002795{
Richard Henderson084d0492013-02-10 10:30:44 -08002796 int i;
bellard106ec872006-06-27 21:08:10 +00002797
Riku Voipio1d8b5122014-04-23 10:26:05 +03002798 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07002799 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00002800
Richard Henderson084d0492013-02-10 10:30:44 -08002801 __put_user(0, &sc->sc_regs[0]);
2802 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002803 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002804 }
bellard106ec872006-06-27 21:08:10 +00002805
Riku Voipio1d8b5122014-04-23 10:26:05 +03002806 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2807 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002808
Richard Henderson084d0492013-02-10 10:30:44 -08002809 /* Rather than checking for dsp existence, always copy. The storage
2810 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002811 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2812 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2813 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2814 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2815 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2816 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002817 {
2818 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002819 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00002820 }
Richard Henderson084d0492013-02-10 10:30:44 -08002821
Riku Voipio1d8b5122014-04-23 10:26:05 +03002822 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08002823
2824 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002825 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00002826 }
bellard106ec872006-06-27 21:08:10 +00002827}
2828
Riku Voipio016d2e12014-04-23 11:19:48 +03002829static inline void
Andreas Färber05390242012-02-25 03:37:53 +01002830restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002831{
Richard Henderson084d0492013-02-10 10:30:44 -08002832 int i;
bellard106ec872006-06-27 21:08:10 +00002833
Riku Voipio1d8b5122014-04-23 10:26:05 +03002834 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00002835
Riku Voipio1d8b5122014-04-23 10:26:05 +03002836 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2837 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002838
Richard Henderson084d0492013-02-10 10:30:44 -08002839 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002840 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00002841 }
2842
Riku Voipio1d8b5122014-04-23 10:26:05 +03002843 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2844 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2845 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2846 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2847 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2848 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002849 {
2850 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002851 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08002852 cpu_wrdsp(dsp, 0x3ff, regs);
2853 }
2854
2855 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002856 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002857 }
bellard106ec872006-06-27 21:08:10 +00002858}
Richard Hendersonff970902013-02-10 10:30:42 -08002859
bellard106ec872006-06-27 21:08:10 +00002860/*
2861 * Determine which stack to use..
2862 */
bellard579a97f2007-11-11 14:26:47 +00002863static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002864get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00002865{
2866 unsigned long sp;
2867
2868 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00002869 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00002870
2871 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01002872 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00002873 * above the user stack, 16-bytes before the next lowest
2874 * 16 byte boundary. Try to avoid trashing it.
2875 */
2876 sp -= 32;
2877
bellard106ec872006-06-27 21:08:10 +00002878 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00002879 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00002880 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2881 }
bellard106ec872006-06-27 21:08:10 +00002882
bellard579a97f2007-11-11 14:26:47 +00002883 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00002884}
2885
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002886static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
2887{
2888 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
2889 env->hflags &= ~MIPS_HFLAG_M16;
2890 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
2891 env->active_tc.PC &= ~(target_ulong) 1;
2892 }
2893}
2894
Richard Hendersonff970902013-02-10 10:30:42 -08002895# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00002896/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002897static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01002898 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002899{
2900 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002901 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00002902 int i;
2903
bellard579a97f2007-11-11 14:26:47 +00002904 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2905 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
bellard106ec872006-06-27 21:08:10 +00002906 goto give_sigsegv;
2907
2908 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2909
Riku Voipio41ecc722014-04-23 11:01:00 +03002910 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002911
2912 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03002913 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00002914 }
2915
2916 /*
2917 * Arguments to signal handler:
2918 *
2919 * a0 = signal number
2920 * a1 = 0 (should be cause)
2921 * a2 = pointer to struct sigcontext
2922 *
2923 * $25 and PC point to the signal handler, $29 points to the
2924 * struct sigframe.
2925 */
thsb5dc7732008-06-27 10:02:35 +00002926 regs->active_tc.gpr[ 4] = sig;
2927 regs->active_tc.gpr[ 5] = 0;
2928 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2929 regs->active_tc.gpr[29] = frame_addr;
2930 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00002931 /* The original kernel code sets CP0_EPC to the handler
2932 * since it returns to userland using eret
2933 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00002934 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002935 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00002936 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00002937 return;
2938
2939give_sigsegv:
2940 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00002941}
2942
Andreas Färber05390242012-02-25 03:37:53 +01002943long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002944{
ths388bb212007-05-13 13:58:00 +00002945 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002946 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00002947 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05002948 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00002949 int i;
bellard106ec872006-06-27 21:08:10 +00002950
2951#if defined(DEBUG_SIGNAL)
ths388bb212007-05-13 13:58:00 +00002952 fprintf(stderr, "do_sigreturn\n");
bellard106ec872006-06-27 21:08:10 +00002953#endif
thsb5dc7732008-06-27 10:02:35 +00002954 frame_addr = regs->active_tc.gpr[29];
bellard579a97f2007-11-11 14:26:47 +00002955 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
bellard106ec872006-06-27 21:08:10 +00002956 goto badframe;
2957
ths388bb212007-05-13 13:58:00 +00002958 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03002959 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00002960 }
bellard106ec872006-06-27 21:08:10 +00002961
ths388bb212007-05-13 13:58:00 +00002962 target_to_host_sigset_internal(&blocked, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002963 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
bellard106ec872006-06-27 21:08:10 +00002964
Riku Voipio016d2e12014-04-23 11:19:48 +03002965 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002966
2967#if 0
ths388bb212007-05-13 13:58:00 +00002968 /*
2969 * Don't let your children do this ...
2970 */
2971 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00002972 "move\t$29, %0\n\t"
2973 "j\tsyscall_exit"
2974 :/* no outputs */
2975 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00002976 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00002977#endif
ths3b46e622007-09-17 08:09:54 +00002978
thsb5dc7732008-06-27 10:02:35 +00002979 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002980 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00002981 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00002982 * maybe a problem with nested signals ? */
2983 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00002984 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00002985
2986badframe:
ths388bb212007-05-13 13:58:00 +00002987 force_sig(TARGET_SIGSEGV/*, current*/);
2988 return 0;
bellard106ec872006-06-27 21:08:10 +00002989}
Richard Hendersonff970902013-02-10 10:30:42 -08002990# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00002991
pbrook624f7972008-05-31 16:11:38 +00002992static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002993 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002994 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00002995{
pbrook0b1bcb02009-04-21 01:41:10 +00002996 struct target_rt_sigframe *frame;
2997 abi_ulong frame_addr;
2998 int i;
2999
3000 frame_addr = get_sigframe(ka, env, sizeof(*frame));
3001 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3002 goto give_sigsegv;
3003
3004 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3005
Peter Maydellf6c7a052015-01-08 12:19:48 +00003006 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003007
Aurelien Jarno60e99242010-03-29 02:12:51 +02003008 __put_user(0, &frame->rs_uc.tuc_flags);
3009 __put_user(0, &frame->rs_uc.tuc_link);
3010 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3011 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003012 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003013 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003014
Aurelien Jarno60e99242010-03-29 02:12:51 +02003015 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003016
3017 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003018 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003019 }
3020
3021 /*
3022 * Arguments to signal handler:
3023 *
3024 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003025 * a1 = pointer to siginfo_t
pbrook0b1bcb02009-04-21 01:41:10 +00003026 * a2 = pointer to struct ucontext
3027 *
3028 * $25 and PC point to the signal handler, $29 points to the
3029 * struct sigframe.
3030 */
3031 env->active_tc.gpr[ 4] = sig;
3032 env->active_tc.gpr[ 5] = frame_addr
3033 + offsetof(struct target_rt_sigframe, rs_info);
3034 env->active_tc.gpr[ 6] = frame_addr
3035 + offsetof(struct target_rt_sigframe, rs_uc);
3036 env->active_tc.gpr[29] = frame_addr;
3037 env->active_tc.gpr[31] = frame_addr
3038 + offsetof(struct target_rt_sigframe, rs_code);
3039 /* The original kernel code sets CP0_EPC to the handler
3040 * since it returns to userland using eret
3041 * we cannot do this here, and we must set PC directly */
3042 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003043 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003044 unlock_user_struct(frame, frame_addr, 1);
3045 return;
3046
3047give_sigsegv:
3048 unlock_user_struct(frame, frame_addr, 1);
3049 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00003050}
3051
Andreas Färber05390242012-02-25 03:37:53 +01003052long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003053{
pbrook0b1bcb02009-04-21 01:41:10 +00003054 struct target_rt_sigframe *frame;
3055 abi_ulong frame_addr;
3056 sigset_t blocked;
3057
3058#if defined(DEBUG_SIGNAL)
3059 fprintf(stderr, "do_rt_sigreturn\n");
3060#endif
3061 frame_addr = env->active_tc.gpr[29];
3062 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3063 goto badframe;
3064
Aurelien Jarno60e99242010-03-29 02:12:51 +02003065 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00003066 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
pbrook0b1bcb02009-04-21 01:41:10 +00003067
Riku Voipio016d2e12014-04-23 11:19:48 +03003068 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003069
3070 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02003071 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
pbrook0b1bcb02009-04-21 01:41:10 +00003072 0, get_sp_from_cpustate(env)) == -EFAULT)
3073 goto badframe;
3074
3075 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003076 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003077 /* I am not sure this is right, but it seems to work
3078 * maybe a problem with nested signals ? */
3079 env->CP0_EPC = 0;
3080 return -TARGET_QEMU_ESIGRETURN;
3081
3082badframe:
3083 force_sig(TARGET_SIGSEGV/*, current*/);
3084 return 0;
bellard106ec872006-06-27 21:08:10 +00003085}
bellard6d5e2162004-09-30 22:04:13 +00003086
thsc3b5bc82007-12-02 06:31:25 +00003087#elif defined(TARGET_SH4)
3088
3089/*
3090 * code and data structures from linux kernel:
3091 * include/asm-sh/sigcontext.h
3092 * arch/sh/kernel/signal.c
3093 */
3094
3095struct target_sigcontext {
3096 target_ulong oldmask;
3097
3098 /* CPU registers */
3099 target_ulong sc_gregs[16];
3100 target_ulong sc_pc;
3101 target_ulong sc_pr;
3102 target_ulong sc_sr;
3103 target_ulong sc_gbr;
3104 target_ulong sc_mach;
3105 target_ulong sc_macl;
3106
3107 /* FPU registers */
3108 target_ulong sc_fpregs[16];
3109 target_ulong sc_xfpregs[16];
3110 unsigned int sc_fpscr;
3111 unsigned int sc_fpul;
3112 unsigned int sc_ownedfp;
3113};
3114
3115struct target_sigframe
3116{
3117 struct target_sigcontext sc;
3118 target_ulong extramask[TARGET_NSIG_WORDS-1];
3119 uint16_t retcode[3];
3120};
3121
3122
3123struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003124 target_ulong tuc_flags;
3125 struct target_ucontext *tuc_link;
3126 target_stack_t tuc_stack;
3127 struct target_sigcontext tuc_mcontext;
3128 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003129};
3130
3131struct target_rt_sigframe
3132{
3133 struct target_siginfo info;
3134 struct target_ucontext uc;
3135 uint16_t retcode[3];
3136};
3137
3138
3139#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3140#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3141
pbrook624f7972008-05-31 16:11:38 +00003142static abi_ulong get_sigframe(struct target_sigaction *ka,
thsc3b5bc82007-12-02 06:31:25 +00003143 unsigned long sp, size_t frame_size)
3144{
pbrook624f7972008-05-31 16:11:38 +00003145 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003146 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3147 }
3148
3149 return (sp - frame_size) & -8ul;
3150}
3151
Riku Voipio41ecc722014-04-23 11:01:00 +03003152static void setup_sigcontext(struct target_sigcontext *sc,
Andreas Färber05390242012-02-25 03:37:53 +01003153 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003154{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003155 int i;
thsc3b5bc82007-12-02 06:31:25 +00003156
Riku Voipio1d8b5122014-04-23 10:26:05 +03003157#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003158 COPY(gregs[0]); COPY(gregs[1]);
3159 COPY(gregs[2]); COPY(gregs[3]);
3160 COPY(gregs[4]); COPY(gregs[5]);
3161 COPY(gregs[6]); COPY(gregs[7]);
3162 COPY(gregs[8]); COPY(gregs[9]);
3163 COPY(gregs[10]); COPY(gregs[11]);
3164 COPY(gregs[12]); COPY(gregs[13]);
3165 COPY(gregs[14]); COPY(gregs[15]);
3166 COPY(gbr); COPY(mach);
3167 COPY(macl); COPY(pr);
3168 COPY(sr); COPY(pc);
3169#undef COPY
3170
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003171 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003172 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003173 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003174 __put_user(regs->fpscr, &sc->sc_fpscr);
3175 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003176
3177 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003178 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003179}
3180
Riku Voipio016d2e12014-04-23 11:19:48 +03003181static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003182 target_ulong *r0_p)
thsc3b5bc82007-12-02 06:31:25 +00003183{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003184 int i;
thsc3b5bc82007-12-02 06:31:25 +00003185
Riku Voipio1d8b5122014-04-23 10:26:05 +03003186#define COPY(x) __get_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003187 COPY(gregs[1]);
3188 COPY(gregs[2]); COPY(gregs[3]);
3189 COPY(gregs[4]); COPY(gregs[5]);
3190 COPY(gregs[6]); COPY(gregs[7]);
3191 COPY(gregs[8]); COPY(gregs[9]);
3192 COPY(gregs[10]); COPY(gregs[11]);
3193 COPY(gregs[12]); COPY(gregs[13]);
3194 COPY(gregs[14]); COPY(gregs[15]);
3195 COPY(gbr); COPY(mach);
3196 COPY(macl); COPY(pr);
3197 COPY(sr); COPY(pc);
3198#undef COPY
3199
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003200 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003201 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003202 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003203 __get_user(regs->fpscr, &sc->sc_fpscr);
3204 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003205
3206 regs->tra = -1; /* disable syscall checks */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003207 __get_user(*r0_p, &sc->sc_gregs[0]);
thsc3b5bc82007-12-02 06:31:25 +00003208}
3209
pbrook624f7972008-05-31 16:11:38 +00003210static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003211 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003212{
3213 struct target_sigframe *frame;
3214 abi_ulong frame_addr;
3215 int i;
3216 int err = 0;
thsc3b5bc82007-12-02 06:31:25 +00003217
3218 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3219 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3220 goto give_sigsegv;
3221
Riku Voipio41ecc722014-04-23 11:01:00 +03003222 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003223
3224 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003225 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003226 }
3227
3228 /* Set up to return from userspace. If provided, use a stub
3229 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003230 if (ka->sa_flags & TARGET_SA_RESTORER) {
3231 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003232 } else {
3233 /* Generate return code (system call to sigreturn) */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003234 __put_user(MOVW(2), &frame->retcode[0]);
3235 __put_user(TRAP_NOARG, &frame->retcode[1]);
3236 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
thsc3b5bc82007-12-02 06:31:25 +00003237 regs->pr = (unsigned long) frame->retcode;
3238 }
3239
3240 if (err)
3241 goto give_sigsegv;
3242
3243 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003244 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003245 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003246 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003247 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003248 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003249
3250 unlock_user_struct(frame, frame_addr, 1);
3251 return;
3252
3253give_sigsegv:
3254 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003255 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003256}
3257
pbrook624f7972008-05-31 16:11:38 +00003258static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003259 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003260 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003261{
3262 struct target_rt_sigframe *frame;
3263 abi_ulong frame_addr;
3264 int i;
3265 int err = 0;
thsc3b5bc82007-12-02 06:31:25 +00003266
3267 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3268 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3269 goto give_sigsegv;
3270
Peter Maydellf6c7a052015-01-08 12:19:48 +00003271 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003272
3273 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003274 __put_user(0, &frame->uc.tuc_flags);
3275 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3276 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3277 &frame->uc.tuc_stack.ss_sp);
3278 __put_user(sas_ss_flags(regs->gregs[15]),
3279 &frame->uc.tuc_stack.ss_flags);
3280 __put_user(target_sigaltstack_used.ss_size,
3281 &frame->uc.tuc_stack.ss_size);
3282 setup_sigcontext(&frame->uc.tuc_mcontext,
thsc3b5bc82007-12-02 06:31:25 +00003283 regs, set->sig[0]);
3284 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003285 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003286 }
3287
3288 /* Set up to return from userspace. If provided, use a stub
3289 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003290 if (ka->sa_flags & TARGET_SA_RESTORER) {
3291 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003292 } else {
3293 /* Generate return code (system call to sigreturn) */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003294 __put_user(MOVW(2), &frame->retcode[0]);
3295 __put_user(TRAP_NOARG, &frame->retcode[1]);
3296 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
thsc3b5bc82007-12-02 06:31:25 +00003297 regs->pr = (unsigned long) frame->retcode;
3298 }
3299
3300 if (err)
3301 goto give_sigsegv;
3302
3303 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003304 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003305 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003306 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3307 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003308 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003309
3310 unlock_user_struct(frame, frame_addr, 1);
3311 return;
3312
3313give_sigsegv:
3314 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003315 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003316}
3317
Andreas Färber05390242012-02-25 03:37:53 +01003318long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003319{
3320 struct target_sigframe *frame;
3321 abi_ulong frame_addr;
3322 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003323 target_sigset_t target_set;
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003324 target_ulong r0;
thsc3b5bc82007-12-02 06:31:25 +00003325 int i;
3326 int err = 0;
3327
3328#if defined(DEBUG_SIGNAL)
3329 fprintf(stderr, "do_sigreturn\n");
3330#endif
3331 frame_addr = regs->gregs[15];
3332 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3333 goto badframe;
3334
Riku Voipio1d8b5122014-04-23 10:26:05 +03003335 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003336 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003337 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003338 }
3339
3340 if (err)
3341 goto badframe;
3342
3343 target_to_host_sigset_internal(&blocked, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00003344 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
thsc3b5bc82007-12-02 06:31:25 +00003345
Riku Voipio016d2e12014-04-23 11:19:48 +03003346 restore_sigcontext(regs, &frame->sc, &r0);
thsc3b5bc82007-12-02 06:31:25 +00003347
3348 unlock_user_struct(frame, frame_addr, 0);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003349 return r0;
thsc3b5bc82007-12-02 06:31:25 +00003350
3351badframe:
3352 unlock_user_struct(frame, frame_addr, 0);
3353 force_sig(TARGET_SIGSEGV);
3354 return 0;
3355}
3356
Andreas Färber05390242012-02-25 03:37:53 +01003357long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003358{
3359 struct target_rt_sigframe *frame;
3360 abi_ulong frame_addr;
3361 sigset_t blocked;
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003362 target_ulong r0;
thsc3b5bc82007-12-02 06:31:25 +00003363
3364#if defined(DEBUG_SIGNAL)
3365 fprintf(stderr, "do_rt_sigreturn\n");
3366#endif
3367 frame_addr = regs->gregs[15];
3368 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3369 goto badframe;
3370
Aurelien Jarno60e99242010-03-29 02:12:51 +02003371 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00003372 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
thsc3b5bc82007-12-02 06:31:25 +00003373
Riku Voipio016d2e12014-04-23 11:19:48 +03003374 restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0);
thsc3b5bc82007-12-02 06:31:25 +00003375
3376 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02003377 offsetof(struct target_rt_sigframe, uc.tuc_stack),
thsc3b5bc82007-12-02 06:31:25 +00003378 0, get_sp_from_cpustate(regs)) == -EFAULT)
3379 goto badframe;
3380
3381 unlock_user_struct(frame, frame_addr, 0);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003382 return r0;
thsc3b5bc82007-12-02 06:31:25 +00003383
3384badframe:
3385 unlock_user_struct(frame, frame_addr, 0);
3386 force_sig(TARGET_SIGSEGV);
3387 return 0;
3388}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003389#elif defined(TARGET_MICROBLAZE)
3390
3391struct target_sigcontext {
3392 struct target_pt_regs regs; /* needs to be first */
3393 uint32_t oldmask;
3394};
3395
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003396struct target_stack_t {
3397 abi_ulong ss_sp;
3398 int ss_flags;
3399 unsigned int ss_size;
3400};
3401
3402struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003403 abi_ulong tuc_flags;
3404 abi_ulong tuc_link;
3405 struct target_stack_t tuc_stack;
3406 struct target_sigcontext tuc_mcontext;
3407 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003408};
3409
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003410/* Signal frames. */
3411struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003412 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003413 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3414 uint32_t tramp[2];
3415};
3416
3417struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003418 siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003419 struct ucontext uc;
3420 uint32_t tramp[2];
3421};
3422
Andreas Färber05390242012-02-25 03:37:53 +01003423static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003424{
3425 __put_user(env->regs[0], &sc->regs.r0);
3426 __put_user(env->regs[1], &sc->regs.r1);
3427 __put_user(env->regs[2], &sc->regs.r2);
3428 __put_user(env->regs[3], &sc->regs.r3);
3429 __put_user(env->regs[4], &sc->regs.r4);
3430 __put_user(env->regs[5], &sc->regs.r5);
3431 __put_user(env->regs[6], &sc->regs.r6);
3432 __put_user(env->regs[7], &sc->regs.r7);
3433 __put_user(env->regs[8], &sc->regs.r8);
3434 __put_user(env->regs[9], &sc->regs.r9);
3435 __put_user(env->regs[10], &sc->regs.r10);
3436 __put_user(env->regs[11], &sc->regs.r11);
3437 __put_user(env->regs[12], &sc->regs.r12);
3438 __put_user(env->regs[13], &sc->regs.r13);
3439 __put_user(env->regs[14], &sc->regs.r14);
3440 __put_user(env->regs[15], &sc->regs.r15);
3441 __put_user(env->regs[16], &sc->regs.r16);
3442 __put_user(env->regs[17], &sc->regs.r17);
3443 __put_user(env->regs[18], &sc->regs.r18);
3444 __put_user(env->regs[19], &sc->regs.r19);
3445 __put_user(env->regs[20], &sc->regs.r20);
3446 __put_user(env->regs[21], &sc->regs.r21);
3447 __put_user(env->regs[22], &sc->regs.r22);
3448 __put_user(env->regs[23], &sc->regs.r23);
3449 __put_user(env->regs[24], &sc->regs.r24);
3450 __put_user(env->regs[25], &sc->regs.r25);
3451 __put_user(env->regs[26], &sc->regs.r26);
3452 __put_user(env->regs[27], &sc->regs.r27);
3453 __put_user(env->regs[28], &sc->regs.r28);
3454 __put_user(env->regs[29], &sc->regs.r29);
3455 __put_user(env->regs[30], &sc->regs.r30);
3456 __put_user(env->regs[31], &sc->regs.r31);
3457 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3458}
3459
Andreas Färber05390242012-02-25 03:37:53 +01003460static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003461{
3462 __get_user(env->regs[0], &sc->regs.r0);
3463 __get_user(env->regs[1], &sc->regs.r1);
3464 __get_user(env->regs[2], &sc->regs.r2);
3465 __get_user(env->regs[3], &sc->regs.r3);
3466 __get_user(env->regs[4], &sc->regs.r4);
3467 __get_user(env->regs[5], &sc->regs.r5);
3468 __get_user(env->regs[6], &sc->regs.r6);
3469 __get_user(env->regs[7], &sc->regs.r7);
3470 __get_user(env->regs[8], &sc->regs.r8);
3471 __get_user(env->regs[9], &sc->regs.r9);
3472 __get_user(env->regs[10], &sc->regs.r10);
3473 __get_user(env->regs[11], &sc->regs.r11);
3474 __get_user(env->regs[12], &sc->regs.r12);
3475 __get_user(env->regs[13], &sc->regs.r13);
3476 __get_user(env->regs[14], &sc->regs.r14);
3477 __get_user(env->regs[15], &sc->regs.r15);
3478 __get_user(env->regs[16], &sc->regs.r16);
3479 __get_user(env->regs[17], &sc->regs.r17);
3480 __get_user(env->regs[18], &sc->regs.r18);
3481 __get_user(env->regs[19], &sc->regs.r19);
3482 __get_user(env->regs[20], &sc->regs.r20);
3483 __get_user(env->regs[21], &sc->regs.r21);
3484 __get_user(env->regs[22], &sc->regs.r22);
3485 __get_user(env->regs[23], &sc->regs.r23);
3486 __get_user(env->regs[24], &sc->regs.r24);
3487 __get_user(env->regs[25], &sc->regs.r25);
3488 __get_user(env->regs[26], &sc->regs.r26);
3489 __get_user(env->regs[27], &sc->regs.r27);
3490 __get_user(env->regs[28], &sc->regs.r28);
3491 __get_user(env->regs[29], &sc->regs.r29);
3492 __get_user(env->regs[30], &sc->regs.r30);
3493 __get_user(env->regs[31], &sc->regs.r31);
3494 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3495}
3496
3497static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003498 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003499{
3500 abi_ulong sp = env->regs[1];
3501
Riku Voipiob545f632014-07-15 17:01:55 +03003502 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003503 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003504 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003505
3506 return ((sp - frame_size) & -8UL);
3507}
3508
3509static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003510 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003511{
3512 struct target_signal_frame *frame;
3513 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003514 int i;
3515
3516 frame_addr = get_sigframe(ka, env, sizeof *frame);
3517 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3518 goto badframe;
3519
3520 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003521 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003522
3523 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003524 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003525 }
3526
Richard Hendersonf711df62010-11-22 14:57:52 -08003527 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003528
3529 /* Set up to return from userspace. If provided, use a stub
3530 already in userspace. */
3531 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3532 if (ka->sa_flags & TARGET_SA_RESTORER) {
3533 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3534 } else {
3535 uint32_t t;
3536 /* Note, these encodings are _big endian_! */
3537 /* addi r12, r0, __NR_sigreturn */
3538 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003539 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003540 /* brki r14, 0x8 */
3541 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003542 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003543
3544 /* Return from sighandler will jump to the tramp.
3545 Negative 8 offset because return is rtsd r15, 8 */
3546 env->regs[15] = ((unsigned long)frame->tramp) - 8;
3547 }
3548
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003549 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003550 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003551 /* Signal handler args: */
3552 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02003553 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003554 /* arg 1: sigcontext */
3555 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003556
3557 /* Offset of 4 to handle microblaze rtid r14, 0 */
3558 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3559
3560 unlock_user_struct(frame, frame_addr, 1);
3561 return;
3562 badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003563 force_sig(TARGET_SIGSEGV);
3564}
3565
3566static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003567 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003568 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003569{
3570 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3571}
3572
Andreas Färber05390242012-02-25 03:37:53 +01003573long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003574{
3575 struct target_signal_frame *frame;
3576 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003577 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003578 sigset_t set;
3579 int i;
3580
3581 frame_addr = env->regs[R_SP];
3582 /* Make sure the guest isn't playing games. */
3583 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3584 goto badframe;
3585
3586 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003587 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003588 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003589 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003590 }
3591 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00003592 do_sigprocmask(SIG_SETMASK, &set, NULL);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003593
Richard Hendersonf711df62010-11-22 14:57:52 -08003594 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003595 /* We got here through a sigreturn syscall, our path back is via an
3596 rtb insn so setup r14 for that. */
3597 env->regs[14] = env->sregs[SR_PC];
3598
3599 unlock_user_struct(frame, frame_addr, 0);
3600 return env->regs[10];
3601 badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003602 force_sig(TARGET_SIGSEGV);
3603}
3604
Andreas Färber05390242012-02-25 03:37:53 +01003605long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003606{
3607 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3608 return -TARGET_ENOSYS;
3609}
3610
edgar_iglb6d3abd2008-02-28 11:29:27 +00003611#elif defined(TARGET_CRIS)
3612
3613struct target_sigcontext {
3614 struct target_pt_regs regs; /* needs to be first */
3615 uint32_t oldmask;
3616 uint32_t usp; /* usp before stacking this gunk on it */
3617};
3618
3619/* Signal frames. */
3620struct target_signal_frame {
3621 struct target_sigcontext sc;
3622 uint32_t extramask[TARGET_NSIG_WORDS - 1];
Stefan Weil8cfc1142014-02-01 09:41:09 +01003623 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003624};
3625
3626struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003627 siginfo_t *pinfo;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003628 void *puc;
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003629 siginfo_t info;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003630 struct ucontext uc;
Stefan Weil8cfc1142014-02-01 09:41:09 +01003631 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003632};
3633
Andreas Färber05390242012-02-25 03:37:53 +01003634static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003635{
edgar_igl9664d922008-03-03 22:23:53 +00003636 __put_user(env->regs[0], &sc->regs.r0);
3637 __put_user(env->regs[1], &sc->regs.r1);
3638 __put_user(env->regs[2], &sc->regs.r2);
3639 __put_user(env->regs[3], &sc->regs.r3);
3640 __put_user(env->regs[4], &sc->regs.r4);
3641 __put_user(env->regs[5], &sc->regs.r5);
3642 __put_user(env->regs[6], &sc->regs.r6);
3643 __put_user(env->regs[7], &sc->regs.r7);
3644 __put_user(env->regs[8], &sc->regs.r8);
3645 __put_user(env->regs[9], &sc->regs.r9);
3646 __put_user(env->regs[10], &sc->regs.r10);
3647 __put_user(env->regs[11], &sc->regs.r11);
3648 __put_user(env->regs[12], &sc->regs.r12);
3649 __put_user(env->regs[13], &sc->regs.r13);
3650 __put_user(env->regs[14], &sc->usp);
3651 __put_user(env->regs[15], &sc->regs.acr);
3652 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3653 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3654 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003655}
edgar_igl9664d922008-03-03 22:23:53 +00003656
Andreas Färber05390242012-02-25 03:37:53 +01003657static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003658{
edgar_igl9664d922008-03-03 22:23:53 +00003659 __get_user(env->regs[0], &sc->regs.r0);
3660 __get_user(env->regs[1], &sc->regs.r1);
3661 __get_user(env->regs[2], &sc->regs.r2);
3662 __get_user(env->regs[3], &sc->regs.r3);
3663 __get_user(env->regs[4], &sc->regs.r4);
3664 __get_user(env->regs[5], &sc->regs.r5);
3665 __get_user(env->regs[6], &sc->regs.r6);
3666 __get_user(env->regs[7], &sc->regs.r7);
3667 __get_user(env->regs[8], &sc->regs.r8);
3668 __get_user(env->regs[9], &sc->regs.r9);
3669 __get_user(env->regs[10], &sc->regs.r10);
3670 __get_user(env->regs[11], &sc->regs.r11);
3671 __get_user(env->regs[12], &sc->regs.r12);
3672 __get_user(env->regs[13], &sc->regs.r13);
3673 __get_user(env->regs[14], &sc->usp);
3674 __get_user(env->regs[15], &sc->regs.acr);
3675 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3676 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3677 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003678}
3679
Andreas Färber05390242012-02-25 03:37:53 +01003680static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003681{
edgar_igl9664d922008-03-03 22:23:53 +00003682 abi_ulong sp;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003683 /* Align the stack downwards to 4. */
edgar_igl9664d922008-03-03 22:23:53 +00003684 sp = (env->regs[R_SP] & ~3);
3685 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003686}
3687
pbrook624f7972008-05-31 16:11:38 +00003688static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003689 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003690{
3691 struct target_signal_frame *frame;
edgar_igl9664d922008-03-03 22:23:53 +00003692 abi_ulong frame_addr;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003693 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003694
edgar_igl9664d922008-03-03 22:23:53 +00003695 frame_addr = get_sigframe(env, sizeof *frame);
3696 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
edgar_iglb6d3abd2008-02-28 11:29:27 +00003697 goto badframe;
3698
3699 /*
3700 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3701 * use this trampoline anymore but it sets it up for GDB.
3702 * In QEMU, using the trampoline simplifies things a bit so we use it.
3703 *
3704 * This is movu.w __NR_sigreturn, r9; break 13;
3705 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003706 __put_user(0x9c5f, frame->retcode+0);
3707 __put_user(TARGET_NR_sigreturn,
3708 frame->retcode + 1);
3709 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003710
3711 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003712 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003713
Riku Voipio0188fad2014-04-23 13:34:15 +03003714 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3715 __put_user(set->sig[i], &frame->extramask[i - 1]);
3716 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003717
3718 setup_sigcontext(&frame->sc, env);
3719
3720 /* Move the stack and setup the arguments for the handler. */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003721 env->regs[R_SP] = frame_addr;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003722 env->regs[10] = sig;
pbrook624f7972008-05-31 16:11:38 +00003723 env->pc = (unsigned long) ka->_sa_handler;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003724 /* Link SRP so the guest returns through the trampoline. */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003725 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003726
edgar_igl9664d922008-03-03 22:23:53 +00003727 unlock_user_struct(frame, frame_addr, 1);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003728 return;
3729 badframe:
edgar_iglb6d3abd2008-02-28 11:29:27 +00003730 force_sig(TARGET_SIGSEGV);
3731}
3732
pbrook624f7972008-05-31 16:11:38 +00003733static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003734 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003735 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003736{
3737 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3738}
3739
Andreas Färber05390242012-02-25 03:37:53 +01003740long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003741{
3742 struct target_signal_frame *frame;
edgar_igl9664d922008-03-03 22:23:53 +00003743 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003744 target_sigset_t target_set;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003745 sigset_t set;
3746 int i;
3747
edgar_igl9664d922008-03-03 22:23:53 +00003748 frame_addr = env->regs[R_SP];
edgar_iglb6d3abd2008-02-28 11:29:27 +00003749 /* Make sure the guest isn't playing games. */
edgar_igl9664d922008-03-03 22:23:53 +00003750 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
edgar_iglb6d3abd2008-02-28 11:29:27 +00003751 goto badframe;
3752
3753 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003754 __get_user(target_set.sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003755 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003756 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003757 }
3758 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00003759 do_sigprocmask(SIG_SETMASK, &set, NULL);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003760
3761 restore_sigcontext(&frame->sc, env);
edgar_igl9664d922008-03-03 22:23:53 +00003762 unlock_user_struct(frame, frame_addr, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003763 return env->regs[10];
3764 badframe:
edgar_iglb6d3abd2008-02-28 11:29:27 +00003765 force_sig(TARGET_SIGSEGV);
3766}
3767
Andreas Färber05390242012-02-25 03:37:53 +01003768long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003769{
3770 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3771 return -TARGET_ENOSYS;
3772}
thsc3b5bc82007-12-02 06:31:25 +00003773
Jia Liud9627832012-07-20 15:50:52 +08003774#elif defined(TARGET_OPENRISC)
3775
3776struct target_sigcontext {
3777 struct target_pt_regs regs;
3778 abi_ulong oldmask;
3779 abi_ulong usp;
3780};
3781
3782struct target_ucontext {
3783 abi_ulong tuc_flags;
3784 abi_ulong tuc_link;
3785 target_stack_t tuc_stack;
3786 struct target_sigcontext tuc_mcontext;
3787 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3788};
3789
3790struct target_rt_sigframe {
3791 abi_ulong pinfo;
3792 uint64_t puc;
3793 struct target_siginfo info;
3794 struct target_sigcontext sc;
3795 struct target_ucontext uc;
3796 unsigned char retcode[16]; /* trampoline code */
3797};
3798
3799/* This is the asm-generic/ucontext.h version */
3800#if 0
3801static int restore_sigcontext(CPUOpenRISCState *regs,
3802 struct target_sigcontext *sc)
3803{
3804 unsigned int err = 0;
3805 unsigned long old_usp;
3806
3807 /* Alwys make any pending restarted system call return -EINTR */
3808 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3809
3810 /* restore the regs from &sc->regs (same as sc, since regs is first)
3811 * (sc is already checked for VERIFY_READ since the sigframe was
3812 * checked in sys_sigreturn previously)
3813 */
3814
3815 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3816 goto badframe;
3817 }
3818
3819 /* make sure the U-flag is set so user-mode cannot fool us */
3820
3821 regs->sr &= ~SR_SM;
3822
3823 /* restore the old USP as it was before we stacked the sc etc.
3824 * (we cannot just pop the sigcontext since we aligned the sp and
3825 * stuff after pushing it)
3826 */
3827
Riku Voipio1d8b5122014-04-23 10:26:05 +03003828 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003829 phx_signal("old_usp 0x%lx", old_usp);
3830
3831 __PHX__ REALLY /* ??? */
3832 wrusp(old_usp);
3833 regs->gpr[1] = old_usp;
3834
3835 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3836 * after this completes, but we don't use that mechanism. maybe we can
3837 * use it now ?
3838 */
3839
3840 return err;
3841
3842badframe:
3843 return 1;
3844}
3845#endif
3846
3847/* Set up a signal frame. */
3848
Riku Voipio41ecc722014-04-23 11:01:00 +03003849static void setup_sigcontext(struct target_sigcontext *sc,
Jia Liud9627832012-07-20 15:50:52 +08003850 CPUOpenRISCState *regs,
3851 unsigned long mask)
3852{
Jia Liud9627832012-07-20 15:50:52 +08003853 unsigned long usp = regs->gpr[1];
3854
3855 /* copy the regs. they are first in sc so we can use sc directly */
3856
Riku Voipio1d8b5122014-04-23 10:26:05 +03003857 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08003858
3859 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3860 the signal handler. The frametype will be restored to its previous
3861 value in restore_sigcontext. */
3862 /*regs->frametype = CRIS_FRAME_NORMAL;*/
3863
3864 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003865 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03003866 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003867}
3868
3869static inline unsigned long align_sigframe(unsigned long sp)
3870{
3871 unsigned long i;
3872 i = sp & ~3UL;
3873 return i;
3874}
3875
3876static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3877 CPUOpenRISCState *regs,
3878 size_t frame_size)
3879{
3880 unsigned long sp = regs->gpr[1];
3881 int onsigstack = on_sig_stack(sp);
3882
3883 /* redzone */
3884 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03003885 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08003886 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3887 }
3888
3889 sp = align_sigframe(sp - frame_size);
3890
3891 /*
3892 * If we are on the alternate signal stack and would overflow it, don't.
3893 * Return an always-bogus address instead so we will die with SIGSEGV.
3894 */
3895
3896 if (onsigstack && !likely(on_sig_stack(sp))) {
3897 return -1L;
3898 }
3899
3900 return sp;
3901}
3902
3903static void setup_frame(int sig, struct target_sigaction *ka,
3904 target_sigset_t *set, CPUOpenRISCState *env)
3905{
3906 qemu_log("Not implement.\n");
3907}
3908
3909static void setup_rt_frame(int sig, struct target_sigaction *ka,
3910 target_siginfo_t *info,
3911 target_sigset_t *set, CPUOpenRISCState *env)
3912{
3913 int err = 0;
3914 abi_ulong frame_addr;
3915 unsigned long return_ip;
3916 struct target_rt_sigframe *frame;
3917 abi_ulong info_addr, uc_addr;
3918
Jia Liud9627832012-07-20 15:50:52 +08003919 frame_addr = get_sigframe(ka, env, sizeof(*frame));
3920 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3921 goto give_sigsegv;
3922 }
3923
3924 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003925 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08003926 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003927 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08003928
3929 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00003930 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08003931 }
3932
3933 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03003934 __put_user(0, &frame->uc.tuc_flags);
3935 __put_user(0, &frame->uc.tuc_link);
3936 __put_user(target_sigaltstack_used.ss_sp,
3937 &frame->uc.tuc_stack.ss_sp);
3938 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
3939 __put_user(target_sigaltstack_used.ss_size,
3940 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03003941 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08003942
3943 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
3944
Jia Liud9627832012-07-20 15:50:52 +08003945 /* trampoline - the desired return ip is the retcode itself */
3946 return_ip = (unsigned long)&frame->retcode;
3947 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003948 __put_user(0xa960, (short *)(frame->retcode + 0));
3949 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
3950 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
3951 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08003952
3953 if (err) {
3954 goto give_sigsegv;
3955 }
3956
3957 /* TODO what is the current->exec_domain stuff and invmap ? */
3958
3959 /* Set up registers for signal handler */
3960 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
3961 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
3962 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
3963 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
3964 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
3965
3966 /* actually move the usp to reflect the stacked frame */
3967 env->gpr[1] = (unsigned long)frame;
3968
3969 return;
3970
3971give_sigsegv:
3972 unlock_user_struct(frame, frame_addr, 1);
3973 if (sig == TARGET_SIGSEGV) {
3974 ka->_sa_handler = TARGET_SIG_DFL;
3975 }
3976 force_sig(TARGET_SIGSEGV);
3977}
3978
3979long do_sigreturn(CPUOpenRISCState *env)
3980{
3981
3982 qemu_log("do_sigreturn: not implemented\n");
3983 return -TARGET_ENOSYS;
3984}
3985
3986long do_rt_sigreturn(CPUOpenRISCState *env)
3987{
3988 qemu_log("do_rt_sigreturn: not implemented\n");
3989 return -TARGET_ENOSYS;
3990}
3991/* TARGET_OPENRISC */
3992
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003993#elif defined(TARGET_S390X)
3994
3995#define __NUM_GPRS 16
3996#define __NUM_FPRS 16
3997#define __NUM_ACRS 16
3998
3999#define S390_SYSCALL_SIZE 2
4000#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4001
4002#define _SIGCONTEXT_NSIG 64
4003#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4004#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4005#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4006#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4007#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4008
4009typedef struct {
4010 target_psw_t psw;
4011 target_ulong gprs[__NUM_GPRS];
4012 unsigned int acrs[__NUM_ACRS];
4013} target_s390_regs_common;
4014
4015typedef struct {
4016 unsigned int fpc;
4017 double fprs[__NUM_FPRS];
4018} target_s390_fp_regs;
4019
4020typedef struct {
4021 target_s390_regs_common regs;
4022 target_s390_fp_regs fpregs;
4023} target_sigregs;
4024
4025struct target_sigcontext {
4026 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4027 target_sigregs *sregs;
4028};
4029
4030typedef struct {
4031 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4032 struct target_sigcontext sc;
4033 target_sigregs sregs;
4034 int signo;
4035 uint8_t retcode[S390_SYSCALL_SIZE];
4036} sigframe;
4037
4038struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004039 target_ulong tuc_flags;
4040 struct target_ucontext *tuc_link;
4041 target_stack_t tuc_stack;
4042 target_sigregs tuc_mcontext;
4043 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004044};
4045
4046typedef struct {
4047 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4048 uint8_t retcode[S390_SYSCALL_SIZE];
4049 struct target_siginfo info;
4050 struct target_ucontext uc;
4051} rt_sigframe;
4052
4053static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004054get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004055{
4056 abi_ulong sp;
4057
4058 /* Default to using normal stack */
4059 sp = env->regs[15];
4060
4061 /* This is the X/Open sanctioned signal stack switching. */
4062 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4063 if (!sas_ss_flags(sp)) {
4064 sp = target_sigaltstack_used.ss_sp +
4065 target_sigaltstack_used.ss_size;
4066 }
4067 }
4068
4069 /* This is the legacy signal stack switching. */
4070 else if (/* FIXME !user_mode(regs) */ 0 &&
4071 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4072 ka->sa_restorer) {
4073 sp = (abi_ulong) ka->sa_restorer;
4074 }
4075
4076 return (sp - frame_size) & -8ul;
4077}
4078
Andreas Färber05390242012-02-25 03:37:53 +01004079static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004080{
4081 int i;
4082 //save_access_regs(current->thread.acrs); FIXME
4083
4084 /* Copy a 'clean' PSW mask to the user to avoid leaking
4085 information about whether PER is currently on. */
4086 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4087 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4088 for (i = 0; i < 16; i++) {
4089 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4090 }
4091 for (i = 0; i < 16; i++) {
4092 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4093 }
4094 /*
4095 * We have to store the fp registers to current->thread.fp_regs
4096 * to merge them with the emulated registers.
4097 */
4098 //save_fp_regs(&current->thread.fp_regs); FIXME
4099 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004100 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004101 }
4102}
4103
4104static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004105 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004106{
4107 sigframe *frame;
4108 abi_ulong frame_addr;
4109
4110 frame_addr = get_sigframe(ka, env, sizeof(*frame));
4111 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4112 (unsigned long long)frame_addr);
4113 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4114 goto give_sigsegv;
4115 }
4116
4117 qemu_log("%s: 1\n", __FUNCTION__);
Riku Voipio0188fad2014-04-23 13:34:15 +03004118 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004119
4120 save_sigregs(env, &frame->sregs);
4121
4122 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4123 (abi_ulong *)&frame->sc.sregs);
4124
4125 /* Set up to return from userspace. If provided, use a stub
4126 already in userspace. */
4127 if (ka->sa_flags & TARGET_SA_RESTORER) {
4128 env->regs[14] = (unsigned long)
4129 ka->sa_restorer | PSW_ADDR_AMODE;
4130 } else {
4131 env->regs[14] = (unsigned long)
4132 frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004133 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4134 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004135 }
4136
4137 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004138 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004139
4140 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004141 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004142 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4143
4144 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004145 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004146
4147 /* We forgot to include these in the sigcontext.
4148 To avoid breaking binary compatibility, they are passed as args. */
4149 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4150 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4151
4152 /* Place signal number on stack to allow backtrace from handler. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004153 __put_user(env->regs[2], (int *) &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004154 unlock_user_struct(frame, frame_addr, 1);
4155 return;
4156
4157give_sigsegv:
4158 qemu_log("%s: give_sigsegv\n", __FUNCTION__);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004159 force_sig(TARGET_SIGSEGV);
4160}
4161
4162static void setup_rt_frame(int sig, struct target_sigaction *ka,
4163 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004164 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004165{
4166 int i;
4167 rt_sigframe *frame;
4168 abi_ulong frame_addr;
4169
4170 frame_addr = get_sigframe(ka, env, sizeof *frame);
4171 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4172 (unsigned long long)frame_addr);
4173 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4174 goto give_sigsegv;
4175 }
4176
4177 qemu_log("%s: 1\n", __FUNCTION__);
Peter Maydellf6c7a052015-01-08 12:19:48 +00004178 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004179
4180 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004181 __put_user(0, &frame->uc.tuc_flags);
4182 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4183 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004184 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004185 &frame->uc.tuc_stack.ss_flags);
4186 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4187 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004188 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4189 __put_user((abi_ulong)set->sig[i],
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004190 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004191 }
4192
4193 /* Set up to return from userspace. If provided, use a stub
4194 already in userspace. */
4195 if (ka->sa_flags & TARGET_SA_RESTORER) {
4196 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4197 } else {
4198 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004199 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4200 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004201 }
4202
4203 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004204 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004205
4206 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004207 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004208 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4209
4210 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004211 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4212 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004213 return;
4214
4215give_sigsegv:
4216 qemu_log("%s: give_sigsegv\n", __FUNCTION__);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004217 force_sig(TARGET_SIGSEGV);
4218}
4219
4220static int
Andreas Färber05390242012-02-25 03:37:53 +01004221restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004222{
4223 int err = 0;
4224 int i;
4225
4226 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004227 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004228 }
4229
Riku Voipio1d8b5122014-04-23 10:26:05 +03004230 __get_user(env->psw.mask, &sc->regs.psw.mask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004231 qemu_log("%s: sc->regs.psw.addr 0x%llx env->psw.addr 0x%llx\n",
4232 __FUNCTION__, (unsigned long long)sc->regs.psw.addr,
4233 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004234 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004235 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4236
4237 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004238 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004239 }
4240 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004241 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004242 }
4243
4244 return err;
4245}
4246
Andreas Färber05390242012-02-25 03:37:53 +01004247long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004248{
4249 sigframe *frame;
4250 abi_ulong frame_addr = env->regs[15];
4251 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4252 (unsigned long long)frame_addr);
4253 target_sigset_t target_set;
4254 sigset_t set;
4255
4256 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4257 goto badframe;
4258 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004259 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004260
4261 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004262 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004263
4264 if (restore_sigregs(env, &frame->sregs)) {
4265 goto badframe;
4266 }
4267
4268 unlock_user_struct(frame, frame_addr, 0);
4269 return env->regs[2];
4270
4271badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004272 force_sig(TARGET_SIGSEGV);
4273 return 0;
4274}
4275
Andreas Färber05390242012-02-25 03:37:53 +01004276long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004277{
4278 rt_sigframe *frame;
4279 abi_ulong frame_addr = env->regs[15];
4280 qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4281 (unsigned long long)frame_addr);
4282 sigset_t set;
4283
4284 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4285 goto badframe;
4286 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004287 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004288
Alex Barcelo1c275922014-03-14 14:36:55 +00004289 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004290
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004291 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004292 goto badframe;
4293 }
4294
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004295 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004296 get_sp_from_cpustate(env)) == -EFAULT) {
4297 goto badframe;
4298 }
4299 unlock_user_struct(frame, frame_addr, 0);
4300 return env->regs[2];
4301
4302badframe:
4303 unlock_user_struct(frame, frame_addr, 0);
4304 force_sig(TARGET_SIGSEGV);
4305 return 0;
4306}
4307
Tom Musta61e75fe2014-06-30 08:13:38 -05004308#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004309
4310/* Size of dummy stack frame allocated when calling signal handler.
4311 See arch/powerpc/include/asm/ptrace.h. */
4312#if defined(TARGET_PPC64)
4313#define SIGNAL_FRAMESIZE 128
4314#else
4315#define SIGNAL_FRAMESIZE 64
4316#endif
4317
Tom Musta61e75fe2014-06-30 08:13:38 -05004318/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4319 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4320struct target_mcontext {
4321 target_ulong mc_gregs[48];
4322 /* Includes fpscr. */
4323 uint64_t mc_fregs[33];
4324 target_ulong mc_pad[2];
4325 /* We need to handle Altivec and SPE at the same time, which no
4326 kernel needs to do. Fortunately, the kernel defines this bit to
4327 be Altivec-register-large all the time, rather than trying to
4328 twiddle it based on the specific platform. */
4329 union {
4330 /* SPE vector registers. One extra for SPEFSCR. */
4331 uint32_t spe[33];
4332 /* Altivec vector registers. The packing of VSCR and VRSAVE
4333 varies depending on whether we're PPC64 or not: PPC64 splits
4334 them apart; PPC32 stuffs them together. */
4335#if defined(TARGET_PPC64)
4336#define QEMU_NVRREG 34
4337#else
4338#define QEMU_NVRREG 33
4339#endif
4340 ppc_avr_t altivec[QEMU_NVRREG];
4341#undef QEMU_NVRREG
4342 } mc_vregs __attribute__((__aligned__(16)));
4343};
4344
Nathan Froydbcd49332009-05-12 19:13:18 -07004345/* See arch/powerpc/include/asm/sigcontext.h. */
4346struct target_sigcontext {
4347 target_ulong _unused[4];
4348 int32_t signal;
4349#if defined(TARGET_PPC64)
4350 int32_t pad0;
4351#endif
4352 target_ulong handler;
4353 target_ulong oldmask;
4354 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05004355#if defined(TARGET_PPC64)
4356 struct target_mcontext mcontext;
4357#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004358};
4359
4360/* Indices for target_mcontext.mc_gregs, below.
4361 See arch/powerpc/include/asm/ptrace.h for details. */
4362enum {
4363 TARGET_PT_R0 = 0,
4364 TARGET_PT_R1 = 1,
4365 TARGET_PT_R2 = 2,
4366 TARGET_PT_R3 = 3,
4367 TARGET_PT_R4 = 4,
4368 TARGET_PT_R5 = 5,
4369 TARGET_PT_R6 = 6,
4370 TARGET_PT_R7 = 7,
4371 TARGET_PT_R8 = 8,
4372 TARGET_PT_R9 = 9,
4373 TARGET_PT_R10 = 10,
4374 TARGET_PT_R11 = 11,
4375 TARGET_PT_R12 = 12,
4376 TARGET_PT_R13 = 13,
4377 TARGET_PT_R14 = 14,
4378 TARGET_PT_R15 = 15,
4379 TARGET_PT_R16 = 16,
4380 TARGET_PT_R17 = 17,
4381 TARGET_PT_R18 = 18,
4382 TARGET_PT_R19 = 19,
4383 TARGET_PT_R20 = 20,
4384 TARGET_PT_R21 = 21,
4385 TARGET_PT_R22 = 22,
4386 TARGET_PT_R23 = 23,
4387 TARGET_PT_R24 = 24,
4388 TARGET_PT_R25 = 25,
4389 TARGET_PT_R26 = 26,
4390 TARGET_PT_R27 = 27,
4391 TARGET_PT_R28 = 28,
4392 TARGET_PT_R29 = 29,
4393 TARGET_PT_R30 = 30,
4394 TARGET_PT_R31 = 31,
4395 TARGET_PT_NIP = 32,
4396 TARGET_PT_MSR = 33,
4397 TARGET_PT_ORIG_R3 = 34,
4398 TARGET_PT_CTR = 35,
4399 TARGET_PT_LNK = 36,
4400 TARGET_PT_XER = 37,
4401 TARGET_PT_CCR = 38,
4402 /* Yes, there are two registers with #39. One is 64-bit only. */
4403 TARGET_PT_MQ = 39,
4404 TARGET_PT_SOFTE = 39,
4405 TARGET_PT_TRAP = 40,
4406 TARGET_PT_DAR = 41,
4407 TARGET_PT_DSISR = 42,
4408 TARGET_PT_RESULT = 43,
4409 TARGET_PT_REGS_COUNT = 44
4410};
4411
Nathan Froydbcd49332009-05-12 19:13:18 -07004412
4413struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004414 target_ulong tuc_flags;
4415 target_ulong tuc_link; /* struct ucontext __user * */
4416 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07004417#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02004418 int32_t tuc_pad[7];
4419 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07004420 points to uc_mcontext field */
4421#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02004422 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07004423#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05004424 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05004425 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004426#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02004427 int32_t tuc_maskext[30];
4428 int32_t tuc_pad2[3];
4429 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004430#endif
4431};
4432
4433/* See arch/powerpc/kernel/signal_32.c. */
4434struct target_sigframe {
4435 struct target_sigcontext sctx;
4436 struct target_mcontext mctx;
4437 int32_t abigap[56];
4438};
4439
Tom Musta61e75fe2014-06-30 08:13:38 -05004440#if defined(TARGET_PPC64)
4441
4442#define TARGET_TRAMP_SIZE 6
4443
4444struct target_rt_sigframe {
4445 /* sys_rt_sigreturn requires the ucontext be the first field */
4446 struct target_ucontext uc;
4447 target_ulong _unused[2];
4448 uint32_t trampoline[TARGET_TRAMP_SIZE];
4449 target_ulong pinfo; /* struct siginfo __user * */
4450 target_ulong puc; /* void __user * */
4451 struct target_siginfo info;
4452 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
4453 char abigap[288];
4454} __attribute__((aligned(16)));
4455
4456#else
4457
Nathan Froydbcd49332009-05-12 19:13:18 -07004458struct target_rt_sigframe {
4459 struct target_siginfo info;
4460 struct target_ucontext uc;
4461 int32_t abigap[56];
4462};
4463
Tom Musta61e75fe2014-06-30 08:13:38 -05004464#endif
4465
Tom Musta8d6ab332014-06-30 08:13:39 -05004466#if defined(TARGET_PPC64)
4467
4468struct target_func_ptr {
4469 target_ulong entry;
4470 target_ulong toc;
4471};
4472
4473#endif
4474
Nathan Froydbcd49332009-05-12 19:13:18 -07004475/* We use the mc_pad field for the signal return trampoline. */
4476#define tramp mc_pad
4477
4478/* See arch/powerpc/kernel/signal.c. */
4479static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004480 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07004481 int frame_size)
4482{
4483 target_ulong oldsp, newsp;
4484
4485 oldsp = env->gpr[1];
4486
4487 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Alex Barcelo32a20032012-02-09 23:55:46 +00004488 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07004489 oldsp = (target_sigaltstack_used.ss_sp
4490 + target_sigaltstack_used.ss_size);
4491 }
4492
4493 newsp = (oldsp - frame_size) & ~0xFUL;
4494
4495 return newsp;
4496}
4497
Tom Musta76781082014-06-30 08:13:37 -05004498static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07004499{
4500 target_ulong msr = env->msr;
4501 int i;
4502 target_ulong ccr = 0;
4503
4504 /* In general, the kernel attempts to be intelligent about what it
4505 needs to save for Altivec/FP/SPE registers. We don't care that
4506 much, so we just go ahead and save everything. */
4507
4508 /* Save general registers. */
4509 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004510 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004511 }
Riku Voipioc650c002014-04-23 13:53:45 +03004512 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4513 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4514 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4515 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004516
4517 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4518 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4519 }
Riku Voipioc650c002014-04-23 13:53:45 +03004520 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004521
4522 /* Save Altivec registers if necessary. */
4523 if (env->insns_flags & PPC_ALTIVEC) {
4524 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004525 ppc_avr_t *avr = &env->avr[i];
4526 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004527
Riku Voipioc650c002014-04-23 13:53:45 +03004528 __put_user(avr->u64[0], &vreg->u64[0]);
4529 __put_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004530 }
4531 /* Set MSR_VR in the saved MSR value to indicate that
4532 frame->mc_vregs contains valid data. */
4533 msr |= MSR_VR;
Riku Voipioc650c002014-04-23 13:53:45 +03004534 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4535 &frame->mc_vregs.altivec[32].u32[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004536 }
4537
4538 /* Save floating point registers. */
4539 if (env->insns_flags & PPC_FLOAT) {
4540 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004541 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004542 }
Riku Voipioc650c002014-04-23 13:53:45 +03004543 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004544 }
4545
4546 /* Save SPE registers. The kernel only saves the high half. */
4547 if (env->insns_flags & PPC_SPE) {
4548#if defined(TARGET_PPC64)
4549 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004550 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004551 }
4552#else
4553 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004554 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004555 }
4556#endif
4557 /* Set MSR_SPE in the saved MSR value to indicate that
4558 frame->mc_vregs contains valid data. */
4559 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03004560 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004561 }
4562
4563 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004564 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05004565}
Nathan Froydbcd49332009-05-12 19:13:18 -07004566
Tom Musta76781082014-06-30 08:13:37 -05004567static void encode_trampoline(int sigret, uint32_t *tramp)
4568{
Nathan Froydbcd49332009-05-12 19:13:18 -07004569 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4570 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05004571 __put_user(0x38000000 | sigret, &tramp[0]);
4572 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004573 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004574}
4575
Riku Voipioc650c002014-04-23 13:53:45 +03004576static void restore_user_regs(CPUPPCState *env,
4577 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004578{
4579 target_ulong save_r2 = 0;
4580 target_ulong msr;
4581 target_ulong ccr;
4582
4583 int i;
4584
4585 if (!sig) {
4586 save_r2 = env->gpr[2];
4587 }
4588
4589 /* Restore general registers. */
4590 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004591 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004592 }
Riku Voipioc650c002014-04-23 13:53:45 +03004593 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4594 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4595 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4596 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4597 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004598
4599 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4600 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4601 }
4602
4603 if (!sig) {
4604 env->gpr[2] = save_r2;
4605 }
4606 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004607 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004608
4609 /* If doing signal return, restore the previous little-endian mode. */
4610 if (sig)
4611 env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
4612
4613 /* Restore Altivec registers if necessary. */
4614 if (env->insns_flags & PPC_ALTIVEC) {
4615 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004616 ppc_avr_t *avr = &env->avr[i];
4617 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004618
Riku Voipioc650c002014-04-23 13:53:45 +03004619 __get_user(avr->u64[0], &vreg->u64[0]);
4620 __get_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004621 }
4622 /* Set MSR_VEC in the saved MSR value to indicate that
4623 frame->mc_vregs contains valid data. */
Riku Voipioc650c002014-04-23 13:53:45 +03004624 __get_user(env->spr[SPR_VRSAVE],
4625 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
Nathan Froydbcd49332009-05-12 19:13:18 -07004626 }
4627
4628 /* Restore floating point registers. */
4629 if (env->insns_flags & PPC_FLOAT) {
4630 uint64_t fpscr;
4631 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004632 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004633 }
Riku Voipioc650c002014-04-23 13:53:45 +03004634 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004635 env->fpscr = (uint32_t) fpscr;
4636 }
4637
4638 /* Save SPE registers. The kernel only saves the high half. */
4639 if (env->insns_flags & PPC_SPE) {
4640#if defined(TARGET_PPC64)
4641 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4642 uint32_t hi;
4643
Riku Voipioc650c002014-04-23 13:53:45 +03004644 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004645 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4646 }
4647#else
4648 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004649 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004650 }
4651#endif
Riku Voipioc650c002014-04-23 13:53:45 +03004652 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004653 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004654}
4655
4656static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004657 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004658{
4659 struct target_sigframe *frame;
4660 struct target_sigcontext *sc;
4661 target_ulong frame_addr, newsp;
4662 int err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004663#if defined(TARGET_PPC64)
4664 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4665#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004666
4667 frame_addr = get_sigframe(ka, env, sizeof(*frame));
4668 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4669 goto sigsegv;
4670 sc = &frame->sctx;
4671
Riku Voipio1d8b5122014-04-23 10:26:05 +03004672 __put_user(ka->_sa_handler, &sc->handler);
4673 __put_user(set->sig[0], &sc->oldmask);
Tom Musta61e75fe2014-06-30 08:13:38 -05004674#if TARGET_ABI_BITS == 64
Riku Voipio1d8b5122014-04-23 10:26:05 +03004675 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004676#else
Riku Voipio1d8b5122014-04-23 10:26:05 +03004677 __put_user(set->sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004678#endif
Riku Voipio1d8b5122014-04-23 10:26:05 +03004679 __put_user(h2g(&frame->mctx), &sc->regs);
4680 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07004681
4682 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05004683 save_user_regs(env, &frame->mctx);
4684
4685 /* Construct the trampoline code on the stack. */
4686 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07004687
4688 /* The kernel checks for the presence of a VDSO here. We don't
4689 emulate a vdso, so use a sigreturn system call. */
4690 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4691
4692 /* Turn off all fp exceptions. */
4693 env->fpscr = 0;
4694
4695 /* Create a stack frame for the caller of the handler. */
4696 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00004697 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004698
4699 if (err)
4700 goto sigsegv;
4701
4702 /* Set up registers for signal handler. */
4703 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004704 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00004705 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05004706
4707#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004708 if (get_ppc64_abi(image) < 2) {
4709 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4710 struct target_func_ptr *handler =
4711 (struct target_func_ptr *)g2h(ka->_sa_handler);
4712 env->nip = tswapl(handler->entry);
4713 env->gpr[2] = tswapl(handler->toc);
4714 } else {
4715 /* ELFv2 PPC64 function pointers are entry points, but R12
4716 * must also be set */
4717 env->nip = tswapl((target_ulong) ka->_sa_handler);
4718 env->gpr[12] = env->nip;
4719 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004720#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004721 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004722#endif
4723
Nathan Froydbcd49332009-05-12 19:13:18 -07004724 /* Signal handlers are entered in big-endian mode. */
4725 env->msr &= ~MSR_LE;
4726
4727 unlock_user_struct(frame, frame_addr, 1);
4728 return;
4729
4730sigsegv:
4731 unlock_user_struct(frame, frame_addr, 1);
Blue Swirleeacee42012-06-03 16:35:32 +00004732 qemu_log("segfaulting from setup_frame\n");
Riku Voipio66393fb2009-12-04 15:16:32 +02004733 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004734}
4735
4736static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004737 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004738 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004739{
4740 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05004741 uint32_t *trampptr = 0;
4742 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004743 target_ulong rt_sf_addr, newsp = 0;
4744 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004745#if defined(TARGET_PPC64)
4746 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4747#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004748
4749 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4750 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4751 goto sigsegv;
4752
Peter Maydellf6c7a052015-01-08 12:19:48 +00004753 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07004754
Riku Voipio1d8b5122014-04-23 10:26:05 +03004755 __put_user(0, &rt_sf->uc.tuc_flags);
4756 __put_user(0, &rt_sf->uc.tuc_link);
4757 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4758 &rt_sf->uc.tuc_stack.ss_sp);
4759 __put_user(sas_ss_flags(env->gpr[1]),
4760 &rt_sf->uc.tuc_stack.ss_flags);
4761 __put_user(target_sigaltstack_used.ss_size,
4762 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05004763#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03004764 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4765 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05004766#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004767 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004768 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004769 }
4770
Tom Musta61e75fe2014-06-30 08:13:38 -05004771#if defined(TARGET_PPC64)
4772 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
4773 trampptr = &rt_sf->trampoline[0];
4774#else
4775 mctx = &rt_sf->uc.tuc_mcontext;
4776 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
4777#endif
4778
4779 save_user_regs(env, mctx);
4780 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004781
4782 /* The kernel checks for the presence of a VDSO here. We don't
4783 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05004784 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004785
4786 /* Turn off all fp exceptions. */
4787 env->fpscr = 0;
4788
4789 /* Create a stack frame for the caller of the handler. */
4790 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05004791 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004792
4793 if (err)
4794 goto sigsegv;
4795
4796 /* Set up registers for signal handler. */
4797 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004798 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07004799 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4800 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4801 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05004802
4803#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004804 if (get_ppc64_abi(image) < 2) {
4805 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4806 struct target_func_ptr *handler =
4807 (struct target_func_ptr *)g2h(ka->_sa_handler);
4808 env->nip = tswapl(handler->entry);
4809 env->gpr[2] = tswapl(handler->toc);
4810 } else {
4811 /* ELFv2 PPC64 function pointers are entry points, but R12
4812 * must also be set */
4813 env->nip = tswapl((target_ulong) ka->_sa_handler);
4814 env->gpr[12] = env->nip;
4815 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004816#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004817 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004818#endif
4819
Nathan Froydbcd49332009-05-12 19:13:18 -07004820 /* Signal handlers are entered in big-endian mode. */
4821 env->msr &= ~MSR_LE;
4822
4823 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4824 return;
4825
4826sigsegv:
4827 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Blue Swirleeacee42012-06-03 16:35:32 +00004828 qemu_log("segfaulting from setup_rt_frame\n");
Riku Voipio66393fb2009-12-04 15:16:32 +02004829 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004830
4831}
4832
Andreas Färber05390242012-02-25 03:37:53 +01004833long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004834{
4835 struct target_sigcontext *sc = NULL;
4836 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01004837 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07004838 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004839 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004840
4841 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4842 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4843 goto sigsegv;
4844
4845#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05004846 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07004847#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03004848 __get_user(set.sig[0], &sc->oldmask);
4849 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004850#endif
4851 target_to_host_sigset_internal(&blocked, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004852 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
Nathan Froydbcd49332009-05-12 19:13:18 -07004853
Riku Voipiof5f601a2014-04-23 13:00:17 +03004854 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004855 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4856 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03004857 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07004858
4859 unlock_user_struct(sr, sr_addr, 1);
4860 unlock_user_struct(sc, sc_addr, 1);
4861 return -TARGET_QEMU_ESIGRETURN;
4862
4863sigsegv:
4864 unlock_user_struct(sr, sr_addr, 1);
4865 unlock_user_struct(sc, sc_addr, 1);
Blue Swirleeacee42012-06-03 16:35:32 +00004866 qemu_log("segfaulting from do_sigreturn\n");
Riku Voipio66393fb2009-12-04 15:16:32 +02004867 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004868 return 0;
4869}
4870
4871/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01004872static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004873{
4874 struct target_mcontext *mcp;
4875 target_ulong mcp_addr;
4876 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004877 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004878
Aurelien Jarno60e99242010-03-29 02:12:51 +02004879 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07004880 sizeof (set)))
4881 return 1;
4882
Tom Musta19774ec2014-06-30 08:13:40 -05004883#if defined(TARGET_PPC64)
4884 mcp_addr = h2g(ucp) +
4885 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
4886#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03004887 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05004888#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004889
4890 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4891 return 1;
4892
4893 target_to_host_sigset_internal(&blocked, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004894 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
Riku Voipioc650c002014-04-23 13:53:45 +03004895 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07004896
4897 unlock_user_struct(mcp, mcp_addr, 1);
4898 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004899}
4900
Andreas Färber05390242012-02-25 03:37:53 +01004901long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004902{
4903 struct target_rt_sigframe *rt_sf = NULL;
4904 target_ulong rt_sf_addr;
4905
4906 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4907 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4908 goto sigsegv;
4909
4910 if (do_setcontext(&rt_sf->uc, env, 1))
4911 goto sigsegv;
4912
4913 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02004914 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07004915 0, env->gpr[1]);
4916
4917 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4918 return -TARGET_QEMU_ESIGRETURN;
4919
4920sigsegv:
4921 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Blue Swirleeacee42012-06-03 16:35:32 +00004922 qemu_log("segfaulting from do_rt_sigreturn\n");
Riku Voipio66393fb2009-12-04 15:16:32 +02004923 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004924 return 0;
4925}
4926
Laurent Vivier492a8742009-08-03 16:12:17 +02004927#elif defined(TARGET_M68K)
4928
4929struct target_sigcontext {
4930 abi_ulong sc_mask;
4931 abi_ulong sc_usp;
4932 abi_ulong sc_d0;
4933 abi_ulong sc_d1;
4934 abi_ulong sc_a0;
4935 abi_ulong sc_a1;
4936 unsigned short sc_sr;
4937 abi_ulong sc_pc;
4938};
4939
4940struct target_sigframe
4941{
4942 abi_ulong pretcode;
4943 int sig;
4944 int code;
4945 abi_ulong psc;
4946 char retcode[8];
4947 abi_ulong extramask[TARGET_NSIG_WORDS-1];
4948 struct target_sigcontext sc;
4949};
Laurent Vivier71811552009-08-03 16:12:18 +02004950
Anthony Liguoric227f092009-10-01 16:12:16 -05004951typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004952#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05004953typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02004954
4955typedef struct target_fpregset {
4956 int f_fpcntl[3];
4957 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05004958} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004959
4960struct target_mcontext {
4961 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05004962 target_gregset_t gregs;
4963 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02004964};
4965
4966#define TARGET_MCONTEXT_VERSION 2
4967
4968struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004969 abi_ulong tuc_flags;
4970 abi_ulong tuc_link;
4971 target_stack_t tuc_stack;
4972 struct target_mcontext tuc_mcontext;
4973 abi_long tuc_filler[80];
4974 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02004975};
4976
4977struct target_rt_sigframe
4978{
4979 abi_ulong pretcode;
4980 int sig;
4981 abi_ulong pinfo;
4982 abi_ulong puc;
4983 char retcode[8];
4984 struct target_siginfo info;
4985 struct target_ucontext uc;
4986};
Laurent Vivier492a8742009-08-03 16:12:17 +02004987
Riku Voipio41ecc722014-04-23 11:01:00 +03004988static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
4989 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02004990{
Riku Voipio1d8b5122014-04-23 10:26:05 +03004991 __put_user(mask, &sc->sc_mask);
4992 __put_user(env->aregs[7], &sc->sc_usp);
4993 __put_user(env->dregs[0], &sc->sc_d0);
4994 __put_user(env->dregs[1], &sc->sc_d1);
4995 __put_user(env->aregs[0], &sc->sc_a0);
4996 __put_user(env->aregs[1], &sc->sc_a1);
4997 __put_user(env->sr, &sc->sc_sr);
4998 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02004999}
5000
Riku Voipio016d2e12014-04-23 11:19:48 +03005001static void
Andreas Färber05390242012-02-25 03:37:53 +01005002restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0)
Laurent Vivier492a8742009-08-03 16:12:17 +02005003{
Laurent Vivier492a8742009-08-03 16:12:17 +02005004 int temp;
5005
Riku Voipio1d8b5122014-04-23 10:26:05 +03005006 __get_user(env->aregs[7], &sc->sc_usp);
5007 __get_user(env->dregs[1], &sc->sc_d1);
5008 __get_user(env->aregs[0], &sc->sc_a0);
5009 __get_user(env->aregs[1], &sc->sc_a1);
5010 __get_user(env->pc, &sc->sc_pc);
5011 __get_user(temp, &sc->sc_sr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005012 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5013
5014 *pd0 = tswapl(sc->sc_d0);
Laurent Vivier492a8742009-08-03 16:12:17 +02005015}
5016
5017/*
5018 * Determine which stack to use..
5019 */
5020static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005021get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5022 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005023{
5024 unsigned long sp;
5025
5026 sp = regs->aregs[7];
5027
5028 /* This is the X/Open sanctioned signal stack switching. */
5029 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5030 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5031 }
5032
5033 return ((sp - frame_size) & -8UL);
5034}
5035
5036static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005037 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005038{
5039 struct target_sigframe *frame;
5040 abi_ulong frame_addr;
5041 abi_ulong retcode_addr;
5042 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005043 int i;
5044
5045 frame_addr = get_sigframe(ka, env, sizeof *frame);
5046 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
5047 goto give_sigsegv;
5048
Riku Voipio1d8b5122014-04-23 10:26:05 +03005049 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005050
5051 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005052 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005053
Riku Voipio41ecc722014-04-23 11:01:00 +03005054 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005055
5056 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005057 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005058 }
5059
5060 /* Set up to return from userspace. */
5061
5062 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005063 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005064
5065 /* moveq #,d0; trap #0 */
5066
Riku Voipio1d8b5122014-04-23 10:26:05 +03005067 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005068 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005069
Laurent Vivier492a8742009-08-03 16:12:17 +02005070 /* Set up to return from userspace */
5071
5072 env->aregs[7] = frame_addr;
5073 env->pc = ka->_sa_handler;
5074
5075 unlock_user_struct(frame, frame_addr, 1);
5076 return;
5077
5078give_sigsegv:
Riku Voipio66393fb2009-12-04 15:16:32 +02005079 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005080}
5081
Laurent Vivier71811552009-08-03 16:12:18 +02005082static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005083 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005084{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005085 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005086
Riku Voipio1d8b5122014-04-23 10:26:05 +03005087 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5088 __put_user(env->dregs[0], &gregs[0]);
5089 __put_user(env->dregs[1], &gregs[1]);
5090 __put_user(env->dregs[2], &gregs[2]);
5091 __put_user(env->dregs[3], &gregs[3]);
5092 __put_user(env->dregs[4], &gregs[4]);
5093 __put_user(env->dregs[5], &gregs[5]);
5094 __put_user(env->dregs[6], &gregs[6]);
5095 __put_user(env->dregs[7], &gregs[7]);
5096 __put_user(env->aregs[0], &gregs[8]);
5097 __put_user(env->aregs[1], &gregs[9]);
5098 __put_user(env->aregs[2], &gregs[10]);
5099 __put_user(env->aregs[3], &gregs[11]);
5100 __put_user(env->aregs[4], &gregs[12]);
5101 __put_user(env->aregs[5], &gregs[13]);
5102 __put_user(env->aregs[6], &gregs[14]);
5103 __put_user(env->aregs[7], &gregs[15]);
5104 __put_user(env->pc, &gregs[16]);
5105 __put_user(env->sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005106
Riku Voipio1d8b5122014-04-23 10:26:05 +03005107 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005108}
5109
Andreas Färber05390242012-02-25 03:37:53 +01005110static inline int target_rt_restore_ucontext(CPUM68KState *env,
Laurent Vivier71811552009-08-03 16:12:18 +02005111 struct target_ucontext *uc,
5112 int *pd0)
5113{
5114 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005115 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005116
Riku Voipio1d8b5122014-04-23 10:26:05 +03005117 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005118 if (temp != TARGET_MCONTEXT_VERSION)
5119 goto badframe;
5120
5121 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005122 __get_user(env->dregs[0], &gregs[0]);
5123 __get_user(env->dregs[1], &gregs[1]);
5124 __get_user(env->dregs[2], &gregs[2]);
5125 __get_user(env->dregs[3], &gregs[3]);
5126 __get_user(env->dregs[4], &gregs[4]);
5127 __get_user(env->dregs[5], &gregs[5]);
5128 __get_user(env->dregs[6], &gregs[6]);
5129 __get_user(env->dregs[7], &gregs[7]);
5130 __get_user(env->aregs[0], &gregs[8]);
5131 __get_user(env->aregs[1], &gregs[9]);
5132 __get_user(env->aregs[2], &gregs[10]);
5133 __get_user(env->aregs[3], &gregs[11]);
5134 __get_user(env->aregs[4], &gregs[12]);
5135 __get_user(env->aregs[5], &gregs[13]);
5136 __get_user(env->aregs[6], &gregs[14]);
5137 __get_user(env->aregs[7], &gregs[15]);
5138 __get_user(env->pc, &gregs[16]);
5139 __get_user(temp, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005140 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5141
5142 *pd0 = env->dregs[0];
Riku Voipio1d8b5122014-04-23 10:26:05 +03005143 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005144
5145badframe:
5146 return 1;
5147}
5148
Laurent Vivier492a8742009-08-03 16:12:17 +02005149static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005150 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005151 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005152{
Laurent Vivier71811552009-08-03 16:12:18 +02005153 struct target_rt_sigframe *frame;
5154 abi_ulong frame_addr;
5155 abi_ulong retcode_addr;
5156 abi_ulong info_addr;
5157 abi_ulong uc_addr;
5158 int err = 0;
5159 int i;
5160
5161 frame_addr = get_sigframe(ka, env, sizeof *frame);
5162 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
5163 goto give_sigsegv;
5164
Riku Voipio1d8b5122014-04-23 10:26:05 +03005165 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005166
5167 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005168 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005169
5170 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005171 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005172
Peter Maydellf6c7a052015-01-08 12:19:48 +00005173 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005174
5175 /* Create the ucontext */
5176
Riku Voipio1d8b5122014-04-23 10:26:05 +03005177 __put_user(0, &frame->uc.tuc_flags);
5178 __put_user(0, &frame->uc.tuc_link);
5179 __put_user(target_sigaltstack_used.ss_sp,
5180 &frame->uc.tuc_stack.ss_sp);
5181 __put_user(sas_ss_flags(env->aregs[7]),
5182 &frame->uc.tuc_stack.ss_flags);
5183 __put_user(target_sigaltstack_used.ss_size,
5184 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005185 err |= target_rt_setup_ucontext(&frame->uc, env);
5186
5187 if (err)
5188 goto give_sigsegv;
5189
5190 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005191 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005192 }
5193
5194 /* Set up to return from userspace. */
5195
5196 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005197 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005198
5199 /* moveq #,d0; notb d0; trap #0 */
5200
Riku Voipio1d8b5122014-04-23 10:26:05 +03005201 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005202 (uint32_t *)(frame->retcode + 0));
5203 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005204
5205 if (err)
5206 goto give_sigsegv;
5207
5208 /* Set up to return from userspace */
5209
5210 env->aregs[7] = frame_addr;
5211 env->pc = ka->_sa_handler;
5212
5213 unlock_user_struct(frame, frame_addr, 1);
5214 return;
5215
5216give_sigsegv:
5217 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005218 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005219}
5220
Andreas Färber05390242012-02-25 03:37:53 +01005221long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005222{
5223 struct target_sigframe *frame;
5224 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005225 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005226 sigset_t set;
5227 int d0, i;
5228
5229 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5230 goto badframe;
5231
5232 /* set blocked signals */
5233
Riku Voipiof5f601a2014-04-23 13:00:17 +03005234 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005235
5236 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005237 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005238 }
5239
5240 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005241 do_sigprocmask(SIG_SETMASK, &set, NULL);
Laurent Vivier492a8742009-08-03 16:12:17 +02005242
5243 /* restore registers */
5244
Riku Voipio016d2e12014-04-23 11:19:48 +03005245 restore_sigcontext(env, &frame->sc, &d0);
Laurent Vivier492a8742009-08-03 16:12:17 +02005246
5247 unlock_user_struct(frame, frame_addr, 0);
5248 return d0;
5249
5250badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005251 force_sig(TARGET_SIGSEGV);
5252 return 0;
5253}
5254
Andreas Färber05390242012-02-25 03:37:53 +01005255long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005256{
Laurent Vivier71811552009-08-03 16:12:18 +02005257 struct target_rt_sigframe *frame;
5258 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005259 target_sigset_t target_set;
Laurent Vivier71811552009-08-03 16:12:18 +02005260 sigset_t set;
5261 int d0;
5262
5263 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5264 goto badframe;
5265
5266 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005267 do_sigprocmask(SIG_SETMASK, &set, NULL);
Laurent Vivier71811552009-08-03 16:12:18 +02005268
5269 /* restore registers */
5270
5271 if (target_rt_restore_ucontext(env, &frame->uc, &d0))
5272 goto badframe;
5273
5274 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02005275 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02005276 0, get_sp_from_cpustate(env)) == -EFAULT)
5277 goto badframe;
5278
5279 unlock_user_struct(frame, frame_addr, 0);
5280 return d0;
5281
5282badframe:
5283 unlock_user_struct(frame, frame_addr, 0);
5284 force_sig(TARGET_SIGSEGV);
5285 return 0;
Laurent Vivier492a8742009-08-03 16:12:17 +02005286}
5287
Richard Henderson6049f4f2009-12-27 18:30:03 -08005288#elif defined(TARGET_ALPHA)
5289
5290struct target_sigcontext {
5291 abi_long sc_onstack;
5292 abi_long sc_mask;
5293 abi_long sc_pc;
5294 abi_long sc_ps;
5295 abi_long sc_regs[32];
5296 abi_long sc_ownedfp;
5297 abi_long sc_fpregs[32];
5298 abi_ulong sc_fpcr;
5299 abi_ulong sc_fp_control;
5300 abi_ulong sc_reserved1;
5301 abi_ulong sc_reserved2;
5302 abi_ulong sc_ssize;
5303 abi_ulong sc_sbase;
5304 abi_ulong sc_traparg_a0;
5305 abi_ulong sc_traparg_a1;
5306 abi_ulong sc_traparg_a2;
5307 abi_ulong sc_fp_trap_pc;
5308 abi_ulong sc_fp_trigger_sum;
5309 abi_ulong sc_fp_trigger_inst;
5310};
5311
5312struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005313 abi_ulong tuc_flags;
5314 abi_ulong tuc_link;
5315 abi_ulong tuc_osf_sigmask;
5316 target_stack_t tuc_stack;
5317 struct target_sigcontext tuc_mcontext;
5318 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005319};
5320
5321struct target_sigframe {
5322 struct target_sigcontext sc;
5323 unsigned int retcode[3];
5324};
5325
5326struct target_rt_sigframe {
5327 target_siginfo_t info;
5328 struct target_ucontext uc;
5329 unsigned int retcode[3];
5330};
5331
5332#define INSN_MOV_R30_R16 0x47fe0410
5333#define INSN_LDI_R0 0x201f0000
5334#define INSN_CALLSYS 0x00000083
5335
Riku Voipio41ecc722014-04-23 11:01:00 +03005336static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Richard Henderson6049f4f2009-12-27 18:30:03 -08005337 abi_ulong frame_addr, target_sigset_t *set)
5338{
Riku Voipio41ecc722014-04-23 11:01:00 +03005339 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005340
Riku Voipio1d8b5122014-04-23 10:26:05 +03005341 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5342 __put_user(set->sig[0], &sc->sc_mask);
5343 __put_user(env->pc, &sc->sc_pc);
5344 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005345
5346 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005347 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005348 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005349 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005350
5351 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005352 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005353 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005354 __put_user(0, &sc->sc_fpregs[31]);
5355 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005356
Riku Voipio1d8b5122014-04-23 10:26:05 +03005357 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5358 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5359 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08005360}
5361
Riku Voipio016d2e12014-04-23 11:19:48 +03005362static void restore_sigcontext(CPUAlphaState *env,
Andreas Färber05390242012-02-25 03:37:53 +01005363 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005364{
5365 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03005366 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005367
Riku Voipio1d8b5122014-04-23 10:26:05 +03005368 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005369
5370 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005371 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005372 }
5373 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005374 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005375 }
5376
Riku Voipio1d8b5122014-04-23 10:26:05 +03005377 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005378 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005379}
5380
5381static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01005382 CPUAlphaState *env,
5383 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005384{
5385 abi_ulong sp = env->ir[IR_SP];
5386
5387 /* This is the X/Open sanctioned signal stack switching. */
5388 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5389 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5390 }
5391 return (sp - framesize) & -32;
5392}
5393
5394static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005395 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005396{
5397 abi_ulong frame_addr, r26;
5398 struct target_sigframe *frame;
5399 int err = 0;
5400
5401 frame_addr = get_sigframe(ka, env, sizeof(*frame));
5402 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5403 goto give_sigsegv;
5404 }
5405
Riku Voipio41ecc722014-04-23 11:01:00 +03005406 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005407
5408 if (ka->sa_restorer) {
5409 r26 = ka->sa_restorer;
5410 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005411 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5412 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5413 &frame->retcode[1]);
5414 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005415 /* imb() */
5416 r26 = frame_addr;
5417 }
5418
5419 unlock_user_struct(frame, frame_addr, 1);
5420
5421 if (err) {
5422 give_sigsegv:
5423 if (sig == TARGET_SIGSEGV) {
5424 ka->_sa_handler = TARGET_SIG_DFL;
5425 }
5426 force_sig(TARGET_SIGSEGV);
5427 }
5428
5429 env->ir[IR_RA] = r26;
5430 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5431 env->ir[IR_A0] = sig;
5432 env->ir[IR_A1] = 0;
5433 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5434 env->ir[IR_SP] = frame_addr;
5435}
5436
5437static void setup_rt_frame(int sig, struct target_sigaction *ka,
5438 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005439 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005440{
5441 abi_ulong frame_addr, r26;
5442 struct target_rt_sigframe *frame;
5443 int i, err = 0;
5444
5445 frame_addr = get_sigframe(ka, env, sizeof(*frame));
5446 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5447 goto give_sigsegv;
5448 }
5449
Peter Maydellf6c7a052015-01-08 12:19:48 +00005450 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005451
Riku Voipio1d8b5122014-04-23 10:26:05 +03005452 __put_user(0, &frame->uc.tuc_flags);
5453 __put_user(0, &frame->uc.tuc_link);
5454 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5455 __put_user(target_sigaltstack_used.ss_sp,
5456 &frame->uc.tuc_stack.ss_sp);
5457 __put_user(sas_ss_flags(env->ir[IR_SP]),
5458 &frame->uc.tuc_stack.ss_flags);
5459 __put_user(target_sigaltstack_used.ss_size,
5460 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03005461 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005462 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005463 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005464 }
5465
5466 if (ka->sa_restorer) {
5467 r26 = ka->sa_restorer;
5468 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005469 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5470 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5471 &frame->retcode[1]);
5472 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005473 /* imb(); */
5474 r26 = frame_addr;
5475 }
5476
5477 if (err) {
5478 give_sigsegv:
5479 if (sig == TARGET_SIGSEGV) {
5480 ka->_sa_handler = TARGET_SIG_DFL;
5481 }
5482 force_sig(TARGET_SIGSEGV);
5483 }
5484
5485 env->ir[IR_RA] = r26;
5486 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5487 env->ir[IR_A0] = sig;
5488 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5489 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5490 env->ir[IR_SP] = frame_addr;
5491}
5492
Andreas Färber05390242012-02-25 03:37:53 +01005493long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005494{
5495 struct target_sigcontext *sc;
5496 abi_ulong sc_addr = env->ir[IR_A0];
5497 target_sigset_t target_set;
5498 sigset_t set;
5499
5500 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5501 goto badframe;
5502 }
5503
5504 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03005505 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005506
5507 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005508 do_sigprocmask(SIG_SETMASK, &set, NULL);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005509
Riku Voipio016d2e12014-04-23 11:19:48 +03005510 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005511 unlock_user_struct(sc, sc_addr, 0);
5512 return env->ir[IR_V0];
5513
5514 badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005515 force_sig(TARGET_SIGSEGV);
5516}
5517
Andreas Färber05390242012-02-25 03:37:53 +01005518long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005519{
5520 abi_ulong frame_addr = env->ir[IR_A0];
5521 struct target_rt_sigframe *frame;
5522 sigset_t set;
5523
5524 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5525 goto badframe;
5526 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02005527 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00005528 do_sigprocmask(SIG_SETMASK, &set, NULL);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005529
Riku Voipio016d2e12014-04-23 11:19:48 +03005530 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005531 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02005532 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08005533 0, env->ir[IR_SP]) == -EFAULT) {
5534 goto badframe;
5535 }
5536
5537 unlock_user_struct(frame, frame_addr, 0);
5538 return env->ir[IR_V0];
5539
5540
5541 badframe:
5542 unlock_user_struct(frame, frame_addr, 0);
5543 force_sig(TARGET_SIGSEGV);
5544}
5545
bellardb346ff42003-06-15 20:05:50 +00005546#else
5547
pbrook624f7972008-05-31 16:11:38 +00005548static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber9349b4f2012-03-14 01:38:32 +01005549 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005550{
5551 fprintf(stderr, "setup_frame: not implemented\n");
5552}
5553
pbrook624f7972008-05-31 16:11:38 +00005554static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005555 target_siginfo_t *info,
Andreas Färber9349b4f2012-03-14 01:38:32 +01005556 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005557{
5558 fprintf(stderr, "setup_rt_frame: not implemented\n");
5559}
5560
Andreas Färber9349b4f2012-03-14 01:38:32 +01005561long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005562{
5563 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005564 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005565}
5566
Andreas Färber9349b4f2012-03-14 01:38:32 +01005567long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005568{
5569 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005570 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005571}
5572
bellard66fb9762003-03-23 01:06:05 +00005573#endif
5574
Andreas Färber9349b4f2012-03-14 01:38:32 +01005575void process_pending_signals(CPUArchState *cpu_env)
bellard66fb9762003-03-23 01:06:05 +00005576{
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005577 CPUState *cpu = ENV_GET_CPU(cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005578 int sig;
blueswir1992f48a2007-10-14 16:27:31 +00005579 abi_ulong handler;
bellard9de5e442003-03-23 16:49:39 +00005580 sigset_t set, old_set;
Anthony Liguoric227f092009-10-01 16:12:16 -05005581 target_sigset_t target_old_set;
pbrook624f7972008-05-31 16:11:38 +00005582 struct emulated_sigtable *k;
5583 struct target_sigaction *sa;
bellard66fb9762003-03-23 01:06:05 +00005584 struct sigqueue *q;
Andreas Färber0429a972013-08-26 18:14:44 +02005585 TaskState *ts = cpu->opaque;
ths3b46e622007-09-17 08:09:54 +00005586
pbrook624f7972008-05-31 16:11:38 +00005587 if (!ts->signal_pending)
bellard31e31b82003-02-18 22:55:36 +00005588 return;
5589
pbrook624f7972008-05-31 16:11:38 +00005590 /* FIXME: This is not threadsafe. */
5591 k = ts->sigtab;
bellard66fb9762003-03-23 01:06:05 +00005592 for(sig = 1; sig <= TARGET_NSIG; sig++) {
5593 if (k->pending)
bellard31e31b82003-02-18 22:55:36 +00005594 goto handle_signal;
bellard66fb9762003-03-23 01:06:05 +00005595 k++;
bellard31e31b82003-02-18 22:55:36 +00005596 }
5597 /* if no signal is pending, just return */
pbrook624f7972008-05-31 16:11:38 +00005598 ts->signal_pending = 0;
bellard31e31b82003-02-18 22:55:36 +00005599 return;
bellard66fb9762003-03-23 01:06:05 +00005600
bellard31e31b82003-02-18 22:55:36 +00005601 handle_signal:
bellard66fb9762003-03-23 01:06:05 +00005602#ifdef DEBUG_SIGNAL
bellardbc8a22c2003-03-30 21:02:40 +00005603 fprintf(stderr, "qemu: process signal %d\n", sig);
bellard66fb9762003-03-23 01:06:05 +00005604#endif
5605 /* dequeue signal */
5606 q = k->first;
5607 k->first = q->next;
5608 if (!k->first)
5609 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00005610
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005611 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00005612 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00005613 sa = NULL;
5614 handler = TARGET_SIG_IGN;
5615 } else {
5616 sa = &sigact_table[sig - 1];
5617 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00005618 }
bellard66fb9762003-03-23 01:06:05 +00005619
Peter Maydella7ec0f92014-03-14 14:36:56 +00005620 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
5621 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
5622 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
5623 * because it got a real MMU fault), and treat as if default handler.
5624 */
5625 handler = TARGET_SIG_DFL;
5626 }
5627
bellard66fb9762003-03-23 01:06:05 +00005628 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00005629 /* default handler : ignore some signal. The other are job control or fatal */
5630 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5631 kill(getpid(),SIGSTOP);
5632 } else if (sig != TARGET_SIGCHLD &&
5633 sig != TARGET_SIGURG &&
5634 sig != TARGET_SIGWINCH &&
5635 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +00005636 force_sig(sig);
5637 }
5638 } else if (handler == TARGET_SIG_IGN) {
5639 /* ignore sig */
5640 } else if (handler == TARGET_SIG_ERR) {
5641 force_sig(sig);
5642 } else {
bellard9de5e442003-03-23 16:49:39 +00005643 /* compute the blocked signals during the handler execution */
pbrook624f7972008-05-31 16:11:38 +00005644 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00005645 /* SA_NODEFER indicates that the current signal should not be
5646 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00005647 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00005648 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00005649
bellard9de5e442003-03-23 16:49:39 +00005650 /* block signals in the handler using Linux */
Alex Barcelo1c275922014-03-14 14:36:55 +00005651 do_sigprocmask(SIG_BLOCK, &set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005652 /* save the previous blocked signal state to restore it at the
5653 end of the signal execution (see do_sigreturn) */
bellard92319442004-06-19 16:58:13 +00005654 host_to_target_sigset_internal(&target_old_set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005655
bellardbc8a22c2003-03-30 21:02:40 +00005656 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00005657#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00005658 {
5659 CPUX86State *env = cpu_env;
5660 if (env->eflags & VM_MASK)
5661 save_v86_state(env);
5662 }
5663#endif
bellard9de5e442003-03-23 16:49:39 +00005664 /* prepare the stack frame of the virtual CPU */
Richard Hendersonff970902013-02-10 10:30:42 -08005665#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
5666 /* These targets do not have traditional signals. */
5667 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
5668#else
pbrook624f7972008-05-31 16:11:38 +00005669 if (sa->sa_flags & TARGET_SA_SIGINFO)
5670 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005671 else
pbrook624f7972008-05-31 16:11:38 +00005672 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005673#endif
pbrook624f7972008-05-31 16:11:38 +00005674 if (sa->sa_flags & TARGET_SA_RESETHAND)
5675 sa->_sa_handler = TARGET_SIG_DFL;
bellard31e31b82003-02-18 22:55:36 +00005676 }
bellard66fb9762003-03-23 01:06:05 +00005677 if (q != &k->info)
pbrook624f7972008-05-31 16:11:38 +00005678 free_sigqueue(cpu_env, q);
bellard31e31b82003-02-18 22:55:36 +00005679}