blob: 2c6790d87280812c8fbb76e0f4bdb254dc91ebba [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
bellard31e31b82003-02-18 22:55:36 +000020#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030021#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000022
bellard3ef693a2003-03-23 20:17:16 +000023#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000024#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000025#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010026#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000027
blueswir1249c4c32008-10-05 11:09:37 +000028static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000029 .ss_sp = 0,
30 .ss_size = 0,
31 .ss_flags = TARGET_SS_DISABLE,
32};
33
pbrook624f7972008-05-31 16:11:38 +000034static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000035
ths5fafdf22007-09-16 21:08:06 +000036static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000037 void *puc);
38
Arnaud Patard3ca05582009-03-30 01:18:20 +020039static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000040 [SIGHUP] = TARGET_SIGHUP,
41 [SIGINT] = TARGET_SIGINT,
42 [SIGQUIT] = TARGET_SIGQUIT,
43 [SIGILL] = TARGET_SIGILL,
44 [SIGTRAP] = TARGET_SIGTRAP,
45 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000046/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000047 [SIGBUS] = TARGET_SIGBUS,
48 [SIGFPE] = TARGET_SIGFPE,
49 [SIGKILL] = TARGET_SIGKILL,
50 [SIGUSR1] = TARGET_SIGUSR1,
51 [SIGSEGV] = TARGET_SIGSEGV,
52 [SIGUSR2] = TARGET_SIGUSR2,
53 [SIGPIPE] = TARGET_SIGPIPE,
54 [SIGALRM] = TARGET_SIGALRM,
55 [SIGTERM] = TARGET_SIGTERM,
56#ifdef SIGSTKFLT
57 [SIGSTKFLT] = TARGET_SIGSTKFLT,
58#endif
59 [SIGCHLD] = TARGET_SIGCHLD,
60 [SIGCONT] = TARGET_SIGCONT,
61 [SIGSTOP] = TARGET_SIGSTOP,
62 [SIGTSTP] = TARGET_SIGTSTP,
63 [SIGTTIN] = TARGET_SIGTTIN,
64 [SIGTTOU] = TARGET_SIGTTOU,
65 [SIGURG] = TARGET_SIGURG,
66 [SIGXCPU] = TARGET_SIGXCPU,
67 [SIGXFSZ] = TARGET_SIGXFSZ,
68 [SIGVTALRM] = TARGET_SIGVTALRM,
69 [SIGPROF] = TARGET_SIGPROF,
70 [SIGWINCH] = TARGET_SIGWINCH,
71 [SIGIO] = TARGET_SIGIO,
72 [SIGPWR] = TARGET_SIGPWR,
73 [SIGSYS] = TARGET_SIGSYS,
74 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000075 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080076 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000077 To fix this properly we need to do manual signal delivery multiplexed
78 over a single host signal. */
79 [__SIGRTMIN] = __SIGRTMAX,
80 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000081};
Arnaud Patard3ca05582009-03-30 01:18:20 +020082static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000083
thsa04e1342007-09-27 13:57:58 +000084static inline int on_sig_stack(unsigned long sp)
85{
86 return (sp - target_sigaltstack_used.ss_sp
87 < target_sigaltstack_used.ss_size);
88}
89
90static inline int sas_ss_flags(unsigned long sp)
91{
92 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
93 : on_sig_stack(sp) ? SS_ONSTACK : 0);
94}
95
pbrook1d9d8b52009-04-16 15:17:02 +000096int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000097{
Andreas Schwab167c50d2013-07-02 14:04:12 +010098 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +000099 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000100 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000101}
102
pbrook4cb05962008-05-30 18:05:19 +0000103int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000104{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100105 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000106 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000107 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000108}
109
Anthony Liguoric227f092009-10-01 16:12:16 -0500110static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000111{
112 memset(set, 0, sizeof(*set));
113}
114
Anthony Liguoric227f092009-10-01 16:12:16 -0500115static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000116{
117 signum--;
118 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
119 set->sig[signum / TARGET_NSIG_BPW] |= mask;
120}
121
Anthony Liguoric227f092009-10-01 16:12:16 -0500122static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000123{
124 signum--;
125 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
126 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
127}
128
Anthony Liguoric227f092009-10-01 16:12:16 -0500129static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000130 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000131{
132 int i;
pbrookf5545b52008-05-30 22:37:07 +0000133 target_sigemptyset(d);
134 for (i = 1; i <= TARGET_NSIG; i++) {
135 if (sigismember(s, i)) {
136 target_sigaddset(d, host_to_target_signal(i));
137 }
bellard9e5f5282003-07-13 17:33:54 +0000138 }
bellard66fb9762003-03-23 01:06:05 +0000139}
140
Anthony Liguoric227f092009-10-01 16:12:16 -0500141void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000142{
Anthony Liguoric227f092009-10-01 16:12:16 -0500143 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000144 int i;
145
146 host_to_target_sigset_internal(&d1, s);
147 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200148 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000149}
150
blueswir18fcd3692008-08-17 20:26:25 +0000151static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500152 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000153{
154 int i;
pbrookf5545b52008-05-30 22:37:07 +0000155 sigemptyset(d);
156 for (i = 1; i <= TARGET_NSIG; i++) {
157 if (target_sigismember(s, i)) {
158 sigaddset(d, target_to_host_signal(i));
159 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100160 }
bellard66fb9762003-03-23 01:06:05 +0000161}
162
Anthony Liguoric227f092009-10-01 16:12:16 -0500163void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000164{
Anthony Liguoric227f092009-10-01 16:12:16 -0500165 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000166 int i;
167
168 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200169 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000170 target_to_host_sigset_internal(d, &s1);
171}
ths3b46e622007-09-17 08:09:54 +0000172
blueswir1992f48a2007-10-14 16:27:31 +0000173void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000174 const sigset_t *sigset)
175{
Anthony Liguoric227f092009-10-01 16:12:16 -0500176 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000177 host_to_target_sigset(&d, sigset);
178 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000179}
180
ths5fafdf22007-09-16 21:08:06 +0000181void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000182 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000183{
Anthony Liguoric227f092009-10-01 16:12:16 -0500184 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000185 int i;
186
187 d.sig[0] = *old_sigset;
188 for(i = 1;i < TARGET_NSIG_WORDS; i++)
189 d.sig[i] = 0;
190 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000191}
192
Peter Maydell3d3efba2016-05-27 15:51:49 +0100193int block_signals(void)
194{
195 TaskState *ts = (TaskState *)thread_cpu->opaque;
196 sigset_t set;
197 int pending;
198
199 /* It's OK to block everything including SIGSEGV, because we won't
200 * run any further guest code before unblocking signals in
201 * process_pending_signals().
202 */
203 sigfillset(&set);
204 sigprocmask(SIG_SETMASK, &set, 0);
205
206 pending = atomic_xchg(&ts->signal_pending, 1);
207
208 return pending;
209}
210
Alex Barcelo1c275922014-03-14 14:36:55 +0000211/* Wrapper for sigprocmask function
212 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
Peter Maydell3d3efba2016-05-27 15:51:49 +0100213 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
214 * a signal was already pending and the syscall must be restarted, or
215 * 0 on success.
216 * If set is NULL, this is guaranteed not to fail.
Alex Barcelo1c275922014-03-14 14:36:55 +0000217 */
218int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
219{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100220 TaskState *ts = (TaskState *)thread_cpu->opaque;
221
222 if (oldset) {
223 *oldset = ts->signal_mask;
224 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000225
226 if (set) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100227 int i;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000228
Peter Maydell3d3efba2016-05-27 15:51:49 +0100229 if (block_signals()) {
230 return -TARGET_ERESTARTSYS;
231 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000232
233 switch (how) {
234 case SIG_BLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100235 sigorset(&ts->signal_mask, &ts->signal_mask, set);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000236 break;
237 case SIG_UNBLOCK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100238 for (i = 1; i <= NSIG; ++i) {
239 if (sigismember(set, i)) {
240 sigdelset(&ts->signal_mask, i);
241 }
Peter Maydella7ec0f92014-03-14 14:36:56 +0000242 }
243 break;
244 case SIG_SETMASK:
Peter Maydell3d3efba2016-05-27 15:51:49 +0100245 ts->signal_mask = *set;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000246 break;
247 default:
248 g_assert_not_reached();
249 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100250
251 /* Silently ignore attempts to change blocking status of KILL or STOP */
252 sigdelset(&ts->signal_mask, SIGKILL);
253 sigdelset(&ts->signal_mask, SIGSTOP);
Peter Maydella7ec0f92014-03-14 14:36:56 +0000254 }
Peter Maydell3d3efba2016-05-27 15:51:49 +0100255 return 0;
Alex Barcelo1c275922014-03-14 14:36:55 +0000256}
257
Peter Maydell9eede5b2016-05-27 15:51:46 +0100258#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
259 !defined(TARGET_X86_64)
Peter Maydell3d3efba2016-05-27 15:51:49 +0100260/* Just set the guest's signal mask to the specified value; the
261 * caller is assumed to have called block_signals() already.
262 */
Peter Maydell9eede5b2016-05-27 15:51:46 +0100263static void set_sigmask(const sigset_t *set)
264{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100265 TaskState *ts = (TaskState *)thread_cpu->opaque;
266
267 ts->signal_mask = *set;
Peter Maydell9eede5b2016-05-27 15:51:46 +0100268}
269#endif
270
bellard9de5e442003-03-23 16:49:39 +0000271/* siginfo conversion */
272
Anthony Liguoric227f092009-10-01 16:12:16 -0500273static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000274 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000275{
Richard Hendersona05c6402012-09-15 11:34:20 -0700276 int sig = host_to_target_signal(info->si_signo);
bellard9de5e442003-03-23 16:49:39 +0000277 tinfo->si_signo = sig;
278 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000279 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700280
281 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100282 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
Richard Hendersona05c6402012-09-15 11:34:20 -0700283 /* Should never come here, but who knows. The information for
284 the target is irrelevant. */
bellard9de5e442003-03-23 16:49:39 +0000285 tinfo->_sifields._sigfault._addr = 0;
Richard Hendersona05c6402012-09-15 11:34:20 -0700286 } else if (sig == TARGET_SIGIO) {
287 tinfo->_sifields._sigpoll._band = info->si_band;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100288 tinfo->_sifields._sigpoll._fd = info->si_fd;
Richard Hendersona05c6402012-09-15 11:34:20 -0700289 } else if (sig == TARGET_SIGCHLD) {
290 tinfo->_sifields._sigchld._pid = info->si_pid;
291 tinfo->_sifields._sigchld._uid = info->si_uid;
292 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100293 = host_to_target_waitstatus(info->si_status);
Richard Hendersona05c6402012-09-15 11:34:20 -0700294 tinfo->_sifields._sigchld._utime = info->si_utime;
295 tinfo->_sifields._sigchld._stime = info->si_stime;
bellard9de5e442003-03-23 16:49:39 +0000296 } else if (sig >= TARGET_SIGRTMIN) {
297 tinfo->_sifields._rt._pid = info->si_pid;
298 tinfo->_sifields._rt._uid = info->si_uid;
299 /* XXX: potential problem if 64 bit */
Richard Hendersona05c6402012-09-15 11:34:20 -0700300 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100301 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
bellard9de5e442003-03-23 16:49:39 +0000302 }
bellard66fb9762003-03-23 01:06:05 +0000303}
304
Anthony Liguoric227f092009-10-01 16:12:16 -0500305static void tswap_siginfo(target_siginfo_t *tinfo,
306 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000307{
Richard Hendersona05c6402012-09-15 11:34:20 -0700308 int sig = info->si_signo;
bellard9de5e442003-03-23 16:49:39 +0000309 tinfo->si_signo = tswap32(sig);
310 tinfo->si_errno = tswap32(info->si_errno);
311 tinfo->si_code = tswap32(info->si_code);
Richard Hendersona05c6402012-09-15 11:34:20 -0700312
313 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
314 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
315 tinfo->_sifields._sigfault._addr
316 = tswapal(info->_sifields._sigfault._addr);
317 } else if (sig == TARGET_SIGIO) {
318 tinfo->_sifields._sigpoll._band
319 = tswap32(info->_sifields._sigpoll._band);
320 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
321 } else if (sig == TARGET_SIGCHLD) {
322 tinfo->_sifields._sigchld._pid
323 = tswap32(info->_sifields._sigchld._pid);
324 tinfo->_sifields._sigchld._uid
325 = tswap32(info->_sifields._sigchld._uid);
326 tinfo->_sifields._sigchld._status
327 = tswap32(info->_sifields._sigchld._status);
328 tinfo->_sifields._sigchld._utime
329 = tswapal(info->_sifields._sigchld._utime);
330 tinfo->_sifields._sigchld._stime
331 = tswapal(info->_sifields._sigchld._stime);
bellard9de5e442003-03-23 16:49:39 +0000332 } else if (sig >= TARGET_SIGRTMIN) {
333 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
334 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
Richard Hendersona05c6402012-09-15 11:34:20 -0700335 tinfo->_sifields._rt._sigval.sival_ptr
336 = tswapal(info->_sifields._rt._sigval.sival_ptr);
bellard9de5e442003-03-23 16:49:39 +0000337 }
338}
339
340
Anthony Liguoric227f092009-10-01 16:12:16 -0500341void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000342{
343 host_to_target_siginfo_noswap(tinfo, info);
344 tswap_siginfo(tinfo, tinfo);
345}
346
347/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000348/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500349void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000350{
351 info->si_signo = tswap32(tinfo->si_signo);
352 info->si_errno = tswap32(tinfo->si_errno);
353 info->si_code = tswap32(tinfo->si_code);
bellard9de5e442003-03-23 16:49:39 +0000354 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
355 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
ths5fafdf22007-09-16 21:08:06 +0000356 info->si_value.sival_ptr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200357 (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr);
bellard66fb9762003-03-23 01:06:05 +0000358}
359
aurel32ca587a82008-12-18 22:44:13 +0000360static int fatal_signal (int sig)
361{
362 switch (sig) {
363 case TARGET_SIGCHLD:
364 case TARGET_SIGURG:
365 case TARGET_SIGWINCH:
366 /* Ignored by default. */
367 return 0;
368 case TARGET_SIGCONT:
369 case TARGET_SIGSTOP:
370 case TARGET_SIGTSTP:
371 case TARGET_SIGTTIN:
372 case TARGET_SIGTTOU:
373 /* Job control signals. */
374 return 0;
375 default:
376 return 1;
377 }
378}
379
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300380/* returns 1 if given signal should dump core if not handled */
381static int core_dump_signal(int sig)
382{
383 switch (sig) {
384 case TARGET_SIGABRT:
385 case TARGET_SIGFPE:
386 case TARGET_SIGILL:
387 case TARGET_SIGQUIT:
388 case TARGET_SIGSEGV:
389 case TARGET_SIGTRAP:
390 case TARGET_SIGBUS:
391 return (1);
392 default:
393 return (0);
394 }
395}
396
bellard31e31b82003-02-18 22:55:36 +0000397void signal_init(void)
398{
Peter Maydell3d3efba2016-05-27 15:51:49 +0100399 TaskState *ts = (TaskState *)thread_cpu->opaque;
bellard31e31b82003-02-18 22:55:36 +0000400 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000401 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000402 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000403 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000404
bellard9e5f5282003-07-13 17:33:54 +0000405 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200406 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000407 if (host_to_target_signal_table[i] == 0)
408 host_to_target_signal_table[i] = i;
409 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200410 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000411 j = host_to_target_signal_table[i];
412 target_to_host_signal_table[j] = i;
413 }
ths3b46e622007-09-17 08:09:54 +0000414
Peter Maydell3d3efba2016-05-27 15:51:49 +0100415 /* Set the signal mask from the host mask. */
416 sigprocmask(0, 0, &ts->signal_mask);
417
bellard9de5e442003-03-23 16:49:39 +0000418 /* set all host signal handlers. ALL signals are blocked during
419 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000420 memset(sigact_table, 0, sizeof(sigact_table));
421
bellard9de5e442003-03-23 16:49:39 +0000422 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000423 act.sa_flags = SA_SIGINFO;
424 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000425 for(i = 1; i <= TARGET_NSIG; i++) {
426 host_sig = target_to_host_signal(i);
427 sigaction(host_sig, NULL, &oact);
428 if (oact.sa_sigaction == (void *)SIG_IGN) {
429 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
430 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
431 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
432 }
433 /* If there's already a handler installed then something has
434 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000435 /* Install some handlers for our own use. We need at least
436 SIGSEGV and SIGBUS, to detect exceptions. We can not just
437 trap all signals because it affects syscall interrupt
438 behavior. But do trap all default-fatal signals. */
439 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000440 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000441 }
bellard31e31b82003-02-18 22:55:36 +0000442}
443
bellard66fb9762003-03-23 01:06:05 +0000444/* signal queue handling */
445
Andreas Färber9349b4f2012-03-14 01:38:32 +0100446static inline struct sigqueue *alloc_sigqueue(CPUArchState *env)
bellard66fb9762003-03-23 01:06:05 +0000447{
Andreas Färber0429a972013-08-26 18:14:44 +0200448 CPUState *cpu = ENV_GET_CPU(env);
449 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000450 struct sigqueue *q = ts->first_free;
bellard66fb9762003-03-23 01:06:05 +0000451 if (!q)
452 return NULL;
pbrook624f7972008-05-31 16:11:38 +0000453 ts->first_free = q->next;
bellard66fb9762003-03-23 01:06:05 +0000454 return q;
455}
456
Andreas Färber9349b4f2012-03-14 01:38:32 +0100457static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
bellard66fb9762003-03-23 01:06:05 +0000458{
Andreas Färber0429a972013-08-26 18:14:44 +0200459 CPUState *cpu = ENV_GET_CPU(env);
460 TaskState *ts = cpu->opaque;
461
pbrook624f7972008-05-31 16:11:38 +0000462 q->next = ts->first_free;
463 ts->first_free = q;
bellard66fb9762003-03-23 01:06:05 +0000464}
465
bellard9de5e442003-03-23 16:49:39 +0000466/* abort execution with signal */
Riku Voipio66393fb2009-12-04 15:16:32 +0200467static void QEMU_NORETURN force_sig(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000468{
Andreas Färber0429a972013-08-26 18:14:44 +0200469 CPUState *cpu = thread_cpu;
470 CPUArchState *env = cpu->env_ptr;
471 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300472 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000473 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100474
Riku Voipio66393fb2009-12-04 15:16:32 +0200475 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100476 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200477 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000478
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300479 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200480 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300481 stop_all_tasks();
482 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200483 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300484 }
485 if (core_dumped) {
486 /* we already dumped the core of target process, we don't want
487 * a coredump of qemu itself */
488 struct rlimit nodump;
489 getrlimit(RLIMIT_CORE, &nodump);
490 nodump.rlim_cur=0;
491 setrlimit(RLIMIT_CORE, &nodump);
492 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200493 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300494 }
495
Stefan Weil0c587512011-04-28 17:20:32 +0200496 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000497 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
498 * a negative value. To get the proper exit code we need to
499 * actually die from an uncaught signal. Here the default signal
500 * handler is installed, we send ourself a signal and we wait for
501 * it to arrive. */
502 sigfillset(&act.sa_mask);
503 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000504 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000505 sigaction(host_sig, &act, NULL);
506
507 /* For some reason raise(host_sig) doesn't send the signal when
508 * statically linked on x86-64. */
509 kill(getpid(), host_sig);
510
511 /* Make sure the signal isn't masked (just reuse the mask inside
512 of act) */
513 sigdelset(&act.sa_mask, host_sig);
514 sigsuspend(&act.sa_mask);
515
516 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000517 abort();
bellard66fb9762003-03-23 01:06:05 +0000518}
519
bellard9de5e442003-03-23 16:49:39 +0000520/* queue a signal so that it will be send to the virtual CPU as soon
521 as possible */
Andreas Färber9349b4f2012-03-14 01:38:32 +0100522int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000523{
Andreas Färber0429a972013-08-26 18:14:44 +0200524 CPUState *cpu = ENV_GET_CPU(env);
525 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000526 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000527 struct sigqueue *q, **pq;
bellard66fb9762003-03-23 01:06:05 +0000528
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100529 trace_user_queue_signal(env, sig);
pbrook624f7972008-05-31 16:11:38 +0000530 k = &ts->sigtab[sig - 1];
Peter Maydella7ec0f92014-03-14 14:36:56 +0000531
bellard9de5e442003-03-23 16:49:39 +0000532 pq = &k->first;
533 if (sig < TARGET_SIGRTMIN) {
534 /* if non real time signal, we queue exactly one signal */
535 if (!k->pending)
536 q = &k->info;
537 else
538 return 0;
539 } else {
540 if (!k->pending) {
541 /* first signal */
542 q = &k->info;
543 } else {
pbrook624f7972008-05-31 16:11:38 +0000544 q = alloc_sigqueue(env);
bellard9de5e442003-03-23 16:49:39 +0000545 if (!q)
546 return -EAGAIN;
547 while (*pq != NULL)
548 pq = &(*pq)->next;
549 }
550 }
551 *pq = q;
552 q->info = *info;
553 q->next = NULL;
554 k->pending = 1;
555 /* signal that a new signal is pending */
Peter Maydell3d3efba2016-05-27 15:51:49 +0100556 atomic_set(&ts->signal_pending, 1);
bellard9de5e442003-03-23 16:49:39 +0000557 return 1; /* indicates that the signal was queued */
bellard9de5e442003-03-23 16:49:39 +0000558}
559
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100560#ifndef HAVE_SAFE_SYSCALL
561static inline void rewind_if_in_safe_syscall(void *puc)
562{
563 /* Default version: never rewind */
564}
565#endif
566
ths5fafdf22007-09-16 21:08:06 +0000567static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000568 void *puc)
569{
Andreas Färbera2247f82013-06-09 19:47:04 +0200570 CPUArchState *env = thread_cpu->env_ptr;
bellard9de5e442003-03-23 16:49:39 +0000571 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500572 target_siginfo_t tinfo;
Peter Maydell3d3efba2016-05-27 15:51:49 +0100573 ucontext_t *uc = puc;
bellard9de5e442003-03-23 16:49:39 +0000574
575 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000576 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000577 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000578 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000579 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000580 return;
581 }
582
583 /* get target signal number */
584 sig = host_to_target_signal(host_signum);
585 if (sig < 1 || sig > TARGET_NSIG)
586 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100587 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100588
589 rewind_if_in_safe_syscall(puc);
590
bellard9de5e442003-03-23 16:49:39 +0000591 host_to_target_siginfo_noswap(&tinfo, info);
Andreas Färbera2247f82013-06-09 19:47:04 +0200592 if (queue_signal(env, sig, &tinfo) == 1) {
Peter Maydell3d3efba2016-05-27 15:51:49 +0100593 /* Block host signals until target signal handler entered. We
594 * can't block SIGSEGV or SIGBUS while we're executing guest
595 * code in case the guest code provokes one in the window between
596 * now and it getting out to the main loop. Signals will be
597 * unblocked again in process_pending_signals().
598 */
599 sigfillset(&uc->uc_sigmask);
600 sigdelset(&uc->uc_sigmask, SIGSEGV);
601 sigdelset(&uc->uc_sigmask, SIGBUS);
602
bellard9de5e442003-03-23 16:49:39 +0000603 /* interrupt the virtual CPU as soon as possible */
Andreas Färbera2247f82013-06-09 19:47:04 +0200604 cpu_exit(thread_cpu);
bellard66fb9762003-03-23 01:06:05 +0000605 }
bellard31e31b82003-02-18 22:55:36 +0000606}
607
ths0da46a62007-10-20 20:23:07 +0000608/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000609/* compare linux/kernel/signal.c:do_sigaltstack() */
610abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000611{
612 int ret;
613 struct target_sigaltstack oss;
614
615 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000616 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000617 {
618 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
619 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
620 __put_user(sas_ss_flags(sp), &oss.ss_flags);
621 }
622
bellard579a97f2007-11-11 14:26:47 +0000623 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000624 {
bellard579a97f2007-11-11 14:26:47 +0000625 struct target_sigaltstack *uss;
626 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500627 size_t minstacksize = TARGET_MINSIGSTKSZ;
628
629#if defined(TARGET_PPC64)
630 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
631 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
632 if (get_ppc64_abi(image) > 1) {
633 minstacksize = 4096;
634 }
635#endif
thsa04e1342007-09-27 13:57:58 +0000636
ths0da46a62007-10-20 20:23:07 +0000637 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300638 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000639 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300640 }
641 __get_user(ss.ss_sp, &uss->ss_sp);
642 __get_user(ss.ss_size, &uss->ss_size);
643 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000644 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000645
ths0da46a62007-10-20 20:23:07 +0000646 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000647 if (on_sig_stack(sp))
648 goto out;
649
ths0da46a62007-10-20 20:23:07 +0000650 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000651 if (ss.ss_flags != TARGET_SS_DISABLE
652 && ss.ss_flags != TARGET_SS_ONSTACK
653 && ss.ss_flags != 0)
654 goto out;
655
656 if (ss.ss_flags == TARGET_SS_DISABLE) {
657 ss.ss_size = 0;
658 ss.ss_sp = 0;
659 } else {
ths0da46a62007-10-20 20:23:07 +0000660 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500661 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000662 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500663 }
thsa04e1342007-09-27 13:57:58 +0000664 }
665
666 target_sigaltstack_used.ss_sp = ss.ss_sp;
667 target_sigaltstack_used.ss_size = ss.ss_size;
668 }
669
bellard579a97f2007-11-11 14:26:47 +0000670 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000671 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000672 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000673 goto out;
thsa04e1342007-09-27 13:57:58 +0000674 }
675
676 ret = 0;
677out:
678 return ret;
679}
680
ths0da46a62007-10-20 20:23:07 +0000681/* do_sigaction() return host values and errnos */
bellard66fb9762003-03-23 01:06:05 +0000682int do_sigaction(int sig, const struct target_sigaction *act,
683 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000684{
pbrook624f7972008-05-31 16:11:38 +0000685 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000686 struct sigaction act1;
687 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000688 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000689
ths2a913eb2008-11-27 15:46:25 +0000690 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
bellard66fb9762003-03-23 01:06:05 +0000691 return -EINVAL;
692 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000693 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800694 __put_user(k->_sa_handler, &oact->_sa_handler);
695 __put_user(k->sa_flags, &oact->sa_flags);
ths388bb212007-05-13 13:58:00 +0000696#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800697 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000698#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800699 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000700 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000701 }
702 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000703 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800704 __get_user(k->_sa_handler, &act->_sa_handler);
705 __get_user(k->sa_flags, &act->sa_flags);
ths388bb212007-05-13 13:58:00 +0000706#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800707 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000708#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800709 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000710 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000711
712 /* we update the host linux signal state */
713 host_sig = target_to_host_signal(sig);
714 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
715 sigfillset(&act1.sa_mask);
716 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000717 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000718 act1.sa_flags |= SA_RESTART;
719 /* NOTE: it is important to update the host kernel signal
720 ignore state to avoid getting unexpected interrupted
721 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000722 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000723 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000724 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000725 if (fatal_signal (sig))
726 act1.sa_sigaction = host_signal_handler;
727 else
728 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000729 } else {
730 act1.sa_sigaction = host_signal_handler;
731 }
ths0da46a62007-10-20 20:23:07 +0000732 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000733 }
bellard66fb9762003-03-23 01:06:05 +0000734 }
ths0da46a62007-10-20 20:23:07 +0000735 return ret;
bellard66fb9762003-03-23 01:06:05 +0000736}
bellard31e31b82003-02-18 22:55:36 +0000737
bellard459a4012007-11-11 19:45:10 +0000738#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
bellard66fb9762003-03-23 01:06:05 +0000739
740/* from the Linux kernel */
741
742struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100743 uint16_t significand[4];
744 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000745};
746
747struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100748 uint16_t significand[4];
749 uint16_t exponent;
750 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000751};
752
753struct target_xmmreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100754 abi_ulong element[4];
bellard66fb9762003-03-23 01:06:05 +0000755};
756
757struct target_fpstate {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100758 /* Regular FPU environment */
759 abi_ulong cw;
760 abi_ulong sw;
761 abi_ulong tag;
762 abi_ulong ipoff;
763 abi_ulong cssel;
764 abi_ulong dataoff;
765 abi_ulong datasel;
766 struct target_fpreg _st[8];
767 uint16_t status;
768 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000769
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100770 /* FXSR FPU environment */
771 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
772 abi_ulong mxcsr;
773 abi_ulong reserved;
774 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
775 struct target_xmmreg _xmm[8];
776 abi_ulong padding[56];
bellard66fb9762003-03-23 01:06:05 +0000777};
778
779#define X86_FXSR_MAGIC 0x0000
780
781struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100782 uint16_t gs, __gsh;
783 uint16_t fs, __fsh;
784 uint16_t es, __esh;
785 uint16_t ds, __dsh;
786 abi_ulong edi;
787 abi_ulong esi;
788 abi_ulong ebp;
789 abi_ulong esp;
790 abi_ulong ebx;
791 abi_ulong edx;
792 abi_ulong ecx;
793 abi_ulong eax;
794 abi_ulong trapno;
795 abi_ulong err;
796 abi_ulong eip;
797 uint16_t cs, __csh;
798 abi_ulong eflags;
799 abi_ulong esp_at_signal;
800 uint16_t ss, __ssh;
801 abi_ulong fpstate; /* pointer */
802 abi_ulong oldmask;
803 abi_ulong cr2;
bellard66fb9762003-03-23 01:06:05 +0000804};
805
bellard66fb9762003-03-23 01:06:05 +0000806struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100807 abi_ulong tuc_flags;
808 abi_ulong tuc_link;
809 target_stack_t tuc_stack;
810 struct target_sigcontext tuc_mcontext;
811 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000812};
813
814struct sigframe
815{
blueswir1992f48a2007-10-14 16:27:31 +0000816 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000817 int sig;
818 struct target_sigcontext sc;
819 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000820 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000821 char retcode[8];
822};
823
824struct rt_sigframe
825{
blueswir1992f48a2007-10-14 16:27:31 +0000826 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000827 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000828 abi_ulong pinfo;
829 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000830 struct target_siginfo info;
831 struct target_ucontext uc;
832 struct target_fpstate fpstate;
833 char retcode[8];
834};
835
836/*
837 * Set up a signal frame.
838 */
839
bellard66fb9762003-03-23 01:06:05 +0000840/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300841static void setup_sigcontext(struct target_sigcontext *sc,
842 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
843 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000844{
Andreas Färber27103422013-08-26 08:31:06 +0200845 CPUState *cs = CPU(x86_env_get_cpu(env));
Andreas Färber27103422013-08-26 08:31:06 +0200846 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +0000847
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100848 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300849 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
850 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
851 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
852 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
853 __put_user(env->regs[R_EDI], &sc->edi);
854 __put_user(env->regs[R_ESI], &sc->esi);
855 __put_user(env->regs[R_EBP], &sc->ebp);
856 __put_user(env->regs[R_ESP], &sc->esp);
857 __put_user(env->regs[R_EBX], &sc->ebx);
858 __put_user(env->regs[R_EDX], &sc->edx);
859 __put_user(env->regs[R_ECX], &sc->ecx);
860 __put_user(env->regs[R_EAX], &sc->eax);
861 __put_user(cs->exception_index, &sc->trapno);
862 __put_user(env->error_code, &sc->err);
863 __put_user(env->eip, &sc->eip);
864 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
865 __put_user(env->eflags, &sc->eflags);
866 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
867 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +0000868
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100869 cpu_x86_fsave(env, fpstate_addr, 1);
870 fpstate->status = fpstate->sw;
871 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300872 __put_user(magic, &fpstate->magic);
873 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +0000874
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100875 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300876 __put_user(mask, &sc->oldmask);
877 __put_user(env->cr[2], &sc->cr2);
bellard66fb9762003-03-23 01:06:05 +0000878}
879
880/*
881 * Determine which stack to use..
882 */
883
bellard579a97f2007-11-11 14:26:47 +0000884static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +0000885get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +0000886{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100887 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +0000888
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100889 /* Default to using normal stack */
890 esp = env->regs[R_ESP];
891 /* This is the X/Open sanctioned signal stack switching. */
892 if (ka->sa_flags & TARGET_SA_ONSTACK) {
893 if (sas_ss_flags(esp) == 0) {
894 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +0000895 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100896 } else {
bellard66fb9762003-03-23 01:06:05 +0000897
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100898 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +0000899 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100900 !(ka->sa_flags & TARGET_SA_RESTORER) &&
901 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +0000902 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100903 }
904 }
905 return (esp - frame_size) & -8ul;
bellard66fb9762003-03-23 01:06:05 +0000906}
907
bellard579a97f2007-11-11 14:26:47 +0000908/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +0000909static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100910 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000911{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100912 abi_ulong frame_addr;
913 struct sigframe *frame;
914 int i;
bellard66fb9762003-03-23 01:06:05 +0000915
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100916 frame_addr = get_sigframe(ka, env, sizeof(*frame));
917 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +0000918
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100919 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
920 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +0000921
Peter Maydellb6e2c932015-01-08 12:19:43 +0000922 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +0000923
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100924 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
925 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +0000926
Riku Voipio7df2fa32014-04-23 10:34:53 +0300927 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
928 __put_user(set->sig[i], &frame->extramask[i - 1]);
929 }
bellard66fb9762003-03-23 01:06:05 +0000930
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100931 /* Set up to return from userspace. If provided, use a stub
932 already in userspace. */
933 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +0300934 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100935 } else {
936 uint16_t val16;
937 abi_ulong retcode_addr;
938 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300939 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100940 /* This is popl %eax ; movl $,%eax ; int $0x80 */
941 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300942 __put_user(val16, (uint16_t *)(frame->retcode+0));
943 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100944 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300945 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100946 }
bellard66fb9762003-03-23 01:06:05 +0000947
bellard66fb9762003-03-23 01:06:05 +0000948
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100949 /* Set up registers for signal handler */
950 env->regs[R_ESP] = frame_addr;
951 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +0000952
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100953 cpu_x86_load_seg(env, R_DS, __USER_DS);
954 cpu_x86_load_seg(env, R_ES, __USER_DS);
955 cpu_x86_load_seg(env, R_SS, __USER_DS);
956 cpu_x86_load_seg(env, R_CS, __USER_CS);
957 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +0000958
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100959 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000960
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100961 return;
bellard66fb9762003-03-23 01:06:05 +0000962
963give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100964 if (sig == TARGET_SIGSEGV) {
965 ka->_sa_handler = TARGET_SIG_DFL;
966 }
967 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +0000968}
969
bellard579a97f2007-11-11 14:26:47 +0000970/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +0000971static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -0500972 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100973 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000974{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100975 abi_ulong frame_addr, addr;
976 struct rt_sigframe *frame;
977 int i;
bellard66fb9762003-03-23 01:06:05 +0000978
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100979 frame_addr = get_sigframe(ka, env, sizeof(*frame));
980 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +0000981
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100982 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
983 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +0000984
Peter Maydellb6e2c932015-01-08 12:19:43 +0000985 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100986 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300987 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100988 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300989 __put_user(addr, &frame->puc);
Peter Maydellf6c7a052015-01-08 12:19:48 +0000990 tswap_siginfo(&frame->info, info);
bellard66fb9762003-03-23 01:06:05 +0000991
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100992 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300993 __put_user(0, &frame->uc.tuc_flags);
994 __put_user(0, &frame->uc.tuc_link);
995 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
996 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
997 &frame->uc.tuc_stack.ss_flags);
998 __put_user(target_sigaltstack_used.ss_size,
999 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001000 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1001 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1002
Riku Voipio0188fad2014-04-23 13:34:15 +03001003 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1004 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1005 }
bellard66fb9762003-03-23 01:06:05 +00001006
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001007 /* Set up to return from userspace. If provided, use a stub
1008 already in userspace. */
1009 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001010 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001011 } else {
1012 uint16_t val16;
1013 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001014 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001015 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001016 __put_user(0xb8, (char *)(frame->retcode+0));
1017 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001018 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001019 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001020 }
bellard66fb9762003-03-23 01:06:05 +00001021
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001022 /* Set up registers for signal handler */
1023 env->regs[R_ESP] = frame_addr;
1024 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001025
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001026 cpu_x86_load_seg(env, R_DS, __USER_DS);
1027 cpu_x86_load_seg(env, R_ES, __USER_DS);
1028 cpu_x86_load_seg(env, R_SS, __USER_DS);
1029 cpu_x86_load_seg(env, R_CS, __USER_CS);
1030 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001031
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001032 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001033
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001034 return;
bellard66fb9762003-03-23 01:06:05 +00001035
1036give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001037 if (sig == TARGET_SIGSEGV) {
1038 ka->_sa_handler = TARGET_SIG_DFL;
1039 }
1040 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +00001041}
1042
1043static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001044restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001045{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001046 unsigned int err = 0;
1047 abi_ulong fpstate_addr;
1048 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001049
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001050 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1051 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1052 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1053 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001054
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001055 env->regs[R_EDI] = tswapl(sc->edi);
1056 env->regs[R_ESI] = tswapl(sc->esi);
1057 env->regs[R_EBP] = tswapl(sc->ebp);
1058 env->regs[R_ESP] = tswapl(sc->esp);
1059 env->regs[R_EBX] = tswapl(sc->ebx);
1060 env->regs[R_EDX] = tswapl(sc->edx);
1061 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001062 env->regs[R_EAX] = tswapl(sc->eax);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001063 env->eip = tswapl(sc->eip);
bellard66fb9762003-03-23 01:06:05 +00001064
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001065 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1066 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001067
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001068 tmpflags = tswapl(sc->eflags);
1069 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1070 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001071
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001072 fpstate_addr = tswapl(sc->fpstate);
1073 if (fpstate_addr != 0) {
1074 if (!access_ok(VERIFY_READ, fpstate_addr,
1075 sizeof(struct target_fpstate)))
1076 goto badframe;
1077 cpu_x86_frstor(env, fpstate_addr, 1);
1078 }
bellard66fb9762003-03-23 01:06:05 +00001079
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001080 return err;
bellard66fb9762003-03-23 01:06:05 +00001081badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001082 return 1;
bellard66fb9762003-03-23 01:06:05 +00001083}
1084
1085long do_sigreturn(CPUX86State *env)
1086{
bellard579a97f2007-11-11 14:26:47 +00001087 struct sigframe *frame;
1088 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001089 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001090 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001091 int i;
bellard66fb9762003-03-23 01:06:05 +00001092
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001093 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001094 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1095 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001096 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001097 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001098 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001099 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001100 }
bellard66fb9762003-03-23 01:06:05 +00001101
bellard92319442004-06-19 16:58:13 +00001102 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001103 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001104
bellard66fb9762003-03-23 01:06:05 +00001105 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001106 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001107 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001108 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001109 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001110
1111badframe:
bellard579a97f2007-11-11 14:26:47 +00001112 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001113 force_sig(TARGET_SIGSEGV);
1114 return 0;
1115}
1116
1117long do_rt_sigreturn(CPUX86State *env)
1118{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001119 abi_ulong frame_addr;
1120 struct rt_sigframe *frame;
1121 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001122
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001123 frame_addr = env->regs[R_ESP] - 4;
1124 trace_user_do_rt_sigreturn(env, frame_addr);
1125 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1126 goto badframe;
1127 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001128 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001129
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001130 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001131 goto badframe;
1132 }
bellard66fb9762003-03-23 01:06:05 +00001133
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001134 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1135 get_sp_from_cpustate(env)) == -EFAULT) {
1136 goto badframe;
1137 }
thsa04e1342007-09-27 13:57:58 +00001138
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001139 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001140 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001141
1142badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001143 unlock_user_struct(frame, frame_addr, 0);
1144 force_sig(TARGET_SIGSEGV);
1145 return 0;
bellard66fb9762003-03-23 01:06:05 +00001146}
1147
Andreas Schwab1744aea2013-09-03 20:12:16 +01001148#elif defined(TARGET_AARCH64)
1149
1150struct target_sigcontext {
1151 uint64_t fault_address;
1152 /* AArch64 registers */
1153 uint64_t regs[31];
1154 uint64_t sp;
1155 uint64_t pc;
1156 uint64_t pstate;
1157 /* 4K reserved for FP/SIMD state and future expansion */
1158 char __reserved[4096] __attribute__((__aligned__(16)));
1159};
1160
1161struct target_ucontext {
1162 abi_ulong tuc_flags;
1163 abi_ulong tuc_link;
1164 target_stack_t tuc_stack;
1165 target_sigset_t tuc_sigmask;
1166 /* glibc uses a 1024-bit sigset_t */
1167 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1168 /* last for future expansion */
1169 struct target_sigcontext tuc_mcontext;
1170};
1171
1172/*
1173 * Header to be used at the beginning of structures extending the user
1174 * context. Such structures must be placed after the rt_sigframe on the stack
1175 * and be 16-byte aligned. The last structure must be a dummy one with the
1176 * magic and size set to 0.
1177 */
1178struct target_aarch64_ctx {
1179 uint32_t magic;
1180 uint32_t size;
1181};
1182
1183#define TARGET_FPSIMD_MAGIC 0x46508001
1184
1185struct target_fpsimd_context {
1186 struct target_aarch64_ctx head;
1187 uint32_t fpsr;
1188 uint32_t fpcr;
1189 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1190};
1191
1192/*
1193 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1194 * user space as it will change with the addition of new context. User space
1195 * should check the magic/size information.
1196 */
1197struct target_aux_context {
1198 struct target_fpsimd_context fpsimd;
1199 /* additional context to be added before "end" */
1200 struct target_aarch64_ctx end;
1201};
1202
1203struct target_rt_sigframe {
1204 struct target_siginfo info;
1205 struct target_ucontext uc;
1206 uint64_t fp;
1207 uint64_t lr;
1208 uint32_t tramp[2];
1209};
1210
1211static int target_setup_sigframe(struct target_rt_sigframe *sf,
1212 CPUARMState *env, target_sigset_t *set)
1213{
1214 int i;
1215 struct target_aux_context *aux =
1216 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1217
1218 /* set up the stack frame for unwinding */
1219 __put_user(env->xregs[29], &sf->fp);
1220 __put_user(env->xregs[30], &sf->lr);
1221
1222 for (i = 0; i < 31; i++) {
1223 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1224 }
1225 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1226 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001227 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001228
Peter Maydell7af03922014-05-01 18:36:17 +01001229 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001230
1231 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1232 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1233 }
1234
1235 for (i = 0; i < 32; i++) {
1236#ifdef TARGET_WORDS_BIGENDIAN
1237 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1238 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1239#else
1240 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1241 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1242#endif
1243 }
Will Newtone0ee1382014-01-04 22:15:48 +00001244 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1245 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001246 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1247 __put_user(sizeof(struct target_fpsimd_context),
1248 &aux->fpsimd.head.size);
1249
1250 /* set the "end" magic */
1251 __put_user(0, &aux->end.magic);
1252 __put_user(0, &aux->end.size);
1253
1254 return 0;
1255}
1256
1257static int target_restore_sigframe(CPUARMState *env,
1258 struct target_rt_sigframe *sf)
1259{
1260 sigset_t set;
1261 int i;
1262 struct target_aux_context *aux =
1263 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
Will Newtone0ee1382014-01-04 22:15:48 +00001264 uint32_t magic, size, fpsr, fpcr;
Peter Maydelld3563122013-12-17 19:42:30 +00001265 uint64_t pstate;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001266
1267 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001268 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001269
1270 for (i = 0; i < 31; i++) {
1271 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1272 }
1273
1274 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1275 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001276 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1277 pstate_write(env, pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001278
1279 __get_user(magic, &aux->fpsimd.head.magic);
1280 __get_user(size, &aux->fpsimd.head.size);
1281
1282 if (magic != TARGET_FPSIMD_MAGIC
1283 || size != sizeof(struct target_fpsimd_context)) {
1284 return 1;
1285 }
1286
Peter Maydell4cf23482014-03-02 19:36:38 +00001287 for (i = 0; i < 32; i++) {
1288#ifdef TARGET_WORDS_BIGENDIAN
1289 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1290 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1291#else
1292 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1293 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1294#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001295 }
Will Newtone0ee1382014-01-04 22:15:48 +00001296 __get_user(fpsr, &aux->fpsimd.fpsr);
1297 vfp_set_fpsr(env, fpsr);
1298 __get_user(fpcr, &aux->fpsimd.fpcr);
1299 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001300
1301 return 0;
1302}
1303
1304static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1305{
1306 abi_ulong sp;
1307
1308 sp = env->xregs[31];
1309
1310 /*
1311 * This is the X/Open sanctioned signal stack switching.
1312 */
Riku Voipiob545f632014-07-15 17:01:55 +03001313 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001314 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1315 }
1316
1317 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1318
1319 return sp;
1320}
1321
1322static void target_setup_frame(int usig, struct target_sigaction *ka,
1323 target_siginfo_t *info, target_sigset_t *set,
1324 CPUARMState *env)
1325{
1326 struct target_rt_sigframe *frame;
Michael Matz8a3ae912014-03-02 19:36:39 +00001327 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001328
1329 frame_addr = get_sigframe(ka, env);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001330 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001331 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1332 goto give_sigsegv;
1333 }
1334
1335 __put_user(0, &frame->uc.tuc_flags);
1336 __put_user(0, &frame->uc.tuc_link);
1337
1338 __put_user(target_sigaltstack_used.ss_sp,
1339 &frame->uc.tuc_stack.ss_sp);
1340 __put_user(sas_ss_flags(env->xregs[31]),
1341 &frame->uc.tuc_stack.ss_flags);
1342 __put_user(target_sigaltstack_used.ss_size,
1343 &frame->uc.tuc_stack.ss_size);
1344 target_setup_sigframe(frame, env, set);
Michael Matz8a3ae912014-03-02 19:36:39 +00001345 if (ka->sa_flags & TARGET_SA_RESTORER) {
1346 return_addr = ka->sa_restorer;
1347 } else {
1348 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1349 __put_user(0xd2801168, &frame->tramp[0]);
1350 __put_user(0xd4000001, &frame->tramp[1]);
1351 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1352 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001353 env->xregs[0] = usig;
1354 env->xregs[31] = frame_addr;
1355 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1356 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001357 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001358 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001359 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001360 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1361 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1362 }
1363
1364 unlock_user_struct(frame, frame_addr, 1);
1365 return;
1366
1367 give_sigsegv:
1368 unlock_user_struct(frame, frame_addr, 1);
1369 force_sig(TARGET_SIGSEGV);
1370}
1371
1372static void setup_rt_frame(int sig, struct target_sigaction *ka,
1373 target_siginfo_t *info, target_sigset_t *set,
1374 CPUARMState *env)
1375{
1376 target_setup_frame(sig, ka, info, set, env);
1377}
1378
1379static void setup_frame(int sig, struct target_sigaction *ka,
1380 target_sigset_t *set, CPUARMState *env)
1381{
1382 target_setup_frame(sig, ka, 0, set, env);
1383}
1384
1385long do_rt_sigreturn(CPUARMState *env)
1386{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001387 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001388 abi_ulong frame_addr = env->xregs[31];
1389
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001390 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001391 if (frame_addr & 15) {
1392 goto badframe;
1393 }
1394
1395 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1396 goto badframe;
1397 }
1398
1399 if (target_restore_sigframe(env, frame)) {
1400 goto badframe;
1401 }
1402
1403 if (do_sigaltstack(frame_addr +
1404 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1405 0, get_sp_from_cpustate(env)) == -EFAULT) {
1406 goto badframe;
1407 }
1408
1409 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001410 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001411
1412 badframe:
1413 unlock_user_struct(frame, frame_addr, 0);
1414 force_sig(TARGET_SIGSEGV);
1415 return 0;
1416}
1417
1418long do_sigreturn(CPUARMState *env)
1419{
1420 return do_rt_sigreturn(env);
1421}
1422
bellard43fff232003-07-09 19:31:39 +00001423#elif defined(TARGET_ARM)
1424
1425struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001426 abi_ulong trap_no;
1427 abi_ulong error_code;
1428 abi_ulong oldmask;
1429 abi_ulong arm_r0;
1430 abi_ulong arm_r1;
1431 abi_ulong arm_r2;
1432 abi_ulong arm_r3;
1433 abi_ulong arm_r4;
1434 abi_ulong arm_r5;
1435 abi_ulong arm_r6;
1436 abi_ulong arm_r7;
1437 abi_ulong arm_r8;
1438 abi_ulong arm_r9;
1439 abi_ulong arm_r10;
1440 abi_ulong arm_fp;
1441 abi_ulong arm_ip;
1442 abi_ulong arm_sp;
1443 abi_ulong arm_lr;
1444 abi_ulong arm_pc;
1445 abi_ulong arm_cpsr;
1446 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001447};
1448
pbrooka745ec62008-05-06 15:36:17 +00001449struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001450 abi_ulong tuc_flags;
1451 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001452 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001453 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001454 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001455};
1456
pbrooka745ec62008-05-06 15:36:17 +00001457struct target_ucontext_v2 {
1458 abi_ulong tuc_flags;
1459 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001460 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001461 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001462 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001463 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001464 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1465};
1466
Peter Maydell0d871bd2010-11-24 15:20:05 +00001467struct target_user_vfp {
1468 uint64_t fpregs[32];
1469 abi_ulong fpscr;
1470};
1471
1472struct target_user_vfp_exc {
1473 abi_ulong fpexc;
1474 abi_ulong fpinst;
1475 abi_ulong fpinst2;
1476};
1477
1478struct target_vfp_sigframe {
1479 abi_ulong magic;
1480 abi_ulong size;
1481 struct target_user_vfp ufp;
1482 struct target_user_vfp_exc ufp_exc;
1483} __attribute__((__aligned__(8)));
1484
Peter Maydell08e11252010-11-24 15:20:07 +00001485struct target_iwmmxt_sigframe {
1486 abi_ulong magic;
1487 abi_ulong size;
1488 uint64_t regs[16];
1489 /* Note that not all the coprocessor control registers are stored here */
1490 uint32_t wcssf;
1491 uint32_t wcasf;
1492 uint32_t wcgr0;
1493 uint32_t wcgr1;
1494 uint32_t wcgr2;
1495 uint32_t wcgr3;
1496} __attribute__((__aligned__(8)));
1497
Peter Maydell0d871bd2010-11-24 15:20:05 +00001498#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001499#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001500
pbrooka8c33202008-05-07 23:22:46 +00001501struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001502{
1503 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001504 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1505 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001506};
1507
pbrooka8c33202008-05-07 23:22:46 +00001508struct sigframe_v2
1509{
1510 struct target_ucontext_v2 uc;
1511 abi_ulong retcode;
1512};
1513
pbrooka745ec62008-05-06 15:36:17 +00001514struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001515{
bellardf8b0aa22007-11-11 23:03:42 +00001516 abi_ulong pinfo;
1517 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001518 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001519 struct target_ucontext_v1 uc;
1520 abi_ulong retcode;
1521};
1522
1523struct rt_sigframe_v2
1524{
1525 struct target_siginfo info;
1526 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001527 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001528};
1529
1530#define TARGET_CONFIG_CPU_32 1
1531
1532/*
1533 * For ARM syscalls, we encode the syscall number into the instruction.
1534 */
1535#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1536#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1537
1538/*
1539 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1540 * need two 16-bit instructions.
1541 */
1542#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1543#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1544
blueswir1992f48a2007-10-14 16:27:31 +00001545static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001546 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1547 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1548};
1549
1550
Andreas Färber05390242012-02-25 03:37:53 +01001551static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001552{
1553 return 1;
1554}
1555
pbrooka8c33202008-05-07 23:22:46 +00001556static void
bellard43fff232003-07-09 19:31:39 +00001557setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001558 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001559{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001560 __put_user(env->regs[0], &sc->arm_r0);
1561 __put_user(env->regs[1], &sc->arm_r1);
1562 __put_user(env->regs[2], &sc->arm_r2);
1563 __put_user(env->regs[3], &sc->arm_r3);
1564 __put_user(env->regs[4], &sc->arm_r4);
1565 __put_user(env->regs[5], &sc->arm_r5);
1566 __put_user(env->regs[6], &sc->arm_r6);
1567 __put_user(env->regs[7], &sc->arm_r7);
1568 __put_user(env->regs[8], &sc->arm_r8);
1569 __put_user(env->regs[9], &sc->arm_r9);
1570 __put_user(env->regs[10], &sc->arm_r10);
1571 __put_user(env->regs[11], &sc->arm_fp);
1572 __put_user(env->regs[12], &sc->arm_ip);
1573 __put_user(env->regs[13], &sc->arm_sp);
1574 __put_user(env->regs[14], &sc->arm_lr);
1575 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001576#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001577 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001578#endif
1579
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001580 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1581 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1582 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1583 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001584}
1585
bellard579a97f2007-11-11 14:26:47 +00001586static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001587get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001588{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001589 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00001590
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001591 /*
1592 * This is the X/Open sanctioned signal stack switching.
1593 */
1594 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1595 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1596 }
1597 /*
1598 * ATPCS B01 mandates 8-byte alignment
1599 */
1600 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001601}
1602
Riku Voipio0188fad2014-04-23 13:34:15 +03001603static void
Andreas Färber05390242012-02-25 03:37:53 +01001604setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001605 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001606{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001607 abi_ulong handler = ka->_sa_handler;
1608 abi_ulong retcode;
1609 int thumb = handler & 1;
1610 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01001611
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001612 cpsr &= ~CPSR_IT;
1613 if (thumb) {
1614 cpsr |= CPSR_T;
1615 } else {
1616 cpsr &= ~CPSR_T;
1617 }
bellard43fff232003-07-09 19:31:39 +00001618
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001619 if (ka->sa_flags & TARGET_SA_RESTORER) {
1620 retcode = ka->sa_restorer;
1621 } else {
1622 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00001623
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001624 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1625 idx += 2;
1626 }
bellard43fff232003-07-09 19:31:39 +00001627
Riku Voipio0188fad2014-04-23 13:34:15 +03001628 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001629
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001630 retcode = rc_addr + thumb;
1631 }
bellard43fff232003-07-09 19:31:39 +00001632
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001633 env->regs[0] = usig;
1634 env->regs[13] = frame_addr;
1635 env->regs[14] = retcode;
1636 env->regs[15] = handler & (thumb ? ~1 : ~3);
1637 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001638}
1639
Andreas Färber05390242012-02-25 03:37:53 +01001640static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001641{
1642 int i;
1643 struct target_vfp_sigframe *vfpframe;
1644 vfpframe = (struct target_vfp_sigframe *)regspace;
1645 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1646 __put_user(sizeof(*vfpframe), &vfpframe->size);
1647 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001648 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001649 }
1650 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1651 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1652 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1653 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1654 return (abi_ulong*)(vfpframe+1);
1655}
1656
Andreas Färber05390242012-02-25 03:37:53 +01001657static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1658 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001659{
1660 int i;
1661 struct target_iwmmxt_sigframe *iwmmxtframe;
1662 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1663 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1664 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1665 for (i = 0; i < 16; i++) {
1666 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1667 }
1668 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1669 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1670 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1671 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1672 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1673 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1674 return (abi_ulong*)(iwmmxtframe+1);
1675}
1676
pbrooka8c33202008-05-07 23:22:46 +00001677static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001678 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001679{
pbrooka8c33202008-05-07 23:22:46 +00001680 struct target_sigaltstack stack;
1681 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001682 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001683
1684 /* Clear all the bits of the ucontext we don't use. */
1685 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1686
1687 memset(&stack, 0, sizeof(stack));
1688 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1689 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1690 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1691 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1692
1693 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001694 /* Save coprocessor signal frame. */
1695 regspace = uc->tuc_regspace;
1696 if (arm_feature(env, ARM_FEATURE_VFP)) {
1697 regspace = setup_sigframe_v2_vfp(regspace, env);
1698 }
Peter Maydell08e11252010-11-24 15:20:07 +00001699 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1700 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1701 }
1702
Peter Maydell0d871bd2010-11-24 15:20:05 +00001703 /* Write terminating magic word */
1704 __put_user(0, regspace);
1705
pbrooka8c33202008-05-07 23:22:46 +00001706 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1707 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1708 }
1709}
1710
1711/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001712static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001713 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001714{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001715 struct sigframe_v1 *frame;
1716 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1717 int i;
bellard43fff232003-07-09 19:31:39 +00001718
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001719 trace_user_setup_frame(regs, frame_addr);
1720 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1721 return;
1722 }
bellard579a97f2007-11-11 14:26:47 +00001723
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001724 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00001725
Riku Voipio0188fad2014-04-23 13:34:15 +03001726 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1727 __put_user(set->sig[i], &frame->extramask[i - 1]);
1728 }
bellard43fff232003-07-09 19:31:39 +00001729
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001730 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1731 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00001732
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001733 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001734}
1735
pbrook624f7972008-05-31 16:11:38 +00001736static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001737 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001738{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001739 struct sigframe_v2 *frame;
1740 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00001741
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001742 trace_user_setup_frame(regs, frame_addr);
1743 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1744 return;
1745 }
pbrooka8c33202008-05-07 23:22:46 +00001746
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001747 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00001748
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001749 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1750 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00001751
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001752 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001753}
1754
pbrook624f7972008-05-31 16:11:38 +00001755static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001756 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001757{
1758 if (get_osversion() >= 0x020612) {
1759 setup_frame_v2(usig, ka, set, regs);
1760 } else {
1761 setup_frame_v1(usig, ka, set, regs);
1762 }
bellard43fff232003-07-09 19:31:39 +00001763}
1764
bellard579a97f2007-11-11 14:26:47 +00001765/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001766static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001767 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001768 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001769{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001770 struct rt_sigframe_v1 *frame;
1771 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1772 struct target_sigaltstack stack;
1773 int i;
1774 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00001775
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001776 trace_user_setup_rt_frame(env, frame_addr);
1777 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1778 return /* 1 */;
1779 }
bellardedf779f2004-02-22 13:40:13 +00001780
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001781 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1782 __put_user(info_addr, &frame->pinfo);
1783 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1784 __put_user(uc_addr, &frame->puc);
1785 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00001786
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001787 /* Clear all the bits of the ucontext we don't use. */
1788 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00001789
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001790 memset(&stack, 0, sizeof(stack));
1791 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1792 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1793 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1794 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00001795
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001796 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1797 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1798 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1799 }
bellard43fff232003-07-09 19:31:39 +00001800
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001801 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1802 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001803
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001804 env->regs[1] = info_addr;
1805 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001806
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001807 unlock_user_struct(frame, frame_addr, 1);
pbrooka745ec62008-05-06 15:36:17 +00001808}
1809
pbrook624f7972008-05-31 16:11:38 +00001810static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001811 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001812 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001813{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001814 struct rt_sigframe_v2 *frame;
1815 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1816 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001817
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001818 trace_user_setup_rt_frame(env, frame_addr);
1819 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1820 return /* 1 */;
1821 }
pbrooka745ec62008-05-06 15:36:17 +00001822
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001823 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1824 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1825 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00001826
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001827 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00001828
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001829 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1830 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001831
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001832 env->regs[1] = info_addr;
1833 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001834
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001835 unlock_user_struct(frame, frame_addr, 1);
bellard43fff232003-07-09 19:31:39 +00001836}
1837
pbrook624f7972008-05-31 16:11:38 +00001838static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001839 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001840 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001841{
1842 if (get_osversion() >= 0x020612) {
1843 setup_rt_frame_v2(usig, ka, info, set, env);
1844 } else {
1845 setup_rt_frame_v1(usig, ka, info, set, env);
1846 }
1847}
1848
bellard43fff232003-07-09 19:31:39 +00001849static int
Andreas Färber05390242012-02-25 03:37:53 +01001850restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00001851{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001852 int err = 0;
1853 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00001854
Riku Voipio1d8b5122014-04-23 10:26:05 +03001855 __get_user(env->regs[0], &sc->arm_r0);
1856 __get_user(env->regs[1], &sc->arm_r1);
1857 __get_user(env->regs[2], &sc->arm_r2);
1858 __get_user(env->regs[3], &sc->arm_r3);
1859 __get_user(env->regs[4], &sc->arm_r4);
1860 __get_user(env->regs[5], &sc->arm_r5);
1861 __get_user(env->regs[6], &sc->arm_r6);
1862 __get_user(env->regs[7], &sc->arm_r7);
1863 __get_user(env->regs[8], &sc->arm_r8);
1864 __get_user(env->regs[9], &sc->arm_r9);
1865 __get_user(env->regs[10], &sc->arm_r10);
1866 __get_user(env->regs[11], &sc->arm_fp);
1867 __get_user(env->regs[12], &sc->arm_ip);
1868 __get_user(env->regs[13], &sc->arm_sp);
1869 __get_user(env->regs[14], &sc->arm_lr);
1870 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001871#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03001872 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00001873 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001874#endif
1875
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001876 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00001877
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001878 return err;
bellard43fff232003-07-09 19:31:39 +00001879}
1880
Andreas Färber05390242012-02-25 03:37:53 +01001881static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001882{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001883 abi_ulong frame_addr;
1884 struct sigframe_v1 *frame = NULL;
1885 target_sigset_t set;
1886 sigset_t host_set;
1887 int i;
bellard43fff232003-07-09 19:31:39 +00001888
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001889 /*
1890 * Since we stacked the signal on a 64-bit boundary,
1891 * then 'sp' should be word aligned here. If it's
1892 * not, then the user is trying to mess with us.
1893 */
1894 frame_addr = env->regs[13];
1895 trace_user_do_sigreturn(env, frame_addr);
1896 if (frame_addr & 7) {
1897 goto badframe;
1898 }
Peter Maydell978fae92013-07-29 12:00:32 +01001899
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001900 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1901 goto badframe;
1902 }
bellard43fff232003-07-09 19:31:39 +00001903
Riku Voipiof5f601a2014-04-23 13:00:17 +03001904 __get_user(set.sig[0], &frame->sc.oldmask);
1905 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1906 __get_user(set.sig[i], &frame->extramask[i - 1]);
1907 }
bellard43fff232003-07-09 19:31:39 +00001908
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001909 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001910 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00001911
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001912 if (restore_sigcontext(env, &frame->sc)) {
1913 goto badframe;
1914 }
bellard43fff232003-07-09 19:31:39 +00001915
1916#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001917 /* Send SIGTRAP if we're single-stepping */
1918 if (ptrace_cancel_bpt(current))
1919 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00001920#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001921 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001922 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00001923
1924badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001925 force_sig(TARGET_SIGSEGV /* , current */);
1926 return 0;
bellard43fff232003-07-09 19:31:39 +00001927}
1928
Andreas Färber05390242012-02-25 03:37:53 +01001929static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00001930{
1931 int i;
1932 abi_ulong magic, sz;
1933 uint32_t fpscr, fpexc;
1934 struct target_vfp_sigframe *vfpframe;
1935 vfpframe = (struct target_vfp_sigframe *)regspace;
1936
1937 __get_user(magic, &vfpframe->magic);
1938 __get_user(sz, &vfpframe->size);
1939 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1940 return 0;
1941 }
1942 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001943 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00001944 }
1945 __get_user(fpscr, &vfpframe->ufp.fpscr);
1946 vfp_set_fpscr(env, fpscr);
1947 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1948 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1949 * and the exception flag is cleared
1950 */
1951 fpexc |= (1 << 30);
1952 fpexc &= ~((1 << 31) | (1 << 28));
1953 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1954 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1955 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1956 return (abi_ulong*)(vfpframe + 1);
1957}
1958
Andreas Färber05390242012-02-25 03:37:53 +01001959static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
1960 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00001961{
1962 int i;
1963 abi_ulong magic, sz;
1964 struct target_iwmmxt_sigframe *iwmmxtframe;
1965 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1966
1967 __get_user(magic, &iwmmxtframe->magic);
1968 __get_user(sz, &iwmmxtframe->size);
1969 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
1970 return 0;
1971 }
1972 for (i = 0; i < 16; i++) {
1973 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1974 }
1975 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1976 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1977 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1978 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1979 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1980 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1981 return (abi_ulong*)(iwmmxtframe + 1);
1982}
1983
Andreas Färber05390242012-02-25 03:37:53 +01001984static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
pbrooka8c33202008-05-07 23:22:46 +00001985 struct target_ucontext_v2 *uc)
1986{
1987 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00001988 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001989
1990 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001991 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00001992
1993 if (restore_sigcontext(env, &uc->tuc_mcontext))
1994 return 1;
1995
Peter Maydell5f9099d2010-11-24 15:20:06 +00001996 /* Restore coprocessor signal frame */
1997 regspace = uc->tuc_regspace;
1998 if (arm_feature(env, ARM_FEATURE_VFP)) {
1999 regspace = restore_sigframe_v2_vfp(env, regspace);
2000 if (!regspace) {
2001 return 1;
2002 }
2003 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002004 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2005 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2006 if (!regspace) {
2007 return 1;
2008 }
2009 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002010
pbrooka8c33202008-05-07 23:22:46 +00002011 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2012 return 1;
2013
2014#if 0
2015 /* Send SIGTRAP if we're single-stepping */
2016 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002017 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002018#endif
2019
2020 return 0;
2021}
2022
Andreas Färber05390242012-02-25 03:37:53 +01002023static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002024{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002025 abi_ulong frame_addr;
2026 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002027
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002028 /*
2029 * Since we stacked the signal on a 64-bit boundary,
2030 * then 'sp' should be word aligned here. If it's
2031 * not, then the user is trying to mess with us.
2032 */
2033 frame_addr = env->regs[13];
2034 trace_user_do_sigreturn(env, frame_addr);
2035 if (frame_addr & 7) {
2036 goto badframe;
2037 }
Peter Maydell978fae92013-07-29 12:00:32 +01002038
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002039 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2040 goto badframe;
2041 }
pbrooka8c33202008-05-07 23:22:46 +00002042
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002043 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2044 goto badframe;
2045 }
pbrooka8c33202008-05-07 23:22:46 +00002046
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002047 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002048 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002049
2050badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002051 unlock_user_struct(frame, frame_addr, 0);
2052 force_sig(TARGET_SIGSEGV /* , current */);
2053 return 0;
pbrooka8c33202008-05-07 23:22:46 +00002054}
2055
Andreas Färber05390242012-02-25 03:37:53 +01002056long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002057{
2058 if (get_osversion() >= 0x020612) {
2059 return do_sigreturn_v2(env);
2060 } else {
2061 return do_sigreturn_v1(env);
2062 }
2063}
2064
Andreas Färber05390242012-02-25 03:37:53 +01002065static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002066{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002067 abi_ulong frame_addr;
2068 struct rt_sigframe_v1 *frame = NULL;
2069 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002070
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002071 /*
2072 * Since we stacked the signal on a 64-bit boundary,
2073 * then 'sp' should be word aligned here. If it's
2074 * not, then the user is trying to mess with us.
2075 */
2076 frame_addr = env->regs[13];
2077 trace_user_do_rt_sigreturn(env, frame_addr);
2078 if (frame_addr & 7) {
2079 goto badframe;
2080 }
Peter Maydell978fae92013-07-29 12:00:32 +01002081
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002082 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2083 goto badframe;
2084 }
bellard43fff232003-07-09 19:31:39 +00002085
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002086 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002087 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002088
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002089 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2090 goto badframe;
2091 }
bellard43fff232003-07-09 19:31:39 +00002092
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002093 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2094 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002095
bellard43fff232003-07-09 19:31:39 +00002096#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002097 /* Send SIGTRAP if we're single-stepping */
2098 if (ptrace_cancel_bpt(current))
2099 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002100#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002101 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002102 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002103
2104badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002105 unlock_user_struct(frame, frame_addr, 0);
2106 force_sig(TARGET_SIGSEGV /* , current */);
2107 return 0;
bellard43fff232003-07-09 19:31:39 +00002108}
2109
Andreas Färber05390242012-02-25 03:37:53 +01002110static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002111{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002112 abi_ulong frame_addr;
2113 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002114
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002115 /*
2116 * Since we stacked the signal on a 64-bit boundary,
2117 * then 'sp' should be word aligned here. If it's
2118 * not, then the user is trying to mess with us.
2119 */
2120 frame_addr = env->regs[13];
2121 trace_user_do_rt_sigreturn(env, frame_addr);
2122 if (frame_addr & 7) {
2123 goto badframe;
2124 }
Peter Maydell978fae92013-07-29 12:00:32 +01002125
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002126 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2127 goto badframe;
2128 }
pbrooka745ec62008-05-06 15:36:17 +00002129
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002130 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2131 goto badframe;
2132 }
pbrooka745ec62008-05-06 15:36:17 +00002133
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002134 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002135 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002136
2137badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002138 unlock_user_struct(frame, frame_addr, 0);
2139 force_sig(TARGET_SIGSEGV /* , current */);
2140 return 0;
pbrooka745ec62008-05-06 15:36:17 +00002141}
2142
Andreas Färber05390242012-02-25 03:37:53 +01002143long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002144{
2145 if (get_osversion() >= 0x020612) {
2146 return do_rt_sigreturn_v2(env);
2147 } else {
2148 return do_rt_sigreturn_v1(env);
2149 }
2150}
2151
bellard6d5e2162004-09-30 22:04:13 +00002152#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002153
bellard6d5e2162004-09-30 22:04:13 +00002154#define __SUNOS_MAXWIN 31
2155
2156/* This is what SunOS does, so shall I. */
2157struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002158 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002159
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002160 abi_ulong sigc_mask; /* sigmask to restore */
2161 abi_ulong sigc_sp; /* stack pointer */
2162 abi_ulong sigc_pc; /* program counter */
2163 abi_ulong sigc_npc; /* next program counter */
2164 abi_ulong sigc_psr; /* for condition codes etc */
2165 abi_ulong sigc_g1; /* User uses these two registers */
2166 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002167
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002168 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002169 * at the time of the signal.
2170 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002171 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002172
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002173 /* stack ptrs for each regwin buf */
2174 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002175
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002176 /* Windows to restore after signal */
2177 struct {
2178 abi_ulong locals[8];
2179 abi_ulong ins[8];
2180 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002181};
2182/* A Sparc stack frame */
2183struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002184 abi_ulong locals[8];
2185 abi_ulong ins[8];
2186 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002187 * since we never need to access them ourselves.
2188 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002189 char *structptr;
2190 abi_ulong xargs[6];
2191 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002192};
2193
2194typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002195 struct {
2196 abi_ulong psr;
2197 abi_ulong pc;
2198 abi_ulong npc;
2199 abi_ulong y;
2200 abi_ulong u_regs[16]; /* globals and ins */
2201 } si_regs;
2202 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002203} __siginfo_t;
2204
2205typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002206 abi_ulong si_float_regs[32];
2207 unsigned long si_fsr;
2208 unsigned long si_fpqdepth;
2209 struct {
2210 unsigned long *insn_addr;
2211 unsigned long insn;
2212 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002213} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002214
2215
2216struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002217 struct sparc_stackf ss;
2218 __siginfo_t info;
2219 abi_ulong fpu_save;
2220 abi_ulong insns[2] __attribute__ ((aligned (8)));
2221 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2222 abi_ulong extra_size; /* Should be 0 */
2223 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002224};
2225struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002226 struct sparc_stackf ss;
2227 siginfo_t info;
2228 abi_ulong regs[20];
2229 sigset_t mask;
2230 abi_ulong fpu_save;
2231 unsigned int insns[2];
2232 stack_t stack;
2233 unsigned int extra_size; /* Should be 0 */
2234 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002235};
2236
bellarde80cfcf2004-12-19 23:18:01 +00002237#define UREG_O0 16
2238#define UREG_O6 22
2239#define UREG_I0 0
2240#define UREG_I1 1
2241#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002242#define UREG_I3 3
2243#define UREG_I4 4
2244#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002245#define UREG_I6 6
2246#define UREG_I7 7
2247#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002248#define UREG_FP UREG_I6
2249#define UREG_SP UREG_O6
2250
pbrook624f7972008-05-31 16:11:38 +00002251static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002252 CPUSPARCState *env,
2253 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002254{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002255 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002256
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002257 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002258
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002259 /* This is the X/Open sanctioned signal stack switching. */
2260 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2261 if (!on_sig_stack(sp)
2262 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2263 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2264 }
2265 }
2266 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002267}
2268
2269static int
Andreas Färber05390242012-02-25 03:37:53 +01002270setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002271{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002272 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002273
Riku Voipio1d8b5122014-04-23 10:26:05 +03002274 __put_user(env->psr, &si->si_regs.psr);
2275 __put_user(env->pc, &si->si_regs.pc);
2276 __put_user(env->npc, &si->si_regs.npc);
2277 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002278 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002279 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002280 }
2281 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002282 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002283 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002284 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002285 return err;
bellard6d5e2162004-09-30 22:04:13 +00002286}
bellarde80cfcf2004-12-19 23:18:01 +00002287
bellard80a9d032005-01-03 23:31:27 +00002288#if 0
bellard6d5e2162004-09-30 22:04:13 +00002289static int
2290setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002291 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002292{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002293 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002294
Riku Voipio1d8b5122014-04-23 10:26:05 +03002295 __put_user(mask, &sc->sigc_mask);
2296 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2297 __put_user(env->pc, &sc->sigc_pc);
2298 __put_user(env->npc, &sc->sigc_npc);
2299 __put_user(env->psr, &sc->sigc_psr);
2300 __put_user(env->gregs[1], &sc->sigc_g1);
2301 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002302
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002303 return err;
bellard6d5e2162004-09-30 22:04:13 +00002304}
bellard80a9d032005-01-03 23:31:27 +00002305#endif
bellard6d5e2162004-09-30 22:04:13 +00002306#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2307
pbrook624f7972008-05-31 16:11:38 +00002308static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002309 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002310{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002311 abi_ulong sf_addr;
2312 struct target_signal_frame *sf;
2313 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002314
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002315 /* 1. Make sure everything is clean */
2316 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002317
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002318 sigframe_size = NF_ALIGNEDSZ;
2319 sf_addr = get_sigframe(ka, env, sigframe_size);
2320 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002321
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002322 sf = lock_user(VERIFY_WRITE, sf_addr,
2323 sizeof(struct target_signal_frame), 0);
2324 if (!sf) {
2325 goto sigsegv;
2326 }
bellard6d5e2162004-09-30 22:04:13 +00002327#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002328 if (invalid_frame_pointer(sf, sigframe_size))
2329 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002330#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002331 /* 2. Save the current process state */
2332 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002333 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002334
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002335 //save_fpu_state(regs, &sf->fpu_state);
2336 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002337
Riku Voipio1d8b5122014-04-23 10:26:05 +03002338 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002339 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002340 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002341 }
bellard6d5e2162004-09-30 22:04:13 +00002342
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002343 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002344 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002345 }
2346 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002347 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002348 }
2349 if (err)
2350 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002351
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002352 /* 3. signal handler back-trampoline and parameters */
2353 env->regwptr[UREG_FP] = sf_addr;
2354 env->regwptr[UREG_I0] = sig;
2355 env->regwptr[UREG_I1] = sf_addr +
2356 offsetof(struct target_signal_frame, info);
2357 env->regwptr[UREG_I2] = sf_addr +
2358 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002359
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002360 /* 4. signal handler */
2361 env->pc = ka->_sa_handler;
2362 env->npc = (env->pc + 4);
2363 /* 5. return to kernel instructions */
2364 if (ka->sa_restorer) {
2365 env->regwptr[UREG_I7] = ka->sa_restorer;
2366 } else {
2367 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002368
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002369 env->regwptr[UREG_I7] = sf_addr +
2370 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002371
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002372 /* mov __NR_sigreturn, %g1 */
2373 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002374 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002375
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002376 /* t 0x10 */
2377 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002378 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002379 if (err)
2380 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002381
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002382 /* Flush instruction space. */
2383 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2384 // tb_flush(env);
2385 }
2386 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2387 return;
bellard459a4012007-11-11 19:45:10 +00002388#if 0
2389sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002390 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002391#endif
bellard6d5e2162004-09-30 22:04:13 +00002392sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002393 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2394 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002395}
bellard6d5e2162004-09-30 22:04:13 +00002396
pbrook624f7972008-05-31 16:11:38 +00002397static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002398 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002399 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002400{
2401 fprintf(stderr, "setup_rt_frame: not implemented\n");
2402}
2403
Andreas Färber05390242012-02-25 03:37:53 +01002404long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002405{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002406 abi_ulong sf_addr;
2407 struct target_signal_frame *sf;
2408 uint32_t up_psr, pc, npc;
2409 target_sigset_t set;
2410 sigset_t host_set;
2411 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002412
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002413 sf_addr = env->regwptr[UREG_FP];
2414 trace_user_do_sigreturn(env, sf_addr);
2415 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2416 goto segv_and_exit;
2417 }
bellard6d5e2162004-09-30 22:04:13 +00002418
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002419 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002420
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002421 if (sf_addr & 3)
2422 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002423
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002424 __get_user(pc, &sf->info.si_regs.pc);
2425 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002426
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002427 if ((pc | npc) & 3) {
2428 goto segv_and_exit;
2429 }
bellard6d5e2162004-09-30 22:04:13 +00002430
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002431 /* 2. Restore the state */
2432 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002433
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002434 /* User can only change condition codes and FPU enabling in %psr. */
2435 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2436 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002437
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002438 env->pc = pc;
2439 env->npc = npc;
2440 __get_user(env->y, &sf->info.si_regs.y);
2441 for (i=0; i < 8; i++) {
2442 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2443 }
2444 for (i=0; i < 8; i++) {
2445 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2446 }
bellard6d5e2162004-09-30 22:04:13 +00002447
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002448 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002449 * __get_user(fpu_save, &sf->fpu_save);
2450 * if (fpu_save)
2451 * err |= restore_fpu_state(env, fpu_save);
2452 */
bellard6d5e2162004-09-30 22:04:13 +00002453
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002454 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00002455 * the races which exist anyways.
2456 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002457 __get_user(set.sig[0], &sf->info.si_mask);
2458 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2459 __get_user(set.sig[i], &sf->extramask[i - 1]);
2460 }
bellarde80cfcf2004-12-19 23:18:01 +00002461
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002462 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002463 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00002464
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002465 if (err) {
2466 goto segv_and_exit;
2467 }
2468 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01002469 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002470
2471segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002472 unlock_user_struct(sf, sf_addr, 0);
2473 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002474}
2475
Andreas Färber05390242012-02-25 03:37:53 +01002476long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002477{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002478 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00002479 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002480 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002481}
2482
bellard459a4012007-11-11 19:45:10 +00002483#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
blueswir15bfb56b2007-10-05 17:01:51 +00002484#define MC_TSTATE 0
2485#define MC_PC 1
2486#define MC_NPC 2
2487#define MC_Y 3
2488#define MC_G1 4
2489#define MC_G2 5
2490#define MC_G3 6
2491#define MC_G4 7
2492#define MC_G5 8
2493#define MC_G6 9
2494#define MC_G7 10
2495#define MC_O0 11
2496#define MC_O1 12
2497#define MC_O2 13
2498#define MC_O3 14
2499#define MC_O4 15
2500#define MC_O5 16
2501#define MC_O6 17
2502#define MC_O7 18
2503#define MC_NGREG 19
2504
Anthony Liguoric227f092009-10-01 16:12:16 -05002505typedef abi_ulong target_mc_greg_t;
2506typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002507
2508struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002509 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002510 uint32_t mcfq_insn;
2511};
2512
2513struct target_mc_fpu {
2514 union {
2515 uint32_t sregs[32];
2516 uint64_t dregs[32];
2517 //uint128_t qregs[16];
2518 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002519 abi_ulong mcfpu_fsr;
2520 abi_ulong mcfpu_fprs;
2521 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002522 struct target_mc_fq *mcfpu_fq;
2523 unsigned char mcfpu_qcnt;
2524 unsigned char mcfpu_qentsz;
2525 unsigned char mcfpu_enab;
2526};
Anthony Liguoric227f092009-10-01 16:12:16 -05002527typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002528
2529typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002530 target_mc_gregset_t mc_gregs;
2531 target_mc_greg_t mc_fp;
2532 target_mc_greg_t mc_i7;
2533 target_mc_fpu_t mc_fpregs;
2534} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002535
2536struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002537 struct target_ucontext *tuc_link;
2538 abi_ulong tuc_flags;
2539 target_sigset_t tuc_sigmask;
2540 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002541};
2542
2543/* A V9 register window */
2544struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002545 abi_ulong locals[8];
2546 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002547};
2548
2549#define TARGET_STACK_BIAS 2047
2550
2551/* {set, get}context() needed for 64-bit SparcLinux userland. */
2552void sparc64_set_context(CPUSPARCState *env)
2553{
bellard459a4012007-11-11 19:45:10 +00002554 abi_ulong ucp_addr;
2555 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002556 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002557 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002558 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002559 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002560
bellard459a4012007-11-11 19:45:10 +00002561 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002562 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00002563 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002564 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02002565 grp = &ucp->tuc_mcontext.mc_gregs;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002566 __get_user(pc, &((*grp)[MC_PC]));
2567 __get_user(npc, &((*grp)[MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002568 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00002569 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002570 }
blueswir15bfb56b2007-10-05 17:01:51 +00002571 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002572 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002573 sigset_t set;
2574
2575 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002576 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002577 } else {
bellard459a4012007-11-11 19:45:10 +00002578 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002579 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002580 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002581 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002582 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002583 }
blueswir15bfb56b2007-10-05 17:01:51 +00002584 }
2585 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002586 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00002587 }
2588 env->pc = pc;
2589 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002590 __get_user(env->y, &((*grp)[MC_Y]));
2591 __get_user(tstate, &((*grp)[MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002592 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002593 cpu_put_ccr(env, tstate >> 32);
2594 cpu_put_cwp64(env, tstate & 0x1f);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002595 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2596 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2597 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2598 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2599 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2600 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2601 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2602 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2603 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2604 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2605 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2606 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2607 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2608 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2609 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002610
Riku Voipio1d8b5122014-04-23 10:26:05 +03002611 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2612 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002613
bellard459a4012007-11-11 19:45:10 +00002614 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002615 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2616 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002617 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002618 }
2619 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2620 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002621 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002622 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01002623 /* FIXME this does not match how the kernel handles the FPU in
2624 * its sparc64_set_context implementation. In particular the FPU
2625 * is only restored if fenab is non-zero in:
2626 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2627 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002628 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002629 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002630 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2631 for (i = 0; i < 64; i++, src++) {
2632 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002633 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002634 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002635 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002636 }
2637 }
bellard459a4012007-11-11 19:45:10 +00002638 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002639 __get_user(env->fsr,
2640 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2641 __get_user(env->gsr,
2642 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002643 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002644 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002645do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002646 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002647 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002648}
2649
2650void sparc64_get_context(CPUSPARCState *env)
2651{
bellard459a4012007-11-11 19:45:10 +00002652 abi_ulong ucp_addr;
2653 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002654 target_mc_gregset_t *grp;
2655 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002656 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002657 int err;
2658 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002659 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002660 sigset_t set;
2661
bellard459a4012007-11-11 19:45:10 +00002662 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002663 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00002664 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002665 }
bellard459a4012007-11-11 19:45:10 +00002666
Aurelien Jarno60e99242010-03-29 02:12:51 +02002667 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002668 grp = &mcp->mc_gregs;
2669
2670 /* Skip over the trap instruction, first. */
2671 env->pc = env->npc;
2672 env->npc += 4;
2673
Peter Maydell3d3efba2016-05-27 15:51:49 +01002674 /* If we're only reading the signal mask then do_sigprocmask()
2675 * is guaranteed not to fail, which is important because we don't
2676 * have any way to signal a failure or restart this operation since
2677 * this is not a normal syscall.
2678 */
2679 err = do_sigprocmask(0, NULL, &set);
2680 assert(err == 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002681 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00002682 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002683 __put_user(target_set.sig[0],
2684 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00002685 } else {
2686 abi_ulong *src, *dst;
2687 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002688 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002689 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002690 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002691 }
blueswir15bfb56b2007-10-05 17:01:51 +00002692 if (err)
2693 goto do_sigsegv;
2694 }
2695
bellard459a4012007-11-11 19:45:10 +00002696 /* XXX: tstate must be saved properly */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002697 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2698 __put_user(env->pc, &((*grp)[MC_PC]));
2699 __put_user(env->npc, &((*grp)[MC_NPC]));
2700 __put_user(env->y, &((*grp)[MC_Y]));
2701 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2702 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2703 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2704 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2705 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2706 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2707 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2708 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2709 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2710 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2711 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2712 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2713 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2714 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2715 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002716
bellard459a4012007-11-11 19:45:10 +00002717 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2718 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002719 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2720 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002721 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002722 }
2723 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2724 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002725 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002726 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002727 __put_user(fp, &(mcp->mc_fp));
2728 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002729
bellard459a4012007-11-11 19:45:10 +00002730 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002731 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2732 for (i = 0; i < 64; i++, dst++) {
2733 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002734 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002735 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002736 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002737 }
2738 }
bellard459a4012007-11-11 19:45:10 +00002739 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002740 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2741 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2742 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00002743
2744 if (err)
2745 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00002746 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00002747 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002748do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002749 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02002750 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002751}
2752#endif
Richard Hendersonff970902013-02-10 10:30:42 -08002753#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00002754
Richard Hendersonff970902013-02-10 10:30:42 -08002755# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00002756struct target_sigcontext {
2757 uint32_t sc_regmask; /* Unused */
2758 uint32_t sc_status;
2759 uint64_t sc_pc;
2760 uint64_t sc_regs[32];
2761 uint64_t sc_fpregs[32];
2762 uint32_t sc_ownedfp; /* Unused */
2763 uint32_t sc_fpc_csr;
2764 uint32_t sc_fpc_eir; /* Unused */
2765 uint32_t sc_used_math;
2766 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01002767 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00002768 uint64_t sc_mdhi;
2769 uint64_t sc_mdlo;
2770 target_ulong sc_hi1; /* Was sc_cause */
2771 target_ulong sc_lo1; /* Was sc_badvaddr */
2772 target_ulong sc_hi2; /* Was sc_sigset[4] */
2773 target_ulong sc_lo2;
2774 target_ulong sc_hi3;
2775 target_ulong sc_lo3;
2776};
Richard Hendersonff970902013-02-10 10:30:42 -08002777# else /* N32 || N64 */
2778struct target_sigcontext {
2779 uint64_t sc_regs[32];
2780 uint64_t sc_fpregs[32];
2781 uint64_t sc_mdhi;
2782 uint64_t sc_hi1;
2783 uint64_t sc_hi2;
2784 uint64_t sc_hi3;
2785 uint64_t sc_mdlo;
2786 uint64_t sc_lo1;
2787 uint64_t sc_lo2;
2788 uint64_t sc_lo3;
2789 uint64_t sc_pc;
2790 uint32_t sc_fpc_csr;
2791 uint32_t sc_used_math;
2792 uint32_t sc_dsp;
2793 uint32_t sc_reserved;
2794};
2795# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00002796
2797struct sigframe {
2798 uint32_t sf_ass[4]; /* argument save space for o32 */
2799 uint32_t sf_code[2]; /* signal trampoline */
2800 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002801 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00002802};
2803
pbrook0b1bcb02009-04-21 01:41:10 +00002804struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002805 target_ulong tuc_flags;
2806 target_ulong tuc_link;
2807 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01002808 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002809 struct target_sigcontext tuc_mcontext;
2810 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00002811};
2812
2813struct target_rt_sigframe {
2814 uint32_t rs_ass[4]; /* argument save space for o32 */
2815 uint32_t rs_code[2]; /* signal trampoline */
2816 struct target_siginfo rs_info;
2817 struct target_ucontext rs_uc;
2818};
2819
bellard106ec872006-06-27 21:08:10 +00002820/* Install trampoline to jump back from signal handler */
2821static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2822{
Richard Henderson084d0492013-02-10 10:30:44 -08002823 int err = 0;
bellard106ec872006-06-27 21:08:10 +00002824
2825 /*
Richard Henderson084d0492013-02-10 10:30:44 -08002826 * Set up the return code ...
2827 *
2828 * li v0, __NR__foo_sigreturn
2829 * syscall
2830 */
bellard106ec872006-06-27 21:08:10 +00002831
Riku Voipio1d8b5122014-04-23 10:26:05 +03002832 __put_user(0x24020000 + syscall, tramp + 0);
2833 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00002834 return err;
2835}
2836
Riku Voipio41ecc722014-04-23 11:01:00 +03002837static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002838 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002839{
Richard Henderson084d0492013-02-10 10:30:44 -08002840 int i;
bellard106ec872006-06-27 21:08:10 +00002841
Riku Voipio1d8b5122014-04-23 10:26:05 +03002842 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07002843 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00002844
Richard Henderson084d0492013-02-10 10:30:44 -08002845 __put_user(0, &sc->sc_regs[0]);
2846 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002847 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002848 }
bellard106ec872006-06-27 21:08:10 +00002849
Riku Voipio1d8b5122014-04-23 10:26:05 +03002850 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2851 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002852
Richard Henderson084d0492013-02-10 10:30:44 -08002853 /* Rather than checking for dsp existence, always copy. The storage
2854 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002855 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2856 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2857 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2858 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2859 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2860 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002861 {
2862 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002863 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00002864 }
Richard Henderson084d0492013-02-10 10:30:44 -08002865
Riku Voipio1d8b5122014-04-23 10:26:05 +03002866 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08002867
2868 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002869 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00002870 }
bellard106ec872006-06-27 21:08:10 +00002871}
2872
Riku Voipio016d2e12014-04-23 11:19:48 +03002873static inline void
Andreas Färber05390242012-02-25 03:37:53 +01002874restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002875{
Richard Henderson084d0492013-02-10 10:30:44 -08002876 int i;
bellard106ec872006-06-27 21:08:10 +00002877
Riku Voipio1d8b5122014-04-23 10:26:05 +03002878 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00002879
Riku Voipio1d8b5122014-04-23 10:26:05 +03002880 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2881 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002882
Richard Henderson084d0492013-02-10 10:30:44 -08002883 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002884 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00002885 }
2886
Riku Voipio1d8b5122014-04-23 10:26:05 +03002887 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2888 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2889 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2890 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2891 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2892 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002893 {
2894 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002895 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08002896 cpu_wrdsp(dsp, 0x3ff, regs);
2897 }
2898
2899 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002900 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002901 }
bellard106ec872006-06-27 21:08:10 +00002902}
Richard Hendersonff970902013-02-10 10:30:42 -08002903
bellard106ec872006-06-27 21:08:10 +00002904/*
2905 * Determine which stack to use..
2906 */
bellard579a97f2007-11-11 14:26:47 +00002907static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002908get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00002909{
2910 unsigned long sp;
2911
2912 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00002913 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00002914
2915 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01002916 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00002917 * above the user stack, 16-bytes before the next lowest
2918 * 16 byte boundary. Try to avoid trashing it.
2919 */
2920 sp -= 32;
2921
bellard106ec872006-06-27 21:08:10 +00002922 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00002923 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00002924 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2925 }
bellard106ec872006-06-27 21:08:10 +00002926
bellard579a97f2007-11-11 14:26:47 +00002927 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00002928}
2929
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002930static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
2931{
2932 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
2933 env->hflags &= ~MIPS_HFLAG_M16;
2934 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
2935 env->active_tc.PC &= ~(target_ulong) 1;
2936 }
2937}
2938
Richard Hendersonff970902013-02-10 10:30:42 -08002939# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00002940/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002941static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01002942 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002943{
2944 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002945 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00002946 int i;
2947
bellard579a97f2007-11-11 14:26:47 +00002948 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002949 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002950 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
2951 goto give_sigsegv;
2952 }
bellard106ec872006-06-27 21:08:10 +00002953
2954 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2955
Riku Voipio41ecc722014-04-23 11:01:00 +03002956 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002957
2958 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03002959 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00002960 }
2961
2962 /*
2963 * Arguments to signal handler:
2964 *
2965 * a0 = signal number
2966 * a1 = 0 (should be cause)
2967 * a2 = pointer to struct sigcontext
2968 *
2969 * $25 and PC point to the signal handler, $29 points to the
2970 * struct sigframe.
2971 */
thsb5dc7732008-06-27 10:02:35 +00002972 regs->active_tc.gpr[ 4] = sig;
2973 regs->active_tc.gpr[ 5] = 0;
2974 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2975 regs->active_tc.gpr[29] = frame_addr;
2976 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00002977 /* The original kernel code sets CP0_EPC to the handler
2978 * since it returns to userland using eret
2979 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00002980 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002981 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00002982 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00002983 return;
2984
2985give_sigsegv:
2986 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00002987}
2988
Andreas Färber05390242012-02-25 03:37:53 +01002989long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002990{
ths388bb212007-05-13 13:58:00 +00002991 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002992 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00002993 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05002994 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00002995 int i;
bellard106ec872006-06-27 21:08:10 +00002996
thsb5dc7732008-06-27 10:02:35 +00002997 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002998 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00002999 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003000 goto badframe;
bellard106ec872006-06-27 21:08:10 +00003001
ths388bb212007-05-13 13:58:00 +00003002 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003003 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003004 }
bellard106ec872006-06-27 21:08:10 +00003005
ths388bb212007-05-13 13:58:00 +00003006 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003007 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003008
Riku Voipio016d2e12014-04-23 11:19:48 +03003009 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003010
3011#if 0
ths388bb212007-05-13 13:58:00 +00003012 /*
3013 * Don't let your children do this ...
3014 */
3015 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003016 "move\t$29, %0\n\t"
3017 "j\tsyscall_exit"
3018 :/* no outputs */
3019 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003020 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003021#endif
ths3b46e622007-09-17 08:09:54 +00003022
thsb5dc7732008-06-27 10:02:35 +00003023 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003024 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003025 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003026 * maybe a problem with nested signals ? */
3027 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003028 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003029
3030badframe:
ths388bb212007-05-13 13:58:00 +00003031 force_sig(TARGET_SIGSEGV/*, current*/);
3032 return 0;
bellard106ec872006-06-27 21:08:10 +00003033}
Richard Hendersonff970902013-02-10 10:30:42 -08003034# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003035
pbrook624f7972008-05-31 16:11:38 +00003036static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003037 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003038 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003039{
pbrook0b1bcb02009-04-21 01:41:10 +00003040 struct target_rt_sigframe *frame;
3041 abi_ulong frame_addr;
3042 int i;
3043
3044 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003045 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003046 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3047 goto give_sigsegv;
3048 }
pbrook0b1bcb02009-04-21 01:41:10 +00003049
3050 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3051
Peter Maydellf6c7a052015-01-08 12:19:48 +00003052 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003053
Aurelien Jarno60e99242010-03-29 02:12:51 +02003054 __put_user(0, &frame->rs_uc.tuc_flags);
3055 __put_user(0, &frame->rs_uc.tuc_link);
3056 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3057 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003058 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003059 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003060
Aurelien Jarno60e99242010-03-29 02:12:51 +02003061 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003062
3063 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003064 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003065 }
3066
3067 /*
3068 * Arguments to signal handler:
3069 *
3070 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003071 * a1 = pointer to siginfo_t
pbrook0b1bcb02009-04-21 01:41:10 +00003072 * a2 = pointer to struct ucontext
3073 *
3074 * $25 and PC point to the signal handler, $29 points to the
3075 * struct sigframe.
3076 */
3077 env->active_tc.gpr[ 4] = sig;
3078 env->active_tc.gpr[ 5] = frame_addr
3079 + offsetof(struct target_rt_sigframe, rs_info);
3080 env->active_tc.gpr[ 6] = frame_addr
3081 + offsetof(struct target_rt_sigframe, rs_uc);
3082 env->active_tc.gpr[29] = frame_addr;
3083 env->active_tc.gpr[31] = frame_addr
3084 + offsetof(struct target_rt_sigframe, rs_code);
3085 /* The original kernel code sets CP0_EPC to the handler
3086 * since it returns to userland using eret
3087 * we cannot do this here, and we must set PC directly */
3088 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003089 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003090 unlock_user_struct(frame, frame_addr, 1);
3091 return;
3092
3093give_sigsegv:
3094 unlock_user_struct(frame, frame_addr, 1);
3095 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00003096}
3097
Andreas Färber05390242012-02-25 03:37:53 +01003098long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003099{
pbrook0b1bcb02009-04-21 01:41:10 +00003100 struct target_rt_sigframe *frame;
3101 abi_ulong frame_addr;
3102 sigset_t blocked;
3103
pbrook0b1bcb02009-04-21 01:41:10 +00003104 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003105 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003106 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3107 goto badframe;
3108 }
pbrook0b1bcb02009-04-21 01:41:10 +00003109
Aurelien Jarno60e99242010-03-29 02:12:51 +02003110 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003111 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003112
Riku Voipio016d2e12014-04-23 11:19:48 +03003113 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003114
3115 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003116 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3117 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003118 goto badframe;
3119
3120 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003121 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003122 /* I am not sure this is right, but it seems to work
3123 * maybe a problem with nested signals ? */
3124 env->CP0_EPC = 0;
3125 return -TARGET_QEMU_ESIGRETURN;
3126
3127badframe:
3128 force_sig(TARGET_SIGSEGV/*, current*/);
3129 return 0;
bellard106ec872006-06-27 21:08:10 +00003130}
bellard6d5e2162004-09-30 22:04:13 +00003131
thsc3b5bc82007-12-02 06:31:25 +00003132#elif defined(TARGET_SH4)
3133
3134/*
3135 * code and data structures from linux kernel:
3136 * include/asm-sh/sigcontext.h
3137 * arch/sh/kernel/signal.c
3138 */
3139
3140struct target_sigcontext {
3141 target_ulong oldmask;
3142
3143 /* CPU registers */
3144 target_ulong sc_gregs[16];
3145 target_ulong sc_pc;
3146 target_ulong sc_pr;
3147 target_ulong sc_sr;
3148 target_ulong sc_gbr;
3149 target_ulong sc_mach;
3150 target_ulong sc_macl;
3151
3152 /* FPU registers */
3153 target_ulong sc_fpregs[16];
3154 target_ulong sc_xfpregs[16];
3155 unsigned int sc_fpscr;
3156 unsigned int sc_fpul;
3157 unsigned int sc_ownedfp;
3158};
3159
3160struct target_sigframe
3161{
3162 struct target_sigcontext sc;
3163 target_ulong extramask[TARGET_NSIG_WORDS-1];
3164 uint16_t retcode[3];
3165};
3166
3167
3168struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003169 target_ulong tuc_flags;
3170 struct target_ucontext *tuc_link;
3171 target_stack_t tuc_stack;
3172 struct target_sigcontext tuc_mcontext;
3173 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003174};
3175
3176struct target_rt_sigframe
3177{
3178 struct target_siginfo info;
3179 struct target_ucontext uc;
3180 uint16_t retcode[3];
3181};
3182
3183
3184#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3185#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3186
pbrook624f7972008-05-31 16:11:38 +00003187static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003188 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003189{
pbrook624f7972008-05-31 16:11:38 +00003190 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003191 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3192 }
3193
3194 return (sp - frame_size) & -8ul;
3195}
3196
Riku Voipio41ecc722014-04-23 11:01:00 +03003197static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003198 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003199{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003200 int i;
thsc3b5bc82007-12-02 06:31:25 +00003201
Riku Voipio1d8b5122014-04-23 10:26:05 +03003202#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003203 COPY(gregs[0]); COPY(gregs[1]);
3204 COPY(gregs[2]); COPY(gregs[3]);
3205 COPY(gregs[4]); COPY(gregs[5]);
3206 COPY(gregs[6]); COPY(gregs[7]);
3207 COPY(gregs[8]); COPY(gregs[9]);
3208 COPY(gregs[10]); COPY(gregs[11]);
3209 COPY(gregs[12]); COPY(gregs[13]);
3210 COPY(gregs[14]); COPY(gregs[15]);
3211 COPY(gbr); COPY(mach);
3212 COPY(macl); COPY(pr);
3213 COPY(sr); COPY(pc);
3214#undef COPY
3215
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003216 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003217 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003218 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003219 __put_user(regs->fpscr, &sc->sc_fpscr);
3220 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003221
3222 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003223 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003224}
3225
Timothy E Baldwinba412492016-05-12 18:47:35 +01003226static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003227{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003228 int i;
thsc3b5bc82007-12-02 06:31:25 +00003229
Riku Voipio1d8b5122014-04-23 10:26:05 +03003230#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003231 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003232 COPY(gregs[2]); COPY(gregs[3]);
3233 COPY(gregs[4]); COPY(gregs[5]);
3234 COPY(gregs[6]); COPY(gregs[7]);
3235 COPY(gregs[8]); COPY(gregs[9]);
3236 COPY(gregs[10]); COPY(gregs[11]);
3237 COPY(gregs[12]); COPY(gregs[13]);
3238 COPY(gregs[14]); COPY(gregs[15]);
3239 COPY(gbr); COPY(mach);
3240 COPY(macl); COPY(pr);
3241 COPY(sr); COPY(pc);
3242#undef COPY
3243
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003244 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003245 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003246 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003247 __get_user(regs->fpscr, &sc->sc_fpscr);
3248 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003249
3250 regs->tra = -1; /* disable syscall checks */
thsc3b5bc82007-12-02 06:31:25 +00003251}
3252
pbrook624f7972008-05-31 16:11:38 +00003253static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003254 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003255{
3256 struct target_sigframe *frame;
3257 abi_ulong frame_addr;
3258 int i;
thsc3b5bc82007-12-02 06:31:25 +00003259
3260 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003261 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003262 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3263 goto give_sigsegv;
3264 }
thsc3b5bc82007-12-02 06:31:25 +00003265
Riku Voipio41ecc722014-04-23 11:01:00 +03003266 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003267
3268 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003269 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003270 }
3271
3272 /* Set up to return from userspace. If provided, use a stub
3273 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003274 if (ka->sa_flags & TARGET_SA_RESTORER) {
3275 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003276 } else {
3277 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003278 abi_ulong retcode_addr = frame_addr +
3279 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003280 __put_user(MOVW(2), &frame->retcode[0]);
3281 __put_user(TRAP_NOARG, &frame->retcode[1]);
3282 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003283 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003284 }
3285
thsc3b5bc82007-12-02 06:31:25 +00003286 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003287 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003288 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003289 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003290 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003291 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003292
3293 unlock_user_struct(frame, frame_addr, 1);
3294 return;
3295
3296give_sigsegv:
3297 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003298 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003299}
3300
pbrook624f7972008-05-31 16:11:38 +00003301static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003302 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003303 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003304{
3305 struct target_rt_sigframe *frame;
3306 abi_ulong frame_addr;
3307 int i;
thsc3b5bc82007-12-02 06:31:25 +00003308
3309 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003310 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003311 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3312 goto give_sigsegv;
3313 }
thsc3b5bc82007-12-02 06:31:25 +00003314
Peter Maydellf6c7a052015-01-08 12:19:48 +00003315 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003316
3317 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003318 __put_user(0, &frame->uc.tuc_flags);
3319 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3320 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3321 &frame->uc.tuc_stack.ss_sp);
3322 __put_user(sas_ss_flags(regs->gregs[15]),
3323 &frame->uc.tuc_stack.ss_flags);
3324 __put_user(target_sigaltstack_used.ss_size,
3325 &frame->uc.tuc_stack.ss_size);
3326 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003327 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003328 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003329 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003330 }
3331
3332 /* Set up to return from userspace. If provided, use a stub
3333 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003334 if (ka->sa_flags & TARGET_SA_RESTORER) {
3335 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003336 } else {
3337 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003338 abi_ulong retcode_addr = frame_addr +
3339 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003340 __put_user(MOVW(2), &frame->retcode[0]);
3341 __put_user(TRAP_NOARG, &frame->retcode[1]);
3342 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003343 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003344 }
3345
thsc3b5bc82007-12-02 06:31:25 +00003346 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003347 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003348 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003349 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3350 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003351 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003352
3353 unlock_user_struct(frame, frame_addr, 1);
3354 return;
3355
3356give_sigsegv:
3357 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003358 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003359}
3360
Andreas Färber05390242012-02-25 03:37:53 +01003361long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003362{
3363 struct target_sigframe *frame;
3364 abi_ulong frame_addr;
3365 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003366 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003367 int i;
3368 int err = 0;
3369
thsc3b5bc82007-12-02 06:31:25 +00003370 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003371 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003372 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3373 goto badframe;
3374 }
thsc3b5bc82007-12-02 06:31:25 +00003375
Riku Voipio1d8b5122014-04-23 10:26:05 +03003376 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003377 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003378 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003379 }
3380
3381 if (err)
3382 goto badframe;
3383
3384 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003385 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003386
Timothy E Baldwinba412492016-05-12 18:47:35 +01003387 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003388
3389 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003390 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003391
3392badframe:
3393 unlock_user_struct(frame, frame_addr, 0);
3394 force_sig(TARGET_SIGSEGV);
3395 return 0;
3396}
3397
Andreas Färber05390242012-02-25 03:37:53 +01003398long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003399{
3400 struct target_rt_sigframe *frame;
3401 abi_ulong frame_addr;
3402 sigset_t blocked;
3403
thsc3b5bc82007-12-02 06:31:25 +00003404 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003405 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003406 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3407 goto badframe;
3408 }
thsc3b5bc82007-12-02 06:31:25 +00003409
Aurelien Jarno60e99242010-03-29 02:12:51 +02003410 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003411 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003412
Timothy E Baldwinba412492016-05-12 18:47:35 +01003413 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003414
3415 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003416 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3417 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00003418 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003419 }
thsc3b5bc82007-12-02 06:31:25 +00003420
3421 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003422 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003423
3424badframe:
3425 unlock_user_struct(frame, frame_addr, 0);
3426 force_sig(TARGET_SIGSEGV);
3427 return 0;
3428}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003429#elif defined(TARGET_MICROBLAZE)
3430
3431struct target_sigcontext {
3432 struct target_pt_regs regs; /* needs to be first */
3433 uint32_t oldmask;
3434};
3435
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003436struct target_stack_t {
3437 abi_ulong ss_sp;
3438 int ss_flags;
3439 unsigned int ss_size;
3440};
3441
3442struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003443 abi_ulong tuc_flags;
3444 abi_ulong tuc_link;
3445 struct target_stack_t tuc_stack;
3446 struct target_sigcontext tuc_mcontext;
3447 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003448};
3449
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003450/* Signal frames. */
3451struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003452 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003453 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3454 uint32_t tramp[2];
3455};
3456
3457struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003458 siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003459 struct ucontext uc;
3460 uint32_t tramp[2];
3461};
3462
Andreas Färber05390242012-02-25 03:37:53 +01003463static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003464{
3465 __put_user(env->regs[0], &sc->regs.r0);
3466 __put_user(env->regs[1], &sc->regs.r1);
3467 __put_user(env->regs[2], &sc->regs.r2);
3468 __put_user(env->regs[3], &sc->regs.r3);
3469 __put_user(env->regs[4], &sc->regs.r4);
3470 __put_user(env->regs[5], &sc->regs.r5);
3471 __put_user(env->regs[6], &sc->regs.r6);
3472 __put_user(env->regs[7], &sc->regs.r7);
3473 __put_user(env->regs[8], &sc->regs.r8);
3474 __put_user(env->regs[9], &sc->regs.r9);
3475 __put_user(env->regs[10], &sc->regs.r10);
3476 __put_user(env->regs[11], &sc->regs.r11);
3477 __put_user(env->regs[12], &sc->regs.r12);
3478 __put_user(env->regs[13], &sc->regs.r13);
3479 __put_user(env->regs[14], &sc->regs.r14);
3480 __put_user(env->regs[15], &sc->regs.r15);
3481 __put_user(env->regs[16], &sc->regs.r16);
3482 __put_user(env->regs[17], &sc->regs.r17);
3483 __put_user(env->regs[18], &sc->regs.r18);
3484 __put_user(env->regs[19], &sc->regs.r19);
3485 __put_user(env->regs[20], &sc->regs.r20);
3486 __put_user(env->regs[21], &sc->regs.r21);
3487 __put_user(env->regs[22], &sc->regs.r22);
3488 __put_user(env->regs[23], &sc->regs.r23);
3489 __put_user(env->regs[24], &sc->regs.r24);
3490 __put_user(env->regs[25], &sc->regs.r25);
3491 __put_user(env->regs[26], &sc->regs.r26);
3492 __put_user(env->regs[27], &sc->regs.r27);
3493 __put_user(env->regs[28], &sc->regs.r28);
3494 __put_user(env->regs[29], &sc->regs.r29);
3495 __put_user(env->regs[30], &sc->regs.r30);
3496 __put_user(env->regs[31], &sc->regs.r31);
3497 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3498}
3499
Andreas Färber05390242012-02-25 03:37:53 +01003500static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003501{
3502 __get_user(env->regs[0], &sc->regs.r0);
3503 __get_user(env->regs[1], &sc->regs.r1);
3504 __get_user(env->regs[2], &sc->regs.r2);
3505 __get_user(env->regs[3], &sc->regs.r3);
3506 __get_user(env->regs[4], &sc->regs.r4);
3507 __get_user(env->regs[5], &sc->regs.r5);
3508 __get_user(env->regs[6], &sc->regs.r6);
3509 __get_user(env->regs[7], &sc->regs.r7);
3510 __get_user(env->regs[8], &sc->regs.r8);
3511 __get_user(env->regs[9], &sc->regs.r9);
3512 __get_user(env->regs[10], &sc->regs.r10);
3513 __get_user(env->regs[11], &sc->regs.r11);
3514 __get_user(env->regs[12], &sc->regs.r12);
3515 __get_user(env->regs[13], &sc->regs.r13);
3516 __get_user(env->regs[14], &sc->regs.r14);
3517 __get_user(env->regs[15], &sc->regs.r15);
3518 __get_user(env->regs[16], &sc->regs.r16);
3519 __get_user(env->regs[17], &sc->regs.r17);
3520 __get_user(env->regs[18], &sc->regs.r18);
3521 __get_user(env->regs[19], &sc->regs.r19);
3522 __get_user(env->regs[20], &sc->regs.r20);
3523 __get_user(env->regs[21], &sc->regs.r21);
3524 __get_user(env->regs[22], &sc->regs.r22);
3525 __get_user(env->regs[23], &sc->regs.r23);
3526 __get_user(env->regs[24], &sc->regs.r24);
3527 __get_user(env->regs[25], &sc->regs.r25);
3528 __get_user(env->regs[26], &sc->regs.r26);
3529 __get_user(env->regs[27], &sc->regs.r27);
3530 __get_user(env->regs[28], &sc->regs.r28);
3531 __get_user(env->regs[29], &sc->regs.r29);
3532 __get_user(env->regs[30], &sc->regs.r30);
3533 __get_user(env->regs[31], &sc->regs.r31);
3534 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3535}
3536
3537static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003538 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003539{
3540 abi_ulong sp = env->regs[1];
3541
Riku Voipiob545f632014-07-15 17:01:55 +03003542 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003543 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003544 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003545
3546 return ((sp - frame_size) & -8UL);
3547}
3548
3549static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003550 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003551{
3552 struct target_signal_frame *frame;
3553 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003554 int i;
3555
3556 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003557 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003558 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3559 goto badframe;
3560
3561 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003562 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003563
3564 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003565 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003566 }
3567
Richard Hendersonf711df62010-11-22 14:57:52 -08003568 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003569
3570 /* Set up to return from userspace. If provided, use a stub
3571 already in userspace. */
3572 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3573 if (ka->sa_flags & TARGET_SA_RESTORER) {
3574 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3575 } else {
3576 uint32_t t;
3577 /* Note, these encodings are _big endian_! */
3578 /* addi r12, r0, __NR_sigreturn */
3579 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003580 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003581 /* brki r14, 0x8 */
3582 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003583 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003584
3585 /* Return from sighandler will jump to the tramp.
3586 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08003587 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
3588 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003589 }
3590
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003591 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003592 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003593 /* Signal handler args: */
3594 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02003595 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003596 /* arg 1: sigcontext */
3597 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003598
3599 /* Offset of 4 to handle microblaze rtid r14, 0 */
3600 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3601
3602 unlock_user_struct(frame, frame_addr, 1);
3603 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003604badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003605 force_sig(TARGET_SIGSEGV);
3606}
3607
3608static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003609 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003610 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003611{
3612 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3613}
3614
Andreas Färber05390242012-02-25 03:37:53 +01003615long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003616{
3617 struct target_signal_frame *frame;
3618 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003619 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003620 sigset_t set;
3621 int i;
3622
3623 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003624 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003625 /* Make sure the guest isn't playing games. */
3626 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3627 goto badframe;
3628
3629 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003630 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003631 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003632 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003633 }
3634 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003635 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003636
Richard Hendersonf711df62010-11-22 14:57:52 -08003637 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003638 /* We got here through a sigreturn syscall, our path back is via an
3639 rtb insn so setup r14 for that. */
3640 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003641
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003642 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01003643 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003644badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003645 force_sig(TARGET_SIGSEGV);
3646}
3647
Andreas Färber05390242012-02-25 03:37:53 +01003648long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003649{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003650 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003651 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3652 return -TARGET_ENOSYS;
3653}
3654
edgar_iglb6d3abd2008-02-28 11:29:27 +00003655#elif defined(TARGET_CRIS)
3656
3657struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003658 struct target_pt_regs regs; /* needs to be first */
3659 uint32_t oldmask;
3660 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003661};
3662
3663/* Signal frames. */
3664struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003665 struct target_sigcontext sc;
3666 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3667 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003668};
3669
3670struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003671 siginfo_t *pinfo;
3672 void *puc;
3673 siginfo_t info;
3674 struct ucontext uc;
3675 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003676};
3677
Andreas Färber05390242012-02-25 03:37:53 +01003678static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003679{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003680 __put_user(env->regs[0], &sc->regs.r0);
3681 __put_user(env->regs[1], &sc->regs.r1);
3682 __put_user(env->regs[2], &sc->regs.r2);
3683 __put_user(env->regs[3], &sc->regs.r3);
3684 __put_user(env->regs[4], &sc->regs.r4);
3685 __put_user(env->regs[5], &sc->regs.r5);
3686 __put_user(env->regs[6], &sc->regs.r6);
3687 __put_user(env->regs[7], &sc->regs.r7);
3688 __put_user(env->regs[8], &sc->regs.r8);
3689 __put_user(env->regs[9], &sc->regs.r9);
3690 __put_user(env->regs[10], &sc->regs.r10);
3691 __put_user(env->regs[11], &sc->regs.r11);
3692 __put_user(env->regs[12], &sc->regs.r12);
3693 __put_user(env->regs[13], &sc->regs.r13);
3694 __put_user(env->regs[14], &sc->usp);
3695 __put_user(env->regs[15], &sc->regs.acr);
3696 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3697 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3698 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003699}
edgar_igl9664d922008-03-03 22:23:53 +00003700
Andreas Färber05390242012-02-25 03:37:53 +01003701static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003702{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003703 __get_user(env->regs[0], &sc->regs.r0);
3704 __get_user(env->regs[1], &sc->regs.r1);
3705 __get_user(env->regs[2], &sc->regs.r2);
3706 __get_user(env->regs[3], &sc->regs.r3);
3707 __get_user(env->regs[4], &sc->regs.r4);
3708 __get_user(env->regs[5], &sc->regs.r5);
3709 __get_user(env->regs[6], &sc->regs.r6);
3710 __get_user(env->regs[7], &sc->regs.r7);
3711 __get_user(env->regs[8], &sc->regs.r8);
3712 __get_user(env->regs[9], &sc->regs.r9);
3713 __get_user(env->regs[10], &sc->regs.r10);
3714 __get_user(env->regs[11], &sc->regs.r11);
3715 __get_user(env->regs[12], &sc->regs.r12);
3716 __get_user(env->regs[13], &sc->regs.r13);
3717 __get_user(env->regs[14], &sc->usp);
3718 __get_user(env->regs[15], &sc->regs.acr);
3719 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3720 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3721 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003722}
3723
Andreas Färber05390242012-02-25 03:37:53 +01003724static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003725{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003726 abi_ulong sp;
3727 /* Align the stack downwards to 4. */
3728 sp = (env->regs[R_SP] & ~3);
3729 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003730}
3731
pbrook624f7972008-05-31 16:11:38 +00003732static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003733 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003734{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003735 struct target_signal_frame *frame;
3736 abi_ulong frame_addr;
3737 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003738
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003739 frame_addr = get_sigframe(env, sizeof *frame);
3740 trace_user_setup_frame(env, frame_addr);
3741 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3742 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003743
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003744 /*
3745 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3746 * use this trampoline anymore but it sets it up for GDB.
3747 * In QEMU, using the trampoline simplifies things a bit so we use it.
3748 *
3749 * This is movu.w __NR_sigreturn, r9; break 13;
3750 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003751 __put_user(0x9c5f, frame->retcode+0);
3752 __put_user(TARGET_NR_sigreturn,
3753 frame->retcode + 1);
3754 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003755
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003756 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003757 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003758
Riku Voipio0188fad2014-04-23 13:34:15 +03003759 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3760 __put_user(set->sig[i], &frame->extramask[i - 1]);
3761 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003762
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003763 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003764
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003765 /* Move the stack and setup the arguments for the handler. */
3766 env->regs[R_SP] = frame_addr;
3767 env->regs[10] = sig;
3768 env->pc = (unsigned long) ka->_sa_handler;
3769 /* Link SRP so the guest returns through the trampoline. */
3770 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003771
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003772 unlock_user_struct(frame, frame_addr, 1);
3773 return;
3774badframe:
3775 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003776}
3777
pbrook624f7972008-05-31 16:11:38 +00003778static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003779 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003780 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003781{
3782 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3783}
3784
Andreas Färber05390242012-02-25 03:37:53 +01003785long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003786{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003787 struct target_signal_frame *frame;
3788 abi_ulong frame_addr;
3789 target_sigset_t target_set;
3790 sigset_t set;
3791 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003792
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003793 frame_addr = env->regs[R_SP];
3794 trace_user_do_sigreturn(env, frame_addr);
3795 /* Make sure the guest isn't playing games. */
3796 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
3797 goto badframe;
3798 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003799
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003800 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003801 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003802 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003803 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003804 }
3805 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003806 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003807
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003808 restore_sigcontext(&frame->sc, env);
3809 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01003810 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003811badframe:
3812 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003813}
3814
Andreas Färber05390242012-02-25 03:37:53 +01003815long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003816{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003817 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003818 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3819 return -TARGET_ENOSYS;
3820}
thsc3b5bc82007-12-02 06:31:25 +00003821
Jia Liud9627832012-07-20 15:50:52 +08003822#elif defined(TARGET_OPENRISC)
3823
3824struct target_sigcontext {
3825 struct target_pt_regs regs;
3826 abi_ulong oldmask;
3827 abi_ulong usp;
3828};
3829
3830struct target_ucontext {
3831 abi_ulong tuc_flags;
3832 abi_ulong tuc_link;
3833 target_stack_t tuc_stack;
3834 struct target_sigcontext tuc_mcontext;
3835 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3836};
3837
3838struct target_rt_sigframe {
3839 abi_ulong pinfo;
3840 uint64_t puc;
3841 struct target_siginfo info;
3842 struct target_sigcontext sc;
3843 struct target_ucontext uc;
3844 unsigned char retcode[16]; /* trampoline code */
3845};
3846
3847/* This is the asm-generic/ucontext.h version */
3848#if 0
3849static int restore_sigcontext(CPUOpenRISCState *regs,
3850 struct target_sigcontext *sc)
3851{
3852 unsigned int err = 0;
3853 unsigned long old_usp;
3854
3855 /* Alwys make any pending restarted system call return -EINTR */
3856 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3857
3858 /* restore the regs from &sc->regs (same as sc, since regs is first)
3859 * (sc is already checked for VERIFY_READ since the sigframe was
3860 * checked in sys_sigreturn previously)
3861 */
3862
3863 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3864 goto badframe;
3865 }
3866
3867 /* make sure the U-flag is set so user-mode cannot fool us */
3868
3869 regs->sr &= ~SR_SM;
3870
3871 /* restore the old USP as it was before we stacked the sc etc.
3872 * (we cannot just pop the sigcontext since we aligned the sp and
3873 * stuff after pushing it)
3874 */
3875
Riku Voipio1d8b5122014-04-23 10:26:05 +03003876 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003877 phx_signal("old_usp 0x%lx", old_usp);
3878
3879 __PHX__ REALLY /* ??? */
3880 wrusp(old_usp);
3881 regs->gpr[1] = old_usp;
3882
3883 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3884 * after this completes, but we don't use that mechanism. maybe we can
3885 * use it now ?
3886 */
3887
3888 return err;
3889
3890badframe:
3891 return 1;
3892}
3893#endif
3894
3895/* Set up a signal frame. */
3896
Riku Voipio41ecc722014-04-23 11:01:00 +03003897static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003898 CPUOpenRISCState *regs,
3899 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08003900{
Jia Liud9627832012-07-20 15:50:52 +08003901 unsigned long usp = regs->gpr[1];
3902
3903 /* copy the regs. they are first in sc so we can use sc directly */
3904
Riku Voipio1d8b5122014-04-23 10:26:05 +03003905 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08003906
3907 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3908 the signal handler. The frametype will be restored to its previous
3909 value in restore_sigcontext. */
3910 /*regs->frametype = CRIS_FRAME_NORMAL;*/
3911
3912 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003913 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03003914 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003915}
3916
3917static inline unsigned long align_sigframe(unsigned long sp)
3918{
3919 unsigned long i;
3920 i = sp & ~3UL;
3921 return i;
3922}
3923
3924static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3925 CPUOpenRISCState *regs,
3926 size_t frame_size)
3927{
3928 unsigned long sp = regs->gpr[1];
3929 int onsigstack = on_sig_stack(sp);
3930
3931 /* redzone */
3932 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03003933 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08003934 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3935 }
3936
3937 sp = align_sigframe(sp - frame_size);
3938
3939 /*
3940 * If we are on the alternate signal stack and would overflow it, don't.
3941 * Return an always-bogus address instead so we will die with SIGSEGV.
3942 */
3943
3944 if (onsigstack && !likely(on_sig_stack(sp))) {
3945 return -1L;
3946 }
3947
3948 return sp;
3949}
3950
Jia Liud9627832012-07-20 15:50:52 +08003951static void setup_rt_frame(int sig, struct target_sigaction *ka,
3952 target_siginfo_t *info,
3953 target_sigset_t *set, CPUOpenRISCState *env)
3954{
3955 int err = 0;
3956 abi_ulong frame_addr;
3957 unsigned long return_ip;
3958 struct target_rt_sigframe *frame;
3959 abi_ulong info_addr, uc_addr;
3960
Jia Liud9627832012-07-20 15:50:52 +08003961 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003962 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08003963 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3964 goto give_sigsegv;
3965 }
3966
3967 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003968 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08003969 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003970 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08003971
3972 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00003973 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08003974 }
3975
3976 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03003977 __put_user(0, &frame->uc.tuc_flags);
3978 __put_user(0, &frame->uc.tuc_link);
3979 __put_user(target_sigaltstack_used.ss_sp,
3980 &frame->uc.tuc_stack.ss_sp);
3981 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
3982 __put_user(target_sigaltstack_used.ss_size,
3983 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03003984 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08003985
3986 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
3987
Jia Liud9627832012-07-20 15:50:52 +08003988 /* trampoline - the desired return ip is the retcode itself */
3989 return_ip = (unsigned long)&frame->retcode;
3990 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003991 __put_user(0xa960, (short *)(frame->retcode + 0));
3992 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
3993 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
3994 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08003995
3996 if (err) {
3997 goto give_sigsegv;
3998 }
3999
4000 /* TODO what is the current->exec_domain stuff and invmap ? */
4001
4002 /* Set up registers for signal handler */
4003 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
4004 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
4005 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
4006 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
4007 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
4008
4009 /* actually move the usp to reflect the stacked frame */
4010 env->gpr[1] = (unsigned long)frame;
4011
4012 return;
4013
4014give_sigsegv:
4015 unlock_user_struct(frame, frame_addr, 1);
4016 if (sig == TARGET_SIGSEGV) {
4017 ka->_sa_handler = TARGET_SIG_DFL;
4018 }
4019 force_sig(TARGET_SIGSEGV);
4020}
4021
4022long do_sigreturn(CPUOpenRISCState *env)
4023{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004024 trace_user_do_sigreturn(env, 0);
4025 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004026 return -TARGET_ENOSYS;
4027}
4028
4029long do_rt_sigreturn(CPUOpenRISCState *env)
4030{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004031 trace_user_do_rt_sigreturn(env, 0);
4032 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004033 return -TARGET_ENOSYS;
4034}
4035/* TARGET_OPENRISC */
4036
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004037#elif defined(TARGET_S390X)
4038
4039#define __NUM_GPRS 16
4040#define __NUM_FPRS 16
4041#define __NUM_ACRS 16
4042
4043#define S390_SYSCALL_SIZE 2
4044#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4045
4046#define _SIGCONTEXT_NSIG 64
4047#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4048#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4049#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4050#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4051#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4052
4053typedef struct {
4054 target_psw_t psw;
4055 target_ulong gprs[__NUM_GPRS];
4056 unsigned int acrs[__NUM_ACRS];
4057} target_s390_regs_common;
4058
4059typedef struct {
4060 unsigned int fpc;
4061 double fprs[__NUM_FPRS];
4062} target_s390_fp_regs;
4063
4064typedef struct {
4065 target_s390_regs_common regs;
4066 target_s390_fp_regs fpregs;
4067} target_sigregs;
4068
4069struct target_sigcontext {
4070 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4071 target_sigregs *sregs;
4072};
4073
4074typedef struct {
4075 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4076 struct target_sigcontext sc;
4077 target_sigregs sregs;
4078 int signo;
4079 uint8_t retcode[S390_SYSCALL_SIZE];
4080} sigframe;
4081
4082struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004083 target_ulong tuc_flags;
4084 struct target_ucontext *tuc_link;
4085 target_stack_t tuc_stack;
4086 target_sigregs tuc_mcontext;
4087 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004088};
4089
4090typedef struct {
4091 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4092 uint8_t retcode[S390_SYSCALL_SIZE];
4093 struct target_siginfo info;
4094 struct target_ucontext uc;
4095} rt_sigframe;
4096
4097static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004098get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004099{
4100 abi_ulong sp;
4101
4102 /* Default to using normal stack */
4103 sp = env->regs[15];
4104
4105 /* This is the X/Open sanctioned signal stack switching. */
4106 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4107 if (!sas_ss_flags(sp)) {
4108 sp = target_sigaltstack_used.ss_sp +
4109 target_sigaltstack_used.ss_size;
4110 }
4111 }
4112
4113 /* This is the legacy signal stack switching. */
4114 else if (/* FIXME !user_mode(regs) */ 0 &&
4115 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4116 ka->sa_restorer) {
4117 sp = (abi_ulong) ka->sa_restorer;
4118 }
4119
4120 return (sp - frame_size) & -8ul;
4121}
4122
Andreas Färber05390242012-02-25 03:37:53 +01004123static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004124{
4125 int i;
4126 //save_access_regs(current->thread.acrs); FIXME
4127
4128 /* Copy a 'clean' PSW mask to the user to avoid leaking
4129 information about whether PER is currently on. */
4130 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4131 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4132 for (i = 0; i < 16; i++) {
4133 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4134 }
4135 for (i = 0; i < 16; i++) {
4136 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4137 }
4138 /*
4139 * We have to store the fp registers to current->thread.fp_regs
4140 * to merge them with the emulated registers.
4141 */
4142 //save_fp_regs(&current->thread.fp_regs); FIXME
4143 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004144 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004145 }
4146}
4147
4148static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004149 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004150{
4151 sigframe *frame;
4152 abi_ulong frame_addr;
4153
4154 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004155 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004156 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004157 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004158 }
4159
Riku Voipio0188fad2014-04-23 13:34:15 +03004160 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004161
4162 save_sigregs(env, &frame->sregs);
4163
4164 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4165 (abi_ulong *)&frame->sc.sregs);
4166
4167 /* Set up to return from userspace. If provided, use a stub
4168 already in userspace. */
4169 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004170 env->regs[14] = (unsigned long)
4171 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004172 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004173 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4174 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004175 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4176 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004177 }
4178
4179 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004180 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004181
4182 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004183 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004184 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4185
4186 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004187 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004188
4189 /* We forgot to include these in the sigcontext.
4190 To avoid breaking binary compatibility, they are passed as args. */
4191 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4192 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4193
4194 /* Place signal number on stack to allow backtrace from handler. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004195 __put_user(env->regs[2], (int *) &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004196 unlock_user_struct(frame, frame_addr, 1);
4197 return;
4198
4199give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004200 force_sig(TARGET_SIGSEGV);
4201}
4202
4203static void setup_rt_frame(int sig, struct target_sigaction *ka,
4204 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004205 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004206{
4207 int i;
4208 rt_sigframe *frame;
4209 abi_ulong frame_addr;
4210
4211 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004212 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004213 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4214 goto give_sigsegv;
4215 }
4216
Peter Maydellf6c7a052015-01-08 12:19:48 +00004217 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004218
4219 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004220 __put_user(0, &frame->uc.tuc_flags);
4221 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4222 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004223 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004224 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004225 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4226 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004227 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4228 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004229 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004230 }
4231
4232 /* Set up to return from userspace. If provided, use a stub
4233 already in userspace. */
4234 if (ka->sa_flags & TARGET_SA_RESTORER) {
4235 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4236 } else {
4237 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004238 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4239 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004240 }
4241
4242 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004243 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004244
4245 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004246 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004247 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4248
4249 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004250 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4251 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004252 return;
4253
4254give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004255 force_sig(TARGET_SIGSEGV);
4256}
4257
4258static int
Andreas Färber05390242012-02-25 03:37:53 +01004259restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004260{
4261 int err = 0;
4262 int i;
4263
4264 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004265 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004266 }
4267
Riku Voipio1d8b5122014-04-23 10:26:05 +03004268 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004269 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4270 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004271 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004272 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4273
4274 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004275 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004276 }
4277 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004278 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004279 }
4280
4281 return err;
4282}
4283
Andreas Färber05390242012-02-25 03:37:53 +01004284long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004285{
4286 sigframe *frame;
4287 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004288 target_sigset_t target_set;
4289 sigset_t set;
4290
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004291 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004292 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4293 goto badframe;
4294 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004295 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004296
4297 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004298 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004299
4300 if (restore_sigregs(env, &frame->sregs)) {
4301 goto badframe;
4302 }
4303
4304 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004305 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004306
4307badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004308 force_sig(TARGET_SIGSEGV);
4309 return 0;
4310}
4311
Andreas Färber05390242012-02-25 03:37:53 +01004312long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004313{
4314 rt_sigframe *frame;
4315 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004316 sigset_t set;
4317
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004318 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004319 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4320 goto badframe;
4321 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004322 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004323
Peter Maydell9eede5b2016-05-27 15:51:46 +01004324 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004325
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004326 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004327 goto badframe;
4328 }
4329
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004330 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004331 get_sp_from_cpustate(env)) == -EFAULT) {
4332 goto badframe;
4333 }
4334 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004335 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004336
4337badframe:
4338 unlock_user_struct(frame, frame_addr, 0);
4339 force_sig(TARGET_SIGSEGV);
4340 return 0;
4341}
4342
Tom Musta61e75fe2014-06-30 08:13:38 -05004343#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004344
4345/* Size of dummy stack frame allocated when calling signal handler.
4346 See arch/powerpc/include/asm/ptrace.h. */
4347#if defined(TARGET_PPC64)
4348#define SIGNAL_FRAMESIZE 128
4349#else
4350#define SIGNAL_FRAMESIZE 64
4351#endif
4352
Tom Musta61e75fe2014-06-30 08:13:38 -05004353/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4354 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4355struct target_mcontext {
4356 target_ulong mc_gregs[48];
4357 /* Includes fpscr. */
4358 uint64_t mc_fregs[33];
4359 target_ulong mc_pad[2];
4360 /* We need to handle Altivec and SPE at the same time, which no
4361 kernel needs to do. Fortunately, the kernel defines this bit to
4362 be Altivec-register-large all the time, rather than trying to
4363 twiddle it based on the specific platform. */
4364 union {
4365 /* SPE vector registers. One extra for SPEFSCR. */
4366 uint32_t spe[33];
4367 /* Altivec vector registers. The packing of VSCR and VRSAVE
4368 varies depending on whether we're PPC64 or not: PPC64 splits
4369 them apart; PPC32 stuffs them together. */
4370#if defined(TARGET_PPC64)
4371#define QEMU_NVRREG 34
4372#else
4373#define QEMU_NVRREG 33
4374#endif
4375 ppc_avr_t altivec[QEMU_NVRREG];
4376#undef QEMU_NVRREG
4377 } mc_vregs __attribute__((__aligned__(16)));
4378};
4379
Nathan Froydbcd49332009-05-12 19:13:18 -07004380/* See arch/powerpc/include/asm/sigcontext.h. */
4381struct target_sigcontext {
4382 target_ulong _unused[4];
4383 int32_t signal;
4384#if defined(TARGET_PPC64)
4385 int32_t pad0;
4386#endif
4387 target_ulong handler;
4388 target_ulong oldmask;
4389 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05004390#if defined(TARGET_PPC64)
4391 struct target_mcontext mcontext;
4392#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004393};
4394
4395/* Indices for target_mcontext.mc_gregs, below.
4396 See arch/powerpc/include/asm/ptrace.h for details. */
4397enum {
4398 TARGET_PT_R0 = 0,
4399 TARGET_PT_R1 = 1,
4400 TARGET_PT_R2 = 2,
4401 TARGET_PT_R3 = 3,
4402 TARGET_PT_R4 = 4,
4403 TARGET_PT_R5 = 5,
4404 TARGET_PT_R6 = 6,
4405 TARGET_PT_R7 = 7,
4406 TARGET_PT_R8 = 8,
4407 TARGET_PT_R9 = 9,
4408 TARGET_PT_R10 = 10,
4409 TARGET_PT_R11 = 11,
4410 TARGET_PT_R12 = 12,
4411 TARGET_PT_R13 = 13,
4412 TARGET_PT_R14 = 14,
4413 TARGET_PT_R15 = 15,
4414 TARGET_PT_R16 = 16,
4415 TARGET_PT_R17 = 17,
4416 TARGET_PT_R18 = 18,
4417 TARGET_PT_R19 = 19,
4418 TARGET_PT_R20 = 20,
4419 TARGET_PT_R21 = 21,
4420 TARGET_PT_R22 = 22,
4421 TARGET_PT_R23 = 23,
4422 TARGET_PT_R24 = 24,
4423 TARGET_PT_R25 = 25,
4424 TARGET_PT_R26 = 26,
4425 TARGET_PT_R27 = 27,
4426 TARGET_PT_R28 = 28,
4427 TARGET_PT_R29 = 29,
4428 TARGET_PT_R30 = 30,
4429 TARGET_PT_R31 = 31,
4430 TARGET_PT_NIP = 32,
4431 TARGET_PT_MSR = 33,
4432 TARGET_PT_ORIG_R3 = 34,
4433 TARGET_PT_CTR = 35,
4434 TARGET_PT_LNK = 36,
4435 TARGET_PT_XER = 37,
4436 TARGET_PT_CCR = 38,
4437 /* Yes, there are two registers with #39. One is 64-bit only. */
4438 TARGET_PT_MQ = 39,
4439 TARGET_PT_SOFTE = 39,
4440 TARGET_PT_TRAP = 40,
4441 TARGET_PT_DAR = 41,
4442 TARGET_PT_DSISR = 42,
4443 TARGET_PT_RESULT = 43,
4444 TARGET_PT_REGS_COUNT = 44
4445};
4446
Nathan Froydbcd49332009-05-12 19:13:18 -07004447
4448struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004449 target_ulong tuc_flags;
4450 target_ulong tuc_link; /* struct ucontext __user * */
4451 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07004452#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02004453 int32_t tuc_pad[7];
4454 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07004455 points to uc_mcontext field */
4456#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02004457 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07004458#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05004459 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05004460 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004461#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02004462 int32_t tuc_maskext[30];
4463 int32_t tuc_pad2[3];
4464 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004465#endif
4466};
4467
4468/* See arch/powerpc/kernel/signal_32.c. */
4469struct target_sigframe {
4470 struct target_sigcontext sctx;
4471 struct target_mcontext mctx;
4472 int32_t abigap[56];
4473};
4474
Tom Musta61e75fe2014-06-30 08:13:38 -05004475#if defined(TARGET_PPC64)
4476
4477#define TARGET_TRAMP_SIZE 6
4478
4479struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004480 /* sys_rt_sigreturn requires the ucontext be the first field */
4481 struct target_ucontext uc;
4482 target_ulong _unused[2];
4483 uint32_t trampoline[TARGET_TRAMP_SIZE];
4484 target_ulong pinfo; /* struct siginfo __user * */
4485 target_ulong puc; /* void __user * */
4486 struct target_siginfo info;
4487 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
4488 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05004489} __attribute__((aligned(16)));
4490
4491#else
4492
Nathan Froydbcd49332009-05-12 19:13:18 -07004493struct target_rt_sigframe {
4494 struct target_siginfo info;
4495 struct target_ucontext uc;
4496 int32_t abigap[56];
4497};
4498
Tom Musta61e75fe2014-06-30 08:13:38 -05004499#endif
4500
Tom Musta8d6ab332014-06-30 08:13:39 -05004501#if defined(TARGET_PPC64)
4502
4503struct target_func_ptr {
4504 target_ulong entry;
4505 target_ulong toc;
4506};
4507
4508#endif
4509
Nathan Froydbcd49332009-05-12 19:13:18 -07004510/* We use the mc_pad field for the signal return trampoline. */
4511#define tramp mc_pad
4512
4513/* See arch/powerpc/kernel/signal.c. */
4514static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004515 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07004516 int frame_size)
4517{
4518 target_ulong oldsp, newsp;
4519
4520 oldsp = env->gpr[1];
4521
4522 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004523 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07004524 oldsp = (target_sigaltstack_used.ss_sp
4525 + target_sigaltstack_used.ss_size);
4526 }
4527
4528 newsp = (oldsp - frame_size) & ~0xFUL;
4529
4530 return newsp;
4531}
4532
Tom Musta76781082014-06-30 08:13:37 -05004533static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07004534{
4535 target_ulong msr = env->msr;
4536 int i;
4537 target_ulong ccr = 0;
4538
4539 /* In general, the kernel attempts to be intelligent about what it
4540 needs to save for Altivec/FP/SPE registers. We don't care that
4541 much, so we just go ahead and save everything. */
4542
4543 /* Save general registers. */
4544 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004545 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004546 }
Riku Voipioc650c002014-04-23 13:53:45 +03004547 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4548 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4549 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4550 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004551
4552 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4553 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4554 }
Riku Voipioc650c002014-04-23 13:53:45 +03004555 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004556
4557 /* Save Altivec registers if necessary. */
4558 if (env->insns_flags & PPC_ALTIVEC) {
4559 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004560 ppc_avr_t *avr = &env->avr[i];
4561 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004562
Riku Voipioc650c002014-04-23 13:53:45 +03004563 __put_user(avr->u64[0], &vreg->u64[0]);
4564 __put_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004565 }
4566 /* Set MSR_VR in the saved MSR value to indicate that
4567 frame->mc_vregs contains valid data. */
4568 msr |= MSR_VR;
Riku Voipioc650c002014-04-23 13:53:45 +03004569 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4570 &frame->mc_vregs.altivec[32].u32[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004571 }
4572
4573 /* Save floating point registers. */
4574 if (env->insns_flags & PPC_FLOAT) {
4575 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004576 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004577 }
Riku Voipioc650c002014-04-23 13:53:45 +03004578 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004579 }
4580
4581 /* Save SPE registers. The kernel only saves the high half. */
4582 if (env->insns_flags & PPC_SPE) {
4583#if defined(TARGET_PPC64)
4584 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004585 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004586 }
4587#else
4588 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004589 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004590 }
4591#endif
4592 /* Set MSR_SPE in the saved MSR value to indicate that
4593 frame->mc_vregs contains valid data. */
4594 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03004595 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004596 }
4597
4598 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004599 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05004600}
Nathan Froydbcd49332009-05-12 19:13:18 -07004601
Tom Musta76781082014-06-30 08:13:37 -05004602static void encode_trampoline(int sigret, uint32_t *tramp)
4603{
Nathan Froydbcd49332009-05-12 19:13:18 -07004604 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4605 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05004606 __put_user(0x38000000 | sigret, &tramp[0]);
4607 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004608 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004609}
4610
Riku Voipioc650c002014-04-23 13:53:45 +03004611static void restore_user_regs(CPUPPCState *env,
4612 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004613{
4614 target_ulong save_r2 = 0;
4615 target_ulong msr;
4616 target_ulong ccr;
4617
4618 int i;
4619
4620 if (!sig) {
4621 save_r2 = env->gpr[2];
4622 }
4623
4624 /* Restore general registers. */
4625 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004626 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004627 }
Riku Voipioc650c002014-04-23 13:53:45 +03004628 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4629 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4630 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4631 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4632 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004633
4634 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4635 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4636 }
4637
4638 if (!sig) {
4639 env->gpr[2] = save_r2;
4640 }
4641 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004642 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004643
4644 /* If doing signal return, restore the previous little-endian mode. */
4645 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004646 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07004647
4648 /* Restore Altivec registers if necessary. */
4649 if (env->insns_flags & PPC_ALTIVEC) {
4650 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004651 ppc_avr_t *avr = &env->avr[i];
4652 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004653
Riku Voipioc650c002014-04-23 13:53:45 +03004654 __get_user(avr->u64[0], &vreg->u64[0]);
4655 __get_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004656 }
4657 /* Set MSR_VEC in the saved MSR value to indicate that
4658 frame->mc_vregs contains valid data. */
Riku Voipioc650c002014-04-23 13:53:45 +03004659 __get_user(env->spr[SPR_VRSAVE],
4660 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
Nathan Froydbcd49332009-05-12 19:13:18 -07004661 }
4662
4663 /* Restore floating point registers. */
4664 if (env->insns_flags & PPC_FLOAT) {
4665 uint64_t fpscr;
4666 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004667 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004668 }
Riku Voipioc650c002014-04-23 13:53:45 +03004669 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004670 env->fpscr = (uint32_t) fpscr;
4671 }
4672
4673 /* Save SPE registers. The kernel only saves the high half. */
4674 if (env->insns_flags & PPC_SPE) {
4675#if defined(TARGET_PPC64)
4676 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4677 uint32_t hi;
4678
Riku Voipioc650c002014-04-23 13:53:45 +03004679 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004680 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4681 }
4682#else
4683 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004684 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004685 }
4686#endif
Riku Voipioc650c002014-04-23 13:53:45 +03004687 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004688 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004689}
4690
4691static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004692 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004693{
4694 struct target_sigframe *frame;
4695 struct target_sigcontext *sc;
4696 target_ulong frame_addr, newsp;
4697 int err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004698#if defined(TARGET_PPC64)
4699 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4700#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004701
4702 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004703 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004704 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4705 goto sigsegv;
4706 sc = &frame->sctx;
4707
Riku Voipio1d8b5122014-04-23 10:26:05 +03004708 __put_user(ka->_sa_handler, &sc->handler);
4709 __put_user(set->sig[0], &sc->oldmask);
Tom Musta61e75fe2014-06-30 08:13:38 -05004710#if TARGET_ABI_BITS == 64
Riku Voipio1d8b5122014-04-23 10:26:05 +03004711 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004712#else
Riku Voipio1d8b5122014-04-23 10:26:05 +03004713 __put_user(set->sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004714#endif
Riku Voipio1d8b5122014-04-23 10:26:05 +03004715 __put_user(h2g(&frame->mctx), &sc->regs);
4716 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07004717
4718 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05004719 save_user_regs(env, &frame->mctx);
4720
4721 /* Construct the trampoline code on the stack. */
4722 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07004723
4724 /* The kernel checks for the presence of a VDSO here. We don't
4725 emulate a vdso, so use a sigreturn system call. */
4726 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4727
4728 /* Turn off all fp exceptions. */
4729 env->fpscr = 0;
4730
4731 /* Create a stack frame for the caller of the handler. */
4732 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00004733 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004734
4735 if (err)
4736 goto sigsegv;
4737
4738 /* Set up registers for signal handler. */
4739 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004740 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00004741 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05004742
4743#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004744 if (get_ppc64_abi(image) < 2) {
4745 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4746 struct target_func_ptr *handler =
4747 (struct target_func_ptr *)g2h(ka->_sa_handler);
4748 env->nip = tswapl(handler->entry);
4749 env->gpr[2] = tswapl(handler->toc);
4750 } else {
4751 /* ELFv2 PPC64 function pointers are entry points, but R12
4752 * must also be set */
4753 env->nip = tswapl((target_ulong) ka->_sa_handler);
4754 env->gpr[12] = env->nip;
4755 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004756#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004757 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004758#endif
4759
Nathan Froydbcd49332009-05-12 19:13:18 -07004760 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004761 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07004762
4763 unlock_user_struct(frame, frame_addr, 1);
4764 return;
4765
4766sigsegv:
4767 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004768 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004769}
4770
4771static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004772 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004773 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004774{
4775 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05004776 uint32_t *trampptr = 0;
4777 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004778 target_ulong rt_sf_addr, newsp = 0;
4779 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004780#if defined(TARGET_PPC64)
4781 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4782#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004783
4784 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4785 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4786 goto sigsegv;
4787
Peter Maydellf6c7a052015-01-08 12:19:48 +00004788 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07004789
Riku Voipio1d8b5122014-04-23 10:26:05 +03004790 __put_user(0, &rt_sf->uc.tuc_flags);
4791 __put_user(0, &rt_sf->uc.tuc_link);
4792 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4793 &rt_sf->uc.tuc_stack.ss_sp);
4794 __put_user(sas_ss_flags(env->gpr[1]),
4795 &rt_sf->uc.tuc_stack.ss_flags);
4796 __put_user(target_sigaltstack_used.ss_size,
4797 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05004798#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03004799 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4800 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05004801#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004802 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004803 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004804 }
4805
Tom Musta61e75fe2014-06-30 08:13:38 -05004806#if defined(TARGET_PPC64)
4807 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
4808 trampptr = &rt_sf->trampoline[0];
4809#else
4810 mctx = &rt_sf->uc.tuc_mcontext;
4811 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
4812#endif
4813
4814 save_user_regs(env, mctx);
4815 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004816
4817 /* The kernel checks for the presence of a VDSO here. We don't
4818 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05004819 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004820
4821 /* Turn off all fp exceptions. */
4822 env->fpscr = 0;
4823
4824 /* Create a stack frame for the caller of the handler. */
4825 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05004826 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004827
4828 if (err)
4829 goto sigsegv;
4830
4831 /* Set up registers for signal handler. */
4832 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004833 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07004834 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4835 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4836 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05004837
4838#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004839 if (get_ppc64_abi(image) < 2) {
4840 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4841 struct target_func_ptr *handler =
4842 (struct target_func_ptr *)g2h(ka->_sa_handler);
4843 env->nip = tswapl(handler->entry);
4844 env->gpr[2] = tswapl(handler->toc);
4845 } else {
4846 /* ELFv2 PPC64 function pointers are entry points, but R12
4847 * must also be set */
4848 env->nip = tswapl((target_ulong) ka->_sa_handler);
4849 env->gpr[12] = env->nip;
4850 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004851#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004852 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004853#endif
4854
Nathan Froydbcd49332009-05-12 19:13:18 -07004855 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004856 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07004857
4858 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4859 return;
4860
4861sigsegv:
4862 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004863 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004864
4865}
4866
Andreas Färber05390242012-02-25 03:37:53 +01004867long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004868{
4869 struct target_sigcontext *sc = NULL;
4870 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01004871 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07004872 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004873 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004874
4875 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4876 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4877 goto sigsegv;
4878
4879#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05004880 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07004881#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03004882 __get_user(set.sig[0], &sc->oldmask);
4883 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004884#endif
4885 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004886 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07004887
Riku Voipiof5f601a2014-04-23 13:00:17 +03004888 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004889 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4890 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03004891 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07004892
4893 unlock_user_struct(sr, sr_addr, 1);
4894 unlock_user_struct(sc, sc_addr, 1);
4895 return -TARGET_QEMU_ESIGRETURN;
4896
4897sigsegv:
4898 unlock_user_struct(sr, sr_addr, 1);
4899 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004900 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004901 return 0;
4902}
4903
4904/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01004905static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004906{
4907 struct target_mcontext *mcp;
4908 target_ulong mcp_addr;
4909 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004910 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004911
Aurelien Jarno60e99242010-03-29 02:12:51 +02004912 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07004913 sizeof (set)))
4914 return 1;
4915
Tom Musta19774ec2014-06-30 08:13:40 -05004916#if defined(TARGET_PPC64)
4917 mcp_addr = h2g(ucp) +
4918 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
4919#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03004920 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05004921#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004922
4923 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4924 return 1;
4925
4926 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004927 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03004928 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07004929
4930 unlock_user_struct(mcp, mcp_addr, 1);
4931 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004932}
4933
Andreas Färber05390242012-02-25 03:37:53 +01004934long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004935{
4936 struct target_rt_sigframe *rt_sf = NULL;
4937 target_ulong rt_sf_addr;
4938
4939 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4940 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4941 goto sigsegv;
4942
4943 if (do_setcontext(&rt_sf->uc, env, 1))
4944 goto sigsegv;
4945
4946 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02004947 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07004948 0, env->gpr[1]);
4949
4950 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4951 return -TARGET_QEMU_ESIGRETURN;
4952
4953sigsegv:
4954 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004955 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004956 return 0;
4957}
4958
Laurent Vivier492a8742009-08-03 16:12:17 +02004959#elif defined(TARGET_M68K)
4960
4961struct target_sigcontext {
4962 abi_ulong sc_mask;
4963 abi_ulong sc_usp;
4964 abi_ulong sc_d0;
4965 abi_ulong sc_d1;
4966 abi_ulong sc_a0;
4967 abi_ulong sc_a1;
4968 unsigned short sc_sr;
4969 abi_ulong sc_pc;
4970};
4971
4972struct target_sigframe
4973{
4974 abi_ulong pretcode;
4975 int sig;
4976 int code;
4977 abi_ulong psc;
4978 char retcode[8];
4979 abi_ulong extramask[TARGET_NSIG_WORDS-1];
4980 struct target_sigcontext sc;
4981};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004982
Anthony Liguoric227f092009-10-01 16:12:16 -05004983typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004984#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05004985typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02004986
4987typedef struct target_fpregset {
4988 int f_fpcntl[3];
4989 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05004990} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004991
4992struct target_mcontext {
4993 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05004994 target_gregset_t gregs;
4995 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02004996};
4997
4998#define TARGET_MCONTEXT_VERSION 2
4999
5000struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005001 abi_ulong tuc_flags;
5002 abi_ulong tuc_link;
5003 target_stack_t tuc_stack;
5004 struct target_mcontext tuc_mcontext;
5005 abi_long tuc_filler[80];
5006 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005007};
5008
5009struct target_rt_sigframe
5010{
5011 abi_ulong pretcode;
5012 int sig;
5013 abi_ulong pinfo;
5014 abi_ulong puc;
5015 char retcode[8];
5016 struct target_siginfo info;
5017 struct target_ucontext uc;
5018};
Laurent Vivier492a8742009-08-03 16:12:17 +02005019
Riku Voipio41ecc722014-04-23 11:01:00 +03005020static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005021 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005022{
Riku Voipio1d8b5122014-04-23 10:26:05 +03005023 __put_user(mask, &sc->sc_mask);
5024 __put_user(env->aregs[7], &sc->sc_usp);
5025 __put_user(env->dregs[0], &sc->sc_d0);
5026 __put_user(env->dregs[1], &sc->sc_d1);
5027 __put_user(env->aregs[0], &sc->sc_a0);
5028 __put_user(env->aregs[1], &sc->sc_a1);
5029 __put_user(env->sr, &sc->sc_sr);
5030 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005031}
5032
Riku Voipio016d2e12014-04-23 11:19:48 +03005033static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005034restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005035{
Laurent Vivier492a8742009-08-03 16:12:17 +02005036 int temp;
5037
Riku Voipio1d8b5122014-04-23 10:26:05 +03005038 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005039 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005040 __get_user(env->dregs[1], &sc->sc_d1);
5041 __get_user(env->aregs[0], &sc->sc_a0);
5042 __get_user(env->aregs[1], &sc->sc_a1);
5043 __get_user(env->pc, &sc->sc_pc);
5044 __get_user(temp, &sc->sc_sr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005045 env->sr = (env->sr & 0xff00) | (temp & 0xff);
Laurent Vivier492a8742009-08-03 16:12:17 +02005046}
5047
5048/*
5049 * Determine which stack to use..
5050 */
5051static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005052get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5053 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005054{
5055 unsigned long sp;
5056
5057 sp = regs->aregs[7];
5058
5059 /* This is the X/Open sanctioned signal stack switching. */
5060 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5061 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5062 }
5063
5064 return ((sp - frame_size) & -8UL);
5065}
5066
5067static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005068 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005069{
5070 struct target_sigframe *frame;
5071 abi_ulong frame_addr;
5072 abi_ulong retcode_addr;
5073 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005074 int i;
5075
5076 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005077 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005078 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5079 goto give_sigsegv;
5080 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005081
Riku Voipio1d8b5122014-04-23 10:26:05 +03005082 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005083
5084 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005085 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005086
Riku Voipio41ecc722014-04-23 11:01:00 +03005087 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005088
5089 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005090 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005091 }
5092
5093 /* Set up to return from userspace. */
5094
5095 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005096 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005097
5098 /* moveq #,d0; trap #0 */
5099
Riku Voipio1d8b5122014-04-23 10:26:05 +03005100 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005101 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005102
Laurent Vivier492a8742009-08-03 16:12:17 +02005103 /* Set up to return from userspace */
5104
5105 env->aregs[7] = frame_addr;
5106 env->pc = ka->_sa_handler;
5107
5108 unlock_user_struct(frame, frame_addr, 1);
5109 return;
5110
5111give_sigsegv:
Riku Voipio66393fb2009-12-04 15:16:32 +02005112 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005113}
5114
Laurent Vivier71811552009-08-03 16:12:18 +02005115static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005116 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005117{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005118 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005119
Riku Voipio1d8b5122014-04-23 10:26:05 +03005120 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5121 __put_user(env->dregs[0], &gregs[0]);
5122 __put_user(env->dregs[1], &gregs[1]);
5123 __put_user(env->dregs[2], &gregs[2]);
5124 __put_user(env->dregs[3], &gregs[3]);
5125 __put_user(env->dregs[4], &gregs[4]);
5126 __put_user(env->dregs[5], &gregs[5]);
5127 __put_user(env->dregs[6], &gregs[6]);
5128 __put_user(env->dregs[7], &gregs[7]);
5129 __put_user(env->aregs[0], &gregs[8]);
5130 __put_user(env->aregs[1], &gregs[9]);
5131 __put_user(env->aregs[2], &gregs[10]);
5132 __put_user(env->aregs[3], &gregs[11]);
5133 __put_user(env->aregs[4], &gregs[12]);
5134 __put_user(env->aregs[5], &gregs[13]);
5135 __put_user(env->aregs[6], &gregs[14]);
5136 __put_user(env->aregs[7], &gregs[15]);
5137 __put_user(env->pc, &gregs[16]);
5138 __put_user(env->sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005139
Riku Voipio1d8b5122014-04-23 10:26:05 +03005140 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005141}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005142
Andreas Färber05390242012-02-25 03:37:53 +01005143static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005144 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02005145{
5146 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005147 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005148
Riku Voipio1d8b5122014-04-23 10:26:05 +03005149 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005150 if (temp != TARGET_MCONTEXT_VERSION)
5151 goto badframe;
5152
5153 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005154 __get_user(env->dregs[0], &gregs[0]);
5155 __get_user(env->dregs[1], &gregs[1]);
5156 __get_user(env->dregs[2], &gregs[2]);
5157 __get_user(env->dregs[3], &gregs[3]);
5158 __get_user(env->dregs[4], &gregs[4]);
5159 __get_user(env->dregs[5], &gregs[5]);
5160 __get_user(env->dregs[6], &gregs[6]);
5161 __get_user(env->dregs[7], &gregs[7]);
5162 __get_user(env->aregs[0], &gregs[8]);
5163 __get_user(env->aregs[1], &gregs[9]);
5164 __get_user(env->aregs[2], &gregs[10]);
5165 __get_user(env->aregs[3], &gregs[11]);
5166 __get_user(env->aregs[4], &gregs[12]);
5167 __get_user(env->aregs[5], &gregs[13]);
5168 __get_user(env->aregs[6], &gregs[14]);
5169 __get_user(env->aregs[7], &gregs[15]);
5170 __get_user(env->pc, &gregs[16]);
5171 __get_user(temp, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005172 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5173
Riku Voipio1d8b5122014-04-23 10:26:05 +03005174 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005175
5176badframe:
5177 return 1;
5178}
5179
Laurent Vivier492a8742009-08-03 16:12:17 +02005180static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005181 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005182 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005183{
Laurent Vivier71811552009-08-03 16:12:18 +02005184 struct target_rt_sigframe *frame;
5185 abi_ulong frame_addr;
5186 abi_ulong retcode_addr;
5187 abi_ulong info_addr;
5188 abi_ulong uc_addr;
5189 int err = 0;
5190 int i;
5191
5192 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005193 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005194 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5195 goto give_sigsegv;
5196 }
Laurent Vivier71811552009-08-03 16:12:18 +02005197
Riku Voipio1d8b5122014-04-23 10:26:05 +03005198 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005199
5200 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005201 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005202
5203 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005204 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005205
Peter Maydellf6c7a052015-01-08 12:19:48 +00005206 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005207
5208 /* Create the ucontext */
5209
Riku Voipio1d8b5122014-04-23 10:26:05 +03005210 __put_user(0, &frame->uc.tuc_flags);
5211 __put_user(0, &frame->uc.tuc_link);
5212 __put_user(target_sigaltstack_used.ss_sp,
5213 &frame->uc.tuc_stack.ss_sp);
5214 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005215 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005216 __put_user(target_sigaltstack_used.ss_size,
5217 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005218 err |= target_rt_setup_ucontext(&frame->uc, env);
5219
5220 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005221 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02005222
5223 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005224 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005225 }
5226
5227 /* Set up to return from userspace. */
5228
5229 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005230 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005231
5232 /* moveq #,d0; notb d0; trap #0 */
5233
Riku Voipio1d8b5122014-04-23 10:26:05 +03005234 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005235 (uint32_t *)(frame->retcode + 0));
5236 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005237
5238 if (err)
5239 goto give_sigsegv;
5240
5241 /* Set up to return from userspace */
5242
5243 env->aregs[7] = frame_addr;
5244 env->pc = ka->_sa_handler;
5245
5246 unlock_user_struct(frame, frame_addr, 1);
5247 return;
5248
5249give_sigsegv:
5250 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005251 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005252}
5253
Andreas Färber05390242012-02-25 03:37:53 +01005254long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005255{
5256 struct target_sigframe *frame;
5257 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005258 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005259 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005260 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02005261
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005262 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005263 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5264 goto badframe;
5265
5266 /* set blocked signals */
5267
Riku Voipiof5f601a2014-04-23 13:00:17 +03005268 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005269
5270 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005271 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005272 }
5273
5274 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005275 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02005276
5277 /* restore registers */
5278
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005279 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005280
5281 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005282 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005283
5284badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005285 force_sig(TARGET_SIGSEGV);
5286 return 0;
5287}
5288
Andreas Färber05390242012-02-25 03:37:53 +01005289long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005290{
Laurent Vivier71811552009-08-03 16:12:18 +02005291 struct target_rt_sigframe *frame;
5292 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005293 target_sigset_t target_set;
Laurent Vivier71811552009-08-03 16:12:18 +02005294 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02005295
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005296 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02005297 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5298 goto badframe;
5299
5300 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005301 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02005302
5303 /* restore registers */
5304
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005305 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02005306 goto badframe;
5307
5308 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02005309 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02005310 0, get_sp_from_cpustate(env)) == -EFAULT)
5311 goto badframe;
5312
5313 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005314 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02005315
5316badframe:
5317 unlock_user_struct(frame, frame_addr, 0);
5318 force_sig(TARGET_SIGSEGV);
5319 return 0;
Laurent Vivier492a8742009-08-03 16:12:17 +02005320}
5321
Richard Henderson6049f4f2009-12-27 18:30:03 -08005322#elif defined(TARGET_ALPHA)
5323
5324struct target_sigcontext {
5325 abi_long sc_onstack;
5326 abi_long sc_mask;
5327 abi_long sc_pc;
5328 abi_long sc_ps;
5329 abi_long sc_regs[32];
5330 abi_long sc_ownedfp;
5331 abi_long sc_fpregs[32];
5332 abi_ulong sc_fpcr;
5333 abi_ulong sc_fp_control;
5334 abi_ulong sc_reserved1;
5335 abi_ulong sc_reserved2;
5336 abi_ulong sc_ssize;
5337 abi_ulong sc_sbase;
5338 abi_ulong sc_traparg_a0;
5339 abi_ulong sc_traparg_a1;
5340 abi_ulong sc_traparg_a2;
5341 abi_ulong sc_fp_trap_pc;
5342 abi_ulong sc_fp_trigger_sum;
5343 abi_ulong sc_fp_trigger_inst;
5344};
5345
5346struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005347 abi_ulong tuc_flags;
5348 abi_ulong tuc_link;
5349 abi_ulong tuc_osf_sigmask;
5350 target_stack_t tuc_stack;
5351 struct target_sigcontext tuc_mcontext;
5352 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005353};
5354
5355struct target_sigframe {
5356 struct target_sigcontext sc;
5357 unsigned int retcode[3];
5358};
5359
5360struct target_rt_sigframe {
5361 target_siginfo_t info;
5362 struct target_ucontext uc;
5363 unsigned int retcode[3];
5364};
5365
5366#define INSN_MOV_R30_R16 0x47fe0410
5367#define INSN_LDI_R0 0x201f0000
5368#define INSN_CALLSYS 0x00000083
5369
Riku Voipio41ecc722014-04-23 11:01:00 +03005370static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005371 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005372{
Riku Voipio41ecc722014-04-23 11:01:00 +03005373 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005374
Riku Voipio1d8b5122014-04-23 10:26:05 +03005375 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5376 __put_user(set->sig[0], &sc->sc_mask);
5377 __put_user(env->pc, &sc->sc_pc);
5378 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005379
5380 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005381 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005382 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005383 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005384
5385 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005386 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005387 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005388 __put_user(0, &sc->sc_fpregs[31]);
5389 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005390
Riku Voipio1d8b5122014-04-23 10:26:05 +03005391 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5392 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5393 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08005394}
5395
Riku Voipio016d2e12014-04-23 11:19:48 +03005396static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005397 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005398{
5399 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03005400 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005401
Riku Voipio1d8b5122014-04-23 10:26:05 +03005402 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005403
5404 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005405 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005406 }
5407 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005408 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005409 }
5410
Riku Voipio1d8b5122014-04-23 10:26:05 +03005411 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005412 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005413}
5414
5415static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01005416 CPUAlphaState *env,
5417 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005418{
5419 abi_ulong sp = env->ir[IR_SP];
5420
5421 /* This is the X/Open sanctioned signal stack switching. */
5422 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5423 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5424 }
5425 return (sp - framesize) & -32;
5426}
5427
5428static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005429 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005430{
5431 abi_ulong frame_addr, r26;
5432 struct target_sigframe *frame;
5433 int err = 0;
5434
5435 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005436 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005437 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5438 goto give_sigsegv;
5439 }
5440
Riku Voipio41ecc722014-04-23 11:01:00 +03005441 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005442
5443 if (ka->sa_restorer) {
5444 r26 = ka->sa_restorer;
5445 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005446 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5447 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5448 &frame->retcode[1]);
5449 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005450 /* imb() */
5451 r26 = frame_addr;
5452 }
5453
5454 unlock_user_struct(frame, frame_addr, 1);
5455
5456 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005457give_sigsegv:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005458 if (sig == TARGET_SIGSEGV) {
5459 ka->_sa_handler = TARGET_SIG_DFL;
5460 }
5461 force_sig(TARGET_SIGSEGV);
5462 }
5463
5464 env->ir[IR_RA] = r26;
5465 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5466 env->ir[IR_A0] = sig;
5467 env->ir[IR_A1] = 0;
5468 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5469 env->ir[IR_SP] = frame_addr;
5470}
5471
5472static void setup_rt_frame(int sig, struct target_sigaction *ka,
5473 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005474 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005475{
5476 abi_ulong frame_addr, r26;
5477 struct target_rt_sigframe *frame;
5478 int i, err = 0;
5479
5480 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005481 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005482 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5483 goto give_sigsegv;
5484 }
5485
Peter Maydellf6c7a052015-01-08 12:19:48 +00005486 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005487
Riku Voipio1d8b5122014-04-23 10:26:05 +03005488 __put_user(0, &frame->uc.tuc_flags);
5489 __put_user(0, &frame->uc.tuc_link);
5490 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5491 __put_user(target_sigaltstack_used.ss_sp,
5492 &frame->uc.tuc_stack.ss_sp);
5493 __put_user(sas_ss_flags(env->ir[IR_SP]),
5494 &frame->uc.tuc_stack.ss_flags);
5495 __put_user(target_sigaltstack_used.ss_size,
5496 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03005497 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005498 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005499 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005500 }
5501
5502 if (ka->sa_restorer) {
5503 r26 = ka->sa_restorer;
5504 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005505 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5506 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5507 &frame->retcode[1]);
5508 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005509 /* imb(); */
5510 r26 = frame_addr;
5511 }
5512
5513 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005514give_sigsegv:
5515 if (sig == TARGET_SIGSEGV) {
Richard Henderson6049f4f2009-12-27 18:30:03 -08005516 ka->_sa_handler = TARGET_SIG_DFL;
5517 }
5518 force_sig(TARGET_SIGSEGV);
5519 }
5520
5521 env->ir[IR_RA] = r26;
5522 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5523 env->ir[IR_A0] = sig;
5524 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5525 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5526 env->ir[IR_SP] = frame_addr;
5527}
5528
Andreas Färber05390242012-02-25 03:37:53 +01005529long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005530{
5531 struct target_sigcontext *sc;
5532 abi_ulong sc_addr = env->ir[IR_A0];
5533 target_sigset_t target_set;
5534 sigset_t set;
5535
5536 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5537 goto badframe;
5538 }
5539
5540 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03005541 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005542
5543 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005544 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005545
Riku Voipio016d2e12014-04-23 11:19:48 +03005546 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005547 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005548 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005549
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005550badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005551 force_sig(TARGET_SIGSEGV);
5552}
5553
Andreas Färber05390242012-02-25 03:37:53 +01005554long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005555{
5556 abi_ulong frame_addr = env->ir[IR_A0];
5557 struct target_rt_sigframe *frame;
5558 sigset_t set;
5559
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005560 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005561 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5562 goto badframe;
5563 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02005564 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005565 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005566
Riku Voipio016d2e12014-04-23 11:19:48 +03005567 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005568 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02005569 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08005570 0, env->ir[IR_SP]) == -EFAULT) {
5571 goto badframe;
5572 }
5573
5574 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005575 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005576
5577
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005578badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005579 unlock_user_struct(frame, frame_addr, 0);
5580 force_sig(TARGET_SIGSEGV);
5581}
5582
Chen Gangbf0f60a2015-09-27 08:10:18 +08005583#elif defined(TARGET_TILEGX)
5584
5585struct target_sigcontext {
5586 union {
5587 /* General-purpose registers. */
5588 abi_ulong gregs[56];
5589 struct {
5590 abi_ulong __gregs[53];
5591 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
5592 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
5593 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
5594 };
5595 };
5596 abi_ulong pc; /* Program counter. */
5597 abi_ulong ics; /* In Interrupt Critical Section? */
5598 abi_ulong faultnum; /* Fault number. */
5599 abi_ulong pad[5];
5600};
5601
5602struct target_ucontext {
5603 abi_ulong tuc_flags;
5604 abi_ulong tuc_link;
5605 target_stack_t tuc_stack;
5606 struct target_sigcontext tuc_mcontext;
5607 target_sigset_t tuc_sigmask; /* mask last for extensibility */
5608};
5609
5610struct target_rt_sigframe {
5611 unsigned char save_area[16]; /* caller save area */
5612 struct target_siginfo info;
5613 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08005614 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08005615};
5616
Chen Gangf1d9d102016-03-29 21:53:49 +08005617#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
5618#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
5619
5620
Chen Gangbf0f60a2015-09-27 08:10:18 +08005621static void setup_sigcontext(struct target_sigcontext *sc,
5622 CPUArchState *env, int signo)
5623{
5624 int i;
5625
5626 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5627 __put_user(env->regs[i], &sc->gregs[i]);
5628 }
5629
5630 __put_user(env->pc, &sc->pc);
5631 __put_user(0, &sc->ics);
5632 __put_user(signo, &sc->faultnum);
5633}
5634
5635static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
5636{
5637 int i;
5638
5639 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5640 __get_user(env->regs[i], &sc->gregs[i]);
5641 }
5642
5643 __get_user(env->pc, &sc->pc);
5644}
5645
5646static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
5647 size_t frame_size)
5648{
5649 unsigned long sp = env->regs[TILEGX_R_SP];
5650
5651 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
5652 return -1UL;
5653 }
5654
5655 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
5656 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5657 }
5658
5659 sp -= frame_size;
5660 sp &= -16UL;
5661 return sp;
5662}
5663
5664static void setup_rt_frame(int sig, struct target_sigaction *ka,
5665 target_siginfo_t *info,
5666 target_sigset_t *set, CPUArchState *env)
5667{
5668 abi_ulong frame_addr;
5669 struct target_rt_sigframe *frame;
5670 unsigned long restorer;
5671
5672 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005673 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005674 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5675 goto give_sigsegv;
5676 }
5677
5678 /* Always write at least the signal number for the stack backtracer. */
5679 if (ka->sa_flags & TARGET_SA_SIGINFO) {
5680 /* At sigreturn time, restore the callee-save registers too. */
5681 tswap_siginfo(&frame->info, info);
5682 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
5683 } else {
5684 __put_user(info->si_signo, &frame->info.si_signo);
5685 }
5686
5687 /* Create the ucontext. */
5688 __put_user(0, &frame->uc.tuc_flags);
5689 __put_user(0, &frame->uc.tuc_link);
5690 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
5691 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
5692 &frame->uc.tuc_stack.ss_flags);
5693 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5694 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
5695
Chen Gangbf0f60a2015-09-27 08:10:18 +08005696 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08005697 restorer = (unsigned long) ka->sa_restorer;
5698 } else {
5699 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
5700 __put_user(INSN_SWINT1, &frame->retcode[1]);
5701 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005702 }
5703 env->pc = (unsigned long) ka->_sa_handler;
5704 env->regs[TILEGX_R_SP] = (unsigned long) frame;
5705 env->regs[TILEGX_R_LR] = restorer;
5706 env->regs[0] = (unsigned long) sig;
5707 env->regs[1] = (unsigned long) &frame->info;
5708 env->regs[2] = (unsigned long) &frame->uc;
5709 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
5710
5711 unlock_user_struct(frame, frame_addr, 1);
5712 return;
5713
5714give_sigsegv:
5715 if (sig == TARGET_SIGSEGV) {
5716 ka->_sa_handler = TARGET_SIG_DFL;
5717 }
5718 force_sig(TARGET_SIGSEGV /* , current */);
5719}
5720
5721long do_rt_sigreturn(CPUTLGState *env)
5722{
5723 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
5724 struct target_rt_sigframe *frame;
5725 sigset_t set;
5726
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005727 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005728 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5729 goto badframe;
5730 }
5731 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005732 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005733
5734 restore_sigcontext(env, &frame->uc.tuc_mcontext);
5735 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
5736 uc.tuc_stack),
5737 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
5738 goto badframe;
5739 }
5740
5741 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01005742 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08005743
5744
5745 badframe:
5746 unlock_user_struct(frame, frame_addr, 0);
5747 force_sig(TARGET_SIGSEGV);
5748}
5749
bellardb346ff42003-06-15 20:05:50 +00005750#else
5751
pbrook624f7972008-05-31 16:11:38 +00005752static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005753 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005754{
5755 fprintf(stderr, "setup_frame: not implemented\n");
5756}
5757
pbrook624f7972008-05-31 16:11:38 +00005758static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005759 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005760 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005761{
5762 fprintf(stderr, "setup_rt_frame: not implemented\n");
5763}
5764
Andreas Färber9349b4f2012-03-14 01:38:32 +01005765long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005766{
5767 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005768 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005769}
5770
Andreas Färber9349b4f2012-03-14 01:38:32 +01005771long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005772{
5773 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005774 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005775}
5776
bellard66fb9762003-03-23 01:06:05 +00005777#endif
5778
Peter Maydelleb552502016-05-27 15:51:43 +01005779static void handle_pending_signal(CPUArchState *cpu_env, int sig)
5780{
5781 CPUState *cpu = ENV_GET_CPU(cpu_env);
5782 abi_ulong handler;
Peter Maydell3d3efba2016-05-27 15:51:49 +01005783 sigset_t set;
Peter Maydelleb552502016-05-27 15:51:43 +01005784 target_sigset_t target_old_set;
5785 struct target_sigaction *sa;
5786 struct sigqueue *q;
5787 TaskState *ts = cpu->opaque;
5788 struct emulated_sigtable *k = &ts->sigtab[sig - 1];
5789
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005790 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00005791 /* dequeue signal */
5792 q = k->first;
5793 k->first = q->next;
5794 if (!k->first)
5795 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00005796
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005797 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00005798 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00005799 sa = NULL;
5800 handler = TARGET_SIG_IGN;
5801 } else {
5802 sa = &sigact_table[sig - 1];
5803 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00005804 }
bellard66fb9762003-03-23 01:06:05 +00005805
Peter Maydell3d3efba2016-05-27 15:51:49 +01005806 if (sig == TARGET_SIGSEGV && sigismember(&ts->signal_mask, SIGSEGV)) {
Peter Maydella7ec0f92014-03-14 14:36:56 +00005807 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
5808 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
5809 * because it got a real MMU fault), and treat as if default handler.
5810 */
5811 handler = TARGET_SIG_DFL;
5812 }
5813
bellard66fb9762003-03-23 01:06:05 +00005814 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00005815 /* default handler : ignore some signal. The other are job control or fatal */
5816 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5817 kill(getpid(),SIGSTOP);
5818 } else if (sig != TARGET_SIGCHLD &&
5819 sig != TARGET_SIGURG &&
5820 sig != TARGET_SIGWINCH &&
5821 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +00005822 force_sig(sig);
5823 }
5824 } else if (handler == TARGET_SIG_IGN) {
5825 /* ignore sig */
5826 } else if (handler == TARGET_SIG_ERR) {
5827 force_sig(sig);
5828 } else {
bellard9de5e442003-03-23 16:49:39 +00005829 /* compute the blocked signals during the handler execution */
Peter Maydell3d3efba2016-05-27 15:51:49 +01005830 sigset_t *blocked_set;
5831
pbrook624f7972008-05-31 16:11:38 +00005832 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00005833 /* SA_NODEFER indicates that the current signal should not be
5834 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00005835 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00005836 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00005837
bellard9de5e442003-03-23 16:49:39 +00005838 /* save the previous blocked signal state to restore it at the
5839 end of the signal execution (see do_sigreturn) */
Peter Maydell3d3efba2016-05-27 15:51:49 +01005840 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
5841
5842 /* block signals in the handler */
5843 blocked_set = ts->in_sigsuspend ?
5844 &ts->sigsuspend_mask : &ts->signal_mask;
5845 sigorset(&ts->signal_mask, blocked_set, &set);
5846 ts->in_sigsuspend = 0;
bellard9de5e442003-03-23 16:49:39 +00005847
bellardbc8a22c2003-03-30 21:02:40 +00005848 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00005849#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00005850 {
5851 CPUX86State *env = cpu_env;
5852 if (env->eflags & VM_MASK)
5853 save_v86_state(env);
5854 }
5855#endif
bellard9de5e442003-03-23 16:49:39 +00005856 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08005857#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Chen Gangbf0f60a2015-09-27 08:10:18 +08005858 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX)
Richard Hendersonff970902013-02-10 10:30:42 -08005859 /* These targets do not have traditional signals. */
5860 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
5861#else
pbrook624f7972008-05-31 16:11:38 +00005862 if (sa->sa_flags & TARGET_SA_SIGINFO)
5863 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005864 else
pbrook624f7972008-05-31 16:11:38 +00005865 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005866#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01005867 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00005868 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01005869 }
bellard31e31b82003-02-18 22:55:36 +00005870 }
bellard66fb9762003-03-23 01:06:05 +00005871 if (q != &k->info)
pbrook624f7972008-05-31 16:11:38 +00005872 free_sigqueue(cpu_env, q);
bellard31e31b82003-02-18 22:55:36 +00005873}
Peter Maydelle902d582016-05-27 15:51:44 +01005874
5875void process_pending_signals(CPUArchState *cpu_env)
5876{
5877 CPUState *cpu = ENV_GET_CPU(cpu_env);
5878 int sig;
5879 TaskState *ts = cpu->opaque;
Peter Maydell3d3efba2016-05-27 15:51:49 +01005880 sigset_t set;
5881 sigset_t *blocked_set;
Peter Maydelle902d582016-05-27 15:51:44 +01005882
Peter Maydell3d3efba2016-05-27 15:51:49 +01005883 while (atomic_read(&ts->signal_pending)) {
5884 /* FIXME: This is not threadsafe. */
5885 sigfillset(&set);
5886 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01005887
Peter Maydell3d3efba2016-05-27 15:51:49 +01005888 for (sig = 1; sig <= TARGET_NSIG; sig++) {
5889 blocked_set = ts->in_sigsuspend ?
5890 &ts->sigsuspend_mask : &ts->signal_mask;
5891
5892 if (ts->sigtab[sig - 1].pending &&
5893 (!sigismember(blocked_set,
5894 target_to_host_signal_table[sig])
5895 || sig == TARGET_SIGSEGV)) {
5896 handle_pending_signal(cpu_env, sig);
5897 /* Restart scan from the beginning */
5898 sig = 1;
5899 }
Peter Maydelle902d582016-05-27 15:51:44 +01005900 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01005901
5902 /* if no signal is pending, unblock signals and recheck (the act
5903 * of unblocking might cause us to take another host signal which
5904 * will set signal_pending again).
5905 */
5906 atomic_set(&ts->signal_pending, 0);
5907 ts->in_sigsuspend = 0;
5908 set = ts->signal_mask;
5909 sigdelset(&set, SIGSEGV);
5910 sigdelset(&set, SIGBUS);
5911 sigprocmask(SIG_SETMASK, &set, 0);
Peter Maydelle902d582016-05-27 15:51:44 +01005912 }
Peter Maydell3d3efba2016-05-27 15:51:49 +01005913 ts->in_sigsuspend = 0;
Peter Maydelle902d582016-05-27 15:51:44 +01005914}