blob: 1b86a8550c026bfd477576b95f6e197d191c6679 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
bellard31e31b82003-02-18 22:55:36 +000020#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030021#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000022
bellard3ef693a2003-03-23 20:17:16 +000023#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000024#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000025#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010026#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000027
blueswir1249c4c32008-10-05 11:09:37 +000028static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000029 .ss_sp = 0,
30 .ss_size = 0,
31 .ss_flags = TARGET_SS_DISABLE,
32};
33
pbrook624f7972008-05-31 16:11:38 +000034static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000035
ths5fafdf22007-09-16 21:08:06 +000036static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000037 void *puc);
38
Arnaud Patard3ca05582009-03-30 01:18:20 +020039static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000040 [SIGHUP] = TARGET_SIGHUP,
41 [SIGINT] = TARGET_SIGINT,
42 [SIGQUIT] = TARGET_SIGQUIT,
43 [SIGILL] = TARGET_SIGILL,
44 [SIGTRAP] = TARGET_SIGTRAP,
45 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000046/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000047 [SIGBUS] = TARGET_SIGBUS,
48 [SIGFPE] = TARGET_SIGFPE,
49 [SIGKILL] = TARGET_SIGKILL,
50 [SIGUSR1] = TARGET_SIGUSR1,
51 [SIGSEGV] = TARGET_SIGSEGV,
52 [SIGUSR2] = TARGET_SIGUSR2,
53 [SIGPIPE] = TARGET_SIGPIPE,
54 [SIGALRM] = TARGET_SIGALRM,
55 [SIGTERM] = TARGET_SIGTERM,
56#ifdef SIGSTKFLT
57 [SIGSTKFLT] = TARGET_SIGSTKFLT,
58#endif
59 [SIGCHLD] = TARGET_SIGCHLD,
60 [SIGCONT] = TARGET_SIGCONT,
61 [SIGSTOP] = TARGET_SIGSTOP,
62 [SIGTSTP] = TARGET_SIGTSTP,
63 [SIGTTIN] = TARGET_SIGTTIN,
64 [SIGTTOU] = TARGET_SIGTTOU,
65 [SIGURG] = TARGET_SIGURG,
66 [SIGXCPU] = TARGET_SIGXCPU,
67 [SIGXFSZ] = TARGET_SIGXFSZ,
68 [SIGVTALRM] = TARGET_SIGVTALRM,
69 [SIGPROF] = TARGET_SIGPROF,
70 [SIGWINCH] = TARGET_SIGWINCH,
71 [SIGIO] = TARGET_SIGIO,
72 [SIGPWR] = TARGET_SIGPWR,
73 [SIGSYS] = TARGET_SIGSYS,
74 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000075 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080076 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000077 To fix this properly we need to do manual signal delivery multiplexed
78 over a single host signal. */
79 [__SIGRTMIN] = __SIGRTMAX,
80 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000081};
Arnaud Patard3ca05582009-03-30 01:18:20 +020082static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000083
thsa04e1342007-09-27 13:57:58 +000084static inline int on_sig_stack(unsigned long sp)
85{
86 return (sp - target_sigaltstack_used.ss_sp
87 < target_sigaltstack_used.ss_size);
88}
89
90static inline int sas_ss_flags(unsigned long sp)
91{
92 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
93 : on_sig_stack(sp) ? SS_ONSTACK : 0);
94}
95
pbrook1d9d8b52009-04-16 15:17:02 +000096int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000097{
Andreas Schwab167c50d2013-07-02 14:04:12 +010098 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +000099 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000100 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000101}
102
pbrook4cb05962008-05-30 18:05:19 +0000103int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000104{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100105 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000106 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000107 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000108}
109
Anthony Liguoric227f092009-10-01 16:12:16 -0500110static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000111{
112 memset(set, 0, sizeof(*set));
113}
114
Anthony Liguoric227f092009-10-01 16:12:16 -0500115static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000116{
117 signum--;
118 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
119 set->sig[signum / TARGET_NSIG_BPW] |= mask;
120}
121
Anthony Liguoric227f092009-10-01 16:12:16 -0500122static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000123{
124 signum--;
125 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
126 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
127}
128
Anthony Liguoric227f092009-10-01 16:12:16 -0500129static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000130 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000131{
132 int i;
pbrookf5545b52008-05-30 22:37:07 +0000133 target_sigemptyset(d);
134 for (i = 1; i <= TARGET_NSIG; i++) {
135 if (sigismember(s, i)) {
136 target_sigaddset(d, host_to_target_signal(i));
137 }
bellard9e5f5282003-07-13 17:33:54 +0000138 }
bellard66fb9762003-03-23 01:06:05 +0000139}
140
Anthony Liguoric227f092009-10-01 16:12:16 -0500141void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000142{
Anthony Liguoric227f092009-10-01 16:12:16 -0500143 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000144 int i;
145
146 host_to_target_sigset_internal(&d1, s);
147 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200148 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000149}
150
blueswir18fcd3692008-08-17 20:26:25 +0000151static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500152 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000153{
154 int i;
pbrookf5545b52008-05-30 22:37:07 +0000155 sigemptyset(d);
156 for (i = 1; i <= TARGET_NSIG; i++) {
157 if (target_sigismember(s, i)) {
158 sigaddset(d, target_to_host_signal(i));
159 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100160 }
bellard66fb9762003-03-23 01:06:05 +0000161}
162
Anthony Liguoric227f092009-10-01 16:12:16 -0500163void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000164{
Anthony Liguoric227f092009-10-01 16:12:16 -0500165 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000166 int i;
167
168 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200169 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000170 target_to_host_sigset_internal(d, &s1);
171}
ths3b46e622007-09-17 08:09:54 +0000172
blueswir1992f48a2007-10-14 16:27:31 +0000173void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000174 const sigset_t *sigset)
175{
Anthony Liguoric227f092009-10-01 16:12:16 -0500176 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000177 host_to_target_sigset(&d, sigset);
178 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000179}
180
ths5fafdf22007-09-16 21:08:06 +0000181void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000182 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000183{
Anthony Liguoric227f092009-10-01 16:12:16 -0500184 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000185 int i;
186
187 d.sig[0] = *old_sigset;
188 for(i = 1;i < TARGET_NSIG_WORDS; i++)
189 d.sig[i] = 0;
190 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000191}
192
Alex Barcelo1c275922014-03-14 14:36:55 +0000193/* Wrapper for sigprocmask function
194 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
195 * are host signal set, not guest ones. This wraps the sigprocmask host calls
196 * that should be protected (calls originated from guest)
197 */
198int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
199{
Peter Maydella7ec0f92014-03-14 14:36:56 +0000200 int ret;
201 sigset_t val;
202 sigset_t *temp = NULL;
203 CPUState *cpu = thread_cpu;
204 TaskState *ts = (TaskState *)cpu->opaque;
205 bool segv_was_blocked = ts->sigsegv_blocked;
206
207 if (set) {
208 bool has_sigsegv = sigismember(set, SIGSEGV);
209 val = *set;
210 temp = &val;
211
212 sigdelset(temp, SIGSEGV);
213
214 switch (how) {
215 case SIG_BLOCK:
216 if (has_sigsegv) {
217 ts->sigsegv_blocked = true;
218 }
219 break;
220 case SIG_UNBLOCK:
221 if (has_sigsegv) {
222 ts->sigsegv_blocked = false;
223 }
224 break;
225 case SIG_SETMASK:
226 ts->sigsegv_blocked = has_sigsegv;
227 break;
228 default:
229 g_assert_not_reached();
230 }
231 }
232
233 ret = sigprocmask(how, temp, oldset);
234
235 if (oldset && segv_was_blocked) {
236 sigaddset(oldset, SIGSEGV);
237 }
238
239 return ret;
Alex Barcelo1c275922014-03-14 14:36:55 +0000240}
241
Peter Maydell9eede5b2016-05-27 15:51:46 +0100242#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
243 !defined(TARGET_X86_64)
244/* Just set the guest's signal mask to the specified value */
245static void set_sigmask(const sigset_t *set)
246{
247 do_sigprocmask(SIG_SETMASK, set, NULL);
248}
249#endif
250
bellard9de5e442003-03-23 16:49:39 +0000251/* siginfo conversion */
252
Anthony Liguoric227f092009-10-01 16:12:16 -0500253static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000254 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000255{
Richard Hendersona05c6402012-09-15 11:34:20 -0700256 int sig = host_to_target_signal(info->si_signo);
bellard9de5e442003-03-23 16:49:39 +0000257 tinfo->si_signo = sig;
258 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000259 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700260
261 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100262 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
Richard Hendersona05c6402012-09-15 11:34:20 -0700263 /* Should never come here, but who knows. The information for
264 the target is irrelevant. */
bellard9de5e442003-03-23 16:49:39 +0000265 tinfo->_sifields._sigfault._addr = 0;
Richard Hendersona05c6402012-09-15 11:34:20 -0700266 } else if (sig == TARGET_SIGIO) {
267 tinfo->_sifields._sigpoll._band = info->si_band;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100268 tinfo->_sifields._sigpoll._fd = info->si_fd;
Richard Hendersona05c6402012-09-15 11:34:20 -0700269 } else if (sig == TARGET_SIGCHLD) {
270 tinfo->_sifields._sigchld._pid = info->si_pid;
271 tinfo->_sifields._sigchld._uid = info->si_uid;
272 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100273 = host_to_target_waitstatus(info->si_status);
Richard Hendersona05c6402012-09-15 11:34:20 -0700274 tinfo->_sifields._sigchld._utime = info->si_utime;
275 tinfo->_sifields._sigchld._stime = info->si_stime;
bellard9de5e442003-03-23 16:49:39 +0000276 } else if (sig >= TARGET_SIGRTMIN) {
277 tinfo->_sifields._rt._pid = info->si_pid;
278 tinfo->_sifields._rt._uid = info->si_uid;
279 /* XXX: potential problem if 64 bit */
Richard Hendersona05c6402012-09-15 11:34:20 -0700280 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100281 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
bellard9de5e442003-03-23 16:49:39 +0000282 }
bellard66fb9762003-03-23 01:06:05 +0000283}
284
Anthony Liguoric227f092009-10-01 16:12:16 -0500285static void tswap_siginfo(target_siginfo_t *tinfo,
286 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000287{
Richard Hendersona05c6402012-09-15 11:34:20 -0700288 int sig = info->si_signo;
bellard9de5e442003-03-23 16:49:39 +0000289 tinfo->si_signo = tswap32(sig);
290 tinfo->si_errno = tswap32(info->si_errno);
291 tinfo->si_code = tswap32(info->si_code);
Richard Hendersona05c6402012-09-15 11:34:20 -0700292
293 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
294 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
295 tinfo->_sifields._sigfault._addr
296 = tswapal(info->_sifields._sigfault._addr);
297 } else if (sig == TARGET_SIGIO) {
298 tinfo->_sifields._sigpoll._band
299 = tswap32(info->_sifields._sigpoll._band);
300 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
301 } else if (sig == TARGET_SIGCHLD) {
302 tinfo->_sifields._sigchld._pid
303 = tswap32(info->_sifields._sigchld._pid);
304 tinfo->_sifields._sigchld._uid
305 = tswap32(info->_sifields._sigchld._uid);
306 tinfo->_sifields._sigchld._status
307 = tswap32(info->_sifields._sigchld._status);
308 tinfo->_sifields._sigchld._utime
309 = tswapal(info->_sifields._sigchld._utime);
310 tinfo->_sifields._sigchld._stime
311 = tswapal(info->_sifields._sigchld._stime);
bellard9de5e442003-03-23 16:49:39 +0000312 } else if (sig >= TARGET_SIGRTMIN) {
313 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
314 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
Richard Hendersona05c6402012-09-15 11:34:20 -0700315 tinfo->_sifields._rt._sigval.sival_ptr
316 = tswapal(info->_sifields._rt._sigval.sival_ptr);
bellard9de5e442003-03-23 16:49:39 +0000317 }
318}
319
320
Anthony Liguoric227f092009-10-01 16:12:16 -0500321void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000322{
323 host_to_target_siginfo_noswap(tinfo, info);
324 tswap_siginfo(tinfo, tinfo);
325}
326
327/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000328/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500329void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000330{
331 info->si_signo = tswap32(tinfo->si_signo);
332 info->si_errno = tswap32(tinfo->si_errno);
333 info->si_code = tswap32(tinfo->si_code);
bellard9de5e442003-03-23 16:49:39 +0000334 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
335 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
ths5fafdf22007-09-16 21:08:06 +0000336 info->si_value.sival_ptr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200337 (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr);
bellard66fb9762003-03-23 01:06:05 +0000338}
339
aurel32ca587a82008-12-18 22:44:13 +0000340static int fatal_signal (int sig)
341{
342 switch (sig) {
343 case TARGET_SIGCHLD:
344 case TARGET_SIGURG:
345 case TARGET_SIGWINCH:
346 /* Ignored by default. */
347 return 0;
348 case TARGET_SIGCONT:
349 case TARGET_SIGSTOP:
350 case TARGET_SIGTSTP:
351 case TARGET_SIGTTIN:
352 case TARGET_SIGTTOU:
353 /* Job control signals. */
354 return 0;
355 default:
356 return 1;
357 }
358}
359
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300360/* returns 1 if given signal should dump core if not handled */
361static int core_dump_signal(int sig)
362{
363 switch (sig) {
364 case TARGET_SIGABRT:
365 case TARGET_SIGFPE:
366 case TARGET_SIGILL:
367 case TARGET_SIGQUIT:
368 case TARGET_SIGSEGV:
369 case TARGET_SIGTRAP:
370 case TARGET_SIGBUS:
371 return (1);
372 default:
373 return (0);
374 }
375}
376
bellard31e31b82003-02-18 22:55:36 +0000377void signal_init(void)
378{
379 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000380 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000381 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000382 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000383
bellard9e5f5282003-07-13 17:33:54 +0000384 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200385 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000386 if (host_to_target_signal_table[i] == 0)
387 host_to_target_signal_table[i] = i;
388 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200389 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000390 j = host_to_target_signal_table[i];
391 target_to_host_signal_table[j] = i;
392 }
ths3b46e622007-09-17 08:09:54 +0000393
bellard9de5e442003-03-23 16:49:39 +0000394 /* set all host signal handlers. ALL signals are blocked during
395 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000396 memset(sigact_table, 0, sizeof(sigact_table));
397
bellard9de5e442003-03-23 16:49:39 +0000398 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000399 act.sa_flags = SA_SIGINFO;
400 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000401 for(i = 1; i <= TARGET_NSIG; i++) {
402 host_sig = target_to_host_signal(i);
403 sigaction(host_sig, NULL, &oact);
404 if (oact.sa_sigaction == (void *)SIG_IGN) {
405 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
406 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
407 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
408 }
409 /* If there's already a handler installed then something has
410 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000411 /* Install some handlers for our own use. We need at least
412 SIGSEGV and SIGBUS, to detect exceptions. We can not just
413 trap all signals because it affects syscall interrupt
414 behavior. But do trap all default-fatal signals. */
415 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000416 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000417 }
bellard31e31b82003-02-18 22:55:36 +0000418}
419
bellard66fb9762003-03-23 01:06:05 +0000420/* signal queue handling */
421
Andreas Färber9349b4f2012-03-14 01:38:32 +0100422static inline struct sigqueue *alloc_sigqueue(CPUArchState *env)
bellard66fb9762003-03-23 01:06:05 +0000423{
Andreas Färber0429a972013-08-26 18:14:44 +0200424 CPUState *cpu = ENV_GET_CPU(env);
425 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000426 struct sigqueue *q = ts->first_free;
bellard66fb9762003-03-23 01:06:05 +0000427 if (!q)
428 return NULL;
pbrook624f7972008-05-31 16:11:38 +0000429 ts->first_free = q->next;
bellard66fb9762003-03-23 01:06:05 +0000430 return q;
431}
432
Andreas Färber9349b4f2012-03-14 01:38:32 +0100433static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
bellard66fb9762003-03-23 01:06:05 +0000434{
Andreas Färber0429a972013-08-26 18:14:44 +0200435 CPUState *cpu = ENV_GET_CPU(env);
436 TaskState *ts = cpu->opaque;
437
pbrook624f7972008-05-31 16:11:38 +0000438 q->next = ts->first_free;
439 ts->first_free = q;
bellard66fb9762003-03-23 01:06:05 +0000440}
441
bellard9de5e442003-03-23 16:49:39 +0000442/* abort execution with signal */
Riku Voipio66393fb2009-12-04 15:16:32 +0200443static void QEMU_NORETURN force_sig(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000444{
Andreas Färber0429a972013-08-26 18:14:44 +0200445 CPUState *cpu = thread_cpu;
446 CPUArchState *env = cpu->env_ptr;
447 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300448 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000449 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100450
Riku Voipio66393fb2009-12-04 15:16:32 +0200451 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100452 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200453 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000454
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300455 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200456 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300457 stop_all_tasks();
458 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200459 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300460 }
461 if (core_dumped) {
462 /* we already dumped the core of target process, we don't want
463 * a coredump of qemu itself */
464 struct rlimit nodump;
465 getrlimit(RLIMIT_CORE, &nodump);
466 nodump.rlim_cur=0;
467 setrlimit(RLIMIT_CORE, &nodump);
468 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200469 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300470 }
471
Stefan Weil0c587512011-04-28 17:20:32 +0200472 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000473 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
474 * a negative value. To get the proper exit code we need to
475 * actually die from an uncaught signal. Here the default signal
476 * handler is installed, we send ourself a signal and we wait for
477 * it to arrive. */
478 sigfillset(&act.sa_mask);
479 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000480 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000481 sigaction(host_sig, &act, NULL);
482
483 /* For some reason raise(host_sig) doesn't send the signal when
484 * statically linked on x86-64. */
485 kill(getpid(), host_sig);
486
487 /* Make sure the signal isn't masked (just reuse the mask inside
488 of act) */
489 sigdelset(&act.sa_mask, host_sig);
490 sigsuspend(&act.sa_mask);
491
492 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000493 abort();
bellard66fb9762003-03-23 01:06:05 +0000494}
495
bellard9de5e442003-03-23 16:49:39 +0000496/* queue a signal so that it will be send to the virtual CPU as soon
497 as possible */
Andreas Färber9349b4f2012-03-14 01:38:32 +0100498int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000499{
Andreas Färber0429a972013-08-26 18:14:44 +0200500 CPUState *cpu = ENV_GET_CPU(env);
501 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000502 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000503 struct sigqueue *q, **pq;
blueswir1992f48a2007-10-14 16:27:31 +0000504 abi_ulong handler;
aurel32ca587a82008-12-18 22:44:13 +0000505 int queue;
bellard66fb9762003-03-23 01:06:05 +0000506
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100507 trace_user_queue_signal(env, sig);
pbrook624f7972008-05-31 16:11:38 +0000508 k = &ts->sigtab[sig - 1];
aurel32ca587a82008-12-18 22:44:13 +0000509 queue = gdb_queuesig ();
pbrook624f7972008-05-31 16:11:38 +0000510 handler = sigact_table[sig - 1]._sa_handler;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000511
512 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
513 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
514 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
515 * because it got a real MMU fault). A blocked SIGSEGV in that
516 * situation is treated as if using the default handler. This is
517 * not correct if some other process has randomly sent us a SIGSEGV
518 * via kill(), but that is not easy to distinguish at this point,
519 * so we assume it doesn't happen.
520 */
521 handler = TARGET_SIG_DFL;
522 }
523
aurel32ca587a82008-12-18 22:44:13 +0000524 if (!queue && handler == TARGET_SIG_DFL) {
ths60b19692008-11-27 15:47:15 +0000525 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
526 kill(getpid(),SIGSTOP);
527 return 0;
528 } else
bellard66fb9762003-03-23 01:06:05 +0000529 /* default handler : ignore some signal. The other are fatal */
ths5fafdf22007-09-16 21:08:06 +0000530 if (sig != TARGET_SIGCHLD &&
531 sig != TARGET_SIGURG &&
ths60b19692008-11-27 15:47:15 +0000532 sig != TARGET_SIGWINCH &&
533 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +0000534 force_sig(sig);
bellard9de5e442003-03-23 16:49:39 +0000535 } else {
536 return 0; /* indicate ignored */
bellard66fb9762003-03-23 01:06:05 +0000537 }
aurel32ca587a82008-12-18 22:44:13 +0000538 } else if (!queue && handler == TARGET_SIG_IGN) {
bellard66fb9762003-03-23 01:06:05 +0000539 /* ignore signal */
bellard9de5e442003-03-23 16:49:39 +0000540 return 0;
aurel32ca587a82008-12-18 22:44:13 +0000541 } else if (!queue && handler == TARGET_SIG_ERR) {
bellard66fb9762003-03-23 01:06:05 +0000542 force_sig(sig);
543 } else {
bellard9de5e442003-03-23 16:49:39 +0000544 pq = &k->first;
545 if (sig < TARGET_SIGRTMIN) {
546 /* if non real time signal, we queue exactly one signal */
547 if (!k->pending)
548 q = &k->info;
549 else
550 return 0;
551 } else {
552 if (!k->pending) {
553 /* first signal */
554 q = &k->info;
555 } else {
pbrook624f7972008-05-31 16:11:38 +0000556 q = alloc_sigqueue(env);
bellard9de5e442003-03-23 16:49:39 +0000557 if (!q)
558 return -EAGAIN;
559 while (*pq != NULL)
560 pq = &(*pq)->next;
561 }
562 }
563 *pq = q;
564 q->info = *info;
565 q->next = NULL;
566 k->pending = 1;
567 /* signal that a new signal is pending */
pbrook624f7972008-05-31 16:11:38 +0000568 ts->signal_pending = 1;
bellard9de5e442003-03-23 16:49:39 +0000569 return 1; /* indicates that the signal was queued */
570 }
571}
572
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100573#ifndef HAVE_SAFE_SYSCALL
574static inline void rewind_if_in_safe_syscall(void *puc)
575{
576 /* Default version: never rewind */
577}
578#endif
579
ths5fafdf22007-09-16 21:08:06 +0000580static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000581 void *puc)
582{
Andreas Färbera2247f82013-06-09 19:47:04 +0200583 CPUArchState *env = thread_cpu->env_ptr;
bellard9de5e442003-03-23 16:49:39 +0000584 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500585 target_siginfo_t tinfo;
bellard9de5e442003-03-23 16:49:39 +0000586
587 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000588 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000589 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000590 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000591 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000592 return;
593 }
594
595 /* get target signal number */
596 sig = host_to_target_signal(host_signum);
597 if (sig < 1 || sig > TARGET_NSIG)
598 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100599 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100600
601 rewind_if_in_safe_syscall(puc);
602
bellard9de5e442003-03-23 16:49:39 +0000603 host_to_target_siginfo_noswap(&tinfo, info);
Andreas Färbera2247f82013-06-09 19:47:04 +0200604 if (queue_signal(env, sig, &tinfo) == 1) {
bellard9de5e442003-03-23 16:49:39 +0000605 /* interrupt the virtual CPU as soon as possible */
Andreas Färbera2247f82013-06-09 19:47:04 +0200606 cpu_exit(thread_cpu);
bellard66fb9762003-03-23 01:06:05 +0000607 }
bellard31e31b82003-02-18 22:55:36 +0000608}
609
ths0da46a62007-10-20 20:23:07 +0000610/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000611/* compare linux/kernel/signal.c:do_sigaltstack() */
612abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000613{
614 int ret;
615 struct target_sigaltstack oss;
616
617 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000618 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000619 {
620 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
621 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
622 __put_user(sas_ss_flags(sp), &oss.ss_flags);
623 }
624
bellard579a97f2007-11-11 14:26:47 +0000625 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000626 {
bellard579a97f2007-11-11 14:26:47 +0000627 struct target_sigaltstack *uss;
628 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500629 size_t minstacksize = TARGET_MINSIGSTKSZ;
630
631#if defined(TARGET_PPC64)
632 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
633 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
634 if (get_ppc64_abi(image) > 1) {
635 minstacksize = 4096;
636 }
637#endif
thsa04e1342007-09-27 13:57:58 +0000638
ths0da46a62007-10-20 20:23:07 +0000639 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300640 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000641 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300642 }
643 __get_user(ss.ss_sp, &uss->ss_sp);
644 __get_user(ss.ss_size, &uss->ss_size);
645 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000646 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000647
ths0da46a62007-10-20 20:23:07 +0000648 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000649 if (on_sig_stack(sp))
650 goto out;
651
ths0da46a62007-10-20 20:23:07 +0000652 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000653 if (ss.ss_flags != TARGET_SS_DISABLE
654 && ss.ss_flags != TARGET_SS_ONSTACK
655 && ss.ss_flags != 0)
656 goto out;
657
658 if (ss.ss_flags == TARGET_SS_DISABLE) {
659 ss.ss_size = 0;
660 ss.ss_sp = 0;
661 } else {
ths0da46a62007-10-20 20:23:07 +0000662 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500663 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000664 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500665 }
thsa04e1342007-09-27 13:57:58 +0000666 }
667
668 target_sigaltstack_used.ss_sp = ss.ss_sp;
669 target_sigaltstack_used.ss_size = ss.ss_size;
670 }
671
bellard579a97f2007-11-11 14:26:47 +0000672 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000673 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000674 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000675 goto out;
thsa04e1342007-09-27 13:57:58 +0000676 }
677
678 ret = 0;
679out:
680 return ret;
681}
682
ths0da46a62007-10-20 20:23:07 +0000683/* do_sigaction() return host values and errnos */
bellard66fb9762003-03-23 01:06:05 +0000684int do_sigaction(int sig, const struct target_sigaction *act,
685 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000686{
pbrook624f7972008-05-31 16:11:38 +0000687 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000688 struct sigaction act1;
689 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000690 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000691
ths2a913eb2008-11-27 15:46:25 +0000692 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
bellard66fb9762003-03-23 01:06:05 +0000693 return -EINVAL;
694 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000695 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800696 __put_user(k->_sa_handler, &oact->_sa_handler);
697 __put_user(k->sa_flags, &oact->sa_flags);
ths388bb212007-05-13 13:58:00 +0000698#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800699 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000700#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800701 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000702 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000703 }
704 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000705 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800706 __get_user(k->_sa_handler, &act->_sa_handler);
707 __get_user(k->sa_flags, &act->sa_flags);
ths388bb212007-05-13 13:58:00 +0000708#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800709 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000710#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800711 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000712 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000713
714 /* we update the host linux signal state */
715 host_sig = target_to_host_signal(sig);
716 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
717 sigfillset(&act1.sa_mask);
718 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000719 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000720 act1.sa_flags |= SA_RESTART;
721 /* NOTE: it is important to update the host kernel signal
722 ignore state to avoid getting unexpected interrupted
723 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000724 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000725 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000726 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000727 if (fatal_signal (sig))
728 act1.sa_sigaction = host_signal_handler;
729 else
730 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000731 } else {
732 act1.sa_sigaction = host_signal_handler;
733 }
ths0da46a62007-10-20 20:23:07 +0000734 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000735 }
bellard66fb9762003-03-23 01:06:05 +0000736 }
ths0da46a62007-10-20 20:23:07 +0000737 return ret;
bellard66fb9762003-03-23 01:06:05 +0000738}
bellard31e31b82003-02-18 22:55:36 +0000739
bellard459a4012007-11-11 19:45:10 +0000740#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
bellard66fb9762003-03-23 01:06:05 +0000741
742/* from the Linux kernel */
743
744struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100745 uint16_t significand[4];
746 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000747};
748
749struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100750 uint16_t significand[4];
751 uint16_t exponent;
752 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000753};
754
755struct target_xmmreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100756 abi_ulong element[4];
bellard66fb9762003-03-23 01:06:05 +0000757};
758
759struct target_fpstate {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100760 /* Regular FPU environment */
761 abi_ulong cw;
762 abi_ulong sw;
763 abi_ulong tag;
764 abi_ulong ipoff;
765 abi_ulong cssel;
766 abi_ulong dataoff;
767 abi_ulong datasel;
768 struct target_fpreg _st[8];
769 uint16_t status;
770 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000771
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100772 /* FXSR FPU environment */
773 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
774 abi_ulong mxcsr;
775 abi_ulong reserved;
776 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
777 struct target_xmmreg _xmm[8];
778 abi_ulong padding[56];
bellard66fb9762003-03-23 01:06:05 +0000779};
780
781#define X86_FXSR_MAGIC 0x0000
782
783struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100784 uint16_t gs, __gsh;
785 uint16_t fs, __fsh;
786 uint16_t es, __esh;
787 uint16_t ds, __dsh;
788 abi_ulong edi;
789 abi_ulong esi;
790 abi_ulong ebp;
791 abi_ulong esp;
792 abi_ulong ebx;
793 abi_ulong edx;
794 abi_ulong ecx;
795 abi_ulong eax;
796 abi_ulong trapno;
797 abi_ulong err;
798 abi_ulong eip;
799 uint16_t cs, __csh;
800 abi_ulong eflags;
801 abi_ulong esp_at_signal;
802 uint16_t ss, __ssh;
803 abi_ulong fpstate; /* pointer */
804 abi_ulong oldmask;
805 abi_ulong cr2;
bellard66fb9762003-03-23 01:06:05 +0000806};
807
bellard66fb9762003-03-23 01:06:05 +0000808struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100809 abi_ulong tuc_flags;
810 abi_ulong tuc_link;
811 target_stack_t tuc_stack;
812 struct target_sigcontext tuc_mcontext;
813 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000814};
815
816struct sigframe
817{
blueswir1992f48a2007-10-14 16:27:31 +0000818 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000819 int sig;
820 struct target_sigcontext sc;
821 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000822 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000823 char retcode[8];
824};
825
826struct rt_sigframe
827{
blueswir1992f48a2007-10-14 16:27:31 +0000828 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000829 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000830 abi_ulong pinfo;
831 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000832 struct target_siginfo info;
833 struct target_ucontext uc;
834 struct target_fpstate fpstate;
835 char retcode[8];
836};
837
838/*
839 * Set up a signal frame.
840 */
841
bellard66fb9762003-03-23 01:06:05 +0000842/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300843static void setup_sigcontext(struct target_sigcontext *sc,
844 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
845 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000846{
Andreas Färber27103422013-08-26 08:31:06 +0200847 CPUState *cs = CPU(x86_env_get_cpu(env));
Andreas Färber27103422013-08-26 08:31:06 +0200848 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +0000849
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100850 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300851 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
852 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
853 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
854 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
855 __put_user(env->regs[R_EDI], &sc->edi);
856 __put_user(env->regs[R_ESI], &sc->esi);
857 __put_user(env->regs[R_EBP], &sc->ebp);
858 __put_user(env->regs[R_ESP], &sc->esp);
859 __put_user(env->regs[R_EBX], &sc->ebx);
860 __put_user(env->regs[R_EDX], &sc->edx);
861 __put_user(env->regs[R_ECX], &sc->ecx);
862 __put_user(env->regs[R_EAX], &sc->eax);
863 __put_user(cs->exception_index, &sc->trapno);
864 __put_user(env->error_code, &sc->err);
865 __put_user(env->eip, &sc->eip);
866 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
867 __put_user(env->eflags, &sc->eflags);
868 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
869 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +0000870
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100871 cpu_x86_fsave(env, fpstate_addr, 1);
872 fpstate->status = fpstate->sw;
873 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300874 __put_user(magic, &fpstate->magic);
875 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +0000876
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100877 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300878 __put_user(mask, &sc->oldmask);
879 __put_user(env->cr[2], &sc->cr2);
bellard66fb9762003-03-23 01:06:05 +0000880}
881
882/*
883 * Determine which stack to use..
884 */
885
bellard579a97f2007-11-11 14:26:47 +0000886static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +0000887get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +0000888{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100889 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +0000890
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100891 /* Default to using normal stack */
892 esp = env->regs[R_ESP];
893 /* This is the X/Open sanctioned signal stack switching. */
894 if (ka->sa_flags & TARGET_SA_ONSTACK) {
895 if (sas_ss_flags(esp) == 0) {
896 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +0000897 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100898 } else {
bellard66fb9762003-03-23 01:06:05 +0000899
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100900 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +0000901 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100902 !(ka->sa_flags & TARGET_SA_RESTORER) &&
903 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +0000904 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100905 }
906 }
907 return (esp - frame_size) & -8ul;
bellard66fb9762003-03-23 01:06:05 +0000908}
909
bellard579a97f2007-11-11 14:26:47 +0000910/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +0000911static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100912 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000913{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100914 abi_ulong frame_addr;
915 struct sigframe *frame;
916 int i;
bellard66fb9762003-03-23 01:06:05 +0000917
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100918 frame_addr = get_sigframe(ka, env, sizeof(*frame));
919 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +0000920
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100921 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
922 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +0000923
Peter Maydellb6e2c932015-01-08 12:19:43 +0000924 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +0000925
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100926 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
927 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +0000928
Riku Voipio7df2fa32014-04-23 10:34:53 +0300929 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
930 __put_user(set->sig[i], &frame->extramask[i - 1]);
931 }
bellard66fb9762003-03-23 01:06:05 +0000932
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100933 /* Set up to return from userspace. If provided, use a stub
934 already in userspace. */
935 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +0300936 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100937 } else {
938 uint16_t val16;
939 abi_ulong retcode_addr;
940 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300941 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100942 /* This is popl %eax ; movl $,%eax ; int $0x80 */
943 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300944 __put_user(val16, (uint16_t *)(frame->retcode+0));
945 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100946 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300947 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100948 }
bellard66fb9762003-03-23 01:06:05 +0000949
bellard66fb9762003-03-23 01:06:05 +0000950
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100951 /* Set up registers for signal handler */
952 env->regs[R_ESP] = frame_addr;
953 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +0000954
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100955 cpu_x86_load_seg(env, R_DS, __USER_DS);
956 cpu_x86_load_seg(env, R_ES, __USER_DS);
957 cpu_x86_load_seg(env, R_SS, __USER_DS);
958 cpu_x86_load_seg(env, R_CS, __USER_CS);
959 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +0000960
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100961 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000962
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100963 return;
bellard66fb9762003-03-23 01:06:05 +0000964
965give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100966 if (sig == TARGET_SIGSEGV) {
967 ka->_sa_handler = TARGET_SIG_DFL;
968 }
969 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +0000970}
971
bellard579a97f2007-11-11 14:26:47 +0000972/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +0000973static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -0500974 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100975 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000976{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100977 abi_ulong frame_addr, addr;
978 struct rt_sigframe *frame;
979 int i;
bellard66fb9762003-03-23 01:06:05 +0000980
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100981 frame_addr = get_sigframe(ka, env, sizeof(*frame));
982 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +0000983
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100984 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
985 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +0000986
Peter Maydellb6e2c932015-01-08 12:19:43 +0000987 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100988 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300989 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100990 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300991 __put_user(addr, &frame->puc);
Peter Maydellf6c7a052015-01-08 12:19:48 +0000992 tswap_siginfo(&frame->info, info);
bellard66fb9762003-03-23 01:06:05 +0000993
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100994 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300995 __put_user(0, &frame->uc.tuc_flags);
996 __put_user(0, &frame->uc.tuc_link);
997 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
998 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
999 &frame->uc.tuc_stack.ss_flags);
1000 __put_user(target_sigaltstack_used.ss_size,
1001 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03001002 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1003 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1004
Riku Voipio0188fad2014-04-23 13:34:15 +03001005 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1006 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1007 }
bellard66fb9762003-03-23 01:06:05 +00001008
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001009 /* Set up to return from userspace. If provided, use a stub
1010 already in userspace. */
1011 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001012 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001013 } else {
1014 uint16_t val16;
1015 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001016 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001017 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001018 __put_user(0xb8, (char *)(frame->retcode+0));
1019 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001020 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001021 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001022 }
bellard66fb9762003-03-23 01:06:05 +00001023
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001024 /* Set up registers for signal handler */
1025 env->regs[R_ESP] = frame_addr;
1026 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001027
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001028 cpu_x86_load_seg(env, R_DS, __USER_DS);
1029 cpu_x86_load_seg(env, R_ES, __USER_DS);
1030 cpu_x86_load_seg(env, R_SS, __USER_DS);
1031 cpu_x86_load_seg(env, R_CS, __USER_CS);
1032 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001033
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001034 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001035
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001036 return;
bellard66fb9762003-03-23 01:06:05 +00001037
1038give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001039 if (sig == TARGET_SIGSEGV) {
1040 ka->_sa_handler = TARGET_SIG_DFL;
1041 }
1042 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +00001043}
1044
1045static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001046restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001047{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001048 unsigned int err = 0;
1049 abi_ulong fpstate_addr;
1050 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001051
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001052 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1053 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1054 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1055 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001056
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001057 env->regs[R_EDI] = tswapl(sc->edi);
1058 env->regs[R_ESI] = tswapl(sc->esi);
1059 env->regs[R_EBP] = tswapl(sc->ebp);
1060 env->regs[R_ESP] = tswapl(sc->esp);
1061 env->regs[R_EBX] = tswapl(sc->ebx);
1062 env->regs[R_EDX] = tswapl(sc->edx);
1063 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001064 env->regs[R_EAX] = tswapl(sc->eax);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001065 env->eip = tswapl(sc->eip);
bellard66fb9762003-03-23 01:06:05 +00001066
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001067 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1068 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001069
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001070 tmpflags = tswapl(sc->eflags);
1071 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1072 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001073
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001074 fpstate_addr = tswapl(sc->fpstate);
1075 if (fpstate_addr != 0) {
1076 if (!access_ok(VERIFY_READ, fpstate_addr,
1077 sizeof(struct target_fpstate)))
1078 goto badframe;
1079 cpu_x86_frstor(env, fpstate_addr, 1);
1080 }
bellard66fb9762003-03-23 01:06:05 +00001081
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001082 return err;
bellard66fb9762003-03-23 01:06:05 +00001083badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001084 return 1;
bellard66fb9762003-03-23 01:06:05 +00001085}
1086
1087long do_sigreturn(CPUX86State *env)
1088{
bellard579a97f2007-11-11 14:26:47 +00001089 struct sigframe *frame;
1090 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001091 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001092 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001093 int i;
bellard66fb9762003-03-23 01:06:05 +00001094
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001095 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001096 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1097 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001098 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001099 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001100 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001101 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001102 }
bellard66fb9762003-03-23 01:06:05 +00001103
bellard92319442004-06-19 16:58:13 +00001104 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001105 set_sigmask(&set);
ths3b46e622007-09-17 08:09:54 +00001106
bellard66fb9762003-03-23 01:06:05 +00001107 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001108 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001109 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001110 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001111 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001112
1113badframe:
bellard579a97f2007-11-11 14:26:47 +00001114 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001115 force_sig(TARGET_SIGSEGV);
1116 return 0;
1117}
1118
1119long do_rt_sigreturn(CPUX86State *env)
1120{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001121 abi_ulong frame_addr;
1122 struct rt_sigframe *frame;
1123 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001124
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001125 frame_addr = env->regs[R_ESP] - 4;
1126 trace_user_do_rt_sigreturn(env, frame_addr);
1127 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1128 goto badframe;
1129 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001130 set_sigmask(&set);
ths5fafdf22007-09-16 21:08:06 +00001131
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001132 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001133 goto badframe;
1134 }
bellard66fb9762003-03-23 01:06:05 +00001135
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001136 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1137 get_sp_from_cpustate(env)) == -EFAULT) {
1138 goto badframe;
1139 }
thsa04e1342007-09-27 13:57:58 +00001140
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001141 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001142 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001143
1144badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001145 unlock_user_struct(frame, frame_addr, 0);
1146 force_sig(TARGET_SIGSEGV);
1147 return 0;
bellard66fb9762003-03-23 01:06:05 +00001148}
1149
Andreas Schwab1744aea2013-09-03 20:12:16 +01001150#elif defined(TARGET_AARCH64)
1151
1152struct target_sigcontext {
1153 uint64_t fault_address;
1154 /* AArch64 registers */
1155 uint64_t regs[31];
1156 uint64_t sp;
1157 uint64_t pc;
1158 uint64_t pstate;
1159 /* 4K reserved for FP/SIMD state and future expansion */
1160 char __reserved[4096] __attribute__((__aligned__(16)));
1161};
1162
1163struct target_ucontext {
1164 abi_ulong tuc_flags;
1165 abi_ulong tuc_link;
1166 target_stack_t tuc_stack;
1167 target_sigset_t tuc_sigmask;
1168 /* glibc uses a 1024-bit sigset_t */
1169 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1170 /* last for future expansion */
1171 struct target_sigcontext tuc_mcontext;
1172};
1173
1174/*
1175 * Header to be used at the beginning of structures extending the user
1176 * context. Such structures must be placed after the rt_sigframe on the stack
1177 * and be 16-byte aligned. The last structure must be a dummy one with the
1178 * magic and size set to 0.
1179 */
1180struct target_aarch64_ctx {
1181 uint32_t magic;
1182 uint32_t size;
1183};
1184
1185#define TARGET_FPSIMD_MAGIC 0x46508001
1186
1187struct target_fpsimd_context {
1188 struct target_aarch64_ctx head;
1189 uint32_t fpsr;
1190 uint32_t fpcr;
1191 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1192};
1193
1194/*
1195 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1196 * user space as it will change with the addition of new context. User space
1197 * should check the magic/size information.
1198 */
1199struct target_aux_context {
1200 struct target_fpsimd_context fpsimd;
1201 /* additional context to be added before "end" */
1202 struct target_aarch64_ctx end;
1203};
1204
1205struct target_rt_sigframe {
1206 struct target_siginfo info;
1207 struct target_ucontext uc;
1208 uint64_t fp;
1209 uint64_t lr;
1210 uint32_t tramp[2];
1211};
1212
1213static int target_setup_sigframe(struct target_rt_sigframe *sf,
1214 CPUARMState *env, target_sigset_t *set)
1215{
1216 int i;
1217 struct target_aux_context *aux =
1218 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1219
1220 /* set up the stack frame for unwinding */
1221 __put_user(env->xregs[29], &sf->fp);
1222 __put_user(env->xregs[30], &sf->lr);
1223
1224 for (i = 0; i < 31; i++) {
1225 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1226 }
1227 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1228 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001229 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001230
Peter Maydell7af03922014-05-01 18:36:17 +01001231 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001232
1233 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1234 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1235 }
1236
1237 for (i = 0; i < 32; i++) {
1238#ifdef TARGET_WORDS_BIGENDIAN
1239 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1240 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1241#else
1242 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1243 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1244#endif
1245 }
Will Newtone0ee1382014-01-04 22:15:48 +00001246 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1247 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001248 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1249 __put_user(sizeof(struct target_fpsimd_context),
1250 &aux->fpsimd.head.size);
1251
1252 /* set the "end" magic */
1253 __put_user(0, &aux->end.magic);
1254 __put_user(0, &aux->end.size);
1255
1256 return 0;
1257}
1258
1259static int target_restore_sigframe(CPUARMState *env,
1260 struct target_rt_sigframe *sf)
1261{
1262 sigset_t set;
1263 int i;
1264 struct target_aux_context *aux =
1265 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
Will Newtone0ee1382014-01-04 22:15:48 +00001266 uint32_t magic, size, fpsr, fpcr;
Peter Maydelld3563122013-12-17 19:42:30 +00001267 uint64_t pstate;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001268
1269 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001270 set_sigmask(&set);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001271
1272 for (i = 0; i < 31; i++) {
1273 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1274 }
1275
1276 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1277 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001278 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1279 pstate_write(env, pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001280
1281 __get_user(magic, &aux->fpsimd.head.magic);
1282 __get_user(size, &aux->fpsimd.head.size);
1283
1284 if (magic != TARGET_FPSIMD_MAGIC
1285 || size != sizeof(struct target_fpsimd_context)) {
1286 return 1;
1287 }
1288
Peter Maydell4cf23482014-03-02 19:36:38 +00001289 for (i = 0; i < 32; i++) {
1290#ifdef TARGET_WORDS_BIGENDIAN
1291 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1292 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1293#else
1294 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1295 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1296#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001297 }
Will Newtone0ee1382014-01-04 22:15:48 +00001298 __get_user(fpsr, &aux->fpsimd.fpsr);
1299 vfp_set_fpsr(env, fpsr);
1300 __get_user(fpcr, &aux->fpsimd.fpcr);
1301 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001302
1303 return 0;
1304}
1305
1306static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1307{
1308 abi_ulong sp;
1309
1310 sp = env->xregs[31];
1311
1312 /*
1313 * This is the X/Open sanctioned signal stack switching.
1314 */
Riku Voipiob545f632014-07-15 17:01:55 +03001315 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001316 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1317 }
1318
1319 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1320
1321 return sp;
1322}
1323
1324static void target_setup_frame(int usig, struct target_sigaction *ka,
1325 target_siginfo_t *info, target_sigset_t *set,
1326 CPUARMState *env)
1327{
1328 struct target_rt_sigframe *frame;
Michael Matz8a3ae912014-03-02 19:36:39 +00001329 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001330
1331 frame_addr = get_sigframe(ka, env);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001332 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001333 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1334 goto give_sigsegv;
1335 }
1336
1337 __put_user(0, &frame->uc.tuc_flags);
1338 __put_user(0, &frame->uc.tuc_link);
1339
1340 __put_user(target_sigaltstack_used.ss_sp,
1341 &frame->uc.tuc_stack.ss_sp);
1342 __put_user(sas_ss_flags(env->xregs[31]),
1343 &frame->uc.tuc_stack.ss_flags);
1344 __put_user(target_sigaltstack_used.ss_size,
1345 &frame->uc.tuc_stack.ss_size);
1346 target_setup_sigframe(frame, env, set);
Michael Matz8a3ae912014-03-02 19:36:39 +00001347 if (ka->sa_flags & TARGET_SA_RESTORER) {
1348 return_addr = ka->sa_restorer;
1349 } else {
1350 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1351 __put_user(0xd2801168, &frame->tramp[0]);
1352 __put_user(0xd4000001, &frame->tramp[1]);
1353 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1354 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001355 env->xregs[0] = usig;
1356 env->xregs[31] = frame_addr;
1357 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1358 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001359 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001360 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001361 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001362 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1363 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1364 }
1365
1366 unlock_user_struct(frame, frame_addr, 1);
1367 return;
1368
1369 give_sigsegv:
1370 unlock_user_struct(frame, frame_addr, 1);
1371 force_sig(TARGET_SIGSEGV);
1372}
1373
1374static void setup_rt_frame(int sig, struct target_sigaction *ka,
1375 target_siginfo_t *info, target_sigset_t *set,
1376 CPUARMState *env)
1377{
1378 target_setup_frame(sig, ka, info, set, env);
1379}
1380
1381static void setup_frame(int sig, struct target_sigaction *ka,
1382 target_sigset_t *set, CPUARMState *env)
1383{
1384 target_setup_frame(sig, ka, 0, set, env);
1385}
1386
1387long do_rt_sigreturn(CPUARMState *env)
1388{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001389 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001390 abi_ulong frame_addr = env->xregs[31];
1391
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001392 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001393 if (frame_addr & 15) {
1394 goto badframe;
1395 }
1396
1397 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1398 goto badframe;
1399 }
1400
1401 if (target_restore_sigframe(env, frame)) {
1402 goto badframe;
1403 }
1404
1405 if (do_sigaltstack(frame_addr +
1406 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1407 0, get_sp_from_cpustate(env)) == -EFAULT) {
1408 goto badframe;
1409 }
1410
1411 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001412 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001413
1414 badframe:
1415 unlock_user_struct(frame, frame_addr, 0);
1416 force_sig(TARGET_SIGSEGV);
1417 return 0;
1418}
1419
1420long do_sigreturn(CPUARMState *env)
1421{
1422 return do_rt_sigreturn(env);
1423}
1424
bellard43fff232003-07-09 19:31:39 +00001425#elif defined(TARGET_ARM)
1426
1427struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001428 abi_ulong trap_no;
1429 abi_ulong error_code;
1430 abi_ulong oldmask;
1431 abi_ulong arm_r0;
1432 abi_ulong arm_r1;
1433 abi_ulong arm_r2;
1434 abi_ulong arm_r3;
1435 abi_ulong arm_r4;
1436 abi_ulong arm_r5;
1437 abi_ulong arm_r6;
1438 abi_ulong arm_r7;
1439 abi_ulong arm_r8;
1440 abi_ulong arm_r9;
1441 abi_ulong arm_r10;
1442 abi_ulong arm_fp;
1443 abi_ulong arm_ip;
1444 abi_ulong arm_sp;
1445 abi_ulong arm_lr;
1446 abi_ulong arm_pc;
1447 abi_ulong arm_cpsr;
1448 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001449};
1450
pbrooka745ec62008-05-06 15:36:17 +00001451struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001452 abi_ulong tuc_flags;
1453 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001454 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001455 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001456 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001457};
1458
pbrooka745ec62008-05-06 15:36:17 +00001459struct target_ucontext_v2 {
1460 abi_ulong tuc_flags;
1461 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001462 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001463 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001464 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001465 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001466 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1467};
1468
Peter Maydell0d871bd2010-11-24 15:20:05 +00001469struct target_user_vfp {
1470 uint64_t fpregs[32];
1471 abi_ulong fpscr;
1472};
1473
1474struct target_user_vfp_exc {
1475 abi_ulong fpexc;
1476 abi_ulong fpinst;
1477 abi_ulong fpinst2;
1478};
1479
1480struct target_vfp_sigframe {
1481 abi_ulong magic;
1482 abi_ulong size;
1483 struct target_user_vfp ufp;
1484 struct target_user_vfp_exc ufp_exc;
1485} __attribute__((__aligned__(8)));
1486
Peter Maydell08e11252010-11-24 15:20:07 +00001487struct target_iwmmxt_sigframe {
1488 abi_ulong magic;
1489 abi_ulong size;
1490 uint64_t regs[16];
1491 /* Note that not all the coprocessor control registers are stored here */
1492 uint32_t wcssf;
1493 uint32_t wcasf;
1494 uint32_t wcgr0;
1495 uint32_t wcgr1;
1496 uint32_t wcgr2;
1497 uint32_t wcgr3;
1498} __attribute__((__aligned__(8)));
1499
Peter Maydell0d871bd2010-11-24 15:20:05 +00001500#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001501#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001502
pbrooka8c33202008-05-07 23:22:46 +00001503struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001504{
1505 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001506 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1507 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001508};
1509
pbrooka8c33202008-05-07 23:22:46 +00001510struct sigframe_v2
1511{
1512 struct target_ucontext_v2 uc;
1513 abi_ulong retcode;
1514};
1515
pbrooka745ec62008-05-06 15:36:17 +00001516struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001517{
bellardf8b0aa22007-11-11 23:03:42 +00001518 abi_ulong pinfo;
1519 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001520 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001521 struct target_ucontext_v1 uc;
1522 abi_ulong retcode;
1523};
1524
1525struct rt_sigframe_v2
1526{
1527 struct target_siginfo info;
1528 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001529 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001530};
1531
1532#define TARGET_CONFIG_CPU_32 1
1533
1534/*
1535 * For ARM syscalls, we encode the syscall number into the instruction.
1536 */
1537#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1538#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1539
1540/*
1541 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1542 * need two 16-bit instructions.
1543 */
1544#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1545#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1546
blueswir1992f48a2007-10-14 16:27:31 +00001547static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001548 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1549 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1550};
1551
1552
Andreas Färber05390242012-02-25 03:37:53 +01001553static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001554{
1555 return 1;
1556}
1557
pbrooka8c33202008-05-07 23:22:46 +00001558static void
bellard43fff232003-07-09 19:31:39 +00001559setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001560 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001561{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001562 __put_user(env->regs[0], &sc->arm_r0);
1563 __put_user(env->regs[1], &sc->arm_r1);
1564 __put_user(env->regs[2], &sc->arm_r2);
1565 __put_user(env->regs[3], &sc->arm_r3);
1566 __put_user(env->regs[4], &sc->arm_r4);
1567 __put_user(env->regs[5], &sc->arm_r5);
1568 __put_user(env->regs[6], &sc->arm_r6);
1569 __put_user(env->regs[7], &sc->arm_r7);
1570 __put_user(env->regs[8], &sc->arm_r8);
1571 __put_user(env->regs[9], &sc->arm_r9);
1572 __put_user(env->regs[10], &sc->arm_r10);
1573 __put_user(env->regs[11], &sc->arm_fp);
1574 __put_user(env->regs[12], &sc->arm_ip);
1575 __put_user(env->regs[13], &sc->arm_sp);
1576 __put_user(env->regs[14], &sc->arm_lr);
1577 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001578#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001579 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001580#endif
1581
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001582 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1583 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1584 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1585 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001586}
1587
bellard579a97f2007-11-11 14:26:47 +00001588static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001589get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001590{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001591 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00001592
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001593 /*
1594 * This is the X/Open sanctioned signal stack switching.
1595 */
1596 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1597 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1598 }
1599 /*
1600 * ATPCS B01 mandates 8-byte alignment
1601 */
1602 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001603}
1604
Riku Voipio0188fad2014-04-23 13:34:15 +03001605static void
Andreas Färber05390242012-02-25 03:37:53 +01001606setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001607 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001608{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001609 abi_ulong handler = ka->_sa_handler;
1610 abi_ulong retcode;
1611 int thumb = handler & 1;
1612 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01001613
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001614 cpsr &= ~CPSR_IT;
1615 if (thumb) {
1616 cpsr |= CPSR_T;
1617 } else {
1618 cpsr &= ~CPSR_T;
1619 }
bellard43fff232003-07-09 19:31:39 +00001620
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001621 if (ka->sa_flags & TARGET_SA_RESTORER) {
1622 retcode = ka->sa_restorer;
1623 } else {
1624 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00001625
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001626 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1627 idx += 2;
1628 }
bellard43fff232003-07-09 19:31:39 +00001629
Riku Voipio0188fad2014-04-23 13:34:15 +03001630 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001631
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001632 retcode = rc_addr + thumb;
1633 }
bellard43fff232003-07-09 19:31:39 +00001634
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001635 env->regs[0] = usig;
1636 env->regs[13] = frame_addr;
1637 env->regs[14] = retcode;
1638 env->regs[15] = handler & (thumb ? ~1 : ~3);
1639 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001640}
1641
Andreas Färber05390242012-02-25 03:37:53 +01001642static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001643{
1644 int i;
1645 struct target_vfp_sigframe *vfpframe;
1646 vfpframe = (struct target_vfp_sigframe *)regspace;
1647 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1648 __put_user(sizeof(*vfpframe), &vfpframe->size);
1649 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001650 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001651 }
1652 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1653 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1654 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1655 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1656 return (abi_ulong*)(vfpframe+1);
1657}
1658
Andreas Färber05390242012-02-25 03:37:53 +01001659static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1660 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001661{
1662 int i;
1663 struct target_iwmmxt_sigframe *iwmmxtframe;
1664 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1665 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1666 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1667 for (i = 0; i < 16; i++) {
1668 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1669 }
1670 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1671 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1672 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1673 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1674 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1675 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1676 return (abi_ulong*)(iwmmxtframe+1);
1677}
1678
pbrooka8c33202008-05-07 23:22:46 +00001679static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001680 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001681{
pbrooka8c33202008-05-07 23:22:46 +00001682 struct target_sigaltstack stack;
1683 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001684 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001685
1686 /* Clear all the bits of the ucontext we don't use. */
1687 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1688
1689 memset(&stack, 0, sizeof(stack));
1690 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1691 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1692 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1693 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1694
1695 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001696 /* Save coprocessor signal frame. */
1697 regspace = uc->tuc_regspace;
1698 if (arm_feature(env, ARM_FEATURE_VFP)) {
1699 regspace = setup_sigframe_v2_vfp(regspace, env);
1700 }
Peter Maydell08e11252010-11-24 15:20:07 +00001701 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1702 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1703 }
1704
Peter Maydell0d871bd2010-11-24 15:20:05 +00001705 /* Write terminating magic word */
1706 __put_user(0, regspace);
1707
pbrooka8c33202008-05-07 23:22:46 +00001708 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1709 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1710 }
1711}
1712
1713/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001714static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001715 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001716{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001717 struct sigframe_v1 *frame;
1718 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1719 int i;
bellard43fff232003-07-09 19:31:39 +00001720
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001721 trace_user_setup_frame(regs, frame_addr);
1722 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1723 return;
1724 }
bellard579a97f2007-11-11 14:26:47 +00001725
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001726 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00001727
Riku Voipio0188fad2014-04-23 13:34:15 +03001728 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1729 __put_user(set->sig[i], &frame->extramask[i - 1]);
1730 }
bellard43fff232003-07-09 19:31:39 +00001731
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001732 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1733 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00001734
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001735 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001736}
1737
pbrook624f7972008-05-31 16:11:38 +00001738static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001739 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001740{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001741 struct sigframe_v2 *frame;
1742 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00001743
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001744 trace_user_setup_frame(regs, frame_addr);
1745 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1746 return;
1747 }
pbrooka8c33202008-05-07 23:22:46 +00001748
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001749 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00001750
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001751 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1752 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00001753
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001754 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001755}
1756
pbrook624f7972008-05-31 16:11:38 +00001757static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001758 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001759{
1760 if (get_osversion() >= 0x020612) {
1761 setup_frame_v2(usig, ka, set, regs);
1762 } else {
1763 setup_frame_v1(usig, ka, set, regs);
1764 }
bellard43fff232003-07-09 19:31:39 +00001765}
1766
bellard579a97f2007-11-11 14:26:47 +00001767/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001768static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001769 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001770 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001771{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001772 struct rt_sigframe_v1 *frame;
1773 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1774 struct target_sigaltstack stack;
1775 int i;
1776 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00001777
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001778 trace_user_setup_rt_frame(env, frame_addr);
1779 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1780 return /* 1 */;
1781 }
bellardedf779f2004-02-22 13:40:13 +00001782
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001783 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1784 __put_user(info_addr, &frame->pinfo);
1785 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1786 __put_user(uc_addr, &frame->puc);
1787 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00001788
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001789 /* Clear all the bits of the ucontext we don't use. */
1790 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00001791
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001792 memset(&stack, 0, sizeof(stack));
1793 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1794 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1795 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1796 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00001797
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001798 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1799 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1800 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1801 }
bellard43fff232003-07-09 19:31:39 +00001802
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001803 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1804 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001805
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001806 env->regs[1] = info_addr;
1807 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001808
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001809 unlock_user_struct(frame, frame_addr, 1);
pbrooka745ec62008-05-06 15:36:17 +00001810}
1811
pbrook624f7972008-05-31 16:11:38 +00001812static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001813 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001814 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001815{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001816 struct rt_sigframe_v2 *frame;
1817 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1818 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001819
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001820 trace_user_setup_rt_frame(env, frame_addr);
1821 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1822 return /* 1 */;
1823 }
pbrooka745ec62008-05-06 15:36:17 +00001824
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001825 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1826 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1827 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00001828
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001829 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00001830
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001831 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1832 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001833
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001834 env->regs[1] = info_addr;
1835 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001836
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001837 unlock_user_struct(frame, frame_addr, 1);
bellard43fff232003-07-09 19:31:39 +00001838}
1839
pbrook624f7972008-05-31 16:11:38 +00001840static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001841 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001842 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001843{
1844 if (get_osversion() >= 0x020612) {
1845 setup_rt_frame_v2(usig, ka, info, set, env);
1846 } else {
1847 setup_rt_frame_v1(usig, ka, info, set, env);
1848 }
1849}
1850
bellard43fff232003-07-09 19:31:39 +00001851static int
Andreas Färber05390242012-02-25 03:37:53 +01001852restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00001853{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001854 int err = 0;
1855 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00001856
Riku Voipio1d8b5122014-04-23 10:26:05 +03001857 __get_user(env->regs[0], &sc->arm_r0);
1858 __get_user(env->regs[1], &sc->arm_r1);
1859 __get_user(env->regs[2], &sc->arm_r2);
1860 __get_user(env->regs[3], &sc->arm_r3);
1861 __get_user(env->regs[4], &sc->arm_r4);
1862 __get_user(env->regs[5], &sc->arm_r5);
1863 __get_user(env->regs[6], &sc->arm_r6);
1864 __get_user(env->regs[7], &sc->arm_r7);
1865 __get_user(env->regs[8], &sc->arm_r8);
1866 __get_user(env->regs[9], &sc->arm_r9);
1867 __get_user(env->regs[10], &sc->arm_r10);
1868 __get_user(env->regs[11], &sc->arm_fp);
1869 __get_user(env->regs[12], &sc->arm_ip);
1870 __get_user(env->regs[13], &sc->arm_sp);
1871 __get_user(env->regs[14], &sc->arm_lr);
1872 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001873#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03001874 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00001875 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001876#endif
1877
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001878 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00001879
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001880 return err;
bellard43fff232003-07-09 19:31:39 +00001881}
1882
Andreas Färber05390242012-02-25 03:37:53 +01001883static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001884{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001885 abi_ulong frame_addr;
1886 struct sigframe_v1 *frame = NULL;
1887 target_sigset_t set;
1888 sigset_t host_set;
1889 int i;
bellard43fff232003-07-09 19:31:39 +00001890
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001891 /*
1892 * Since we stacked the signal on a 64-bit boundary,
1893 * then 'sp' should be word aligned here. If it's
1894 * not, then the user is trying to mess with us.
1895 */
1896 frame_addr = env->regs[13];
1897 trace_user_do_sigreturn(env, frame_addr);
1898 if (frame_addr & 7) {
1899 goto badframe;
1900 }
Peter Maydell978fae92013-07-29 12:00:32 +01001901
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001902 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1903 goto badframe;
1904 }
bellard43fff232003-07-09 19:31:39 +00001905
Riku Voipiof5f601a2014-04-23 13:00:17 +03001906 __get_user(set.sig[0], &frame->sc.oldmask);
1907 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1908 __get_user(set.sig[i], &frame->extramask[i - 1]);
1909 }
bellard43fff232003-07-09 19:31:39 +00001910
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001911 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001912 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00001913
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001914 if (restore_sigcontext(env, &frame->sc)) {
1915 goto badframe;
1916 }
bellard43fff232003-07-09 19:31:39 +00001917
1918#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001919 /* Send SIGTRAP if we're single-stepping */
1920 if (ptrace_cancel_bpt(current))
1921 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00001922#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001923 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001924 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00001925
1926badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001927 force_sig(TARGET_SIGSEGV /* , current */);
1928 return 0;
bellard43fff232003-07-09 19:31:39 +00001929}
1930
Andreas Färber05390242012-02-25 03:37:53 +01001931static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00001932{
1933 int i;
1934 abi_ulong magic, sz;
1935 uint32_t fpscr, fpexc;
1936 struct target_vfp_sigframe *vfpframe;
1937 vfpframe = (struct target_vfp_sigframe *)regspace;
1938
1939 __get_user(magic, &vfpframe->magic);
1940 __get_user(sz, &vfpframe->size);
1941 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1942 return 0;
1943 }
1944 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001945 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00001946 }
1947 __get_user(fpscr, &vfpframe->ufp.fpscr);
1948 vfp_set_fpscr(env, fpscr);
1949 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1950 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1951 * and the exception flag is cleared
1952 */
1953 fpexc |= (1 << 30);
1954 fpexc &= ~((1 << 31) | (1 << 28));
1955 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1956 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1957 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1958 return (abi_ulong*)(vfpframe + 1);
1959}
1960
Andreas Färber05390242012-02-25 03:37:53 +01001961static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
1962 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00001963{
1964 int i;
1965 abi_ulong magic, sz;
1966 struct target_iwmmxt_sigframe *iwmmxtframe;
1967 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1968
1969 __get_user(magic, &iwmmxtframe->magic);
1970 __get_user(sz, &iwmmxtframe->size);
1971 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
1972 return 0;
1973 }
1974 for (i = 0; i < 16; i++) {
1975 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1976 }
1977 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1978 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1979 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1980 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1981 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1982 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1983 return (abi_ulong*)(iwmmxtframe + 1);
1984}
1985
Andreas Färber05390242012-02-25 03:37:53 +01001986static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
pbrooka8c33202008-05-07 23:22:46 +00001987 struct target_ucontext_v2 *uc)
1988{
1989 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00001990 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001991
1992 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01001993 set_sigmask(&host_set);
pbrooka8c33202008-05-07 23:22:46 +00001994
1995 if (restore_sigcontext(env, &uc->tuc_mcontext))
1996 return 1;
1997
Peter Maydell5f9099d2010-11-24 15:20:06 +00001998 /* Restore coprocessor signal frame */
1999 regspace = uc->tuc_regspace;
2000 if (arm_feature(env, ARM_FEATURE_VFP)) {
2001 regspace = restore_sigframe_v2_vfp(env, regspace);
2002 if (!regspace) {
2003 return 1;
2004 }
2005 }
Peter Maydella59d69d2010-11-24 15:20:08 +00002006 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2007 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2008 if (!regspace) {
2009 return 1;
2010 }
2011 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002012
pbrooka8c33202008-05-07 23:22:46 +00002013 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2014 return 1;
2015
2016#if 0
2017 /* Send SIGTRAP if we're single-stepping */
2018 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002019 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002020#endif
2021
2022 return 0;
2023}
2024
Andreas Färber05390242012-02-25 03:37:53 +01002025static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002026{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002027 abi_ulong frame_addr;
2028 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002029
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002030 /*
2031 * Since we stacked the signal on a 64-bit boundary,
2032 * then 'sp' should be word aligned here. If it's
2033 * not, then the user is trying to mess with us.
2034 */
2035 frame_addr = env->regs[13];
2036 trace_user_do_sigreturn(env, frame_addr);
2037 if (frame_addr & 7) {
2038 goto badframe;
2039 }
Peter Maydell978fae92013-07-29 12:00:32 +01002040
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002041 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2042 goto badframe;
2043 }
pbrooka8c33202008-05-07 23:22:46 +00002044
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002045 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2046 goto badframe;
2047 }
pbrooka8c33202008-05-07 23:22:46 +00002048
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002049 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002050 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002051
2052badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002053 unlock_user_struct(frame, frame_addr, 0);
2054 force_sig(TARGET_SIGSEGV /* , current */);
2055 return 0;
pbrooka8c33202008-05-07 23:22:46 +00002056}
2057
Andreas Färber05390242012-02-25 03:37:53 +01002058long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002059{
2060 if (get_osversion() >= 0x020612) {
2061 return do_sigreturn_v2(env);
2062 } else {
2063 return do_sigreturn_v1(env);
2064 }
2065}
2066
Andreas Färber05390242012-02-25 03:37:53 +01002067static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002068{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002069 abi_ulong frame_addr;
2070 struct rt_sigframe_v1 *frame = NULL;
2071 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002072
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002073 /*
2074 * Since we stacked the signal on a 64-bit boundary,
2075 * then 'sp' should be word aligned here. If it's
2076 * not, then the user is trying to mess with us.
2077 */
2078 frame_addr = env->regs[13];
2079 trace_user_do_rt_sigreturn(env, frame_addr);
2080 if (frame_addr & 7) {
2081 goto badframe;
2082 }
Peter Maydell978fae92013-07-29 12:00:32 +01002083
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002084 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2085 goto badframe;
2086 }
bellard43fff232003-07-09 19:31:39 +00002087
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002088 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002089 set_sigmask(&host_set);
bellard43fff232003-07-09 19:31:39 +00002090
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002091 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2092 goto badframe;
2093 }
bellard43fff232003-07-09 19:31:39 +00002094
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002095 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2096 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002097
bellard43fff232003-07-09 19:31:39 +00002098#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002099 /* Send SIGTRAP if we're single-stepping */
2100 if (ptrace_cancel_bpt(current))
2101 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002102#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002103 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002104 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002105
2106badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002107 unlock_user_struct(frame, frame_addr, 0);
2108 force_sig(TARGET_SIGSEGV /* , current */);
2109 return 0;
bellard43fff232003-07-09 19:31:39 +00002110}
2111
Andreas Färber05390242012-02-25 03:37:53 +01002112static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002113{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002114 abi_ulong frame_addr;
2115 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002116
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002117 /*
2118 * Since we stacked the signal on a 64-bit boundary,
2119 * then 'sp' should be word aligned here. If it's
2120 * not, then the user is trying to mess with us.
2121 */
2122 frame_addr = env->regs[13];
2123 trace_user_do_rt_sigreturn(env, frame_addr);
2124 if (frame_addr & 7) {
2125 goto badframe;
2126 }
Peter Maydell978fae92013-07-29 12:00:32 +01002127
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002128 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2129 goto badframe;
2130 }
pbrooka745ec62008-05-06 15:36:17 +00002131
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002132 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2133 goto badframe;
2134 }
pbrooka745ec62008-05-06 15:36:17 +00002135
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002136 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002137 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002138
2139badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002140 unlock_user_struct(frame, frame_addr, 0);
2141 force_sig(TARGET_SIGSEGV /* , current */);
2142 return 0;
pbrooka745ec62008-05-06 15:36:17 +00002143}
2144
Andreas Färber05390242012-02-25 03:37:53 +01002145long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002146{
2147 if (get_osversion() >= 0x020612) {
2148 return do_rt_sigreturn_v2(env);
2149 } else {
2150 return do_rt_sigreturn_v1(env);
2151 }
2152}
2153
bellard6d5e2162004-09-30 22:04:13 +00002154#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002155
bellard6d5e2162004-09-30 22:04:13 +00002156#define __SUNOS_MAXWIN 31
2157
2158/* This is what SunOS does, so shall I. */
2159struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002160 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002161
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002162 abi_ulong sigc_mask; /* sigmask to restore */
2163 abi_ulong sigc_sp; /* stack pointer */
2164 abi_ulong sigc_pc; /* program counter */
2165 abi_ulong sigc_npc; /* next program counter */
2166 abi_ulong sigc_psr; /* for condition codes etc */
2167 abi_ulong sigc_g1; /* User uses these two registers */
2168 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002169
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002170 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002171 * at the time of the signal.
2172 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002173 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002174
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002175 /* stack ptrs for each regwin buf */
2176 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002177
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002178 /* Windows to restore after signal */
2179 struct {
2180 abi_ulong locals[8];
2181 abi_ulong ins[8];
2182 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002183};
2184/* A Sparc stack frame */
2185struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002186 abi_ulong locals[8];
2187 abi_ulong ins[8];
2188 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002189 * since we never need to access them ourselves.
2190 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002191 char *structptr;
2192 abi_ulong xargs[6];
2193 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002194};
2195
2196typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002197 struct {
2198 abi_ulong psr;
2199 abi_ulong pc;
2200 abi_ulong npc;
2201 abi_ulong y;
2202 abi_ulong u_regs[16]; /* globals and ins */
2203 } si_regs;
2204 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002205} __siginfo_t;
2206
2207typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002208 abi_ulong si_float_regs[32];
2209 unsigned long si_fsr;
2210 unsigned long si_fpqdepth;
2211 struct {
2212 unsigned long *insn_addr;
2213 unsigned long insn;
2214 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002215} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002216
2217
2218struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002219 struct sparc_stackf ss;
2220 __siginfo_t info;
2221 abi_ulong fpu_save;
2222 abi_ulong insns[2] __attribute__ ((aligned (8)));
2223 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2224 abi_ulong extra_size; /* Should be 0 */
2225 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002226};
2227struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002228 struct sparc_stackf ss;
2229 siginfo_t info;
2230 abi_ulong regs[20];
2231 sigset_t mask;
2232 abi_ulong fpu_save;
2233 unsigned int insns[2];
2234 stack_t stack;
2235 unsigned int extra_size; /* Should be 0 */
2236 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002237};
2238
bellarde80cfcf2004-12-19 23:18:01 +00002239#define UREG_O0 16
2240#define UREG_O6 22
2241#define UREG_I0 0
2242#define UREG_I1 1
2243#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002244#define UREG_I3 3
2245#define UREG_I4 4
2246#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002247#define UREG_I6 6
2248#define UREG_I7 7
2249#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002250#define UREG_FP UREG_I6
2251#define UREG_SP UREG_O6
2252
pbrook624f7972008-05-31 16:11:38 +00002253static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002254 CPUSPARCState *env,
2255 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002256{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002257 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002258
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002259 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002260
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002261 /* This is the X/Open sanctioned signal stack switching. */
2262 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2263 if (!on_sig_stack(sp)
2264 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2265 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2266 }
2267 }
2268 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002269}
2270
2271static int
Andreas Färber05390242012-02-25 03:37:53 +01002272setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002273{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002274 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002275
Riku Voipio1d8b5122014-04-23 10:26:05 +03002276 __put_user(env->psr, &si->si_regs.psr);
2277 __put_user(env->pc, &si->si_regs.pc);
2278 __put_user(env->npc, &si->si_regs.npc);
2279 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002280 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002281 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002282 }
2283 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002284 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002285 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002286 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002287 return err;
bellard6d5e2162004-09-30 22:04:13 +00002288}
bellarde80cfcf2004-12-19 23:18:01 +00002289
bellard80a9d032005-01-03 23:31:27 +00002290#if 0
bellard6d5e2162004-09-30 22:04:13 +00002291static int
2292setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002293 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002294{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002295 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002296
Riku Voipio1d8b5122014-04-23 10:26:05 +03002297 __put_user(mask, &sc->sigc_mask);
2298 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2299 __put_user(env->pc, &sc->sigc_pc);
2300 __put_user(env->npc, &sc->sigc_npc);
2301 __put_user(env->psr, &sc->sigc_psr);
2302 __put_user(env->gregs[1], &sc->sigc_g1);
2303 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002304
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002305 return err;
bellard6d5e2162004-09-30 22:04:13 +00002306}
bellard80a9d032005-01-03 23:31:27 +00002307#endif
bellard6d5e2162004-09-30 22:04:13 +00002308#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2309
pbrook624f7972008-05-31 16:11:38 +00002310static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002311 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002312{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002313 abi_ulong sf_addr;
2314 struct target_signal_frame *sf;
2315 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002316
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002317 /* 1. Make sure everything is clean */
2318 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002319
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002320 sigframe_size = NF_ALIGNEDSZ;
2321 sf_addr = get_sigframe(ka, env, sigframe_size);
2322 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002323
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002324 sf = lock_user(VERIFY_WRITE, sf_addr,
2325 sizeof(struct target_signal_frame), 0);
2326 if (!sf) {
2327 goto sigsegv;
2328 }
bellard6d5e2162004-09-30 22:04:13 +00002329#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002330 if (invalid_frame_pointer(sf, sigframe_size))
2331 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002332#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002333 /* 2. Save the current process state */
2334 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002335 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002336
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002337 //save_fpu_state(regs, &sf->fpu_state);
2338 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002339
Riku Voipio1d8b5122014-04-23 10:26:05 +03002340 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002341 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002342 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002343 }
bellard6d5e2162004-09-30 22:04:13 +00002344
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002345 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002346 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002347 }
2348 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002349 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002350 }
2351 if (err)
2352 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002353
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002354 /* 3. signal handler back-trampoline and parameters */
2355 env->regwptr[UREG_FP] = sf_addr;
2356 env->regwptr[UREG_I0] = sig;
2357 env->regwptr[UREG_I1] = sf_addr +
2358 offsetof(struct target_signal_frame, info);
2359 env->regwptr[UREG_I2] = sf_addr +
2360 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002361
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002362 /* 4. signal handler */
2363 env->pc = ka->_sa_handler;
2364 env->npc = (env->pc + 4);
2365 /* 5. return to kernel instructions */
2366 if (ka->sa_restorer) {
2367 env->regwptr[UREG_I7] = ka->sa_restorer;
2368 } else {
2369 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002370
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002371 env->regwptr[UREG_I7] = sf_addr +
2372 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002373
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002374 /* mov __NR_sigreturn, %g1 */
2375 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002376 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002377
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002378 /* t 0x10 */
2379 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002380 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002381 if (err)
2382 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002383
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002384 /* Flush instruction space. */
2385 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2386 // tb_flush(env);
2387 }
2388 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2389 return;
bellard459a4012007-11-11 19:45:10 +00002390#if 0
2391sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002392 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002393#endif
bellard6d5e2162004-09-30 22:04:13 +00002394sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002395 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2396 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002397}
bellard6d5e2162004-09-30 22:04:13 +00002398
pbrook624f7972008-05-31 16:11:38 +00002399static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002400 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002401 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002402{
2403 fprintf(stderr, "setup_rt_frame: not implemented\n");
2404}
2405
Andreas Färber05390242012-02-25 03:37:53 +01002406long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002407{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002408 abi_ulong sf_addr;
2409 struct target_signal_frame *sf;
2410 uint32_t up_psr, pc, npc;
2411 target_sigset_t set;
2412 sigset_t host_set;
2413 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002414
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002415 sf_addr = env->regwptr[UREG_FP];
2416 trace_user_do_sigreturn(env, sf_addr);
2417 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2418 goto segv_and_exit;
2419 }
bellard6d5e2162004-09-30 22:04:13 +00002420
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002421 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002422
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002423 if (sf_addr & 3)
2424 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002425
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002426 __get_user(pc, &sf->info.si_regs.pc);
2427 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002428
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002429 if ((pc | npc) & 3) {
2430 goto segv_and_exit;
2431 }
bellard6d5e2162004-09-30 22:04:13 +00002432
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002433 /* 2. Restore the state */
2434 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002435
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002436 /* User can only change condition codes and FPU enabling in %psr. */
2437 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2438 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002439
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002440 env->pc = pc;
2441 env->npc = npc;
2442 __get_user(env->y, &sf->info.si_regs.y);
2443 for (i=0; i < 8; i++) {
2444 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2445 }
2446 for (i=0; i < 8; i++) {
2447 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2448 }
bellard6d5e2162004-09-30 22:04:13 +00002449
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002450 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002451 * __get_user(fpu_save, &sf->fpu_save);
2452 * if (fpu_save)
2453 * err |= restore_fpu_state(env, fpu_save);
2454 */
bellard6d5e2162004-09-30 22:04:13 +00002455
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002456 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00002457 * the races which exist anyways.
2458 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002459 __get_user(set.sig[0], &sf->info.si_mask);
2460 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2461 __get_user(set.sig[i], &sf->extramask[i - 1]);
2462 }
bellarde80cfcf2004-12-19 23:18:01 +00002463
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002464 target_to_host_sigset_internal(&host_set, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002465 set_sigmask(&host_set);
bellard6d5e2162004-09-30 22:04:13 +00002466
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002467 if (err) {
2468 goto segv_and_exit;
2469 }
2470 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01002471 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002472
2473segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002474 unlock_user_struct(sf, sf_addr, 0);
2475 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002476}
2477
Andreas Färber05390242012-02-25 03:37:53 +01002478long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002479{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002480 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00002481 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002482 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002483}
2484
bellard459a4012007-11-11 19:45:10 +00002485#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
blueswir15bfb56b2007-10-05 17:01:51 +00002486#define MC_TSTATE 0
2487#define MC_PC 1
2488#define MC_NPC 2
2489#define MC_Y 3
2490#define MC_G1 4
2491#define MC_G2 5
2492#define MC_G3 6
2493#define MC_G4 7
2494#define MC_G5 8
2495#define MC_G6 9
2496#define MC_G7 10
2497#define MC_O0 11
2498#define MC_O1 12
2499#define MC_O2 13
2500#define MC_O3 14
2501#define MC_O4 15
2502#define MC_O5 16
2503#define MC_O6 17
2504#define MC_O7 18
2505#define MC_NGREG 19
2506
Anthony Liguoric227f092009-10-01 16:12:16 -05002507typedef abi_ulong target_mc_greg_t;
2508typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002509
2510struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002511 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002512 uint32_t mcfq_insn;
2513};
2514
2515struct target_mc_fpu {
2516 union {
2517 uint32_t sregs[32];
2518 uint64_t dregs[32];
2519 //uint128_t qregs[16];
2520 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002521 abi_ulong mcfpu_fsr;
2522 abi_ulong mcfpu_fprs;
2523 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002524 struct target_mc_fq *mcfpu_fq;
2525 unsigned char mcfpu_qcnt;
2526 unsigned char mcfpu_qentsz;
2527 unsigned char mcfpu_enab;
2528};
Anthony Liguoric227f092009-10-01 16:12:16 -05002529typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002530
2531typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002532 target_mc_gregset_t mc_gregs;
2533 target_mc_greg_t mc_fp;
2534 target_mc_greg_t mc_i7;
2535 target_mc_fpu_t mc_fpregs;
2536} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002537
2538struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002539 struct target_ucontext *tuc_link;
2540 abi_ulong tuc_flags;
2541 target_sigset_t tuc_sigmask;
2542 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002543};
2544
2545/* A V9 register window */
2546struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002547 abi_ulong locals[8];
2548 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002549};
2550
2551#define TARGET_STACK_BIAS 2047
2552
2553/* {set, get}context() needed for 64-bit SparcLinux userland. */
2554void sparc64_set_context(CPUSPARCState *env)
2555{
bellard459a4012007-11-11 19:45:10 +00002556 abi_ulong ucp_addr;
2557 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002558 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002559 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002560 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002561 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002562
bellard459a4012007-11-11 19:45:10 +00002563 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002564 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00002565 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002566 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02002567 grp = &ucp->tuc_mcontext.mc_gregs;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002568 __get_user(pc, &((*grp)[MC_PC]));
2569 __get_user(npc, &((*grp)[MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002570 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00002571 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002572 }
blueswir15bfb56b2007-10-05 17:01:51 +00002573 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002574 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002575 sigset_t set;
2576
2577 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002578 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002579 } else {
bellard459a4012007-11-11 19:45:10 +00002580 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002581 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002582 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002583 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002584 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002585 }
blueswir15bfb56b2007-10-05 17:01:51 +00002586 }
2587 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01002588 set_sigmask(&set);
blueswir15bfb56b2007-10-05 17:01:51 +00002589 }
2590 env->pc = pc;
2591 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002592 __get_user(env->y, &((*grp)[MC_Y]));
2593 __get_user(tstate, &((*grp)[MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002594 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002595 cpu_put_ccr(env, tstate >> 32);
2596 cpu_put_cwp64(env, tstate & 0x1f);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002597 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2598 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2599 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2600 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2601 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2602 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2603 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2604 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2605 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2606 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2607 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2608 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2609 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2610 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2611 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002612
Riku Voipio1d8b5122014-04-23 10:26:05 +03002613 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2614 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002615
bellard459a4012007-11-11 19:45:10 +00002616 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002617 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2618 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002619 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002620 }
2621 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2622 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002623 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002624 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01002625 /* FIXME this does not match how the kernel handles the FPU in
2626 * its sparc64_set_context implementation. In particular the FPU
2627 * is only restored if fenab is non-zero in:
2628 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2629 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002630 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002631 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002632 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2633 for (i = 0; i < 64; i++, src++) {
2634 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002635 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002636 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002637 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002638 }
2639 }
bellard459a4012007-11-11 19:45:10 +00002640 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002641 __get_user(env->fsr,
2642 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2643 __get_user(env->gsr,
2644 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002645 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002646 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002647do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002648 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002649 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002650}
2651
2652void sparc64_get_context(CPUSPARCState *env)
2653{
bellard459a4012007-11-11 19:45:10 +00002654 abi_ulong ucp_addr;
2655 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002656 target_mc_gregset_t *grp;
2657 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002658 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002659 int err;
2660 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002661 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002662 sigset_t set;
2663
bellard459a4012007-11-11 19:45:10 +00002664 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002665 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00002666 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002667 }
bellard459a4012007-11-11 19:45:10 +00002668
Aurelien Jarno60e99242010-03-29 02:12:51 +02002669 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002670 grp = &mcp->mc_gregs;
2671
2672 /* Skip over the trap instruction, first. */
2673 env->pc = env->npc;
2674 env->npc += 4;
2675
2676 err = 0;
2677
Alex Barcelo1c275922014-03-14 14:36:55 +00002678 do_sigprocmask(0, NULL, &set);
blueswir15bfb56b2007-10-05 17:01:51 +00002679 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00002680 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002681 __put_user(target_set.sig[0],
2682 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00002683 } else {
2684 abi_ulong *src, *dst;
2685 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002686 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002687 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002688 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002689 }
blueswir15bfb56b2007-10-05 17:01:51 +00002690 if (err)
2691 goto do_sigsegv;
2692 }
2693
bellard459a4012007-11-11 19:45:10 +00002694 /* XXX: tstate must be saved properly */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002695 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2696 __put_user(env->pc, &((*grp)[MC_PC]));
2697 __put_user(env->npc, &((*grp)[MC_NPC]));
2698 __put_user(env->y, &((*grp)[MC_Y]));
2699 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2700 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2701 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2702 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2703 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2704 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2705 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2706 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2707 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2708 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2709 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2710 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2711 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2712 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2713 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002714
bellard459a4012007-11-11 19:45:10 +00002715 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2716 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002717 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2718 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002719 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002720 }
2721 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2722 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002723 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002724 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002725 __put_user(fp, &(mcp->mc_fp));
2726 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002727
bellard459a4012007-11-11 19:45:10 +00002728 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002729 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2730 for (i = 0; i < 64; i++, dst++) {
2731 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002732 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002733 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002734 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002735 }
2736 }
bellard459a4012007-11-11 19:45:10 +00002737 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002738 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2739 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2740 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00002741
2742 if (err)
2743 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00002744 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00002745 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002746do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002747 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02002748 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002749}
2750#endif
Richard Hendersonff970902013-02-10 10:30:42 -08002751#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00002752
Richard Hendersonff970902013-02-10 10:30:42 -08002753# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00002754struct target_sigcontext {
2755 uint32_t sc_regmask; /* Unused */
2756 uint32_t sc_status;
2757 uint64_t sc_pc;
2758 uint64_t sc_regs[32];
2759 uint64_t sc_fpregs[32];
2760 uint32_t sc_ownedfp; /* Unused */
2761 uint32_t sc_fpc_csr;
2762 uint32_t sc_fpc_eir; /* Unused */
2763 uint32_t sc_used_math;
2764 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01002765 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00002766 uint64_t sc_mdhi;
2767 uint64_t sc_mdlo;
2768 target_ulong sc_hi1; /* Was sc_cause */
2769 target_ulong sc_lo1; /* Was sc_badvaddr */
2770 target_ulong sc_hi2; /* Was sc_sigset[4] */
2771 target_ulong sc_lo2;
2772 target_ulong sc_hi3;
2773 target_ulong sc_lo3;
2774};
Richard Hendersonff970902013-02-10 10:30:42 -08002775# else /* N32 || N64 */
2776struct target_sigcontext {
2777 uint64_t sc_regs[32];
2778 uint64_t sc_fpregs[32];
2779 uint64_t sc_mdhi;
2780 uint64_t sc_hi1;
2781 uint64_t sc_hi2;
2782 uint64_t sc_hi3;
2783 uint64_t sc_mdlo;
2784 uint64_t sc_lo1;
2785 uint64_t sc_lo2;
2786 uint64_t sc_lo3;
2787 uint64_t sc_pc;
2788 uint32_t sc_fpc_csr;
2789 uint32_t sc_used_math;
2790 uint32_t sc_dsp;
2791 uint32_t sc_reserved;
2792};
2793# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00002794
2795struct sigframe {
2796 uint32_t sf_ass[4]; /* argument save space for o32 */
2797 uint32_t sf_code[2]; /* signal trampoline */
2798 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002799 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00002800};
2801
pbrook0b1bcb02009-04-21 01:41:10 +00002802struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002803 target_ulong tuc_flags;
2804 target_ulong tuc_link;
2805 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01002806 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002807 struct target_sigcontext tuc_mcontext;
2808 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00002809};
2810
2811struct target_rt_sigframe {
2812 uint32_t rs_ass[4]; /* argument save space for o32 */
2813 uint32_t rs_code[2]; /* signal trampoline */
2814 struct target_siginfo rs_info;
2815 struct target_ucontext rs_uc;
2816};
2817
bellard106ec872006-06-27 21:08:10 +00002818/* Install trampoline to jump back from signal handler */
2819static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2820{
Richard Henderson084d0492013-02-10 10:30:44 -08002821 int err = 0;
bellard106ec872006-06-27 21:08:10 +00002822
2823 /*
Richard Henderson084d0492013-02-10 10:30:44 -08002824 * Set up the return code ...
2825 *
2826 * li v0, __NR__foo_sigreturn
2827 * syscall
2828 */
bellard106ec872006-06-27 21:08:10 +00002829
Riku Voipio1d8b5122014-04-23 10:26:05 +03002830 __put_user(0x24020000 + syscall, tramp + 0);
2831 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00002832 return err;
2833}
2834
Riku Voipio41ecc722014-04-23 11:01:00 +03002835static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002836 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002837{
Richard Henderson084d0492013-02-10 10:30:44 -08002838 int i;
bellard106ec872006-06-27 21:08:10 +00002839
Riku Voipio1d8b5122014-04-23 10:26:05 +03002840 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07002841 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00002842
Richard Henderson084d0492013-02-10 10:30:44 -08002843 __put_user(0, &sc->sc_regs[0]);
2844 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002845 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002846 }
bellard106ec872006-06-27 21:08:10 +00002847
Riku Voipio1d8b5122014-04-23 10:26:05 +03002848 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2849 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002850
Richard Henderson084d0492013-02-10 10:30:44 -08002851 /* Rather than checking for dsp existence, always copy. The storage
2852 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002853 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2854 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2855 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2856 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2857 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2858 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002859 {
2860 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002861 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00002862 }
Richard Henderson084d0492013-02-10 10:30:44 -08002863
Riku Voipio1d8b5122014-04-23 10:26:05 +03002864 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08002865
2866 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002867 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00002868 }
bellard106ec872006-06-27 21:08:10 +00002869}
2870
Riku Voipio016d2e12014-04-23 11:19:48 +03002871static inline void
Andreas Färber05390242012-02-25 03:37:53 +01002872restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002873{
Richard Henderson084d0492013-02-10 10:30:44 -08002874 int i;
bellard106ec872006-06-27 21:08:10 +00002875
Riku Voipio1d8b5122014-04-23 10:26:05 +03002876 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00002877
Riku Voipio1d8b5122014-04-23 10:26:05 +03002878 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2879 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002880
Richard Henderson084d0492013-02-10 10:30:44 -08002881 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002882 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00002883 }
2884
Riku Voipio1d8b5122014-04-23 10:26:05 +03002885 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2886 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2887 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2888 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2889 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2890 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002891 {
2892 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002893 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08002894 cpu_wrdsp(dsp, 0x3ff, regs);
2895 }
2896
2897 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002898 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002899 }
bellard106ec872006-06-27 21:08:10 +00002900}
Richard Hendersonff970902013-02-10 10:30:42 -08002901
bellard106ec872006-06-27 21:08:10 +00002902/*
2903 * Determine which stack to use..
2904 */
bellard579a97f2007-11-11 14:26:47 +00002905static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002906get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00002907{
2908 unsigned long sp;
2909
2910 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00002911 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00002912
2913 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01002914 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00002915 * above the user stack, 16-bytes before the next lowest
2916 * 16 byte boundary. Try to avoid trashing it.
2917 */
2918 sp -= 32;
2919
bellard106ec872006-06-27 21:08:10 +00002920 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00002921 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00002922 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2923 }
bellard106ec872006-06-27 21:08:10 +00002924
bellard579a97f2007-11-11 14:26:47 +00002925 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00002926}
2927
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002928static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
2929{
2930 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
2931 env->hflags &= ~MIPS_HFLAG_M16;
2932 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
2933 env->active_tc.PC &= ~(target_ulong) 1;
2934 }
2935}
2936
Richard Hendersonff970902013-02-10 10:30:42 -08002937# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00002938/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002939static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01002940 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002941{
2942 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002943 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00002944 int i;
2945
bellard579a97f2007-11-11 14:26:47 +00002946 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002947 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002948 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
2949 goto give_sigsegv;
2950 }
bellard106ec872006-06-27 21:08:10 +00002951
2952 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2953
Riku Voipio41ecc722014-04-23 11:01:00 +03002954 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002955
2956 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03002957 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00002958 }
2959
2960 /*
2961 * Arguments to signal handler:
2962 *
2963 * a0 = signal number
2964 * a1 = 0 (should be cause)
2965 * a2 = pointer to struct sigcontext
2966 *
2967 * $25 and PC point to the signal handler, $29 points to the
2968 * struct sigframe.
2969 */
thsb5dc7732008-06-27 10:02:35 +00002970 regs->active_tc.gpr[ 4] = sig;
2971 regs->active_tc.gpr[ 5] = 0;
2972 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2973 regs->active_tc.gpr[29] = frame_addr;
2974 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00002975 /* The original kernel code sets CP0_EPC to the handler
2976 * since it returns to userland using eret
2977 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00002978 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002979 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00002980 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00002981 return;
2982
2983give_sigsegv:
2984 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00002985}
2986
Andreas Färber05390242012-02-25 03:37:53 +01002987long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002988{
ths388bb212007-05-13 13:58:00 +00002989 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002990 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00002991 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05002992 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00002993 int i;
bellard106ec872006-06-27 21:08:10 +00002994
thsb5dc7732008-06-27 10:02:35 +00002995 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002996 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00002997 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002998 goto badframe;
bellard106ec872006-06-27 21:08:10 +00002999
ths388bb212007-05-13 13:58:00 +00003000 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003001 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00003002 }
bellard106ec872006-06-27 21:08:10 +00003003
ths388bb212007-05-13 13:58:00 +00003004 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003005 set_sigmask(&blocked);
bellard106ec872006-06-27 21:08:10 +00003006
Riku Voipio016d2e12014-04-23 11:19:48 +03003007 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00003008
3009#if 0
ths388bb212007-05-13 13:58:00 +00003010 /*
3011 * Don't let your children do this ...
3012 */
3013 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003014 "move\t$29, %0\n\t"
3015 "j\tsyscall_exit"
3016 :/* no outputs */
3017 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003018 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003019#endif
ths3b46e622007-09-17 08:09:54 +00003020
thsb5dc7732008-06-27 10:02:35 +00003021 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003022 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003023 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003024 * maybe a problem with nested signals ? */
3025 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003026 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003027
3028badframe:
ths388bb212007-05-13 13:58:00 +00003029 force_sig(TARGET_SIGSEGV/*, current*/);
3030 return 0;
bellard106ec872006-06-27 21:08:10 +00003031}
Richard Hendersonff970902013-02-10 10:30:42 -08003032# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003033
pbrook624f7972008-05-31 16:11:38 +00003034static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003035 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003036 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003037{
pbrook0b1bcb02009-04-21 01:41:10 +00003038 struct target_rt_sigframe *frame;
3039 abi_ulong frame_addr;
3040 int i;
3041
3042 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003043 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003044 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3045 goto give_sigsegv;
3046 }
pbrook0b1bcb02009-04-21 01:41:10 +00003047
3048 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3049
Peter Maydellf6c7a052015-01-08 12:19:48 +00003050 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003051
Aurelien Jarno60e99242010-03-29 02:12:51 +02003052 __put_user(0, &frame->rs_uc.tuc_flags);
3053 __put_user(0, &frame->rs_uc.tuc_link);
3054 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3055 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003056 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003057 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003058
Aurelien Jarno60e99242010-03-29 02:12:51 +02003059 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003060
3061 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003062 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003063 }
3064
3065 /*
3066 * Arguments to signal handler:
3067 *
3068 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003069 * a1 = pointer to siginfo_t
pbrook0b1bcb02009-04-21 01:41:10 +00003070 * a2 = pointer to struct ucontext
3071 *
3072 * $25 and PC point to the signal handler, $29 points to the
3073 * struct sigframe.
3074 */
3075 env->active_tc.gpr[ 4] = sig;
3076 env->active_tc.gpr[ 5] = frame_addr
3077 + offsetof(struct target_rt_sigframe, rs_info);
3078 env->active_tc.gpr[ 6] = frame_addr
3079 + offsetof(struct target_rt_sigframe, rs_uc);
3080 env->active_tc.gpr[29] = frame_addr;
3081 env->active_tc.gpr[31] = frame_addr
3082 + offsetof(struct target_rt_sigframe, rs_code);
3083 /* The original kernel code sets CP0_EPC to the handler
3084 * since it returns to userland using eret
3085 * we cannot do this here, and we must set PC directly */
3086 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003087 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003088 unlock_user_struct(frame, frame_addr, 1);
3089 return;
3090
3091give_sigsegv:
3092 unlock_user_struct(frame, frame_addr, 1);
3093 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00003094}
3095
Andreas Färber05390242012-02-25 03:37:53 +01003096long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003097{
pbrook0b1bcb02009-04-21 01:41:10 +00003098 struct target_rt_sigframe *frame;
3099 abi_ulong frame_addr;
3100 sigset_t blocked;
3101
pbrook0b1bcb02009-04-21 01:41:10 +00003102 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003103 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003104 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3105 goto badframe;
3106 }
pbrook0b1bcb02009-04-21 01:41:10 +00003107
Aurelien Jarno60e99242010-03-29 02:12:51 +02003108 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003109 set_sigmask(&blocked);
pbrook0b1bcb02009-04-21 01:41:10 +00003110
Riku Voipio016d2e12014-04-23 11:19:48 +03003111 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003112
3113 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003114 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3115 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003116 goto badframe;
3117
3118 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003119 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003120 /* I am not sure this is right, but it seems to work
3121 * maybe a problem with nested signals ? */
3122 env->CP0_EPC = 0;
3123 return -TARGET_QEMU_ESIGRETURN;
3124
3125badframe:
3126 force_sig(TARGET_SIGSEGV/*, current*/);
3127 return 0;
bellard106ec872006-06-27 21:08:10 +00003128}
bellard6d5e2162004-09-30 22:04:13 +00003129
thsc3b5bc82007-12-02 06:31:25 +00003130#elif defined(TARGET_SH4)
3131
3132/*
3133 * code and data structures from linux kernel:
3134 * include/asm-sh/sigcontext.h
3135 * arch/sh/kernel/signal.c
3136 */
3137
3138struct target_sigcontext {
3139 target_ulong oldmask;
3140
3141 /* CPU registers */
3142 target_ulong sc_gregs[16];
3143 target_ulong sc_pc;
3144 target_ulong sc_pr;
3145 target_ulong sc_sr;
3146 target_ulong sc_gbr;
3147 target_ulong sc_mach;
3148 target_ulong sc_macl;
3149
3150 /* FPU registers */
3151 target_ulong sc_fpregs[16];
3152 target_ulong sc_xfpregs[16];
3153 unsigned int sc_fpscr;
3154 unsigned int sc_fpul;
3155 unsigned int sc_ownedfp;
3156};
3157
3158struct target_sigframe
3159{
3160 struct target_sigcontext sc;
3161 target_ulong extramask[TARGET_NSIG_WORDS-1];
3162 uint16_t retcode[3];
3163};
3164
3165
3166struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003167 target_ulong tuc_flags;
3168 struct target_ucontext *tuc_link;
3169 target_stack_t tuc_stack;
3170 struct target_sigcontext tuc_mcontext;
3171 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003172};
3173
3174struct target_rt_sigframe
3175{
3176 struct target_siginfo info;
3177 struct target_ucontext uc;
3178 uint16_t retcode[3];
3179};
3180
3181
3182#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3183#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3184
pbrook624f7972008-05-31 16:11:38 +00003185static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003186 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003187{
pbrook624f7972008-05-31 16:11:38 +00003188 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003189 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3190 }
3191
3192 return (sp - frame_size) & -8ul;
3193}
3194
Riku Voipio41ecc722014-04-23 11:01:00 +03003195static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003196 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003197{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003198 int i;
thsc3b5bc82007-12-02 06:31:25 +00003199
Riku Voipio1d8b5122014-04-23 10:26:05 +03003200#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003201 COPY(gregs[0]); COPY(gregs[1]);
3202 COPY(gregs[2]); COPY(gregs[3]);
3203 COPY(gregs[4]); COPY(gregs[5]);
3204 COPY(gregs[6]); COPY(gregs[7]);
3205 COPY(gregs[8]); COPY(gregs[9]);
3206 COPY(gregs[10]); COPY(gregs[11]);
3207 COPY(gregs[12]); COPY(gregs[13]);
3208 COPY(gregs[14]); COPY(gregs[15]);
3209 COPY(gbr); COPY(mach);
3210 COPY(macl); COPY(pr);
3211 COPY(sr); COPY(pc);
3212#undef COPY
3213
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003214 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003215 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003216 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003217 __put_user(regs->fpscr, &sc->sc_fpscr);
3218 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003219
3220 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003221 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003222}
3223
Timothy E Baldwinba412492016-05-12 18:47:35 +01003224static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003225{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003226 int i;
thsc3b5bc82007-12-02 06:31:25 +00003227
Riku Voipio1d8b5122014-04-23 10:26:05 +03003228#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003229 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003230 COPY(gregs[2]); COPY(gregs[3]);
3231 COPY(gregs[4]); COPY(gregs[5]);
3232 COPY(gregs[6]); COPY(gregs[7]);
3233 COPY(gregs[8]); COPY(gregs[9]);
3234 COPY(gregs[10]); COPY(gregs[11]);
3235 COPY(gregs[12]); COPY(gregs[13]);
3236 COPY(gregs[14]); COPY(gregs[15]);
3237 COPY(gbr); COPY(mach);
3238 COPY(macl); COPY(pr);
3239 COPY(sr); COPY(pc);
3240#undef COPY
3241
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003242 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003243 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003244 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003245 __get_user(regs->fpscr, &sc->sc_fpscr);
3246 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003247
3248 regs->tra = -1; /* disable syscall checks */
thsc3b5bc82007-12-02 06:31:25 +00003249}
3250
pbrook624f7972008-05-31 16:11:38 +00003251static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003252 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003253{
3254 struct target_sigframe *frame;
3255 abi_ulong frame_addr;
3256 int i;
thsc3b5bc82007-12-02 06:31:25 +00003257
3258 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003259 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003260 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3261 goto give_sigsegv;
3262 }
thsc3b5bc82007-12-02 06:31:25 +00003263
Riku Voipio41ecc722014-04-23 11:01:00 +03003264 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003265
3266 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003267 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003268 }
3269
3270 /* Set up to return from userspace. If provided, use a stub
3271 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003272 if (ka->sa_flags & TARGET_SA_RESTORER) {
3273 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003274 } else {
3275 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003276 abi_ulong retcode_addr = frame_addr +
3277 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003278 __put_user(MOVW(2), &frame->retcode[0]);
3279 __put_user(TRAP_NOARG, &frame->retcode[1]);
3280 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003281 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003282 }
3283
thsc3b5bc82007-12-02 06:31:25 +00003284 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003285 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003286 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003287 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003288 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003289 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003290
3291 unlock_user_struct(frame, frame_addr, 1);
3292 return;
3293
3294give_sigsegv:
3295 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003296 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003297}
3298
pbrook624f7972008-05-31 16:11:38 +00003299static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003300 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003301 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003302{
3303 struct target_rt_sigframe *frame;
3304 abi_ulong frame_addr;
3305 int i;
thsc3b5bc82007-12-02 06:31:25 +00003306
3307 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003308 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003309 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3310 goto give_sigsegv;
3311 }
thsc3b5bc82007-12-02 06:31:25 +00003312
Peter Maydellf6c7a052015-01-08 12:19:48 +00003313 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003314
3315 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003316 __put_user(0, &frame->uc.tuc_flags);
3317 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3318 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3319 &frame->uc.tuc_stack.ss_sp);
3320 __put_user(sas_ss_flags(regs->gregs[15]),
3321 &frame->uc.tuc_stack.ss_flags);
3322 __put_user(target_sigaltstack_used.ss_size,
3323 &frame->uc.tuc_stack.ss_size);
3324 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003325 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003326 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003327 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003328 }
3329
3330 /* Set up to return from userspace. If provided, use a stub
3331 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003332 if (ka->sa_flags & TARGET_SA_RESTORER) {
3333 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003334 } else {
3335 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003336 abi_ulong retcode_addr = frame_addr +
3337 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003338 __put_user(MOVW(2), &frame->retcode[0]);
3339 __put_user(TRAP_NOARG, &frame->retcode[1]);
3340 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003341 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003342 }
3343
thsc3b5bc82007-12-02 06:31:25 +00003344 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003345 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003346 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003347 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3348 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003349 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003350
3351 unlock_user_struct(frame, frame_addr, 1);
3352 return;
3353
3354give_sigsegv:
3355 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003356 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003357}
3358
Andreas Färber05390242012-02-25 03:37:53 +01003359long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003360{
3361 struct target_sigframe *frame;
3362 abi_ulong frame_addr;
3363 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003364 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003365 int i;
3366 int err = 0;
3367
thsc3b5bc82007-12-02 06:31:25 +00003368 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003369 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003370 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3371 goto badframe;
3372 }
thsc3b5bc82007-12-02 06:31:25 +00003373
Riku Voipio1d8b5122014-04-23 10:26:05 +03003374 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003375 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003376 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003377 }
3378
3379 if (err)
3380 goto badframe;
3381
3382 target_to_host_sigset_internal(&blocked, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003383 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003384
Timothy E Baldwinba412492016-05-12 18:47:35 +01003385 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003386
3387 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003388 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003389
3390badframe:
3391 unlock_user_struct(frame, frame_addr, 0);
3392 force_sig(TARGET_SIGSEGV);
3393 return 0;
3394}
3395
Andreas Färber05390242012-02-25 03:37:53 +01003396long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003397{
3398 struct target_rt_sigframe *frame;
3399 abi_ulong frame_addr;
3400 sigset_t blocked;
3401
thsc3b5bc82007-12-02 06:31:25 +00003402 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003403 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003404 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3405 goto badframe;
3406 }
thsc3b5bc82007-12-02 06:31:25 +00003407
Aurelien Jarno60e99242010-03-29 02:12:51 +02003408 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003409 set_sigmask(&blocked);
thsc3b5bc82007-12-02 06:31:25 +00003410
Timothy E Baldwinba412492016-05-12 18:47:35 +01003411 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003412
3413 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003414 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3415 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00003416 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003417 }
thsc3b5bc82007-12-02 06:31:25 +00003418
3419 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003420 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003421
3422badframe:
3423 unlock_user_struct(frame, frame_addr, 0);
3424 force_sig(TARGET_SIGSEGV);
3425 return 0;
3426}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003427#elif defined(TARGET_MICROBLAZE)
3428
3429struct target_sigcontext {
3430 struct target_pt_regs regs; /* needs to be first */
3431 uint32_t oldmask;
3432};
3433
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003434struct target_stack_t {
3435 abi_ulong ss_sp;
3436 int ss_flags;
3437 unsigned int ss_size;
3438};
3439
3440struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003441 abi_ulong tuc_flags;
3442 abi_ulong tuc_link;
3443 struct target_stack_t tuc_stack;
3444 struct target_sigcontext tuc_mcontext;
3445 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003446};
3447
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003448/* Signal frames. */
3449struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003450 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003451 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3452 uint32_t tramp[2];
3453};
3454
3455struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003456 siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003457 struct ucontext uc;
3458 uint32_t tramp[2];
3459};
3460
Andreas Färber05390242012-02-25 03:37:53 +01003461static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003462{
3463 __put_user(env->regs[0], &sc->regs.r0);
3464 __put_user(env->regs[1], &sc->regs.r1);
3465 __put_user(env->regs[2], &sc->regs.r2);
3466 __put_user(env->regs[3], &sc->regs.r3);
3467 __put_user(env->regs[4], &sc->regs.r4);
3468 __put_user(env->regs[5], &sc->regs.r5);
3469 __put_user(env->regs[6], &sc->regs.r6);
3470 __put_user(env->regs[7], &sc->regs.r7);
3471 __put_user(env->regs[8], &sc->regs.r8);
3472 __put_user(env->regs[9], &sc->regs.r9);
3473 __put_user(env->regs[10], &sc->regs.r10);
3474 __put_user(env->regs[11], &sc->regs.r11);
3475 __put_user(env->regs[12], &sc->regs.r12);
3476 __put_user(env->regs[13], &sc->regs.r13);
3477 __put_user(env->regs[14], &sc->regs.r14);
3478 __put_user(env->regs[15], &sc->regs.r15);
3479 __put_user(env->regs[16], &sc->regs.r16);
3480 __put_user(env->regs[17], &sc->regs.r17);
3481 __put_user(env->regs[18], &sc->regs.r18);
3482 __put_user(env->regs[19], &sc->regs.r19);
3483 __put_user(env->regs[20], &sc->regs.r20);
3484 __put_user(env->regs[21], &sc->regs.r21);
3485 __put_user(env->regs[22], &sc->regs.r22);
3486 __put_user(env->regs[23], &sc->regs.r23);
3487 __put_user(env->regs[24], &sc->regs.r24);
3488 __put_user(env->regs[25], &sc->regs.r25);
3489 __put_user(env->regs[26], &sc->regs.r26);
3490 __put_user(env->regs[27], &sc->regs.r27);
3491 __put_user(env->regs[28], &sc->regs.r28);
3492 __put_user(env->regs[29], &sc->regs.r29);
3493 __put_user(env->regs[30], &sc->regs.r30);
3494 __put_user(env->regs[31], &sc->regs.r31);
3495 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3496}
3497
Andreas Färber05390242012-02-25 03:37:53 +01003498static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003499{
3500 __get_user(env->regs[0], &sc->regs.r0);
3501 __get_user(env->regs[1], &sc->regs.r1);
3502 __get_user(env->regs[2], &sc->regs.r2);
3503 __get_user(env->regs[3], &sc->regs.r3);
3504 __get_user(env->regs[4], &sc->regs.r4);
3505 __get_user(env->regs[5], &sc->regs.r5);
3506 __get_user(env->regs[6], &sc->regs.r6);
3507 __get_user(env->regs[7], &sc->regs.r7);
3508 __get_user(env->regs[8], &sc->regs.r8);
3509 __get_user(env->regs[9], &sc->regs.r9);
3510 __get_user(env->regs[10], &sc->regs.r10);
3511 __get_user(env->regs[11], &sc->regs.r11);
3512 __get_user(env->regs[12], &sc->regs.r12);
3513 __get_user(env->regs[13], &sc->regs.r13);
3514 __get_user(env->regs[14], &sc->regs.r14);
3515 __get_user(env->regs[15], &sc->regs.r15);
3516 __get_user(env->regs[16], &sc->regs.r16);
3517 __get_user(env->regs[17], &sc->regs.r17);
3518 __get_user(env->regs[18], &sc->regs.r18);
3519 __get_user(env->regs[19], &sc->regs.r19);
3520 __get_user(env->regs[20], &sc->regs.r20);
3521 __get_user(env->regs[21], &sc->regs.r21);
3522 __get_user(env->regs[22], &sc->regs.r22);
3523 __get_user(env->regs[23], &sc->regs.r23);
3524 __get_user(env->regs[24], &sc->regs.r24);
3525 __get_user(env->regs[25], &sc->regs.r25);
3526 __get_user(env->regs[26], &sc->regs.r26);
3527 __get_user(env->regs[27], &sc->regs.r27);
3528 __get_user(env->regs[28], &sc->regs.r28);
3529 __get_user(env->regs[29], &sc->regs.r29);
3530 __get_user(env->regs[30], &sc->regs.r30);
3531 __get_user(env->regs[31], &sc->regs.r31);
3532 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3533}
3534
3535static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003536 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003537{
3538 abi_ulong sp = env->regs[1];
3539
Riku Voipiob545f632014-07-15 17:01:55 +03003540 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003541 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003542 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003543
3544 return ((sp - frame_size) & -8UL);
3545}
3546
3547static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003548 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003549{
3550 struct target_signal_frame *frame;
3551 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003552 int i;
3553
3554 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003555 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003556 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3557 goto badframe;
3558
3559 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003560 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003561
3562 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003563 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003564 }
3565
Richard Hendersonf711df62010-11-22 14:57:52 -08003566 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003567
3568 /* Set up to return from userspace. If provided, use a stub
3569 already in userspace. */
3570 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3571 if (ka->sa_flags & TARGET_SA_RESTORER) {
3572 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3573 } else {
3574 uint32_t t;
3575 /* Note, these encodings are _big endian_! */
3576 /* addi r12, r0, __NR_sigreturn */
3577 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003578 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003579 /* brki r14, 0x8 */
3580 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003581 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003582
3583 /* Return from sighandler will jump to the tramp.
3584 Negative 8 offset because return is rtsd r15, 8 */
Chen Gang166c97e2016-03-29 22:13:45 +08003585 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
3586 - 8;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003587 }
3588
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003589 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003590 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003591 /* Signal handler args: */
3592 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02003593 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003594 /* arg 1: sigcontext */
3595 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003596
3597 /* Offset of 4 to handle microblaze rtid r14, 0 */
3598 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3599
3600 unlock_user_struct(frame, frame_addr, 1);
3601 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003602badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003603 force_sig(TARGET_SIGSEGV);
3604}
3605
3606static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003607 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003608 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003609{
3610 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3611}
3612
Andreas Färber05390242012-02-25 03:37:53 +01003613long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003614{
3615 struct target_signal_frame *frame;
3616 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003617 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003618 sigset_t set;
3619 int i;
3620
3621 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003622 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003623 /* Make sure the guest isn't playing games. */
3624 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3625 goto badframe;
3626
3627 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003628 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003629 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003630 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003631 }
3632 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003633 set_sigmask(&set);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003634
Richard Hendersonf711df62010-11-22 14:57:52 -08003635 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003636 /* We got here through a sigreturn syscall, our path back is via an
3637 rtb insn so setup r14 for that. */
3638 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003639
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003640 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01003641 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003642badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003643 force_sig(TARGET_SIGSEGV);
3644}
3645
Andreas Färber05390242012-02-25 03:37:53 +01003646long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003647{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003648 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003649 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3650 return -TARGET_ENOSYS;
3651}
3652
edgar_iglb6d3abd2008-02-28 11:29:27 +00003653#elif defined(TARGET_CRIS)
3654
3655struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003656 struct target_pt_regs regs; /* needs to be first */
3657 uint32_t oldmask;
3658 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003659};
3660
3661/* Signal frames. */
3662struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003663 struct target_sigcontext sc;
3664 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3665 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003666};
3667
3668struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003669 siginfo_t *pinfo;
3670 void *puc;
3671 siginfo_t info;
3672 struct ucontext uc;
3673 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003674};
3675
Andreas Färber05390242012-02-25 03:37:53 +01003676static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003677{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003678 __put_user(env->regs[0], &sc->regs.r0);
3679 __put_user(env->regs[1], &sc->regs.r1);
3680 __put_user(env->regs[2], &sc->regs.r2);
3681 __put_user(env->regs[3], &sc->regs.r3);
3682 __put_user(env->regs[4], &sc->regs.r4);
3683 __put_user(env->regs[5], &sc->regs.r5);
3684 __put_user(env->regs[6], &sc->regs.r6);
3685 __put_user(env->regs[7], &sc->regs.r7);
3686 __put_user(env->regs[8], &sc->regs.r8);
3687 __put_user(env->regs[9], &sc->regs.r9);
3688 __put_user(env->regs[10], &sc->regs.r10);
3689 __put_user(env->regs[11], &sc->regs.r11);
3690 __put_user(env->regs[12], &sc->regs.r12);
3691 __put_user(env->regs[13], &sc->regs.r13);
3692 __put_user(env->regs[14], &sc->usp);
3693 __put_user(env->regs[15], &sc->regs.acr);
3694 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3695 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3696 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003697}
edgar_igl9664d922008-03-03 22:23:53 +00003698
Andreas Färber05390242012-02-25 03:37:53 +01003699static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003700{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003701 __get_user(env->regs[0], &sc->regs.r0);
3702 __get_user(env->regs[1], &sc->regs.r1);
3703 __get_user(env->regs[2], &sc->regs.r2);
3704 __get_user(env->regs[3], &sc->regs.r3);
3705 __get_user(env->regs[4], &sc->regs.r4);
3706 __get_user(env->regs[5], &sc->regs.r5);
3707 __get_user(env->regs[6], &sc->regs.r6);
3708 __get_user(env->regs[7], &sc->regs.r7);
3709 __get_user(env->regs[8], &sc->regs.r8);
3710 __get_user(env->regs[9], &sc->regs.r9);
3711 __get_user(env->regs[10], &sc->regs.r10);
3712 __get_user(env->regs[11], &sc->regs.r11);
3713 __get_user(env->regs[12], &sc->regs.r12);
3714 __get_user(env->regs[13], &sc->regs.r13);
3715 __get_user(env->regs[14], &sc->usp);
3716 __get_user(env->regs[15], &sc->regs.acr);
3717 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3718 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3719 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003720}
3721
Andreas Färber05390242012-02-25 03:37:53 +01003722static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003723{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003724 abi_ulong sp;
3725 /* Align the stack downwards to 4. */
3726 sp = (env->regs[R_SP] & ~3);
3727 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003728}
3729
pbrook624f7972008-05-31 16:11:38 +00003730static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003731 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003732{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003733 struct target_signal_frame *frame;
3734 abi_ulong frame_addr;
3735 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003736
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003737 frame_addr = get_sigframe(env, sizeof *frame);
3738 trace_user_setup_frame(env, frame_addr);
3739 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3740 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003741
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003742 /*
3743 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3744 * use this trampoline anymore but it sets it up for GDB.
3745 * In QEMU, using the trampoline simplifies things a bit so we use it.
3746 *
3747 * This is movu.w __NR_sigreturn, r9; break 13;
3748 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003749 __put_user(0x9c5f, frame->retcode+0);
3750 __put_user(TARGET_NR_sigreturn,
3751 frame->retcode + 1);
3752 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003753
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003754 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003755 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003756
Riku Voipio0188fad2014-04-23 13:34:15 +03003757 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3758 __put_user(set->sig[i], &frame->extramask[i - 1]);
3759 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003760
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003761 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003762
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003763 /* Move the stack and setup the arguments for the handler. */
3764 env->regs[R_SP] = frame_addr;
3765 env->regs[10] = sig;
3766 env->pc = (unsigned long) ka->_sa_handler;
3767 /* Link SRP so the guest returns through the trampoline. */
3768 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003769
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003770 unlock_user_struct(frame, frame_addr, 1);
3771 return;
3772badframe:
3773 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003774}
3775
pbrook624f7972008-05-31 16:11:38 +00003776static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003777 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003778 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003779{
3780 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3781}
3782
Andreas Färber05390242012-02-25 03:37:53 +01003783long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003784{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003785 struct target_signal_frame *frame;
3786 abi_ulong frame_addr;
3787 target_sigset_t target_set;
3788 sigset_t set;
3789 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003790
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003791 frame_addr = env->regs[R_SP];
3792 trace_user_do_sigreturn(env, frame_addr);
3793 /* Make sure the guest isn't playing games. */
3794 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
3795 goto badframe;
3796 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003797
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003798 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003799 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003800 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003801 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003802 }
3803 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01003804 set_sigmask(&set);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003805
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003806 restore_sigcontext(&frame->sc, env);
3807 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01003808 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003809badframe:
3810 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003811}
3812
Andreas Färber05390242012-02-25 03:37:53 +01003813long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003814{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003815 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003816 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3817 return -TARGET_ENOSYS;
3818}
thsc3b5bc82007-12-02 06:31:25 +00003819
Jia Liud9627832012-07-20 15:50:52 +08003820#elif defined(TARGET_OPENRISC)
3821
3822struct target_sigcontext {
3823 struct target_pt_regs regs;
3824 abi_ulong oldmask;
3825 abi_ulong usp;
3826};
3827
3828struct target_ucontext {
3829 abi_ulong tuc_flags;
3830 abi_ulong tuc_link;
3831 target_stack_t tuc_stack;
3832 struct target_sigcontext tuc_mcontext;
3833 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3834};
3835
3836struct target_rt_sigframe {
3837 abi_ulong pinfo;
3838 uint64_t puc;
3839 struct target_siginfo info;
3840 struct target_sigcontext sc;
3841 struct target_ucontext uc;
3842 unsigned char retcode[16]; /* trampoline code */
3843};
3844
3845/* This is the asm-generic/ucontext.h version */
3846#if 0
3847static int restore_sigcontext(CPUOpenRISCState *regs,
3848 struct target_sigcontext *sc)
3849{
3850 unsigned int err = 0;
3851 unsigned long old_usp;
3852
3853 /* Alwys make any pending restarted system call return -EINTR */
3854 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3855
3856 /* restore the regs from &sc->regs (same as sc, since regs is first)
3857 * (sc is already checked for VERIFY_READ since the sigframe was
3858 * checked in sys_sigreturn previously)
3859 */
3860
3861 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3862 goto badframe;
3863 }
3864
3865 /* make sure the U-flag is set so user-mode cannot fool us */
3866
3867 regs->sr &= ~SR_SM;
3868
3869 /* restore the old USP as it was before we stacked the sc etc.
3870 * (we cannot just pop the sigcontext since we aligned the sp and
3871 * stuff after pushing it)
3872 */
3873
Riku Voipio1d8b5122014-04-23 10:26:05 +03003874 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003875 phx_signal("old_usp 0x%lx", old_usp);
3876
3877 __PHX__ REALLY /* ??? */
3878 wrusp(old_usp);
3879 regs->gpr[1] = old_usp;
3880
3881 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3882 * after this completes, but we don't use that mechanism. maybe we can
3883 * use it now ?
3884 */
3885
3886 return err;
3887
3888badframe:
3889 return 1;
3890}
3891#endif
3892
3893/* Set up a signal frame. */
3894
Riku Voipio41ecc722014-04-23 11:01:00 +03003895static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003896 CPUOpenRISCState *regs,
3897 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08003898{
Jia Liud9627832012-07-20 15:50:52 +08003899 unsigned long usp = regs->gpr[1];
3900
3901 /* copy the regs. they are first in sc so we can use sc directly */
3902
Riku Voipio1d8b5122014-04-23 10:26:05 +03003903 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08003904
3905 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3906 the signal handler. The frametype will be restored to its previous
3907 value in restore_sigcontext. */
3908 /*regs->frametype = CRIS_FRAME_NORMAL;*/
3909
3910 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003911 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03003912 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003913}
3914
3915static inline unsigned long align_sigframe(unsigned long sp)
3916{
3917 unsigned long i;
3918 i = sp & ~3UL;
3919 return i;
3920}
3921
3922static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3923 CPUOpenRISCState *regs,
3924 size_t frame_size)
3925{
3926 unsigned long sp = regs->gpr[1];
3927 int onsigstack = on_sig_stack(sp);
3928
3929 /* redzone */
3930 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03003931 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08003932 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3933 }
3934
3935 sp = align_sigframe(sp - frame_size);
3936
3937 /*
3938 * If we are on the alternate signal stack and would overflow it, don't.
3939 * Return an always-bogus address instead so we will die with SIGSEGV.
3940 */
3941
3942 if (onsigstack && !likely(on_sig_stack(sp))) {
3943 return -1L;
3944 }
3945
3946 return sp;
3947}
3948
Jia Liud9627832012-07-20 15:50:52 +08003949static void setup_rt_frame(int sig, struct target_sigaction *ka,
3950 target_siginfo_t *info,
3951 target_sigset_t *set, CPUOpenRISCState *env)
3952{
3953 int err = 0;
3954 abi_ulong frame_addr;
3955 unsigned long return_ip;
3956 struct target_rt_sigframe *frame;
3957 abi_ulong info_addr, uc_addr;
3958
Jia Liud9627832012-07-20 15:50:52 +08003959 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003960 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08003961 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3962 goto give_sigsegv;
3963 }
3964
3965 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003966 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08003967 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003968 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08003969
3970 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00003971 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08003972 }
3973
3974 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03003975 __put_user(0, &frame->uc.tuc_flags);
3976 __put_user(0, &frame->uc.tuc_link);
3977 __put_user(target_sigaltstack_used.ss_sp,
3978 &frame->uc.tuc_stack.ss_sp);
3979 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
3980 __put_user(target_sigaltstack_used.ss_size,
3981 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03003982 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08003983
3984 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
3985
Jia Liud9627832012-07-20 15:50:52 +08003986 /* trampoline - the desired return ip is the retcode itself */
3987 return_ip = (unsigned long)&frame->retcode;
3988 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003989 __put_user(0xa960, (short *)(frame->retcode + 0));
3990 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
3991 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
3992 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08003993
3994 if (err) {
3995 goto give_sigsegv;
3996 }
3997
3998 /* TODO what is the current->exec_domain stuff and invmap ? */
3999
4000 /* Set up registers for signal handler */
4001 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
4002 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
4003 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
4004 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
4005 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
4006
4007 /* actually move the usp to reflect the stacked frame */
4008 env->gpr[1] = (unsigned long)frame;
4009
4010 return;
4011
4012give_sigsegv:
4013 unlock_user_struct(frame, frame_addr, 1);
4014 if (sig == TARGET_SIGSEGV) {
4015 ka->_sa_handler = TARGET_SIG_DFL;
4016 }
4017 force_sig(TARGET_SIGSEGV);
4018}
4019
4020long do_sigreturn(CPUOpenRISCState *env)
4021{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004022 trace_user_do_sigreturn(env, 0);
4023 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004024 return -TARGET_ENOSYS;
4025}
4026
4027long do_rt_sigreturn(CPUOpenRISCState *env)
4028{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004029 trace_user_do_rt_sigreturn(env, 0);
4030 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004031 return -TARGET_ENOSYS;
4032}
4033/* TARGET_OPENRISC */
4034
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004035#elif defined(TARGET_S390X)
4036
4037#define __NUM_GPRS 16
4038#define __NUM_FPRS 16
4039#define __NUM_ACRS 16
4040
4041#define S390_SYSCALL_SIZE 2
4042#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4043
4044#define _SIGCONTEXT_NSIG 64
4045#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4046#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4047#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4048#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4049#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4050
4051typedef struct {
4052 target_psw_t psw;
4053 target_ulong gprs[__NUM_GPRS];
4054 unsigned int acrs[__NUM_ACRS];
4055} target_s390_regs_common;
4056
4057typedef struct {
4058 unsigned int fpc;
4059 double fprs[__NUM_FPRS];
4060} target_s390_fp_regs;
4061
4062typedef struct {
4063 target_s390_regs_common regs;
4064 target_s390_fp_regs fpregs;
4065} target_sigregs;
4066
4067struct target_sigcontext {
4068 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4069 target_sigregs *sregs;
4070};
4071
4072typedef struct {
4073 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4074 struct target_sigcontext sc;
4075 target_sigregs sregs;
4076 int signo;
4077 uint8_t retcode[S390_SYSCALL_SIZE];
4078} sigframe;
4079
4080struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004081 target_ulong tuc_flags;
4082 struct target_ucontext *tuc_link;
4083 target_stack_t tuc_stack;
4084 target_sigregs tuc_mcontext;
4085 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004086};
4087
4088typedef struct {
4089 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4090 uint8_t retcode[S390_SYSCALL_SIZE];
4091 struct target_siginfo info;
4092 struct target_ucontext uc;
4093} rt_sigframe;
4094
4095static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004096get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004097{
4098 abi_ulong sp;
4099
4100 /* Default to using normal stack */
4101 sp = env->regs[15];
4102
4103 /* This is the X/Open sanctioned signal stack switching. */
4104 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4105 if (!sas_ss_flags(sp)) {
4106 sp = target_sigaltstack_used.ss_sp +
4107 target_sigaltstack_used.ss_size;
4108 }
4109 }
4110
4111 /* This is the legacy signal stack switching. */
4112 else if (/* FIXME !user_mode(regs) */ 0 &&
4113 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4114 ka->sa_restorer) {
4115 sp = (abi_ulong) ka->sa_restorer;
4116 }
4117
4118 return (sp - frame_size) & -8ul;
4119}
4120
Andreas Färber05390242012-02-25 03:37:53 +01004121static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004122{
4123 int i;
4124 //save_access_regs(current->thread.acrs); FIXME
4125
4126 /* Copy a 'clean' PSW mask to the user to avoid leaking
4127 information about whether PER is currently on. */
4128 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4129 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4130 for (i = 0; i < 16; i++) {
4131 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4132 }
4133 for (i = 0; i < 16; i++) {
4134 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4135 }
4136 /*
4137 * We have to store the fp registers to current->thread.fp_regs
4138 * to merge them with the emulated registers.
4139 */
4140 //save_fp_regs(&current->thread.fp_regs); FIXME
4141 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004142 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004143 }
4144}
4145
4146static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004147 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004148{
4149 sigframe *frame;
4150 abi_ulong frame_addr;
4151
4152 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004153 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004154 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004155 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004156 }
4157
Riku Voipio0188fad2014-04-23 13:34:15 +03004158 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004159
4160 save_sigregs(env, &frame->sregs);
4161
4162 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4163 (abi_ulong *)&frame->sc.sregs);
4164
4165 /* Set up to return from userspace. If provided, use a stub
4166 already in userspace. */
4167 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004168 env->regs[14] = (unsigned long)
4169 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004170 } else {
Chen Gang5b1d59d2016-05-24 14:54:32 +03004171 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4172 | PSW_ADDR_AMODE;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004173 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4174 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004175 }
4176
4177 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004178 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004179
4180 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004181 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004182 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4183
4184 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004185 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004186
4187 /* We forgot to include these in the sigcontext.
4188 To avoid breaking binary compatibility, they are passed as args. */
4189 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4190 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4191
4192 /* Place signal number on stack to allow backtrace from handler. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004193 __put_user(env->regs[2], (int *) &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004194 unlock_user_struct(frame, frame_addr, 1);
4195 return;
4196
4197give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004198 force_sig(TARGET_SIGSEGV);
4199}
4200
4201static void setup_rt_frame(int sig, struct target_sigaction *ka,
4202 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004203 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004204{
4205 int i;
4206 rt_sigframe *frame;
4207 abi_ulong frame_addr;
4208
4209 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004210 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004211 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4212 goto give_sigsegv;
4213 }
4214
Peter Maydellf6c7a052015-01-08 12:19:48 +00004215 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004216
4217 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004218 __put_user(0, &frame->uc.tuc_flags);
4219 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4220 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004221 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004222 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004223 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4224 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004225 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4226 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004227 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004228 }
4229
4230 /* Set up to return from userspace. If provided, use a stub
4231 already in userspace. */
4232 if (ka->sa_flags & TARGET_SA_RESTORER) {
4233 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4234 } else {
4235 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004236 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4237 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004238 }
4239
4240 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004241 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004242
4243 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004244 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004245 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4246
4247 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004248 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4249 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004250 return;
4251
4252give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004253 force_sig(TARGET_SIGSEGV);
4254}
4255
4256static int
Andreas Färber05390242012-02-25 03:37:53 +01004257restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004258{
4259 int err = 0;
4260 int i;
4261
4262 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004263 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004264 }
4265
Riku Voipio1d8b5122014-04-23 10:26:05 +03004266 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004267 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4268 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004269 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004270 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4271
4272 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004273 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004274 }
4275 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004276 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004277 }
4278
4279 return err;
4280}
4281
Andreas Färber05390242012-02-25 03:37:53 +01004282long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004283{
4284 sigframe *frame;
4285 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004286 target_sigset_t target_set;
4287 sigset_t set;
4288
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004289 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004290 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4291 goto badframe;
4292 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004293 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004294
4295 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004296 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004297
4298 if (restore_sigregs(env, &frame->sregs)) {
4299 goto badframe;
4300 }
4301
4302 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004303 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004304
4305badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004306 force_sig(TARGET_SIGSEGV);
4307 return 0;
4308}
4309
Andreas Färber05390242012-02-25 03:37:53 +01004310long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004311{
4312 rt_sigframe *frame;
4313 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004314 sigset_t set;
4315
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004316 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004317 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4318 goto badframe;
4319 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004320 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004321
Peter Maydell9eede5b2016-05-27 15:51:46 +01004322 set_sigmask(&set); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004323
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004324 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004325 goto badframe;
4326 }
4327
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004328 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004329 get_sp_from_cpustate(env)) == -EFAULT) {
4330 goto badframe;
4331 }
4332 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004333 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004334
4335badframe:
4336 unlock_user_struct(frame, frame_addr, 0);
4337 force_sig(TARGET_SIGSEGV);
4338 return 0;
4339}
4340
Tom Musta61e75fe2014-06-30 08:13:38 -05004341#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004342
4343/* Size of dummy stack frame allocated when calling signal handler.
4344 See arch/powerpc/include/asm/ptrace.h. */
4345#if defined(TARGET_PPC64)
4346#define SIGNAL_FRAMESIZE 128
4347#else
4348#define SIGNAL_FRAMESIZE 64
4349#endif
4350
Tom Musta61e75fe2014-06-30 08:13:38 -05004351/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4352 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4353struct target_mcontext {
4354 target_ulong mc_gregs[48];
4355 /* Includes fpscr. */
4356 uint64_t mc_fregs[33];
4357 target_ulong mc_pad[2];
4358 /* We need to handle Altivec and SPE at the same time, which no
4359 kernel needs to do. Fortunately, the kernel defines this bit to
4360 be Altivec-register-large all the time, rather than trying to
4361 twiddle it based on the specific platform. */
4362 union {
4363 /* SPE vector registers. One extra for SPEFSCR. */
4364 uint32_t spe[33];
4365 /* Altivec vector registers. The packing of VSCR and VRSAVE
4366 varies depending on whether we're PPC64 or not: PPC64 splits
4367 them apart; PPC32 stuffs them together. */
4368#if defined(TARGET_PPC64)
4369#define QEMU_NVRREG 34
4370#else
4371#define QEMU_NVRREG 33
4372#endif
4373 ppc_avr_t altivec[QEMU_NVRREG];
4374#undef QEMU_NVRREG
4375 } mc_vregs __attribute__((__aligned__(16)));
4376};
4377
Nathan Froydbcd49332009-05-12 19:13:18 -07004378/* See arch/powerpc/include/asm/sigcontext.h. */
4379struct target_sigcontext {
4380 target_ulong _unused[4];
4381 int32_t signal;
4382#if defined(TARGET_PPC64)
4383 int32_t pad0;
4384#endif
4385 target_ulong handler;
4386 target_ulong oldmask;
4387 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05004388#if defined(TARGET_PPC64)
4389 struct target_mcontext mcontext;
4390#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004391};
4392
4393/* Indices for target_mcontext.mc_gregs, below.
4394 See arch/powerpc/include/asm/ptrace.h for details. */
4395enum {
4396 TARGET_PT_R0 = 0,
4397 TARGET_PT_R1 = 1,
4398 TARGET_PT_R2 = 2,
4399 TARGET_PT_R3 = 3,
4400 TARGET_PT_R4 = 4,
4401 TARGET_PT_R5 = 5,
4402 TARGET_PT_R6 = 6,
4403 TARGET_PT_R7 = 7,
4404 TARGET_PT_R8 = 8,
4405 TARGET_PT_R9 = 9,
4406 TARGET_PT_R10 = 10,
4407 TARGET_PT_R11 = 11,
4408 TARGET_PT_R12 = 12,
4409 TARGET_PT_R13 = 13,
4410 TARGET_PT_R14 = 14,
4411 TARGET_PT_R15 = 15,
4412 TARGET_PT_R16 = 16,
4413 TARGET_PT_R17 = 17,
4414 TARGET_PT_R18 = 18,
4415 TARGET_PT_R19 = 19,
4416 TARGET_PT_R20 = 20,
4417 TARGET_PT_R21 = 21,
4418 TARGET_PT_R22 = 22,
4419 TARGET_PT_R23 = 23,
4420 TARGET_PT_R24 = 24,
4421 TARGET_PT_R25 = 25,
4422 TARGET_PT_R26 = 26,
4423 TARGET_PT_R27 = 27,
4424 TARGET_PT_R28 = 28,
4425 TARGET_PT_R29 = 29,
4426 TARGET_PT_R30 = 30,
4427 TARGET_PT_R31 = 31,
4428 TARGET_PT_NIP = 32,
4429 TARGET_PT_MSR = 33,
4430 TARGET_PT_ORIG_R3 = 34,
4431 TARGET_PT_CTR = 35,
4432 TARGET_PT_LNK = 36,
4433 TARGET_PT_XER = 37,
4434 TARGET_PT_CCR = 38,
4435 /* Yes, there are two registers with #39. One is 64-bit only. */
4436 TARGET_PT_MQ = 39,
4437 TARGET_PT_SOFTE = 39,
4438 TARGET_PT_TRAP = 40,
4439 TARGET_PT_DAR = 41,
4440 TARGET_PT_DSISR = 42,
4441 TARGET_PT_RESULT = 43,
4442 TARGET_PT_REGS_COUNT = 44
4443};
4444
Nathan Froydbcd49332009-05-12 19:13:18 -07004445
4446struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004447 target_ulong tuc_flags;
4448 target_ulong tuc_link; /* struct ucontext __user * */
4449 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07004450#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02004451 int32_t tuc_pad[7];
4452 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07004453 points to uc_mcontext field */
4454#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02004455 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07004456#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05004457 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05004458 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004459#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02004460 int32_t tuc_maskext[30];
4461 int32_t tuc_pad2[3];
4462 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004463#endif
4464};
4465
4466/* See arch/powerpc/kernel/signal_32.c. */
4467struct target_sigframe {
4468 struct target_sigcontext sctx;
4469 struct target_mcontext mctx;
4470 int32_t abigap[56];
4471};
4472
Tom Musta61e75fe2014-06-30 08:13:38 -05004473#if defined(TARGET_PPC64)
4474
4475#define TARGET_TRAMP_SIZE 6
4476
4477struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004478 /* sys_rt_sigreturn requires the ucontext be the first field */
4479 struct target_ucontext uc;
4480 target_ulong _unused[2];
4481 uint32_t trampoline[TARGET_TRAMP_SIZE];
4482 target_ulong pinfo; /* struct siginfo __user * */
4483 target_ulong puc; /* void __user * */
4484 struct target_siginfo info;
4485 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
4486 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05004487} __attribute__((aligned(16)));
4488
4489#else
4490
Nathan Froydbcd49332009-05-12 19:13:18 -07004491struct target_rt_sigframe {
4492 struct target_siginfo info;
4493 struct target_ucontext uc;
4494 int32_t abigap[56];
4495};
4496
Tom Musta61e75fe2014-06-30 08:13:38 -05004497#endif
4498
Tom Musta8d6ab332014-06-30 08:13:39 -05004499#if defined(TARGET_PPC64)
4500
4501struct target_func_ptr {
4502 target_ulong entry;
4503 target_ulong toc;
4504};
4505
4506#endif
4507
Nathan Froydbcd49332009-05-12 19:13:18 -07004508/* We use the mc_pad field for the signal return trampoline. */
4509#define tramp mc_pad
4510
4511/* See arch/powerpc/kernel/signal.c. */
4512static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004513 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07004514 int frame_size)
4515{
4516 target_ulong oldsp, newsp;
4517
4518 oldsp = env->gpr[1];
4519
4520 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004521 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07004522 oldsp = (target_sigaltstack_used.ss_sp
4523 + target_sigaltstack_used.ss_size);
4524 }
4525
4526 newsp = (oldsp - frame_size) & ~0xFUL;
4527
4528 return newsp;
4529}
4530
Tom Musta76781082014-06-30 08:13:37 -05004531static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07004532{
4533 target_ulong msr = env->msr;
4534 int i;
4535 target_ulong ccr = 0;
4536
4537 /* In general, the kernel attempts to be intelligent about what it
4538 needs to save for Altivec/FP/SPE registers. We don't care that
4539 much, so we just go ahead and save everything. */
4540
4541 /* Save general registers. */
4542 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004543 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004544 }
Riku Voipioc650c002014-04-23 13:53:45 +03004545 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4546 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4547 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4548 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004549
4550 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4551 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4552 }
Riku Voipioc650c002014-04-23 13:53:45 +03004553 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004554
4555 /* Save Altivec registers if necessary. */
4556 if (env->insns_flags & PPC_ALTIVEC) {
4557 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004558 ppc_avr_t *avr = &env->avr[i];
4559 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004560
Riku Voipioc650c002014-04-23 13:53:45 +03004561 __put_user(avr->u64[0], &vreg->u64[0]);
4562 __put_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004563 }
4564 /* Set MSR_VR in the saved MSR value to indicate that
4565 frame->mc_vregs contains valid data. */
4566 msr |= MSR_VR;
Riku Voipioc650c002014-04-23 13:53:45 +03004567 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4568 &frame->mc_vregs.altivec[32].u32[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004569 }
4570
4571 /* Save floating point registers. */
4572 if (env->insns_flags & PPC_FLOAT) {
4573 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004574 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004575 }
Riku Voipioc650c002014-04-23 13:53:45 +03004576 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004577 }
4578
4579 /* Save SPE registers. The kernel only saves the high half. */
4580 if (env->insns_flags & PPC_SPE) {
4581#if defined(TARGET_PPC64)
4582 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004583 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004584 }
4585#else
4586 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004587 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004588 }
4589#endif
4590 /* Set MSR_SPE in the saved MSR value to indicate that
4591 frame->mc_vregs contains valid data. */
4592 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03004593 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004594 }
4595
4596 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004597 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05004598}
Nathan Froydbcd49332009-05-12 19:13:18 -07004599
Tom Musta76781082014-06-30 08:13:37 -05004600static void encode_trampoline(int sigret, uint32_t *tramp)
4601{
Nathan Froydbcd49332009-05-12 19:13:18 -07004602 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4603 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05004604 __put_user(0x38000000 | sigret, &tramp[0]);
4605 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004606 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004607}
4608
Riku Voipioc650c002014-04-23 13:53:45 +03004609static void restore_user_regs(CPUPPCState *env,
4610 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004611{
4612 target_ulong save_r2 = 0;
4613 target_ulong msr;
4614 target_ulong ccr;
4615
4616 int i;
4617
4618 if (!sig) {
4619 save_r2 = env->gpr[2];
4620 }
4621
4622 /* Restore general registers. */
4623 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004624 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004625 }
Riku Voipioc650c002014-04-23 13:53:45 +03004626 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4627 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4628 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4629 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4630 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004631
4632 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4633 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4634 }
4635
4636 if (!sig) {
4637 env->gpr[2] = save_r2;
4638 }
4639 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004640 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004641
4642 /* If doing signal return, restore the previous little-endian mode. */
4643 if (sig)
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004644 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
Nathan Froydbcd49332009-05-12 19:13:18 -07004645
4646 /* Restore Altivec registers if necessary. */
4647 if (env->insns_flags & PPC_ALTIVEC) {
4648 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004649 ppc_avr_t *avr = &env->avr[i];
4650 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004651
Riku Voipioc650c002014-04-23 13:53:45 +03004652 __get_user(avr->u64[0], &vreg->u64[0]);
4653 __get_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004654 }
4655 /* Set MSR_VEC in the saved MSR value to indicate that
4656 frame->mc_vregs contains valid data. */
Riku Voipioc650c002014-04-23 13:53:45 +03004657 __get_user(env->spr[SPR_VRSAVE],
4658 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
Nathan Froydbcd49332009-05-12 19:13:18 -07004659 }
4660
4661 /* Restore floating point registers. */
4662 if (env->insns_flags & PPC_FLOAT) {
4663 uint64_t fpscr;
4664 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004665 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004666 }
Riku Voipioc650c002014-04-23 13:53:45 +03004667 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004668 env->fpscr = (uint32_t) fpscr;
4669 }
4670
4671 /* Save SPE registers. The kernel only saves the high half. */
4672 if (env->insns_flags & PPC_SPE) {
4673#if defined(TARGET_PPC64)
4674 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4675 uint32_t hi;
4676
Riku Voipioc650c002014-04-23 13:53:45 +03004677 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004678 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4679 }
4680#else
4681 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004682 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004683 }
4684#endif
Riku Voipioc650c002014-04-23 13:53:45 +03004685 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004686 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004687}
4688
4689static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004690 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004691{
4692 struct target_sigframe *frame;
4693 struct target_sigcontext *sc;
4694 target_ulong frame_addr, newsp;
4695 int err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004696#if defined(TARGET_PPC64)
4697 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4698#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004699
4700 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004701 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004702 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4703 goto sigsegv;
4704 sc = &frame->sctx;
4705
Riku Voipio1d8b5122014-04-23 10:26:05 +03004706 __put_user(ka->_sa_handler, &sc->handler);
4707 __put_user(set->sig[0], &sc->oldmask);
Tom Musta61e75fe2014-06-30 08:13:38 -05004708#if TARGET_ABI_BITS == 64
Riku Voipio1d8b5122014-04-23 10:26:05 +03004709 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004710#else
Riku Voipio1d8b5122014-04-23 10:26:05 +03004711 __put_user(set->sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004712#endif
Riku Voipio1d8b5122014-04-23 10:26:05 +03004713 __put_user(h2g(&frame->mctx), &sc->regs);
4714 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07004715
4716 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05004717 save_user_regs(env, &frame->mctx);
4718
4719 /* Construct the trampoline code on the stack. */
4720 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07004721
4722 /* The kernel checks for the presence of a VDSO here. We don't
4723 emulate a vdso, so use a sigreturn system call. */
4724 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4725
4726 /* Turn off all fp exceptions. */
4727 env->fpscr = 0;
4728
4729 /* Create a stack frame for the caller of the handler. */
4730 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00004731 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004732
4733 if (err)
4734 goto sigsegv;
4735
4736 /* Set up registers for signal handler. */
4737 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004738 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00004739 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05004740
4741#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004742 if (get_ppc64_abi(image) < 2) {
4743 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4744 struct target_func_ptr *handler =
4745 (struct target_func_ptr *)g2h(ka->_sa_handler);
4746 env->nip = tswapl(handler->entry);
4747 env->gpr[2] = tswapl(handler->toc);
4748 } else {
4749 /* ELFv2 PPC64 function pointers are entry points, but R12
4750 * must also be set */
4751 env->nip = tswapl((target_ulong) ka->_sa_handler);
4752 env->gpr[12] = env->nip;
4753 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004754#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004755 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004756#endif
4757
Nathan Froydbcd49332009-05-12 19:13:18 -07004758 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004759 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07004760
4761 unlock_user_struct(frame, frame_addr, 1);
4762 return;
4763
4764sigsegv:
4765 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004766 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004767}
4768
4769static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004770 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004771 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004772{
4773 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05004774 uint32_t *trampptr = 0;
4775 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004776 target_ulong rt_sf_addr, newsp = 0;
4777 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004778#if defined(TARGET_PPC64)
4779 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4780#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004781
4782 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4783 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4784 goto sigsegv;
4785
Peter Maydellf6c7a052015-01-08 12:19:48 +00004786 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07004787
Riku Voipio1d8b5122014-04-23 10:26:05 +03004788 __put_user(0, &rt_sf->uc.tuc_flags);
4789 __put_user(0, &rt_sf->uc.tuc_link);
4790 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4791 &rt_sf->uc.tuc_stack.ss_sp);
4792 __put_user(sas_ss_flags(env->gpr[1]),
4793 &rt_sf->uc.tuc_stack.ss_flags);
4794 __put_user(target_sigaltstack_used.ss_size,
4795 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05004796#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03004797 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4798 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05004799#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004800 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004801 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004802 }
4803
Tom Musta61e75fe2014-06-30 08:13:38 -05004804#if defined(TARGET_PPC64)
4805 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
4806 trampptr = &rt_sf->trampoline[0];
4807#else
4808 mctx = &rt_sf->uc.tuc_mcontext;
4809 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
4810#endif
4811
4812 save_user_regs(env, mctx);
4813 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004814
4815 /* The kernel checks for the presence of a VDSO here. We don't
4816 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05004817 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004818
4819 /* Turn off all fp exceptions. */
4820 env->fpscr = 0;
4821
4822 /* Create a stack frame for the caller of the handler. */
4823 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05004824 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004825
4826 if (err)
4827 goto sigsegv;
4828
4829 /* Set up registers for signal handler. */
4830 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004831 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07004832 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4833 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4834 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05004835
4836#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004837 if (get_ppc64_abi(image) < 2) {
4838 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4839 struct target_func_ptr *handler =
4840 (struct target_func_ptr *)g2h(ka->_sa_handler);
4841 env->nip = tswapl(handler->entry);
4842 env->gpr[2] = tswapl(handler->toc);
4843 } else {
4844 /* ELFv2 PPC64 function pointers are entry points, but R12
4845 * must also be set */
4846 env->nip = tswapl((target_ulong) ka->_sa_handler);
4847 env->gpr[12] = env->nip;
4848 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004849#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004850 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004851#endif
4852
Nathan Froydbcd49332009-05-12 19:13:18 -07004853 /* Signal handlers are entered in big-endian mode. */
Laurent Vivier49e55cb2016-03-30 18:36:51 +02004854 env->msr &= ~(1ull << MSR_LE);
Nathan Froydbcd49332009-05-12 19:13:18 -07004855
4856 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4857 return;
4858
4859sigsegv:
4860 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004861 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004862
4863}
4864
Andreas Färber05390242012-02-25 03:37:53 +01004865long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004866{
4867 struct target_sigcontext *sc = NULL;
4868 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01004869 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07004870 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004871 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004872
4873 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4874 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4875 goto sigsegv;
4876
4877#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05004878 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07004879#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03004880 __get_user(set.sig[0], &sc->oldmask);
4881 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004882#endif
4883 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004884 set_sigmask(&blocked);
Nathan Froydbcd49332009-05-12 19:13:18 -07004885
Riku Voipiof5f601a2014-04-23 13:00:17 +03004886 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004887 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4888 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03004889 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07004890
4891 unlock_user_struct(sr, sr_addr, 1);
4892 unlock_user_struct(sc, sc_addr, 1);
4893 return -TARGET_QEMU_ESIGRETURN;
4894
4895sigsegv:
4896 unlock_user_struct(sr, sr_addr, 1);
4897 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004898 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004899 return 0;
4900}
4901
4902/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01004903static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004904{
4905 struct target_mcontext *mcp;
4906 target_ulong mcp_addr;
4907 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004908 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004909
Aurelien Jarno60e99242010-03-29 02:12:51 +02004910 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07004911 sizeof (set)))
4912 return 1;
4913
Tom Musta19774ec2014-06-30 08:13:40 -05004914#if defined(TARGET_PPC64)
4915 mcp_addr = h2g(ucp) +
4916 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
4917#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03004918 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05004919#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004920
4921 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4922 return 1;
4923
4924 target_to_host_sigset_internal(&blocked, &set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01004925 set_sigmask(&blocked);
Riku Voipioc650c002014-04-23 13:53:45 +03004926 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07004927
4928 unlock_user_struct(mcp, mcp_addr, 1);
4929 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004930}
4931
Andreas Färber05390242012-02-25 03:37:53 +01004932long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004933{
4934 struct target_rt_sigframe *rt_sf = NULL;
4935 target_ulong rt_sf_addr;
4936
4937 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4938 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4939 goto sigsegv;
4940
4941 if (do_setcontext(&rt_sf->uc, env, 1))
4942 goto sigsegv;
4943
4944 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02004945 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07004946 0, env->gpr[1]);
4947
4948 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4949 return -TARGET_QEMU_ESIGRETURN;
4950
4951sigsegv:
4952 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004953 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004954 return 0;
4955}
4956
Laurent Vivier492a8742009-08-03 16:12:17 +02004957#elif defined(TARGET_M68K)
4958
4959struct target_sigcontext {
4960 abi_ulong sc_mask;
4961 abi_ulong sc_usp;
4962 abi_ulong sc_d0;
4963 abi_ulong sc_d1;
4964 abi_ulong sc_a0;
4965 abi_ulong sc_a1;
4966 unsigned short sc_sr;
4967 abi_ulong sc_pc;
4968};
4969
4970struct target_sigframe
4971{
4972 abi_ulong pretcode;
4973 int sig;
4974 int code;
4975 abi_ulong psc;
4976 char retcode[8];
4977 abi_ulong extramask[TARGET_NSIG_WORDS-1];
4978 struct target_sigcontext sc;
4979};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004980
Anthony Liguoric227f092009-10-01 16:12:16 -05004981typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004982#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05004983typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02004984
4985typedef struct target_fpregset {
4986 int f_fpcntl[3];
4987 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05004988} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004989
4990struct target_mcontext {
4991 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05004992 target_gregset_t gregs;
4993 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02004994};
4995
4996#define TARGET_MCONTEXT_VERSION 2
4997
4998struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004999 abi_ulong tuc_flags;
5000 abi_ulong tuc_link;
5001 target_stack_t tuc_stack;
5002 struct target_mcontext tuc_mcontext;
5003 abi_long tuc_filler[80];
5004 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02005005};
5006
5007struct target_rt_sigframe
5008{
5009 abi_ulong pretcode;
5010 int sig;
5011 abi_ulong pinfo;
5012 abi_ulong puc;
5013 char retcode[8];
5014 struct target_siginfo info;
5015 struct target_ucontext uc;
5016};
Laurent Vivier492a8742009-08-03 16:12:17 +02005017
Riku Voipio41ecc722014-04-23 11:01:00 +03005018static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005019 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005020{
Riku Voipio1d8b5122014-04-23 10:26:05 +03005021 __put_user(mask, &sc->sc_mask);
5022 __put_user(env->aregs[7], &sc->sc_usp);
5023 __put_user(env->dregs[0], &sc->sc_d0);
5024 __put_user(env->dregs[1], &sc->sc_d1);
5025 __put_user(env->aregs[0], &sc->sc_a0);
5026 __put_user(env->aregs[1], &sc->sc_a1);
5027 __put_user(env->sr, &sc->sc_sr);
5028 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005029}
5030
Riku Voipio016d2e12014-04-23 11:19:48 +03005031static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005032restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005033{
Laurent Vivier492a8742009-08-03 16:12:17 +02005034 int temp;
5035
Riku Voipio1d8b5122014-04-23 10:26:05 +03005036 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005037 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005038 __get_user(env->dregs[1], &sc->sc_d1);
5039 __get_user(env->aregs[0], &sc->sc_a0);
5040 __get_user(env->aregs[1], &sc->sc_a1);
5041 __get_user(env->pc, &sc->sc_pc);
5042 __get_user(temp, &sc->sc_sr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005043 env->sr = (env->sr & 0xff00) | (temp & 0xff);
Laurent Vivier492a8742009-08-03 16:12:17 +02005044}
5045
5046/*
5047 * Determine which stack to use..
5048 */
5049static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005050get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5051 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005052{
5053 unsigned long sp;
5054
5055 sp = regs->aregs[7];
5056
5057 /* This is the X/Open sanctioned signal stack switching. */
5058 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5059 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5060 }
5061
5062 return ((sp - frame_size) & -8UL);
5063}
5064
5065static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005066 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005067{
5068 struct target_sigframe *frame;
5069 abi_ulong frame_addr;
5070 abi_ulong retcode_addr;
5071 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005072 int i;
5073
5074 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005075 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005076 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5077 goto give_sigsegv;
5078 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005079
Riku Voipio1d8b5122014-04-23 10:26:05 +03005080 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005081
5082 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005083 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005084
Riku Voipio41ecc722014-04-23 11:01:00 +03005085 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005086
5087 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005088 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005089 }
5090
5091 /* Set up to return from userspace. */
5092
5093 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005094 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005095
5096 /* moveq #,d0; trap #0 */
5097
Riku Voipio1d8b5122014-04-23 10:26:05 +03005098 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005099 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005100
Laurent Vivier492a8742009-08-03 16:12:17 +02005101 /* Set up to return from userspace */
5102
5103 env->aregs[7] = frame_addr;
5104 env->pc = ka->_sa_handler;
5105
5106 unlock_user_struct(frame, frame_addr, 1);
5107 return;
5108
5109give_sigsegv:
Riku Voipio66393fb2009-12-04 15:16:32 +02005110 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005111}
5112
Laurent Vivier71811552009-08-03 16:12:18 +02005113static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005114 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005115{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005116 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005117
Riku Voipio1d8b5122014-04-23 10:26:05 +03005118 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5119 __put_user(env->dregs[0], &gregs[0]);
5120 __put_user(env->dregs[1], &gregs[1]);
5121 __put_user(env->dregs[2], &gregs[2]);
5122 __put_user(env->dregs[3], &gregs[3]);
5123 __put_user(env->dregs[4], &gregs[4]);
5124 __put_user(env->dregs[5], &gregs[5]);
5125 __put_user(env->dregs[6], &gregs[6]);
5126 __put_user(env->dregs[7], &gregs[7]);
5127 __put_user(env->aregs[0], &gregs[8]);
5128 __put_user(env->aregs[1], &gregs[9]);
5129 __put_user(env->aregs[2], &gregs[10]);
5130 __put_user(env->aregs[3], &gregs[11]);
5131 __put_user(env->aregs[4], &gregs[12]);
5132 __put_user(env->aregs[5], &gregs[13]);
5133 __put_user(env->aregs[6], &gregs[14]);
5134 __put_user(env->aregs[7], &gregs[15]);
5135 __put_user(env->pc, &gregs[16]);
5136 __put_user(env->sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005137
Riku Voipio1d8b5122014-04-23 10:26:05 +03005138 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005139}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005140
Andreas Färber05390242012-02-25 03:37:53 +01005141static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005142 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02005143{
5144 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005145 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005146
Riku Voipio1d8b5122014-04-23 10:26:05 +03005147 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005148 if (temp != TARGET_MCONTEXT_VERSION)
5149 goto badframe;
5150
5151 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005152 __get_user(env->dregs[0], &gregs[0]);
5153 __get_user(env->dregs[1], &gregs[1]);
5154 __get_user(env->dregs[2], &gregs[2]);
5155 __get_user(env->dregs[3], &gregs[3]);
5156 __get_user(env->dregs[4], &gregs[4]);
5157 __get_user(env->dregs[5], &gregs[5]);
5158 __get_user(env->dregs[6], &gregs[6]);
5159 __get_user(env->dregs[7], &gregs[7]);
5160 __get_user(env->aregs[0], &gregs[8]);
5161 __get_user(env->aregs[1], &gregs[9]);
5162 __get_user(env->aregs[2], &gregs[10]);
5163 __get_user(env->aregs[3], &gregs[11]);
5164 __get_user(env->aregs[4], &gregs[12]);
5165 __get_user(env->aregs[5], &gregs[13]);
5166 __get_user(env->aregs[6], &gregs[14]);
5167 __get_user(env->aregs[7], &gregs[15]);
5168 __get_user(env->pc, &gregs[16]);
5169 __get_user(temp, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005170 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5171
Riku Voipio1d8b5122014-04-23 10:26:05 +03005172 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005173
5174badframe:
5175 return 1;
5176}
5177
Laurent Vivier492a8742009-08-03 16:12:17 +02005178static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005179 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005180 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005181{
Laurent Vivier71811552009-08-03 16:12:18 +02005182 struct target_rt_sigframe *frame;
5183 abi_ulong frame_addr;
5184 abi_ulong retcode_addr;
5185 abi_ulong info_addr;
5186 abi_ulong uc_addr;
5187 int err = 0;
5188 int i;
5189
5190 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005191 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005192 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5193 goto give_sigsegv;
5194 }
Laurent Vivier71811552009-08-03 16:12:18 +02005195
Riku Voipio1d8b5122014-04-23 10:26:05 +03005196 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005197
5198 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005199 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005200
5201 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005202 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005203
Peter Maydellf6c7a052015-01-08 12:19:48 +00005204 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005205
5206 /* Create the ucontext */
5207
Riku Voipio1d8b5122014-04-23 10:26:05 +03005208 __put_user(0, &frame->uc.tuc_flags);
5209 __put_user(0, &frame->uc.tuc_link);
5210 __put_user(target_sigaltstack_used.ss_sp,
5211 &frame->uc.tuc_stack.ss_sp);
5212 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005213 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005214 __put_user(target_sigaltstack_used.ss_size,
5215 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005216 err |= target_rt_setup_ucontext(&frame->uc, env);
5217
5218 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005219 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02005220
5221 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005222 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005223 }
5224
5225 /* Set up to return from userspace. */
5226
5227 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005228 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005229
5230 /* moveq #,d0; notb d0; trap #0 */
5231
Riku Voipio1d8b5122014-04-23 10:26:05 +03005232 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005233 (uint32_t *)(frame->retcode + 0));
5234 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005235
5236 if (err)
5237 goto give_sigsegv;
5238
5239 /* Set up to return from userspace */
5240
5241 env->aregs[7] = frame_addr;
5242 env->pc = ka->_sa_handler;
5243
5244 unlock_user_struct(frame, frame_addr, 1);
5245 return;
5246
5247give_sigsegv:
5248 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005249 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005250}
5251
Andreas Färber05390242012-02-25 03:37:53 +01005252long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005253{
5254 struct target_sigframe *frame;
5255 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005256 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005257 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005258 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02005259
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005260 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005261 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5262 goto badframe;
5263
5264 /* set blocked signals */
5265
Riku Voipiof5f601a2014-04-23 13:00:17 +03005266 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005267
5268 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005269 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005270 }
5271
5272 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005273 set_sigmask(&set);
Laurent Vivier492a8742009-08-03 16:12:17 +02005274
5275 /* restore registers */
5276
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005277 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005278
5279 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005280 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005281
5282badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005283 force_sig(TARGET_SIGSEGV);
5284 return 0;
5285}
5286
Andreas Färber05390242012-02-25 03:37:53 +01005287long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005288{
Laurent Vivier71811552009-08-03 16:12:18 +02005289 struct target_rt_sigframe *frame;
5290 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005291 target_sigset_t target_set;
Laurent Vivier71811552009-08-03 16:12:18 +02005292 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02005293
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005294 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02005295 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5296 goto badframe;
5297
5298 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005299 set_sigmask(&set);
Laurent Vivier71811552009-08-03 16:12:18 +02005300
5301 /* restore registers */
5302
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005303 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02005304 goto badframe;
5305
5306 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02005307 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02005308 0, get_sp_from_cpustate(env)) == -EFAULT)
5309 goto badframe;
5310
5311 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005312 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02005313
5314badframe:
5315 unlock_user_struct(frame, frame_addr, 0);
5316 force_sig(TARGET_SIGSEGV);
5317 return 0;
Laurent Vivier492a8742009-08-03 16:12:17 +02005318}
5319
Richard Henderson6049f4f2009-12-27 18:30:03 -08005320#elif defined(TARGET_ALPHA)
5321
5322struct target_sigcontext {
5323 abi_long sc_onstack;
5324 abi_long sc_mask;
5325 abi_long sc_pc;
5326 abi_long sc_ps;
5327 abi_long sc_regs[32];
5328 abi_long sc_ownedfp;
5329 abi_long sc_fpregs[32];
5330 abi_ulong sc_fpcr;
5331 abi_ulong sc_fp_control;
5332 abi_ulong sc_reserved1;
5333 abi_ulong sc_reserved2;
5334 abi_ulong sc_ssize;
5335 abi_ulong sc_sbase;
5336 abi_ulong sc_traparg_a0;
5337 abi_ulong sc_traparg_a1;
5338 abi_ulong sc_traparg_a2;
5339 abi_ulong sc_fp_trap_pc;
5340 abi_ulong sc_fp_trigger_sum;
5341 abi_ulong sc_fp_trigger_inst;
5342};
5343
5344struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005345 abi_ulong tuc_flags;
5346 abi_ulong tuc_link;
5347 abi_ulong tuc_osf_sigmask;
5348 target_stack_t tuc_stack;
5349 struct target_sigcontext tuc_mcontext;
5350 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005351};
5352
5353struct target_sigframe {
5354 struct target_sigcontext sc;
5355 unsigned int retcode[3];
5356};
5357
5358struct target_rt_sigframe {
5359 target_siginfo_t info;
5360 struct target_ucontext uc;
5361 unsigned int retcode[3];
5362};
5363
5364#define INSN_MOV_R30_R16 0x47fe0410
5365#define INSN_LDI_R0 0x201f0000
5366#define INSN_CALLSYS 0x00000083
5367
Riku Voipio41ecc722014-04-23 11:01:00 +03005368static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005369 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005370{
Riku Voipio41ecc722014-04-23 11:01:00 +03005371 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005372
Riku Voipio1d8b5122014-04-23 10:26:05 +03005373 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5374 __put_user(set->sig[0], &sc->sc_mask);
5375 __put_user(env->pc, &sc->sc_pc);
5376 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005377
5378 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005379 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005380 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005381 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005382
5383 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005384 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005385 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005386 __put_user(0, &sc->sc_fpregs[31]);
5387 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005388
Riku Voipio1d8b5122014-04-23 10:26:05 +03005389 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5390 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5391 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08005392}
5393
Riku Voipio016d2e12014-04-23 11:19:48 +03005394static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005395 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005396{
5397 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03005398 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005399
Riku Voipio1d8b5122014-04-23 10:26:05 +03005400 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005401
5402 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005403 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005404 }
5405 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005406 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005407 }
5408
Riku Voipio1d8b5122014-04-23 10:26:05 +03005409 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005410 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005411}
5412
5413static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01005414 CPUAlphaState *env,
5415 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005416{
5417 abi_ulong sp = env->ir[IR_SP];
5418
5419 /* This is the X/Open sanctioned signal stack switching. */
5420 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5421 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5422 }
5423 return (sp - framesize) & -32;
5424}
5425
5426static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005427 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005428{
5429 abi_ulong frame_addr, r26;
5430 struct target_sigframe *frame;
5431 int err = 0;
5432
5433 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005434 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005435 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5436 goto give_sigsegv;
5437 }
5438
Riku Voipio41ecc722014-04-23 11:01:00 +03005439 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005440
5441 if (ka->sa_restorer) {
5442 r26 = ka->sa_restorer;
5443 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005444 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5445 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5446 &frame->retcode[1]);
5447 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005448 /* imb() */
5449 r26 = frame_addr;
5450 }
5451
5452 unlock_user_struct(frame, frame_addr, 1);
5453
5454 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005455give_sigsegv:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005456 if (sig == TARGET_SIGSEGV) {
5457 ka->_sa_handler = TARGET_SIG_DFL;
5458 }
5459 force_sig(TARGET_SIGSEGV);
5460 }
5461
5462 env->ir[IR_RA] = r26;
5463 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5464 env->ir[IR_A0] = sig;
5465 env->ir[IR_A1] = 0;
5466 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5467 env->ir[IR_SP] = frame_addr;
5468}
5469
5470static void setup_rt_frame(int sig, struct target_sigaction *ka,
5471 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005472 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005473{
5474 abi_ulong frame_addr, r26;
5475 struct target_rt_sigframe *frame;
5476 int i, err = 0;
5477
5478 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005479 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005480 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5481 goto give_sigsegv;
5482 }
5483
Peter Maydellf6c7a052015-01-08 12:19:48 +00005484 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005485
Riku Voipio1d8b5122014-04-23 10:26:05 +03005486 __put_user(0, &frame->uc.tuc_flags);
5487 __put_user(0, &frame->uc.tuc_link);
5488 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5489 __put_user(target_sigaltstack_used.ss_sp,
5490 &frame->uc.tuc_stack.ss_sp);
5491 __put_user(sas_ss_flags(env->ir[IR_SP]),
5492 &frame->uc.tuc_stack.ss_flags);
5493 __put_user(target_sigaltstack_used.ss_size,
5494 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03005495 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005496 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005497 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005498 }
5499
5500 if (ka->sa_restorer) {
5501 r26 = ka->sa_restorer;
5502 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005503 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5504 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5505 &frame->retcode[1]);
5506 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005507 /* imb(); */
5508 r26 = frame_addr;
5509 }
5510
5511 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005512give_sigsegv:
5513 if (sig == TARGET_SIGSEGV) {
Richard Henderson6049f4f2009-12-27 18:30:03 -08005514 ka->_sa_handler = TARGET_SIG_DFL;
5515 }
5516 force_sig(TARGET_SIGSEGV);
5517 }
5518
5519 env->ir[IR_RA] = r26;
5520 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5521 env->ir[IR_A0] = sig;
5522 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5523 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5524 env->ir[IR_SP] = frame_addr;
5525}
5526
Andreas Färber05390242012-02-25 03:37:53 +01005527long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005528{
5529 struct target_sigcontext *sc;
5530 abi_ulong sc_addr = env->ir[IR_A0];
5531 target_sigset_t target_set;
5532 sigset_t set;
5533
5534 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5535 goto badframe;
5536 }
5537
5538 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03005539 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005540
5541 target_to_host_sigset_internal(&set, &target_set);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005542 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005543
Riku Voipio016d2e12014-04-23 11:19:48 +03005544 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005545 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005546 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005547
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005548badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005549 force_sig(TARGET_SIGSEGV);
5550}
5551
Andreas Färber05390242012-02-25 03:37:53 +01005552long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005553{
5554 abi_ulong frame_addr = env->ir[IR_A0];
5555 struct target_rt_sigframe *frame;
5556 sigset_t set;
5557
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005558 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005559 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5560 goto badframe;
5561 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02005562 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005563 set_sigmask(&set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005564
Riku Voipio016d2e12014-04-23 11:19:48 +03005565 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005566 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02005567 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08005568 0, env->ir[IR_SP]) == -EFAULT) {
5569 goto badframe;
5570 }
5571
5572 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005573 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005574
5575
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005576badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005577 unlock_user_struct(frame, frame_addr, 0);
5578 force_sig(TARGET_SIGSEGV);
5579}
5580
Chen Gangbf0f60a2015-09-27 08:10:18 +08005581#elif defined(TARGET_TILEGX)
5582
5583struct target_sigcontext {
5584 union {
5585 /* General-purpose registers. */
5586 abi_ulong gregs[56];
5587 struct {
5588 abi_ulong __gregs[53];
5589 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
5590 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
5591 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
5592 };
5593 };
5594 abi_ulong pc; /* Program counter. */
5595 abi_ulong ics; /* In Interrupt Critical Section? */
5596 abi_ulong faultnum; /* Fault number. */
5597 abi_ulong pad[5];
5598};
5599
5600struct target_ucontext {
5601 abi_ulong tuc_flags;
5602 abi_ulong tuc_link;
5603 target_stack_t tuc_stack;
5604 struct target_sigcontext tuc_mcontext;
5605 target_sigset_t tuc_sigmask; /* mask last for extensibility */
5606};
5607
5608struct target_rt_sigframe {
5609 unsigned char save_area[16]; /* caller save area */
5610 struct target_siginfo info;
5611 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08005612 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08005613};
5614
Chen Gangf1d9d102016-03-29 21:53:49 +08005615#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
5616#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
5617
5618
Chen Gangbf0f60a2015-09-27 08:10:18 +08005619static void setup_sigcontext(struct target_sigcontext *sc,
5620 CPUArchState *env, int signo)
5621{
5622 int i;
5623
5624 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5625 __put_user(env->regs[i], &sc->gregs[i]);
5626 }
5627
5628 __put_user(env->pc, &sc->pc);
5629 __put_user(0, &sc->ics);
5630 __put_user(signo, &sc->faultnum);
5631}
5632
5633static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
5634{
5635 int i;
5636
5637 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5638 __get_user(env->regs[i], &sc->gregs[i]);
5639 }
5640
5641 __get_user(env->pc, &sc->pc);
5642}
5643
5644static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
5645 size_t frame_size)
5646{
5647 unsigned long sp = env->regs[TILEGX_R_SP];
5648
5649 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
5650 return -1UL;
5651 }
5652
5653 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
5654 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5655 }
5656
5657 sp -= frame_size;
5658 sp &= -16UL;
5659 return sp;
5660}
5661
5662static void setup_rt_frame(int sig, struct target_sigaction *ka,
5663 target_siginfo_t *info,
5664 target_sigset_t *set, CPUArchState *env)
5665{
5666 abi_ulong frame_addr;
5667 struct target_rt_sigframe *frame;
5668 unsigned long restorer;
5669
5670 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005671 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005672 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5673 goto give_sigsegv;
5674 }
5675
5676 /* Always write at least the signal number for the stack backtracer. */
5677 if (ka->sa_flags & TARGET_SA_SIGINFO) {
5678 /* At sigreturn time, restore the callee-save registers too. */
5679 tswap_siginfo(&frame->info, info);
5680 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
5681 } else {
5682 __put_user(info->si_signo, &frame->info.si_signo);
5683 }
5684
5685 /* Create the ucontext. */
5686 __put_user(0, &frame->uc.tuc_flags);
5687 __put_user(0, &frame->uc.tuc_link);
5688 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
5689 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
5690 &frame->uc.tuc_stack.ss_flags);
5691 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5692 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
5693
Chen Gangbf0f60a2015-09-27 08:10:18 +08005694 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08005695 restorer = (unsigned long) ka->sa_restorer;
5696 } else {
5697 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
5698 __put_user(INSN_SWINT1, &frame->retcode[1]);
5699 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005700 }
5701 env->pc = (unsigned long) ka->_sa_handler;
5702 env->regs[TILEGX_R_SP] = (unsigned long) frame;
5703 env->regs[TILEGX_R_LR] = restorer;
5704 env->regs[0] = (unsigned long) sig;
5705 env->regs[1] = (unsigned long) &frame->info;
5706 env->regs[2] = (unsigned long) &frame->uc;
5707 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
5708
5709 unlock_user_struct(frame, frame_addr, 1);
5710 return;
5711
5712give_sigsegv:
5713 if (sig == TARGET_SIGSEGV) {
5714 ka->_sa_handler = TARGET_SIG_DFL;
5715 }
5716 force_sig(TARGET_SIGSEGV /* , current */);
5717}
5718
5719long do_rt_sigreturn(CPUTLGState *env)
5720{
5721 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
5722 struct target_rt_sigframe *frame;
5723 sigset_t set;
5724
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005725 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005726 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5727 goto badframe;
5728 }
5729 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Peter Maydell9eede5b2016-05-27 15:51:46 +01005730 set_sigmask(&set);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005731
5732 restore_sigcontext(env, &frame->uc.tuc_mcontext);
5733 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
5734 uc.tuc_stack),
5735 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
5736 goto badframe;
5737 }
5738
5739 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01005740 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08005741
5742
5743 badframe:
5744 unlock_user_struct(frame, frame_addr, 0);
5745 force_sig(TARGET_SIGSEGV);
5746}
5747
bellardb346ff42003-06-15 20:05:50 +00005748#else
5749
pbrook624f7972008-05-31 16:11:38 +00005750static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005751 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005752{
5753 fprintf(stderr, "setup_frame: not implemented\n");
5754}
5755
pbrook624f7972008-05-31 16:11:38 +00005756static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005757 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005758 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005759{
5760 fprintf(stderr, "setup_rt_frame: not implemented\n");
5761}
5762
Andreas Färber9349b4f2012-03-14 01:38:32 +01005763long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005764{
5765 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005766 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005767}
5768
Andreas Färber9349b4f2012-03-14 01:38:32 +01005769long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005770{
5771 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005772 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005773}
5774
bellard66fb9762003-03-23 01:06:05 +00005775#endif
5776
Peter Maydelleb552502016-05-27 15:51:43 +01005777static void handle_pending_signal(CPUArchState *cpu_env, int sig)
5778{
5779 CPUState *cpu = ENV_GET_CPU(cpu_env);
5780 abi_ulong handler;
5781 sigset_t set, old_set;
5782 target_sigset_t target_old_set;
5783 struct target_sigaction *sa;
5784 struct sigqueue *q;
5785 TaskState *ts = cpu->opaque;
5786 struct emulated_sigtable *k = &ts->sigtab[sig - 1];
5787
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005788 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00005789 /* dequeue signal */
5790 q = k->first;
5791 k->first = q->next;
5792 if (!k->first)
5793 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00005794
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005795 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00005796 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00005797 sa = NULL;
5798 handler = TARGET_SIG_IGN;
5799 } else {
5800 sa = &sigact_table[sig - 1];
5801 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00005802 }
bellard66fb9762003-03-23 01:06:05 +00005803
Peter Maydella7ec0f92014-03-14 14:36:56 +00005804 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
5805 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
5806 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
5807 * because it got a real MMU fault), and treat as if default handler.
5808 */
5809 handler = TARGET_SIG_DFL;
5810 }
5811
bellard66fb9762003-03-23 01:06:05 +00005812 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00005813 /* default handler : ignore some signal. The other are job control or fatal */
5814 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5815 kill(getpid(),SIGSTOP);
5816 } else if (sig != TARGET_SIGCHLD &&
5817 sig != TARGET_SIGURG &&
5818 sig != TARGET_SIGWINCH &&
5819 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +00005820 force_sig(sig);
5821 }
5822 } else if (handler == TARGET_SIG_IGN) {
5823 /* ignore sig */
5824 } else if (handler == TARGET_SIG_ERR) {
5825 force_sig(sig);
5826 } else {
bellard9de5e442003-03-23 16:49:39 +00005827 /* compute the blocked signals during the handler execution */
pbrook624f7972008-05-31 16:11:38 +00005828 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00005829 /* SA_NODEFER indicates that the current signal should not be
5830 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00005831 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00005832 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00005833
bellard9de5e442003-03-23 16:49:39 +00005834 /* block signals in the handler using Linux */
Alex Barcelo1c275922014-03-14 14:36:55 +00005835 do_sigprocmask(SIG_BLOCK, &set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005836 /* save the previous blocked signal state to restore it at the
5837 end of the signal execution (see do_sigreturn) */
bellard92319442004-06-19 16:58:13 +00005838 host_to_target_sigset_internal(&target_old_set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005839
bellardbc8a22c2003-03-30 21:02:40 +00005840 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00005841#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00005842 {
5843 CPUX86State *env = cpu_env;
5844 if (env->eflags & VM_MASK)
5845 save_v86_state(env);
5846 }
5847#endif
bellard9de5e442003-03-23 16:49:39 +00005848 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08005849#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Chen Gangbf0f60a2015-09-27 08:10:18 +08005850 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX)
Richard Hendersonff970902013-02-10 10:30:42 -08005851 /* These targets do not have traditional signals. */
5852 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
5853#else
pbrook624f7972008-05-31 16:11:38 +00005854 if (sa->sa_flags & TARGET_SA_SIGINFO)
5855 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005856 else
pbrook624f7972008-05-31 16:11:38 +00005857 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005858#endif
Peter Maydell7ec87e02016-05-27 15:51:45 +01005859 if (sa->sa_flags & TARGET_SA_RESETHAND) {
pbrook624f7972008-05-31 16:11:38 +00005860 sa->_sa_handler = TARGET_SIG_DFL;
Peter Maydell7ec87e02016-05-27 15:51:45 +01005861 }
bellard31e31b82003-02-18 22:55:36 +00005862 }
bellard66fb9762003-03-23 01:06:05 +00005863 if (q != &k->info)
pbrook624f7972008-05-31 16:11:38 +00005864 free_sigqueue(cpu_env, q);
bellard31e31b82003-02-18 22:55:36 +00005865}
Peter Maydelle902d582016-05-27 15:51:44 +01005866
5867void process_pending_signals(CPUArchState *cpu_env)
5868{
5869 CPUState *cpu = ENV_GET_CPU(cpu_env);
5870 int sig;
5871 TaskState *ts = cpu->opaque;
5872
5873 if (!ts->signal_pending)
5874 return;
5875
5876 /* FIXME: This is not threadsafe. */
5877 for(sig = 1; sig <= TARGET_NSIG; sig++) {
5878 if (ts->sigtab[sig - 1].pending) {
5879 handle_pending_signal(cpu_env, sig);
5880 return;
5881 }
5882 }
5883 /* if no signal is pending, just return */
5884 ts->signal_pending = 0;
5885 return;
5886}