blob: a072fa6efd0a5805ed3c246b75c393aee486a548 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard66fb9762003-03-23 01:06:05 +00002 * Emulation of Linux signals
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Peter Maydelld39594e2016-01-26 18:17:02 +000019#include "qemu/osdep.h"
bellard31e31b82003-02-18 22:55:36 +000020#include <sys/ucontext.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030021#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000022
bellard3ef693a2003-03-23 20:17:16 +000023#include "qemu.h"
blueswir17d99a002009-01-14 19:00:36 +000024#include "qemu-common.h"
blueswir1992f48a2007-10-14 16:27:31 +000025#include "target_signal.h"
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +010026#include "trace.h"
bellard66fb9762003-03-23 01:06:05 +000027
blueswir1249c4c32008-10-05 11:09:37 +000028static struct target_sigaltstack target_sigaltstack_used = {
thsa04e1342007-09-27 13:57:58 +000029 .ss_sp = 0,
30 .ss_size = 0,
31 .ss_flags = TARGET_SS_DISABLE,
32};
33
pbrook624f7972008-05-31 16:11:38 +000034static struct target_sigaction sigact_table[TARGET_NSIG];
bellard31e31b82003-02-18 22:55:36 +000035
ths5fafdf22007-09-16 21:08:06 +000036static void host_signal_handler(int host_signum, siginfo_t *info,
bellard66fb9762003-03-23 01:06:05 +000037 void *puc);
38
Arnaud Patard3ca05582009-03-30 01:18:20 +020039static uint8_t host_to_target_signal_table[_NSIG] = {
bellard9e5f5282003-07-13 17:33:54 +000040 [SIGHUP] = TARGET_SIGHUP,
41 [SIGINT] = TARGET_SIGINT,
42 [SIGQUIT] = TARGET_SIGQUIT,
43 [SIGILL] = TARGET_SIGILL,
44 [SIGTRAP] = TARGET_SIGTRAP,
45 [SIGABRT] = TARGET_SIGABRT,
bellard01e3b762003-09-30 21:10:14 +000046/* [SIGIOT] = TARGET_SIGIOT,*/
bellard9e5f5282003-07-13 17:33:54 +000047 [SIGBUS] = TARGET_SIGBUS,
48 [SIGFPE] = TARGET_SIGFPE,
49 [SIGKILL] = TARGET_SIGKILL,
50 [SIGUSR1] = TARGET_SIGUSR1,
51 [SIGSEGV] = TARGET_SIGSEGV,
52 [SIGUSR2] = TARGET_SIGUSR2,
53 [SIGPIPE] = TARGET_SIGPIPE,
54 [SIGALRM] = TARGET_SIGALRM,
55 [SIGTERM] = TARGET_SIGTERM,
56#ifdef SIGSTKFLT
57 [SIGSTKFLT] = TARGET_SIGSTKFLT,
58#endif
59 [SIGCHLD] = TARGET_SIGCHLD,
60 [SIGCONT] = TARGET_SIGCONT,
61 [SIGSTOP] = TARGET_SIGSTOP,
62 [SIGTSTP] = TARGET_SIGTSTP,
63 [SIGTTIN] = TARGET_SIGTTIN,
64 [SIGTTOU] = TARGET_SIGTTOU,
65 [SIGURG] = TARGET_SIGURG,
66 [SIGXCPU] = TARGET_SIGXCPU,
67 [SIGXFSZ] = TARGET_SIGXFSZ,
68 [SIGVTALRM] = TARGET_SIGVTALRM,
69 [SIGPROF] = TARGET_SIGPROF,
70 [SIGWINCH] = TARGET_SIGWINCH,
71 [SIGIO] = TARGET_SIGIO,
72 [SIGPWR] = TARGET_SIGPWR,
73 [SIGSYS] = TARGET_SIGSYS,
74 /* next signals stay the same */
pbrook624f7972008-05-31 16:11:38 +000075 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
Dong Xu Wangb4916d72011-11-22 18:06:17 +080076 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
pbrook624f7972008-05-31 16:11:38 +000077 To fix this properly we need to do manual signal delivery multiplexed
78 over a single host signal. */
79 [__SIGRTMIN] = __SIGRTMAX,
80 [__SIGRTMAX] = __SIGRTMIN,
bellard9e5f5282003-07-13 17:33:54 +000081};
Arnaud Patard3ca05582009-03-30 01:18:20 +020082static uint8_t target_to_host_signal_table[_NSIG];
bellard9e5f5282003-07-13 17:33:54 +000083
thsa04e1342007-09-27 13:57:58 +000084static inline int on_sig_stack(unsigned long sp)
85{
86 return (sp - target_sigaltstack_used.ss_sp
87 < target_sigaltstack_used.ss_size);
88}
89
90static inline int sas_ss_flags(unsigned long sp)
91{
92 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
93 : on_sig_stack(sp) ? SS_ONSTACK : 0);
94}
95
pbrook1d9d8b52009-04-16 15:17:02 +000096int host_to_target_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +000097{
Andreas Schwab167c50d2013-07-02 14:04:12 +010098 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +000099 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000100 return host_to_target_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000101}
102
pbrook4cb05962008-05-30 18:05:19 +0000103int target_to_host_signal(int sig)
bellard31e31b82003-02-18 22:55:36 +0000104{
Andreas Schwab167c50d2013-07-02 14:04:12 +0100105 if (sig < 0 || sig >= _NSIG)
pbrook4cb05962008-05-30 18:05:19 +0000106 return sig;
bellard9e5f5282003-07-13 17:33:54 +0000107 return target_to_host_signal_table[sig];
bellard31e31b82003-02-18 22:55:36 +0000108}
109
Anthony Liguoric227f092009-10-01 16:12:16 -0500110static inline void target_sigemptyset(target_sigset_t *set)
pbrookf5545b52008-05-30 22:37:07 +0000111{
112 memset(set, 0, sizeof(*set));
113}
114
Anthony Liguoric227f092009-10-01 16:12:16 -0500115static inline void target_sigaddset(target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000116{
117 signum--;
118 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
119 set->sig[signum / TARGET_NSIG_BPW] |= mask;
120}
121
Anthony Liguoric227f092009-10-01 16:12:16 -0500122static inline int target_sigismember(const target_sigset_t *set, int signum)
pbrookf5545b52008-05-30 22:37:07 +0000123{
124 signum--;
125 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
126 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
127}
128
Anthony Liguoric227f092009-10-01 16:12:16 -0500129static void host_to_target_sigset_internal(target_sigset_t *d,
bellard92319442004-06-19 16:58:13 +0000130 const sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000131{
132 int i;
pbrookf5545b52008-05-30 22:37:07 +0000133 target_sigemptyset(d);
134 for (i = 1; i <= TARGET_NSIG; i++) {
135 if (sigismember(s, i)) {
136 target_sigaddset(d, host_to_target_signal(i));
137 }
bellard9e5f5282003-07-13 17:33:54 +0000138 }
bellard66fb9762003-03-23 01:06:05 +0000139}
140
Anthony Liguoric227f092009-10-01 16:12:16 -0500141void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000142{
Anthony Liguoric227f092009-10-01 16:12:16 -0500143 target_sigset_t d1;
bellard92319442004-06-19 16:58:13 +0000144 int i;
145
146 host_to_target_sigset_internal(&d1, s);
147 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200148 d->sig[i] = tswapal(d1.sig[i]);
bellard92319442004-06-19 16:58:13 +0000149}
150
blueswir18fcd3692008-08-17 20:26:25 +0000151static void target_to_host_sigset_internal(sigset_t *d,
Anthony Liguoric227f092009-10-01 16:12:16 -0500152 const target_sigset_t *s)
bellard66fb9762003-03-23 01:06:05 +0000153{
154 int i;
pbrookf5545b52008-05-30 22:37:07 +0000155 sigemptyset(d);
156 for (i = 1; i <= TARGET_NSIG; i++) {
157 if (target_sigismember(s, i)) {
158 sigaddset(d, target_to_host_signal(i));
159 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100160 }
bellard66fb9762003-03-23 01:06:05 +0000161}
162
Anthony Liguoric227f092009-10-01 16:12:16 -0500163void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
bellard92319442004-06-19 16:58:13 +0000164{
Anthony Liguoric227f092009-10-01 16:12:16 -0500165 target_sigset_t s1;
bellard92319442004-06-19 16:58:13 +0000166 int i;
167
168 for(i = 0;i < TARGET_NSIG_WORDS; i++)
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200169 s1.sig[i] = tswapal(s->sig[i]);
bellard92319442004-06-19 16:58:13 +0000170 target_to_host_sigset_internal(d, &s1);
171}
ths3b46e622007-09-17 08:09:54 +0000172
blueswir1992f48a2007-10-14 16:27:31 +0000173void host_to_target_old_sigset(abi_ulong *old_sigset,
bellard66fb9762003-03-23 01:06:05 +0000174 const sigset_t *sigset)
175{
Anthony Liguoric227f092009-10-01 16:12:16 -0500176 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000177 host_to_target_sigset(&d, sigset);
178 *old_sigset = d.sig[0];
bellard66fb9762003-03-23 01:06:05 +0000179}
180
ths5fafdf22007-09-16 21:08:06 +0000181void target_to_host_old_sigset(sigset_t *sigset,
blueswir1992f48a2007-10-14 16:27:31 +0000182 const abi_ulong *old_sigset)
bellard66fb9762003-03-23 01:06:05 +0000183{
Anthony Liguoric227f092009-10-01 16:12:16 -0500184 target_sigset_t d;
bellard9e5f5282003-07-13 17:33:54 +0000185 int i;
186
187 d.sig[0] = *old_sigset;
188 for(i = 1;i < TARGET_NSIG_WORDS; i++)
189 d.sig[i] = 0;
190 target_to_host_sigset(sigset, &d);
bellard66fb9762003-03-23 01:06:05 +0000191}
192
Alex Barcelo1c275922014-03-14 14:36:55 +0000193/* Wrapper for sigprocmask function
194 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
195 * are host signal set, not guest ones. This wraps the sigprocmask host calls
196 * that should be protected (calls originated from guest)
197 */
198int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
199{
Peter Maydella7ec0f92014-03-14 14:36:56 +0000200 int ret;
201 sigset_t val;
202 sigset_t *temp = NULL;
203 CPUState *cpu = thread_cpu;
204 TaskState *ts = (TaskState *)cpu->opaque;
205 bool segv_was_blocked = ts->sigsegv_blocked;
206
207 if (set) {
208 bool has_sigsegv = sigismember(set, SIGSEGV);
209 val = *set;
210 temp = &val;
211
212 sigdelset(temp, SIGSEGV);
213
214 switch (how) {
215 case SIG_BLOCK:
216 if (has_sigsegv) {
217 ts->sigsegv_blocked = true;
218 }
219 break;
220 case SIG_UNBLOCK:
221 if (has_sigsegv) {
222 ts->sigsegv_blocked = false;
223 }
224 break;
225 case SIG_SETMASK:
226 ts->sigsegv_blocked = has_sigsegv;
227 break;
228 default:
229 g_assert_not_reached();
230 }
231 }
232
233 ret = sigprocmask(how, temp, oldset);
234
235 if (oldset && segv_was_blocked) {
236 sigaddset(oldset, SIGSEGV);
237 }
238
239 return ret;
Alex Barcelo1c275922014-03-14 14:36:55 +0000240}
241
bellard9de5e442003-03-23 16:49:39 +0000242/* siginfo conversion */
243
Anthony Liguoric227f092009-10-01 16:12:16 -0500244static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
bellard9de5e442003-03-23 16:49:39 +0000245 const siginfo_t *info)
bellard66fb9762003-03-23 01:06:05 +0000246{
Richard Hendersona05c6402012-09-15 11:34:20 -0700247 int sig = host_to_target_signal(info->si_signo);
bellard9de5e442003-03-23 16:49:39 +0000248 tinfo->si_signo = sig;
249 tinfo->si_errno = 0;
pbrookafd7cd92008-05-31 12:14:21 +0000250 tinfo->si_code = info->si_code;
Richard Hendersona05c6402012-09-15 11:34:20 -0700251
252 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100253 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
Richard Hendersona05c6402012-09-15 11:34:20 -0700254 /* Should never come here, but who knows. The information for
255 the target is irrelevant. */
bellard9de5e442003-03-23 16:49:39 +0000256 tinfo->_sifields._sigfault._addr = 0;
Richard Hendersona05c6402012-09-15 11:34:20 -0700257 } else if (sig == TARGET_SIGIO) {
258 tinfo->_sifields._sigpoll._band = info->si_band;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100259 tinfo->_sifields._sigpoll._fd = info->si_fd;
Richard Hendersona05c6402012-09-15 11:34:20 -0700260 } else if (sig == TARGET_SIGCHLD) {
261 tinfo->_sifields._sigchld._pid = info->si_pid;
262 tinfo->_sifields._sigchld._uid = info->si_uid;
263 tinfo->_sifields._sigchld._status
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100264 = host_to_target_waitstatus(info->si_status);
Richard Hendersona05c6402012-09-15 11:34:20 -0700265 tinfo->_sifields._sigchld._utime = info->si_utime;
266 tinfo->_sifields._sigchld._stime = info->si_stime;
bellard9de5e442003-03-23 16:49:39 +0000267 } else if (sig >= TARGET_SIGRTMIN) {
268 tinfo->_sifields._rt._pid = info->si_pid;
269 tinfo->_sifields._rt._uid = info->si_uid;
270 /* XXX: potential problem if 64 bit */
Richard Hendersona05c6402012-09-15 11:34:20 -0700271 tinfo->_sifields._rt._sigval.sival_ptr
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100272 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
bellard9de5e442003-03-23 16:49:39 +0000273 }
bellard66fb9762003-03-23 01:06:05 +0000274}
275
Anthony Liguoric227f092009-10-01 16:12:16 -0500276static void tswap_siginfo(target_siginfo_t *tinfo,
277 const target_siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000278{
Richard Hendersona05c6402012-09-15 11:34:20 -0700279 int sig = info->si_signo;
bellard9de5e442003-03-23 16:49:39 +0000280 tinfo->si_signo = tswap32(sig);
281 tinfo->si_errno = tswap32(info->si_errno);
282 tinfo->si_code = tswap32(info->si_code);
Richard Hendersona05c6402012-09-15 11:34:20 -0700283
284 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
285 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
286 tinfo->_sifields._sigfault._addr
287 = tswapal(info->_sifields._sigfault._addr);
288 } else if (sig == TARGET_SIGIO) {
289 tinfo->_sifields._sigpoll._band
290 = tswap32(info->_sifields._sigpoll._band);
291 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
292 } else if (sig == TARGET_SIGCHLD) {
293 tinfo->_sifields._sigchld._pid
294 = tswap32(info->_sifields._sigchld._pid);
295 tinfo->_sifields._sigchld._uid
296 = tswap32(info->_sifields._sigchld._uid);
297 tinfo->_sifields._sigchld._status
298 = tswap32(info->_sifields._sigchld._status);
299 tinfo->_sifields._sigchld._utime
300 = tswapal(info->_sifields._sigchld._utime);
301 tinfo->_sifields._sigchld._stime
302 = tswapal(info->_sifields._sigchld._stime);
bellard9de5e442003-03-23 16:49:39 +0000303 } else if (sig >= TARGET_SIGRTMIN) {
304 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
305 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
Richard Hendersona05c6402012-09-15 11:34:20 -0700306 tinfo->_sifields._rt._sigval.sival_ptr
307 = tswapal(info->_sifields._rt._sigval.sival_ptr);
bellard9de5e442003-03-23 16:49:39 +0000308 }
309}
310
311
Anthony Liguoric227f092009-10-01 16:12:16 -0500312void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
bellard9de5e442003-03-23 16:49:39 +0000313{
314 host_to_target_siginfo_noswap(tinfo, info);
315 tswap_siginfo(tinfo, tinfo);
316}
317
318/* XXX: we support only POSIX RT signals are used. */
thsaa1f17c2007-07-11 22:48:58 +0000319/* XXX: find a solution for 64 bit (additional malloced data is needed) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500320void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
bellard66fb9762003-03-23 01:06:05 +0000321{
322 info->si_signo = tswap32(tinfo->si_signo);
323 info->si_errno = tswap32(tinfo->si_errno);
324 info->si_code = tswap32(tinfo->si_code);
bellard9de5e442003-03-23 16:49:39 +0000325 info->si_pid = tswap32(tinfo->_sifields._rt._pid);
326 info->si_uid = tswap32(tinfo->_sifields._rt._uid);
ths5fafdf22007-09-16 21:08:06 +0000327 info->si_value.sival_ptr =
Matthias Brauncbb21ee2011-08-12 19:57:41 +0200328 (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr);
bellard66fb9762003-03-23 01:06:05 +0000329}
330
aurel32ca587a82008-12-18 22:44:13 +0000331static int fatal_signal (int sig)
332{
333 switch (sig) {
334 case TARGET_SIGCHLD:
335 case TARGET_SIGURG:
336 case TARGET_SIGWINCH:
337 /* Ignored by default. */
338 return 0;
339 case TARGET_SIGCONT:
340 case TARGET_SIGSTOP:
341 case TARGET_SIGTSTP:
342 case TARGET_SIGTTIN:
343 case TARGET_SIGTTOU:
344 /* Job control signals. */
345 return 0;
346 default:
347 return 1;
348 }
349}
350
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300351/* returns 1 if given signal should dump core if not handled */
352static int core_dump_signal(int sig)
353{
354 switch (sig) {
355 case TARGET_SIGABRT:
356 case TARGET_SIGFPE:
357 case TARGET_SIGILL:
358 case TARGET_SIGQUIT:
359 case TARGET_SIGSEGV:
360 case TARGET_SIGTRAP:
361 case TARGET_SIGBUS:
362 return (1);
363 default:
364 return (0);
365 }
366}
367
bellard31e31b82003-02-18 22:55:36 +0000368void signal_init(void)
369{
370 struct sigaction act;
pbrook624f7972008-05-31 16:11:38 +0000371 struct sigaction oact;
bellard9e5f5282003-07-13 17:33:54 +0000372 int i, j;
pbrook624f7972008-05-31 16:11:38 +0000373 int host_sig;
bellard31e31b82003-02-18 22:55:36 +0000374
bellard9e5f5282003-07-13 17:33:54 +0000375 /* generate signal conversion tables */
Arnaud Patard3ca05582009-03-30 01:18:20 +0200376 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000377 if (host_to_target_signal_table[i] == 0)
378 host_to_target_signal_table[i] = i;
379 }
Arnaud Patard3ca05582009-03-30 01:18:20 +0200380 for(i = 1; i < _NSIG; i++) {
bellard9e5f5282003-07-13 17:33:54 +0000381 j = host_to_target_signal_table[i];
382 target_to_host_signal_table[j] = i;
383 }
ths3b46e622007-09-17 08:09:54 +0000384
bellard9de5e442003-03-23 16:49:39 +0000385 /* set all host signal handlers. ALL signals are blocked during
386 the handlers to serialize them. */
pbrook624f7972008-05-31 16:11:38 +0000387 memset(sigact_table, 0, sizeof(sigact_table));
388
bellard9de5e442003-03-23 16:49:39 +0000389 sigfillset(&act.sa_mask);
bellard31e31b82003-02-18 22:55:36 +0000390 act.sa_flags = SA_SIGINFO;
391 act.sa_sigaction = host_signal_handler;
pbrook624f7972008-05-31 16:11:38 +0000392 for(i = 1; i <= TARGET_NSIG; i++) {
393 host_sig = target_to_host_signal(i);
394 sigaction(host_sig, NULL, &oact);
395 if (oact.sa_sigaction == (void *)SIG_IGN) {
396 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
397 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
398 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
399 }
400 /* If there's already a handler installed then something has
401 gone horribly wrong, so don't even try to handle that case. */
aurel32ca587a82008-12-18 22:44:13 +0000402 /* Install some handlers for our own use. We need at least
403 SIGSEGV and SIGBUS, to detect exceptions. We can not just
404 trap all signals because it affects syscall interrupt
405 behavior. But do trap all default-fatal signals. */
406 if (fatal_signal (i))
pbrook624f7972008-05-31 16:11:38 +0000407 sigaction(host_sig, &act, NULL);
bellard31e31b82003-02-18 22:55:36 +0000408 }
bellard31e31b82003-02-18 22:55:36 +0000409}
410
bellard66fb9762003-03-23 01:06:05 +0000411/* signal queue handling */
412
Andreas Färber9349b4f2012-03-14 01:38:32 +0100413static inline struct sigqueue *alloc_sigqueue(CPUArchState *env)
bellard66fb9762003-03-23 01:06:05 +0000414{
Andreas Färber0429a972013-08-26 18:14:44 +0200415 CPUState *cpu = ENV_GET_CPU(env);
416 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000417 struct sigqueue *q = ts->first_free;
bellard66fb9762003-03-23 01:06:05 +0000418 if (!q)
419 return NULL;
pbrook624f7972008-05-31 16:11:38 +0000420 ts->first_free = q->next;
bellard66fb9762003-03-23 01:06:05 +0000421 return q;
422}
423
Andreas Färber9349b4f2012-03-14 01:38:32 +0100424static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
bellard66fb9762003-03-23 01:06:05 +0000425{
Andreas Färber0429a972013-08-26 18:14:44 +0200426 CPUState *cpu = ENV_GET_CPU(env);
427 TaskState *ts = cpu->opaque;
428
pbrook624f7972008-05-31 16:11:38 +0000429 q->next = ts->first_free;
430 ts->first_free = q;
bellard66fb9762003-03-23 01:06:05 +0000431}
432
bellard9de5e442003-03-23 16:49:39 +0000433/* abort execution with signal */
Riku Voipio66393fb2009-12-04 15:16:32 +0200434static void QEMU_NORETURN force_sig(int target_sig)
bellard66fb9762003-03-23 01:06:05 +0000435{
Andreas Färber0429a972013-08-26 18:14:44 +0200436 CPUState *cpu = thread_cpu;
437 CPUArchState *env = cpu->env_ptr;
438 TaskState *ts = (TaskState *)cpu->opaque;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300439 int host_sig, core_dumped = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000440 struct sigaction act;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100441
Riku Voipio66393fb2009-12-04 15:16:32 +0200442 host_sig = target_to_host_signal(target_sig);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100443 trace_user_force_sig(env, target_sig, host_sig);
Andreas Färbera2247f82013-06-09 19:47:04 +0200444 gdb_signalled(env, target_sig);
aurel32603e4fd2009-04-15 16:18:38 +0000445
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300446 /* dump core if supported by target binary format */
Riku Voipio66393fb2009-12-04 15:16:32 +0200447 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300448 stop_all_tasks();
449 core_dumped =
Andreas Färbera2247f82013-06-09 19:47:04 +0200450 ((*ts->bprm->core_dump)(target_sig, env) == 0);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300451 }
452 if (core_dumped) {
453 /* we already dumped the core of target process, we don't want
454 * a coredump of qemu itself */
455 struct rlimit nodump;
456 getrlimit(RLIMIT_CORE, &nodump);
457 nodump.rlim_cur=0;
458 setrlimit(RLIMIT_CORE, &nodump);
459 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
Riku Voipio66393fb2009-12-04 15:16:32 +0200460 target_sig, strsignal(host_sig), "core dumped" );
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300461 }
462
Stefan Weil0c587512011-04-28 17:20:32 +0200463 /* The proper exit code for dying from an uncaught signal is
aurel32603e4fd2009-04-15 16:18:38 +0000464 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
465 * a negative value. To get the proper exit code we need to
466 * actually die from an uncaught signal. Here the default signal
467 * handler is installed, we send ourself a signal and we wait for
468 * it to arrive. */
469 sigfillset(&act.sa_mask);
470 act.sa_handler = SIG_DFL;
Peter Maydell3a5d30b2014-02-17 18:55:32 +0000471 act.sa_flags = 0;
aurel32603e4fd2009-04-15 16:18:38 +0000472 sigaction(host_sig, &act, NULL);
473
474 /* For some reason raise(host_sig) doesn't send the signal when
475 * statically linked on x86-64. */
476 kill(getpid(), host_sig);
477
478 /* Make sure the signal isn't masked (just reuse the mask inside
479 of act) */
480 sigdelset(&act.sa_mask, host_sig);
481 sigsuspend(&act.sa_mask);
482
483 /* unreachable */
Blue Swirla6c6f762010-03-13 14:18:50 +0000484 abort();
bellard66fb9762003-03-23 01:06:05 +0000485}
486
bellard9de5e442003-03-23 16:49:39 +0000487/* queue a signal so that it will be send to the virtual CPU as soon
488 as possible */
Andreas Färber9349b4f2012-03-14 01:38:32 +0100489int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
bellard31e31b82003-02-18 22:55:36 +0000490{
Andreas Färber0429a972013-08-26 18:14:44 +0200491 CPUState *cpu = ENV_GET_CPU(env);
492 TaskState *ts = cpu->opaque;
pbrook624f7972008-05-31 16:11:38 +0000493 struct emulated_sigtable *k;
bellard9de5e442003-03-23 16:49:39 +0000494 struct sigqueue *q, **pq;
blueswir1992f48a2007-10-14 16:27:31 +0000495 abi_ulong handler;
aurel32ca587a82008-12-18 22:44:13 +0000496 int queue;
bellard66fb9762003-03-23 01:06:05 +0000497
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100498 trace_user_queue_signal(env, sig);
pbrook624f7972008-05-31 16:11:38 +0000499 k = &ts->sigtab[sig - 1];
aurel32ca587a82008-12-18 22:44:13 +0000500 queue = gdb_queuesig ();
pbrook624f7972008-05-31 16:11:38 +0000501 handler = sigact_table[sig - 1]._sa_handler;
Peter Maydella7ec0f92014-03-14 14:36:56 +0000502
503 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
504 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
505 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
506 * because it got a real MMU fault). A blocked SIGSEGV in that
507 * situation is treated as if using the default handler. This is
508 * not correct if some other process has randomly sent us a SIGSEGV
509 * via kill(), but that is not easy to distinguish at this point,
510 * so we assume it doesn't happen.
511 */
512 handler = TARGET_SIG_DFL;
513 }
514
aurel32ca587a82008-12-18 22:44:13 +0000515 if (!queue && handler == TARGET_SIG_DFL) {
ths60b19692008-11-27 15:47:15 +0000516 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
517 kill(getpid(),SIGSTOP);
518 return 0;
519 } else
bellard66fb9762003-03-23 01:06:05 +0000520 /* default handler : ignore some signal. The other are fatal */
ths5fafdf22007-09-16 21:08:06 +0000521 if (sig != TARGET_SIGCHLD &&
522 sig != TARGET_SIGURG &&
ths60b19692008-11-27 15:47:15 +0000523 sig != TARGET_SIGWINCH &&
524 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +0000525 force_sig(sig);
bellard9de5e442003-03-23 16:49:39 +0000526 } else {
527 return 0; /* indicate ignored */
bellard66fb9762003-03-23 01:06:05 +0000528 }
aurel32ca587a82008-12-18 22:44:13 +0000529 } else if (!queue && handler == TARGET_SIG_IGN) {
bellard66fb9762003-03-23 01:06:05 +0000530 /* ignore signal */
bellard9de5e442003-03-23 16:49:39 +0000531 return 0;
aurel32ca587a82008-12-18 22:44:13 +0000532 } else if (!queue && handler == TARGET_SIG_ERR) {
bellard66fb9762003-03-23 01:06:05 +0000533 force_sig(sig);
534 } else {
bellard9de5e442003-03-23 16:49:39 +0000535 pq = &k->first;
536 if (sig < TARGET_SIGRTMIN) {
537 /* if non real time signal, we queue exactly one signal */
538 if (!k->pending)
539 q = &k->info;
540 else
541 return 0;
542 } else {
543 if (!k->pending) {
544 /* first signal */
545 q = &k->info;
546 } else {
pbrook624f7972008-05-31 16:11:38 +0000547 q = alloc_sigqueue(env);
bellard9de5e442003-03-23 16:49:39 +0000548 if (!q)
549 return -EAGAIN;
550 while (*pq != NULL)
551 pq = &(*pq)->next;
552 }
553 }
554 *pq = q;
555 q->info = *info;
556 q->next = NULL;
557 k->pending = 1;
558 /* signal that a new signal is pending */
pbrook624f7972008-05-31 16:11:38 +0000559 ts->signal_pending = 1;
bellard9de5e442003-03-23 16:49:39 +0000560 return 1; /* indicates that the signal was queued */
561 }
562}
563
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100564#ifndef HAVE_SAFE_SYSCALL
565static inline void rewind_if_in_safe_syscall(void *puc)
566{
567 /* Default version: never rewind */
568}
569#endif
570
ths5fafdf22007-09-16 21:08:06 +0000571static void host_signal_handler(int host_signum, siginfo_t *info,
bellard9de5e442003-03-23 16:49:39 +0000572 void *puc)
573{
Andreas Färbera2247f82013-06-09 19:47:04 +0200574 CPUArchState *env = thread_cpu->env_ptr;
bellard9de5e442003-03-23 16:49:39 +0000575 int sig;
Anthony Liguoric227f092009-10-01 16:12:16 -0500576 target_siginfo_t tinfo;
bellard9de5e442003-03-23 16:49:39 +0000577
578 /* the CPU emulator uses some host signals to detect exceptions,
aurel32eaa449b2009-01-03 13:14:52 +0000579 we forward to it some signals */
aurel32ca587a82008-12-18 22:44:13 +0000580 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
aurel32eaa449b2009-01-03 13:14:52 +0000581 && info->si_code > 0) {
bellardb346ff42003-06-15 20:05:50 +0000582 if (cpu_signal_handler(host_signum, info, puc))
bellard9de5e442003-03-23 16:49:39 +0000583 return;
584 }
585
586 /* get target signal number */
587 sig = host_to_target_signal(host_signum);
588 if (sig < 1 || sig > TARGET_NSIG)
589 return;
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +0100590 trace_user_host_signal(env, host_signum, sig);
Timothy E Baldwin4d330ce2016-05-12 18:47:46 +0100591
592 rewind_if_in_safe_syscall(puc);
593
bellard9de5e442003-03-23 16:49:39 +0000594 host_to_target_siginfo_noswap(&tinfo, info);
Andreas Färbera2247f82013-06-09 19:47:04 +0200595 if (queue_signal(env, sig, &tinfo) == 1) {
bellard9de5e442003-03-23 16:49:39 +0000596 /* interrupt the virtual CPU as soon as possible */
Andreas Färbera2247f82013-06-09 19:47:04 +0200597 cpu_exit(thread_cpu);
bellard66fb9762003-03-23 01:06:05 +0000598 }
bellard31e31b82003-02-18 22:55:36 +0000599}
600
ths0da46a62007-10-20 20:23:07 +0000601/* do_sigaltstack() returns target values and errnos. */
bellard579a97f2007-11-11 14:26:47 +0000602/* compare linux/kernel/signal.c:do_sigaltstack() */
603abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
thsa04e1342007-09-27 13:57:58 +0000604{
605 int ret;
606 struct target_sigaltstack oss;
607
608 /* XXX: test errors */
bellard579a97f2007-11-11 14:26:47 +0000609 if(uoss_addr)
thsa04e1342007-09-27 13:57:58 +0000610 {
611 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
612 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
613 __put_user(sas_ss_flags(sp), &oss.ss_flags);
614 }
615
bellard579a97f2007-11-11 14:26:47 +0000616 if(uss_addr)
thsa04e1342007-09-27 13:57:58 +0000617 {
bellard579a97f2007-11-11 14:26:47 +0000618 struct target_sigaltstack *uss;
619 struct target_sigaltstack ss;
Tom Musta0903c8b2014-08-12 13:53:40 -0500620 size_t minstacksize = TARGET_MINSIGSTKSZ;
621
622#if defined(TARGET_PPC64)
623 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
624 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
625 if (get_ppc64_abi(image) > 1) {
626 minstacksize = 4096;
627 }
628#endif
thsa04e1342007-09-27 13:57:58 +0000629
ths0da46a62007-10-20 20:23:07 +0000630 ret = -TARGET_EFAULT;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300631 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
thsa04e1342007-09-27 13:57:58 +0000632 goto out;
Riku Voipio9eeb8302014-04-23 11:26:34 +0300633 }
634 __get_user(ss.ss_sp, &uss->ss_sp);
635 __get_user(ss.ss_size, &uss->ss_size);
636 __get_user(ss.ss_flags, &uss->ss_flags);
bellard579a97f2007-11-11 14:26:47 +0000637 unlock_user_struct(uss, uss_addr, 0);
thsa04e1342007-09-27 13:57:58 +0000638
ths0da46a62007-10-20 20:23:07 +0000639 ret = -TARGET_EPERM;
thsa04e1342007-09-27 13:57:58 +0000640 if (on_sig_stack(sp))
641 goto out;
642
ths0da46a62007-10-20 20:23:07 +0000643 ret = -TARGET_EINVAL;
thsa04e1342007-09-27 13:57:58 +0000644 if (ss.ss_flags != TARGET_SS_DISABLE
645 && ss.ss_flags != TARGET_SS_ONSTACK
646 && ss.ss_flags != 0)
647 goto out;
648
649 if (ss.ss_flags == TARGET_SS_DISABLE) {
650 ss.ss_size = 0;
651 ss.ss_sp = 0;
652 } else {
ths0da46a62007-10-20 20:23:07 +0000653 ret = -TARGET_ENOMEM;
Tom Musta0903c8b2014-08-12 13:53:40 -0500654 if (ss.ss_size < minstacksize) {
thsa04e1342007-09-27 13:57:58 +0000655 goto out;
Tom Musta0903c8b2014-08-12 13:53:40 -0500656 }
thsa04e1342007-09-27 13:57:58 +0000657 }
658
659 target_sigaltstack_used.ss_sp = ss.ss_sp;
660 target_sigaltstack_used.ss_size = ss.ss_size;
661 }
662
bellard579a97f2007-11-11 14:26:47 +0000663 if (uoss_addr) {
ths0da46a62007-10-20 20:23:07 +0000664 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +0000665 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
thsa04e1342007-09-27 13:57:58 +0000666 goto out;
thsa04e1342007-09-27 13:57:58 +0000667 }
668
669 ret = 0;
670out:
671 return ret;
672}
673
ths0da46a62007-10-20 20:23:07 +0000674/* do_sigaction() return host values and errnos */
bellard66fb9762003-03-23 01:06:05 +0000675int do_sigaction(int sig, const struct target_sigaction *act,
676 struct target_sigaction *oact)
bellard31e31b82003-02-18 22:55:36 +0000677{
pbrook624f7972008-05-31 16:11:38 +0000678 struct target_sigaction *k;
bellard773b93e2004-01-04 17:15:59 +0000679 struct sigaction act1;
680 int host_sig;
ths0da46a62007-10-20 20:23:07 +0000681 int ret = 0;
bellard31e31b82003-02-18 22:55:36 +0000682
ths2a913eb2008-11-27 15:46:25 +0000683 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
bellard66fb9762003-03-23 01:06:05 +0000684 return -EINVAL;
685 k = &sigact_table[sig - 1];
bellard66fb9762003-03-23 01:06:05 +0000686 if (oact) {
Richard Hendersond2565872013-01-04 16:39:32 -0800687 __put_user(k->_sa_handler, &oact->_sa_handler);
688 __put_user(k->sa_flags, &oact->sa_flags);
ths388bb212007-05-13 13:58:00 +0000689#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800690 __put_user(k->sa_restorer, &oact->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000691#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800692 /* Not swapped. */
pbrook624f7972008-05-31 16:11:38 +0000693 oact->sa_mask = k->sa_mask;
bellard66fb9762003-03-23 01:06:05 +0000694 }
695 if (act) {
pbrook624f7972008-05-31 16:11:38 +0000696 /* FIXME: This is not threadsafe. */
Richard Hendersond2565872013-01-04 16:39:32 -0800697 __get_user(k->_sa_handler, &act->_sa_handler);
698 __get_user(k->sa_flags, &act->sa_flags);
ths388bb212007-05-13 13:58:00 +0000699#if !defined(TARGET_MIPS)
Richard Hendersond2565872013-01-04 16:39:32 -0800700 __get_user(k->sa_restorer, &act->sa_restorer);
ths388bb212007-05-13 13:58:00 +0000701#endif
Richard Hendersond2565872013-01-04 16:39:32 -0800702 /* To be swapped in target_to_host_sigset. */
pbrook624f7972008-05-31 16:11:38 +0000703 k->sa_mask = act->sa_mask;
bellard773b93e2004-01-04 17:15:59 +0000704
705 /* we update the host linux signal state */
706 host_sig = target_to_host_signal(sig);
707 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
708 sigfillset(&act1.sa_mask);
709 act1.sa_flags = SA_SIGINFO;
pbrook624f7972008-05-31 16:11:38 +0000710 if (k->sa_flags & TARGET_SA_RESTART)
bellard773b93e2004-01-04 17:15:59 +0000711 act1.sa_flags |= SA_RESTART;
712 /* NOTE: it is important to update the host kernel signal
713 ignore state to avoid getting unexpected interrupted
714 syscalls */
pbrook624f7972008-05-31 16:11:38 +0000715 if (k->_sa_handler == TARGET_SIG_IGN) {
bellard773b93e2004-01-04 17:15:59 +0000716 act1.sa_sigaction = (void *)SIG_IGN;
pbrook624f7972008-05-31 16:11:38 +0000717 } else if (k->_sa_handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +0000718 if (fatal_signal (sig))
719 act1.sa_sigaction = host_signal_handler;
720 else
721 act1.sa_sigaction = (void *)SIG_DFL;
bellard773b93e2004-01-04 17:15:59 +0000722 } else {
723 act1.sa_sigaction = host_signal_handler;
724 }
ths0da46a62007-10-20 20:23:07 +0000725 ret = sigaction(host_sig, &act1, NULL);
bellard773b93e2004-01-04 17:15:59 +0000726 }
bellard66fb9762003-03-23 01:06:05 +0000727 }
ths0da46a62007-10-20 20:23:07 +0000728 return ret;
bellard66fb9762003-03-23 01:06:05 +0000729}
bellard31e31b82003-02-18 22:55:36 +0000730
bellard459a4012007-11-11 19:45:10 +0000731#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
bellard66fb9762003-03-23 01:06:05 +0000732
733/* from the Linux kernel */
734
735struct target_fpreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100736 uint16_t significand[4];
737 uint16_t exponent;
bellard66fb9762003-03-23 01:06:05 +0000738};
739
740struct target_fpxreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100741 uint16_t significand[4];
742 uint16_t exponent;
743 uint16_t padding[3];
bellard66fb9762003-03-23 01:06:05 +0000744};
745
746struct target_xmmreg {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100747 abi_ulong element[4];
bellard66fb9762003-03-23 01:06:05 +0000748};
749
750struct target_fpstate {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100751 /* Regular FPU environment */
752 abi_ulong cw;
753 abi_ulong sw;
754 abi_ulong tag;
755 abi_ulong ipoff;
756 abi_ulong cssel;
757 abi_ulong dataoff;
758 abi_ulong datasel;
759 struct target_fpreg _st[8];
760 uint16_t status;
761 uint16_t magic; /* 0xffff = regular FPU data only */
bellard66fb9762003-03-23 01:06:05 +0000762
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100763 /* FXSR FPU environment */
764 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
765 abi_ulong mxcsr;
766 abi_ulong reserved;
767 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
768 struct target_xmmreg _xmm[8];
769 abi_ulong padding[56];
bellard66fb9762003-03-23 01:06:05 +0000770};
771
772#define X86_FXSR_MAGIC 0x0000
773
774struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100775 uint16_t gs, __gsh;
776 uint16_t fs, __fsh;
777 uint16_t es, __esh;
778 uint16_t ds, __dsh;
779 abi_ulong edi;
780 abi_ulong esi;
781 abi_ulong ebp;
782 abi_ulong esp;
783 abi_ulong ebx;
784 abi_ulong edx;
785 abi_ulong ecx;
786 abi_ulong eax;
787 abi_ulong trapno;
788 abi_ulong err;
789 abi_ulong eip;
790 uint16_t cs, __csh;
791 abi_ulong eflags;
792 abi_ulong esp_at_signal;
793 uint16_t ss, __ssh;
794 abi_ulong fpstate; /* pointer */
795 abi_ulong oldmask;
796 abi_ulong cr2;
bellard66fb9762003-03-23 01:06:05 +0000797};
798
bellard66fb9762003-03-23 01:06:05 +0000799struct target_ucontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100800 abi_ulong tuc_flags;
801 abi_ulong tuc_link;
802 target_stack_t tuc_stack;
803 struct target_sigcontext tuc_mcontext;
804 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard66fb9762003-03-23 01:06:05 +0000805};
806
807struct sigframe
808{
blueswir1992f48a2007-10-14 16:27:31 +0000809 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000810 int sig;
811 struct target_sigcontext sc;
812 struct target_fpstate fpstate;
blueswir1992f48a2007-10-14 16:27:31 +0000813 abi_ulong extramask[TARGET_NSIG_WORDS-1];
bellard66fb9762003-03-23 01:06:05 +0000814 char retcode[8];
815};
816
817struct rt_sigframe
818{
blueswir1992f48a2007-10-14 16:27:31 +0000819 abi_ulong pretcode;
bellard66fb9762003-03-23 01:06:05 +0000820 int sig;
blueswir1992f48a2007-10-14 16:27:31 +0000821 abi_ulong pinfo;
822 abi_ulong puc;
bellard66fb9762003-03-23 01:06:05 +0000823 struct target_siginfo info;
824 struct target_ucontext uc;
825 struct target_fpstate fpstate;
826 char retcode[8];
827};
828
829/*
830 * Set up a signal frame.
831 */
832
bellard66fb9762003-03-23 01:06:05 +0000833/* XXX: save x87 state */
Riku Voipio41ecc722014-04-23 11:01:00 +0300834static void setup_sigcontext(struct target_sigcontext *sc,
835 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
836 abi_ulong fpstate_addr)
bellard66fb9762003-03-23 01:06:05 +0000837{
Andreas Färber27103422013-08-26 08:31:06 +0200838 CPUState *cs = CPU(x86_env_get_cpu(env));
Andreas Färber27103422013-08-26 08:31:06 +0200839 uint16_t magic;
bellard66fb9762003-03-23 01:06:05 +0000840
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100841 /* already locked in setup_frame() */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300842 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
843 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
844 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
845 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
846 __put_user(env->regs[R_EDI], &sc->edi);
847 __put_user(env->regs[R_ESI], &sc->esi);
848 __put_user(env->regs[R_EBP], &sc->ebp);
849 __put_user(env->regs[R_ESP], &sc->esp);
850 __put_user(env->regs[R_EBX], &sc->ebx);
851 __put_user(env->regs[R_EDX], &sc->edx);
852 __put_user(env->regs[R_ECX], &sc->ecx);
853 __put_user(env->regs[R_EAX], &sc->eax);
854 __put_user(cs->exception_index, &sc->trapno);
855 __put_user(env->error_code, &sc->err);
856 __put_user(env->eip, &sc->eip);
857 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
858 __put_user(env->eflags, &sc->eflags);
859 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
860 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
bellarded2dcdf2003-05-29 20:06:27 +0000861
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100862 cpu_x86_fsave(env, fpstate_addr, 1);
863 fpstate->status = fpstate->sw;
864 magic = 0xffff;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300865 __put_user(magic, &fpstate->magic);
866 __put_user(fpstate_addr, &sc->fpstate);
bellarded2dcdf2003-05-29 20:06:27 +0000867
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100868 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300869 __put_user(mask, &sc->oldmask);
870 __put_user(env->cr[2], &sc->cr2);
bellard66fb9762003-03-23 01:06:05 +0000871}
872
873/*
874 * Determine which stack to use..
875 */
876
bellard579a97f2007-11-11 14:26:47 +0000877static inline abi_ulong
pbrook624f7972008-05-31 16:11:38 +0000878get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
bellard66fb9762003-03-23 01:06:05 +0000879{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100880 unsigned long esp;
bellard66fb9762003-03-23 01:06:05 +0000881
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100882 /* Default to using normal stack */
883 esp = env->regs[R_ESP];
884 /* This is the X/Open sanctioned signal stack switching. */
885 if (ka->sa_flags & TARGET_SA_ONSTACK) {
886 if (sas_ss_flags(esp) == 0) {
887 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
thsa04e1342007-09-27 13:57:58 +0000888 }
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100889 } else {
bellard66fb9762003-03-23 01:06:05 +0000890
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100891 /* This is the legacy signal stack switching. */
bellarda52c7572003-06-21 13:14:12 +0000892 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100893 !(ka->sa_flags & TARGET_SA_RESTORER) &&
894 ka->sa_restorer) {
pbrook624f7972008-05-31 16:11:38 +0000895 esp = (unsigned long) ka->sa_restorer;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100896 }
897 }
898 return (esp - frame_size) & -8ul;
bellard66fb9762003-03-23 01:06:05 +0000899}
900
bellard579a97f2007-11-11 14:26:47 +0000901/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +0000902static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100903 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000904{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100905 abi_ulong frame_addr;
906 struct sigframe *frame;
907 int i;
bellard66fb9762003-03-23 01:06:05 +0000908
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100909 frame_addr = get_sigframe(ka, env, sizeof(*frame));
910 trace_user_setup_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +0000911
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100912 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
913 goto give_sigsegv;
bellard579a97f2007-11-11 14:26:47 +0000914
Peter Maydellb6e2c932015-01-08 12:19:43 +0000915 __put_user(sig, &frame->sig);
bellard66fb9762003-03-23 01:06:05 +0000916
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100917 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
918 frame_addr + offsetof(struct sigframe, fpstate));
bellard66fb9762003-03-23 01:06:05 +0000919
Riku Voipio7df2fa32014-04-23 10:34:53 +0300920 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
921 __put_user(set->sig[i], &frame->extramask[i - 1]);
922 }
bellard66fb9762003-03-23 01:06:05 +0000923
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100924 /* Set up to return from userspace. If provided, use a stub
925 already in userspace. */
926 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +0300927 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100928 } else {
929 uint16_t val16;
930 abi_ulong retcode_addr;
931 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300932 __put_user(retcode_addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100933 /* This is popl %eax ; movl $,%eax ; int $0x80 */
934 val16 = 0xb858;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300935 __put_user(val16, (uint16_t *)(frame->retcode+0));
936 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100937 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +0300938 __put_user(val16, (uint16_t *)(frame->retcode+6));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100939 }
bellard66fb9762003-03-23 01:06:05 +0000940
bellard66fb9762003-03-23 01:06:05 +0000941
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100942 /* Set up registers for signal handler */
943 env->regs[R_ESP] = frame_addr;
944 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +0000945
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100946 cpu_x86_load_seg(env, R_DS, __USER_DS);
947 cpu_x86_load_seg(env, R_ES, __USER_DS);
948 cpu_x86_load_seg(env, R_SS, __USER_DS);
949 cpu_x86_load_seg(env, R_CS, __USER_CS);
950 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +0000951
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100952 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000953
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100954 return;
bellard66fb9762003-03-23 01:06:05 +0000955
956give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100957 if (sig == TARGET_SIGSEGV) {
958 ka->_sa_handler = TARGET_SIG_DFL;
959 }
960 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +0000961}
962
bellard579a97f2007-11-11 14:26:47 +0000963/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +0000964static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -0500965 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100966 target_sigset_t *set, CPUX86State *env)
bellard66fb9762003-03-23 01:06:05 +0000967{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100968 abi_ulong frame_addr, addr;
969 struct rt_sigframe *frame;
970 int i;
bellard66fb9762003-03-23 01:06:05 +0000971
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100972 frame_addr = get_sigframe(ka, env, sizeof(*frame));
973 trace_user_setup_rt_frame(env, frame_addr);
bellard66fb9762003-03-23 01:06:05 +0000974
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100975 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
976 goto give_sigsegv;
bellard66fb9762003-03-23 01:06:05 +0000977
Peter Maydellb6e2c932015-01-08 12:19:43 +0000978 __put_user(sig, &frame->sig);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100979 addr = frame_addr + offsetof(struct rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300980 __put_user(addr, &frame->pinfo);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100981 addr = frame_addr + offsetof(struct rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +0300982 __put_user(addr, &frame->puc);
Peter Maydellf6c7a052015-01-08 12:19:48 +0000983 tswap_siginfo(&frame->info, info);
bellard66fb9762003-03-23 01:06:05 +0000984
Timothy E Baldwinda7c8642016-05-12 18:47:27 +0100985 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +0300986 __put_user(0, &frame->uc.tuc_flags);
987 __put_user(0, &frame->uc.tuc_link);
988 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
989 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
990 &frame->uc.tuc_stack.ss_flags);
991 __put_user(target_sigaltstack_used.ss_size,
992 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +0300993 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
994 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
995
Riku Voipio0188fad2014-04-23 13:34:15 +0300996 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
997 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
998 }
bellard66fb9762003-03-23 01:06:05 +0000999
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001000 /* Set up to return from userspace. If provided, use a stub
1001 already in userspace. */
1002 if (ka->sa_flags & TARGET_SA_RESTORER) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03001003 __put_user(ka->sa_restorer, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001004 } else {
1005 uint16_t val16;
1006 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03001007 __put_user(addr, &frame->pretcode);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001008 /* This is movl $,%eax ; int $0x80 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03001009 __put_user(0xb8, (char *)(frame->retcode+0));
1010 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001011 val16 = 0x80cd;
Riku Voipio1d8b5122014-04-23 10:26:05 +03001012 __put_user(val16, (uint16_t *)(frame->retcode+5));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001013 }
bellard66fb9762003-03-23 01:06:05 +00001014
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001015 /* Set up registers for signal handler */
1016 env->regs[R_ESP] = frame_addr;
1017 env->eip = ka->_sa_handler;
bellard66fb9762003-03-23 01:06:05 +00001018
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001019 cpu_x86_load_seg(env, R_DS, __USER_DS);
1020 cpu_x86_load_seg(env, R_ES, __USER_DS);
1021 cpu_x86_load_seg(env, R_SS, __USER_DS);
1022 cpu_x86_load_seg(env, R_CS, __USER_CS);
1023 env->eflags &= ~TF_MASK;
bellard66fb9762003-03-23 01:06:05 +00001024
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001025 unlock_user_struct(frame, frame_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001026
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001027 return;
bellard66fb9762003-03-23 01:06:05 +00001028
1029give_sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001030 if (sig == TARGET_SIGSEGV) {
1031 ka->_sa_handler = TARGET_SIG_DFL;
1032 }
1033 force_sig(TARGET_SIGSEGV /* , current */);
bellard66fb9762003-03-23 01:06:05 +00001034}
1035
1036static int
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001037restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
bellard66fb9762003-03-23 01:06:05 +00001038{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001039 unsigned int err = 0;
1040 abi_ulong fpstate_addr;
1041 unsigned int tmpflags;
bellard66fb9762003-03-23 01:06:05 +00001042
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001043 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1044 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1045 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1046 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
bellard66fb9762003-03-23 01:06:05 +00001047
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001048 env->regs[R_EDI] = tswapl(sc->edi);
1049 env->regs[R_ESI] = tswapl(sc->esi);
1050 env->regs[R_EBP] = tswapl(sc->ebp);
1051 env->regs[R_ESP] = tswapl(sc->esp);
1052 env->regs[R_EBX] = tswapl(sc->ebx);
1053 env->regs[R_EDX] = tswapl(sc->edx);
1054 env->regs[R_ECX] = tswapl(sc->ecx);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001055 env->regs[R_EAX] = tswapl(sc->eax);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001056 env->eip = tswapl(sc->eip);
bellard66fb9762003-03-23 01:06:05 +00001057
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001058 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1059 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
ths5fafdf22007-09-16 21:08:06 +00001060
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001061 tmpflags = tswapl(sc->eflags);
1062 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1063 // regs->orig_eax = -1; /* disable syscall checks */
bellard28be6232007-11-11 22:23:38 +00001064
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001065 fpstate_addr = tswapl(sc->fpstate);
1066 if (fpstate_addr != 0) {
1067 if (!access_ok(VERIFY_READ, fpstate_addr,
1068 sizeof(struct target_fpstate)))
1069 goto badframe;
1070 cpu_x86_frstor(env, fpstate_addr, 1);
1071 }
bellard66fb9762003-03-23 01:06:05 +00001072
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001073 return err;
bellard66fb9762003-03-23 01:06:05 +00001074badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001075 return 1;
bellard66fb9762003-03-23 01:06:05 +00001076}
1077
1078long do_sigreturn(CPUX86State *env)
1079{
bellard579a97f2007-11-11 14:26:47 +00001080 struct sigframe *frame;
1081 abi_ulong frame_addr = env->regs[R_ESP] - 8;
Anthony Liguoric227f092009-10-01 16:12:16 -05001082 target_sigset_t target_set;
bellard66fb9762003-03-23 01:06:05 +00001083 sigset_t set;
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001084 int i;
bellard66fb9762003-03-23 01:06:05 +00001085
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001086 trace_user_do_sigreturn(env, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00001087 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1088 goto badframe;
bellard66fb9762003-03-23 01:06:05 +00001089 /* set blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03001090 __get_user(target_set.sig[0], &frame->sc.oldmask);
bellard92319442004-06-19 16:58:13 +00001091 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03001092 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
bellard92319442004-06-19 16:58:13 +00001093 }
bellard66fb9762003-03-23 01:06:05 +00001094
bellard92319442004-06-19 16:58:13 +00001095 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00001096 do_sigprocmask(SIG_SETMASK, &set, NULL);
ths3b46e622007-09-17 08:09:54 +00001097
bellard66fb9762003-03-23 01:06:05 +00001098 /* restore registers */
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001099 if (restore_sigcontext(env, &frame->sc))
bellard66fb9762003-03-23 01:06:05 +00001100 goto badframe;
bellard579a97f2007-11-11 14:26:47 +00001101 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001102 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001103
1104badframe:
bellard579a97f2007-11-11 14:26:47 +00001105 unlock_user_struct(frame, frame_addr, 0);
bellard66fb9762003-03-23 01:06:05 +00001106 force_sig(TARGET_SIGSEGV);
1107 return 0;
1108}
1109
1110long do_rt_sigreturn(CPUX86State *env)
1111{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001112 abi_ulong frame_addr;
1113 struct rt_sigframe *frame;
1114 sigset_t set;
bellard66fb9762003-03-23 01:06:05 +00001115
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001116 frame_addr = env->regs[R_ESP] - 4;
1117 trace_user_do_rt_sigreturn(env, frame_addr);
1118 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1119 goto badframe;
1120 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
1121 do_sigprocmask(SIG_SETMASK, &set, NULL);
ths5fafdf22007-09-16 21:08:06 +00001122
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001123 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001124 goto badframe;
1125 }
bellard66fb9762003-03-23 01:06:05 +00001126
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001127 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1128 get_sp_from_cpustate(env)) == -EFAULT) {
1129 goto badframe;
1130 }
thsa04e1342007-09-27 13:57:58 +00001131
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001132 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin0284b032016-05-12 18:47:30 +01001133 return -TARGET_QEMU_ESIGRETURN;
bellard66fb9762003-03-23 01:06:05 +00001134
1135badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001136 unlock_user_struct(frame, frame_addr, 0);
1137 force_sig(TARGET_SIGSEGV);
1138 return 0;
bellard66fb9762003-03-23 01:06:05 +00001139}
1140
Andreas Schwab1744aea2013-09-03 20:12:16 +01001141#elif defined(TARGET_AARCH64)
1142
1143struct target_sigcontext {
1144 uint64_t fault_address;
1145 /* AArch64 registers */
1146 uint64_t regs[31];
1147 uint64_t sp;
1148 uint64_t pc;
1149 uint64_t pstate;
1150 /* 4K reserved for FP/SIMD state and future expansion */
1151 char __reserved[4096] __attribute__((__aligned__(16)));
1152};
1153
1154struct target_ucontext {
1155 abi_ulong tuc_flags;
1156 abi_ulong tuc_link;
1157 target_stack_t tuc_stack;
1158 target_sigset_t tuc_sigmask;
1159 /* glibc uses a 1024-bit sigset_t */
1160 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1161 /* last for future expansion */
1162 struct target_sigcontext tuc_mcontext;
1163};
1164
1165/*
1166 * Header to be used at the beginning of structures extending the user
1167 * context. Such structures must be placed after the rt_sigframe on the stack
1168 * and be 16-byte aligned. The last structure must be a dummy one with the
1169 * magic and size set to 0.
1170 */
1171struct target_aarch64_ctx {
1172 uint32_t magic;
1173 uint32_t size;
1174};
1175
1176#define TARGET_FPSIMD_MAGIC 0x46508001
1177
1178struct target_fpsimd_context {
1179 struct target_aarch64_ctx head;
1180 uint32_t fpsr;
1181 uint32_t fpcr;
1182 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1183};
1184
1185/*
1186 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1187 * user space as it will change with the addition of new context. User space
1188 * should check the magic/size information.
1189 */
1190struct target_aux_context {
1191 struct target_fpsimd_context fpsimd;
1192 /* additional context to be added before "end" */
1193 struct target_aarch64_ctx end;
1194};
1195
1196struct target_rt_sigframe {
1197 struct target_siginfo info;
1198 struct target_ucontext uc;
1199 uint64_t fp;
1200 uint64_t lr;
1201 uint32_t tramp[2];
1202};
1203
1204static int target_setup_sigframe(struct target_rt_sigframe *sf,
1205 CPUARMState *env, target_sigset_t *set)
1206{
1207 int i;
1208 struct target_aux_context *aux =
1209 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1210
1211 /* set up the stack frame for unwinding */
1212 __put_user(env->xregs[29], &sf->fp);
1213 __put_user(env->xregs[30], &sf->lr);
1214
1215 for (i = 0; i < 31; i++) {
1216 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1217 }
1218 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1219 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001220 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001221
Peter Maydell7af03922014-05-01 18:36:17 +01001222 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001223
1224 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1225 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1226 }
1227
1228 for (i = 0; i < 32; i++) {
1229#ifdef TARGET_WORDS_BIGENDIAN
1230 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1231 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1232#else
1233 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1234 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1235#endif
1236 }
Will Newtone0ee1382014-01-04 22:15:48 +00001237 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1238 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001239 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1240 __put_user(sizeof(struct target_fpsimd_context),
1241 &aux->fpsimd.head.size);
1242
1243 /* set the "end" magic */
1244 __put_user(0, &aux->end.magic);
1245 __put_user(0, &aux->end.size);
1246
1247 return 0;
1248}
1249
1250static int target_restore_sigframe(CPUARMState *env,
1251 struct target_rt_sigframe *sf)
1252{
1253 sigset_t set;
1254 int i;
1255 struct target_aux_context *aux =
1256 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
Will Newtone0ee1382014-01-04 22:15:48 +00001257 uint32_t magic, size, fpsr, fpcr;
Peter Maydelld3563122013-12-17 19:42:30 +00001258 uint64_t pstate;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001259
1260 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001261 do_sigprocmask(SIG_SETMASK, &set, NULL);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001262
1263 for (i = 0; i < 31; i++) {
1264 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1265 }
1266
1267 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1268 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
Peter Maydelld3563122013-12-17 19:42:30 +00001269 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1270 pstate_write(env, pstate);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001271
1272 __get_user(magic, &aux->fpsimd.head.magic);
1273 __get_user(size, &aux->fpsimd.head.size);
1274
1275 if (magic != TARGET_FPSIMD_MAGIC
1276 || size != sizeof(struct target_fpsimd_context)) {
1277 return 1;
1278 }
1279
Peter Maydell4cf23482014-03-02 19:36:38 +00001280 for (i = 0; i < 32; i++) {
1281#ifdef TARGET_WORDS_BIGENDIAN
1282 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1283 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1284#else
1285 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1286 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1287#endif
Andreas Schwab1744aea2013-09-03 20:12:16 +01001288 }
Will Newtone0ee1382014-01-04 22:15:48 +00001289 __get_user(fpsr, &aux->fpsimd.fpsr);
1290 vfp_set_fpsr(env, fpsr);
1291 __get_user(fpcr, &aux->fpsimd.fpcr);
1292 vfp_set_fpcr(env, fpcr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001293
1294 return 0;
1295}
1296
1297static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1298{
1299 abi_ulong sp;
1300
1301 sp = env->xregs[31];
1302
1303 /*
1304 * This is the X/Open sanctioned signal stack switching.
1305 */
Riku Voipiob545f632014-07-15 17:01:55 +03001306 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
Andreas Schwab1744aea2013-09-03 20:12:16 +01001307 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1308 }
1309
1310 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1311
1312 return sp;
1313}
1314
1315static void target_setup_frame(int usig, struct target_sigaction *ka,
1316 target_siginfo_t *info, target_sigset_t *set,
1317 CPUARMState *env)
1318{
1319 struct target_rt_sigframe *frame;
Michael Matz8a3ae912014-03-02 19:36:39 +00001320 abi_ulong frame_addr, return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001321
1322 frame_addr = get_sigframe(ka, env);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001323 trace_user_setup_frame(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001324 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1325 goto give_sigsegv;
1326 }
1327
1328 __put_user(0, &frame->uc.tuc_flags);
1329 __put_user(0, &frame->uc.tuc_link);
1330
1331 __put_user(target_sigaltstack_used.ss_sp,
1332 &frame->uc.tuc_stack.ss_sp);
1333 __put_user(sas_ss_flags(env->xregs[31]),
1334 &frame->uc.tuc_stack.ss_flags);
1335 __put_user(target_sigaltstack_used.ss_size,
1336 &frame->uc.tuc_stack.ss_size);
1337 target_setup_sigframe(frame, env, set);
Michael Matz8a3ae912014-03-02 19:36:39 +00001338 if (ka->sa_flags & TARGET_SA_RESTORER) {
1339 return_addr = ka->sa_restorer;
1340 } else {
1341 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1342 __put_user(0xd2801168, &frame->tramp[0]);
1343 __put_user(0xd4000001, &frame->tramp[1]);
1344 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1345 }
Andreas Schwab1744aea2013-09-03 20:12:16 +01001346 env->xregs[0] = usig;
1347 env->xregs[31] = frame_addr;
1348 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1349 env->pc = ka->_sa_handler;
Michael Matz8a3ae912014-03-02 19:36:39 +00001350 env->xregs[30] = return_addr;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001351 if (info) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00001352 tswap_siginfo(&frame->info, info);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001353 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1354 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1355 }
1356
1357 unlock_user_struct(frame, frame_addr, 1);
1358 return;
1359
1360 give_sigsegv:
1361 unlock_user_struct(frame, frame_addr, 1);
1362 force_sig(TARGET_SIGSEGV);
1363}
1364
1365static void setup_rt_frame(int sig, struct target_sigaction *ka,
1366 target_siginfo_t *info, target_sigset_t *set,
1367 CPUARMState *env)
1368{
1369 target_setup_frame(sig, ka, info, set, env);
1370}
1371
1372static void setup_frame(int sig, struct target_sigaction *ka,
1373 target_sigset_t *set, CPUARMState *env)
1374{
1375 target_setup_frame(sig, ka, 0, set, env);
1376}
1377
1378long do_rt_sigreturn(CPUARMState *env)
1379{
Peter Maydell7f72cd22014-03-12 13:06:00 +00001380 struct target_rt_sigframe *frame = NULL;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001381 abi_ulong frame_addr = env->xregs[31];
1382
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01001383 trace_user_do_rt_sigreturn(env, frame_addr);
Andreas Schwab1744aea2013-09-03 20:12:16 +01001384 if (frame_addr & 15) {
1385 goto badframe;
1386 }
1387
1388 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1389 goto badframe;
1390 }
1391
1392 if (target_restore_sigframe(env, frame)) {
1393 goto badframe;
1394 }
1395
1396 if (do_sigaltstack(frame_addr +
1397 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1398 0, get_sp_from_cpustate(env)) == -EFAULT) {
1399 goto badframe;
1400 }
1401
1402 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001403 return -TARGET_QEMU_ESIGRETURN;
Andreas Schwab1744aea2013-09-03 20:12:16 +01001404
1405 badframe:
1406 unlock_user_struct(frame, frame_addr, 0);
1407 force_sig(TARGET_SIGSEGV);
1408 return 0;
1409}
1410
1411long do_sigreturn(CPUARMState *env)
1412{
1413 return do_rt_sigreturn(env);
1414}
1415
bellard43fff232003-07-09 19:31:39 +00001416#elif defined(TARGET_ARM)
1417
1418struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001419 abi_ulong trap_no;
1420 abi_ulong error_code;
1421 abi_ulong oldmask;
1422 abi_ulong arm_r0;
1423 abi_ulong arm_r1;
1424 abi_ulong arm_r2;
1425 abi_ulong arm_r3;
1426 abi_ulong arm_r4;
1427 abi_ulong arm_r5;
1428 abi_ulong arm_r6;
1429 abi_ulong arm_r7;
1430 abi_ulong arm_r8;
1431 abi_ulong arm_r9;
1432 abi_ulong arm_r10;
1433 abi_ulong arm_fp;
1434 abi_ulong arm_ip;
1435 abi_ulong arm_sp;
1436 abi_ulong arm_lr;
1437 abi_ulong arm_pc;
1438 abi_ulong arm_cpsr;
1439 abi_ulong fault_address;
bellard43fff232003-07-09 19:31:39 +00001440};
1441
pbrooka745ec62008-05-06 15:36:17 +00001442struct target_ucontext_v1 {
blueswir1992f48a2007-10-14 16:27:31 +00001443 abi_ulong tuc_flags;
1444 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001445 target_stack_t tuc_stack;
bellardb8076a72005-04-07 22:20:31 +00001446 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001447 target_sigset_t tuc_sigmask; /* mask last for extensibility */
bellard43fff232003-07-09 19:31:39 +00001448};
1449
pbrooka745ec62008-05-06 15:36:17 +00001450struct target_ucontext_v2 {
1451 abi_ulong tuc_flags;
1452 abi_ulong tuc_link;
Anthony Liguoric227f092009-10-01 16:12:16 -05001453 target_stack_t tuc_stack;
pbrooka745ec62008-05-06 15:36:17 +00001454 struct target_sigcontext tuc_mcontext;
Anthony Liguoric227f092009-10-01 16:12:16 -05001455 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Peter Maydell5f0b7c82010-11-24 15:20:03 +00001456 char __unused[128 - sizeof(target_sigset_t)];
pbrooka745ec62008-05-06 15:36:17 +00001457 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1458};
1459
Peter Maydell0d871bd2010-11-24 15:20:05 +00001460struct target_user_vfp {
1461 uint64_t fpregs[32];
1462 abi_ulong fpscr;
1463};
1464
1465struct target_user_vfp_exc {
1466 abi_ulong fpexc;
1467 abi_ulong fpinst;
1468 abi_ulong fpinst2;
1469};
1470
1471struct target_vfp_sigframe {
1472 abi_ulong magic;
1473 abi_ulong size;
1474 struct target_user_vfp ufp;
1475 struct target_user_vfp_exc ufp_exc;
1476} __attribute__((__aligned__(8)));
1477
Peter Maydell08e11252010-11-24 15:20:07 +00001478struct target_iwmmxt_sigframe {
1479 abi_ulong magic;
1480 abi_ulong size;
1481 uint64_t regs[16];
1482 /* Note that not all the coprocessor control registers are stored here */
1483 uint32_t wcssf;
1484 uint32_t wcasf;
1485 uint32_t wcgr0;
1486 uint32_t wcgr1;
1487 uint32_t wcgr2;
1488 uint32_t wcgr3;
1489} __attribute__((__aligned__(8)));
1490
Peter Maydell0d871bd2010-11-24 15:20:05 +00001491#define TARGET_VFP_MAGIC 0x56465001
Peter Maydell08e11252010-11-24 15:20:07 +00001492#define TARGET_IWMMXT_MAGIC 0x12ef842a
Peter Maydell0d871bd2010-11-24 15:20:05 +00001493
pbrooka8c33202008-05-07 23:22:46 +00001494struct sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001495{
1496 struct target_sigcontext sc;
blueswir1992f48a2007-10-14 16:27:31 +00001497 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1498 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001499};
1500
pbrooka8c33202008-05-07 23:22:46 +00001501struct sigframe_v2
1502{
1503 struct target_ucontext_v2 uc;
1504 abi_ulong retcode;
1505};
1506
pbrooka745ec62008-05-06 15:36:17 +00001507struct rt_sigframe_v1
bellard43fff232003-07-09 19:31:39 +00001508{
bellardf8b0aa22007-11-11 23:03:42 +00001509 abi_ulong pinfo;
1510 abi_ulong puc;
bellard43fff232003-07-09 19:31:39 +00001511 struct target_siginfo info;
pbrooka745ec62008-05-06 15:36:17 +00001512 struct target_ucontext_v1 uc;
1513 abi_ulong retcode;
1514};
1515
1516struct rt_sigframe_v2
1517{
1518 struct target_siginfo info;
1519 struct target_ucontext_v2 uc;
blueswir1992f48a2007-10-14 16:27:31 +00001520 abi_ulong retcode;
bellard43fff232003-07-09 19:31:39 +00001521};
1522
1523#define TARGET_CONFIG_CPU_32 1
1524
1525/*
1526 * For ARM syscalls, we encode the syscall number into the instruction.
1527 */
1528#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1529#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1530
1531/*
1532 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1533 * need two 16-bit instructions.
1534 */
1535#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1536#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1537
blueswir1992f48a2007-10-14 16:27:31 +00001538static const abi_ulong retcodes[4] = {
bellard43fff232003-07-09 19:31:39 +00001539 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1540 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1541};
1542
1543
Andreas Färber05390242012-02-25 03:37:53 +01001544static inline int valid_user_regs(CPUARMState *regs)
bellard43fff232003-07-09 19:31:39 +00001545{
1546 return 1;
1547}
1548
pbrooka8c33202008-05-07 23:22:46 +00001549static void
bellard43fff232003-07-09 19:31:39 +00001550setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01001551 CPUARMState *env, abi_ulong mask)
bellard43fff232003-07-09 19:31:39 +00001552{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001553 __put_user(env->regs[0], &sc->arm_r0);
1554 __put_user(env->regs[1], &sc->arm_r1);
1555 __put_user(env->regs[2], &sc->arm_r2);
1556 __put_user(env->regs[3], &sc->arm_r3);
1557 __put_user(env->regs[4], &sc->arm_r4);
1558 __put_user(env->regs[5], &sc->arm_r5);
1559 __put_user(env->regs[6], &sc->arm_r6);
1560 __put_user(env->regs[7], &sc->arm_r7);
1561 __put_user(env->regs[8], &sc->arm_r8);
1562 __put_user(env->regs[9], &sc->arm_r9);
1563 __put_user(env->regs[10], &sc->arm_r10);
1564 __put_user(env->regs[11], &sc->arm_fp);
1565 __put_user(env->regs[12], &sc->arm_ip);
1566 __put_user(env->regs[13], &sc->arm_sp);
1567 __put_user(env->regs[14], &sc->arm_lr);
1568 __put_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001569#ifdef TARGET_CONFIG_CPU_32
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001570 __put_user(cpsr_read(env), &sc->arm_cpsr);
bellard43fff232003-07-09 19:31:39 +00001571#endif
1572
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001573 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1574 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1575 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1576 __put_user(mask, &sc->oldmask);
bellard43fff232003-07-09 19:31:39 +00001577}
1578
bellard579a97f2007-11-11 14:26:47 +00001579static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01001580get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
bellard43fff232003-07-09 19:31:39 +00001581{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001582 unsigned long sp = regs->regs[13];
bellard43fff232003-07-09 19:31:39 +00001583
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001584 /*
1585 * This is the X/Open sanctioned signal stack switching.
1586 */
1587 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1588 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1589 }
1590 /*
1591 * ATPCS B01 mandates 8-byte alignment
1592 */
1593 return (sp - framesize) & ~7;
bellard43fff232003-07-09 19:31:39 +00001594}
1595
Riku Voipio0188fad2014-04-23 13:34:15 +03001596static void
Andreas Färber05390242012-02-25 03:37:53 +01001597setup_return(CPUARMState *env, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001598 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
bellard43fff232003-07-09 19:31:39 +00001599{
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001600 abi_ulong handler = ka->_sa_handler;
1601 abi_ulong retcode;
1602 int thumb = handler & 1;
1603 uint32_t cpsr = cpsr_read(env);
Peter Maydell964413d2011-01-14 20:39:19 +01001604
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001605 cpsr &= ~CPSR_IT;
1606 if (thumb) {
1607 cpsr |= CPSR_T;
1608 } else {
1609 cpsr &= ~CPSR_T;
1610 }
bellard43fff232003-07-09 19:31:39 +00001611
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001612 if (ka->sa_flags & TARGET_SA_RESTORER) {
1613 retcode = ka->sa_restorer;
1614 } else {
1615 unsigned int idx = thumb;
bellard43fff232003-07-09 19:31:39 +00001616
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001617 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1618 idx += 2;
1619 }
bellard43fff232003-07-09 19:31:39 +00001620
Riku Voipio0188fad2014-04-23 13:34:15 +03001621 __put_user(retcodes[idx], rc);
Stefan Weilca8a2772011-10-03 22:43:19 +02001622
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001623 retcode = rc_addr + thumb;
1624 }
bellard43fff232003-07-09 19:31:39 +00001625
Paolo Bonzinia0e1e6d2016-03-04 11:30:18 +00001626 env->regs[0] = usig;
1627 env->regs[13] = frame_addr;
1628 env->regs[14] = retcode;
1629 env->regs[15] = handler & (thumb ? ~1 : ~3);
1630 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001631}
1632
Andreas Färber05390242012-02-25 03:37:53 +01001633static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Peter Maydell0d871bd2010-11-24 15:20:05 +00001634{
1635 int i;
1636 struct target_vfp_sigframe *vfpframe;
1637 vfpframe = (struct target_vfp_sigframe *)regspace;
1638 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1639 __put_user(sizeof(*vfpframe), &vfpframe->size);
1640 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001641 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001642 }
1643 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1644 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1645 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1646 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1647 return (abi_ulong*)(vfpframe+1);
1648}
1649
Andreas Färber05390242012-02-25 03:37:53 +01001650static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1651 CPUARMState *env)
Peter Maydell08e11252010-11-24 15:20:07 +00001652{
1653 int i;
1654 struct target_iwmmxt_sigframe *iwmmxtframe;
1655 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1656 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1657 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1658 for (i = 0; i < 16; i++) {
1659 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1660 }
1661 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1662 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1663 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1664 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1665 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1666 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1667 return (abi_ulong*)(iwmmxtframe+1);
1668}
1669
pbrooka8c33202008-05-07 23:22:46 +00001670static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
Andreas Färber05390242012-02-25 03:37:53 +01001671 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001672{
pbrooka8c33202008-05-07 23:22:46 +00001673 struct target_sigaltstack stack;
1674 int i;
Peter Maydell0d871bd2010-11-24 15:20:05 +00001675 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001676
1677 /* Clear all the bits of the ucontext we don't use. */
1678 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1679
1680 memset(&stack, 0, sizeof(stack));
1681 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1682 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1683 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1684 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1685
1686 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
Peter Maydell0d871bd2010-11-24 15:20:05 +00001687 /* Save coprocessor signal frame. */
1688 regspace = uc->tuc_regspace;
1689 if (arm_feature(env, ARM_FEATURE_VFP)) {
1690 regspace = setup_sigframe_v2_vfp(regspace, env);
1691 }
Peter Maydell08e11252010-11-24 15:20:07 +00001692 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1693 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1694 }
1695
Peter Maydell0d871bd2010-11-24 15:20:05 +00001696 /* Write terminating magic word */
1697 __put_user(0, regspace);
1698
pbrooka8c33202008-05-07 23:22:46 +00001699 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1700 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1701 }
1702}
1703
1704/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00001705static void setup_frame_v1(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001706 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001707{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001708 struct sigframe_v1 *frame;
1709 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1710 int i;
bellard43fff232003-07-09 19:31:39 +00001711
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001712 trace_user_setup_frame(regs, frame_addr);
1713 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1714 return;
1715 }
bellard579a97f2007-11-11 14:26:47 +00001716
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001717 setup_sigcontext(&frame->sc, regs, set->sig[0]);
bellard43fff232003-07-09 19:31:39 +00001718
Riku Voipio0188fad2014-04-23 13:34:15 +03001719 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1720 __put_user(set->sig[i], &frame->extramask[i - 1]);
1721 }
bellard43fff232003-07-09 19:31:39 +00001722
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001723 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1724 frame_addr + offsetof(struct sigframe_v1, retcode));
bellard579a97f2007-11-11 14:26:47 +00001725
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001726 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001727}
1728
pbrook624f7972008-05-31 16:11:38 +00001729static void setup_frame_v2(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001730 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001731{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001732 struct sigframe_v2 *frame;
1733 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
pbrooka8c33202008-05-07 23:22:46 +00001734
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001735 trace_user_setup_frame(regs, frame_addr);
1736 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1737 return;
1738 }
pbrooka8c33202008-05-07 23:22:46 +00001739
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001740 setup_sigframe_v2(&frame->uc, set, regs);
pbrooka8c33202008-05-07 23:22:46 +00001741
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001742 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1743 frame_addr + offsetof(struct sigframe_v2, retcode));
pbrooka8c33202008-05-07 23:22:46 +00001744
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001745 unlock_user_struct(frame, frame_addr, 1);
pbrooka8c33202008-05-07 23:22:46 +00001746}
1747
pbrook624f7972008-05-31 16:11:38 +00001748static void setup_frame(int usig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01001749 target_sigset_t *set, CPUARMState *regs)
pbrooka8c33202008-05-07 23:22:46 +00001750{
1751 if (get_osversion() >= 0x020612) {
1752 setup_frame_v2(usig, ka, set, regs);
1753 } else {
1754 setup_frame_v1(usig, ka, set, regs);
1755 }
bellard43fff232003-07-09 19:31:39 +00001756}
1757
bellard579a97f2007-11-11 14:26:47 +00001758/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
pbrook624f7972008-05-31 16:11:38 +00001759static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001760 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001761 target_sigset_t *set, CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001762{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001763 struct rt_sigframe_v1 *frame;
1764 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1765 struct target_sigaltstack stack;
1766 int i;
1767 abi_ulong info_addr, uc_addr;
bellard43fff232003-07-09 19:31:39 +00001768
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001769 trace_user_setup_rt_frame(env, frame_addr);
1770 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1771 return /* 1 */;
1772 }
bellardedf779f2004-02-22 13:40:13 +00001773
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001774 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1775 __put_user(info_addr, &frame->pinfo);
1776 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1777 __put_user(uc_addr, &frame->puc);
1778 tswap_siginfo(&frame->info, info);
bellard43fff232003-07-09 19:31:39 +00001779
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001780 /* Clear all the bits of the ucontext we don't use. */
1781 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
bellard43fff232003-07-09 19:31:39 +00001782
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001783 memset(&stack, 0, sizeof(stack));
1784 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1785 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1786 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1787 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
thsa04e1342007-09-27 13:57:58 +00001788
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001789 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1790 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1791 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1792 }
bellard43fff232003-07-09 19:31:39 +00001793
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001794 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1795 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001796
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001797 env->regs[1] = info_addr;
1798 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001799
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001800 unlock_user_struct(frame, frame_addr, 1);
pbrooka745ec62008-05-06 15:36:17 +00001801}
1802
pbrook624f7972008-05-31 16:11:38 +00001803static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001804 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001805 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001806{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001807 struct rt_sigframe_v2 *frame;
1808 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1809 abi_ulong info_addr, uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001810
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001811 trace_user_setup_rt_frame(env, frame_addr);
1812 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1813 return /* 1 */;
1814 }
pbrooka745ec62008-05-06 15:36:17 +00001815
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001816 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1817 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1818 tswap_siginfo(&frame->info, info);
pbrooka745ec62008-05-06 15:36:17 +00001819
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001820 setup_sigframe_v2(&frame->uc, set, env);
pbrooka745ec62008-05-06 15:36:17 +00001821
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001822 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1823 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
pbrooka745ec62008-05-06 15:36:17 +00001824
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001825 env->regs[1] = info_addr;
1826 env->regs[2] = uc_addr;
pbrooka745ec62008-05-06 15:36:17 +00001827
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001828 unlock_user_struct(frame, frame_addr, 1);
bellard43fff232003-07-09 19:31:39 +00001829}
1830
pbrook624f7972008-05-31 16:11:38 +00001831static void setup_rt_frame(int usig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05001832 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01001833 target_sigset_t *set, CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00001834{
1835 if (get_osversion() >= 0x020612) {
1836 setup_rt_frame_v2(usig, ka, info, set, env);
1837 } else {
1838 setup_rt_frame_v1(usig, ka, info, set, env);
1839 }
1840}
1841
bellard43fff232003-07-09 19:31:39 +00001842static int
Andreas Färber05390242012-02-25 03:37:53 +01001843restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
bellard43fff232003-07-09 19:31:39 +00001844{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001845 int err = 0;
1846 uint32_t cpsr;
bellard43fff232003-07-09 19:31:39 +00001847
Riku Voipio1d8b5122014-04-23 10:26:05 +03001848 __get_user(env->regs[0], &sc->arm_r0);
1849 __get_user(env->regs[1], &sc->arm_r1);
1850 __get_user(env->regs[2], &sc->arm_r2);
1851 __get_user(env->regs[3], &sc->arm_r3);
1852 __get_user(env->regs[4], &sc->arm_r4);
1853 __get_user(env->regs[5], &sc->arm_r5);
1854 __get_user(env->regs[6], &sc->arm_r6);
1855 __get_user(env->regs[7], &sc->arm_r7);
1856 __get_user(env->regs[8], &sc->arm_r8);
1857 __get_user(env->regs[9], &sc->arm_r9);
1858 __get_user(env->regs[10], &sc->arm_r10);
1859 __get_user(env->regs[11], &sc->arm_fp);
1860 __get_user(env->regs[12], &sc->arm_ip);
1861 __get_user(env->regs[13], &sc->arm_sp);
1862 __get_user(env->regs[14], &sc->arm_lr);
1863 __get_user(env->regs[15], &sc->arm_pc);
bellard43fff232003-07-09 19:31:39 +00001864#ifdef TARGET_CONFIG_CPU_32
Riku Voipio1d8b5122014-04-23 10:26:05 +03001865 __get_user(cpsr, &sc->arm_cpsr);
Peter Maydell50866ba2016-02-23 15:36:43 +00001866 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
bellard43fff232003-07-09 19:31:39 +00001867#endif
1868
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001869 err |= !valid_user_regs(env);
bellard43fff232003-07-09 19:31:39 +00001870
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001871 return err;
bellard43fff232003-07-09 19:31:39 +00001872}
1873
Andreas Färber05390242012-02-25 03:37:53 +01001874static long do_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00001875{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001876 abi_ulong frame_addr;
1877 struct sigframe_v1 *frame = NULL;
1878 target_sigset_t set;
1879 sigset_t host_set;
1880 int i;
bellard43fff232003-07-09 19:31:39 +00001881
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001882 /*
1883 * Since we stacked the signal on a 64-bit boundary,
1884 * then 'sp' should be word aligned here. If it's
1885 * not, then the user is trying to mess with us.
1886 */
1887 frame_addr = env->regs[13];
1888 trace_user_do_sigreturn(env, frame_addr);
1889 if (frame_addr & 7) {
1890 goto badframe;
1891 }
Peter Maydell978fae92013-07-29 12:00:32 +01001892
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001893 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1894 goto badframe;
1895 }
bellard43fff232003-07-09 19:31:39 +00001896
Riku Voipiof5f601a2014-04-23 13:00:17 +03001897 __get_user(set.sig[0], &frame->sc.oldmask);
1898 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1899 __get_user(set.sig[i], &frame->extramask[i - 1]);
1900 }
bellard43fff232003-07-09 19:31:39 +00001901
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001902 target_to_host_sigset_internal(&host_set, &set);
1903 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard43fff232003-07-09 19:31:39 +00001904
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001905 if (restore_sigcontext(env, &frame->sc)) {
1906 goto badframe;
1907 }
bellard43fff232003-07-09 19:31:39 +00001908
1909#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001910 /* Send SIGTRAP if we're single-stepping */
1911 if (ptrace_cancel_bpt(current))
1912 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00001913#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001914 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01001915 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00001916
1917badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01001918 force_sig(TARGET_SIGSEGV /* , current */);
1919 return 0;
bellard43fff232003-07-09 19:31:39 +00001920}
1921
Andreas Färber05390242012-02-25 03:37:53 +01001922static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
Peter Maydell5f9099d2010-11-24 15:20:06 +00001923{
1924 int i;
1925 abi_ulong magic, sz;
1926 uint32_t fpscr, fpexc;
1927 struct target_vfp_sigframe *vfpframe;
1928 vfpframe = (struct target_vfp_sigframe *)regspace;
1929
1930 __get_user(magic, &vfpframe->magic);
1931 __get_user(sz, &vfpframe->size);
1932 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1933 return 0;
1934 }
1935 for (i = 0; i < 32; i++) {
Peter Maydell005e1a02011-02-10 13:59:35 +00001936 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
Peter Maydell5f9099d2010-11-24 15:20:06 +00001937 }
1938 __get_user(fpscr, &vfpframe->ufp.fpscr);
1939 vfp_set_fpscr(env, fpscr);
1940 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1941 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1942 * and the exception flag is cleared
1943 */
1944 fpexc |= (1 << 30);
1945 fpexc &= ~((1 << 31) | (1 << 28));
1946 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1947 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1948 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1949 return (abi_ulong*)(vfpframe + 1);
1950}
1951
Andreas Färber05390242012-02-25 03:37:53 +01001952static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
1953 abi_ulong *regspace)
Peter Maydella59d69d2010-11-24 15:20:08 +00001954{
1955 int i;
1956 abi_ulong magic, sz;
1957 struct target_iwmmxt_sigframe *iwmmxtframe;
1958 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1959
1960 __get_user(magic, &iwmmxtframe->magic);
1961 __get_user(sz, &iwmmxtframe->size);
1962 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
1963 return 0;
1964 }
1965 for (i = 0; i < 16; i++) {
1966 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1967 }
1968 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1969 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1970 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1971 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1972 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1973 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1974 return (abi_ulong*)(iwmmxtframe + 1);
1975}
1976
Andreas Färber05390242012-02-25 03:37:53 +01001977static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
pbrooka8c33202008-05-07 23:22:46 +00001978 struct target_ucontext_v2 *uc)
1979{
1980 sigset_t host_set;
Peter Maydell5f9099d2010-11-24 15:20:06 +00001981 abi_ulong *regspace;
pbrooka8c33202008-05-07 23:22:46 +00001982
1983 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00001984 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
pbrooka8c33202008-05-07 23:22:46 +00001985
1986 if (restore_sigcontext(env, &uc->tuc_mcontext))
1987 return 1;
1988
Peter Maydell5f9099d2010-11-24 15:20:06 +00001989 /* Restore coprocessor signal frame */
1990 regspace = uc->tuc_regspace;
1991 if (arm_feature(env, ARM_FEATURE_VFP)) {
1992 regspace = restore_sigframe_v2_vfp(env, regspace);
1993 if (!regspace) {
1994 return 1;
1995 }
1996 }
Peter Maydella59d69d2010-11-24 15:20:08 +00001997 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1998 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
1999 if (!regspace) {
2000 return 1;
2001 }
2002 }
Peter Maydell5f9099d2010-11-24 15:20:06 +00002003
pbrooka8c33202008-05-07 23:22:46 +00002004 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2005 return 1;
2006
2007#if 0
2008 /* Send SIGTRAP if we're single-stepping */
2009 if (ptrace_cancel_bpt(current))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002010 send_sig(SIGTRAP, current, 1);
pbrooka8c33202008-05-07 23:22:46 +00002011#endif
2012
2013 return 0;
2014}
2015
Andreas Färber05390242012-02-25 03:37:53 +01002016static long do_sigreturn_v2(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002017{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002018 abi_ulong frame_addr;
2019 struct sigframe_v2 *frame = NULL;
pbrooka8c33202008-05-07 23:22:46 +00002020
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002021 /*
2022 * Since we stacked the signal on a 64-bit boundary,
2023 * then 'sp' should be word aligned here. If it's
2024 * not, then the user is trying to mess with us.
2025 */
2026 frame_addr = env->regs[13];
2027 trace_user_do_sigreturn(env, frame_addr);
2028 if (frame_addr & 7) {
2029 goto badframe;
2030 }
Peter Maydell978fae92013-07-29 12:00:32 +01002031
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002032 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2033 goto badframe;
2034 }
pbrooka8c33202008-05-07 23:22:46 +00002035
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002036 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2037 goto badframe;
2038 }
pbrooka8c33202008-05-07 23:22:46 +00002039
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002040 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002041 return -TARGET_QEMU_ESIGRETURN;
pbrooka8c33202008-05-07 23:22:46 +00002042
2043badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002044 unlock_user_struct(frame, frame_addr, 0);
2045 force_sig(TARGET_SIGSEGV /* , current */);
2046 return 0;
pbrooka8c33202008-05-07 23:22:46 +00002047}
2048
Andreas Färber05390242012-02-25 03:37:53 +01002049long do_sigreturn(CPUARMState *env)
pbrooka8c33202008-05-07 23:22:46 +00002050{
2051 if (get_osversion() >= 0x020612) {
2052 return do_sigreturn_v2(env);
2053 } else {
2054 return do_sigreturn_v1(env);
2055 }
2056}
2057
Andreas Färber05390242012-02-25 03:37:53 +01002058static long do_rt_sigreturn_v1(CPUARMState *env)
bellard43fff232003-07-09 19:31:39 +00002059{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002060 abi_ulong frame_addr;
2061 struct rt_sigframe_v1 *frame = NULL;
2062 sigset_t host_set;
bellard43fff232003-07-09 19:31:39 +00002063
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002064 /*
2065 * Since we stacked the signal on a 64-bit boundary,
2066 * then 'sp' should be word aligned here. If it's
2067 * not, then the user is trying to mess with us.
2068 */
2069 frame_addr = env->regs[13];
2070 trace_user_do_rt_sigreturn(env, frame_addr);
2071 if (frame_addr & 7) {
2072 goto badframe;
2073 }
Peter Maydell978fae92013-07-29 12:00:32 +01002074
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002075 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2076 goto badframe;
2077 }
bellard43fff232003-07-09 19:31:39 +00002078
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002079 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
2080 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard43fff232003-07-09 19:31:39 +00002081
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002082 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2083 goto badframe;
2084 }
bellard43fff232003-07-09 19:31:39 +00002085
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002086 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2087 goto badframe;
thsa04e1342007-09-27 13:57:58 +00002088
bellard43fff232003-07-09 19:31:39 +00002089#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002090 /* Send SIGTRAP if we're single-stepping */
2091 if (ptrace_cancel_bpt(current))
2092 send_sig(SIGTRAP, current, 1);
bellard43fff232003-07-09 19:31:39 +00002093#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002094 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002095 return -TARGET_QEMU_ESIGRETURN;
bellard43fff232003-07-09 19:31:39 +00002096
2097badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002098 unlock_user_struct(frame, frame_addr, 0);
2099 force_sig(TARGET_SIGSEGV /* , current */);
2100 return 0;
bellard43fff232003-07-09 19:31:39 +00002101}
2102
Andreas Färber05390242012-02-25 03:37:53 +01002103static long do_rt_sigreturn_v2(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002104{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002105 abi_ulong frame_addr;
2106 struct rt_sigframe_v2 *frame = NULL;
pbrooka745ec62008-05-06 15:36:17 +00002107
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002108 /*
2109 * Since we stacked the signal on a 64-bit boundary,
2110 * then 'sp' should be word aligned here. If it's
2111 * not, then the user is trying to mess with us.
2112 */
2113 frame_addr = env->regs[13];
2114 trace_user_do_rt_sigreturn(env, frame_addr);
2115 if (frame_addr & 7) {
2116 goto badframe;
2117 }
Peter Maydell978fae92013-07-29 12:00:32 +01002118
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002119 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2120 goto badframe;
2121 }
pbrooka745ec62008-05-06 15:36:17 +00002122
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002123 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2124 goto badframe;
2125 }
pbrooka745ec62008-05-06 15:36:17 +00002126
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002127 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinf0267ef2016-05-12 18:47:31 +01002128 return -TARGET_QEMU_ESIGRETURN;
pbrooka745ec62008-05-06 15:36:17 +00002129
2130badframe:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002131 unlock_user_struct(frame, frame_addr, 0);
2132 force_sig(TARGET_SIGSEGV /* , current */);
2133 return 0;
pbrooka745ec62008-05-06 15:36:17 +00002134}
2135
Andreas Färber05390242012-02-25 03:37:53 +01002136long do_rt_sigreturn(CPUARMState *env)
pbrooka745ec62008-05-06 15:36:17 +00002137{
2138 if (get_osversion() >= 0x020612) {
2139 return do_rt_sigreturn_v2(env);
2140 } else {
2141 return do_rt_sigreturn_v1(env);
2142 }
2143}
2144
bellard6d5e2162004-09-30 22:04:13 +00002145#elif defined(TARGET_SPARC)
bellard80a9d032005-01-03 23:31:27 +00002146
bellard6d5e2162004-09-30 22:04:13 +00002147#define __SUNOS_MAXWIN 31
2148
2149/* This is what SunOS does, so shall I. */
2150struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002151 abi_ulong sigc_onstack; /* state to restore */
bellard6d5e2162004-09-30 22:04:13 +00002152
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002153 abi_ulong sigc_mask; /* sigmask to restore */
2154 abi_ulong sigc_sp; /* stack pointer */
2155 abi_ulong sigc_pc; /* program counter */
2156 abi_ulong sigc_npc; /* next program counter */
2157 abi_ulong sigc_psr; /* for condition codes etc */
2158 abi_ulong sigc_g1; /* User uses these two registers */
2159 abi_ulong sigc_o0; /* within the trampoline code. */
bellard6d5e2162004-09-30 22:04:13 +00002160
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002161 /* Now comes information regarding the users window set
bellard6d5e2162004-09-30 22:04:13 +00002162 * at the time of the signal.
2163 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002164 abi_ulong sigc_oswins; /* outstanding windows */
bellard6d5e2162004-09-30 22:04:13 +00002165
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002166 /* stack ptrs for each regwin buf */
2167 char *sigc_spbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002168
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002169 /* Windows to restore after signal */
2170 struct {
2171 abi_ulong locals[8];
2172 abi_ulong ins[8];
2173 } sigc_wbuf[__SUNOS_MAXWIN];
bellard6d5e2162004-09-30 22:04:13 +00002174};
2175/* A Sparc stack frame */
2176struct sparc_stackf {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002177 abi_ulong locals[8];
2178 abi_ulong ins[8];
2179 /* It's simpler to treat fp and callers_pc as elements of ins[]
Peter Maydelle321c342011-02-01 15:54:52 +00002180 * since we never need to access them ourselves.
2181 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002182 char *structptr;
2183 abi_ulong xargs[6];
2184 abi_ulong xxargs[1];
bellard6d5e2162004-09-30 22:04:13 +00002185};
2186
2187typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002188 struct {
2189 abi_ulong psr;
2190 abi_ulong pc;
2191 abi_ulong npc;
2192 abi_ulong y;
2193 abi_ulong u_regs[16]; /* globals and ins */
2194 } si_regs;
2195 int si_mask;
bellard6d5e2162004-09-30 22:04:13 +00002196} __siginfo_t;
2197
2198typedef struct {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002199 abi_ulong si_float_regs[32];
2200 unsigned long si_fsr;
2201 unsigned long si_fpqdepth;
2202 struct {
2203 unsigned long *insn_addr;
2204 unsigned long insn;
2205 } si_fpqueue [16];
Anthony Liguoric227f092009-10-01 16:12:16 -05002206} qemu_siginfo_fpu_t;
bellard6d5e2162004-09-30 22:04:13 +00002207
2208
2209struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002210 struct sparc_stackf ss;
2211 __siginfo_t info;
2212 abi_ulong fpu_save;
2213 abi_ulong insns[2] __attribute__ ((aligned (8)));
2214 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2215 abi_ulong extra_size; /* Should be 0 */
2216 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002217};
2218struct target_rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002219 struct sparc_stackf ss;
2220 siginfo_t info;
2221 abi_ulong regs[20];
2222 sigset_t mask;
2223 abi_ulong fpu_save;
2224 unsigned int insns[2];
2225 stack_t stack;
2226 unsigned int extra_size; /* Should be 0 */
2227 qemu_siginfo_fpu_t fpu_state;
bellard6d5e2162004-09-30 22:04:13 +00002228};
2229
bellarde80cfcf2004-12-19 23:18:01 +00002230#define UREG_O0 16
2231#define UREG_O6 22
2232#define UREG_I0 0
2233#define UREG_I1 1
2234#define UREG_I2 2
blueswir15bfb56b2007-10-05 17:01:51 +00002235#define UREG_I3 3
2236#define UREG_I4 4
2237#define UREG_I5 5
bellarde80cfcf2004-12-19 23:18:01 +00002238#define UREG_I6 6
2239#define UREG_I7 7
2240#define UREG_L0 8
bellard6d5e2162004-09-30 22:04:13 +00002241#define UREG_FP UREG_I6
2242#define UREG_SP UREG_O6
2243
pbrook624f7972008-05-31 16:11:38 +00002244static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01002245 CPUSPARCState *env,
2246 unsigned long framesize)
bellard6d5e2162004-09-30 22:04:13 +00002247{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002248 abi_ulong sp;
bellard6d5e2162004-09-30 22:04:13 +00002249
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002250 sp = env->regwptr[UREG_FP];
bellard6d5e2162004-09-30 22:04:13 +00002251
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002252 /* This is the X/Open sanctioned signal stack switching. */
2253 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2254 if (!on_sig_stack(sp)
2255 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2256 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2257 }
2258 }
2259 return sp - framesize;
bellard6d5e2162004-09-30 22:04:13 +00002260}
2261
2262static int
Andreas Färber05390242012-02-25 03:37:53 +01002263setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
bellard6d5e2162004-09-30 22:04:13 +00002264{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002265 int err = 0, i;
bellard6d5e2162004-09-30 22:04:13 +00002266
Riku Voipio1d8b5122014-04-23 10:26:05 +03002267 __put_user(env->psr, &si->si_regs.psr);
2268 __put_user(env->pc, &si->si_regs.pc);
2269 __put_user(env->npc, &si->si_regs.npc);
2270 __put_user(env->y, &si->si_regs.y);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002271 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002272 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002273 }
2274 for (i=0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002275 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002276 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002277 __put_user(mask, &si->si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002278 return err;
bellard6d5e2162004-09-30 22:04:13 +00002279}
bellarde80cfcf2004-12-19 23:18:01 +00002280
bellard80a9d032005-01-03 23:31:27 +00002281#if 0
bellard6d5e2162004-09-30 22:04:13 +00002282static int
2283setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
Andreas Färber05390242012-02-25 03:37:53 +01002284 CPUSPARCState *env, unsigned long mask)
bellard6d5e2162004-09-30 22:04:13 +00002285{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002286 int err = 0;
bellard6d5e2162004-09-30 22:04:13 +00002287
Riku Voipio1d8b5122014-04-23 10:26:05 +03002288 __put_user(mask, &sc->sigc_mask);
2289 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2290 __put_user(env->pc, &sc->sigc_pc);
2291 __put_user(env->npc, &sc->sigc_npc);
2292 __put_user(env->psr, &sc->sigc_psr);
2293 __put_user(env->gregs[1], &sc->sigc_g1);
2294 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
bellard6d5e2162004-09-30 22:04:13 +00002295
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002296 return err;
bellard6d5e2162004-09-30 22:04:13 +00002297}
bellard80a9d032005-01-03 23:31:27 +00002298#endif
bellard6d5e2162004-09-30 22:04:13 +00002299#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2300
pbrook624f7972008-05-31 16:11:38 +00002301static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01002302 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002303{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002304 abi_ulong sf_addr;
2305 struct target_signal_frame *sf;
2306 int sigframe_size, err, i;
bellard6d5e2162004-09-30 22:04:13 +00002307
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002308 /* 1. Make sure everything is clean */
2309 //synchronize_user_stack();
bellard6d5e2162004-09-30 22:04:13 +00002310
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002311 sigframe_size = NF_ALIGNEDSZ;
2312 sf_addr = get_sigframe(ka, env, sigframe_size);
2313 trace_user_setup_frame(env, sf_addr);
bellard6d5e2162004-09-30 22:04:13 +00002314
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002315 sf = lock_user(VERIFY_WRITE, sf_addr,
2316 sizeof(struct target_signal_frame), 0);
2317 if (!sf) {
2318 goto sigsegv;
2319 }
bellard6d5e2162004-09-30 22:04:13 +00002320#if 0
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002321 if (invalid_frame_pointer(sf, sigframe_size))
2322 goto sigill_and_return;
bellard6d5e2162004-09-30 22:04:13 +00002323#endif
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002324 /* 2. Save the current process state */
2325 err = setup___siginfo(&sf->info, env, set->sig[0]);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002326 __put_user(0, &sf->extra_size);
bellard6d5e2162004-09-30 22:04:13 +00002327
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002328 //save_fpu_state(regs, &sf->fpu_state);
2329 //__put_user(&sf->fpu_state, &sf->fpu_save);
bellard6d5e2162004-09-30 22:04:13 +00002330
Riku Voipio1d8b5122014-04-23 10:26:05 +03002331 __put_user(set->sig[0], &sf->info.si_mask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002332 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002333 __put_user(set->sig[i + 1], &sf->extramask[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002334 }
bellard6d5e2162004-09-30 22:04:13 +00002335
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002336 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002337 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002338 }
2339 for (i = 0; i < 8; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002340 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002341 }
2342 if (err)
2343 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002344
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002345 /* 3. signal handler back-trampoline and parameters */
2346 env->regwptr[UREG_FP] = sf_addr;
2347 env->regwptr[UREG_I0] = sig;
2348 env->regwptr[UREG_I1] = sf_addr +
2349 offsetof(struct target_signal_frame, info);
2350 env->regwptr[UREG_I2] = sf_addr +
2351 offsetof(struct target_signal_frame, info);
bellard6d5e2162004-09-30 22:04:13 +00002352
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002353 /* 4. signal handler */
2354 env->pc = ka->_sa_handler;
2355 env->npc = (env->pc + 4);
2356 /* 5. return to kernel instructions */
2357 if (ka->sa_restorer) {
2358 env->regwptr[UREG_I7] = ka->sa_restorer;
2359 } else {
2360 uint32_t val32;
bellard459a4012007-11-11 19:45:10 +00002361
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002362 env->regwptr[UREG_I7] = sf_addr +
2363 offsetof(struct target_signal_frame, insns) - 2 * 4;
bellard6d5e2162004-09-30 22:04:13 +00002364
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002365 /* mov __NR_sigreturn, %g1 */
2366 val32 = 0x821020d8;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002367 __put_user(val32, &sf->insns[0]);
bellard6d5e2162004-09-30 22:04:13 +00002368
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002369 /* t 0x10 */
2370 val32 = 0x91d02010;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002371 __put_user(val32, &sf->insns[1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002372 if (err)
2373 goto sigsegv;
bellard6d5e2162004-09-30 22:04:13 +00002374
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002375 /* Flush instruction space. */
2376 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2377 // tb_flush(env);
2378 }
2379 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2380 return;
bellard459a4012007-11-11 19:45:10 +00002381#if 0
2382sigill_and_return:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002383 force_sig(TARGET_SIGILL);
bellard459a4012007-11-11 19:45:10 +00002384#endif
bellard6d5e2162004-09-30 22:04:13 +00002385sigsegv:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002386 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2387 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002388}
bellard6d5e2162004-09-30 22:04:13 +00002389
pbrook624f7972008-05-31 16:11:38 +00002390static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05002391 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01002392 target_sigset_t *set, CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002393{
2394 fprintf(stderr, "setup_rt_frame: not implemented\n");
2395}
2396
Andreas Färber05390242012-02-25 03:37:53 +01002397long do_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002398{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002399 abi_ulong sf_addr;
2400 struct target_signal_frame *sf;
2401 uint32_t up_psr, pc, npc;
2402 target_sigset_t set;
2403 sigset_t host_set;
2404 int err=0, i;
bellard6d5e2162004-09-30 22:04:13 +00002405
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002406 sf_addr = env->regwptr[UREG_FP];
2407 trace_user_do_sigreturn(env, sf_addr);
2408 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2409 goto segv_and_exit;
2410 }
bellard6d5e2162004-09-30 22:04:13 +00002411
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002412 /* 1. Make sure we are not getting garbage from the user */
bellard6d5e2162004-09-30 22:04:13 +00002413
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002414 if (sf_addr & 3)
2415 goto segv_and_exit;
bellard6d5e2162004-09-30 22:04:13 +00002416
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002417 __get_user(pc, &sf->info.si_regs.pc);
2418 __get_user(npc, &sf->info.si_regs.npc);
bellard6d5e2162004-09-30 22:04:13 +00002419
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002420 if ((pc | npc) & 3) {
2421 goto segv_and_exit;
2422 }
bellard6d5e2162004-09-30 22:04:13 +00002423
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002424 /* 2. Restore the state */
2425 __get_user(up_psr, &sf->info.si_regs.psr);
bellarde80cfcf2004-12-19 23:18:01 +00002426
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002427 /* User can only change condition codes and FPU enabling in %psr. */
2428 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2429 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
bellarda315a142005-01-30 22:59:18 +00002430
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002431 env->pc = pc;
2432 env->npc = npc;
2433 __get_user(env->y, &sf->info.si_regs.y);
2434 for (i=0; i < 8; i++) {
2435 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2436 }
2437 for (i=0; i < 8; i++) {
2438 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2439 }
bellard6d5e2162004-09-30 22:04:13 +00002440
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002441 /* FIXME: implement FPU save/restore:
Peter Maydell2aec3a22011-06-16 17:37:14 +01002442 * __get_user(fpu_save, &sf->fpu_save);
2443 * if (fpu_save)
2444 * err |= restore_fpu_state(env, fpu_save);
2445 */
bellard6d5e2162004-09-30 22:04:13 +00002446
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002447 /* This is pretty much atomic, no amount locking would prevent
bellard6d5e2162004-09-30 22:04:13 +00002448 * the races which exist anyways.
2449 */
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002450 __get_user(set.sig[0], &sf->info.si_mask);
2451 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2452 __get_user(set.sig[i], &sf->extramask[i - 1]);
2453 }
bellarde80cfcf2004-12-19 23:18:01 +00002454
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002455 target_to_host_sigset_internal(&host_set, &set);
2456 do_sigprocmask(SIG_SETMASK, &host_set, NULL);
bellard6d5e2162004-09-30 22:04:13 +00002457
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002458 if (err) {
2459 goto segv_and_exit;
2460 }
2461 unlock_user_struct(sf, sf_addr, 0);
Timothy E Baldwinc0bea682016-05-12 18:47:34 +01002462 return -TARGET_QEMU_ESIGRETURN;
bellard6d5e2162004-09-30 22:04:13 +00002463
2464segv_and_exit:
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002465 unlock_user_struct(sf, sf_addr, 0);
2466 force_sig(TARGET_SIGSEGV);
bellard6d5e2162004-09-30 22:04:13 +00002467}
2468
Andreas Färber05390242012-02-25 03:37:53 +01002469long do_rt_sigreturn(CPUSPARCState *env)
bellard6d5e2162004-09-30 22:04:13 +00002470{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002471 trace_user_do_rt_sigreturn(env, 0);
bellard6d5e2162004-09-30 22:04:13 +00002472 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00002473 return -TARGET_ENOSYS;
bellard6d5e2162004-09-30 22:04:13 +00002474}
2475
bellard459a4012007-11-11 19:45:10 +00002476#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
blueswir15bfb56b2007-10-05 17:01:51 +00002477#define MC_TSTATE 0
2478#define MC_PC 1
2479#define MC_NPC 2
2480#define MC_Y 3
2481#define MC_G1 4
2482#define MC_G2 5
2483#define MC_G3 6
2484#define MC_G4 7
2485#define MC_G5 8
2486#define MC_G6 9
2487#define MC_G7 10
2488#define MC_O0 11
2489#define MC_O1 12
2490#define MC_O2 13
2491#define MC_O3 14
2492#define MC_O4 15
2493#define MC_O5 16
2494#define MC_O6 17
2495#define MC_O7 18
2496#define MC_NGREG 19
2497
Anthony Liguoric227f092009-10-01 16:12:16 -05002498typedef abi_ulong target_mc_greg_t;
2499typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
blueswir15bfb56b2007-10-05 17:01:51 +00002500
2501struct target_mc_fq {
blueswir1992f48a2007-10-14 16:27:31 +00002502 abi_ulong *mcfq_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002503 uint32_t mcfq_insn;
2504};
2505
2506struct target_mc_fpu {
2507 union {
2508 uint32_t sregs[32];
2509 uint64_t dregs[32];
2510 //uint128_t qregs[16];
2511 } mcfpu_fregs;
blueswir1992f48a2007-10-14 16:27:31 +00002512 abi_ulong mcfpu_fsr;
2513 abi_ulong mcfpu_fprs;
2514 abi_ulong mcfpu_gsr;
blueswir15bfb56b2007-10-05 17:01:51 +00002515 struct target_mc_fq *mcfpu_fq;
2516 unsigned char mcfpu_qcnt;
2517 unsigned char mcfpu_qentsz;
2518 unsigned char mcfpu_enab;
2519};
Anthony Liguoric227f092009-10-01 16:12:16 -05002520typedef struct target_mc_fpu target_mc_fpu_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002521
2522typedef struct {
Anthony Liguoric227f092009-10-01 16:12:16 -05002523 target_mc_gregset_t mc_gregs;
2524 target_mc_greg_t mc_fp;
2525 target_mc_greg_t mc_i7;
2526 target_mc_fpu_t mc_fpregs;
2527} target_mcontext_t;
blueswir15bfb56b2007-10-05 17:01:51 +00002528
2529struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002530 struct target_ucontext *tuc_link;
2531 abi_ulong tuc_flags;
2532 target_sigset_t tuc_sigmask;
2533 target_mcontext_t tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002534};
2535
2536/* A V9 register window */
2537struct target_reg_window {
blueswir1992f48a2007-10-14 16:27:31 +00002538 abi_ulong locals[8];
2539 abi_ulong ins[8];
blueswir15bfb56b2007-10-05 17:01:51 +00002540};
2541
2542#define TARGET_STACK_BIAS 2047
2543
2544/* {set, get}context() needed for 64-bit SparcLinux userland. */
2545void sparc64_set_context(CPUSPARCState *env)
2546{
bellard459a4012007-11-11 19:45:10 +00002547 abi_ulong ucp_addr;
2548 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002549 target_mc_gregset_t *grp;
blueswir1992f48a2007-10-14 16:27:31 +00002550 abi_ulong pc, npc, tstate;
bellard459a4012007-11-11 19:45:10 +00002551 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002552 unsigned int i;
blueswir15bfb56b2007-10-05 17:01:51 +00002553
bellard459a4012007-11-11 19:45:10 +00002554 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002555 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
bellard459a4012007-11-11 19:45:10 +00002556 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002557 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02002558 grp = &ucp->tuc_mcontext.mc_gregs;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002559 __get_user(pc, &((*grp)[MC_PC]));
2560 __get_user(npc, &((*grp)[MC_NPC]));
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002561 if ((pc | npc) & 3) {
blueswir15bfb56b2007-10-05 17:01:51 +00002562 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002563 }
blueswir15bfb56b2007-10-05 17:01:51 +00002564 if (env->regwptr[UREG_I1]) {
Anthony Liguoric227f092009-10-01 16:12:16 -05002565 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002566 sigset_t set;
2567
2568 if (TARGET_NSIG_WORDS == 1) {
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002569 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
blueswir15bfb56b2007-10-05 17:01:51 +00002570 } else {
bellard459a4012007-11-11 19:45:10 +00002571 abi_ulong *src, *dst;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002572 src = ucp->tuc_sigmask.sig;
bellard459a4012007-11-11 19:45:10 +00002573 dst = target_set.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002574 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002575 __get_user(*dst, src);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002576 }
blueswir15bfb56b2007-10-05 17:01:51 +00002577 }
2578 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002579 do_sigprocmask(SIG_SETMASK, &set, NULL);
blueswir15bfb56b2007-10-05 17:01:51 +00002580 }
2581 env->pc = pc;
2582 env->npc = npc;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002583 __get_user(env->y, &((*grp)[MC_Y]));
2584 __get_user(tstate, &((*grp)[MC_TSTATE]));
blueswir15bfb56b2007-10-05 17:01:51 +00002585 env->asi = (tstate >> 24) & 0xff;
Blue Swirl5a834bb2010-05-09 20:19:04 +00002586 cpu_put_ccr(env, tstate >> 32);
2587 cpu_put_cwp64(env, tstate & 0x1f);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002588 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2589 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2590 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2591 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2592 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2593 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2594 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2595 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2596 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2597 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2598 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2599 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2600 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2601 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2602 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002603
Riku Voipio1d8b5122014-04-23 10:26:05 +03002604 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2605 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002606
bellard459a4012007-11-11 19:45:10 +00002607 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002608 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2609 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002610 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002611 }
2612 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2613 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002614 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002615 }
Peter Maydellc7b016b2011-06-16 17:37:15 +01002616 /* FIXME this does not match how the kernel handles the FPU in
2617 * its sparc64_set_context implementation. In particular the FPU
2618 * is only restored if fenab is non-zero in:
2619 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2620 */
Riku Voipiobe3ef5c2014-04-23 14:02:36 +03002621 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
bellard459a4012007-11-11 19:45:10 +00002622 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002623 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2624 for (i = 0; i < 64; i++, src++) {
2625 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002626 __get_user(env->fpr[i/2].l.lower, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002627 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002628 __get_user(env->fpr[i/2].l.upper, src);
Richard Henderson30038fd2011-10-17 10:42:49 -07002629 }
2630 }
bellard459a4012007-11-11 19:45:10 +00002631 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002632 __get_user(env->fsr,
2633 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2634 __get_user(env->gsr,
2635 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
bellard459a4012007-11-11 19:45:10 +00002636 unlock_user_struct(ucp, ucp_addr, 0);
blueswir15bfb56b2007-10-05 17:01:51 +00002637 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002638do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002639 unlock_user_struct(ucp, ucp_addr, 0);
Riku Voipio66393fb2009-12-04 15:16:32 +02002640 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002641}
2642
2643void sparc64_get_context(CPUSPARCState *env)
2644{
bellard459a4012007-11-11 19:45:10 +00002645 abi_ulong ucp_addr;
2646 struct target_ucontext *ucp;
Anthony Liguoric227f092009-10-01 16:12:16 -05002647 target_mc_gregset_t *grp;
2648 target_mcontext_t *mcp;
bellard459a4012007-11-11 19:45:10 +00002649 abi_ulong fp, i7, w_addr;
blueswir15bfb56b2007-10-05 17:01:51 +00002650 int err;
2651 unsigned int i;
Anthony Liguoric227f092009-10-01 16:12:16 -05002652 target_sigset_t target_set;
blueswir15bfb56b2007-10-05 17:01:51 +00002653 sigset_t set;
2654
bellard459a4012007-11-11 19:45:10 +00002655 ucp_addr = env->regwptr[UREG_I0];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002656 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
bellard459a4012007-11-11 19:45:10 +00002657 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002658 }
bellard459a4012007-11-11 19:45:10 +00002659
Aurelien Jarno60e99242010-03-29 02:12:51 +02002660 mcp = &ucp->tuc_mcontext;
blueswir15bfb56b2007-10-05 17:01:51 +00002661 grp = &mcp->mc_gregs;
2662
2663 /* Skip over the trap instruction, first. */
2664 env->pc = env->npc;
2665 env->npc += 4;
2666
2667 err = 0;
2668
Alex Barcelo1c275922014-03-14 14:36:55 +00002669 do_sigprocmask(0, NULL, &set);
blueswir15bfb56b2007-10-05 17:01:51 +00002670 host_to_target_sigset_internal(&target_set, &set);
bellard459a4012007-11-11 19:45:10 +00002671 if (TARGET_NSIG_WORDS == 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002672 __put_user(target_set.sig[0],
2673 (abi_ulong *)&ucp->tuc_sigmask);
bellard459a4012007-11-11 19:45:10 +00002674 } else {
2675 abi_ulong *src, *dst;
2676 src = target_set.sig;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002677 dst = ucp->tuc_sigmask.sig;
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002678 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002679 __put_user(*src, dst);
Stefan Weil0d9e61c2013-12-07 14:48:08 +01002680 }
blueswir15bfb56b2007-10-05 17:01:51 +00002681 if (err)
2682 goto do_sigsegv;
2683 }
2684
bellard459a4012007-11-11 19:45:10 +00002685 /* XXX: tstate must be saved properly */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002686 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2687 __put_user(env->pc, &((*grp)[MC_PC]));
2688 __put_user(env->npc, &((*grp)[MC_NPC]));
2689 __put_user(env->y, &((*grp)[MC_Y]));
2690 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2691 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2692 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2693 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2694 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2695 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2696 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2697 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2698 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2699 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2700 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2701 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2702 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2703 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2704 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
blueswir15bfb56b2007-10-05 17:01:51 +00002705
bellard459a4012007-11-11 19:45:10 +00002706 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2707 fp = i7 = 0;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002708 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2709 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002710 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002711 }
2712 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2713 abi_ulong) != 0) {
bellard459a4012007-11-11 19:45:10 +00002714 goto do_sigsegv;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002715 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002716 __put_user(fp, &(mcp->mc_fp));
2717 __put_user(i7, &(mcp->mc_i7));
blueswir15bfb56b2007-10-05 17:01:51 +00002718
bellard459a4012007-11-11 19:45:10 +00002719 {
Richard Henderson30038fd2011-10-17 10:42:49 -07002720 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2721 for (i = 0; i < 64; i++, dst++) {
2722 if (i & 1) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002723 __put_user(env->fpr[i/2].l.lower, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002724 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002725 __put_user(env->fpr[i/2].l.upper, dst);
Richard Henderson30038fd2011-10-17 10:42:49 -07002726 }
2727 }
bellard459a4012007-11-11 19:45:10 +00002728 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03002729 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2730 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2731 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
blueswir15bfb56b2007-10-05 17:01:51 +00002732
2733 if (err)
2734 goto do_sigsegv;
bellard459a4012007-11-11 19:45:10 +00002735 unlock_user_struct(ucp, ucp_addr, 1);
blueswir15bfb56b2007-10-05 17:01:51 +00002736 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002737do_sigsegv:
bellard459a4012007-11-11 19:45:10 +00002738 unlock_user_struct(ucp, ucp_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02002739 force_sig(TARGET_SIGSEGV);
blueswir15bfb56b2007-10-05 17:01:51 +00002740}
2741#endif
Richard Hendersonff970902013-02-10 10:30:42 -08002742#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
bellard106ec872006-06-27 21:08:10 +00002743
Richard Hendersonff970902013-02-10 10:30:42 -08002744# if defined(TARGET_ABI_MIPSO32)
bellard106ec872006-06-27 21:08:10 +00002745struct target_sigcontext {
2746 uint32_t sc_regmask; /* Unused */
2747 uint32_t sc_status;
2748 uint64_t sc_pc;
2749 uint64_t sc_regs[32];
2750 uint64_t sc_fpregs[32];
2751 uint32_t sc_ownedfp; /* Unused */
2752 uint32_t sc_fpc_csr;
2753 uint32_t sc_fpc_eir; /* Unused */
2754 uint32_t sc_used_math;
2755 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
Paul Brook94c54952009-07-09 18:40:15 +01002756 uint32_t pad0;
bellard106ec872006-06-27 21:08:10 +00002757 uint64_t sc_mdhi;
2758 uint64_t sc_mdlo;
2759 target_ulong sc_hi1; /* Was sc_cause */
2760 target_ulong sc_lo1; /* Was sc_badvaddr */
2761 target_ulong sc_hi2; /* Was sc_sigset[4] */
2762 target_ulong sc_lo2;
2763 target_ulong sc_hi3;
2764 target_ulong sc_lo3;
2765};
Richard Hendersonff970902013-02-10 10:30:42 -08002766# else /* N32 || N64 */
2767struct target_sigcontext {
2768 uint64_t sc_regs[32];
2769 uint64_t sc_fpregs[32];
2770 uint64_t sc_mdhi;
2771 uint64_t sc_hi1;
2772 uint64_t sc_hi2;
2773 uint64_t sc_hi3;
2774 uint64_t sc_mdlo;
2775 uint64_t sc_lo1;
2776 uint64_t sc_lo2;
2777 uint64_t sc_lo3;
2778 uint64_t sc_pc;
2779 uint32_t sc_fpc_csr;
2780 uint32_t sc_used_math;
2781 uint32_t sc_dsp;
2782 uint32_t sc_reserved;
2783};
2784# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00002785
2786struct sigframe {
2787 uint32_t sf_ass[4]; /* argument save space for o32 */
2788 uint32_t sf_code[2]; /* signal trampoline */
2789 struct target_sigcontext sf_sc;
Anthony Liguoric227f092009-10-01 16:12:16 -05002790 target_sigset_t sf_mask;
bellard106ec872006-06-27 21:08:10 +00002791};
2792
pbrook0b1bcb02009-04-21 01:41:10 +00002793struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02002794 target_ulong tuc_flags;
2795 target_ulong tuc_link;
2796 target_stack_t tuc_stack;
Paul Brook94c54952009-07-09 18:40:15 +01002797 target_ulong pad0;
Aurelien Jarno60e99242010-03-29 02:12:51 +02002798 struct target_sigcontext tuc_mcontext;
2799 target_sigset_t tuc_sigmask;
pbrook0b1bcb02009-04-21 01:41:10 +00002800};
2801
2802struct target_rt_sigframe {
2803 uint32_t rs_ass[4]; /* argument save space for o32 */
2804 uint32_t rs_code[2]; /* signal trampoline */
2805 struct target_siginfo rs_info;
2806 struct target_ucontext rs_uc;
2807};
2808
bellard106ec872006-06-27 21:08:10 +00002809/* Install trampoline to jump back from signal handler */
2810static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2811{
Richard Henderson084d0492013-02-10 10:30:44 -08002812 int err = 0;
bellard106ec872006-06-27 21:08:10 +00002813
2814 /*
Richard Henderson084d0492013-02-10 10:30:44 -08002815 * Set up the return code ...
2816 *
2817 * li v0, __NR__foo_sigreturn
2818 * syscall
2819 */
bellard106ec872006-06-27 21:08:10 +00002820
Riku Voipio1d8b5122014-04-23 10:26:05 +03002821 __put_user(0x24020000 + syscall, tramp + 0);
2822 __put_user(0x0000000c , tramp + 1);
bellard106ec872006-06-27 21:08:10 +00002823 return err;
2824}
2825
Riku Voipio41ecc722014-04-23 11:01:00 +03002826static inline void setup_sigcontext(CPUMIPSState *regs,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002827 struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002828{
Richard Henderson084d0492013-02-10 10:30:44 -08002829 int i;
bellard106ec872006-06-27 21:08:10 +00002830
Riku Voipio1d8b5122014-04-23 10:26:05 +03002831 __put_user(exception_resume_pc(regs), &sc->sc_pc);
Kwok Cheung Yeung1239b472013-05-17 14:51:21 -07002832 regs->hflags &= ~MIPS_HFLAG_BMASK;
bellard106ec872006-06-27 21:08:10 +00002833
Richard Henderson084d0492013-02-10 10:30:44 -08002834 __put_user(0, &sc->sc_regs[0]);
2835 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002836 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002837 }
bellard106ec872006-06-27 21:08:10 +00002838
Riku Voipio1d8b5122014-04-23 10:26:05 +03002839 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2840 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002841
Richard Henderson084d0492013-02-10 10:30:44 -08002842 /* Rather than checking for dsp existence, always copy. The storage
2843 would just be garbage otherwise. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03002844 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2845 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2846 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2847 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2848 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2849 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002850 {
2851 uint32_t dsp = cpu_rddsp(0x3ff, regs);
Riku Voipio1d8b5122014-04-23 10:26:05 +03002852 __put_user(dsp, &sc->sc_dsp);
bellard106ec872006-06-27 21:08:10 +00002853 }
Richard Henderson084d0492013-02-10 10:30:44 -08002854
Riku Voipio1d8b5122014-04-23 10:26:05 +03002855 __put_user(1, &sc->sc_used_math);
Richard Henderson084d0492013-02-10 10:30:44 -08002856
2857 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002858 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
bellard106ec872006-06-27 21:08:10 +00002859 }
bellard106ec872006-06-27 21:08:10 +00002860}
2861
Riku Voipio016d2e12014-04-23 11:19:48 +03002862static inline void
Andreas Färber05390242012-02-25 03:37:53 +01002863restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
bellard106ec872006-06-27 21:08:10 +00002864{
Richard Henderson084d0492013-02-10 10:30:44 -08002865 int i;
bellard106ec872006-06-27 21:08:10 +00002866
Riku Voipio1d8b5122014-04-23 10:26:05 +03002867 __get_user(regs->CP0_EPC, &sc->sc_pc);
bellard106ec872006-06-27 21:08:10 +00002868
Riku Voipio1d8b5122014-04-23 10:26:05 +03002869 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2870 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
bellard106ec872006-06-27 21:08:10 +00002871
Richard Henderson084d0492013-02-10 10:30:44 -08002872 for (i = 1; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002873 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
bellard106ec872006-06-27 21:08:10 +00002874 }
2875
Riku Voipio1d8b5122014-04-23 10:26:05 +03002876 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2877 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2878 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2879 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2880 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2881 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
Richard Henderson084d0492013-02-10 10:30:44 -08002882 {
2883 uint32_t dsp;
Riku Voipio1d8b5122014-04-23 10:26:05 +03002884 __get_user(dsp, &sc->sc_dsp);
Richard Henderson084d0492013-02-10 10:30:44 -08002885 cpu_wrdsp(dsp, 0x3ff, regs);
2886 }
2887
2888 for (i = 0; i < 32; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03002889 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
Richard Henderson084d0492013-02-10 10:30:44 -08002890 }
bellard106ec872006-06-27 21:08:10 +00002891}
Richard Hendersonff970902013-02-10 10:30:42 -08002892
bellard106ec872006-06-27 21:08:10 +00002893/*
2894 * Determine which stack to use..
2895 */
bellard579a97f2007-11-11 14:26:47 +00002896static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01002897get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
bellard106ec872006-06-27 21:08:10 +00002898{
2899 unsigned long sp;
2900
2901 /* Default to using normal stack */
thsb5dc7732008-06-27 10:02:35 +00002902 sp = regs->active_tc.gpr[29];
bellard106ec872006-06-27 21:08:10 +00002903
2904 /*
Stefan Weil93148aa2012-02-26 18:46:12 +01002905 * FPU emulator may have its own trampoline active just
bellard106ec872006-06-27 21:08:10 +00002906 * above the user stack, 16-bytes before the next lowest
2907 * 16 byte boundary. Try to avoid trashing it.
2908 */
2909 sp -= 32;
2910
bellard106ec872006-06-27 21:08:10 +00002911 /* This is the X/Open sanctioned signal stack switching. */
pbrook624f7972008-05-31 16:11:38 +00002912 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
thsa04e1342007-09-27 13:57:58 +00002913 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2914 }
bellard106ec872006-06-27 21:08:10 +00002915
bellard579a97f2007-11-11 14:26:47 +00002916 return (sp - frame_size) & ~7;
bellard106ec872006-06-27 21:08:10 +00002917}
2918
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002919static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
2920{
2921 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
2922 env->hflags &= ~MIPS_HFLAG_M16;
2923 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
2924 env->active_tc.PC &= ~(target_ulong) 1;
2925 }
2926}
2927
Richard Hendersonff970902013-02-10 10:30:42 -08002928# if defined(TARGET_ABI_MIPSO32)
bellard579a97f2007-11-11 14:26:47 +00002929/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
pbrook624f7972008-05-31 16:11:38 +00002930static void setup_frame(int sig, struct target_sigaction * ka,
Andreas Färber05390242012-02-25 03:37:53 +01002931 target_sigset_t *set, CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002932{
2933 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002934 abi_ulong frame_addr;
bellard106ec872006-06-27 21:08:10 +00002935 int i;
2936
bellard579a97f2007-11-11 14:26:47 +00002937 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002938 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002939 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
2940 goto give_sigsegv;
2941 }
bellard106ec872006-06-27 21:08:10 +00002942
2943 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2944
Riku Voipio41ecc722014-04-23 11:01:00 +03002945 setup_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002946
2947 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03002948 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
bellard106ec872006-06-27 21:08:10 +00002949 }
2950
2951 /*
2952 * Arguments to signal handler:
2953 *
2954 * a0 = signal number
2955 * a1 = 0 (should be cause)
2956 * a2 = pointer to struct sigcontext
2957 *
2958 * $25 and PC point to the signal handler, $29 points to the
2959 * struct sigframe.
2960 */
thsb5dc7732008-06-27 10:02:35 +00002961 regs->active_tc.gpr[ 4] = sig;
2962 regs->active_tc.gpr[ 5] = 0;
2963 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2964 regs->active_tc.gpr[29] = frame_addr;
2965 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
bellard106ec872006-06-27 21:08:10 +00002966 /* The original kernel code sets CP0_EPC to the handler
2967 * since it returns to userland using eret
2968 * we cannot do this here, and we must set PC directly */
thsb5dc7732008-06-27 10:02:35 +00002969 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07002970 mips_set_hflags_isa_mode_from_pc(regs);
bellard579a97f2007-11-11 14:26:47 +00002971 unlock_user_struct(frame, frame_addr, 1);
bellard106ec872006-06-27 21:08:10 +00002972 return;
2973
2974give_sigsegv:
2975 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00002976}
2977
Andreas Färber05390242012-02-25 03:37:53 +01002978long do_sigreturn(CPUMIPSState *regs)
bellard106ec872006-06-27 21:08:10 +00002979{
ths388bb212007-05-13 13:58:00 +00002980 struct sigframe *frame;
bellard579a97f2007-11-11 14:26:47 +00002981 abi_ulong frame_addr;
ths388bb212007-05-13 13:58:00 +00002982 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05002983 target_sigset_t target_set;
ths388bb212007-05-13 13:58:00 +00002984 int i;
bellard106ec872006-06-27 21:08:10 +00002985
thsb5dc7732008-06-27 10:02:35 +00002986 frame_addr = regs->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01002987 trace_user_do_sigreturn(regs, frame_addr);
bellard579a97f2007-11-11 14:26:47 +00002988 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01002989 goto badframe;
bellard106ec872006-06-27 21:08:10 +00002990
ths388bb212007-05-13 13:58:00 +00002991 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03002992 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
ths388bb212007-05-13 13:58:00 +00002993 }
bellard106ec872006-06-27 21:08:10 +00002994
ths388bb212007-05-13 13:58:00 +00002995 target_to_host_sigset_internal(&blocked, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00002996 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
bellard106ec872006-06-27 21:08:10 +00002997
Riku Voipio016d2e12014-04-23 11:19:48 +03002998 restore_sigcontext(regs, &frame->sf_sc);
bellard106ec872006-06-27 21:08:10 +00002999
3000#if 0
ths388bb212007-05-13 13:58:00 +00003001 /*
3002 * Don't let your children do this ...
3003 */
3004 __asm__ __volatile__(
bellard106ec872006-06-27 21:08:10 +00003005 "move\t$29, %0\n\t"
3006 "j\tsyscall_exit"
3007 :/* no outputs */
3008 :"r" (&regs));
ths388bb212007-05-13 13:58:00 +00003009 /* Unreached */
bellard106ec872006-06-27 21:08:10 +00003010#endif
ths3b46e622007-09-17 08:09:54 +00003011
thsb5dc7732008-06-27 10:02:35 +00003012 regs->active_tc.PC = regs->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003013 mips_set_hflags_isa_mode_from_pc(regs);
ths388bb212007-05-13 13:58:00 +00003014 /* I am not sure this is right, but it seems to work
bellard106ec872006-06-27 21:08:10 +00003015 * maybe a problem with nested signals ? */
3016 regs->CP0_EPC = 0;
pbrook0b1bcb02009-04-21 01:41:10 +00003017 return -TARGET_QEMU_ESIGRETURN;
bellard106ec872006-06-27 21:08:10 +00003018
3019badframe:
ths388bb212007-05-13 13:58:00 +00003020 force_sig(TARGET_SIGSEGV/*, current*/);
3021 return 0;
bellard106ec872006-06-27 21:08:10 +00003022}
Richard Hendersonff970902013-02-10 10:30:42 -08003023# endif /* O32 */
bellard106ec872006-06-27 21:08:10 +00003024
pbrook624f7972008-05-31 16:11:38 +00003025static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003026 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003027 target_sigset_t *set, CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003028{
pbrook0b1bcb02009-04-21 01:41:10 +00003029 struct target_rt_sigframe *frame;
3030 abi_ulong frame_addr;
3031 int i;
3032
3033 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003034 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003035 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3036 goto give_sigsegv;
3037 }
pbrook0b1bcb02009-04-21 01:41:10 +00003038
3039 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3040
Peter Maydellf6c7a052015-01-08 12:19:48 +00003041 tswap_siginfo(&frame->rs_info, info);
pbrook0b1bcb02009-04-21 01:41:10 +00003042
Aurelien Jarno60e99242010-03-29 02:12:51 +02003043 __put_user(0, &frame->rs_uc.tuc_flags);
3044 __put_user(0, &frame->rs_uc.tuc_link);
3045 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3046 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
pbrook0b1bcb02009-04-21 01:41:10 +00003047 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Aurelien Jarno60e99242010-03-29 02:12:51 +02003048 &frame->rs_uc.tuc_stack.ss_flags);
pbrook0b1bcb02009-04-21 01:41:10 +00003049
Aurelien Jarno60e99242010-03-29 02:12:51 +02003050 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003051
3052 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003053 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
pbrook0b1bcb02009-04-21 01:41:10 +00003054 }
3055
3056 /*
3057 * Arguments to signal handler:
3058 *
3059 * a0 = signal number
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003060 * a1 = pointer to siginfo_t
pbrook0b1bcb02009-04-21 01:41:10 +00003061 * a2 = pointer to struct ucontext
3062 *
3063 * $25 and PC point to the signal handler, $29 points to the
3064 * struct sigframe.
3065 */
3066 env->active_tc.gpr[ 4] = sig;
3067 env->active_tc.gpr[ 5] = frame_addr
3068 + offsetof(struct target_rt_sigframe, rs_info);
3069 env->active_tc.gpr[ 6] = frame_addr
3070 + offsetof(struct target_rt_sigframe, rs_uc);
3071 env->active_tc.gpr[29] = frame_addr;
3072 env->active_tc.gpr[31] = frame_addr
3073 + offsetof(struct target_rt_sigframe, rs_code);
3074 /* The original kernel code sets CP0_EPC to the handler
3075 * since it returns to userland using eret
3076 * we cannot do this here, and we must set PC directly */
3077 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003078 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003079 unlock_user_struct(frame, frame_addr, 1);
3080 return;
3081
3082give_sigsegv:
3083 unlock_user_struct(frame, frame_addr, 1);
3084 force_sig(TARGET_SIGSEGV/*, current*/);
bellard106ec872006-06-27 21:08:10 +00003085}
3086
Andreas Färber05390242012-02-25 03:37:53 +01003087long do_rt_sigreturn(CPUMIPSState *env)
bellard106ec872006-06-27 21:08:10 +00003088{
pbrook0b1bcb02009-04-21 01:41:10 +00003089 struct target_rt_sigframe *frame;
3090 abi_ulong frame_addr;
3091 sigset_t blocked;
3092
pbrook0b1bcb02009-04-21 01:41:10 +00003093 frame_addr = env->active_tc.gpr[29];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003094 trace_user_do_rt_sigreturn(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003095 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3096 goto badframe;
3097 }
pbrook0b1bcb02009-04-21 01:41:10 +00003098
Aurelien Jarno60e99242010-03-29 02:12:51 +02003099 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00003100 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
pbrook0b1bcb02009-04-21 01:41:10 +00003101
Riku Voipio016d2e12014-04-23 11:19:48 +03003102 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
pbrook0b1bcb02009-04-21 01:41:10 +00003103
3104 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003105 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3106 0, get_sp_from_cpustate(env)) == -EFAULT)
pbrook0b1bcb02009-04-21 01:41:10 +00003107 goto badframe;
3108
3109 env->active_tc.PC = env->CP0_EPC;
Kwok Cheung Yeungea3164a2013-05-17 14:51:20 -07003110 mips_set_hflags_isa_mode_from_pc(env);
pbrook0b1bcb02009-04-21 01:41:10 +00003111 /* I am not sure this is right, but it seems to work
3112 * maybe a problem with nested signals ? */
3113 env->CP0_EPC = 0;
3114 return -TARGET_QEMU_ESIGRETURN;
3115
3116badframe:
3117 force_sig(TARGET_SIGSEGV/*, current*/);
3118 return 0;
bellard106ec872006-06-27 21:08:10 +00003119}
bellard6d5e2162004-09-30 22:04:13 +00003120
thsc3b5bc82007-12-02 06:31:25 +00003121#elif defined(TARGET_SH4)
3122
3123/*
3124 * code and data structures from linux kernel:
3125 * include/asm-sh/sigcontext.h
3126 * arch/sh/kernel/signal.c
3127 */
3128
3129struct target_sigcontext {
3130 target_ulong oldmask;
3131
3132 /* CPU registers */
3133 target_ulong sc_gregs[16];
3134 target_ulong sc_pc;
3135 target_ulong sc_pr;
3136 target_ulong sc_sr;
3137 target_ulong sc_gbr;
3138 target_ulong sc_mach;
3139 target_ulong sc_macl;
3140
3141 /* FPU registers */
3142 target_ulong sc_fpregs[16];
3143 target_ulong sc_xfpregs[16];
3144 unsigned int sc_fpscr;
3145 unsigned int sc_fpul;
3146 unsigned int sc_ownedfp;
3147};
3148
3149struct target_sigframe
3150{
3151 struct target_sigcontext sc;
3152 target_ulong extramask[TARGET_NSIG_WORDS-1];
3153 uint16_t retcode[3];
3154};
3155
3156
3157struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02003158 target_ulong tuc_flags;
3159 struct target_ucontext *tuc_link;
3160 target_stack_t tuc_stack;
3161 struct target_sigcontext tuc_mcontext;
3162 target_sigset_t tuc_sigmask; /* mask last for extensibility */
thsc3b5bc82007-12-02 06:31:25 +00003163};
3164
3165struct target_rt_sigframe
3166{
3167 struct target_siginfo info;
3168 struct target_ucontext uc;
3169 uint16_t retcode[3];
3170};
3171
3172
3173#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3174#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3175
pbrook624f7972008-05-31 16:11:38 +00003176static abi_ulong get_sigframe(struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003177 unsigned long sp, size_t frame_size)
thsc3b5bc82007-12-02 06:31:25 +00003178{
pbrook624f7972008-05-31 16:11:38 +00003179 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
thsc3b5bc82007-12-02 06:31:25 +00003180 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3181 }
3182
3183 return (sp - frame_size) & -8ul;
3184}
3185
Riku Voipio41ecc722014-04-23 11:01:00 +03003186static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003187 CPUSH4State *regs, unsigned long mask)
thsc3b5bc82007-12-02 06:31:25 +00003188{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003189 int i;
thsc3b5bc82007-12-02 06:31:25 +00003190
Riku Voipio1d8b5122014-04-23 10:26:05 +03003191#define COPY(x) __put_user(regs->x, &sc->sc_##x)
thsc3b5bc82007-12-02 06:31:25 +00003192 COPY(gregs[0]); COPY(gregs[1]);
3193 COPY(gregs[2]); COPY(gregs[3]);
3194 COPY(gregs[4]); COPY(gregs[5]);
3195 COPY(gregs[6]); COPY(gregs[7]);
3196 COPY(gregs[8]); COPY(gregs[9]);
3197 COPY(gregs[10]); COPY(gregs[11]);
3198 COPY(gregs[12]); COPY(gregs[13]);
3199 COPY(gregs[14]); COPY(gregs[15]);
3200 COPY(gbr); COPY(mach);
3201 COPY(macl); COPY(pr);
3202 COPY(sr); COPY(pc);
3203#undef COPY
3204
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003205 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003206 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003207 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003208 __put_user(regs->fpscr, &sc->sc_fpscr);
3209 __put_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003210
3211 /* non-iBCS2 extensions.. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003212 __put_user(mask, &sc->oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003213}
3214
Timothy E Baldwinba412492016-05-12 18:47:35 +01003215static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
thsc3b5bc82007-12-02 06:31:25 +00003216{
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003217 int i;
thsc3b5bc82007-12-02 06:31:25 +00003218
Riku Voipio1d8b5122014-04-23 10:26:05 +03003219#define COPY(x) __get_user(regs->x, &sc->sc_##x)
Timothy E Baldwinba412492016-05-12 18:47:35 +01003220 COPY(gregs[0]); COPY(gregs[1]);
thsc3b5bc82007-12-02 06:31:25 +00003221 COPY(gregs[2]); COPY(gregs[3]);
3222 COPY(gregs[4]); COPY(gregs[5]);
3223 COPY(gregs[6]); COPY(gregs[7]);
3224 COPY(gregs[8]); COPY(gregs[9]);
3225 COPY(gregs[10]); COPY(gregs[11]);
3226 COPY(gregs[12]); COPY(gregs[13]);
3227 COPY(gregs[14]); COPY(gregs[15]);
3228 COPY(gbr); COPY(mach);
3229 COPY(macl); COPY(pr);
3230 COPY(sr); COPY(pc);
3231#undef COPY
3232
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003233 for (i=0; i<16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003234 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
takasi-y@ops.dti.ne.jpd8714432010-02-18 00:46:45 +09003235 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03003236 __get_user(regs->fpscr, &sc->sc_fpscr);
3237 __get_user(regs->fpul, &sc->sc_fpul);
thsc3b5bc82007-12-02 06:31:25 +00003238
3239 regs->tra = -1; /* disable syscall checks */
thsc3b5bc82007-12-02 06:31:25 +00003240}
3241
pbrook624f7972008-05-31 16:11:38 +00003242static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003243 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003244{
3245 struct target_sigframe *frame;
3246 abi_ulong frame_addr;
3247 int i;
thsc3b5bc82007-12-02 06:31:25 +00003248
3249 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003250 trace_user_setup_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003251 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3252 goto give_sigsegv;
3253 }
thsc3b5bc82007-12-02 06:31:25 +00003254
Riku Voipio41ecc722014-04-23 11:01:00 +03003255 setup_sigcontext(&frame->sc, regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003256
3257 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003258 __put_user(set->sig[i + 1], &frame->extramask[i]);
thsc3b5bc82007-12-02 06:31:25 +00003259 }
3260
3261 /* Set up to return from userspace. If provided, use a stub
3262 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003263 if (ka->sa_flags & TARGET_SA_RESTORER) {
3264 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003265 } else {
3266 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003267 abi_ulong retcode_addr = frame_addr +
3268 offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003269 __put_user(MOVW(2), &frame->retcode[0]);
3270 __put_user(TRAP_NOARG, &frame->retcode[1]);
3271 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003272 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003273 }
3274
thsc3b5bc82007-12-02 06:31:25 +00003275 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003276 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003277 regs->gregs[4] = sig; /* Arg for signal handler */
thsc3b5bc82007-12-02 06:31:25 +00003278 regs->gregs[5] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003279 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
pbrook624f7972008-05-31 16:11:38 +00003280 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003281
3282 unlock_user_struct(frame, frame_addr, 1);
3283 return;
3284
3285give_sigsegv:
3286 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003287 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003288}
3289
pbrook624f7972008-05-31 16:11:38 +00003290static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003291 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003292 target_sigset_t *set, CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003293{
3294 struct target_rt_sigframe *frame;
3295 abi_ulong frame_addr;
3296 int i;
thsc3b5bc82007-12-02 06:31:25 +00003297
3298 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003299 trace_user_setup_rt_frame(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003300 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3301 goto give_sigsegv;
3302 }
thsc3b5bc82007-12-02 06:31:25 +00003303
Peter Maydellf6c7a052015-01-08 12:19:48 +00003304 tswap_siginfo(&frame->info, info);
thsc3b5bc82007-12-02 06:31:25 +00003305
3306 /* Create the ucontext. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003307 __put_user(0, &frame->uc.tuc_flags);
3308 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3309 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3310 &frame->uc.tuc_stack.ss_sp);
3311 __put_user(sas_ss_flags(regs->gregs[15]),
3312 &frame->uc.tuc_stack.ss_flags);
3313 __put_user(target_sigaltstack_used.ss_size,
3314 &frame->uc.tuc_stack.ss_size);
3315 setup_sigcontext(&frame->uc.tuc_mcontext,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003316 regs, set->sig[0]);
thsc3b5bc82007-12-02 06:31:25 +00003317 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003318 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
thsc3b5bc82007-12-02 06:31:25 +00003319 }
3320
3321 /* Set up to return from userspace. If provided, use a stub
3322 already in userspace. */
pbrook624f7972008-05-31 16:11:38 +00003323 if (ka->sa_flags & TARGET_SA_RESTORER) {
3324 regs->pr = (unsigned long) ka->sa_restorer;
thsc3b5bc82007-12-02 06:31:25 +00003325 } else {
3326 /* Generate return code (system call to sigreturn) */
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003327 abi_ulong retcode_addr = frame_addr +
3328 offsetof(struct target_rt_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003329 __put_user(MOVW(2), &frame->retcode[0]);
3330 __put_user(TRAP_NOARG, &frame->retcode[1]);
3331 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
Laurent Vivier2a0fa682015-11-23 11:38:26 +01003332 regs->pr = (unsigned long) retcode_addr;
thsc3b5bc82007-12-02 06:31:25 +00003333 }
3334
thsc3b5bc82007-12-02 06:31:25 +00003335 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003336 regs->gregs[15] = frame_addr;
Peter Maydellb6e2c932015-01-08 12:19:43 +00003337 regs->gregs[4] = sig; /* Arg for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003338 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3339 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
pbrook624f7972008-05-31 16:11:38 +00003340 regs->pc = (unsigned long) ka->_sa_handler;
thsc3b5bc82007-12-02 06:31:25 +00003341
3342 unlock_user_struct(frame, frame_addr, 1);
3343 return;
3344
3345give_sigsegv:
3346 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02003347 force_sig(TARGET_SIGSEGV);
thsc3b5bc82007-12-02 06:31:25 +00003348}
3349
Andreas Färber05390242012-02-25 03:37:53 +01003350long do_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003351{
3352 struct target_sigframe *frame;
3353 abi_ulong frame_addr;
3354 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05003355 target_sigset_t target_set;
thsc3b5bc82007-12-02 06:31:25 +00003356 int i;
3357 int err = 0;
3358
thsc3b5bc82007-12-02 06:31:25 +00003359 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003360 trace_user_do_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003361 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3362 goto badframe;
3363 }
thsc3b5bc82007-12-02 06:31:25 +00003364
Riku Voipio1d8b5122014-04-23 10:26:05 +03003365 __get_user(target_set.sig[0], &frame->sc.oldmask);
thsc3b5bc82007-12-02 06:31:25 +00003366 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03003367 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
thsc3b5bc82007-12-02 06:31:25 +00003368 }
3369
3370 if (err)
3371 goto badframe;
3372
3373 target_to_host_sigset_internal(&blocked, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00003374 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
thsc3b5bc82007-12-02 06:31:25 +00003375
Timothy E Baldwinba412492016-05-12 18:47:35 +01003376 restore_sigcontext(regs, &frame->sc);
thsc3b5bc82007-12-02 06:31:25 +00003377
3378 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003379 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003380
3381badframe:
3382 unlock_user_struct(frame, frame_addr, 0);
3383 force_sig(TARGET_SIGSEGV);
3384 return 0;
3385}
3386
Andreas Färber05390242012-02-25 03:37:53 +01003387long do_rt_sigreturn(CPUSH4State *regs)
thsc3b5bc82007-12-02 06:31:25 +00003388{
3389 struct target_rt_sigframe *frame;
3390 abi_ulong frame_addr;
3391 sigset_t blocked;
3392
thsc3b5bc82007-12-02 06:31:25 +00003393 frame_addr = regs->gregs[15];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003394 trace_user_do_rt_sigreturn(regs, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003395 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3396 goto badframe;
3397 }
thsc3b5bc82007-12-02 06:31:25 +00003398
Aurelien Jarno60e99242010-03-29 02:12:51 +02003399 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00003400 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
thsc3b5bc82007-12-02 06:31:25 +00003401
Timothy E Baldwinba412492016-05-12 18:47:35 +01003402 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
thsc3b5bc82007-12-02 06:31:25 +00003403
3404 if (do_sigaltstack(frame_addr +
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003405 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3406 0, get_sp_from_cpustate(regs)) == -EFAULT) {
thsc3b5bc82007-12-02 06:31:25 +00003407 goto badframe;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003408 }
thsc3b5bc82007-12-02 06:31:25 +00003409
3410 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwinba412492016-05-12 18:47:35 +01003411 return -TARGET_QEMU_ESIGRETURN;
thsc3b5bc82007-12-02 06:31:25 +00003412
3413badframe:
3414 unlock_user_struct(frame, frame_addr, 0);
3415 force_sig(TARGET_SIGSEGV);
3416 return 0;
3417}
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003418#elif defined(TARGET_MICROBLAZE)
3419
3420struct target_sigcontext {
3421 struct target_pt_regs regs; /* needs to be first */
3422 uint32_t oldmask;
3423};
3424
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003425struct target_stack_t {
3426 abi_ulong ss_sp;
3427 int ss_flags;
3428 unsigned int ss_size;
3429};
3430
3431struct target_ucontext {
Richard Hendersonf711df62010-11-22 14:57:52 -08003432 abi_ulong tuc_flags;
3433 abi_ulong tuc_link;
3434 struct target_stack_t tuc_stack;
3435 struct target_sigcontext tuc_mcontext;
3436 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003437};
3438
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003439/* Signal frames. */
3440struct target_signal_frame {
Edgar E. Iglesiasb2178702010-07-23 09:30:37 +02003441 struct target_ucontext uc;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003442 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3443 uint32_t tramp[2];
3444};
3445
3446struct rt_signal_frame {
Richard W.M. Jones02d2bd52012-07-05 03:32:44 +00003447 siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003448 struct ucontext uc;
3449 uint32_t tramp[2];
3450};
3451
Andreas Färber05390242012-02-25 03:37:53 +01003452static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003453{
3454 __put_user(env->regs[0], &sc->regs.r0);
3455 __put_user(env->regs[1], &sc->regs.r1);
3456 __put_user(env->regs[2], &sc->regs.r2);
3457 __put_user(env->regs[3], &sc->regs.r3);
3458 __put_user(env->regs[4], &sc->regs.r4);
3459 __put_user(env->regs[5], &sc->regs.r5);
3460 __put_user(env->regs[6], &sc->regs.r6);
3461 __put_user(env->regs[7], &sc->regs.r7);
3462 __put_user(env->regs[8], &sc->regs.r8);
3463 __put_user(env->regs[9], &sc->regs.r9);
3464 __put_user(env->regs[10], &sc->regs.r10);
3465 __put_user(env->regs[11], &sc->regs.r11);
3466 __put_user(env->regs[12], &sc->regs.r12);
3467 __put_user(env->regs[13], &sc->regs.r13);
3468 __put_user(env->regs[14], &sc->regs.r14);
3469 __put_user(env->regs[15], &sc->regs.r15);
3470 __put_user(env->regs[16], &sc->regs.r16);
3471 __put_user(env->regs[17], &sc->regs.r17);
3472 __put_user(env->regs[18], &sc->regs.r18);
3473 __put_user(env->regs[19], &sc->regs.r19);
3474 __put_user(env->regs[20], &sc->regs.r20);
3475 __put_user(env->regs[21], &sc->regs.r21);
3476 __put_user(env->regs[22], &sc->regs.r22);
3477 __put_user(env->regs[23], &sc->regs.r23);
3478 __put_user(env->regs[24], &sc->regs.r24);
3479 __put_user(env->regs[25], &sc->regs.r25);
3480 __put_user(env->regs[26], &sc->regs.r26);
3481 __put_user(env->regs[27], &sc->regs.r27);
3482 __put_user(env->regs[28], &sc->regs.r28);
3483 __put_user(env->regs[29], &sc->regs.r29);
3484 __put_user(env->regs[30], &sc->regs.r30);
3485 __put_user(env->regs[31], &sc->regs.r31);
3486 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3487}
3488
Andreas Färber05390242012-02-25 03:37:53 +01003489static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003490{
3491 __get_user(env->regs[0], &sc->regs.r0);
3492 __get_user(env->regs[1], &sc->regs.r1);
3493 __get_user(env->regs[2], &sc->regs.r2);
3494 __get_user(env->regs[3], &sc->regs.r3);
3495 __get_user(env->regs[4], &sc->regs.r4);
3496 __get_user(env->regs[5], &sc->regs.r5);
3497 __get_user(env->regs[6], &sc->regs.r6);
3498 __get_user(env->regs[7], &sc->regs.r7);
3499 __get_user(env->regs[8], &sc->regs.r8);
3500 __get_user(env->regs[9], &sc->regs.r9);
3501 __get_user(env->regs[10], &sc->regs.r10);
3502 __get_user(env->regs[11], &sc->regs.r11);
3503 __get_user(env->regs[12], &sc->regs.r12);
3504 __get_user(env->regs[13], &sc->regs.r13);
3505 __get_user(env->regs[14], &sc->regs.r14);
3506 __get_user(env->regs[15], &sc->regs.r15);
3507 __get_user(env->regs[16], &sc->regs.r16);
3508 __get_user(env->regs[17], &sc->regs.r17);
3509 __get_user(env->regs[18], &sc->regs.r18);
3510 __get_user(env->regs[19], &sc->regs.r19);
3511 __get_user(env->regs[20], &sc->regs.r20);
3512 __get_user(env->regs[21], &sc->regs.r21);
3513 __get_user(env->regs[22], &sc->regs.r22);
3514 __get_user(env->regs[23], &sc->regs.r23);
3515 __get_user(env->regs[24], &sc->regs.r24);
3516 __get_user(env->regs[25], &sc->regs.r25);
3517 __get_user(env->regs[26], &sc->regs.r26);
3518 __get_user(env->regs[27], &sc->regs.r27);
3519 __get_user(env->regs[28], &sc->regs.r28);
3520 __get_user(env->regs[29], &sc->regs.r29);
3521 __get_user(env->regs[30], &sc->regs.r30);
3522 __get_user(env->regs[31], &sc->regs.r31);
3523 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3524}
3525
3526static abi_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003527 CPUMBState *env, int frame_size)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003528{
3529 abi_ulong sp = env->regs[1];
3530
Riku Voipiob545f632014-07-15 17:01:55 +03003531 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003532 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
Riku Voipiob545f632014-07-15 17:01:55 +03003533 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003534
3535 return ((sp - frame_size) & -8UL);
3536}
3537
3538static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003539 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003540{
3541 struct target_signal_frame *frame;
3542 abi_ulong frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003543 int i;
3544
3545 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003546 trace_user_setup_frame(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003547 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3548 goto badframe;
3549
3550 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003551 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003552
3553 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03003554 __put_user(set->sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003555 }
3556
Richard Hendersonf711df62010-11-22 14:57:52 -08003557 setup_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003558
3559 /* Set up to return from userspace. If provided, use a stub
3560 already in userspace. */
3561 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3562 if (ka->sa_flags & TARGET_SA_RESTORER) {
3563 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3564 } else {
3565 uint32_t t;
3566 /* Note, these encodings are _big endian_! */
3567 /* addi r12, r0, __NR_sigreturn */
3568 t = 0x31800000UL | TARGET_NR_sigreturn;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003569 __put_user(t, frame->tramp + 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003570 /* brki r14, 0x8 */
3571 t = 0xb9cc0008UL;
Riku Voipio1d8b5122014-04-23 10:26:05 +03003572 __put_user(t, frame->tramp + 1);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003573
3574 /* Return from sighandler will jump to the tramp.
3575 Negative 8 offset because return is rtsd r15, 8 */
3576 env->regs[15] = ((unsigned long)frame->tramp) - 8;
3577 }
3578
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003579 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003580 env->regs[1] = frame_addr;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003581 /* Signal handler args: */
3582 env->regs[5] = sig; /* Arg 0: signum */
Edgar E. Iglesias187b4e02010-07-15 15:32:51 +02003583 env->regs[6] = 0;
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02003584 /* arg 1: sigcontext */
3585 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003586
3587 /* Offset of 4 to handle microblaze rtid r14, 0 */
3588 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3589
3590 unlock_user_struct(frame, frame_addr, 1);
3591 return;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003592badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003593 force_sig(TARGET_SIGSEGV);
3594}
3595
3596static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003597 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003598 target_sigset_t *set, CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003599{
3600 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3601}
3602
Andreas Färber05390242012-02-25 03:37:53 +01003603long do_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003604{
3605 struct target_signal_frame *frame;
3606 abi_ulong frame_addr;
Anthony Liguoric227f092009-10-01 16:12:16 -05003607 target_sigset_t target_set;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003608 sigset_t set;
3609 int i;
3610
3611 frame_addr = env->regs[R_SP];
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003612 trace_user_do_sigreturn(env, frame_addr);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003613 /* Make sure the guest isn't playing games. */
3614 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3615 goto badframe;
3616
3617 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003618 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003619 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003620 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003621 }
3622 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00003623 do_sigprocmask(SIG_SETMASK, &set, NULL);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003624
Richard Hendersonf711df62010-11-22 14:57:52 -08003625 restore_sigcontext(&frame->uc.tuc_mcontext, env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003626 /* We got here through a sigreturn syscall, our path back is via an
3627 rtb insn so setup r14 for that. */
3628 env->regs[14] = env->sregs[SR_PC];
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003629
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003630 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin4134ecf2016-05-12 18:47:44 +01003631 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003632badframe:
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003633 force_sig(TARGET_SIGSEGV);
3634}
3635
Andreas Färber05390242012-02-25 03:37:53 +01003636long do_rt_sigreturn(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003637{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003638 trace_user_do_rt_sigreturn(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003639 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3640 return -TARGET_ENOSYS;
3641}
3642
edgar_iglb6d3abd2008-02-28 11:29:27 +00003643#elif defined(TARGET_CRIS)
3644
3645struct target_sigcontext {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003646 struct target_pt_regs regs; /* needs to be first */
3647 uint32_t oldmask;
3648 uint32_t usp; /* usp before stacking this gunk on it */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003649};
3650
3651/* Signal frames. */
3652struct target_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003653 struct target_sigcontext sc;
3654 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3655 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003656};
3657
3658struct rt_signal_frame {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003659 siginfo_t *pinfo;
3660 void *puc;
3661 siginfo_t info;
3662 struct ucontext uc;
3663 uint16_t retcode[4]; /* Trampoline code. */
edgar_iglb6d3abd2008-02-28 11:29:27 +00003664};
3665
Andreas Färber05390242012-02-25 03:37:53 +01003666static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003667{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003668 __put_user(env->regs[0], &sc->regs.r0);
3669 __put_user(env->regs[1], &sc->regs.r1);
3670 __put_user(env->regs[2], &sc->regs.r2);
3671 __put_user(env->regs[3], &sc->regs.r3);
3672 __put_user(env->regs[4], &sc->regs.r4);
3673 __put_user(env->regs[5], &sc->regs.r5);
3674 __put_user(env->regs[6], &sc->regs.r6);
3675 __put_user(env->regs[7], &sc->regs.r7);
3676 __put_user(env->regs[8], &sc->regs.r8);
3677 __put_user(env->regs[9], &sc->regs.r9);
3678 __put_user(env->regs[10], &sc->regs.r10);
3679 __put_user(env->regs[11], &sc->regs.r11);
3680 __put_user(env->regs[12], &sc->regs.r12);
3681 __put_user(env->regs[13], &sc->regs.r13);
3682 __put_user(env->regs[14], &sc->usp);
3683 __put_user(env->regs[15], &sc->regs.acr);
3684 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3685 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3686 __put_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003687}
edgar_igl9664d922008-03-03 22:23:53 +00003688
Andreas Färber05390242012-02-25 03:37:53 +01003689static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003690{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003691 __get_user(env->regs[0], &sc->regs.r0);
3692 __get_user(env->regs[1], &sc->regs.r1);
3693 __get_user(env->regs[2], &sc->regs.r2);
3694 __get_user(env->regs[3], &sc->regs.r3);
3695 __get_user(env->regs[4], &sc->regs.r4);
3696 __get_user(env->regs[5], &sc->regs.r5);
3697 __get_user(env->regs[6], &sc->regs.r6);
3698 __get_user(env->regs[7], &sc->regs.r7);
3699 __get_user(env->regs[8], &sc->regs.r8);
3700 __get_user(env->regs[9], &sc->regs.r9);
3701 __get_user(env->regs[10], &sc->regs.r10);
3702 __get_user(env->regs[11], &sc->regs.r11);
3703 __get_user(env->regs[12], &sc->regs.r12);
3704 __get_user(env->regs[13], &sc->regs.r13);
3705 __get_user(env->regs[14], &sc->usp);
3706 __get_user(env->regs[15], &sc->regs.acr);
3707 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3708 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3709 __get_user(env->pc, &sc->regs.erp);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003710}
3711
Andreas Färber05390242012-02-25 03:37:53 +01003712static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003713{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003714 abi_ulong sp;
3715 /* Align the stack downwards to 4. */
3716 sp = (env->regs[R_SP] & ~3);
3717 return sp - framesize;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003718}
3719
pbrook624f7972008-05-31 16:11:38 +00003720static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01003721 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003722{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003723 struct target_signal_frame *frame;
3724 abi_ulong frame_addr;
3725 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003726
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003727 frame_addr = get_sigframe(env, sizeof *frame);
3728 trace_user_setup_frame(env, frame_addr);
3729 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3730 goto badframe;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003731
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003732 /*
3733 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3734 * use this trampoline anymore but it sets it up for GDB.
3735 * In QEMU, using the trampoline simplifies things a bit so we use it.
3736 *
3737 * This is movu.w __NR_sigreturn, r9; break 13;
3738 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003739 __put_user(0x9c5f, frame->retcode+0);
3740 __put_user(TARGET_NR_sigreturn,
3741 frame->retcode + 1);
3742 __put_user(0xe93d, frame->retcode + 2);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003743
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003744 /* Save the mask. */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003745 __put_user(set->sig[0], &frame->sc.oldmask);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003746
Riku Voipio0188fad2014-04-23 13:34:15 +03003747 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3748 __put_user(set->sig[i], &frame->extramask[i - 1]);
3749 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003750
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003751 setup_sigcontext(&frame->sc, env);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003752
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003753 /* Move the stack and setup the arguments for the handler. */
3754 env->regs[R_SP] = frame_addr;
3755 env->regs[10] = sig;
3756 env->pc = (unsigned long) ka->_sa_handler;
3757 /* Link SRP so the guest returns through the trampoline. */
3758 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003759
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003760 unlock_user_struct(frame, frame_addr, 1);
3761 return;
3762badframe:
3763 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003764}
3765
pbrook624f7972008-05-31 16:11:38 +00003766static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05003767 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01003768 target_sigset_t *set, CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003769{
3770 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3771}
3772
Andreas Färber05390242012-02-25 03:37:53 +01003773long do_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003774{
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003775 struct target_signal_frame *frame;
3776 abi_ulong frame_addr;
3777 target_sigset_t target_set;
3778 sigset_t set;
3779 int i;
edgar_iglb6d3abd2008-02-28 11:29:27 +00003780
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003781 frame_addr = env->regs[R_SP];
3782 trace_user_do_sigreturn(env, frame_addr);
3783 /* Make sure the guest isn't playing games. */
3784 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
3785 goto badframe;
3786 }
edgar_iglb6d3abd2008-02-28 11:29:27 +00003787
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003788 /* Restore blocked signals */
Riku Voipiof5f601a2014-04-23 13:00:17 +03003789 __get_user(target_set.sig[0], &frame->sc.oldmask);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003790 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03003791 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003792 }
3793 target_to_host_sigset_internal(&set, &target_set);
3794 do_sigprocmask(SIG_SETMASK, &set, NULL);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003795
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003796 restore_sigcontext(&frame->sc, env);
3797 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin62050862016-05-12 18:47:41 +01003798 return -TARGET_QEMU_ESIGRETURN;
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003799badframe:
3800 force_sig(TARGET_SIGSEGV);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003801}
3802
Andreas Färber05390242012-02-25 03:37:53 +01003803long do_rt_sigreturn(CPUCRISState *env)
edgar_iglb6d3abd2008-02-28 11:29:27 +00003804{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003805 trace_user_do_rt_sigreturn(env, 0);
edgar_iglb6d3abd2008-02-28 11:29:27 +00003806 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3807 return -TARGET_ENOSYS;
3808}
thsc3b5bc82007-12-02 06:31:25 +00003809
Jia Liud9627832012-07-20 15:50:52 +08003810#elif defined(TARGET_OPENRISC)
3811
3812struct target_sigcontext {
3813 struct target_pt_regs regs;
3814 abi_ulong oldmask;
3815 abi_ulong usp;
3816};
3817
3818struct target_ucontext {
3819 abi_ulong tuc_flags;
3820 abi_ulong tuc_link;
3821 target_stack_t tuc_stack;
3822 struct target_sigcontext tuc_mcontext;
3823 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3824};
3825
3826struct target_rt_sigframe {
3827 abi_ulong pinfo;
3828 uint64_t puc;
3829 struct target_siginfo info;
3830 struct target_sigcontext sc;
3831 struct target_ucontext uc;
3832 unsigned char retcode[16]; /* trampoline code */
3833};
3834
3835/* This is the asm-generic/ucontext.h version */
3836#if 0
3837static int restore_sigcontext(CPUOpenRISCState *regs,
3838 struct target_sigcontext *sc)
3839{
3840 unsigned int err = 0;
3841 unsigned long old_usp;
3842
3843 /* Alwys make any pending restarted system call return -EINTR */
3844 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3845
3846 /* restore the regs from &sc->regs (same as sc, since regs is first)
3847 * (sc is already checked for VERIFY_READ since the sigframe was
3848 * checked in sys_sigreturn previously)
3849 */
3850
3851 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3852 goto badframe;
3853 }
3854
3855 /* make sure the U-flag is set so user-mode cannot fool us */
3856
3857 regs->sr &= ~SR_SM;
3858
3859 /* restore the old USP as it was before we stacked the sc etc.
3860 * (we cannot just pop the sigcontext since we aligned the sp and
3861 * stuff after pushing it)
3862 */
3863
Riku Voipio1d8b5122014-04-23 10:26:05 +03003864 __get_user(old_usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003865 phx_signal("old_usp 0x%lx", old_usp);
3866
3867 __PHX__ REALLY /* ??? */
3868 wrusp(old_usp);
3869 regs->gpr[1] = old_usp;
3870
3871 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3872 * after this completes, but we don't use that mechanism. maybe we can
3873 * use it now ?
3874 */
3875
3876 return err;
3877
3878badframe:
3879 return 1;
3880}
3881#endif
3882
3883/* Set up a signal frame. */
3884
Riku Voipio41ecc722014-04-23 11:01:00 +03003885static void setup_sigcontext(struct target_sigcontext *sc,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01003886 CPUOpenRISCState *regs,
3887 unsigned long mask)
Jia Liud9627832012-07-20 15:50:52 +08003888{
Jia Liud9627832012-07-20 15:50:52 +08003889 unsigned long usp = regs->gpr[1];
3890
3891 /* copy the regs. they are first in sc so we can use sc directly */
3892
Riku Voipio1d8b5122014-04-23 10:26:05 +03003893 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
Jia Liud9627832012-07-20 15:50:52 +08003894
3895 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3896 the signal handler. The frametype will be restored to its previous
3897 value in restore_sigcontext. */
3898 /*regs->frametype = CRIS_FRAME_NORMAL;*/
3899
3900 /* then some other stuff */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003901 __put_user(mask, &sc->oldmask);
Riku Voipio41ecc722014-04-23 11:01:00 +03003902 __put_user(usp, &sc->usp);
Jia Liud9627832012-07-20 15:50:52 +08003903}
3904
3905static inline unsigned long align_sigframe(unsigned long sp)
3906{
3907 unsigned long i;
3908 i = sp & ~3UL;
3909 return i;
3910}
3911
3912static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3913 CPUOpenRISCState *regs,
3914 size_t frame_size)
3915{
3916 unsigned long sp = regs->gpr[1];
3917 int onsigstack = on_sig_stack(sp);
3918
3919 /* redzone */
3920 /* This is the X/Open sanctioned signal stack switching. */
Riku Voipiob545f632014-07-15 17:01:55 +03003921 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
Jia Liud9627832012-07-20 15:50:52 +08003922 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3923 }
3924
3925 sp = align_sigframe(sp - frame_size);
3926
3927 /*
3928 * If we are on the alternate signal stack and would overflow it, don't.
3929 * Return an always-bogus address instead so we will die with SIGSEGV.
3930 */
3931
3932 if (onsigstack && !likely(on_sig_stack(sp))) {
3933 return -1L;
3934 }
3935
3936 return sp;
3937}
3938
Jia Liud9627832012-07-20 15:50:52 +08003939static void setup_rt_frame(int sig, struct target_sigaction *ka,
3940 target_siginfo_t *info,
3941 target_sigset_t *set, CPUOpenRISCState *env)
3942{
3943 int err = 0;
3944 abi_ulong frame_addr;
3945 unsigned long return_ip;
3946 struct target_rt_sigframe *frame;
3947 abi_ulong info_addr, uc_addr;
3948
Jia Liud9627832012-07-20 15:50:52 +08003949 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01003950 trace_user_setup_rt_frame(env, frame_addr);
Jia Liud9627832012-07-20 15:50:52 +08003951 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3952 goto give_sigsegv;
3953 }
3954
3955 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003956 __put_user(info_addr, &frame->pinfo);
Jia Liud9627832012-07-20 15:50:52 +08003957 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03003958 __put_user(uc_addr, &frame->puc);
Jia Liud9627832012-07-20 15:50:52 +08003959
3960 if (ka->sa_flags & SA_SIGINFO) {
Peter Maydellf6c7a052015-01-08 12:19:48 +00003961 tswap_siginfo(&frame->info, info);
Jia Liud9627832012-07-20 15:50:52 +08003962 }
3963
3964 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
Riku Voipio1d8b5122014-04-23 10:26:05 +03003965 __put_user(0, &frame->uc.tuc_flags);
3966 __put_user(0, &frame->uc.tuc_link);
3967 __put_user(target_sigaltstack_used.ss_sp,
3968 &frame->uc.tuc_stack.ss_sp);
3969 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
3970 __put_user(target_sigaltstack_used.ss_size,
3971 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03003972 setup_sigcontext(&frame->sc, env, set->sig[0]);
Jia Liud9627832012-07-20 15:50:52 +08003973
3974 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
3975
Jia Liud9627832012-07-20 15:50:52 +08003976 /* trampoline - the desired return ip is the retcode itself */
3977 return_ip = (unsigned long)&frame->retcode;
3978 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
Riku Voipio1d8b5122014-04-23 10:26:05 +03003979 __put_user(0xa960, (short *)(frame->retcode + 0));
3980 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
3981 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
3982 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
Jia Liud9627832012-07-20 15:50:52 +08003983
3984 if (err) {
3985 goto give_sigsegv;
3986 }
3987
3988 /* TODO what is the current->exec_domain stuff and invmap ? */
3989
3990 /* Set up registers for signal handler */
3991 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
3992 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
3993 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
3994 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
3995 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
3996
3997 /* actually move the usp to reflect the stacked frame */
3998 env->gpr[1] = (unsigned long)frame;
3999
4000 return;
4001
4002give_sigsegv:
4003 unlock_user_struct(frame, frame_addr, 1);
4004 if (sig == TARGET_SIGSEGV) {
4005 ka->_sa_handler = TARGET_SIG_DFL;
4006 }
4007 force_sig(TARGET_SIGSEGV);
4008}
4009
4010long do_sigreturn(CPUOpenRISCState *env)
4011{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004012 trace_user_do_sigreturn(env, 0);
4013 fprintf(stderr, "do_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004014 return -TARGET_ENOSYS;
4015}
4016
4017long do_rt_sigreturn(CPUOpenRISCState *env)
4018{
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004019 trace_user_do_rt_sigreturn(env, 0);
4020 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
Jia Liud9627832012-07-20 15:50:52 +08004021 return -TARGET_ENOSYS;
4022}
4023/* TARGET_OPENRISC */
4024
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004025#elif defined(TARGET_S390X)
4026
4027#define __NUM_GPRS 16
4028#define __NUM_FPRS 16
4029#define __NUM_ACRS 16
4030
4031#define S390_SYSCALL_SIZE 2
4032#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4033
4034#define _SIGCONTEXT_NSIG 64
4035#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4036#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4037#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4038#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4039#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4040
4041typedef struct {
4042 target_psw_t psw;
4043 target_ulong gprs[__NUM_GPRS];
4044 unsigned int acrs[__NUM_ACRS];
4045} target_s390_regs_common;
4046
4047typedef struct {
4048 unsigned int fpc;
4049 double fprs[__NUM_FPRS];
4050} target_s390_fp_regs;
4051
4052typedef struct {
4053 target_s390_regs_common regs;
4054 target_s390_fp_regs fpregs;
4055} target_sigregs;
4056
4057struct target_sigcontext {
4058 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4059 target_sigregs *sregs;
4060};
4061
4062typedef struct {
4063 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4064 struct target_sigcontext sc;
4065 target_sigregs sregs;
4066 int signo;
4067 uint8_t retcode[S390_SYSCALL_SIZE];
4068} sigframe;
4069
4070struct target_ucontext {
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004071 target_ulong tuc_flags;
4072 struct target_ucontext *tuc_link;
4073 target_stack_t tuc_stack;
4074 target_sigregs tuc_mcontext;
4075 target_sigset_t tuc_sigmask; /* mask last for extensibility */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004076};
4077
4078typedef struct {
4079 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4080 uint8_t retcode[S390_SYSCALL_SIZE];
4081 struct target_siginfo info;
4082 struct target_ucontext uc;
4083} rt_sigframe;
4084
4085static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01004086get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004087{
4088 abi_ulong sp;
4089
4090 /* Default to using normal stack */
4091 sp = env->regs[15];
4092
4093 /* This is the X/Open sanctioned signal stack switching. */
4094 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4095 if (!sas_ss_flags(sp)) {
4096 sp = target_sigaltstack_used.ss_sp +
4097 target_sigaltstack_used.ss_size;
4098 }
4099 }
4100
4101 /* This is the legacy signal stack switching. */
4102 else if (/* FIXME !user_mode(regs) */ 0 &&
4103 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4104 ka->sa_restorer) {
4105 sp = (abi_ulong) ka->sa_restorer;
4106 }
4107
4108 return (sp - frame_size) & -8ul;
4109}
4110
Andreas Färber05390242012-02-25 03:37:53 +01004111static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004112{
4113 int i;
4114 //save_access_regs(current->thread.acrs); FIXME
4115
4116 /* Copy a 'clean' PSW mask to the user to avoid leaking
4117 information about whether PER is currently on. */
4118 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4119 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4120 for (i = 0; i < 16; i++) {
4121 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4122 }
4123 for (i = 0; i < 16; i++) {
4124 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4125 }
4126 /*
4127 * We have to store the fp registers to current->thread.fp_regs
4128 * to merge them with the emulated registers.
4129 */
4130 //save_fp_regs(&current->thread.fp_regs); FIXME
4131 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004132 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004133 }
4134}
4135
4136static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004137 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004138{
4139 sigframe *frame;
4140 abi_ulong frame_addr;
4141
4142 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004143 trace_user_setup_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004144 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004145 goto give_sigsegv;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004146 }
4147
Riku Voipio0188fad2014-04-23 13:34:15 +03004148 __put_user(set->sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004149
4150 save_sigregs(env, &frame->sregs);
4151
4152 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4153 (abi_ulong *)&frame->sc.sregs);
4154
4155 /* Set up to return from userspace. If provided, use a stub
4156 already in userspace. */
4157 if (ka->sa_flags & TARGET_SA_RESTORER) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004158 env->regs[14] = (unsigned long)
4159 ka->sa_restorer | PSW_ADDR_AMODE;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004160 } else {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004161 env->regs[14] = (unsigned long)
4162 frame->retcode | PSW_ADDR_AMODE;
4163 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4164 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004165 }
4166
4167 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004168 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004169
4170 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004171 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004172 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4173
4174 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004175 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004176
4177 /* We forgot to include these in the sigcontext.
4178 To avoid breaking binary compatibility, they are passed as args. */
4179 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4180 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4181
4182 /* Place signal number on stack to allow backtrace from handler. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004183 __put_user(env->regs[2], (int *) &frame->signo);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004184 unlock_user_struct(frame, frame_addr, 1);
4185 return;
4186
4187give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004188 force_sig(TARGET_SIGSEGV);
4189}
4190
4191static void setup_rt_frame(int sig, struct target_sigaction *ka,
4192 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004193 target_sigset_t *set, CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004194{
4195 int i;
4196 rt_sigframe *frame;
4197 abi_ulong frame_addr;
4198
4199 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004200 trace_user_setup_rt_frame(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004201 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4202 goto give_sigsegv;
4203 }
4204
Peter Maydellf6c7a052015-01-08 12:19:48 +00004205 tswap_siginfo(&frame->info, info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004206
4207 /* Create the ucontext. */
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004208 __put_user(0, &frame->uc.tuc_flags);
4209 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4210 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004211 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004212 &frame->uc.tuc_stack.ss_flags);
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004213 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4214 save_sigregs(env, &frame->uc.tuc_mcontext);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004215 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4216 __put_user((abi_ulong)set->sig[i],
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004217 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004218 }
4219
4220 /* Set up to return from userspace. If provided, use a stub
4221 already in userspace. */
4222 if (ka->sa_flags & TARGET_SA_RESTORER) {
4223 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4224 } else {
4225 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
Riku Voipio0188fad2014-04-23 13:34:15 +03004226 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4227 (uint16_t *)(frame->retcode));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004228 }
4229
4230 /* Set up backchain. */
Riku Voipio0188fad2014-04-23 13:34:15 +03004231 __put_user(env->regs[15], (abi_ulong *) frame);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004232
4233 /* Set up registers for signal handler */
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004234 env->regs[15] = frame_addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004235 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4236
4237 env->regs[2] = sig; //map_signal(sig);
Edgar E. Iglesiascb9c6262011-08-22 18:44:58 +02004238 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4239 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004240 return;
4241
4242give_sigsegv:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004243 force_sig(TARGET_SIGSEGV);
4244}
4245
4246static int
Andreas Färber05390242012-02-25 03:37:53 +01004247restore_sigregs(CPUS390XState *env, target_sigregs *sc)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004248{
4249 int err = 0;
4250 int i;
4251
4252 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004253 __get_user(env->regs[i], &sc->regs.gprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004254 }
4255
Riku Voipio1d8b5122014-04-23 10:26:05 +03004256 __get_user(env->psw.mask, &sc->regs.psw.mask);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004257 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4258 (unsigned long long)env->psw.addr);
Riku Voipio1d8b5122014-04-23 10:26:05 +03004259 __get_user(env->psw.addr, &sc->regs.psw.addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004260 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4261
4262 for (i = 0; i < 16; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004263 __get_user(env->aregs[i], &sc->regs.acrs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004264 }
4265 for (i = 0; i < 16; i++) {
Eric Farmanc498d8e2015-05-07 14:35:44 -04004266 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004267 }
4268
4269 return err;
4270}
4271
Andreas Färber05390242012-02-25 03:37:53 +01004272long do_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004273{
4274 sigframe *frame;
4275 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004276 target_sigset_t target_set;
4277 sigset_t set;
4278
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004279 trace_user_do_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004280 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4281 goto badframe;
4282 }
Riku Voipiof5f601a2014-04-23 13:00:17 +03004283 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004284
4285 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004286 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004287
4288 if (restore_sigregs(env, &frame->sregs)) {
4289 goto badframe;
4290 }
4291
4292 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004293 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004294
4295badframe:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004296 force_sig(TARGET_SIGSEGV);
4297 return 0;
4298}
4299
Andreas Färber05390242012-02-25 03:37:53 +01004300long do_rt_sigreturn(CPUS390XState *env)
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004301{
4302 rt_sigframe *frame;
4303 abi_ulong frame_addr = env->regs[15];
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004304 sigset_t set;
4305
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004306 trace_user_do_rt_sigreturn(env, frame_addr);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004307 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4308 goto badframe;
4309 }
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004310 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004311
Alex Barcelo1c275922014-03-14 14:36:55 +00004312 do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004313
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004314 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004315 goto badframe;
4316 }
4317
Peter Maydell6fea2ea2011-07-12 21:27:15 +01004318 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004319 get_sp_from_cpustate(env)) == -EFAULT) {
4320 goto badframe;
4321 }
4322 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin47405ab2016-05-12 18:47:40 +01004323 return -TARGET_QEMU_ESIGRETURN;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004324
4325badframe:
4326 unlock_user_struct(frame, frame_addr, 0);
4327 force_sig(TARGET_SIGSEGV);
4328 return 0;
4329}
4330
Tom Musta61e75fe2014-06-30 08:13:38 -05004331#elif defined(TARGET_PPC)
Nathan Froydbcd49332009-05-12 19:13:18 -07004332
4333/* Size of dummy stack frame allocated when calling signal handler.
4334 See arch/powerpc/include/asm/ptrace.h. */
4335#if defined(TARGET_PPC64)
4336#define SIGNAL_FRAMESIZE 128
4337#else
4338#define SIGNAL_FRAMESIZE 64
4339#endif
4340
Tom Musta61e75fe2014-06-30 08:13:38 -05004341/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4342 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4343struct target_mcontext {
4344 target_ulong mc_gregs[48];
4345 /* Includes fpscr. */
4346 uint64_t mc_fregs[33];
4347 target_ulong mc_pad[2];
4348 /* We need to handle Altivec and SPE at the same time, which no
4349 kernel needs to do. Fortunately, the kernel defines this bit to
4350 be Altivec-register-large all the time, rather than trying to
4351 twiddle it based on the specific platform. */
4352 union {
4353 /* SPE vector registers. One extra for SPEFSCR. */
4354 uint32_t spe[33];
4355 /* Altivec vector registers. The packing of VSCR and VRSAVE
4356 varies depending on whether we're PPC64 or not: PPC64 splits
4357 them apart; PPC32 stuffs them together. */
4358#if defined(TARGET_PPC64)
4359#define QEMU_NVRREG 34
4360#else
4361#define QEMU_NVRREG 33
4362#endif
4363 ppc_avr_t altivec[QEMU_NVRREG];
4364#undef QEMU_NVRREG
4365 } mc_vregs __attribute__((__aligned__(16)));
4366};
4367
Nathan Froydbcd49332009-05-12 19:13:18 -07004368/* See arch/powerpc/include/asm/sigcontext.h. */
4369struct target_sigcontext {
4370 target_ulong _unused[4];
4371 int32_t signal;
4372#if defined(TARGET_PPC64)
4373 int32_t pad0;
4374#endif
4375 target_ulong handler;
4376 target_ulong oldmask;
4377 target_ulong regs; /* struct pt_regs __user * */
Tom Musta61e75fe2014-06-30 08:13:38 -05004378#if defined(TARGET_PPC64)
4379 struct target_mcontext mcontext;
4380#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004381};
4382
4383/* Indices for target_mcontext.mc_gregs, below.
4384 See arch/powerpc/include/asm/ptrace.h for details. */
4385enum {
4386 TARGET_PT_R0 = 0,
4387 TARGET_PT_R1 = 1,
4388 TARGET_PT_R2 = 2,
4389 TARGET_PT_R3 = 3,
4390 TARGET_PT_R4 = 4,
4391 TARGET_PT_R5 = 5,
4392 TARGET_PT_R6 = 6,
4393 TARGET_PT_R7 = 7,
4394 TARGET_PT_R8 = 8,
4395 TARGET_PT_R9 = 9,
4396 TARGET_PT_R10 = 10,
4397 TARGET_PT_R11 = 11,
4398 TARGET_PT_R12 = 12,
4399 TARGET_PT_R13 = 13,
4400 TARGET_PT_R14 = 14,
4401 TARGET_PT_R15 = 15,
4402 TARGET_PT_R16 = 16,
4403 TARGET_PT_R17 = 17,
4404 TARGET_PT_R18 = 18,
4405 TARGET_PT_R19 = 19,
4406 TARGET_PT_R20 = 20,
4407 TARGET_PT_R21 = 21,
4408 TARGET_PT_R22 = 22,
4409 TARGET_PT_R23 = 23,
4410 TARGET_PT_R24 = 24,
4411 TARGET_PT_R25 = 25,
4412 TARGET_PT_R26 = 26,
4413 TARGET_PT_R27 = 27,
4414 TARGET_PT_R28 = 28,
4415 TARGET_PT_R29 = 29,
4416 TARGET_PT_R30 = 30,
4417 TARGET_PT_R31 = 31,
4418 TARGET_PT_NIP = 32,
4419 TARGET_PT_MSR = 33,
4420 TARGET_PT_ORIG_R3 = 34,
4421 TARGET_PT_CTR = 35,
4422 TARGET_PT_LNK = 36,
4423 TARGET_PT_XER = 37,
4424 TARGET_PT_CCR = 38,
4425 /* Yes, there are two registers with #39. One is 64-bit only. */
4426 TARGET_PT_MQ = 39,
4427 TARGET_PT_SOFTE = 39,
4428 TARGET_PT_TRAP = 40,
4429 TARGET_PT_DAR = 41,
4430 TARGET_PT_DSISR = 42,
4431 TARGET_PT_RESULT = 43,
4432 TARGET_PT_REGS_COUNT = 44
4433};
4434
Nathan Froydbcd49332009-05-12 19:13:18 -07004435
4436struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004437 target_ulong tuc_flags;
4438 target_ulong tuc_link; /* struct ucontext __user * */
4439 struct target_sigaltstack tuc_stack;
Nathan Froydbcd49332009-05-12 19:13:18 -07004440#if !defined(TARGET_PPC64)
Aurelien Jarno60e99242010-03-29 02:12:51 +02004441 int32_t tuc_pad[7];
4442 target_ulong tuc_regs; /* struct mcontext __user *
Nathan Froydbcd49332009-05-12 19:13:18 -07004443 points to uc_mcontext field */
4444#endif
Aurelien Jarno60e99242010-03-29 02:12:51 +02004445 target_sigset_t tuc_sigmask;
Nathan Froydbcd49332009-05-12 19:13:18 -07004446#if defined(TARGET_PPC64)
Anthony Liguoric227f092009-10-01 16:12:16 -05004447 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
Tom Musta61e75fe2014-06-30 08:13:38 -05004448 struct target_sigcontext tuc_sigcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004449#else
Aurelien Jarno60e99242010-03-29 02:12:51 +02004450 int32_t tuc_maskext[30];
4451 int32_t tuc_pad2[3];
4452 struct target_mcontext tuc_mcontext;
Nathan Froydbcd49332009-05-12 19:13:18 -07004453#endif
4454};
4455
4456/* See arch/powerpc/kernel/signal_32.c. */
4457struct target_sigframe {
4458 struct target_sigcontext sctx;
4459 struct target_mcontext mctx;
4460 int32_t abigap[56];
4461};
4462
Tom Musta61e75fe2014-06-30 08:13:38 -05004463#if defined(TARGET_PPC64)
4464
4465#define TARGET_TRAMP_SIZE 6
4466
4467struct target_rt_sigframe {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004468 /* sys_rt_sigreturn requires the ucontext be the first field */
4469 struct target_ucontext uc;
4470 target_ulong _unused[2];
4471 uint32_t trampoline[TARGET_TRAMP_SIZE];
4472 target_ulong pinfo; /* struct siginfo __user * */
4473 target_ulong puc; /* void __user * */
4474 struct target_siginfo info;
4475 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
4476 char abigap[288];
Tom Musta61e75fe2014-06-30 08:13:38 -05004477} __attribute__((aligned(16)));
4478
4479#else
4480
Nathan Froydbcd49332009-05-12 19:13:18 -07004481struct target_rt_sigframe {
4482 struct target_siginfo info;
4483 struct target_ucontext uc;
4484 int32_t abigap[56];
4485};
4486
Tom Musta61e75fe2014-06-30 08:13:38 -05004487#endif
4488
Tom Musta8d6ab332014-06-30 08:13:39 -05004489#if defined(TARGET_PPC64)
4490
4491struct target_func_ptr {
4492 target_ulong entry;
4493 target_ulong toc;
4494};
4495
4496#endif
4497
Nathan Froydbcd49332009-05-12 19:13:18 -07004498/* We use the mc_pad field for the signal return trampoline. */
4499#define tramp mc_pad
4500
4501/* See arch/powerpc/kernel/signal.c. */
4502static target_ulong get_sigframe(struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004503 CPUPPCState *env,
Nathan Froydbcd49332009-05-12 19:13:18 -07004504 int frame_size)
4505{
4506 target_ulong oldsp, newsp;
4507
4508 oldsp = env->gpr[1];
4509
4510 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004511 (sas_ss_flags(oldsp) == 0)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07004512 oldsp = (target_sigaltstack_used.ss_sp
4513 + target_sigaltstack_used.ss_size);
4514 }
4515
4516 newsp = (oldsp - frame_size) & ~0xFUL;
4517
4518 return newsp;
4519}
4520
Tom Musta76781082014-06-30 08:13:37 -05004521static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
Nathan Froydbcd49332009-05-12 19:13:18 -07004522{
4523 target_ulong msr = env->msr;
4524 int i;
4525 target_ulong ccr = 0;
4526
4527 /* In general, the kernel attempts to be intelligent about what it
4528 needs to save for Altivec/FP/SPE registers. We don't care that
4529 much, so we just go ahead and save everything. */
4530
4531 /* Save general registers. */
4532 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004533 __put_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004534 }
Riku Voipioc650c002014-04-23 13:53:45 +03004535 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4536 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4537 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4538 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004539
4540 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4541 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4542 }
Riku Voipioc650c002014-04-23 13:53:45 +03004543 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004544
4545 /* Save Altivec registers if necessary. */
4546 if (env->insns_flags & PPC_ALTIVEC) {
4547 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004548 ppc_avr_t *avr = &env->avr[i];
4549 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004550
Riku Voipioc650c002014-04-23 13:53:45 +03004551 __put_user(avr->u64[0], &vreg->u64[0]);
4552 __put_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004553 }
4554 /* Set MSR_VR in the saved MSR value to indicate that
4555 frame->mc_vregs contains valid data. */
4556 msr |= MSR_VR;
Riku Voipioc650c002014-04-23 13:53:45 +03004557 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4558 &frame->mc_vregs.altivec[32].u32[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004559 }
4560
4561 /* Save floating point registers. */
4562 if (env->insns_flags & PPC_FLOAT) {
4563 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004564 __put_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004565 }
Riku Voipioc650c002014-04-23 13:53:45 +03004566 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004567 }
4568
4569 /* Save SPE registers. The kernel only saves the high half. */
4570 if (env->insns_flags & PPC_SPE) {
4571#if defined(TARGET_PPC64)
4572 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004573 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004574 }
4575#else
4576 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004577 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004578 }
4579#endif
4580 /* Set MSR_SPE in the saved MSR value to indicate that
4581 frame->mc_vregs contains valid data. */
4582 msr |= MSR_SPE;
Riku Voipioc650c002014-04-23 13:53:45 +03004583 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004584 }
4585
4586 /* Store MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004587 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Tom Musta76781082014-06-30 08:13:37 -05004588}
Nathan Froydbcd49332009-05-12 19:13:18 -07004589
Tom Musta76781082014-06-30 08:13:37 -05004590static void encode_trampoline(int sigret, uint32_t *tramp)
4591{
Nathan Froydbcd49332009-05-12 19:13:18 -07004592 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4593 if (sigret) {
Tom Musta76781082014-06-30 08:13:37 -05004594 __put_user(0x38000000 | sigret, &tramp[0]);
4595 __put_user(0x44000002, &tramp[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004596 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004597}
4598
Riku Voipioc650c002014-04-23 13:53:45 +03004599static void restore_user_regs(CPUPPCState *env,
4600 struct target_mcontext *frame, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004601{
4602 target_ulong save_r2 = 0;
4603 target_ulong msr;
4604 target_ulong ccr;
4605
4606 int i;
4607
4608 if (!sig) {
4609 save_r2 = env->gpr[2];
4610 }
4611
4612 /* Restore general registers. */
4613 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004614 __get_user(env->gpr[i], &frame->mc_gregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004615 }
Riku Voipioc650c002014-04-23 13:53:45 +03004616 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4617 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4618 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4619 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4620 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004621
4622 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4623 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4624 }
4625
4626 if (!sig) {
4627 env->gpr[2] = save_r2;
4628 }
4629 /* Restore MSR. */
Riku Voipioc650c002014-04-23 13:53:45 +03004630 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004631
4632 /* If doing signal return, restore the previous little-endian mode. */
4633 if (sig)
4634 env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
4635
4636 /* Restore Altivec registers if necessary. */
4637 if (env->insns_flags & PPC_ALTIVEC) {
4638 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004639 ppc_avr_t *avr = &env->avr[i];
4640 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
Nathan Froydbcd49332009-05-12 19:13:18 -07004641
Riku Voipioc650c002014-04-23 13:53:45 +03004642 __get_user(avr->u64[0], &vreg->u64[0]);
4643 __get_user(avr->u64[1], &vreg->u64[1]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004644 }
4645 /* Set MSR_VEC in the saved MSR value to indicate that
4646 frame->mc_vregs contains valid data. */
Riku Voipioc650c002014-04-23 13:53:45 +03004647 __get_user(env->spr[SPR_VRSAVE],
4648 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
Nathan Froydbcd49332009-05-12 19:13:18 -07004649 }
4650
4651 /* Restore floating point registers. */
4652 if (env->insns_flags & PPC_FLOAT) {
4653 uint64_t fpscr;
4654 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004655 __get_user(env->fpr[i], &frame->mc_fregs[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004656 }
Riku Voipioc650c002014-04-23 13:53:45 +03004657 __get_user(fpscr, &frame->mc_fregs[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004658 env->fpscr = (uint32_t) fpscr;
4659 }
4660
4661 /* Save SPE registers. The kernel only saves the high half. */
4662 if (env->insns_flags & PPC_SPE) {
4663#if defined(TARGET_PPC64)
4664 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4665 uint32_t hi;
4666
Riku Voipioc650c002014-04-23 13:53:45 +03004667 __get_user(hi, &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004668 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4669 }
4670#else
4671 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
Riku Voipioc650c002014-04-23 13:53:45 +03004672 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004673 }
4674#endif
Riku Voipioc650c002014-04-23 13:53:45 +03004675 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004676 }
Nathan Froydbcd49332009-05-12 19:13:18 -07004677}
4678
4679static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01004680 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004681{
4682 struct target_sigframe *frame;
4683 struct target_sigcontext *sc;
4684 target_ulong frame_addr, newsp;
4685 int err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004686#if defined(TARGET_PPC64)
4687 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4688#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004689
4690 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01004691 trace_user_setup_frame(env, frame_addr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004692 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4693 goto sigsegv;
4694 sc = &frame->sctx;
4695
Riku Voipio1d8b5122014-04-23 10:26:05 +03004696 __put_user(ka->_sa_handler, &sc->handler);
4697 __put_user(set->sig[0], &sc->oldmask);
Tom Musta61e75fe2014-06-30 08:13:38 -05004698#if TARGET_ABI_BITS == 64
Riku Voipio1d8b5122014-04-23 10:26:05 +03004699 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004700#else
Riku Voipio1d8b5122014-04-23 10:26:05 +03004701 __put_user(set->sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004702#endif
Riku Voipio1d8b5122014-04-23 10:26:05 +03004703 __put_user(h2g(&frame->mctx), &sc->regs);
4704 __put_user(sig, &sc->signal);
Nathan Froydbcd49332009-05-12 19:13:18 -07004705
4706 /* Save user regs. */
Tom Musta76781082014-06-30 08:13:37 -05004707 save_user_regs(env, &frame->mctx);
4708
4709 /* Construct the trampoline code on the stack. */
4710 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
Nathan Froydbcd49332009-05-12 19:13:18 -07004711
4712 /* The kernel checks for the presence of a VDSO here. We don't
4713 emulate a vdso, so use a sigreturn system call. */
4714 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4715
4716 /* Turn off all fp exceptions. */
4717 env->fpscr = 0;
4718
4719 /* Create a stack frame for the caller of the handler. */
4720 newsp = frame_addr - SIGNAL_FRAMESIZE;
Samuel Seaybeb526b2013-01-02 10:53:46 +00004721 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004722
4723 if (err)
4724 goto sigsegv;
4725
4726 /* Set up registers for signal handler. */
4727 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004728 env->gpr[3] = sig;
Samuel Seay61993a62013-01-04 14:35:48 +00004729 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
Tom Musta8d6ab332014-06-30 08:13:39 -05004730
4731#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004732 if (get_ppc64_abi(image) < 2) {
4733 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4734 struct target_func_ptr *handler =
4735 (struct target_func_ptr *)g2h(ka->_sa_handler);
4736 env->nip = tswapl(handler->entry);
4737 env->gpr[2] = tswapl(handler->toc);
4738 } else {
4739 /* ELFv2 PPC64 function pointers are entry points, but R12
4740 * must also be set */
4741 env->nip = tswapl((target_ulong) ka->_sa_handler);
4742 env->gpr[12] = env->nip;
4743 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004744#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004745 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004746#endif
4747
Nathan Froydbcd49332009-05-12 19:13:18 -07004748 /* Signal handlers are entered in big-endian mode. */
4749 env->msr &= ~MSR_LE;
4750
4751 unlock_user_struct(frame, frame_addr, 1);
4752 return;
4753
4754sigsegv:
4755 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004756 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004757}
4758
4759static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05004760 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01004761 target_sigset_t *set, CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004762{
4763 struct target_rt_sigframe *rt_sf;
Tom Musta61e75fe2014-06-30 08:13:38 -05004764 uint32_t *trampptr = 0;
4765 struct target_mcontext *mctx = 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004766 target_ulong rt_sf_addr, newsp = 0;
4767 int i, err = 0;
Tom Musta14585582014-06-30 08:13:42 -05004768#if defined(TARGET_PPC64)
4769 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4770#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004771
4772 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4773 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4774 goto sigsegv;
4775
Peter Maydellf6c7a052015-01-08 12:19:48 +00004776 tswap_siginfo(&rt_sf->info, info);
Nathan Froydbcd49332009-05-12 19:13:18 -07004777
Riku Voipio1d8b5122014-04-23 10:26:05 +03004778 __put_user(0, &rt_sf->uc.tuc_flags);
4779 __put_user(0, &rt_sf->uc.tuc_link);
4780 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4781 &rt_sf->uc.tuc_stack.ss_sp);
4782 __put_user(sas_ss_flags(env->gpr[1]),
4783 &rt_sf->uc.tuc_stack.ss_flags);
4784 __put_user(target_sigaltstack_used.ss_size,
4785 &rt_sf->uc.tuc_stack.ss_size);
Tom Musta61e75fe2014-06-30 08:13:38 -05004786#if !defined(TARGET_PPC64)
Riku Voipio1d8b5122014-04-23 10:26:05 +03004787 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4788 &rt_sf->uc.tuc_regs);
Tom Musta61e75fe2014-06-30 08:13:38 -05004789#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004790 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03004791 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004792 }
4793
Tom Musta61e75fe2014-06-30 08:13:38 -05004794#if defined(TARGET_PPC64)
4795 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
4796 trampptr = &rt_sf->trampoline[0];
4797#else
4798 mctx = &rt_sf->uc.tuc_mcontext;
4799 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
4800#endif
4801
4802 save_user_regs(env, mctx);
4803 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004804
4805 /* The kernel checks for the presence of a VDSO here. We don't
4806 emulate a vdso, so use a sigreturn system call. */
Tom Musta61e75fe2014-06-30 08:13:38 -05004807 env->lr = (target_ulong) h2g(trampptr);
Nathan Froydbcd49332009-05-12 19:13:18 -07004808
4809 /* Turn off all fp exceptions. */
4810 env->fpscr = 0;
4811
4812 /* Create a stack frame for the caller of the handler. */
4813 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
Tom Mustafbdc2002014-06-30 08:13:36 -05004814 err |= put_user(env->gpr[1], newsp, target_ulong);
Nathan Froydbcd49332009-05-12 19:13:18 -07004815
4816 if (err)
4817 goto sigsegv;
4818
4819 /* Set up registers for signal handler. */
4820 env->gpr[1] = newsp;
Peter Maydellb6e2c932015-01-08 12:19:43 +00004821 env->gpr[3] = (target_ulong) sig;
Nathan Froydbcd49332009-05-12 19:13:18 -07004822 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4823 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4824 env->gpr[6] = (target_ulong) h2g(rt_sf);
Tom Musta8d6ab332014-06-30 08:13:39 -05004825
4826#if defined(TARGET_PPC64)
Tom Musta14585582014-06-30 08:13:42 -05004827 if (get_ppc64_abi(image) < 2) {
4828 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4829 struct target_func_ptr *handler =
4830 (struct target_func_ptr *)g2h(ka->_sa_handler);
4831 env->nip = tswapl(handler->entry);
4832 env->gpr[2] = tswapl(handler->toc);
4833 } else {
4834 /* ELFv2 PPC64 function pointers are entry points, but R12
4835 * must also be set */
4836 env->nip = tswapl((target_ulong) ka->_sa_handler);
4837 env->gpr[12] = env->nip;
4838 }
Tom Musta8d6ab332014-06-30 08:13:39 -05004839#else
Nathan Froydbcd49332009-05-12 19:13:18 -07004840 env->nip = (target_ulong) ka->_sa_handler;
Tom Musta8d6ab332014-06-30 08:13:39 -05004841#endif
4842
Nathan Froydbcd49332009-05-12 19:13:18 -07004843 /* Signal handlers are entered in big-endian mode. */
4844 env->msr &= ~MSR_LE;
4845
4846 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4847 return;
4848
4849sigsegv:
4850 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004851 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004852
4853}
4854
Andreas Färber05390242012-02-25 03:37:53 +01004855long do_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004856{
4857 struct target_sigcontext *sc = NULL;
4858 struct target_mcontext *sr = NULL;
Peter Maydellb04636f2013-07-29 12:00:31 +01004859 target_ulong sr_addr = 0, sc_addr;
Nathan Froydbcd49332009-05-12 19:13:18 -07004860 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004861 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004862
4863 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4864 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4865 goto sigsegv;
4866
4867#if defined(TARGET_PPC64)
Tom Musta61e75fe2014-06-30 08:13:38 -05004868 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
Nathan Froydbcd49332009-05-12 19:13:18 -07004869#else
Riku Voipiof5f601a2014-04-23 13:00:17 +03004870 __get_user(set.sig[0], &sc->oldmask);
4871 __get_user(set.sig[1], &sc->_unused[3]);
Nathan Froydbcd49332009-05-12 19:13:18 -07004872#endif
4873 target_to_host_sigset_internal(&blocked, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004874 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
Nathan Froydbcd49332009-05-12 19:13:18 -07004875
Riku Voipiof5f601a2014-04-23 13:00:17 +03004876 __get_user(sr_addr, &sc->regs);
Nathan Froydbcd49332009-05-12 19:13:18 -07004877 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4878 goto sigsegv;
Riku Voipioc650c002014-04-23 13:53:45 +03004879 restore_user_regs(env, sr, 1);
Nathan Froydbcd49332009-05-12 19:13:18 -07004880
4881 unlock_user_struct(sr, sr_addr, 1);
4882 unlock_user_struct(sc, sc_addr, 1);
4883 return -TARGET_QEMU_ESIGRETURN;
4884
4885sigsegv:
4886 unlock_user_struct(sr, sr_addr, 1);
4887 unlock_user_struct(sc, sc_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004888 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004889 return 0;
4890}
4891
4892/* See arch/powerpc/kernel/signal_32.c. */
Andreas Färber05390242012-02-25 03:37:53 +01004893static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
Nathan Froydbcd49332009-05-12 19:13:18 -07004894{
4895 struct target_mcontext *mcp;
4896 target_ulong mcp_addr;
4897 sigset_t blocked;
Anthony Liguoric227f092009-10-01 16:12:16 -05004898 target_sigset_t set;
Nathan Froydbcd49332009-05-12 19:13:18 -07004899
Aurelien Jarno60e99242010-03-29 02:12:51 +02004900 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
Nathan Froydbcd49332009-05-12 19:13:18 -07004901 sizeof (set)))
4902 return 1;
4903
Tom Musta19774ec2014-06-30 08:13:40 -05004904#if defined(TARGET_PPC64)
4905 mcp_addr = h2g(ucp) +
4906 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
4907#else
Riku Voipio9e918dc2014-04-23 14:05:09 +03004908 __get_user(mcp_addr, &ucp->tuc_regs);
Tom Musta19774ec2014-06-30 08:13:40 -05004909#endif
Nathan Froydbcd49332009-05-12 19:13:18 -07004910
4911 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4912 return 1;
4913
4914 target_to_host_sigset_internal(&blocked, &set);
Alex Barcelo1c275922014-03-14 14:36:55 +00004915 do_sigprocmask(SIG_SETMASK, &blocked, NULL);
Riku Voipioc650c002014-04-23 13:53:45 +03004916 restore_user_regs(env, mcp, sig);
Nathan Froydbcd49332009-05-12 19:13:18 -07004917
4918 unlock_user_struct(mcp, mcp_addr, 1);
4919 return 0;
Nathan Froydbcd49332009-05-12 19:13:18 -07004920}
4921
Andreas Färber05390242012-02-25 03:37:53 +01004922long do_rt_sigreturn(CPUPPCState *env)
Nathan Froydbcd49332009-05-12 19:13:18 -07004923{
4924 struct target_rt_sigframe *rt_sf = NULL;
4925 target_ulong rt_sf_addr;
4926
4927 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4928 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4929 goto sigsegv;
4930
4931 if (do_setcontext(&rt_sf->uc, env, 1))
4932 goto sigsegv;
4933
4934 do_sigaltstack(rt_sf_addr
Aurelien Jarno60e99242010-03-29 02:12:51 +02004935 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
Nathan Froydbcd49332009-05-12 19:13:18 -07004936 0, env->gpr[1]);
4937
4938 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4939 return -TARGET_QEMU_ESIGRETURN;
4940
4941sigsegv:
4942 unlock_user_struct(rt_sf, rt_sf_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02004943 force_sig(TARGET_SIGSEGV);
Nathan Froydbcd49332009-05-12 19:13:18 -07004944 return 0;
4945}
4946
Laurent Vivier492a8742009-08-03 16:12:17 +02004947#elif defined(TARGET_M68K)
4948
4949struct target_sigcontext {
4950 abi_ulong sc_mask;
4951 abi_ulong sc_usp;
4952 abi_ulong sc_d0;
4953 abi_ulong sc_d1;
4954 abi_ulong sc_a0;
4955 abi_ulong sc_a1;
4956 unsigned short sc_sr;
4957 abi_ulong sc_pc;
4958};
4959
4960struct target_sigframe
4961{
4962 abi_ulong pretcode;
4963 int sig;
4964 int code;
4965 abi_ulong psc;
4966 char retcode[8];
4967 abi_ulong extramask[TARGET_NSIG_WORDS-1];
4968 struct target_sigcontext sc;
4969};
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01004970
Anthony Liguoric227f092009-10-01 16:12:16 -05004971typedef int target_greg_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004972#define TARGET_NGREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -05004973typedef target_greg_t target_gregset_t[TARGET_NGREG];
Laurent Vivier71811552009-08-03 16:12:18 +02004974
4975typedef struct target_fpregset {
4976 int f_fpcntl[3];
4977 int f_fpregs[8*3];
Anthony Liguoric227f092009-10-01 16:12:16 -05004978} target_fpregset_t;
Laurent Vivier71811552009-08-03 16:12:18 +02004979
4980struct target_mcontext {
4981 int version;
Anthony Liguoric227f092009-10-01 16:12:16 -05004982 target_gregset_t gregs;
4983 target_fpregset_t fpregs;
Laurent Vivier71811552009-08-03 16:12:18 +02004984};
4985
4986#define TARGET_MCONTEXT_VERSION 2
4987
4988struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02004989 abi_ulong tuc_flags;
4990 abi_ulong tuc_link;
4991 target_stack_t tuc_stack;
4992 struct target_mcontext tuc_mcontext;
4993 abi_long tuc_filler[80];
4994 target_sigset_t tuc_sigmask;
Laurent Vivier71811552009-08-03 16:12:18 +02004995};
4996
4997struct target_rt_sigframe
4998{
4999 abi_ulong pretcode;
5000 int sig;
5001 abi_ulong pinfo;
5002 abi_ulong puc;
5003 char retcode[8];
5004 struct target_siginfo info;
5005 struct target_ucontext uc;
5006};
Laurent Vivier492a8742009-08-03 16:12:17 +02005007
Riku Voipio41ecc722014-04-23 11:01:00 +03005008static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005009 abi_ulong mask)
Laurent Vivier492a8742009-08-03 16:12:17 +02005010{
Riku Voipio1d8b5122014-04-23 10:26:05 +03005011 __put_user(mask, &sc->sc_mask);
5012 __put_user(env->aregs[7], &sc->sc_usp);
5013 __put_user(env->dregs[0], &sc->sc_d0);
5014 __put_user(env->dregs[1], &sc->sc_d1);
5015 __put_user(env->aregs[0], &sc->sc_a0);
5016 __put_user(env->aregs[1], &sc->sc_a1);
5017 __put_user(env->sr, &sc->sc_sr);
5018 __put_user(env->pc, &sc->sc_pc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005019}
5020
Riku Voipio016d2e12014-04-23 11:19:48 +03005021static void
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005022restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
Laurent Vivier492a8742009-08-03 16:12:17 +02005023{
Laurent Vivier492a8742009-08-03 16:12:17 +02005024 int temp;
5025
Riku Voipio1d8b5122014-04-23 10:26:05 +03005026 __get_user(env->aregs[7], &sc->sc_usp);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005027 __get_user(env->dregs[0], &sc->sc_d0);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005028 __get_user(env->dregs[1], &sc->sc_d1);
5029 __get_user(env->aregs[0], &sc->sc_a0);
5030 __get_user(env->aregs[1], &sc->sc_a1);
5031 __get_user(env->pc, &sc->sc_pc);
5032 __get_user(temp, &sc->sc_sr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005033 env->sr = (env->sr & 0xff00) | (temp & 0xff);
Laurent Vivier492a8742009-08-03 16:12:17 +02005034}
5035
5036/*
5037 * Determine which stack to use..
5038 */
5039static inline abi_ulong
Andreas Färber05390242012-02-25 03:37:53 +01005040get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5041 size_t frame_size)
Laurent Vivier492a8742009-08-03 16:12:17 +02005042{
5043 unsigned long sp;
5044
5045 sp = regs->aregs[7];
5046
5047 /* This is the X/Open sanctioned signal stack switching. */
5048 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5049 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5050 }
5051
5052 return ((sp - frame_size) & -8UL);
5053}
5054
5055static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005056 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005057{
5058 struct target_sigframe *frame;
5059 abi_ulong frame_addr;
5060 abi_ulong retcode_addr;
5061 abi_ulong sc_addr;
Laurent Vivier492a8742009-08-03 16:12:17 +02005062 int i;
5063
5064 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005065 trace_user_setup_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005066 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5067 goto give_sigsegv;
5068 }
Laurent Vivier492a8742009-08-03 16:12:17 +02005069
Riku Voipio1d8b5122014-04-23 10:26:05 +03005070 __put_user(sig, &frame->sig);
Laurent Vivier492a8742009-08-03 16:12:17 +02005071
5072 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005073 __put_user(sc_addr, &frame->psc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005074
Riku Voipio41ecc722014-04-23 11:01:00 +03005075 setup_sigcontext(&frame->sc, env, set->sig[0]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005076
5077 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005078 __put_user(set->sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005079 }
5080
5081 /* Set up to return from userspace. */
5082
5083 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005084 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier492a8742009-08-03 16:12:17 +02005085
5086 /* moveq #,d0; trap #0 */
5087
Riku Voipio1d8b5122014-04-23 10:26:05 +03005088 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005089 (uint32_t *)(frame->retcode));
Laurent Vivier492a8742009-08-03 16:12:17 +02005090
Laurent Vivier492a8742009-08-03 16:12:17 +02005091 /* Set up to return from userspace */
5092
5093 env->aregs[7] = frame_addr;
5094 env->pc = ka->_sa_handler;
5095
5096 unlock_user_struct(frame, frame_addr, 1);
5097 return;
5098
5099give_sigsegv:
Riku Voipio66393fb2009-12-04 15:16:32 +02005100 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005101}
5102
Laurent Vivier71811552009-08-03 16:12:18 +02005103static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
Andreas Färber05390242012-02-25 03:37:53 +01005104 CPUM68KState *env)
Laurent Vivier71811552009-08-03 16:12:18 +02005105{
Aurelien Jarno60e99242010-03-29 02:12:51 +02005106 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005107
Riku Voipio1d8b5122014-04-23 10:26:05 +03005108 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5109 __put_user(env->dregs[0], &gregs[0]);
5110 __put_user(env->dregs[1], &gregs[1]);
5111 __put_user(env->dregs[2], &gregs[2]);
5112 __put_user(env->dregs[3], &gregs[3]);
5113 __put_user(env->dregs[4], &gregs[4]);
5114 __put_user(env->dregs[5], &gregs[5]);
5115 __put_user(env->dregs[6], &gregs[6]);
5116 __put_user(env->dregs[7], &gregs[7]);
5117 __put_user(env->aregs[0], &gregs[8]);
5118 __put_user(env->aregs[1], &gregs[9]);
5119 __put_user(env->aregs[2], &gregs[10]);
5120 __put_user(env->aregs[3], &gregs[11]);
5121 __put_user(env->aregs[4], &gregs[12]);
5122 __put_user(env->aregs[5], &gregs[13]);
5123 __put_user(env->aregs[6], &gregs[14]);
5124 __put_user(env->aregs[7], &gregs[15]);
5125 __put_user(env->pc, &gregs[16]);
5126 __put_user(env->sr, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005127
Riku Voipio1d8b5122014-04-23 10:26:05 +03005128 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005129}
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005130
Andreas Färber05390242012-02-25 03:37:53 +01005131static inline int target_rt_restore_ucontext(CPUM68KState *env,
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005132 struct target_ucontext *uc)
Laurent Vivier71811552009-08-03 16:12:18 +02005133{
5134 int temp;
Aurelien Jarno60e99242010-03-29 02:12:51 +02005135 target_greg_t *gregs = uc->tuc_mcontext.gregs;
Laurent Vivier71811552009-08-03 16:12:18 +02005136
Riku Voipio1d8b5122014-04-23 10:26:05 +03005137 __get_user(temp, &uc->tuc_mcontext.version);
Laurent Vivier71811552009-08-03 16:12:18 +02005138 if (temp != TARGET_MCONTEXT_VERSION)
5139 goto badframe;
5140
5141 /* restore passed registers */
Riku Voipio1d8b5122014-04-23 10:26:05 +03005142 __get_user(env->dregs[0], &gregs[0]);
5143 __get_user(env->dregs[1], &gregs[1]);
5144 __get_user(env->dregs[2], &gregs[2]);
5145 __get_user(env->dregs[3], &gregs[3]);
5146 __get_user(env->dregs[4], &gregs[4]);
5147 __get_user(env->dregs[5], &gregs[5]);
5148 __get_user(env->dregs[6], &gregs[6]);
5149 __get_user(env->dregs[7], &gregs[7]);
5150 __get_user(env->aregs[0], &gregs[8]);
5151 __get_user(env->aregs[1], &gregs[9]);
5152 __get_user(env->aregs[2], &gregs[10]);
5153 __get_user(env->aregs[3], &gregs[11]);
5154 __get_user(env->aregs[4], &gregs[12]);
5155 __get_user(env->aregs[5], &gregs[13]);
5156 __get_user(env->aregs[6], &gregs[14]);
5157 __get_user(env->aregs[7], &gregs[15]);
5158 __get_user(env->pc, &gregs[16]);
5159 __get_user(temp, &gregs[17]);
Laurent Vivier71811552009-08-03 16:12:18 +02005160 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5161
Riku Voipio1d8b5122014-04-23 10:26:05 +03005162 return 0;
Laurent Vivier71811552009-08-03 16:12:18 +02005163
5164badframe:
5165 return 1;
5166}
5167
Laurent Vivier492a8742009-08-03 16:12:17 +02005168static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005169 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005170 target_sigset_t *set, CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005171{
Laurent Vivier71811552009-08-03 16:12:18 +02005172 struct target_rt_sigframe *frame;
5173 abi_ulong frame_addr;
5174 abi_ulong retcode_addr;
5175 abi_ulong info_addr;
5176 abi_ulong uc_addr;
5177 int err = 0;
5178 int i;
5179
5180 frame_addr = get_sigframe(ka, env, sizeof *frame);
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005181 trace_user_setup_rt_frame(env, frame_addr);
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005182 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5183 goto give_sigsegv;
5184 }
Laurent Vivier71811552009-08-03 16:12:18 +02005185
Riku Voipio1d8b5122014-04-23 10:26:05 +03005186 __put_user(sig, &frame->sig);
Laurent Vivier71811552009-08-03 16:12:18 +02005187
5188 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005189 __put_user(info_addr, &frame->pinfo);
Laurent Vivier71811552009-08-03 16:12:18 +02005190
5191 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005192 __put_user(uc_addr, &frame->puc);
Laurent Vivier71811552009-08-03 16:12:18 +02005193
Peter Maydellf6c7a052015-01-08 12:19:48 +00005194 tswap_siginfo(&frame->info, info);
Laurent Vivier71811552009-08-03 16:12:18 +02005195
5196 /* Create the ucontext */
5197
Riku Voipio1d8b5122014-04-23 10:26:05 +03005198 __put_user(0, &frame->uc.tuc_flags);
5199 __put_user(0, &frame->uc.tuc_link);
5200 __put_user(target_sigaltstack_used.ss_sp,
5201 &frame->uc.tuc_stack.ss_sp);
5202 __put_user(sas_ss_flags(env->aregs[7]),
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005203 &frame->uc.tuc_stack.ss_flags);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005204 __put_user(target_sigaltstack_used.ss_size,
5205 &frame->uc.tuc_stack.ss_size);
Laurent Vivier71811552009-08-03 16:12:18 +02005206 err |= target_rt_setup_ucontext(&frame->uc, env);
5207
5208 if (err)
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005209 goto give_sigsegv;
Laurent Vivier71811552009-08-03 16:12:18 +02005210
5211 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
Riku Voipio0188fad2014-04-23 13:34:15 +03005212 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Laurent Vivier71811552009-08-03 16:12:18 +02005213 }
5214
5215 /* Set up to return from userspace. */
5216
5217 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
Riku Voipio1d8b5122014-04-23 10:26:05 +03005218 __put_user(retcode_addr, &frame->pretcode);
Laurent Vivier71811552009-08-03 16:12:18 +02005219
5220 /* moveq #,d0; notb d0; trap #0 */
5221
Riku Voipio1d8b5122014-04-23 10:26:05 +03005222 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
Peter Maydell1669add2014-12-22 17:47:00 +00005223 (uint32_t *)(frame->retcode + 0));
5224 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
Laurent Vivier71811552009-08-03 16:12:18 +02005225
5226 if (err)
5227 goto give_sigsegv;
5228
5229 /* Set up to return from userspace */
5230
5231 env->aregs[7] = frame_addr;
5232 env->pc = ka->_sa_handler;
5233
5234 unlock_user_struct(frame, frame_addr, 1);
5235 return;
5236
5237give_sigsegv:
5238 unlock_user_struct(frame, frame_addr, 1);
Riku Voipio66393fb2009-12-04 15:16:32 +02005239 force_sig(TARGET_SIGSEGV);
Laurent Vivier492a8742009-08-03 16:12:17 +02005240}
5241
Andreas Färber05390242012-02-25 03:37:53 +01005242long do_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005243{
5244 struct target_sigframe *frame;
5245 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005246 target_sigset_t target_set;
Laurent Vivier492a8742009-08-03 16:12:17 +02005247 sigset_t set;
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005248 int i;
Laurent Vivier492a8742009-08-03 16:12:17 +02005249
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005250 trace_user_do_sigreturn(env, frame_addr);
Laurent Vivier492a8742009-08-03 16:12:17 +02005251 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5252 goto badframe;
5253
5254 /* set blocked signals */
5255
Riku Voipiof5f601a2014-04-23 13:00:17 +03005256 __get_user(target_set.sig[0], &frame->sc.sc_mask);
Laurent Vivier492a8742009-08-03 16:12:17 +02005257
5258 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
Riku Voipiof5f601a2014-04-23 13:00:17 +03005259 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
Laurent Vivier492a8742009-08-03 16:12:17 +02005260 }
5261
5262 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005263 do_sigprocmask(SIG_SETMASK, &set, NULL);
Laurent Vivier492a8742009-08-03 16:12:17 +02005264
5265 /* restore registers */
5266
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005267 restore_sigcontext(env, &frame->sc);
Laurent Vivier492a8742009-08-03 16:12:17 +02005268
5269 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005270 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier492a8742009-08-03 16:12:17 +02005271
5272badframe:
Laurent Vivier492a8742009-08-03 16:12:17 +02005273 force_sig(TARGET_SIGSEGV);
5274 return 0;
5275}
5276
Andreas Färber05390242012-02-25 03:37:53 +01005277long do_rt_sigreturn(CPUM68KState *env)
Laurent Vivier492a8742009-08-03 16:12:17 +02005278{
Laurent Vivier71811552009-08-03 16:12:18 +02005279 struct target_rt_sigframe *frame;
5280 abi_ulong frame_addr = env->aregs[7] - 4;
Anthony Liguoric227f092009-10-01 16:12:16 -05005281 target_sigset_t target_set;
Laurent Vivier71811552009-08-03 16:12:18 +02005282 sigset_t set;
Laurent Vivier71811552009-08-03 16:12:18 +02005283
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005284 trace_user_do_rt_sigreturn(env, frame_addr);
Laurent Vivier71811552009-08-03 16:12:18 +02005285 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5286 goto badframe;
5287
5288 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005289 do_sigprocmask(SIG_SETMASK, &set, NULL);
Laurent Vivier71811552009-08-03 16:12:18 +02005290
5291 /* restore registers */
5292
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005293 if (target_rt_restore_ucontext(env, &frame->uc))
Laurent Vivier71811552009-08-03 16:12:18 +02005294 goto badframe;
5295
5296 if (do_sigaltstack(frame_addr +
Aurelien Jarno60e99242010-03-29 02:12:51 +02005297 offsetof(struct target_rt_sigframe, uc.tuc_stack),
Laurent Vivier71811552009-08-03 16:12:18 +02005298 0, get_sp_from_cpustate(env)) == -EFAULT)
5299 goto badframe;
5300
5301 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin7ccb84a2016-05-12 18:47:39 +01005302 return -TARGET_QEMU_ESIGRETURN;
Laurent Vivier71811552009-08-03 16:12:18 +02005303
5304badframe:
5305 unlock_user_struct(frame, frame_addr, 0);
5306 force_sig(TARGET_SIGSEGV);
5307 return 0;
Laurent Vivier492a8742009-08-03 16:12:17 +02005308}
5309
Richard Henderson6049f4f2009-12-27 18:30:03 -08005310#elif defined(TARGET_ALPHA)
5311
5312struct target_sigcontext {
5313 abi_long sc_onstack;
5314 abi_long sc_mask;
5315 abi_long sc_pc;
5316 abi_long sc_ps;
5317 abi_long sc_regs[32];
5318 abi_long sc_ownedfp;
5319 abi_long sc_fpregs[32];
5320 abi_ulong sc_fpcr;
5321 abi_ulong sc_fp_control;
5322 abi_ulong sc_reserved1;
5323 abi_ulong sc_reserved2;
5324 abi_ulong sc_ssize;
5325 abi_ulong sc_sbase;
5326 abi_ulong sc_traparg_a0;
5327 abi_ulong sc_traparg_a1;
5328 abi_ulong sc_traparg_a2;
5329 abi_ulong sc_fp_trap_pc;
5330 abi_ulong sc_fp_trigger_sum;
5331 abi_ulong sc_fp_trigger_inst;
5332};
5333
5334struct target_ucontext {
Aurelien Jarno60e99242010-03-29 02:12:51 +02005335 abi_ulong tuc_flags;
5336 abi_ulong tuc_link;
5337 abi_ulong tuc_osf_sigmask;
5338 target_stack_t tuc_stack;
5339 struct target_sigcontext tuc_mcontext;
5340 target_sigset_t tuc_sigmask;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005341};
5342
5343struct target_sigframe {
5344 struct target_sigcontext sc;
5345 unsigned int retcode[3];
5346};
5347
5348struct target_rt_sigframe {
5349 target_siginfo_t info;
5350 struct target_ucontext uc;
5351 unsigned int retcode[3];
5352};
5353
5354#define INSN_MOV_R30_R16 0x47fe0410
5355#define INSN_LDI_R0 0x201f0000
5356#define INSN_CALLSYS 0x00000083
5357
Riku Voipio41ecc722014-04-23 11:01:00 +03005358static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005359 abi_ulong frame_addr, target_sigset_t *set)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005360{
Riku Voipio41ecc722014-04-23 11:01:00 +03005361 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005362
Riku Voipio1d8b5122014-04-23 10:26:05 +03005363 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5364 __put_user(set->sig[0], &sc->sc_mask);
5365 __put_user(env->pc, &sc->sc_pc);
5366 __put_user(8, &sc->sc_ps);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005367
5368 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005369 __put_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005370 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005371 __put_user(0, &sc->sc_regs[31]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005372
5373 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005374 __put_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005375 }
Riku Voipio1d8b5122014-04-23 10:26:05 +03005376 __put_user(0, &sc->sc_fpregs[31]);
5377 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005378
Riku Voipio1d8b5122014-04-23 10:26:05 +03005379 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5380 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5381 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
Richard Henderson6049f4f2009-12-27 18:30:03 -08005382}
5383
Riku Voipio016d2e12014-04-23 11:19:48 +03005384static void restore_sigcontext(CPUAlphaState *env,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005385 struct target_sigcontext *sc)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005386{
5387 uint64_t fpcr;
Riku Voipio016d2e12014-04-23 11:19:48 +03005388 int i;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005389
Riku Voipio1d8b5122014-04-23 10:26:05 +03005390 __get_user(env->pc, &sc->sc_pc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005391
5392 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005393 __get_user(env->ir[i], &sc->sc_regs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005394 }
5395 for (i = 0; i < 31; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005396 __get_user(env->fir[i], &sc->sc_fpregs[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005397 }
5398
Riku Voipio1d8b5122014-04-23 10:26:05 +03005399 __get_user(fpcr, &sc->sc_fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005400 cpu_alpha_store_fpcr(env, fpcr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005401}
5402
5403static inline abi_ulong get_sigframe(struct target_sigaction *sa,
Andreas Färber05390242012-02-25 03:37:53 +01005404 CPUAlphaState *env,
5405 unsigned long framesize)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005406{
5407 abi_ulong sp = env->ir[IR_SP];
5408
5409 /* This is the X/Open sanctioned signal stack switching. */
5410 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5411 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5412 }
5413 return (sp - framesize) & -32;
5414}
5415
5416static void setup_frame(int sig, struct target_sigaction *ka,
Andreas Färber05390242012-02-25 03:37:53 +01005417 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005418{
5419 abi_ulong frame_addr, r26;
5420 struct target_sigframe *frame;
5421 int err = 0;
5422
5423 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005424 trace_user_setup_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005425 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5426 goto give_sigsegv;
5427 }
5428
Riku Voipio41ecc722014-04-23 11:01:00 +03005429 setup_sigcontext(&frame->sc, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005430
5431 if (ka->sa_restorer) {
5432 r26 = ka->sa_restorer;
5433 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005434 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5435 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5436 &frame->retcode[1]);
5437 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005438 /* imb() */
5439 r26 = frame_addr;
5440 }
5441
5442 unlock_user_struct(frame, frame_addr, 1);
5443
5444 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005445give_sigsegv:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005446 if (sig == TARGET_SIGSEGV) {
5447 ka->_sa_handler = TARGET_SIG_DFL;
5448 }
5449 force_sig(TARGET_SIGSEGV);
5450 }
5451
5452 env->ir[IR_RA] = r26;
5453 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5454 env->ir[IR_A0] = sig;
5455 env->ir[IR_A1] = 0;
5456 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5457 env->ir[IR_SP] = frame_addr;
5458}
5459
5460static void setup_rt_frame(int sig, struct target_sigaction *ka,
5461 target_siginfo_t *info,
Andreas Färber05390242012-02-25 03:37:53 +01005462 target_sigset_t *set, CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005463{
5464 abi_ulong frame_addr, r26;
5465 struct target_rt_sigframe *frame;
5466 int i, err = 0;
5467
5468 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005469 trace_user_setup_rt_frame(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005470 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5471 goto give_sigsegv;
5472 }
5473
Peter Maydellf6c7a052015-01-08 12:19:48 +00005474 tswap_siginfo(&frame->info, info);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005475
Riku Voipio1d8b5122014-04-23 10:26:05 +03005476 __put_user(0, &frame->uc.tuc_flags);
5477 __put_user(0, &frame->uc.tuc_link);
5478 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5479 __put_user(target_sigaltstack_used.ss_sp,
5480 &frame->uc.tuc_stack.ss_sp);
5481 __put_user(sas_ss_flags(env->ir[IR_SP]),
5482 &frame->uc.tuc_stack.ss_flags);
5483 __put_user(target_sigaltstack_used.ss_size,
5484 &frame->uc.tuc_stack.ss_size);
Riku Voipio41ecc722014-04-23 11:01:00 +03005485 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005486 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005487 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005488 }
5489
5490 if (ka->sa_restorer) {
5491 r26 = ka->sa_restorer;
5492 } else {
Riku Voipio1d8b5122014-04-23 10:26:05 +03005493 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5494 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5495 &frame->retcode[1]);
5496 __put_user(INSN_CALLSYS, &frame->retcode[2]);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005497 /* imb(); */
5498 r26 = frame_addr;
5499 }
5500
5501 if (err) {
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005502give_sigsegv:
5503 if (sig == TARGET_SIGSEGV) {
Richard Henderson6049f4f2009-12-27 18:30:03 -08005504 ka->_sa_handler = TARGET_SIG_DFL;
5505 }
5506 force_sig(TARGET_SIGSEGV);
5507 }
5508
5509 env->ir[IR_RA] = r26;
5510 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5511 env->ir[IR_A0] = sig;
5512 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5513 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5514 env->ir[IR_SP] = frame_addr;
5515}
5516
Andreas Färber05390242012-02-25 03:37:53 +01005517long do_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005518{
5519 struct target_sigcontext *sc;
5520 abi_ulong sc_addr = env->ir[IR_A0];
5521 target_sigset_t target_set;
5522 sigset_t set;
5523
5524 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5525 goto badframe;
5526 }
5527
5528 target_sigemptyset(&target_set);
Riku Voipiof5f601a2014-04-23 13:00:17 +03005529 __get_user(target_set.sig[0], &sc->sc_mask);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005530
5531 target_to_host_sigset_internal(&set, &target_set);
Alex Barcelo1c275922014-03-14 14:36:55 +00005532 do_sigprocmask(SIG_SETMASK, &set, NULL);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005533
Riku Voipio016d2e12014-04-23 11:19:48 +03005534 restore_sigcontext(env, sc);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005535 unlock_user_struct(sc, sc_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005536 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005537
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005538badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005539 force_sig(TARGET_SIGSEGV);
5540}
5541
Andreas Färber05390242012-02-25 03:37:53 +01005542long do_rt_sigreturn(CPUAlphaState *env)
Richard Henderson6049f4f2009-12-27 18:30:03 -08005543{
5544 abi_ulong frame_addr = env->ir[IR_A0];
5545 struct target_rt_sigframe *frame;
5546 sigset_t set;
5547
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005548 trace_user_do_rt_sigreturn(env, frame_addr);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005549 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5550 goto badframe;
5551 }
Aurelien Jarno60e99242010-03-29 02:12:51 +02005552 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
Alex Barcelo1c275922014-03-14 14:36:55 +00005553 do_sigprocmask(SIG_SETMASK, &set, NULL);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005554
Riku Voipio016d2e12014-04-23 11:19:48 +03005555 restore_sigcontext(env, &frame->uc.tuc_mcontext);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005556 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
Aurelien Jarno60e99242010-03-29 02:12:51 +02005557 uc.tuc_stack),
Richard Henderson6049f4f2009-12-27 18:30:03 -08005558 0, env->ir[IR_SP]) == -EFAULT) {
5559 goto badframe;
5560 }
5561
5562 unlock_user_struct(frame, frame_addr, 0);
Timothy E Baldwin338c8582016-05-12 18:47:36 +01005563 return -TARGET_QEMU_ESIGRETURN;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005564
5565
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005566badframe:
Richard Henderson6049f4f2009-12-27 18:30:03 -08005567 unlock_user_struct(frame, frame_addr, 0);
5568 force_sig(TARGET_SIGSEGV);
5569}
5570
Chen Gangbf0f60a2015-09-27 08:10:18 +08005571#elif defined(TARGET_TILEGX)
5572
5573struct target_sigcontext {
5574 union {
5575 /* General-purpose registers. */
5576 abi_ulong gregs[56];
5577 struct {
5578 abi_ulong __gregs[53];
5579 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
5580 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
5581 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
5582 };
5583 };
5584 abi_ulong pc; /* Program counter. */
5585 abi_ulong ics; /* In Interrupt Critical Section? */
5586 abi_ulong faultnum; /* Fault number. */
5587 abi_ulong pad[5];
5588};
5589
5590struct target_ucontext {
5591 abi_ulong tuc_flags;
5592 abi_ulong tuc_link;
5593 target_stack_t tuc_stack;
5594 struct target_sigcontext tuc_mcontext;
5595 target_sigset_t tuc_sigmask; /* mask last for extensibility */
5596};
5597
5598struct target_rt_sigframe {
5599 unsigned char save_area[16]; /* caller save area */
5600 struct target_siginfo info;
5601 struct target_ucontext uc;
Chen Gangf1d9d102016-03-29 21:53:49 +08005602 abi_ulong retcode[2];
Chen Gangbf0f60a2015-09-27 08:10:18 +08005603};
5604
Chen Gangf1d9d102016-03-29 21:53:49 +08005605#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
5606#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
5607
5608
Chen Gangbf0f60a2015-09-27 08:10:18 +08005609static void setup_sigcontext(struct target_sigcontext *sc,
5610 CPUArchState *env, int signo)
5611{
5612 int i;
5613
5614 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5615 __put_user(env->regs[i], &sc->gregs[i]);
5616 }
5617
5618 __put_user(env->pc, &sc->pc);
5619 __put_user(0, &sc->ics);
5620 __put_user(signo, &sc->faultnum);
5621}
5622
5623static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
5624{
5625 int i;
5626
5627 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5628 __get_user(env->regs[i], &sc->gregs[i]);
5629 }
5630
5631 __get_user(env->pc, &sc->pc);
5632}
5633
5634static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
5635 size_t frame_size)
5636{
5637 unsigned long sp = env->regs[TILEGX_R_SP];
5638
5639 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
5640 return -1UL;
5641 }
5642
5643 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
5644 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5645 }
5646
5647 sp -= frame_size;
5648 sp &= -16UL;
5649 return sp;
5650}
5651
5652static void setup_rt_frame(int sig, struct target_sigaction *ka,
5653 target_siginfo_t *info,
5654 target_sigset_t *set, CPUArchState *env)
5655{
5656 abi_ulong frame_addr;
5657 struct target_rt_sigframe *frame;
5658 unsigned long restorer;
5659
5660 frame_addr = get_sigframe(ka, env, sizeof(*frame));
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005661 trace_user_setup_rt_frame(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005662 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5663 goto give_sigsegv;
5664 }
5665
5666 /* Always write at least the signal number for the stack backtracer. */
5667 if (ka->sa_flags & TARGET_SA_SIGINFO) {
5668 /* At sigreturn time, restore the callee-save registers too. */
5669 tswap_siginfo(&frame->info, info);
5670 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
5671 } else {
5672 __put_user(info->si_signo, &frame->info.si_signo);
5673 }
5674
5675 /* Create the ucontext. */
5676 __put_user(0, &frame->uc.tuc_flags);
5677 __put_user(0, &frame->uc.tuc_link);
5678 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
5679 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
5680 &frame->uc.tuc_stack.ss_flags);
5681 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5682 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
5683
Chen Gangbf0f60a2015-09-27 08:10:18 +08005684 if (ka->sa_flags & TARGET_SA_RESTORER) {
Chen Gangf1d9d102016-03-29 21:53:49 +08005685 restorer = (unsigned long) ka->sa_restorer;
5686 } else {
5687 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
5688 __put_user(INSN_SWINT1, &frame->retcode[1]);
5689 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005690 }
5691 env->pc = (unsigned long) ka->_sa_handler;
5692 env->regs[TILEGX_R_SP] = (unsigned long) frame;
5693 env->regs[TILEGX_R_LR] = restorer;
5694 env->regs[0] = (unsigned long) sig;
5695 env->regs[1] = (unsigned long) &frame->info;
5696 env->regs[2] = (unsigned long) &frame->uc;
5697 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
5698
5699 unlock_user_struct(frame, frame_addr, 1);
5700 return;
5701
5702give_sigsegv:
5703 if (sig == TARGET_SIGSEGV) {
5704 ka->_sa_handler = TARGET_SIG_DFL;
5705 }
5706 force_sig(TARGET_SIGSEGV /* , current */);
5707}
5708
5709long do_rt_sigreturn(CPUTLGState *env)
5710{
5711 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
5712 struct target_rt_sigframe *frame;
5713 sigset_t set;
5714
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005715 trace_user_do_rt_sigreturn(env, frame_addr);
Chen Gangbf0f60a2015-09-27 08:10:18 +08005716 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5717 goto badframe;
5718 }
5719 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
5720 do_sigprocmask(SIG_SETMASK, &set, NULL);
5721
5722 restore_sigcontext(env, &frame->uc.tuc_mcontext);
5723 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
5724 uc.tuc_stack),
5725 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
5726 goto badframe;
5727 }
5728
5729 unlock_user_struct(frame, frame_addr, 0);
Peter Maydella9175162016-05-12 18:47:42 +01005730 return -TARGET_QEMU_ESIGRETURN;
Chen Gangbf0f60a2015-09-27 08:10:18 +08005731
5732
5733 badframe:
5734 unlock_user_struct(frame, frame_addr, 0);
5735 force_sig(TARGET_SIGSEGV);
5736}
5737
bellardb346ff42003-06-15 20:05:50 +00005738#else
5739
pbrook624f7972008-05-31 16:11:38 +00005740static void setup_frame(int sig, struct target_sigaction *ka,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005741 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005742{
5743 fprintf(stderr, "setup_frame: not implemented\n");
5744}
5745
pbrook624f7972008-05-31 16:11:38 +00005746static void setup_rt_frame(int sig, struct target_sigaction *ka,
Anthony Liguoric227f092009-10-01 16:12:16 -05005747 target_siginfo_t *info,
Timothy E Baldwinda7c8642016-05-12 18:47:27 +01005748 target_sigset_t *set, CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005749{
5750 fprintf(stderr, "setup_rt_frame: not implemented\n");
5751}
5752
Andreas Färber9349b4f2012-03-14 01:38:32 +01005753long do_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005754{
5755 fprintf(stderr, "do_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005756 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005757}
5758
Andreas Färber9349b4f2012-03-14 01:38:32 +01005759long do_rt_sigreturn(CPUArchState *env)
bellardb346ff42003-06-15 20:05:50 +00005760{
5761 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
bellardf8b0aa22007-11-11 23:03:42 +00005762 return -TARGET_ENOSYS;
bellardb346ff42003-06-15 20:05:50 +00005763}
5764
bellard66fb9762003-03-23 01:06:05 +00005765#endif
5766
Andreas Färber9349b4f2012-03-14 01:38:32 +01005767void process_pending_signals(CPUArchState *cpu_env)
bellard66fb9762003-03-23 01:06:05 +00005768{
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005769 CPUState *cpu = ENV_GET_CPU(cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005770 int sig;
blueswir1992f48a2007-10-14 16:27:31 +00005771 abi_ulong handler;
bellard9de5e442003-03-23 16:49:39 +00005772 sigset_t set, old_set;
Anthony Liguoric227f092009-10-01 16:12:16 -05005773 target_sigset_t target_old_set;
pbrook624f7972008-05-31 16:11:38 +00005774 struct emulated_sigtable *k;
5775 struct target_sigaction *sa;
bellard66fb9762003-03-23 01:06:05 +00005776 struct sigqueue *q;
Andreas Färber0429a972013-08-26 18:14:44 +02005777 TaskState *ts = cpu->opaque;
ths3b46e622007-09-17 08:09:54 +00005778
pbrook624f7972008-05-31 16:11:38 +00005779 if (!ts->signal_pending)
bellard31e31b82003-02-18 22:55:36 +00005780 return;
5781
pbrook624f7972008-05-31 16:11:38 +00005782 /* FIXME: This is not threadsafe. */
5783 k = ts->sigtab;
bellard66fb9762003-03-23 01:06:05 +00005784 for(sig = 1; sig <= TARGET_NSIG; sig++) {
5785 if (k->pending)
bellard31e31b82003-02-18 22:55:36 +00005786 goto handle_signal;
bellard66fb9762003-03-23 01:06:05 +00005787 k++;
bellard31e31b82003-02-18 22:55:36 +00005788 }
5789 /* if no signal is pending, just return */
pbrook624f7972008-05-31 16:11:38 +00005790 ts->signal_pending = 0;
bellard31e31b82003-02-18 22:55:36 +00005791 return;
bellard66fb9762003-03-23 01:06:05 +00005792
bellard31e31b82003-02-18 22:55:36 +00005793 handle_signal:
Paolo Bonzinic8ee0a42015-11-13 13:52:21 +01005794 trace_user_handle_signal(cpu_env, sig);
bellard66fb9762003-03-23 01:06:05 +00005795 /* dequeue signal */
5796 q = k->first;
5797 k->first = q->next;
5798 if (!k->first)
5799 k->pending = 0;
ths3b46e622007-09-17 08:09:54 +00005800
Andreas Färberdb6b81d2013-06-27 19:49:31 +02005801 sig = gdb_handlesig(cpu, sig);
bellard1fddef42005-04-17 19:16:13 +00005802 if (!sig) {
aurel32ca587a82008-12-18 22:44:13 +00005803 sa = NULL;
5804 handler = TARGET_SIG_IGN;
5805 } else {
5806 sa = &sigact_table[sig - 1];
5807 handler = sa->_sa_handler;
bellard1fddef42005-04-17 19:16:13 +00005808 }
bellard66fb9762003-03-23 01:06:05 +00005809
Peter Maydella7ec0f92014-03-14 14:36:56 +00005810 if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
5811 /* Guest has blocked SIGSEGV but we got one anyway. Assume this
5812 * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
5813 * because it got a real MMU fault), and treat as if default handler.
5814 */
5815 handler = TARGET_SIG_DFL;
5816 }
5817
bellard66fb9762003-03-23 01:06:05 +00005818 if (handler == TARGET_SIG_DFL) {
aurel32ca587a82008-12-18 22:44:13 +00005819 /* default handler : ignore some signal. The other are job control or fatal */
5820 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5821 kill(getpid(),SIGSTOP);
5822 } else if (sig != TARGET_SIGCHLD &&
5823 sig != TARGET_SIGURG &&
5824 sig != TARGET_SIGWINCH &&
5825 sig != TARGET_SIGCONT) {
bellard66fb9762003-03-23 01:06:05 +00005826 force_sig(sig);
5827 }
5828 } else if (handler == TARGET_SIG_IGN) {
5829 /* ignore sig */
5830 } else if (handler == TARGET_SIG_ERR) {
5831 force_sig(sig);
5832 } else {
bellard9de5e442003-03-23 16:49:39 +00005833 /* compute the blocked signals during the handler execution */
pbrook624f7972008-05-31 16:11:38 +00005834 target_to_host_sigset(&set, &sa->sa_mask);
bellard9de5e442003-03-23 16:49:39 +00005835 /* SA_NODEFER indicates that the current signal should not be
5836 blocked during the handler */
pbrook624f7972008-05-31 16:11:38 +00005837 if (!(sa->sa_flags & TARGET_SA_NODEFER))
bellard9de5e442003-03-23 16:49:39 +00005838 sigaddset(&set, target_to_host_signal(sig));
ths3b46e622007-09-17 08:09:54 +00005839
bellard9de5e442003-03-23 16:49:39 +00005840 /* block signals in the handler using Linux */
Alex Barcelo1c275922014-03-14 14:36:55 +00005841 do_sigprocmask(SIG_BLOCK, &set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005842 /* save the previous blocked signal state to restore it at the
5843 end of the signal execution (see do_sigreturn) */
bellard92319442004-06-19 16:58:13 +00005844 host_to_target_sigset_internal(&target_old_set, &old_set);
bellard9de5e442003-03-23 16:49:39 +00005845
bellardbc8a22c2003-03-30 21:02:40 +00005846 /* if the CPU is in VM86 mode, we restore the 32 bit values */
j_mayer84409dd2007-04-06 08:56:50 +00005847#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bellardbc8a22c2003-03-30 21:02:40 +00005848 {
5849 CPUX86State *env = cpu_env;
5850 if (env->eflags & VM_MASK)
5851 save_v86_state(env);
5852 }
5853#endif
bellard9de5e442003-03-23 16:49:39 +00005854 /* prepare the stack frame of the virtual CPU */
Chen Gangd0924a22015-09-12 23:32:30 +08005855#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
Chen Gangbf0f60a2015-09-27 08:10:18 +08005856 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX)
Richard Hendersonff970902013-02-10 10:30:42 -08005857 /* These targets do not have traditional signals. */
5858 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
5859#else
pbrook624f7972008-05-31 16:11:38 +00005860 if (sa->sa_flags & TARGET_SA_SIGINFO)
5861 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
bellard66fb9762003-03-23 01:06:05 +00005862 else
pbrook624f7972008-05-31 16:11:38 +00005863 setup_frame(sig, sa, &target_old_set, cpu_env);
Richard Hendersonff970902013-02-10 10:30:42 -08005864#endif
pbrook624f7972008-05-31 16:11:38 +00005865 if (sa->sa_flags & TARGET_SA_RESETHAND)
5866 sa->_sa_handler = TARGET_SIG_DFL;
bellard31e31b82003-02-18 22:55:36 +00005867 }
bellard66fb9762003-03-23 01:06:05 +00005868 if (q != &k->info)
pbrook624f7972008-05-31 16:11:38 +00005869 free_sigqueue(cpu_env, q);
bellard31e31b82003-02-18 22:55:36 +00005870}