]> Git Repo - qemu.git/blame - linux-user/signal.c
target-mips: Implement FCR31's R/W bitmask and related functionalities
[qemu.git] / linux-user / signal.c
CommitLineData
31e31b8a 1/*
66fb9763 2 * Emulation of Linux signals
5fafdf24 3 *
31e31b8a
FB
4 * 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
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31e31b8a 18 */
d39594e9 19#include "qemu/osdep.h"
a70dadc7 20#include "qemu/bitops.h"
31e31b8a 21#include <sys/ucontext.h>
edf8e2af 22#include <sys/resource.h>
31e31b8a 23
3ef693a0 24#include "qemu.h"
7d99a001 25#include "qemu-common.h"
992f48a0 26#include "target_signal.h"
c8ee0a44 27#include "trace.h"
66fb9763 28
249c4c32 29static struct target_sigaltstack target_sigaltstack_used = {
a04e134a
TS
30 .ss_sp = 0,
31 .ss_size = 0,
32 .ss_flags = TARGET_SS_DISABLE,
33};
34
624f7979 35static struct target_sigaction sigact_table[TARGET_NSIG];
31e31b8a 36
5fafdf24 37static void host_signal_handler(int host_signum, siginfo_t *info,
66fb9763
FB
38 void *puc);
39
3ca05588 40static uint8_t host_to_target_signal_table[_NSIG] = {
9e5f5284
FB
41 [SIGHUP] = TARGET_SIGHUP,
42 [SIGINT] = TARGET_SIGINT,
43 [SIGQUIT] = TARGET_SIGQUIT,
44 [SIGILL] = TARGET_SIGILL,
45 [SIGTRAP] = TARGET_SIGTRAP,
46 [SIGABRT] = TARGET_SIGABRT,
01e3b763 47/* [SIGIOT] = TARGET_SIGIOT,*/
9e5f5284
FB
48 [SIGBUS] = TARGET_SIGBUS,
49 [SIGFPE] = TARGET_SIGFPE,
50 [SIGKILL] = TARGET_SIGKILL,
51 [SIGUSR1] = TARGET_SIGUSR1,
52 [SIGSEGV] = TARGET_SIGSEGV,
53 [SIGUSR2] = TARGET_SIGUSR2,
54 [SIGPIPE] = TARGET_SIGPIPE,
55 [SIGALRM] = TARGET_SIGALRM,
56 [SIGTERM] = TARGET_SIGTERM,
57#ifdef SIGSTKFLT
58 [SIGSTKFLT] = TARGET_SIGSTKFLT,
59#endif
60 [SIGCHLD] = TARGET_SIGCHLD,
61 [SIGCONT] = TARGET_SIGCONT,
62 [SIGSTOP] = TARGET_SIGSTOP,
63 [SIGTSTP] = TARGET_SIGTSTP,
64 [SIGTTIN] = TARGET_SIGTTIN,
65 [SIGTTOU] = TARGET_SIGTTOU,
66 [SIGURG] = TARGET_SIGURG,
67 [SIGXCPU] = TARGET_SIGXCPU,
68 [SIGXFSZ] = TARGET_SIGXFSZ,
69 [SIGVTALRM] = TARGET_SIGVTALRM,
70 [SIGPROF] = TARGET_SIGPROF,
71 [SIGWINCH] = TARGET_SIGWINCH,
72 [SIGIO] = TARGET_SIGIO,
73 [SIGPWR] = TARGET_SIGPWR,
74 [SIGSYS] = TARGET_SIGSYS,
75 /* next signals stay the same */
624f7979 76 /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
b4916d7b 77 host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
624f7979
PB
78 To fix this properly we need to do manual signal delivery multiplexed
79 over a single host signal. */
80 [__SIGRTMIN] = __SIGRTMAX,
81 [__SIGRTMAX] = __SIGRTMIN,
9e5f5284 82};
3ca05588 83static uint8_t target_to_host_signal_table[_NSIG];
9e5f5284 84
a04e134a
TS
85static inline int on_sig_stack(unsigned long sp)
86{
87 return (sp - target_sigaltstack_used.ss_sp
88 < target_sigaltstack_used.ss_size);
89}
90
91static inline int sas_ss_flags(unsigned long sp)
92{
93 return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
94 : on_sig_stack(sp) ? SS_ONSTACK : 0);
95}
96
1d9d8b55 97int host_to_target_signal(int sig)
31e31b8a 98{
167c50d8 99 if (sig < 0 || sig >= _NSIG)
4cb05961 100 return sig;
9e5f5284 101 return host_to_target_signal_table[sig];
31e31b8a
FB
102}
103
4cb05961 104int target_to_host_signal(int sig)
31e31b8a 105{
167c50d8 106 if (sig < 0 || sig >= _NSIG)
4cb05961 107 return sig;
9e5f5284 108 return target_to_host_signal_table[sig];
31e31b8a
FB
109}
110
c227f099 111static inline void target_sigemptyset(target_sigset_t *set)
f5545b5c
PB
112{
113 memset(set, 0, sizeof(*set));
114}
115
c227f099 116static inline void target_sigaddset(target_sigset_t *set, int signum)
f5545b5c
PB
117{
118 signum--;
119 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
120 set->sig[signum / TARGET_NSIG_BPW] |= mask;
121}
122
c227f099 123static inline int target_sigismember(const target_sigset_t *set, int signum)
f5545b5c
PB
124{
125 signum--;
126 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
128}
129
c227f099 130static void host_to_target_sigset_internal(target_sigset_t *d,
9231944d 131 const sigset_t *s)
66fb9763
FB
132{
133 int i;
f5545b5c
PB
134 target_sigemptyset(d);
135 for (i = 1; i <= TARGET_NSIG; i++) {
136 if (sigismember(s, i)) {
137 target_sigaddset(d, host_to_target_signal(i));
138 }
66fb9763
FB
139 }
140}
141
c227f099 142void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
9231944d 143{
c227f099 144 target_sigset_t d1;
9231944d
FB
145 int i;
146
147 host_to_target_sigset_internal(&d1, s);
148 for(i = 0;i < TARGET_NSIG_WORDS; i++)
cbb21eed 149 d->sig[i] = tswapal(d1.sig[i]);
9231944d
FB
150}
151
8fcd3692 152static void target_to_host_sigset_internal(sigset_t *d,
c227f099 153 const target_sigset_t *s)
66fb9763
FB
154{
155 int i;
f5545b5c
PB
156 sigemptyset(d);
157 for (i = 1; i <= TARGET_NSIG; i++) {
158 if (target_sigismember(s, i)) {
159 sigaddset(d, target_to_host_signal(i));
160 }
da7c8647 161 }
66fb9763
FB
162}
163
c227f099 164void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
9231944d 165{
c227f099 166 target_sigset_t s1;
9231944d
FB
167 int i;
168
169 for(i = 0;i < TARGET_NSIG_WORDS; i++)
cbb21eed 170 s1.sig[i] = tswapal(s->sig[i]);
9231944d
FB
171 target_to_host_sigset_internal(d, &s1);
172}
3b46e624 173
992f48a0 174void host_to_target_old_sigset(abi_ulong *old_sigset,
66fb9763
FB
175 const sigset_t *sigset)
176{
c227f099 177 target_sigset_t d;
9e5f5284
FB
178 host_to_target_sigset(&d, sigset);
179 *old_sigset = d.sig[0];
66fb9763
FB
180}
181
5fafdf24 182void target_to_host_old_sigset(sigset_t *sigset,
992f48a0 183 const abi_ulong *old_sigset)
66fb9763 184{
c227f099 185 target_sigset_t d;
9e5f5284
FB
186 int i;
187
188 d.sig[0] = *old_sigset;
189 for(i = 1;i < TARGET_NSIG_WORDS; i++)
190 d.sig[i] = 0;
191 target_to_host_sigset(sigset, &d);
66fb9763
FB
192}
193
3d3efba0
PM
194int block_signals(void)
195{
196 TaskState *ts = (TaskState *)thread_cpu->opaque;
197 sigset_t set;
3d3efba0
PM
198
199 /* It's OK to block everything including SIGSEGV, because we won't
200 * run any further guest code before unblocking signals in
201 * process_pending_signals().
202 */
203 sigfillset(&set);
204 sigprocmask(SIG_SETMASK, &set, 0);
205
9be38598 206 return atomic_xchg(&ts->signal_pending, 1);
3d3efba0
PM
207}
208
1c275925
AB
209/* Wrapper for sigprocmask function
210 * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
3d3efba0
PM
211 * are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
212 * a signal was already pending and the syscall must be restarted, or
213 * 0 on success.
214 * If set is NULL, this is guaranteed not to fail.
1c275925
AB
215 */
216int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
217{
3d3efba0
PM
218 TaskState *ts = (TaskState *)thread_cpu->opaque;
219
220 if (oldset) {
221 *oldset = ts->signal_mask;
222 }
a7ec0f98
PM
223
224 if (set) {
3d3efba0 225 int i;
a7ec0f98 226
3d3efba0
PM
227 if (block_signals()) {
228 return -TARGET_ERESTARTSYS;
229 }
a7ec0f98
PM
230
231 switch (how) {
232 case SIG_BLOCK:
3d3efba0 233 sigorset(&ts->signal_mask, &ts->signal_mask, set);
a7ec0f98
PM
234 break;
235 case SIG_UNBLOCK:
3d3efba0
PM
236 for (i = 1; i <= NSIG; ++i) {
237 if (sigismember(set, i)) {
238 sigdelset(&ts->signal_mask, i);
239 }
a7ec0f98
PM
240 }
241 break;
242 case SIG_SETMASK:
3d3efba0 243 ts->signal_mask = *set;
a7ec0f98
PM
244 break;
245 default:
246 g_assert_not_reached();
247 }
a7ec0f98 248
3d3efba0
PM
249 /* Silently ignore attempts to change blocking status of KILL or STOP */
250 sigdelset(&ts->signal_mask, SIGKILL);
251 sigdelset(&ts->signal_mask, SIGSTOP);
a7ec0f98 252 }
3d3efba0 253 return 0;
1c275925
AB
254}
255
9eede5b6
PM
256#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
257 !defined(TARGET_X86_64)
3d3efba0
PM
258/* Just set the guest's signal mask to the specified value; the
259 * caller is assumed to have called block_signals() already.
260 */
9eede5b6
PM
261static void set_sigmask(const sigset_t *set)
262{
3d3efba0
PM
263 TaskState *ts = (TaskState *)thread_cpu->opaque;
264
265 ts->signal_mask = *set;
9eede5b6
PM
266}
267#endif
268
9de5e440
FB
269/* siginfo conversion */
270
c227f099 271static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
9de5e440 272 const siginfo_t *info)
66fb9763 273{
a05c6409 274 int sig = host_to_target_signal(info->si_signo);
a70dadc7
PM
275 int si_code = info->si_code;
276 int si_type;
9de5e440
FB
277 tinfo->si_signo = sig;
278 tinfo->si_errno = 0;
afd7cd92 279 tinfo->si_code = info->si_code;
a05c6409 280
a70dadc7
PM
281 /* This is awkward, because we have to use a combination of
282 * the si_code and si_signo to figure out which of the union's
283 * members are valid. (Within the host kernel it is always possible
284 * to tell, but the kernel carefully avoids giving userspace the
285 * high 16 bits of si_code, so we don't have the information to
286 * do this the easy way...) We therefore make our best guess,
287 * bearing in mind that a guest can spoof most of the si_codes
288 * via rt_sigqueueinfo() if it likes.
289 *
290 * Once we have made our guess, we record it in the top 16 bits of
291 * the si_code, so that tswap_siginfo() later can use it.
292 * tswap_siginfo() will strip these top bits out before writing
293 * si_code to the guest (sign-extending the lower bits).
294 */
295
296 switch (si_code) {
297 case SI_USER:
298 case SI_TKILL:
299 case SI_KERNEL:
300 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
301 * These are the only unspoofable si_code values.
302 */
303 tinfo->_sifields._kill._pid = info->si_pid;
304 tinfo->_sifields._kill._uid = info->si_uid;
305 si_type = QEMU_SI_KILL;
306 break;
307 default:
308 /* Everything else is spoofable. Make best guess based on signal */
309 switch (sig) {
310 case TARGET_SIGCHLD:
311 tinfo->_sifields._sigchld._pid = info->si_pid;
312 tinfo->_sifields._sigchld._uid = info->si_uid;
313 tinfo->_sifields._sigchld._status
da7c8647 314 = host_to_target_waitstatus(info->si_status);
a70dadc7
PM
315 tinfo->_sifields._sigchld._utime = info->si_utime;
316 tinfo->_sifields._sigchld._stime = info->si_stime;
317 si_type = QEMU_SI_CHLD;
318 break;
319 case TARGET_SIGIO:
320 tinfo->_sifields._sigpoll._band = info->si_band;
321 tinfo->_sifields._sigpoll._fd = info->si_fd;
322 si_type = QEMU_SI_POLL;
323 break;
324 default:
325 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
326 tinfo->_sifields._rt._pid = info->si_pid;
327 tinfo->_sifields._rt._uid = info->si_uid;
328 /* XXX: potential problem if 64 bit */
329 tinfo->_sifields._rt._sigval.sival_ptr
da7c8647 330 = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
a70dadc7
PM
331 si_type = QEMU_SI_RT;
332 break;
333 }
334 break;
9de5e440 335 }
a70dadc7
PM
336
337 tinfo->si_code = deposit32(si_code, 16, 16, si_type);
9de5e440
FB
338}
339
c227f099
AL
340static void tswap_siginfo(target_siginfo_t *tinfo,
341 const target_siginfo_t *info)
9de5e440 342{
a70dadc7
PM
343 int si_type = extract32(info->si_code, 16, 16);
344 int si_code = sextract32(info->si_code, 0, 16);
345
346 __put_user(info->si_signo, &tinfo->si_signo);
347 __put_user(info->si_errno, &tinfo->si_errno);
348 __put_user(si_code, &tinfo->si_code);
349
350 /* We can use our internal marker of which fields in the structure
351 * are valid, rather than duplicating the guesswork of
352 * host_to_target_siginfo_noswap() here.
353 */
354 switch (si_type) {
355 case QEMU_SI_KILL:
356 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid);
357 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid);
358 break;
359 case QEMU_SI_TIMER:
360 __put_user(info->_sifields._timer._timer1,
361 &tinfo->_sifields._timer._timer1);
362 __put_user(info->_sifields._timer._timer2,
363 &tinfo->_sifields._timer._timer2);
364 break;
365 case QEMU_SI_POLL:
366 __put_user(info->_sifields._sigpoll._band,
367 &tinfo->_sifields._sigpoll._band);
368 __put_user(info->_sifields._sigpoll._fd,
369 &tinfo->_sifields._sigpoll._fd);
370 break;
371 case QEMU_SI_FAULT:
372 __put_user(info->_sifields._sigfault._addr,
373 &tinfo->_sifields._sigfault._addr);
374 break;
375 case QEMU_SI_CHLD:
376 __put_user(info->_sifields._sigchld._pid,
377 &tinfo->_sifields._sigchld._pid);
378 __put_user(info->_sifields._sigchld._uid,
379 &tinfo->_sifields._sigchld._uid);
380 __put_user(info->_sifields._sigchld._status,
381 &tinfo->_sifields._sigchld._status);
382 __put_user(info->_sifields._sigchld._utime,
383 &tinfo->_sifields._sigchld._utime);
384 __put_user(info->_sifields._sigchld._stime,
385 &tinfo->_sifields._sigchld._stime);
386 break;
387 case QEMU_SI_RT:
388 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid);
389 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid);
390 __put_user(info->_sifields._rt._sigval.sival_ptr,
391 &tinfo->_sifields._rt._sigval.sival_ptr);
392 break;
393 default:
394 g_assert_not_reached();
9de5e440
FB
395 }
396}
397
c227f099 398void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
9de5e440
FB
399{
400 host_to_target_siginfo_noswap(tinfo, info);
401 tswap_siginfo(tinfo, tinfo);
66fb9763
FB
402}
403
9de5e440 404/* XXX: we support only POSIX RT signals are used. */
aa1f17c1 405/* XXX: find a solution for 64 bit (additional malloced data is needed) */
c227f099 406void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
66fb9763 407{
90c0f080
PM
408 /* This conversion is used only for the rt_sigqueueinfo syscall,
409 * and so we know that the _rt fields are the valid ones.
410 */
411 abi_ulong sival_ptr;
412
413 __get_user(info->si_signo, &tinfo->si_signo);
414 __get_user(info->si_errno, &tinfo->si_errno);
415 __get_user(info->si_code, &tinfo->si_code);
416 __get_user(info->si_pid, &tinfo->_sifields._rt._pid);
417 __get_user(info->si_uid, &tinfo->_sifields._rt._uid);
418 __get_user(sival_ptr, &tinfo->_sifields._rt._sigval.sival_ptr);
419 info->si_value.sival_ptr = (void *)(long)sival_ptr;
66fb9763
FB
420}
421
ca587a8e
AJ
422static int fatal_signal (int sig)
423{
424 switch (sig) {
425 case TARGET_SIGCHLD:
426 case TARGET_SIGURG:
427 case TARGET_SIGWINCH:
428 /* Ignored by default. */
429 return 0;
430 case TARGET_SIGCONT:
431 case TARGET_SIGSTOP:
432 case TARGET_SIGTSTP:
433 case TARGET_SIGTTIN:
434 case TARGET_SIGTTOU:
435 /* Job control signals. */
436 return 0;
437 default:
438 return 1;
439 }
440}
441
edf8e2af
MW
442/* returns 1 if given signal should dump core if not handled */
443static int core_dump_signal(int sig)
444{
445 switch (sig) {
446 case TARGET_SIGABRT:
447 case TARGET_SIGFPE:
448 case TARGET_SIGILL:
449 case TARGET_SIGQUIT:
450 case TARGET_SIGSEGV:
451 case TARGET_SIGTRAP:
452 case TARGET_SIGBUS:
453 return (1);
454 default:
455 return (0);
456 }
457}
458
31e31b8a
FB
459void signal_init(void)
460{
3d3efba0 461 TaskState *ts = (TaskState *)thread_cpu->opaque;
31e31b8a 462 struct sigaction act;
624f7979 463 struct sigaction oact;
9e5f5284 464 int i, j;
624f7979 465 int host_sig;
31e31b8a 466
9e5f5284 467 /* generate signal conversion tables */
3ca05588 468 for(i = 1; i < _NSIG; i++) {
9e5f5284
FB
469 if (host_to_target_signal_table[i] == 0)
470 host_to_target_signal_table[i] = i;
471 }
3ca05588 472 for(i = 1; i < _NSIG; i++) {
9e5f5284
FB
473 j = host_to_target_signal_table[i];
474 target_to_host_signal_table[j] = i;
475 }
3b46e624 476
3d3efba0
PM
477 /* Set the signal mask from the host mask. */
478 sigprocmask(0, 0, &ts->signal_mask);
479
9de5e440
FB
480 /* set all host signal handlers. ALL signals are blocked during
481 the handlers to serialize them. */
624f7979
PB
482 memset(sigact_table, 0, sizeof(sigact_table));
483
9de5e440 484 sigfillset(&act.sa_mask);
31e31b8a
FB
485 act.sa_flags = SA_SIGINFO;
486 act.sa_sigaction = host_signal_handler;
624f7979
PB
487 for(i = 1; i <= TARGET_NSIG; i++) {
488 host_sig = target_to_host_signal(i);
489 sigaction(host_sig, NULL, &oact);
490 if (oact.sa_sigaction == (void *)SIG_IGN) {
491 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
492 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
493 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
494 }
495 /* If there's already a handler installed then something has
496 gone horribly wrong, so don't even try to handle that case. */
ca587a8e
AJ
497 /* Install some handlers for our own use. We need at least
498 SIGSEGV and SIGBUS, to detect exceptions. We can not just
499 trap all signals because it affects syscall interrupt
500 behavior. But do trap all default-fatal signals. */
501 if (fatal_signal (i))
624f7979 502 sigaction(host_sig, &act, NULL);
31e31b8a 503 }
66fb9763
FB
504}
505
66fb9763 506
9de5e440 507/* abort execution with signal */
66393fb9 508static void QEMU_NORETURN force_sig(int target_sig)
66fb9763 509{
0429a971
AF
510 CPUState *cpu = thread_cpu;
511 CPUArchState *env = cpu->env_ptr;
512 TaskState *ts = (TaskState *)cpu->opaque;
edf8e2af 513 int host_sig, core_dumped = 0;
603e4fd7 514 struct sigaction act;
c8ee0a44 515
66393fb9 516 host_sig = target_to_host_signal(target_sig);
c8ee0a44 517 trace_user_force_sig(env, target_sig, host_sig);
a2247f8e 518 gdb_signalled(env, target_sig);
603e4fd7 519
edf8e2af 520 /* dump core if supported by target binary format */
66393fb9 521 if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
edf8e2af
MW
522 stop_all_tasks();
523 core_dumped =
a2247f8e 524 ((*ts->bprm->core_dump)(target_sig, env) == 0);
edf8e2af
MW
525 }
526 if (core_dumped) {
527 /* we already dumped the core of target process, we don't want
528 * a coredump of qemu itself */
529 struct rlimit nodump;
530 getrlimit(RLIMIT_CORE, &nodump);
531 nodump.rlim_cur=0;
532 setrlimit(RLIMIT_CORE, &nodump);
533 (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
66393fb9 534 target_sig, strsignal(host_sig), "core dumped" );
edf8e2af
MW
535 }
536
0c58751c 537 /* The proper exit code for dying from an uncaught signal is
603e4fd7
AJ
538 * -<signal>. The kernel doesn't allow exit() or _exit() to pass
539 * a negative value. To get the proper exit code we need to
540 * actually die from an uncaught signal. Here the default signal
541 * handler is installed, we send ourself a signal and we wait for
542 * it to arrive. */
543 sigfillset(&act.sa_mask);
544 act.sa_handler = SIG_DFL;
3a5d30bf 545 act.sa_flags = 0;
603e4fd7
AJ
546 sigaction(host_sig, &act, NULL);
547
548 /* For some reason raise(host_sig) doesn't send the signal when
549 * statically linked on x86-64. */
550 kill(getpid(), host_sig);
551
552 /* Make sure the signal isn't masked (just reuse the mask inside
553 of act) */
554 sigdelset(&act.sa_mask, host_sig);
555 sigsuspend(&act.sa_mask);
556
557 /* unreachable */
a6c6f76c 558 abort();
66fb9763
FB
559}
560
9de5e440
FB
561/* queue a signal so that it will be send to the virtual CPU as soon
562 as possible */
9349b4f9 563int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
31e31b8a 564{
0429a971
AF
565 CPUState *cpu = ENV_GET_CPU(env);
566 TaskState *ts = cpu->opaque;
66fb9763 567
c8ee0a44 568 trace_user_queue_signal(env, sig);
907f5fdd 569
a70dadc7
PM
570 /* Currently all callers define siginfo structures which
571 * use the _sifields._sigfault union member, so we can
572 * set the type here. If that changes we should push this
573 * out so the si_type is passed in by callers.
574 */
575 info->si_code = deposit32(info->si_code, 16, 16, QEMU_SI_FAULT);
576
655ed67c
TB
577 ts->sync_signal.info = *info;
578 ts->sync_signal.pending = sig;
907f5fdd
TB
579 /* signal that a new signal is pending */
580 atomic_set(&ts->signal_pending, 1);
581 return 1; /* indicates that the signal was queued */
9de5e440
FB
582}
583
4d330cee
TB
584#ifndef HAVE_SAFE_SYSCALL
585static inline void rewind_if_in_safe_syscall(void *puc)
586{
587 /* Default version: never rewind */
588}
589#endif
590
5fafdf24 591static void host_signal_handler(int host_signum, siginfo_t *info,
9de5e440
FB
592 void *puc)
593{
a2247f8e 594 CPUArchState *env = thread_cpu->env_ptr;
655ed67c
TB
595 CPUState *cpu = ENV_GET_CPU(env);
596 TaskState *ts = cpu->opaque;
597
9de5e440 598 int sig;
c227f099 599 target_siginfo_t tinfo;
3d3efba0 600 ucontext_t *uc = puc;
655ed67c 601 struct emulated_sigtable *k;
9de5e440
FB
602
603 /* the CPU emulator uses some host signals to detect exceptions,
eaa449b9 604 we forward to it some signals */
ca587a8e 605 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
eaa449b9 606 && info->si_code > 0) {
b346ff46 607 if (cpu_signal_handler(host_signum, info, puc))
9de5e440
FB
608 return;
609 }
610
611 /* get target signal number */
612 sig = host_to_target_signal(host_signum);
613 if (sig < 1 || sig > TARGET_NSIG)
614 return;
c8ee0a44 615 trace_user_host_signal(env, host_signum, sig);
4d330cee
TB
616
617 rewind_if_in_safe_syscall(puc);
618
9de5e440 619 host_to_target_siginfo_noswap(&tinfo, info);
655ed67c
TB
620 k = &ts->sigtab[sig - 1];
621 k->info = tinfo;
622 k->pending = sig;
623 ts->signal_pending = 1;
624
625 /* Block host signals until target signal handler entered. We
626 * can't block SIGSEGV or SIGBUS while we're executing guest
627 * code in case the guest code provokes one in the window between
628 * now and it getting out to the main loop. Signals will be
629 * unblocked again in process_pending_signals().
630 */
631 sigfillset(&uc->uc_sigmask);
632 sigdelset(&uc->uc_sigmask, SIGSEGV);
633 sigdelset(&uc->uc_sigmask, SIGBUS);
3d3efba0 634
655ed67c
TB
635 /* interrupt the virtual CPU as soon as possible */
636 cpu_exit(thread_cpu);
66fb9763
FB
637}
638
0da46a6e 639/* do_sigaltstack() returns target values and errnos. */
579a97f7
FB
640/* compare linux/kernel/signal.c:do_sigaltstack() */
641abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
a04e134a
TS
642{
643 int ret;
644 struct target_sigaltstack oss;
645
646 /* XXX: test errors */
579a97f7 647 if(uoss_addr)
a04e134a
TS
648 {
649 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
650 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
651 __put_user(sas_ss_flags(sp), &oss.ss_flags);
652 }
653
579a97f7 654 if(uss_addr)
a04e134a 655 {
579a97f7
FB
656 struct target_sigaltstack *uss;
657 struct target_sigaltstack ss;
0903c8be
TM
658 size_t minstacksize = TARGET_MINSIGSTKSZ;
659
660#if defined(TARGET_PPC64)
661 /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
662 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
663 if (get_ppc64_abi(image) > 1) {
664 minstacksize = 4096;
665 }
666#endif
a04e134a 667
0da46a6e 668 ret = -TARGET_EFAULT;
9eeb8306 669 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
a04e134a 670 goto out;
9eeb8306
RV
671 }
672 __get_user(ss.ss_sp, &uss->ss_sp);
673 __get_user(ss.ss_size, &uss->ss_size);
674 __get_user(ss.ss_flags, &uss->ss_flags);
579a97f7 675 unlock_user_struct(uss, uss_addr, 0);
a04e134a 676
0da46a6e 677 ret = -TARGET_EPERM;
a04e134a
TS
678 if (on_sig_stack(sp))
679 goto out;
680
0da46a6e 681 ret = -TARGET_EINVAL;
a04e134a
TS
682 if (ss.ss_flags != TARGET_SS_DISABLE
683 && ss.ss_flags != TARGET_SS_ONSTACK
684 && ss.ss_flags != 0)
685 goto out;
686
687 if (ss.ss_flags == TARGET_SS_DISABLE) {
688 ss.ss_size = 0;
689 ss.ss_sp = 0;
690 } else {
0da46a6e 691 ret = -TARGET_ENOMEM;
0903c8be 692 if (ss.ss_size < minstacksize) {
a04e134a 693 goto out;
0903c8be 694 }
a04e134a
TS
695 }
696
697 target_sigaltstack_used.ss_sp = ss.ss_sp;
698 target_sigaltstack_used.ss_size = ss.ss_size;
699 }
700
579a97f7 701 if (uoss_addr) {
0da46a6e 702 ret = -TARGET_EFAULT;
579a97f7 703 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
a04e134a 704 goto out;
a04e134a
TS
705 }
706
707 ret = 0;
708out:
709 return ret;
710}
711
ef6a778e 712/* do_sigaction() return target values and host errnos */
66fb9763
FB
713int do_sigaction(int sig, const struct target_sigaction *act,
714 struct target_sigaction *oact)
715{
624f7979 716 struct target_sigaction *k;
773b93ee
FB
717 struct sigaction act1;
718 int host_sig;
0da46a6e 719 int ret = 0;
66fb9763 720
ef6a778e
TB
721 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
722 return -TARGET_EINVAL;
723 }
724
725 if (block_signals()) {
726 return -TARGET_ERESTARTSYS;
727 }
728
66fb9763 729 k = &sigact_table[sig - 1];
66fb9763 730 if (oact) {
d2565875
RH
731 __put_user(k->_sa_handler, &oact->_sa_handler);
732 __put_user(k->sa_flags, &oact->sa_flags);
388bb21a 733#if !defined(TARGET_MIPS)
d2565875 734 __put_user(k->sa_restorer, &oact->sa_restorer);
388bb21a 735#endif
d2565875 736 /* Not swapped. */
624f7979 737 oact->sa_mask = k->sa_mask;
66fb9763
FB
738 }
739 if (act) {
624f7979 740 /* FIXME: This is not threadsafe. */
d2565875
RH
741 __get_user(k->_sa_handler, &act->_sa_handler);
742 __get_user(k->sa_flags, &act->sa_flags);
388bb21a 743#if !defined(TARGET_MIPS)
d2565875 744 __get_user(k->sa_restorer, &act->sa_restorer);
388bb21a 745#endif
d2565875 746 /* To be swapped in target_to_host_sigset. */
624f7979 747 k->sa_mask = act->sa_mask;
773b93ee
FB
748
749 /* we update the host linux signal state */
750 host_sig = target_to_host_signal(sig);
751 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
752 sigfillset(&act1.sa_mask);
753 act1.sa_flags = SA_SIGINFO;
624f7979 754 if (k->sa_flags & TARGET_SA_RESTART)
773b93ee
FB
755 act1.sa_flags |= SA_RESTART;
756 /* NOTE: it is important to update the host kernel signal
757 ignore state to avoid getting unexpected interrupted
758 syscalls */
624f7979 759 if (k->_sa_handler == TARGET_SIG_IGN) {
773b93ee 760 act1.sa_sigaction = (void *)SIG_IGN;
624f7979 761 } else if (k->_sa_handler == TARGET_SIG_DFL) {
ca587a8e
AJ
762 if (fatal_signal (sig))
763 act1.sa_sigaction = host_signal_handler;
764 else
765 act1.sa_sigaction = (void *)SIG_DFL;
773b93ee
FB
766 } else {
767 act1.sa_sigaction = host_signal_handler;
768 }
0da46a6e 769 ret = sigaction(host_sig, &act1, NULL);
773b93ee 770 }
66fb9763 771 }
0da46a6e 772 return ret;
66fb9763
FB
773}
774
459a4017 775#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
66fb9763
FB
776
777/* from the Linux kernel */
778
779struct target_fpreg {
da7c8647
TB
780 uint16_t significand[4];
781 uint16_t exponent;
66fb9763
FB
782};
783
784struct target_fpxreg {
da7c8647
TB
785 uint16_t significand[4];
786 uint16_t exponent;
787 uint16_t padding[3];
66fb9763
FB
788};
789
790struct target_xmmreg {
da7c8647 791 abi_ulong element[4];
66fb9763
FB
792};
793
794struct target_fpstate {
da7c8647
TB
795 /* Regular FPU environment */
796 abi_ulong cw;
797 abi_ulong sw;
798 abi_ulong tag;
799 abi_ulong ipoff;
800 abi_ulong cssel;
801 abi_ulong dataoff;
802 abi_ulong datasel;
803 struct target_fpreg _st[8];
804 uint16_t status;
805 uint16_t magic; /* 0xffff = regular FPU data only */
806
807 /* FXSR FPU environment */
808 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
809 abi_ulong mxcsr;
810 abi_ulong reserved;
811 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
812 struct target_xmmreg _xmm[8];
813 abi_ulong padding[56];
66fb9763
FB
814};
815
816#define X86_FXSR_MAGIC 0x0000
817
818struct target_sigcontext {
da7c8647
TB
819 uint16_t gs, __gsh;
820 uint16_t fs, __fsh;
821 uint16_t es, __esh;
822 uint16_t ds, __dsh;
823 abi_ulong edi;
824 abi_ulong esi;
825 abi_ulong ebp;
826 abi_ulong esp;
827 abi_ulong ebx;
828 abi_ulong edx;
829 abi_ulong ecx;
830 abi_ulong eax;
831 abi_ulong trapno;
832 abi_ulong err;
833 abi_ulong eip;
834 uint16_t cs, __csh;
835 abi_ulong eflags;
836 abi_ulong esp_at_signal;
837 uint16_t ss, __ssh;
838 abi_ulong fpstate; /* pointer */
839 abi_ulong oldmask;
840 abi_ulong cr2;
66fb9763
FB
841};
842
66fb9763 843struct target_ucontext {
da7c8647
TB
844 abi_ulong tuc_flags;
845 abi_ulong tuc_link;
846 target_stack_t tuc_stack;
847 struct target_sigcontext tuc_mcontext;
848 target_sigset_t tuc_sigmask; /* mask last for extensibility */
66fb9763
FB
849};
850
851struct sigframe
852{
992f48a0 853 abi_ulong pretcode;
66fb9763
FB
854 int sig;
855 struct target_sigcontext sc;
856 struct target_fpstate fpstate;
992f48a0 857 abi_ulong extramask[TARGET_NSIG_WORDS-1];
66fb9763
FB
858 char retcode[8];
859};
860
861struct rt_sigframe
862{
992f48a0 863 abi_ulong pretcode;
66fb9763 864 int sig;
992f48a0
BS
865 abi_ulong pinfo;
866 abi_ulong puc;
66fb9763
FB
867 struct target_siginfo info;
868 struct target_ucontext uc;
869 struct target_fpstate fpstate;
870 char retcode[8];
871};
872
873/*
874 * Set up a signal frame.
875 */
876
66fb9763 877/* XXX: save x87 state */
41ecc72b
RV
878static void setup_sigcontext(struct target_sigcontext *sc,
879 struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask,
880 abi_ulong fpstate_addr)
66fb9763 881{
27103424 882 CPUState *cs = CPU(x86_env_get_cpu(env));
27103424 883 uint16_t magic;
66fb9763 884
da7c8647 885 /* already locked in setup_frame() */
1d8b512b
RV
886 __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
887 __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
888 __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
889 __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
890 __put_user(env->regs[R_EDI], &sc->edi);
891 __put_user(env->regs[R_ESI], &sc->esi);
892 __put_user(env->regs[R_EBP], &sc->ebp);
893 __put_user(env->regs[R_ESP], &sc->esp);
894 __put_user(env->regs[R_EBX], &sc->ebx);
895 __put_user(env->regs[R_EDX], &sc->edx);
896 __put_user(env->regs[R_ECX], &sc->ecx);
897 __put_user(env->regs[R_EAX], &sc->eax);
898 __put_user(cs->exception_index, &sc->trapno);
899 __put_user(env->error_code, &sc->err);
900 __put_user(env->eip, &sc->eip);
901 __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
902 __put_user(env->eflags, &sc->eflags);
903 __put_user(env->regs[R_ESP], &sc->esp_at_signal);
904 __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
ed2dcdf6 905
da7c8647
TB
906 cpu_x86_fsave(env, fpstate_addr, 1);
907 fpstate->status = fpstate->sw;
908 magic = 0xffff;
1d8b512b
RV
909 __put_user(magic, &fpstate->magic);
910 __put_user(fpstate_addr, &sc->fpstate);
ed2dcdf6 911
da7c8647 912 /* non-iBCS2 extensions.. */
1d8b512b
RV
913 __put_user(mask, &sc->oldmask);
914 __put_user(env->cr[2], &sc->cr2);
31e31b8a
FB
915}
916
66fb9763
FB
917/*
918 * Determine which stack to use..
919 */
31e31b8a 920
579a97f7 921static inline abi_ulong
624f7979 922get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
31e31b8a 923{
da7c8647 924 unsigned long esp;
66fb9763 925
da7c8647
TB
926 /* Default to using normal stack */
927 esp = env->regs[R_ESP];
928 /* This is the X/Open sanctioned signal stack switching. */
929 if (ka->sa_flags & TARGET_SA_ONSTACK) {
930 if (sas_ss_flags(esp) == 0) {
931 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
a04e134a 932 }
da7c8647 933 } else {
66fb9763 934
da7c8647 935 /* This is the legacy signal stack switching. */
a52c757c 936 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
da7c8647
TB
937 !(ka->sa_flags & TARGET_SA_RESTORER) &&
938 ka->sa_restorer) {
624f7979 939 esp = (unsigned long) ka->sa_restorer;
da7c8647
TB
940 }
941 }
942 return (esp - frame_size) & -8ul;
66fb9763
FB
943}
944
579a97f7 945/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
624f7979 946static void setup_frame(int sig, struct target_sigaction *ka,
da7c8647 947 target_sigset_t *set, CPUX86State *env)
66fb9763 948{
da7c8647
TB
949 abi_ulong frame_addr;
950 struct sigframe *frame;
951 int i;
66fb9763 952
da7c8647
TB
953 frame_addr = get_sigframe(ka, env, sizeof(*frame));
954 trace_user_setup_frame(env, frame_addr);
66fb9763 955
da7c8647
TB
956 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
957 goto give_sigsegv;
579a97f7 958
b6e2c935 959 __put_user(sig, &frame->sig);
66fb9763 960
da7c8647
TB
961 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
962 frame_addr + offsetof(struct sigframe, fpstate));
66fb9763 963
7df2fa36
RV
964 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
965 __put_user(set->sig[i], &frame->extramask[i - 1]);
966 }
66fb9763 967
da7c8647
TB
968 /* Set up to return from userspace. If provided, use a stub
969 already in userspace. */
970 if (ka->sa_flags & TARGET_SA_RESTORER) {
1d8b512b 971 __put_user(ka->sa_restorer, &frame->pretcode);
da7c8647
TB
972 } else {
973 uint16_t val16;
974 abi_ulong retcode_addr;
975 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
1d8b512b 976 __put_user(retcode_addr, &frame->pretcode);
da7c8647
TB
977 /* This is popl %eax ; movl $,%eax ; int $0x80 */
978 val16 = 0xb858;
1d8b512b
RV
979 __put_user(val16, (uint16_t *)(frame->retcode+0));
980 __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
da7c8647 981 val16 = 0x80cd;
1d8b512b 982 __put_user(val16, (uint16_t *)(frame->retcode+6));
da7c8647 983 }
66fb9763 984
66fb9763 985
da7c8647
TB
986 /* Set up registers for signal handler */
987 env->regs[R_ESP] = frame_addr;
988 env->eip = ka->_sa_handler;
66fb9763 989
da7c8647
TB
990 cpu_x86_load_seg(env, R_DS, __USER_DS);
991 cpu_x86_load_seg(env, R_ES, __USER_DS);
992 cpu_x86_load_seg(env, R_SS, __USER_DS);
993 cpu_x86_load_seg(env, R_CS, __USER_CS);
994 env->eflags &= ~TF_MASK;
66fb9763 995
da7c8647 996 unlock_user_struct(frame, frame_addr, 1);
579a97f7 997
da7c8647 998 return;
66fb9763
FB
999
1000give_sigsegv:
da7c8647
TB
1001 if (sig == TARGET_SIGSEGV) {
1002 ka->_sa_handler = TARGET_SIG_DFL;
1003 }
1004 force_sig(TARGET_SIGSEGV /* , current */);
66fb9763
FB
1005}
1006
579a97f7 1007/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
624f7979 1008static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 1009 target_siginfo_t *info,
da7c8647 1010 target_sigset_t *set, CPUX86State *env)
66fb9763 1011{
da7c8647
TB
1012 abi_ulong frame_addr, addr;
1013 struct rt_sigframe *frame;
1014 int i;
66fb9763 1015
da7c8647
TB
1016 frame_addr = get_sigframe(ka, env, sizeof(*frame));
1017 trace_user_setup_rt_frame(env, frame_addr);
66fb9763 1018
da7c8647
TB
1019 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1020 goto give_sigsegv;
66fb9763 1021
b6e2c935 1022 __put_user(sig, &frame->sig);
da7c8647 1023 addr = frame_addr + offsetof(struct rt_sigframe, info);
1d8b512b 1024 __put_user(addr, &frame->pinfo);
da7c8647 1025 addr = frame_addr + offsetof(struct rt_sigframe, uc);
1d8b512b 1026 __put_user(addr, &frame->puc);
f6c7a05b 1027 tswap_siginfo(&frame->info, info);
31e31b8a 1028
da7c8647 1029 /* Create the ucontext. */
1d8b512b
RV
1030 __put_user(0, &frame->uc.tuc_flags);
1031 __put_user(0, &frame->uc.tuc_link);
1032 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
1033 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
1034 &frame->uc.tuc_stack.ss_flags);
1035 __put_user(target_sigaltstack_used.ss_size,
1036 &frame->uc.tuc_stack.ss_size);
41ecc72b
RV
1037 setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env,
1038 set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate));
1039
0188fadb
RV
1040 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1041 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1042 }
31e31b8a 1043
da7c8647
TB
1044 /* Set up to return from userspace. If provided, use a stub
1045 already in userspace. */
1046 if (ka->sa_flags & TARGET_SA_RESTORER) {
1d8b512b 1047 __put_user(ka->sa_restorer, &frame->pretcode);
da7c8647
TB
1048 } else {
1049 uint16_t val16;
1050 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
1d8b512b 1051 __put_user(addr, &frame->pretcode);
da7c8647 1052 /* This is movl $,%eax ; int $0x80 */
1d8b512b
RV
1053 __put_user(0xb8, (char *)(frame->retcode+0));
1054 __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
da7c8647 1055 val16 = 0x80cd;
1d8b512b 1056 __put_user(val16, (uint16_t *)(frame->retcode+5));
da7c8647 1057 }
66fb9763 1058
da7c8647
TB
1059 /* Set up registers for signal handler */
1060 env->regs[R_ESP] = frame_addr;
1061 env->eip = ka->_sa_handler;
66fb9763 1062
da7c8647
TB
1063 cpu_x86_load_seg(env, R_DS, __USER_DS);
1064 cpu_x86_load_seg(env, R_ES, __USER_DS);
1065 cpu_x86_load_seg(env, R_SS, __USER_DS);
1066 cpu_x86_load_seg(env, R_CS, __USER_CS);
1067 env->eflags &= ~TF_MASK;
66fb9763 1068
da7c8647 1069 unlock_user_struct(frame, frame_addr, 1);
579a97f7 1070
da7c8647 1071 return;
66fb9763
FB
1072
1073give_sigsegv:
da7c8647
TB
1074 if (sig == TARGET_SIGSEGV) {
1075 ka->_sa_handler = TARGET_SIG_DFL;
1076 }
1077 force_sig(TARGET_SIGSEGV /* , current */);
66fb9763
FB
1078}
1079
1080static int
0284b03b 1081restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
66fb9763 1082{
da7c8647
TB
1083 unsigned int err = 0;
1084 abi_ulong fpstate_addr;
1085 unsigned int tmpflags;
1086
1087 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
1088 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
1089 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
1090 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
1091
1092 env->regs[R_EDI] = tswapl(sc->edi);
1093 env->regs[R_ESI] = tswapl(sc->esi);
1094 env->regs[R_EBP] = tswapl(sc->ebp);
1095 env->regs[R_ESP] = tswapl(sc->esp);
1096 env->regs[R_EBX] = tswapl(sc->ebx);
1097 env->regs[R_EDX] = tswapl(sc->edx);
1098 env->regs[R_ECX] = tswapl(sc->ecx);
0284b03b 1099 env->regs[R_EAX] = tswapl(sc->eax);
da7c8647
TB
1100 env->eip = tswapl(sc->eip);
1101
1102 cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
1103 cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
1104
1105 tmpflags = tswapl(sc->eflags);
1106 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
1107 // regs->orig_eax = -1; /* disable syscall checks */
1108
1109 fpstate_addr = tswapl(sc->fpstate);
1110 if (fpstate_addr != 0) {
1111 if (!access_ok(VERIFY_READ, fpstate_addr,
1112 sizeof(struct target_fpstate)))
1113 goto badframe;
1114 cpu_x86_frstor(env, fpstate_addr, 1);
1115 }
ed2dcdf6 1116
da7c8647 1117 return err;
66fb9763 1118badframe:
da7c8647 1119 return 1;
66fb9763
FB
1120}
1121
1122long do_sigreturn(CPUX86State *env)
1123{
579a97f7
FB
1124 struct sigframe *frame;
1125 abi_ulong frame_addr = env->regs[R_ESP] - 8;
c227f099 1126 target_sigset_t target_set;
66fb9763 1127 sigset_t set;
0284b03b 1128 int i;
66fb9763 1129
c8ee0a44 1130 trace_user_do_sigreturn(env, frame_addr);
579a97f7
FB
1131 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1132 goto badframe;
66fb9763 1133 /* set blocked signals */
f5f601af 1134 __get_user(target_set.sig[0], &frame->sc.oldmask);
9231944d 1135 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
f5f601af 1136 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
9231944d 1137 }
66fb9763 1138
9231944d 1139 target_to_host_sigset_internal(&set, &target_set);
9eede5b6 1140 set_sigmask(&set);
3b46e624 1141
66fb9763 1142 /* restore registers */
0284b03b 1143 if (restore_sigcontext(env, &frame->sc))
66fb9763 1144 goto badframe;
579a97f7 1145 unlock_user_struct(frame, frame_addr, 0);
0284b03b 1146 return -TARGET_QEMU_ESIGRETURN;
66fb9763
FB
1147
1148badframe:
579a97f7 1149 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
1150 force_sig(TARGET_SIGSEGV);
1151 return 0;
1152}
1153
1154long do_rt_sigreturn(CPUX86State *env)
1155{
da7c8647
TB
1156 abi_ulong frame_addr;
1157 struct rt_sigframe *frame;
1158 sigset_t set;
66fb9763 1159
da7c8647
TB
1160 frame_addr = env->regs[R_ESP] - 4;
1161 trace_user_do_rt_sigreturn(env, frame_addr);
1162 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1163 goto badframe;
1164 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
9eede5b6 1165 set_sigmask(&set);
5fafdf24 1166
0284b03b 1167 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
da7c8647
TB
1168 goto badframe;
1169 }
66fb9763 1170
da7c8647
TB
1171 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1172 get_sp_from_cpustate(env)) == -EFAULT) {
1173 goto badframe;
1174 }
a04e134a 1175
da7c8647 1176 unlock_user_struct(frame, frame_addr, 0);
0284b03b 1177 return -TARGET_QEMU_ESIGRETURN;
66fb9763
FB
1178
1179badframe:
da7c8647
TB
1180 unlock_user_struct(frame, frame_addr, 0);
1181 force_sig(TARGET_SIGSEGV);
1182 return 0;
66fb9763
FB
1183}
1184
1744aea1
AS
1185#elif defined(TARGET_AARCH64)
1186
1187struct target_sigcontext {
1188 uint64_t fault_address;
1189 /* AArch64 registers */
1190 uint64_t regs[31];
1191 uint64_t sp;
1192 uint64_t pc;
1193 uint64_t pstate;
1194 /* 4K reserved for FP/SIMD state and future expansion */
1195 char __reserved[4096] __attribute__((__aligned__(16)));
1196};
1197
1198struct target_ucontext {
1199 abi_ulong tuc_flags;
1200 abi_ulong tuc_link;
1201 target_stack_t tuc_stack;
1202 target_sigset_t tuc_sigmask;
1203 /* glibc uses a 1024-bit sigset_t */
1204 char __unused[1024 / 8 - sizeof(target_sigset_t)];
1205 /* last for future expansion */
1206 struct target_sigcontext tuc_mcontext;
1207};
1208
1209/*
1210 * Header to be used at the beginning of structures extending the user
1211 * context. Such structures must be placed after the rt_sigframe on the stack
1212 * and be 16-byte aligned. The last structure must be a dummy one with the
1213 * magic and size set to 0.
1214 */
1215struct target_aarch64_ctx {
1216 uint32_t magic;
1217 uint32_t size;
1218};
1219
1220#define TARGET_FPSIMD_MAGIC 0x46508001
1221
1222struct target_fpsimd_context {
1223 struct target_aarch64_ctx head;
1224 uint32_t fpsr;
1225 uint32_t fpcr;
1226 uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */
1227};
1228
1229/*
1230 * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
1231 * user space as it will change with the addition of new context. User space
1232 * should check the magic/size information.
1233 */
1234struct target_aux_context {
1235 struct target_fpsimd_context fpsimd;
1236 /* additional context to be added before "end" */
1237 struct target_aarch64_ctx end;
1238};
1239
1240struct target_rt_sigframe {
1241 struct target_siginfo info;
1242 struct target_ucontext uc;
1243 uint64_t fp;
1244 uint64_t lr;
1245 uint32_t tramp[2];
1246};
1247
1248static int target_setup_sigframe(struct target_rt_sigframe *sf,
1249 CPUARMState *env, target_sigset_t *set)
1250{
1251 int i;
1252 struct target_aux_context *aux =
1253 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
1254
1255 /* set up the stack frame for unwinding */
1256 __put_user(env->xregs[29], &sf->fp);
1257 __put_user(env->xregs[30], &sf->lr);
1258
1259 for (i = 0; i < 31; i++) {
1260 __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1261 }
1262 __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1263 __put_user(env->pc, &sf->uc.tuc_mcontext.pc);
d356312f 1264 __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate);
1744aea1 1265
7af03928 1266 __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address);
1744aea1
AS
1267
1268 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
1269 __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]);
1270 }
1271
1272 for (i = 0; i < 32; i++) {
1273#ifdef TARGET_WORDS_BIGENDIAN
1274 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1275 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1276#else
1277 __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1278 __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1279#endif
1280 }
e0ee138b
WN
1281 __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
1282 __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
1744aea1
AS
1283 __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
1284 __put_user(sizeof(struct target_fpsimd_context),
1285 &aux->fpsimd.head.size);
1286
1287 /* set the "end" magic */
1288 __put_user(0, &aux->end.magic);
1289 __put_user(0, &aux->end.size);
1290
1291 return 0;
1292}
1293
1294static int target_restore_sigframe(CPUARMState *env,
1295 struct target_rt_sigframe *sf)
1296{
1297 sigset_t set;
1298 int i;
1299 struct target_aux_context *aux =
1300 (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
e0ee138b 1301 uint32_t magic, size, fpsr, fpcr;
d356312f 1302 uint64_t pstate;
1744aea1
AS
1303
1304 target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
9eede5b6 1305 set_sigmask(&set);
1744aea1
AS
1306
1307 for (i = 0; i < 31; i++) {
1308 __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
1309 }
1310
1311 __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp);
1312 __get_user(env->pc, &sf->uc.tuc_mcontext.pc);
d356312f
PM
1313 __get_user(pstate, &sf->uc.tuc_mcontext.pstate);
1314 pstate_write(env, pstate);
1744aea1
AS
1315
1316 __get_user(magic, &aux->fpsimd.head.magic);
1317 __get_user(size, &aux->fpsimd.head.size);
1318
1319 if (magic != TARGET_FPSIMD_MAGIC
1320 || size != sizeof(struct target_fpsimd_context)) {
1321 return 1;
1322 }
1323
4cf23480
PM
1324 for (i = 0; i < 32; i++) {
1325#ifdef TARGET_WORDS_BIGENDIAN
1326 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
1327 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
1328#else
1329 __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
1330 __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
1331#endif
1744aea1 1332 }
e0ee138b
WN
1333 __get_user(fpsr, &aux->fpsimd.fpsr);
1334 vfp_set_fpsr(env, fpsr);
1335 __get_user(fpcr, &aux->fpsimd.fpcr);
1336 vfp_set_fpcr(env, fpcr);
1744aea1
AS
1337
1338 return 0;
1339}
1340
1341static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env)
1342{
1343 abi_ulong sp;
1344
1345 sp = env->xregs[31];
1346
1347 /*
1348 * This is the X/Open sanctioned signal stack switching.
1349 */
b545f63f 1350 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1744aea1
AS
1351 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1352 }
1353
1354 sp = (sp - sizeof(struct target_rt_sigframe)) & ~15;
1355
1356 return sp;
1357}
1358
1359static void target_setup_frame(int usig, struct target_sigaction *ka,
1360 target_siginfo_t *info, target_sigset_t *set,
1361 CPUARMState *env)
1362{
1363 struct target_rt_sigframe *frame;
8a3ae910 1364 abi_ulong frame_addr, return_addr;
1744aea1
AS
1365
1366 frame_addr = get_sigframe(ka, env);
c8ee0a44 1367 trace_user_setup_frame(env, frame_addr);
1744aea1
AS
1368 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1369 goto give_sigsegv;
1370 }
1371
1372 __put_user(0, &frame->uc.tuc_flags);
1373 __put_user(0, &frame->uc.tuc_link);
1374
1375 __put_user(target_sigaltstack_used.ss_sp,
1376 &frame->uc.tuc_stack.ss_sp);
1377 __put_user(sas_ss_flags(env->xregs[31]),
1378 &frame->uc.tuc_stack.ss_flags);
1379 __put_user(target_sigaltstack_used.ss_size,
1380 &frame->uc.tuc_stack.ss_size);
1381 target_setup_sigframe(frame, env, set);
8a3ae910
MM
1382 if (ka->sa_flags & TARGET_SA_RESTORER) {
1383 return_addr = ka->sa_restorer;
1384 } else {
1385 /* mov x8,#__NR_rt_sigreturn; svc #0 */
1386 __put_user(0xd2801168, &frame->tramp[0]);
1387 __put_user(0xd4000001, &frame->tramp[1]);
1388 return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
1389 }
1744aea1
AS
1390 env->xregs[0] = usig;
1391 env->xregs[31] = frame_addr;
1392 env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
1393 env->pc = ka->_sa_handler;
8a3ae910 1394 env->xregs[30] = return_addr;
1744aea1 1395 if (info) {
f6c7a05b 1396 tswap_siginfo(&frame->info, info);
1744aea1
AS
1397 env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
1398 env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
1399 }
1400
1401 unlock_user_struct(frame, frame_addr, 1);
1402 return;
1403
1404 give_sigsegv:
1405 unlock_user_struct(frame, frame_addr, 1);
1406 force_sig(TARGET_SIGSEGV);
1407}
1408
1409static void setup_rt_frame(int sig, struct target_sigaction *ka,
1410 target_siginfo_t *info, target_sigset_t *set,
1411 CPUARMState *env)
1412{
1413 target_setup_frame(sig, ka, info, set, env);
1414}
1415
1416static void setup_frame(int sig, struct target_sigaction *ka,
1417 target_sigset_t *set, CPUARMState *env)
1418{
1419 target_setup_frame(sig, ka, 0, set, env);
1420}
1421
1422long do_rt_sigreturn(CPUARMState *env)
1423{
7f72cd23 1424 struct target_rt_sigframe *frame = NULL;
1744aea1
AS
1425 abi_ulong frame_addr = env->xregs[31];
1426
c8ee0a44 1427 trace_user_do_rt_sigreturn(env, frame_addr);
1744aea1
AS
1428 if (frame_addr & 15) {
1429 goto badframe;
1430 }
1431
1432 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1433 goto badframe;
1434 }
1435
1436 if (target_restore_sigframe(env, frame)) {
1437 goto badframe;
1438 }
1439
1440 if (do_sigaltstack(frame_addr +
1441 offsetof(struct target_rt_sigframe, uc.tuc_stack),
1442 0, get_sp_from_cpustate(env)) == -EFAULT) {
1443 goto badframe;
1444 }
1445
1446 unlock_user_struct(frame, frame_addr, 0);
f0267ef7 1447 return -TARGET_QEMU_ESIGRETURN;
1744aea1
AS
1448
1449 badframe:
1450 unlock_user_struct(frame, frame_addr, 0);
1451 force_sig(TARGET_SIGSEGV);
1452 return 0;
1453}
1454
1455long do_sigreturn(CPUARMState *env)
1456{
1457 return do_rt_sigreturn(env);
1458}
1459
43fff238
FB
1460#elif defined(TARGET_ARM)
1461
1462struct target_sigcontext {
da7c8647
TB
1463 abi_ulong trap_no;
1464 abi_ulong error_code;
1465 abi_ulong oldmask;
1466 abi_ulong arm_r0;
1467 abi_ulong arm_r1;
1468 abi_ulong arm_r2;
1469 abi_ulong arm_r3;
1470 abi_ulong arm_r4;
1471 abi_ulong arm_r5;
1472 abi_ulong arm_r6;
1473 abi_ulong arm_r7;
1474 abi_ulong arm_r8;
1475 abi_ulong arm_r9;
1476 abi_ulong arm_r10;
1477 abi_ulong arm_fp;
1478 abi_ulong arm_ip;
1479 abi_ulong arm_sp;
1480 abi_ulong arm_lr;
1481 abi_ulong arm_pc;
1482 abi_ulong arm_cpsr;
1483 abi_ulong fault_address;
43fff238
FB
1484};
1485
a745ec6d
PB
1486struct target_ucontext_v1 {
1487 abi_ulong tuc_flags;
1488 abi_ulong tuc_link;
c227f099 1489 target_stack_t tuc_stack;
a745ec6d 1490 struct target_sigcontext tuc_mcontext;
c227f099 1491 target_sigset_t tuc_sigmask; /* mask last for extensibility */
a745ec6d
PB
1492};
1493
1494struct target_ucontext_v2 {
992f48a0
BS
1495 abi_ulong tuc_flags;
1496 abi_ulong tuc_link;
c227f099 1497 target_stack_t tuc_stack;
b8076a74 1498 struct target_sigcontext tuc_mcontext;
c227f099 1499 target_sigset_t tuc_sigmask; /* mask last for extensibility */
5f0b7c88 1500 char __unused[128 - sizeof(target_sigset_t)];
a745ec6d 1501 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
43fff238
FB
1502};
1503
0d871bdb
PM
1504struct target_user_vfp {
1505 uint64_t fpregs[32];
1506 abi_ulong fpscr;
1507};
1508
1509struct target_user_vfp_exc {
1510 abi_ulong fpexc;
1511 abi_ulong fpinst;
1512 abi_ulong fpinst2;
1513};
1514
1515struct target_vfp_sigframe {
1516 abi_ulong magic;
1517 abi_ulong size;
1518 struct target_user_vfp ufp;
1519 struct target_user_vfp_exc ufp_exc;
1520} __attribute__((__aligned__(8)));
1521
08e11256
PM
1522struct target_iwmmxt_sigframe {
1523 abi_ulong magic;
1524 abi_ulong size;
1525 uint64_t regs[16];
1526 /* Note that not all the coprocessor control registers are stored here */
1527 uint32_t wcssf;
1528 uint32_t wcasf;
1529 uint32_t wcgr0;
1530 uint32_t wcgr1;
1531 uint32_t wcgr2;
1532 uint32_t wcgr3;
1533} __attribute__((__aligned__(8)));
1534
0d871bdb 1535#define TARGET_VFP_MAGIC 0x56465001
08e11256 1536#define TARGET_IWMMXT_MAGIC 0x12ef842a
0d871bdb 1537
a8c33204 1538struct sigframe_v1
43fff238
FB
1539{
1540 struct target_sigcontext sc;
992f48a0
BS
1541 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1542 abi_ulong retcode;
43fff238
FB
1543};
1544
a8c33204
PB
1545struct sigframe_v2
1546{
1547 struct target_ucontext_v2 uc;
1548 abi_ulong retcode;
1549};
1550
a745ec6d 1551struct rt_sigframe_v1
43fff238 1552{
f8b0aa25
FB
1553 abi_ulong pinfo;
1554 abi_ulong puc;
43fff238 1555 struct target_siginfo info;
a745ec6d
PB
1556 struct target_ucontext_v1 uc;
1557 abi_ulong retcode;
1558};
1559
1560struct rt_sigframe_v2
1561{
1562 struct target_siginfo info;
1563 struct target_ucontext_v2 uc;
992f48a0 1564 abi_ulong retcode;
43fff238
FB
1565};
1566
1567#define TARGET_CONFIG_CPU_32 1
1568
1569/*
1570 * For ARM syscalls, we encode the syscall number into the instruction.
1571 */
1572#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1573#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1574
1575/*
1576 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1577 * need two 16-bit instructions.
1578 */
1579#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1580#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1581
992f48a0 1582static const abi_ulong retcodes[4] = {
43fff238
FB
1583 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1584 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1585};
1586
1587
05390248 1588static inline int valid_user_regs(CPUARMState *regs)
43fff238
FB
1589{
1590 return 1;
1591}
1592
a8c33204 1593static void
43fff238 1594setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
05390248 1595 CPUARMState *env, abi_ulong mask)
43fff238 1596{
a0e1e6d7
PB
1597 __put_user(env->regs[0], &sc->arm_r0);
1598 __put_user(env->regs[1], &sc->arm_r1);
1599 __put_user(env->regs[2], &sc->arm_r2);
1600 __put_user(env->regs[3], &sc->arm_r3);
1601 __put_user(env->regs[4], &sc->arm_r4);
1602 __put_user(env->regs[5], &sc->arm_r5);
1603 __put_user(env->regs[6], &sc->arm_r6);
1604 __put_user(env->regs[7], &sc->arm_r7);
1605 __put_user(env->regs[8], &sc->arm_r8);
1606 __put_user(env->regs[9], &sc->arm_r9);
1607 __put_user(env->regs[10], &sc->arm_r10);
1608 __put_user(env->regs[11], &sc->arm_fp);
1609 __put_user(env->regs[12], &sc->arm_ip);
1610 __put_user(env->regs[13], &sc->arm_sp);
1611 __put_user(env->regs[14], &sc->arm_lr);
1612 __put_user(env->regs[15], &sc->arm_pc);
43fff238 1613#ifdef TARGET_CONFIG_CPU_32
a0e1e6d7 1614 __put_user(cpsr_read(env), &sc->arm_cpsr);
43fff238
FB
1615#endif
1616
a0e1e6d7
PB
1617 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1618 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1619 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1620 __put_user(mask, &sc->oldmask);
43fff238
FB
1621}
1622
579a97f7 1623static inline abi_ulong
05390248 1624get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
43fff238 1625{
a0e1e6d7
PB
1626 unsigned long sp = regs->regs[13];
1627
1628 /*
1629 * This is the X/Open sanctioned signal stack switching.
1630 */
1631 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
1632 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1633 }
1634 /*
1635 * ATPCS B01 mandates 8-byte alignment
1636 */
1637 return (sp - framesize) & ~7;
43fff238
FB
1638}
1639
0188fadb 1640static void
05390248 1641setup_return(CPUARMState *env, struct target_sigaction *ka,
da7c8647 1642 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
43fff238 1643{
a0e1e6d7
PB
1644 abi_ulong handler = ka->_sa_handler;
1645 abi_ulong retcode;
1646 int thumb = handler & 1;
1647 uint32_t cpsr = cpsr_read(env);
43fff238 1648
a0e1e6d7
PB
1649 cpsr &= ~CPSR_IT;
1650 if (thumb) {
1651 cpsr |= CPSR_T;
1652 } else {
1653 cpsr &= ~CPSR_T;
1654 }
43fff238 1655
a0e1e6d7
PB
1656 if (ka->sa_flags & TARGET_SA_RESTORER) {
1657 retcode = ka->sa_restorer;
1658 } else {
1659 unsigned int idx = thumb;
1660
1661 if (ka->sa_flags & TARGET_SA_SIGINFO) {
1662 idx += 2;
1663 }
43fff238 1664
0188fadb 1665 __put_user(retcodes[idx], rc);
ca8a277c 1666
a0e1e6d7
PB
1667 retcode = rc_addr + thumb;
1668 }
43fff238 1669
a0e1e6d7
PB
1670 env->regs[0] = usig;
1671 env->regs[13] = frame_addr;
1672 env->regs[14] = retcode;
1673 env->regs[15] = handler & (thumb ? ~1 : ~3);
1674 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
43fff238
FB
1675}
1676
05390248 1677static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
0d871bdb
PM
1678{
1679 int i;
1680 struct target_vfp_sigframe *vfpframe;
1681 vfpframe = (struct target_vfp_sigframe *)regspace;
1682 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
1683 __put_user(sizeof(*vfpframe), &vfpframe->size);
1684 for (i = 0; i < 32; i++) {
005e1a0a 1685 __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
0d871bdb
PM
1686 }
1687 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
1688 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
1689 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1690 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1691 return (abi_ulong*)(vfpframe+1);
1692}
1693
05390248
AF
1694static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
1695 CPUARMState *env)
08e11256
PM
1696{
1697 int i;
1698 struct target_iwmmxt_sigframe *iwmmxtframe;
1699 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
1700 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
1701 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
1702 for (i = 0; i < 16; i++) {
1703 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
1704 }
1705 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
1706 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
1707 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
1708 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
1709 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
1710 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
1711 return (abi_ulong*)(iwmmxtframe+1);
1712}
1713
a8c33204 1714static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
05390248 1715 target_sigset_t *set, CPUARMState *env)
a8c33204
PB
1716{
1717 struct target_sigaltstack stack;
1718 int i;
0d871bdb 1719 abi_ulong *regspace;
a8c33204
PB
1720
1721 /* Clear all the bits of the ucontext we don't use. */
1722 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1723
1724 memset(&stack, 0, sizeof(stack));
1725 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1726 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1727 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1728 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1729
1730 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
0d871bdb
PM
1731 /* Save coprocessor signal frame. */
1732 regspace = uc->tuc_regspace;
1733 if (arm_feature(env, ARM_FEATURE_VFP)) {
1734 regspace = setup_sigframe_v2_vfp(regspace, env);
1735 }
08e11256
PM
1736 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
1737 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
1738 }
1739
0d871bdb
PM
1740 /* Write terminating magic word */
1741 __put_user(0, regspace);
1742
a8c33204
PB
1743 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1744 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1745 }
1746}
1747
579a97f7 1748/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
624f7979 1749static void setup_frame_v1(int usig, struct target_sigaction *ka,
05390248 1750 target_sigset_t *set, CPUARMState *regs)
43fff238 1751{
da7c8647
TB
1752 struct sigframe_v1 *frame;
1753 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1754 int i;
43fff238 1755
da7c8647
TB
1756 trace_user_setup_frame(regs, frame_addr);
1757 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1758 return;
1759 }
579a97f7 1760
da7c8647 1761 setup_sigcontext(&frame->sc, regs, set->sig[0]);
43fff238 1762
0188fadb
RV
1763 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1764 __put_user(set->sig[i], &frame->extramask[i - 1]);
1765 }
43fff238 1766
da7c8647
TB
1767 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1768 frame_addr + offsetof(struct sigframe_v1, retcode));
579a97f7 1769
da7c8647 1770 unlock_user_struct(frame, frame_addr, 1);
a8c33204
PB
1771}
1772
624f7979 1773static void setup_frame_v2(int usig, struct target_sigaction *ka,
05390248 1774 target_sigset_t *set, CPUARMState *regs)
a8c33204 1775{
da7c8647
TB
1776 struct sigframe_v2 *frame;
1777 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
a8c33204 1778
da7c8647
TB
1779 trace_user_setup_frame(regs, frame_addr);
1780 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1781 return;
1782 }
a8c33204 1783
da7c8647 1784 setup_sigframe_v2(&frame->uc, set, regs);
a8c33204 1785
da7c8647
TB
1786 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1787 frame_addr + offsetof(struct sigframe_v2, retcode));
a8c33204 1788
da7c8647 1789 unlock_user_struct(frame, frame_addr, 1);
a8c33204
PB
1790}
1791
624f7979 1792static void setup_frame(int usig, struct target_sigaction *ka,
05390248 1793 target_sigset_t *set, CPUARMState *regs)
a8c33204
PB
1794{
1795 if (get_osversion() >= 0x020612) {
1796 setup_frame_v2(usig, ka, set, regs);
1797 } else {
1798 setup_frame_v1(usig, ka, set, regs);
1799 }
43fff238
FB
1800}
1801
579a97f7 1802/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
624f7979 1803static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
c227f099 1804 target_siginfo_t *info,
05390248 1805 target_sigset_t *set, CPUARMState *env)
43fff238 1806{
da7c8647
TB
1807 struct rt_sigframe_v1 *frame;
1808 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1809 struct target_sigaltstack stack;
1810 int i;
1811 abi_ulong info_addr, uc_addr;
43fff238 1812
da7c8647
TB
1813 trace_user_setup_rt_frame(env, frame_addr);
1814 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1815 return /* 1 */;
1816 }
edf779ff 1817
da7c8647
TB
1818 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1819 __put_user(info_addr, &frame->pinfo);
1820 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1821 __put_user(uc_addr, &frame->puc);
1822 tswap_siginfo(&frame->info, info);
43fff238 1823
da7c8647
TB
1824 /* Clear all the bits of the ucontext we don't use. */
1825 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
43fff238 1826
da7c8647
TB
1827 memset(&stack, 0, sizeof(stack));
1828 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1829 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1830 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1831 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
a04e134a 1832
da7c8647
TB
1833 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1834 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1835 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
1836 }
43fff238 1837
da7c8647
TB
1838 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1839 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
a745ec6d 1840
da7c8647
TB
1841 env->regs[1] = info_addr;
1842 env->regs[2] = uc_addr;
a745ec6d 1843
da7c8647 1844 unlock_user_struct(frame, frame_addr, 1);
a745ec6d
PB
1845}
1846
624f7979 1847static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
c227f099 1848 target_siginfo_t *info,
05390248 1849 target_sigset_t *set, CPUARMState *env)
a745ec6d 1850{
da7c8647
TB
1851 struct rt_sigframe_v2 *frame;
1852 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1853 abi_ulong info_addr, uc_addr;
a745ec6d 1854
da7c8647
TB
1855 trace_user_setup_rt_frame(env, frame_addr);
1856 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
1857 return /* 1 */;
1858 }
a745ec6d 1859
da7c8647
TB
1860 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1861 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1862 tswap_siginfo(&frame->info, info);
a745ec6d 1863
da7c8647 1864 setup_sigframe_v2(&frame->uc, set, env);
a745ec6d 1865
da7c8647
TB
1866 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1867 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
a745ec6d 1868
da7c8647
TB
1869 env->regs[1] = info_addr;
1870 env->regs[2] = uc_addr;
43fff238 1871
da7c8647 1872 unlock_user_struct(frame, frame_addr, 1);
43fff238
FB
1873}
1874
624f7979 1875static void setup_rt_frame(int usig, struct target_sigaction *ka,
c227f099 1876 target_siginfo_t *info,
05390248 1877 target_sigset_t *set, CPUARMState *env)
a745ec6d
PB
1878{
1879 if (get_osversion() >= 0x020612) {
1880 setup_rt_frame_v2(usig, ka, info, set, env);
1881 } else {
1882 setup_rt_frame_v1(usig, ka, info, set, env);
1883 }
1884}
1885
43fff238 1886static int
05390248 1887restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
43fff238 1888{
da7c8647
TB
1889 int err = 0;
1890 uint32_t cpsr;
43fff238 1891
1d8b512b
RV
1892 __get_user(env->regs[0], &sc->arm_r0);
1893 __get_user(env->regs[1], &sc->arm_r1);
1894 __get_user(env->regs[2], &sc->arm_r2);
1895 __get_user(env->regs[3], &sc->arm_r3);
1896 __get_user(env->regs[4], &sc->arm_r4);
1897 __get_user(env->regs[5], &sc->arm_r5);
1898 __get_user(env->regs[6], &sc->arm_r6);
1899 __get_user(env->regs[7], &sc->arm_r7);
1900 __get_user(env->regs[8], &sc->arm_r8);
1901 __get_user(env->regs[9], &sc->arm_r9);
1902 __get_user(env->regs[10], &sc->arm_r10);
1903 __get_user(env->regs[11], &sc->arm_fp);
1904 __get_user(env->regs[12], &sc->arm_ip);
1905 __get_user(env->regs[13], &sc->arm_sp);
1906 __get_user(env->regs[14], &sc->arm_lr);
1907 __get_user(env->regs[15], &sc->arm_pc);
43fff238 1908#ifdef TARGET_CONFIG_CPU_32
1d8b512b 1909 __get_user(cpsr, &sc->arm_cpsr);
50866ba5 1910 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
43fff238
FB
1911#endif
1912
da7c8647 1913 err |= !valid_user_regs(env);
43fff238 1914
da7c8647 1915 return err;
43fff238
FB
1916}
1917
05390248 1918static long do_sigreturn_v1(CPUARMState *env)
43fff238 1919{
da7c8647
TB
1920 abi_ulong frame_addr;
1921 struct sigframe_v1 *frame = NULL;
1922 target_sigset_t set;
1923 sigset_t host_set;
1924 int i;
978fae9f 1925
da7c8647
TB
1926 /*
1927 * Since we stacked the signal on a 64-bit boundary,
1928 * then 'sp' should be word aligned here. If it's
1929 * not, then the user is trying to mess with us.
1930 */
1931 frame_addr = env->regs[13];
1932 trace_user_do_sigreturn(env, frame_addr);
1933 if (frame_addr & 7) {
1934 goto badframe;
1935 }
1936
1937 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
1938 goto badframe;
1939 }
43fff238 1940
f5f601af
RV
1941 __get_user(set.sig[0], &frame->sc.oldmask);
1942 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1943 __get_user(set.sig[i], &frame->extramask[i - 1]);
1944 }
43fff238 1945
da7c8647 1946 target_to_host_sigset_internal(&host_set, &set);
9eede5b6 1947 set_sigmask(&host_set);
43fff238 1948
da7c8647
TB
1949 if (restore_sigcontext(env, &frame->sc)) {
1950 goto badframe;
1951 }
43fff238
FB
1952
1953#if 0
da7c8647
TB
1954 /* Send SIGTRAP if we're single-stepping */
1955 if (ptrace_cancel_bpt(current))
1956 send_sig(SIGTRAP, current, 1);
43fff238 1957#endif
da7c8647 1958 unlock_user_struct(frame, frame_addr, 0);
f0267ef7 1959 return -TARGET_QEMU_ESIGRETURN;
43fff238
FB
1960
1961badframe:
da7c8647
TB
1962 force_sig(TARGET_SIGSEGV /* , current */);
1963 return 0;
43fff238
FB
1964}
1965
05390248 1966static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
5f9099d9
PM
1967{
1968 int i;
1969 abi_ulong magic, sz;
1970 uint32_t fpscr, fpexc;
1971 struct target_vfp_sigframe *vfpframe;
1972 vfpframe = (struct target_vfp_sigframe *)regspace;
1973
1974 __get_user(magic, &vfpframe->magic);
1975 __get_user(sz, &vfpframe->size);
1976 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
1977 return 0;
1978 }
1979 for (i = 0; i < 32; i++) {
005e1a0a 1980 __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
5f9099d9
PM
1981 }
1982 __get_user(fpscr, &vfpframe->ufp.fpscr);
1983 vfp_set_fpscr(env, fpscr);
1984 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
1985 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
1986 * and the exception flag is cleared
1987 */
1988 fpexc |= (1 << 30);
1989 fpexc &= ~((1 << 31) | (1 << 28));
1990 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
1991 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
1992 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
1993 return (abi_ulong*)(vfpframe + 1);
1994}
1995
05390248
AF
1996static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
1997 abi_ulong *regspace)
a59d69da
PM
1998{
1999 int i;
2000 abi_ulong magic, sz;
2001 struct target_iwmmxt_sigframe *iwmmxtframe;
2002 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
2003
2004 __get_user(magic, &iwmmxtframe->magic);
2005 __get_user(sz, &iwmmxtframe->size);
2006 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
2007 return 0;
2008 }
2009 for (i = 0; i < 16; i++) {
2010 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
2011 }
2012 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
2013 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
2014 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
2015 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
2016 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
2017 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
2018 return (abi_ulong*)(iwmmxtframe + 1);
2019}
2020
05390248 2021static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
a8c33204
PB
2022 struct target_ucontext_v2 *uc)
2023{
2024 sigset_t host_set;
5f9099d9 2025 abi_ulong *regspace;
a8c33204
PB
2026
2027 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
9eede5b6 2028 set_sigmask(&host_set);
a8c33204
PB
2029
2030 if (restore_sigcontext(env, &uc->tuc_mcontext))
2031 return 1;
2032
5f9099d9
PM
2033 /* Restore coprocessor signal frame */
2034 regspace = uc->tuc_regspace;
2035 if (arm_feature(env, ARM_FEATURE_VFP)) {
2036 regspace = restore_sigframe_v2_vfp(env, regspace);
2037 if (!regspace) {
2038 return 1;
2039 }
2040 }
a59d69da
PM
2041 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2042 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
2043 if (!regspace) {
2044 return 1;
2045 }
2046 }
5f9099d9 2047
a8c33204
PB
2048 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2049 return 1;
2050
2051#if 0
2052 /* Send SIGTRAP if we're single-stepping */
2053 if (ptrace_cancel_bpt(current))
da7c8647 2054 send_sig(SIGTRAP, current, 1);
a8c33204
PB
2055#endif
2056
2057 return 0;
2058}
2059
05390248 2060static long do_sigreturn_v2(CPUARMState *env)
a8c33204 2061{
da7c8647
TB
2062 abi_ulong frame_addr;
2063 struct sigframe_v2 *frame = NULL;
2064
2065 /*
2066 * Since we stacked the signal on a 64-bit boundary,
2067 * then 'sp' should be word aligned here. If it's
2068 * not, then the user is trying to mess with us.
2069 */
2070 frame_addr = env->regs[13];
2071 trace_user_do_sigreturn(env, frame_addr);
2072 if (frame_addr & 7) {
2073 goto badframe;
2074 }
978fae9f 2075
da7c8647
TB
2076 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2077 goto badframe;
2078 }
a8c33204 2079
da7c8647
TB
2080 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2081 goto badframe;
2082 }
a8c33204 2083
da7c8647 2084 unlock_user_struct(frame, frame_addr, 0);
f0267ef7 2085 return -TARGET_QEMU_ESIGRETURN;
a8c33204
PB
2086
2087badframe:
da7c8647
TB
2088 unlock_user_struct(frame, frame_addr, 0);
2089 force_sig(TARGET_SIGSEGV /* , current */);
2090 return 0;
a8c33204
PB
2091}
2092
05390248 2093long do_sigreturn(CPUARMState *env)
a8c33204
PB
2094{
2095 if (get_osversion() >= 0x020612) {
2096 return do_sigreturn_v2(env);
2097 } else {
2098 return do_sigreturn_v1(env);
2099 }
2100}
2101
05390248 2102static long do_rt_sigreturn_v1(CPUARMState *env)
43fff238 2103{
da7c8647
TB
2104 abi_ulong frame_addr;
2105 struct rt_sigframe_v1 *frame = NULL;
2106 sigset_t host_set;
978fae9f 2107
da7c8647
TB
2108 /*
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 }
a745ec6d 2118
da7c8647
TB
2119 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2120 goto badframe;
2121 }
2122
2123 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
9eede5b6 2124 set_sigmask(&host_set);
a745ec6d 2125
da7c8647
TB
2126 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
2127 goto badframe;
2128 }
a745ec6d 2129
da7c8647
TB
2130 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
2131 goto badframe;
a745ec6d
PB
2132
2133#if 0
da7c8647
TB
2134 /* Send SIGTRAP if we're single-stepping */
2135 if (ptrace_cancel_bpt(current))
2136 send_sig(SIGTRAP, current, 1);
a745ec6d 2137#endif
da7c8647 2138 unlock_user_struct(frame, frame_addr, 0);
f0267ef7 2139 return -TARGET_QEMU_ESIGRETURN;
a745ec6d
PB
2140
2141badframe:
da7c8647
TB
2142 unlock_user_struct(frame, frame_addr, 0);
2143 force_sig(TARGET_SIGSEGV /* , current */);
2144 return 0;
a745ec6d
PB
2145}
2146
05390248 2147static long do_rt_sigreturn_v2(CPUARMState *env)
a745ec6d 2148{
da7c8647
TB
2149 abi_ulong frame_addr;
2150 struct rt_sigframe_v2 *frame = NULL;
978fae9f 2151
da7c8647
TB
2152 /*
2153 * Since we stacked the signal on a 64-bit boundary,
2154 * then 'sp' should be word aligned here. If it's
2155 * not, then the user is trying to mess with us.
2156 */
2157 frame_addr = env->regs[13];
2158 trace_user_do_rt_sigreturn(env, frame_addr);
2159 if (frame_addr & 7) {
2160 goto badframe;
2161 }
2162
2163 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
2164 goto badframe;
2165 }
43fff238 2166
da7c8647
TB
2167 if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
2168 goto badframe;
2169 }
a04e134a 2170
da7c8647 2171 unlock_user_struct(frame, frame_addr, 0);
f0267ef7 2172 return -TARGET_QEMU_ESIGRETURN;
43fff238
FB
2173
2174badframe:
da7c8647
TB
2175 unlock_user_struct(frame, frame_addr, 0);
2176 force_sig(TARGET_SIGSEGV /* , current */);
2177 return 0;
43fff238
FB
2178}
2179
05390248 2180long do_rt_sigreturn(CPUARMState *env)
a745ec6d
PB
2181{
2182 if (get_osversion() >= 0x020612) {
2183 return do_rt_sigreturn_v2(env);
2184 } else {
2185 return do_rt_sigreturn_v1(env);
2186 }
2187}
2188
6d5e216d 2189#elif defined(TARGET_SPARC)
80a9d035 2190
6d5e216d
FB
2191#define __SUNOS_MAXWIN 31
2192
2193/* This is what SunOS does, so shall I. */
2194struct target_sigcontext {
da7c8647 2195 abi_ulong sigc_onstack; /* state to restore */
6d5e216d 2196
da7c8647
TB
2197 abi_ulong sigc_mask; /* sigmask to restore */
2198 abi_ulong sigc_sp; /* stack pointer */
2199 abi_ulong sigc_pc; /* program counter */
2200 abi_ulong sigc_npc; /* next program counter */
2201 abi_ulong sigc_psr; /* for condition codes etc */
2202 abi_ulong sigc_g1; /* User uses these two registers */
2203 abi_ulong sigc_o0; /* within the trampoline code. */
6d5e216d 2204
da7c8647 2205 /* Now comes information regarding the users window set
6d5e216d
FB
2206 * at the time of the signal.
2207 */
da7c8647 2208 abi_ulong sigc_oswins; /* outstanding windows */
6d5e216d 2209
da7c8647
TB
2210 /* stack ptrs for each regwin buf */
2211 char *sigc_spbuf[__SUNOS_MAXWIN];
6d5e216d 2212
da7c8647
TB
2213 /* Windows to restore after signal */
2214 struct {
2215 abi_ulong locals[8];
2216 abi_ulong ins[8];
2217 } sigc_wbuf[__SUNOS_MAXWIN];
6d5e216d
FB
2218};
2219/* A Sparc stack frame */
2220struct sparc_stackf {
da7c8647
TB
2221 abi_ulong locals[8];
2222 abi_ulong ins[8];
2223 /* It's simpler to treat fp and callers_pc as elements of ins[]
e321c34a
PM
2224 * since we never need to access them ourselves.
2225 */
da7c8647
TB
2226 char *structptr;
2227 abi_ulong xargs[6];
2228 abi_ulong xxargs[1];
6d5e216d
FB
2229};
2230
2231typedef struct {
da7c8647
TB
2232 struct {
2233 abi_ulong psr;
2234 abi_ulong pc;
2235 abi_ulong npc;
2236 abi_ulong y;
2237 abi_ulong u_regs[16]; /* globals and ins */
2238 } si_regs;
2239 int si_mask;
6d5e216d
FB
2240} __siginfo_t;
2241
2242typedef struct {
da7c8647
TB
2243 abi_ulong si_float_regs[32];
2244 unsigned long si_fsr;
2245 unsigned long si_fpqdepth;
2246 struct {
2247 unsigned long *insn_addr;
2248 unsigned long insn;
2249 } si_fpqueue [16];
c227f099 2250} qemu_siginfo_fpu_t;
6d5e216d
FB
2251
2252
2253struct target_signal_frame {
da7c8647
TB
2254 struct sparc_stackf ss;
2255 __siginfo_t info;
2256 abi_ulong fpu_save;
2257 abi_ulong insns[2] __attribute__ ((aligned (8)));
2258 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
2259 abi_ulong extra_size; /* Should be 0 */
2260 qemu_siginfo_fpu_t fpu_state;
6d5e216d
FB
2261};
2262struct target_rt_signal_frame {
da7c8647
TB
2263 struct sparc_stackf ss;
2264 siginfo_t info;
2265 abi_ulong regs[20];
2266 sigset_t mask;
2267 abi_ulong fpu_save;
2268 unsigned int insns[2];
2269 stack_t stack;
2270 unsigned int extra_size; /* Should be 0 */
2271 qemu_siginfo_fpu_t fpu_state;
6d5e216d
FB
2272};
2273
e80cfcfc
FB
2274#define UREG_O0 16
2275#define UREG_O6 22
2276#define UREG_I0 0
2277#define UREG_I1 1
2278#define UREG_I2 2
5bfb56b2
BS
2279#define UREG_I3 3
2280#define UREG_I4 4
2281#define UREG_I5 5
e80cfcfc
FB
2282#define UREG_I6 6
2283#define UREG_I7 7
2284#define UREG_L0 8
6d5e216d
FB
2285#define UREG_FP UREG_I6
2286#define UREG_SP UREG_O6
2287
624f7979 2288static inline abi_ulong get_sigframe(struct target_sigaction *sa,
05390248
AF
2289 CPUSPARCState *env,
2290 unsigned long framesize)
6d5e216d 2291{
da7c8647 2292 abi_ulong sp;
6d5e216d 2293
da7c8647 2294 sp = env->regwptr[UREG_FP];
6d5e216d 2295
da7c8647
TB
2296 /* This is the X/Open sanctioned signal stack switching. */
2297 if (sa->sa_flags & TARGET_SA_ONSTACK) {
2298 if (!on_sig_stack(sp)
2299 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
2300 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2301 }
2302 }
2303 return sp - framesize;
6d5e216d
FB
2304}
2305
2306static int
05390248 2307setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
6d5e216d 2308{
da7c8647 2309 int err = 0, i;
6d5e216d 2310
1d8b512b
RV
2311 __put_user(env->psr, &si->si_regs.psr);
2312 __put_user(env->pc, &si->si_regs.pc);
2313 __put_user(env->npc, &si->si_regs.npc);
2314 __put_user(env->y, &si->si_regs.y);
da7c8647 2315 for (i=0; i < 8; i++) {
1d8b512b 2316 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
da7c8647
TB
2317 }
2318 for (i=0; i < 8; i++) {
1d8b512b 2319 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
da7c8647 2320 }
1d8b512b 2321 __put_user(mask, &si->si_mask);
da7c8647 2322 return err;
6d5e216d 2323}
e80cfcfc 2324
80a9d035 2325#if 0
6d5e216d
FB
2326static int
2327setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
05390248 2328 CPUSPARCState *env, unsigned long mask)
6d5e216d 2329{
da7c8647 2330 int err = 0;
6d5e216d 2331
1d8b512b
RV
2332 __put_user(mask, &sc->sigc_mask);
2333 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
2334 __put_user(env->pc, &sc->sigc_pc);
2335 __put_user(env->npc, &sc->sigc_npc);
2336 __put_user(env->psr, &sc->sigc_psr);
2337 __put_user(env->gregs[1], &sc->sigc_g1);
2338 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
6d5e216d 2339
da7c8647 2340 return err;
6d5e216d 2341}
80a9d035 2342#endif
6d5e216d
FB
2343#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
2344
624f7979 2345static void setup_frame(int sig, struct target_sigaction *ka,
05390248 2346 target_sigset_t *set, CPUSPARCState *env)
6d5e216d 2347{
da7c8647
TB
2348 abi_ulong sf_addr;
2349 struct target_signal_frame *sf;
2350 int sigframe_size, err, i;
6d5e216d 2351
da7c8647
TB
2352 /* 1. Make sure everything is clean */
2353 //synchronize_user_stack();
6d5e216d 2354
da7c8647
TB
2355 sigframe_size = NF_ALIGNEDSZ;
2356 sf_addr = get_sigframe(ka, env, sigframe_size);
2357 trace_user_setup_frame(env, sf_addr);
6d5e216d 2358
da7c8647
TB
2359 sf = lock_user(VERIFY_WRITE, sf_addr,
2360 sizeof(struct target_signal_frame), 0);
2361 if (!sf) {
2362 goto sigsegv;
2363 }
6d5e216d 2364#if 0
da7c8647
TB
2365 if (invalid_frame_pointer(sf, sigframe_size))
2366 goto sigill_and_return;
6d5e216d 2367#endif
da7c8647
TB
2368 /* 2. Save the current process state */
2369 err = setup___siginfo(&sf->info, env, set->sig[0]);
1d8b512b 2370 __put_user(0, &sf->extra_size);
6d5e216d 2371
da7c8647
TB
2372 //save_fpu_state(regs, &sf->fpu_state);
2373 //__put_user(&sf->fpu_state, &sf->fpu_save);
6d5e216d 2374
1d8b512b 2375 __put_user(set->sig[0], &sf->info.si_mask);
da7c8647 2376 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
1d8b512b 2377 __put_user(set->sig[i + 1], &sf->extramask[i]);
da7c8647 2378 }
6d5e216d 2379
da7c8647 2380 for (i = 0; i < 8; i++) {
1d8b512b 2381 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
da7c8647
TB
2382 }
2383 for (i = 0; i < 8; i++) {
1d8b512b 2384 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
da7c8647
TB
2385 }
2386 if (err)
2387 goto sigsegv;
2388
2389 /* 3. signal handler back-trampoline and parameters */
2390 env->regwptr[UREG_FP] = sf_addr;
2391 env->regwptr[UREG_I0] = sig;
2392 env->regwptr[UREG_I1] = sf_addr +
2393 offsetof(struct target_signal_frame, info);
2394 env->regwptr[UREG_I2] = sf_addr +
2395 offsetof(struct target_signal_frame, info);
2396
2397 /* 4. signal handler */
2398 env->pc = ka->_sa_handler;
2399 env->npc = (env->pc + 4);
2400 /* 5. return to kernel instructions */
2401 if (ka->sa_restorer) {
2402 env->regwptr[UREG_I7] = ka->sa_restorer;
2403 } else {
2404 uint32_t val32;
2405
2406 env->regwptr[UREG_I7] = sf_addr +
2407 offsetof(struct target_signal_frame, insns) - 2 * 4;
2408
2409 /* mov __NR_sigreturn, %g1 */
2410 val32 = 0x821020d8;
1d8b512b 2411 __put_user(val32, &sf->insns[0]);
6d5e216d 2412
da7c8647
TB
2413 /* t 0x10 */
2414 val32 = 0x91d02010;
1d8b512b 2415 __put_user(val32, &sf->insns[1]);
da7c8647
TB
2416 if (err)
2417 goto sigsegv;
6d5e216d 2418
da7c8647
TB
2419 /* Flush instruction space. */
2420 // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2421 // tb_flush(env);
2422 }
2423 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2424 return;
459a4017
FB
2425#if 0
2426sigill_and_return:
da7c8647 2427 force_sig(TARGET_SIGILL);
459a4017 2428#endif
6d5e216d 2429sigsegv:
da7c8647
TB
2430 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2431 force_sig(TARGET_SIGSEGV);
6d5e216d 2432}
6d5e216d 2433
624f7979 2434static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 2435 target_siginfo_t *info,
05390248 2436 target_sigset_t *set, CPUSPARCState *env)
6d5e216d
FB
2437{
2438 fprintf(stderr, "setup_rt_frame: not implemented\n");
2439}
2440
05390248 2441long do_sigreturn(CPUSPARCState *env)
6d5e216d 2442{
da7c8647
TB
2443 abi_ulong sf_addr;
2444 struct target_signal_frame *sf;
2445 uint32_t up_psr, pc, npc;
2446 target_sigset_t set;
2447 sigset_t host_set;
2448 int err=0, i;
6d5e216d 2449
da7c8647
TB
2450 sf_addr = env->regwptr[UREG_FP];
2451 trace_user_do_sigreturn(env, sf_addr);
2452 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
2453 goto segv_and_exit;
2454 }
6d5e216d 2455
da7c8647 2456 /* 1. Make sure we are not getting garbage from the user */
6d5e216d 2457
da7c8647
TB
2458 if (sf_addr & 3)
2459 goto segv_and_exit;
6d5e216d 2460
da7c8647
TB
2461 __get_user(pc, &sf->info.si_regs.pc);
2462 __get_user(npc, &sf->info.si_regs.npc);
6d5e216d 2463
da7c8647
TB
2464 if ((pc | npc) & 3) {
2465 goto segv_and_exit;
2466 }
6d5e216d 2467
da7c8647
TB
2468 /* 2. Restore the state */
2469 __get_user(up_psr, &sf->info.si_regs.psr);
e80cfcfc 2470
da7c8647
TB
2471 /* User can only change condition codes and FPU enabling in %psr. */
2472 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2473 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
a315a145 2474
da7c8647
TB
2475 env->pc = pc;
2476 env->npc = npc;
2477 __get_user(env->y, &sf->info.si_regs.y);
2478 for (i=0; i < 8; i++) {
2479 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2480 }
2481 for (i=0; i < 8; i++) {
2482 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2483 }
6d5e216d 2484
da7c8647 2485 /* FIXME: implement FPU save/restore:
2aec3a27
PM
2486 * __get_user(fpu_save, &sf->fpu_save);
2487 * if (fpu_save)
2488 * err |= restore_fpu_state(env, fpu_save);
2489 */
6d5e216d 2490
da7c8647 2491 /* This is pretty much atomic, no amount locking would prevent
6d5e216d
FB
2492 * the races which exist anyways.
2493 */
da7c8647
TB
2494 __get_user(set.sig[0], &sf->info.si_mask);
2495 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2496 __get_user(set.sig[i], &sf->extramask[i - 1]);
2497 }
e80cfcfc 2498
da7c8647 2499 target_to_host_sigset_internal(&host_set, &set);
9eede5b6 2500 set_sigmask(&host_set);
6d5e216d 2501
da7c8647
TB
2502 if (err) {
2503 goto segv_and_exit;
2504 }
2505 unlock_user_struct(sf, sf_addr, 0);
c0bea68f 2506 return -TARGET_QEMU_ESIGRETURN;
6d5e216d
FB
2507
2508segv_and_exit:
da7c8647
TB
2509 unlock_user_struct(sf, sf_addr, 0);
2510 force_sig(TARGET_SIGSEGV);
6d5e216d
FB
2511}
2512
05390248 2513long do_rt_sigreturn(CPUSPARCState *env)
6d5e216d 2514{
c8ee0a44 2515 trace_user_do_rt_sigreturn(env, 0);
6d5e216d 2516 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 2517 return -TARGET_ENOSYS;
6d5e216d
FB
2518}
2519
459a4017 2520#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
5bfb56b2
BS
2521#define MC_TSTATE 0
2522#define MC_PC 1
2523#define MC_NPC 2
2524#define MC_Y 3
2525#define MC_G1 4
2526#define MC_G2 5
2527#define MC_G3 6
2528#define MC_G4 7
2529#define MC_G5 8
2530#define MC_G6 9
2531#define MC_G7 10
2532#define MC_O0 11
2533#define MC_O1 12
2534#define MC_O2 13
2535#define MC_O3 14
2536#define MC_O4 15
2537#define MC_O5 16
2538#define MC_O6 17
2539#define MC_O7 18
2540#define MC_NGREG 19
2541
c227f099
AL
2542typedef abi_ulong target_mc_greg_t;
2543typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
5bfb56b2
BS
2544
2545struct target_mc_fq {
992f48a0 2546 abi_ulong *mcfq_addr;
5bfb56b2
BS
2547 uint32_t mcfq_insn;
2548};
2549
2550struct target_mc_fpu {
2551 union {
2552 uint32_t sregs[32];
2553 uint64_t dregs[32];
2554 //uint128_t qregs[16];
2555 } mcfpu_fregs;
992f48a0
BS
2556 abi_ulong mcfpu_fsr;
2557 abi_ulong mcfpu_fprs;
2558 abi_ulong mcfpu_gsr;
5bfb56b2
BS
2559 struct target_mc_fq *mcfpu_fq;
2560 unsigned char mcfpu_qcnt;
2561 unsigned char mcfpu_qentsz;
2562 unsigned char mcfpu_enab;
2563};
c227f099 2564typedef struct target_mc_fpu target_mc_fpu_t;
5bfb56b2
BS
2565
2566typedef struct {
c227f099
AL
2567 target_mc_gregset_t mc_gregs;
2568 target_mc_greg_t mc_fp;
2569 target_mc_greg_t mc_i7;
2570 target_mc_fpu_t mc_fpregs;
2571} target_mcontext_t;
5bfb56b2
BS
2572
2573struct target_ucontext {
60e99246
AJ
2574 struct target_ucontext *tuc_link;
2575 abi_ulong tuc_flags;
2576 target_sigset_t tuc_sigmask;
2577 target_mcontext_t tuc_mcontext;
5bfb56b2
BS
2578};
2579
2580/* A V9 register window */
2581struct target_reg_window {
992f48a0
BS
2582 abi_ulong locals[8];
2583 abi_ulong ins[8];
5bfb56b2
BS
2584};
2585
2586#define TARGET_STACK_BIAS 2047
2587
2588/* {set, get}context() needed for 64-bit SparcLinux userland. */
2589void sparc64_set_context(CPUSPARCState *env)
2590{
459a4017
FB
2591 abi_ulong ucp_addr;
2592 struct target_ucontext *ucp;
c227f099 2593 target_mc_gregset_t *grp;
992f48a0 2594 abi_ulong pc, npc, tstate;
459a4017 2595 abi_ulong fp, i7, w_addr;
5bfb56b2 2596 unsigned int i;
5bfb56b2 2597
459a4017 2598 ucp_addr = env->regwptr[UREG_I0];
da7c8647 2599 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
459a4017 2600 goto do_sigsegv;
da7c8647 2601 }
60e99246 2602 grp = &ucp->tuc_mcontext.mc_gregs;
1d8b512b
RV
2603 __get_user(pc, &((*grp)[MC_PC]));
2604 __get_user(npc, &((*grp)[MC_NPC]));
da7c8647 2605 if ((pc | npc) & 3) {
5bfb56b2 2606 goto do_sigsegv;
da7c8647 2607 }
5bfb56b2 2608 if (env->regwptr[UREG_I1]) {
c227f099 2609 target_sigset_t target_set;
5bfb56b2
BS
2610 sigset_t set;
2611
2612 if (TARGET_NSIG_WORDS == 1) {
be3ef5c7 2613 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
5bfb56b2 2614 } else {
459a4017 2615 abi_ulong *src, *dst;
60e99246 2616 src = ucp->tuc_sigmask.sig;
459a4017 2617 dst = target_set.sig;
0d9e61c2 2618 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
1d8b512b 2619 __get_user(*dst, src);
0d9e61c2 2620 }
5bfb56b2
BS
2621 }
2622 target_to_host_sigset_internal(&set, &target_set);
9eede5b6 2623 set_sigmask(&set);
5bfb56b2
BS
2624 }
2625 env->pc = pc;
2626 env->npc = npc;
1d8b512b
RV
2627 __get_user(env->y, &((*grp)[MC_Y]));
2628 __get_user(tstate, &((*grp)[MC_TSTATE]));
5bfb56b2 2629 env->asi = (tstate >> 24) & 0xff;
5a834bb4
BS
2630 cpu_put_ccr(env, tstate >> 32);
2631 cpu_put_cwp64(env, tstate & 0x1f);
1d8b512b
RV
2632 __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2633 __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2634 __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2635 __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2636 __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2637 __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2638 __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2639 __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2640 __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2641 __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2642 __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2643 __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2644 __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2645 __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2646 __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
2647
2648 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2649 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
579a97f7 2650
459a4017 2651 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
da7c8647
TB
2652 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2653 abi_ulong) != 0) {
459a4017 2654 goto do_sigsegv;
da7c8647
TB
2655 }
2656 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2657 abi_ulong) != 0) {
459a4017 2658 goto do_sigsegv;
da7c8647 2659 }
c7b016ba
PM
2660 /* FIXME this does not match how the kernel handles the FPU in
2661 * its sparc64_set_context implementation. In particular the FPU
2662 * is only restored if fenab is non-zero in:
2663 * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2664 */
be3ef5c7 2665 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
459a4017 2666 {
30038fd8
RH
2667 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2668 for (i = 0; i < 64; i++, src++) {
2669 if (i & 1) {
1d8b512b 2670 __get_user(env->fpr[i/2].l.lower, src);
30038fd8 2671 } else {
1d8b512b 2672 __get_user(env->fpr[i/2].l.upper, src);
30038fd8
RH
2673 }
2674 }
459a4017 2675 }
1d8b512b
RV
2676 __get_user(env->fsr,
2677 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2678 __get_user(env->gsr,
2679 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
459a4017 2680 unlock_user_struct(ucp, ucp_addr, 0);
5bfb56b2 2681 return;
da7c8647 2682do_sigsegv:
459a4017 2683 unlock_user_struct(ucp, ucp_addr, 0);
66393fb9 2684 force_sig(TARGET_SIGSEGV);
5bfb56b2
BS
2685}
2686
2687void sparc64_get_context(CPUSPARCState *env)
2688{
459a4017
FB
2689 abi_ulong ucp_addr;
2690 struct target_ucontext *ucp;
c227f099
AL
2691 target_mc_gregset_t *grp;
2692 target_mcontext_t *mcp;
459a4017 2693 abi_ulong fp, i7, w_addr;
5bfb56b2
BS
2694 int err;
2695 unsigned int i;
c227f099 2696 target_sigset_t target_set;
5bfb56b2
BS
2697 sigset_t set;
2698
459a4017 2699 ucp_addr = env->regwptr[UREG_I0];
da7c8647 2700 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
459a4017 2701 goto do_sigsegv;
da7c8647 2702 }
459a4017 2703
60e99246 2704 mcp = &ucp->tuc_mcontext;
5bfb56b2
BS
2705 grp = &mcp->mc_gregs;
2706
2707 /* Skip over the trap instruction, first. */
2708 env->pc = env->npc;
2709 env->npc += 4;
2710
3d3efba0
PM
2711 /* If we're only reading the signal mask then do_sigprocmask()
2712 * is guaranteed not to fail, which is important because we don't
2713 * have any way to signal a failure or restart this operation since
2714 * this is not a normal syscall.
2715 */
2716 err = do_sigprocmask(0, NULL, &set);
2717 assert(err == 0);
5bfb56b2 2718 host_to_target_sigset_internal(&target_set, &set);
459a4017 2719 if (TARGET_NSIG_WORDS == 1) {
1d8b512b
RV
2720 __put_user(target_set.sig[0],
2721 (abi_ulong *)&ucp->tuc_sigmask);
459a4017
FB
2722 } else {
2723 abi_ulong *src, *dst;
2724 src = target_set.sig;
60e99246 2725 dst = ucp->tuc_sigmask.sig;
0d9e61c2 2726 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
1d8b512b 2727 __put_user(*src, dst);
0d9e61c2 2728 }
5bfb56b2
BS
2729 if (err)
2730 goto do_sigsegv;
2731 }
2732
459a4017 2733 /* XXX: tstate must be saved properly */
1d8b512b
RV
2734 // __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2735 __put_user(env->pc, &((*grp)[MC_PC]));
2736 __put_user(env->npc, &((*grp)[MC_NPC]));
2737 __put_user(env->y, &((*grp)[MC_Y]));
2738 __put_user(env->gregs[1], &((*grp)[MC_G1]));
2739 __put_user(env->gregs[2], &((*grp)[MC_G2]));
2740 __put_user(env->gregs[3], &((*grp)[MC_G3]));
2741 __put_user(env->gregs[4], &((*grp)[MC_G4]));
2742 __put_user(env->gregs[5], &((*grp)[MC_G5]));
2743 __put_user(env->gregs[6], &((*grp)[MC_G6]));
2744 __put_user(env->gregs[7], &((*grp)[MC_G7]));
2745 __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2746 __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2747 __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2748 __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2749 __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2750 __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2751 __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2752 __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
579a97f7 2753
459a4017
FB
2754 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2755 fp = i7 = 0;
da7c8647
TB
2756 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2757 abi_ulong) != 0) {
459a4017 2758 goto do_sigsegv;
da7c8647
TB
2759 }
2760 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2761 abi_ulong) != 0) {
459a4017 2762 goto do_sigsegv;
da7c8647 2763 }
1d8b512b
RV
2764 __put_user(fp, &(mcp->mc_fp));
2765 __put_user(i7, &(mcp->mc_i7));
5bfb56b2 2766
459a4017 2767 {
30038fd8
RH
2768 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2769 for (i = 0; i < 64; i++, dst++) {
2770 if (i & 1) {
1d8b512b 2771 __put_user(env->fpr[i/2].l.lower, dst);
30038fd8 2772 } else {
1d8b512b 2773 __put_user(env->fpr[i/2].l.upper, dst);
30038fd8
RH
2774 }
2775 }
459a4017 2776 }
1d8b512b
RV
2777 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2778 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2779 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
5bfb56b2
BS
2780
2781 if (err)
2782 goto do_sigsegv;
459a4017 2783 unlock_user_struct(ucp, ucp_addr, 1);
5bfb56b2 2784 return;
da7c8647 2785do_sigsegv:
459a4017 2786 unlock_user_struct(ucp, ucp_addr, 1);
66393fb9 2787 force_sig(TARGET_SIGSEGV);
5bfb56b2
BS
2788}
2789#endif
ff970904 2790#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
106ec879 2791
ff970904 2792# if defined(TARGET_ABI_MIPSO32)
106ec879
FB
2793struct target_sigcontext {
2794 uint32_t sc_regmask; /* Unused */
2795 uint32_t sc_status;
2796 uint64_t sc_pc;
2797 uint64_t sc_regs[32];
2798 uint64_t sc_fpregs[32];
2799 uint32_t sc_ownedfp; /* Unused */
2800 uint32_t sc_fpc_csr;
2801 uint32_t sc_fpc_eir; /* Unused */
2802 uint32_t sc_used_math;
2803 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
94c5495d 2804 uint32_t pad0;
106ec879
FB
2805 uint64_t sc_mdhi;
2806 uint64_t sc_mdlo;
2807 target_ulong sc_hi1; /* Was sc_cause */
2808 target_ulong sc_lo1; /* Was sc_badvaddr */
2809 target_ulong sc_hi2; /* Was sc_sigset[4] */
2810 target_ulong sc_lo2;
2811 target_ulong sc_hi3;
2812 target_ulong sc_lo3;
2813};
ff970904
RH
2814# else /* N32 || N64 */
2815struct target_sigcontext {
2816 uint64_t sc_regs[32];
2817 uint64_t sc_fpregs[32];
2818 uint64_t sc_mdhi;
2819 uint64_t sc_hi1;
2820 uint64_t sc_hi2;
2821 uint64_t sc_hi3;
2822 uint64_t sc_mdlo;
2823 uint64_t sc_lo1;
2824 uint64_t sc_lo2;
2825 uint64_t sc_lo3;
2826 uint64_t sc_pc;
2827 uint32_t sc_fpc_csr;
2828 uint32_t sc_used_math;
2829 uint32_t sc_dsp;
2830 uint32_t sc_reserved;
2831};
2832# endif /* O32 */
106ec879
FB
2833
2834struct sigframe {
2835 uint32_t sf_ass[4]; /* argument save space for o32 */
2836 uint32_t sf_code[2]; /* signal trampoline */
2837 struct target_sigcontext sf_sc;
c227f099 2838 target_sigset_t sf_mask;
106ec879
FB
2839};
2840
0b1bcb00 2841struct target_ucontext {
60e99246
AJ
2842 target_ulong tuc_flags;
2843 target_ulong tuc_link;
2844 target_stack_t tuc_stack;
94c5495d 2845 target_ulong pad0;
60e99246
AJ
2846 struct target_sigcontext tuc_mcontext;
2847 target_sigset_t tuc_sigmask;
0b1bcb00
PB
2848};
2849
2850struct target_rt_sigframe {
2851 uint32_t rs_ass[4]; /* argument save space for o32 */
2852 uint32_t rs_code[2]; /* signal trampoline */
2853 struct target_siginfo rs_info;
2854 struct target_ucontext rs_uc;
2855};
2856
106ec879
FB
2857/* Install trampoline to jump back from signal handler */
2858static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2859{
084d0497 2860 int err = 0;
106ec879
FB
2861
2862 /*
084d0497
RH
2863 * Set up the return code ...
2864 *
2865 * li v0, __NR__foo_sigreturn
2866 * syscall
2867 */
106ec879 2868
1d8b512b
RV
2869 __put_user(0x24020000 + syscall, tramp + 0);
2870 __put_user(0x0000000c , tramp + 1);
106ec879
FB
2871 return err;
2872}
2873
41ecc72b 2874static inline void setup_sigcontext(CPUMIPSState *regs,
da7c8647 2875 struct target_sigcontext *sc)
106ec879 2876{
084d0497 2877 int i;
106ec879 2878
1d8b512b 2879 __put_user(exception_resume_pc(regs), &sc->sc_pc);
1239b472 2880 regs->hflags &= ~MIPS_HFLAG_BMASK;
106ec879 2881
084d0497
RH
2882 __put_user(0, &sc->sc_regs[0]);
2883 for (i = 1; i < 32; ++i) {
1d8b512b 2884 __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
084d0497 2885 }
106ec879 2886
1d8b512b
RV
2887 __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2888 __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
106ec879 2889
084d0497
RH
2890 /* Rather than checking for dsp existence, always copy. The storage
2891 would just be garbage otherwise. */
1d8b512b
RV
2892 __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
2893 __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
2894 __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
2895 __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
2896 __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
2897 __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
084d0497
RH
2898 {
2899 uint32_t dsp = cpu_rddsp(0x3ff, regs);
1d8b512b 2900 __put_user(dsp, &sc->sc_dsp);
106ec879 2901 }
106ec879 2902
1d8b512b 2903 __put_user(1, &sc->sc_used_math);
106ec879 2904
084d0497 2905 for (i = 0; i < 32; ++i) {
1d8b512b 2906 __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
106ec879 2907 }
106ec879
FB
2908}
2909
016d2e1d 2910static inline void
05390248 2911restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
106ec879 2912{
084d0497 2913 int i;
106ec879 2914
1d8b512b 2915 __get_user(regs->CP0_EPC, &sc->sc_pc);
106ec879 2916
1d8b512b
RV
2917 __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2918 __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
106ec879 2919
084d0497 2920 for (i = 1; i < 32; ++i) {
1d8b512b 2921 __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
106ec879 2922 }
106ec879 2923
1d8b512b
RV
2924 __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
2925 __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
2926 __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
2927 __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
2928 __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
2929 __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
084d0497
RH
2930 {
2931 uint32_t dsp;
1d8b512b 2932 __get_user(dsp, &sc->sc_dsp);
084d0497
RH
2933 cpu_wrdsp(dsp, 0x3ff, regs);
2934 }
106ec879 2935
084d0497 2936 for (i = 0; i < 32; ++i) {
1d8b512b 2937 __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
106ec879 2938 }
106ec879 2939}
ff970904 2940
106ec879
FB
2941/*
2942 * Determine which stack to use..
2943 */
579a97f7 2944static inline abi_ulong
05390248 2945get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
106ec879
FB
2946{
2947 unsigned long sp;
2948
2949 /* Default to using normal stack */
b5dc7732 2950 sp = regs->active_tc.gpr[29];
106ec879
FB
2951
2952 /*
93148aa5 2953 * FPU emulator may have its own trampoline active just
106ec879
FB
2954 * above the user stack, 16-bytes before the next lowest
2955 * 16 byte boundary. Try to avoid trashing it.
2956 */
2957 sp -= 32;
2958
106ec879 2959 /* This is the X/Open sanctioned signal stack switching. */
624f7979 2960 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
a04e134a
TS
2961 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2962 }
106ec879 2963
579a97f7 2964 return (sp - frame_size) & ~7;
106ec879
FB
2965}
2966
ea3164aa
KCY
2967static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
2968{
2969 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
2970 env->hflags &= ~MIPS_HFLAG_M16;
2971 env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT;
2972 env->active_tc.PC &= ~(target_ulong) 1;
2973 }
2974}
2975
ff970904 2976# if defined(TARGET_ABI_MIPSO32)
579a97f7 2977/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
624f7979 2978static void setup_frame(int sig, struct target_sigaction * ka,
05390248 2979 target_sigset_t *set, CPUMIPSState *regs)
106ec879
FB
2980{
2981 struct sigframe *frame;
579a97f7 2982 abi_ulong frame_addr;
106ec879
FB
2983 int i;
2984
579a97f7 2985 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
c8ee0a44 2986 trace_user_setup_frame(regs, frame_addr);
da7c8647
TB
2987 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
2988 goto give_sigsegv;
2989 }
106ec879
FB
2990
2991 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2992
41ecc72b 2993 setup_sigcontext(regs, &frame->sf_sc);
106ec879
FB
2994
2995 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
0188fadb 2996 __put_user(set->sig[i], &frame->sf_mask.sig[i]);
106ec879
FB
2997 }
2998
2999 /*
3000 * Arguments to signal handler:
3001 *
3002 * a0 = signal number
3003 * a1 = 0 (should be cause)
3004 * a2 = pointer to struct sigcontext
3005 *
3006 * $25 and PC point to the signal handler, $29 points to the
3007 * struct sigframe.
3008 */
b5dc7732
TS
3009 regs->active_tc.gpr[ 4] = sig;
3010 regs->active_tc.gpr[ 5] = 0;
3011 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
3012 regs->active_tc.gpr[29] = frame_addr;
3013 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
106ec879
FB
3014 /* The original kernel code sets CP0_EPC to the handler
3015 * since it returns to userland using eret
3016 * we cannot do this here, and we must set PC directly */
b5dc7732 3017 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
ea3164aa 3018 mips_set_hflags_isa_mode_from_pc(regs);
579a97f7 3019 unlock_user_struct(frame, frame_addr, 1);
106ec879
FB
3020 return;
3021
3022give_sigsegv:
3023 force_sig(TARGET_SIGSEGV/*, current*/);
106ec879
FB
3024}
3025
05390248 3026long do_sigreturn(CPUMIPSState *regs)
106ec879 3027{
388bb21a 3028 struct sigframe *frame;
579a97f7 3029 abi_ulong frame_addr;
388bb21a 3030 sigset_t blocked;
c227f099 3031 target_sigset_t target_set;
388bb21a 3032 int i;
106ec879 3033
b5dc7732 3034 frame_addr = regs->active_tc.gpr[29];
c8ee0a44 3035 trace_user_do_sigreturn(regs, frame_addr);
579a97f7 3036 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
da7c8647 3037 goto badframe;
106ec879 3038
388bb21a 3039 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
f5f601af 3040 __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
388bb21a 3041 }
106ec879 3042
388bb21a 3043 target_to_host_sigset_internal(&blocked, &target_set);
9eede5b6 3044 set_sigmask(&blocked);
106ec879 3045
016d2e1d 3046 restore_sigcontext(regs, &frame->sf_sc);
106ec879
FB
3047
3048#if 0
388bb21a
TS
3049 /*
3050 * Don't let your children do this ...
3051 */
3052 __asm__ __volatile__(
106ec879
FB
3053 "move\t$29, %0\n\t"
3054 "j\tsyscall_exit"
3055 :/* no outputs */
3056 :"r" (&regs));
388bb21a 3057 /* Unreached */
106ec879 3058#endif
3b46e624 3059
b5dc7732 3060 regs->active_tc.PC = regs->CP0_EPC;
ea3164aa 3061 mips_set_hflags_isa_mode_from_pc(regs);
388bb21a 3062 /* I am not sure this is right, but it seems to work
106ec879
FB
3063 * maybe a problem with nested signals ? */
3064 regs->CP0_EPC = 0;
0b1bcb00 3065 return -TARGET_QEMU_ESIGRETURN;
106ec879
FB
3066
3067badframe:
388bb21a
TS
3068 force_sig(TARGET_SIGSEGV/*, current*/);
3069 return 0;
106ec879 3070}
ff970904 3071# endif /* O32 */
106ec879 3072
624f7979 3073static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 3074 target_siginfo_t *info,
05390248 3075 target_sigset_t *set, CPUMIPSState *env)
106ec879 3076{
0b1bcb00
PB
3077 struct target_rt_sigframe *frame;
3078 abi_ulong frame_addr;
3079 int i;
3080
3081 frame_addr = get_sigframe(ka, env, sizeof(*frame));
c8ee0a44 3082 trace_user_setup_rt_frame(env, frame_addr);
da7c8647
TB
3083 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3084 goto give_sigsegv;
3085 }
0b1bcb00
PB
3086
3087 install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
3088
f6c7a05b 3089 tswap_siginfo(&frame->rs_info, info);
0b1bcb00 3090
60e99246
AJ
3091 __put_user(0, &frame->rs_uc.tuc_flags);
3092 __put_user(0, &frame->rs_uc.tuc_link);
3093 __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
3094 __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
0b1bcb00 3095 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
60e99246 3096 &frame->rs_uc.tuc_stack.ss_flags);
0b1bcb00 3097
60e99246 3098 setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
0b1bcb00
PB
3099
3100 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
60e99246 3101 __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
0b1bcb00
PB
3102 }
3103
3104 /*
3105 * Arguments to signal handler:
3106 *
3107 * a0 = signal number
02d2bd5d 3108 * a1 = pointer to siginfo_t
0b1bcb00
PB
3109 * a2 = pointer to struct ucontext
3110 *
3111 * $25 and PC point to the signal handler, $29 points to the
3112 * struct sigframe.
3113 */
3114 env->active_tc.gpr[ 4] = sig;
3115 env->active_tc.gpr[ 5] = frame_addr
3116 + offsetof(struct target_rt_sigframe, rs_info);
3117 env->active_tc.gpr[ 6] = frame_addr
3118 + offsetof(struct target_rt_sigframe, rs_uc);
3119 env->active_tc.gpr[29] = frame_addr;
3120 env->active_tc.gpr[31] = frame_addr
3121 + offsetof(struct target_rt_sigframe, rs_code);
3122 /* The original kernel code sets CP0_EPC to the handler
3123 * since it returns to userland using eret
3124 * we cannot do this here, and we must set PC directly */
3125 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
ea3164aa 3126 mips_set_hflags_isa_mode_from_pc(env);
0b1bcb00
PB
3127 unlock_user_struct(frame, frame_addr, 1);
3128 return;
3129
3130give_sigsegv:
3131 unlock_user_struct(frame, frame_addr, 1);
3132 force_sig(TARGET_SIGSEGV/*, current*/);
106ec879
FB
3133}
3134
05390248 3135long do_rt_sigreturn(CPUMIPSState *env)
106ec879 3136{
0b1bcb00
PB
3137 struct target_rt_sigframe *frame;
3138 abi_ulong frame_addr;
3139 sigset_t blocked;
3140
0b1bcb00 3141 frame_addr = env->active_tc.gpr[29];
c8ee0a44 3142 trace_user_do_rt_sigreturn(env, frame_addr);
da7c8647
TB
3143 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3144 goto badframe;
3145 }
0b1bcb00 3146
60e99246 3147 target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
9eede5b6 3148 set_sigmask(&blocked);
0b1bcb00 3149
016d2e1d 3150 restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
0b1bcb00
PB
3151
3152 if (do_sigaltstack(frame_addr +
da7c8647
TB
3153 offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
3154 0, get_sp_from_cpustate(env)) == -EFAULT)
0b1bcb00
PB
3155 goto badframe;
3156
3157 env->active_tc.PC = env->CP0_EPC;
ea3164aa 3158 mips_set_hflags_isa_mode_from_pc(env);
0b1bcb00
PB
3159 /* I am not sure this is right, but it seems to work
3160 * maybe a problem with nested signals ? */
3161 env->CP0_EPC = 0;
3162 return -TARGET_QEMU_ESIGRETURN;
3163
3164badframe:
3165 force_sig(TARGET_SIGSEGV/*, current*/);
3166 return 0;
106ec879 3167}
6d5e216d 3168
c3b5bc8a
TS
3169#elif defined(TARGET_SH4)
3170
3171/*
3172 * code and data structures from linux kernel:
3173 * include/asm-sh/sigcontext.h
3174 * arch/sh/kernel/signal.c
3175 */
3176
3177struct target_sigcontext {
3178 target_ulong oldmask;
3179
3180 /* CPU registers */
3181 target_ulong sc_gregs[16];
3182 target_ulong sc_pc;
3183 target_ulong sc_pr;
3184 target_ulong sc_sr;
3185 target_ulong sc_gbr;
3186 target_ulong sc_mach;
3187 target_ulong sc_macl;
3188
3189 /* FPU registers */
3190 target_ulong sc_fpregs[16];
3191 target_ulong sc_xfpregs[16];
3192 unsigned int sc_fpscr;
3193 unsigned int sc_fpul;
3194 unsigned int sc_ownedfp;
3195};
3196
3197struct target_sigframe
3198{
3199 struct target_sigcontext sc;
3200 target_ulong extramask[TARGET_NSIG_WORDS-1];
3201 uint16_t retcode[3];
3202};
3203
3204
3205struct target_ucontext {
60e99246
AJ
3206 target_ulong tuc_flags;
3207 struct target_ucontext *tuc_link;
3208 target_stack_t tuc_stack;
3209 struct target_sigcontext tuc_mcontext;
3210 target_sigset_t tuc_sigmask; /* mask last for extensibility */
c3b5bc8a
TS
3211};
3212
3213struct target_rt_sigframe
3214{
3215 struct target_siginfo info;
3216 struct target_ucontext uc;
3217 uint16_t retcode[3];
3218};
3219
3220
3221#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
3222#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
3223
624f7979 3224static abi_ulong get_sigframe(struct target_sigaction *ka,
da7c8647 3225 unsigned long sp, size_t frame_size)
c3b5bc8a 3226{
624f7979 3227 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
c3b5bc8a
TS
3228 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3229 }
3230
3231 return (sp - frame_size) & -8ul;
3232}
3233
41ecc72b 3234static void setup_sigcontext(struct target_sigcontext *sc,
da7c8647 3235 CPUSH4State *regs, unsigned long mask)
c3b5bc8a 3236{
d8714436 3237 int i;
c3b5bc8a 3238
1d8b512b 3239#define COPY(x) __put_user(regs->x, &sc->sc_##x)
c3b5bc8a
TS
3240 COPY(gregs[0]); COPY(gregs[1]);
3241 COPY(gregs[2]); COPY(gregs[3]);
3242 COPY(gregs[4]); COPY(gregs[5]);
3243 COPY(gregs[6]); COPY(gregs[7]);
3244 COPY(gregs[8]); COPY(gregs[9]);
3245 COPY(gregs[10]); COPY(gregs[11]);
3246 COPY(gregs[12]); COPY(gregs[13]);
3247 COPY(gregs[14]); COPY(gregs[15]);
3248 COPY(gbr); COPY(mach);
3249 COPY(macl); COPY(pr);
3250 COPY(sr); COPY(pc);
3251#undef COPY
3252
d8714436 3253 for (i=0; i<16; i++) {
1d8b512b 3254 __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
d8714436 3255 }
1d8b512b
RV
3256 __put_user(regs->fpscr, &sc->sc_fpscr);
3257 __put_user(regs->fpul, &sc->sc_fpul);
c3b5bc8a
TS
3258
3259 /* non-iBCS2 extensions.. */
1d8b512b 3260 __put_user(mask, &sc->oldmask);
c3b5bc8a
TS
3261}
3262
ba412496 3263static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
c3b5bc8a 3264{
d8714436 3265 int i;
c3b5bc8a 3266
1d8b512b 3267#define COPY(x) __get_user(regs->x, &sc->sc_##x)
ba412496 3268 COPY(gregs[0]); COPY(gregs[1]);
c3b5bc8a
TS
3269 COPY(gregs[2]); COPY(gregs[3]);
3270 COPY(gregs[4]); COPY(gregs[5]);
3271 COPY(gregs[6]); COPY(gregs[7]);
3272 COPY(gregs[8]); COPY(gregs[9]);
3273 COPY(gregs[10]); COPY(gregs[11]);
3274 COPY(gregs[12]); COPY(gregs[13]);
3275 COPY(gregs[14]); COPY(gregs[15]);
3276 COPY(gbr); COPY(mach);
3277 COPY(macl); COPY(pr);
3278 COPY(sr); COPY(pc);
3279#undef COPY
3280
d8714436 3281 for (i=0; i<16; i++) {
1d8b512b 3282 __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
d8714436 3283 }
1d8b512b
RV
3284 __get_user(regs->fpscr, &sc->sc_fpscr);
3285 __get_user(regs->fpul, &sc->sc_fpul);
c3b5bc8a
TS
3286
3287 regs->tra = -1; /* disable syscall checks */
c3b5bc8a
TS
3288}
3289
624f7979 3290static void setup_frame(int sig, struct target_sigaction *ka,
05390248 3291 target_sigset_t *set, CPUSH4State *regs)
c3b5bc8a
TS
3292{
3293 struct target_sigframe *frame;
3294 abi_ulong frame_addr;
3295 int i;
c3b5bc8a
TS
3296
3297 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
c8ee0a44 3298 trace_user_setup_frame(regs, frame_addr);
da7c8647
TB
3299 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3300 goto give_sigsegv;
3301 }
c3b5bc8a 3302
41ecc72b 3303 setup_sigcontext(&frame->sc, regs, set->sig[0]);
c3b5bc8a
TS
3304
3305 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
1d8b512b 3306 __put_user(set->sig[i + 1], &frame->extramask[i]);
c3b5bc8a
TS
3307 }
3308
3309 /* Set up to return from userspace. If provided, use a stub
3310 already in userspace. */
624f7979
PB
3311 if (ka->sa_flags & TARGET_SA_RESTORER) {
3312 regs->pr = (unsigned long) ka->sa_restorer;
c3b5bc8a
TS
3313 } else {
3314 /* Generate return code (system call to sigreturn) */
2a0fa68f
LV
3315 abi_ulong retcode_addr = frame_addr +
3316 offsetof(struct target_sigframe, retcode);
1d8b512b
RV
3317 __put_user(MOVW(2), &frame->retcode[0]);
3318 __put_user(TRAP_NOARG, &frame->retcode[1]);
3319 __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
2a0fa68f 3320 regs->pr = (unsigned long) retcode_addr;
c3b5bc8a
TS
3321 }
3322
c3b5bc8a 3323 /* Set up registers for signal handler */
cb9c6268 3324 regs->gregs[15] = frame_addr;
b6e2c935 3325 regs->gregs[4] = sig; /* Arg for signal handler */
c3b5bc8a 3326 regs->gregs[5] = 0;
cb9c6268 3327 regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
624f7979 3328 regs->pc = (unsigned long) ka->_sa_handler;
c3b5bc8a
TS
3329
3330 unlock_user_struct(frame, frame_addr, 1);
3331 return;
3332
3333give_sigsegv:
3334 unlock_user_struct(frame, frame_addr, 1);
66393fb9 3335 force_sig(TARGET_SIGSEGV);
c3b5bc8a
TS
3336}
3337
624f7979 3338static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 3339 target_siginfo_t *info,
05390248 3340 target_sigset_t *set, CPUSH4State *regs)
c3b5bc8a
TS
3341{
3342 struct target_rt_sigframe *frame;
3343 abi_ulong frame_addr;
3344 int i;
c3b5bc8a
TS
3345
3346 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
c8ee0a44 3347 trace_user_setup_rt_frame(regs, frame_addr);
da7c8647
TB
3348 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3349 goto give_sigsegv;
3350 }
c3b5bc8a 3351
f6c7a05b 3352 tswap_siginfo(&frame->info, info);
c3b5bc8a
TS
3353
3354 /* Create the ucontext. */
1d8b512b
RV
3355 __put_user(0, &frame->uc.tuc_flags);
3356 __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3357 __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3358 &frame->uc.tuc_stack.ss_sp);
3359 __put_user(sas_ss_flags(regs->gregs[15]),
3360 &frame->uc.tuc_stack.ss_flags);
3361 __put_user(target_sigaltstack_used.ss_size,
3362 &frame->uc.tuc_stack.ss_size);
3363 setup_sigcontext(&frame->uc.tuc_mcontext,
da7c8647 3364 regs, set->sig[0]);
c3b5bc8a 3365 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1d8b512b 3366 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
c3b5bc8a
TS
3367 }
3368
3369 /* Set up to return from userspace. If provided, use a stub
3370 already in userspace. */
624f7979
PB
3371 if (ka->sa_flags & TARGET_SA_RESTORER) {
3372 regs->pr = (unsigned long) ka->sa_restorer;
c3b5bc8a
TS
3373 } else {
3374 /* Generate return code (system call to sigreturn) */
2a0fa68f
LV
3375 abi_ulong retcode_addr = frame_addr +
3376 offsetof(struct target_rt_sigframe, retcode);
1d8b512b
RV
3377 __put_user(MOVW(2), &frame->retcode[0]);
3378 __put_user(TRAP_NOARG, &frame->retcode[1]);
3379 __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
2a0fa68f 3380 regs->pr = (unsigned long) retcode_addr;
c3b5bc8a
TS
3381 }
3382
c3b5bc8a 3383 /* Set up registers for signal handler */
cb9c6268 3384 regs->gregs[15] = frame_addr;
b6e2c935 3385 regs->gregs[4] = sig; /* Arg for signal handler */
cb9c6268
EI
3386 regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3387 regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
624f7979 3388 regs->pc = (unsigned long) ka->_sa_handler;
c3b5bc8a
TS
3389
3390 unlock_user_struct(frame, frame_addr, 1);
3391 return;
3392
3393give_sigsegv:
3394 unlock_user_struct(frame, frame_addr, 1);
66393fb9 3395 force_sig(TARGET_SIGSEGV);
c3b5bc8a
TS
3396}
3397
05390248 3398long do_sigreturn(CPUSH4State *regs)
c3b5bc8a
TS
3399{
3400 struct target_sigframe *frame;
3401 abi_ulong frame_addr;
3402 sigset_t blocked;
c227f099 3403 target_sigset_t target_set;
c3b5bc8a
TS
3404 int i;
3405 int err = 0;
3406
c3b5bc8a 3407 frame_addr = regs->gregs[15];
c8ee0a44 3408 trace_user_do_sigreturn(regs, frame_addr);
da7c8647
TB
3409 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3410 goto badframe;
3411 }
c3b5bc8a 3412
1d8b512b 3413 __get_user(target_set.sig[0], &frame->sc.oldmask);
c3b5bc8a 3414 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1d8b512b 3415 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
c3b5bc8a
TS
3416 }
3417
3418 if (err)
3419 goto badframe;
3420
3421 target_to_host_sigset_internal(&blocked, &target_set);
9eede5b6 3422 set_sigmask(&blocked);
c3b5bc8a 3423
ba412496 3424 restore_sigcontext(regs, &frame->sc);
c3b5bc8a
TS
3425
3426 unlock_user_struct(frame, frame_addr, 0);
ba412496 3427 return -TARGET_QEMU_ESIGRETURN;
c3b5bc8a
TS
3428
3429badframe:
3430 unlock_user_struct(frame, frame_addr, 0);
3431 force_sig(TARGET_SIGSEGV);
3432 return 0;
3433}
3434
05390248 3435long do_rt_sigreturn(CPUSH4State *regs)
c3b5bc8a
TS
3436{
3437 struct target_rt_sigframe *frame;
3438 abi_ulong frame_addr;
3439 sigset_t blocked;
3440
c3b5bc8a 3441 frame_addr = regs->gregs[15];
c8ee0a44 3442 trace_user_do_rt_sigreturn(regs, frame_addr);
da7c8647
TB
3443 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3444 goto badframe;
3445 }
c3b5bc8a 3446
60e99246 3447 target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
9eede5b6 3448 set_sigmask(&blocked);
c3b5bc8a 3449
ba412496 3450 restore_sigcontext(regs, &frame->uc.tuc_mcontext);
c3b5bc8a
TS
3451
3452 if (do_sigaltstack(frame_addr +
da7c8647
TB
3453 offsetof(struct target_rt_sigframe, uc.tuc_stack),
3454 0, get_sp_from_cpustate(regs)) == -EFAULT) {
c3b5bc8a 3455 goto badframe;
da7c8647 3456 }
c3b5bc8a
TS
3457
3458 unlock_user_struct(frame, frame_addr, 0);
ba412496 3459 return -TARGET_QEMU_ESIGRETURN;
c3b5bc8a
TS
3460
3461badframe:
3462 unlock_user_struct(frame, frame_addr, 0);
3463 force_sig(TARGET_SIGSEGV);
3464 return 0;
3465}
b779e29e
EI
3466#elif defined(TARGET_MICROBLAZE)
3467
3468struct target_sigcontext {
3469 struct target_pt_regs regs; /* needs to be first */
3470 uint32_t oldmask;
3471};
3472
b2178704
EI
3473struct target_stack_t {
3474 abi_ulong ss_sp;
3475 int ss_flags;
3476 unsigned int ss_size;
3477};
3478
3479struct target_ucontext {
f711df67
RH
3480 abi_ulong tuc_flags;
3481 abi_ulong tuc_link;
3482 struct target_stack_t tuc_stack;
3483 struct target_sigcontext tuc_mcontext;
3484 uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
b2178704
EI
3485};
3486
b779e29e
EI
3487/* Signal frames. */
3488struct target_signal_frame {
b2178704 3489 struct target_ucontext uc;
b779e29e
EI
3490 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3491 uint32_t tramp[2];
3492};
3493
3494struct rt_signal_frame {
02d2bd5d 3495 siginfo_t info;
b779e29e
EI
3496 struct ucontext uc;
3497 uint32_t tramp[2];
3498};
3499
05390248 3500static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
b779e29e
EI
3501{
3502 __put_user(env->regs[0], &sc->regs.r0);
3503 __put_user(env->regs[1], &sc->regs.r1);
3504 __put_user(env->regs[2], &sc->regs.r2);
3505 __put_user(env->regs[3], &sc->regs.r3);
3506 __put_user(env->regs[4], &sc->regs.r4);
3507 __put_user(env->regs[5], &sc->regs.r5);
3508 __put_user(env->regs[6], &sc->regs.r6);
3509 __put_user(env->regs[7], &sc->regs.r7);
3510 __put_user(env->regs[8], &sc->regs.r8);
3511 __put_user(env->regs[9], &sc->regs.r9);
3512 __put_user(env->regs[10], &sc->regs.r10);
3513 __put_user(env->regs[11], &sc->regs.r11);
3514 __put_user(env->regs[12], &sc->regs.r12);
3515 __put_user(env->regs[13], &sc->regs.r13);
3516 __put_user(env->regs[14], &sc->regs.r14);
3517 __put_user(env->regs[15], &sc->regs.r15);
3518 __put_user(env->regs[16], &sc->regs.r16);
3519 __put_user(env->regs[17], &sc->regs.r17);
3520 __put_user(env->regs[18], &sc->regs.r18);
3521 __put_user(env->regs[19], &sc->regs.r19);
3522 __put_user(env->regs[20], &sc->regs.r20);
3523 __put_user(env->regs[21], &sc->regs.r21);
3524 __put_user(env->regs[22], &sc->regs.r22);
3525 __put_user(env->regs[23], &sc->regs.r23);
3526 __put_user(env->regs[24], &sc->regs.r24);
3527 __put_user(env->regs[25], &sc->regs.r25);
3528 __put_user(env->regs[26], &sc->regs.r26);
3529 __put_user(env->regs[27], &sc->regs.r27);
3530 __put_user(env->regs[28], &sc->regs.r28);
3531 __put_user(env->regs[29], &sc->regs.r29);
3532 __put_user(env->regs[30], &sc->regs.r30);
3533 __put_user(env->regs[31], &sc->regs.r31);
3534 __put_user(env->sregs[SR_PC], &sc->regs.pc);
3535}
3536
05390248 3537static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
b779e29e
EI
3538{
3539 __get_user(env->regs[0], &sc->regs.r0);
3540 __get_user(env->regs[1], &sc->regs.r1);
3541 __get_user(env->regs[2], &sc->regs.r2);
3542 __get_user(env->regs[3], &sc->regs.r3);
3543 __get_user(env->regs[4], &sc->regs.r4);
3544 __get_user(env->regs[5], &sc->regs.r5);
3545 __get_user(env->regs[6], &sc->regs.r6);
3546 __get_user(env->regs[7], &sc->regs.r7);
3547 __get_user(env->regs[8], &sc->regs.r8);
3548 __get_user(env->regs[9], &sc->regs.r9);
3549 __get_user(env->regs[10], &sc->regs.r10);
3550 __get_user(env->regs[11], &sc->regs.r11);
3551 __get_user(env->regs[12], &sc->regs.r12);
3552 __get_user(env->regs[13], &sc->regs.r13);
3553 __get_user(env->regs[14], &sc->regs.r14);
3554 __get_user(env->regs[15], &sc->regs.r15);
3555 __get_user(env->regs[16], &sc->regs.r16);
3556 __get_user(env->regs[17], &sc->regs.r17);
3557 __get_user(env->regs[18], &sc->regs.r18);
3558 __get_user(env->regs[19], &sc->regs.r19);
3559 __get_user(env->regs[20], &sc->regs.r20);
3560 __get_user(env->regs[21], &sc->regs.r21);
3561 __get_user(env->regs[22], &sc->regs.r22);
3562 __get_user(env->regs[23], &sc->regs.r23);
3563 __get_user(env->regs[24], &sc->regs.r24);
3564 __get_user(env->regs[25], &sc->regs.r25);
3565 __get_user(env->regs[26], &sc->regs.r26);
3566 __get_user(env->regs[27], &sc->regs.r27);
3567 __get_user(env->regs[28], &sc->regs.r28);
3568 __get_user(env->regs[29], &sc->regs.r29);
3569 __get_user(env->regs[30], &sc->regs.r30);
3570 __get_user(env->regs[31], &sc->regs.r31);
3571 __get_user(env->sregs[SR_PC], &sc->regs.pc);
3572}
3573
3574static abi_ulong get_sigframe(struct target_sigaction *ka,
05390248 3575 CPUMBState *env, int frame_size)
b779e29e
EI
3576{
3577 abi_ulong sp = env->regs[1];
3578
b545f63f 3579 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) {
b779e29e 3580 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
b545f63f 3581 }
b779e29e
EI
3582
3583 return ((sp - frame_size) & -8UL);
3584}
3585
3586static void setup_frame(int sig, struct target_sigaction *ka,
05390248 3587 target_sigset_t *set, CPUMBState *env)
b779e29e
EI
3588{
3589 struct target_signal_frame *frame;
3590 abi_ulong frame_addr;
b779e29e
EI
3591 int i;
3592
3593 frame_addr = get_sigframe(ka, env, sizeof *frame);
c8ee0a44 3594 trace_user_setup_frame(env, frame_addr);
b779e29e
EI
3595 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3596 goto badframe;
3597
3598 /* Save the mask. */
1d8b512b 3599 __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
b779e29e
EI
3600
3601 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
0188fadb 3602 __put_user(set->sig[i], &frame->extramask[i - 1]);
b779e29e
EI
3603 }
3604
f711df67 3605 setup_sigcontext(&frame->uc.tuc_mcontext, env);
b779e29e
EI
3606
3607 /* Set up to return from userspace. If provided, use a stub
3608 already in userspace. */
3609 /* minus 8 is offset to cater for "rtsd r15,8" offset */
3610 if (ka->sa_flags & TARGET_SA_RESTORER) {
3611 env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3612 } else {
3613 uint32_t t;
3614 /* Note, these encodings are _big endian_! */
3615 /* addi r12, r0, __NR_sigreturn */
3616 t = 0x31800000UL | TARGET_NR_sigreturn;
1d8b512b 3617 __put_user(t, frame->tramp + 0);
b779e29e
EI
3618 /* brki r14, 0x8 */
3619 t = 0xb9cc0008UL;
1d8b512b 3620 __put_user(t, frame->tramp + 1);
b779e29e
EI
3621
3622 /* Return from sighandler will jump to the tramp.
3623 Negative 8 offset because return is rtsd r15, 8 */
166c97ed
CG
3624 env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
3625 - 8;
b779e29e
EI
3626 }
3627
b779e29e 3628 /* Set up registers for signal handler */
cb9c6268 3629 env->regs[1] = frame_addr;
b779e29e
EI
3630 /* Signal handler args: */
3631 env->regs[5] = sig; /* Arg 0: signum */
187b4e08 3632 env->regs[6] = 0;
cb9c6268
EI
3633 /* arg 1: sigcontext */
3634 env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
b779e29e
EI
3635
3636 /* Offset of 4 to handle microblaze rtid r14, 0 */
3637 env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3638
3639 unlock_user_struct(frame, frame_addr, 1);
3640 return;
da7c8647 3641badframe:
b779e29e
EI
3642 force_sig(TARGET_SIGSEGV);
3643}
3644
3645static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 3646 target_siginfo_t *info,
05390248 3647 target_sigset_t *set, CPUMBState *env)
b779e29e
EI
3648{
3649 fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3650}
3651
05390248 3652long do_sigreturn(CPUMBState *env)
b779e29e
EI
3653{
3654 struct target_signal_frame *frame;
3655 abi_ulong frame_addr;
c227f099 3656 target_sigset_t target_set;
b779e29e
EI
3657 sigset_t set;
3658 int i;
3659
3660 frame_addr = env->regs[R_SP];
c8ee0a44 3661 trace_user_do_sigreturn(env, frame_addr);
b779e29e
EI
3662 /* Make sure the guest isn't playing games. */
3663 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3664 goto badframe;
3665
3666 /* Restore blocked signals */
f5f601af 3667 __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
b779e29e 3668 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
da7c8647 3669 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
b779e29e
EI
3670 }
3671 target_to_host_sigset_internal(&set, &target_set);
9eede5b6 3672 set_sigmask(&set);
b779e29e 3673
f711df67 3674 restore_sigcontext(&frame->uc.tuc_mcontext, env);
b779e29e
EI
3675 /* We got here through a sigreturn syscall, our path back is via an
3676 rtb insn so setup r14 for that. */
3677 env->regs[14] = env->sregs[SR_PC];
da7c8647 3678
b779e29e 3679 unlock_user_struct(frame, frame_addr, 0);
4134ecfe 3680 return -TARGET_QEMU_ESIGRETURN;
da7c8647 3681badframe:
b779e29e
EI
3682 force_sig(TARGET_SIGSEGV);
3683}
3684
05390248 3685long do_rt_sigreturn(CPUMBState *env)
b779e29e 3686{
c8ee0a44 3687 trace_user_do_rt_sigreturn(env, 0);
b779e29e
EI
3688 fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3689 return -TARGET_ENOSYS;
3690}
3691
b6d3abda
EI
3692#elif defined(TARGET_CRIS)
3693
3694struct target_sigcontext {
da7c8647
TB
3695 struct target_pt_regs regs; /* needs to be first */
3696 uint32_t oldmask;
3697 uint32_t usp; /* usp before stacking this gunk on it */
b6d3abda
EI
3698};
3699
3700/* Signal frames. */
3701struct target_signal_frame {
da7c8647
TB
3702 struct target_sigcontext sc;
3703 uint32_t extramask[TARGET_NSIG_WORDS - 1];
3704 uint16_t retcode[4]; /* Trampoline code. */
b6d3abda
EI
3705};
3706
3707struct rt_signal_frame {
da7c8647
TB
3708 siginfo_t *pinfo;
3709 void *puc;
3710 siginfo_t info;
3711 struct ucontext uc;
3712 uint16_t retcode[4]; /* Trampoline code. */
b6d3abda
EI
3713};
3714
05390248 3715static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
b6d3abda 3716{
da7c8647
TB
3717 __put_user(env->regs[0], &sc->regs.r0);
3718 __put_user(env->regs[1], &sc->regs.r1);
3719 __put_user(env->regs[2], &sc->regs.r2);
3720 __put_user(env->regs[3], &sc->regs.r3);
3721 __put_user(env->regs[4], &sc->regs.r4);
3722 __put_user(env->regs[5], &sc->regs.r5);
3723 __put_user(env->regs[6], &sc->regs.r6);
3724 __put_user(env->regs[7], &sc->regs.r7);
3725 __put_user(env->regs[8], &sc->regs.r8);
3726 __put_user(env->regs[9], &sc->regs.r9);
3727 __put_user(env->regs[10], &sc->regs.r10);
3728 __put_user(env->regs[11], &sc->regs.r11);
3729 __put_user(env->regs[12], &sc->regs.r12);
3730 __put_user(env->regs[13], &sc->regs.r13);
3731 __put_user(env->regs[14], &sc->usp);
3732 __put_user(env->regs[15], &sc->regs.acr);
3733 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3734 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3735 __put_user(env->pc, &sc->regs.erp);
b6d3abda 3736}
9664d928 3737
05390248 3738static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
b6d3abda 3739{
da7c8647
TB
3740 __get_user(env->regs[0], &sc->regs.r0);
3741 __get_user(env->regs[1], &sc->regs.r1);
3742 __get_user(env->regs[2], &sc->regs.r2);
3743 __get_user(env->regs[3], &sc->regs.r3);
3744 __get_user(env->regs[4], &sc->regs.r4);
3745 __get_user(env->regs[5], &sc->regs.r5);
3746 __get_user(env->regs[6], &sc->regs.r6);
3747 __get_user(env->regs[7], &sc->regs.r7);
3748 __get_user(env->regs[8], &sc->regs.r8);
3749 __get_user(env->regs[9], &sc->regs.r9);
3750 __get_user(env->regs[10], &sc->regs.r10);
3751 __get_user(env->regs[11], &sc->regs.r11);
3752 __get_user(env->regs[12], &sc->regs.r12);
3753 __get_user(env->regs[13], &sc->regs.r13);
3754 __get_user(env->regs[14], &sc->usp);
3755 __get_user(env->regs[15], &sc->regs.acr);
3756 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3757 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3758 __get_user(env->pc, &sc->regs.erp);
9664d928
EI
3759}
3760
05390248 3761static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
9664d928 3762{
da7c8647
TB
3763 abi_ulong sp;
3764 /* Align the stack downwards to 4. */
3765 sp = (env->regs[R_SP] & ~3);
3766 return sp - framesize;
b6d3abda
EI
3767}
3768
624f7979 3769static void setup_frame(int sig, struct target_sigaction *ka,
05390248 3770 target_sigset_t *set, CPUCRISState *env)
b6d3abda 3771{
da7c8647
TB
3772 struct target_signal_frame *frame;
3773 abi_ulong frame_addr;
3774 int i;
3775
3776 frame_addr = get_sigframe(env, sizeof *frame);
3777 trace_user_setup_frame(env, frame_addr);
3778 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3779 goto badframe;
3780
3781 /*
3782 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3783 * use this trampoline anymore but it sets it up for GDB.
3784 * In QEMU, using the trampoline simplifies things a bit so we use it.
3785 *
3786 * This is movu.w __NR_sigreturn, r9; break 13;
3787 */
1d8b512b
RV
3788 __put_user(0x9c5f, frame->retcode+0);
3789 __put_user(TARGET_NR_sigreturn,
3790 frame->retcode + 1);
3791 __put_user(0xe93d, frame->retcode + 2);
b6d3abda 3792
da7c8647 3793 /* Save the mask. */
1d8b512b 3794 __put_user(set->sig[0], &frame->sc.oldmask);
b6d3abda 3795
0188fadb
RV
3796 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3797 __put_user(set->sig[i], &frame->extramask[i - 1]);
3798 }
b6d3abda 3799
da7c8647 3800 setup_sigcontext(&frame->sc, env);
b6d3abda 3801
da7c8647
TB
3802 /* Move the stack and setup the arguments for the handler. */
3803 env->regs[R_SP] = frame_addr;
3804 env->regs[10] = sig;
3805 env->pc = (unsigned long) ka->_sa_handler;
3806 /* Link SRP so the guest returns through the trampoline. */
3807 env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
b6d3abda 3808
da7c8647
TB
3809 unlock_user_struct(frame, frame_addr, 1);
3810 return;
3811badframe:
3812 force_sig(TARGET_SIGSEGV);
b6d3abda
EI
3813}
3814
624f7979 3815static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 3816 target_siginfo_t *info,
05390248 3817 target_sigset_t *set, CPUCRISState *env)
b6d3abda
EI
3818{
3819 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3820}
3821
05390248 3822long do_sigreturn(CPUCRISState *env)
b6d3abda 3823{
da7c8647
TB
3824 struct target_signal_frame *frame;
3825 abi_ulong frame_addr;
3826 target_sigset_t target_set;
3827 sigset_t set;
3828 int i;
b6d3abda 3829
da7c8647
TB
3830 frame_addr = env->regs[R_SP];
3831 trace_user_do_sigreturn(env, frame_addr);
3832 /* Make sure the guest isn't playing games. */
3833 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
3834 goto badframe;
3835 }
b6d3abda 3836
da7c8647 3837 /* Restore blocked signals */
f5f601af 3838 __get_user(target_set.sig[0], &frame->sc.oldmask);
da7c8647 3839 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
f5f601af 3840 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
da7c8647
TB
3841 }
3842 target_to_host_sigset_internal(&set, &target_set);
9eede5b6 3843 set_sigmask(&set);
b6d3abda 3844
da7c8647
TB
3845 restore_sigcontext(&frame->sc, env);
3846 unlock_user_struct(frame, frame_addr, 0);
62050865 3847 return -TARGET_QEMU_ESIGRETURN;
da7c8647
TB
3848badframe:
3849 force_sig(TARGET_SIGSEGV);
b6d3abda
EI
3850}
3851
05390248 3852long do_rt_sigreturn(CPUCRISState *env)
b6d3abda 3853{
c8ee0a44 3854 trace_user_do_rt_sigreturn(env, 0);
b6d3abda
EI
3855 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3856 return -TARGET_ENOSYS;
3857}
c3b5bc8a 3858
d962783e
JL
3859#elif defined(TARGET_OPENRISC)
3860
3861struct target_sigcontext {
3862 struct target_pt_regs regs;
3863 abi_ulong oldmask;
3864 abi_ulong usp;
3865};
3866
3867struct target_ucontext {
3868 abi_ulong tuc_flags;
3869 abi_ulong tuc_link;
3870 target_stack_t tuc_stack;
3871 struct target_sigcontext tuc_mcontext;
3872 target_sigset_t tuc_sigmask; /* mask last for extensibility */
3873};
3874
3875struct target_rt_sigframe {
3876 abi_ulong pinfo;
3877 uint64_t puc;
3878 struct target_siginfo info;
3879 struct target_sigcontext sc;
3880 struct target_ucontext uc;
3881 unsigned char retcode[16]; /* trampoline code */
3882};
3883
3884/* This is the asm-generic/ucontext.h version */
3885#if 0
3886static int restore_sigcontext(CPUOpenRISCState *regs,
3887 struct target_sigcontext *sc)
3888{
3889 unsigned int err = 0;
3890 unsigned long old_usp;
3891
3892 /* Alwys make any pending restarted system call return -EINTR */
3893 current_thread_info()->restart_block.fn = do_no_restart_syscall;
3894
3895 /* restore the regs from &sc->regs (same as sc, since regs is first)
3896 * (sc is already checked for VERIFY_READ since the sigframe was
3897 * checked in sys_sigreturn previously)
3898 */
3899
3900 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3901 goto badframe;
3902 }
3903
3904 /* make sure the U-flag is set so user-mode cannot fool us */
3905
3906 regs->sr &= ~SR_SM;
3907
3908 /* restore the old USP as it was before we stacked the sc etc.
3909 * (we cannot just pop the sigcontext since we aligned the sp and
3910 * stuff after pushing it)
3911 */
3912
1d8b512b 3913 __get_user(old_usp, &sc->usp);
d962783e
JL
3914 phx_signal("old_usp 0x%lx", old_usp);
3915
3916 __PHX__ REALLY /* ??? */
3917 wrusp(old_usp);
3918 regs->gpr[1] = old_usp;
3919
3920 /* TODO: the other ports use regs->orig_XX to disable syscall checks
3921 * after this completes, but we don't use that mechanism. maybe we can
3922 * use it now ?
3923 */
3924
3925 return err;
3926
3927badframe:
3928 return 1;
3929}
3930#endif
3931
3932/* Set up a signal frame. */
3933
41ecc72b 3934static void setup_sigcontext(struct target_sigcontext *sc,
da7c8647
TB
3935 CPUOpenRISCState *regs,
3936 unsigned long mask)
d962783e 3937{
d962783e
JL
3938 unsigned long usp = regs->gpr[1];
3939
3940 /* copy the regs. they are first in sc so we can use sc directly */
3941
1d8b512b 3942 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
d962783e
JL
3943
3944 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3945 the signal handler. The frametype will be restored to its previous
3946 value in restore_sigcontext. */
3947 /*regs->frametype = CRIS_FRAME_NORMAL;*/
3948
3949 /* then some other stuff */
1d8b512b 3950 __put_user(mask, &sc->oldmask);
41ecc72b 3951 __put_user(usp, &sc->usp);
d962783e
JL
3952}
3953
3954static inline unsigned long align_sigframe(unsigned long sp)
3955{
9be38598 3956 return sp & ~3UL;
d962783e
JL
3957}
3958
3959static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3960 CPUOpenRISCState *regs,
3961 size_t frame_size)
3962{
3963 unsigned long sp = regs->gpr[1];
3964 int onsigstack = on_sig_stack(sp);
3965
3966 /* redzone */
3967 /* This is the X/Open sanctioned signal stack switching. */
b545f63f 3968 if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) {
d962783e
JL
3969 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3970 }
3971
3972 sp = align_sigframe(sp - frame_size);
3973
3974 /*
3975 * If we are on the alternate signal stack and would overflow it, don't.
3976 * Return an always-bogus address instead so we will die with SIGSEGV.
3977 */
3978
3979 if (onsigstack && !likely(on_sig_stack(sp))) {
3980 return -1L;
3981 }
3982
3983 return sp;
3984}
3985
d962783e
JL
3986static void setup_rt_frame(int sig, struct target_sigaction *ka,
3987 target_siginfo_t *info,
3988 target_sigset_t *set, CPUOpenRISCState *env)
3989{
3990 int err = 0;
3991 abi_ulong frame_addr;
3992 unsigned long return_ip;
3993 struct target_rt_sigframe *frame;
3994 abi_ulong info_addr, uc_addr;
3995
d962783e 3996 frame_addr = get_sigframe(ka, env, sizeof(*frame));
c8ee0a44 3997 trace_user_setup_rt_frame(env, frame_addr);
d962783e
JL
3998 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3999 goto give_sigsegv;
4000 }
4001
4002 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
1d8b512b 4003 __put_user(info_addr, &frame->pinfo);
d962783e 4004 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
1d8b512b 4005 __put_user(uc_addr, &frame->puc);
d962783e
JL
4006
4007 if (ka->sa_flags & SA_SIGINFO) {
f6c7a05b 4008 tswap_siginfo(&frame->info, info);
d962783e
JL
4009 }
4010
4011 /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
1d8b512b
RV
4012 __put_user(0, &frame->uc.tuc_flags);
4013 __put_user(0, &frame->uc.tuc_link);
4014 __put_user(target_sigaltstack_used.ss_sp,
4015 &frame->uc.tuc_stack.ss_sp);
4016 __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
4017 __put_user(target_sigaltstack_used.ss_size,
4018 &frame->uc.tuc_stack.ss_size);
41ecc72b 4019 setup_sigcontext(&frame->sc, env, set->sig[0]);
d962783e
JL
4020
4021 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
4022
d962783e
JL
4023 /* trampoline - the desired return ip is the retcode itself */
4024 return_ip = (unsigned long)&frame->retcode;
4025 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
1d8b512b
RV
4026 __put_user(0xa960, (short *)(frame->retcode + 0));
4027 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
4028 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
4029 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
d962783e
JL
4030
4031 if (err) {
4032 goto give_sigsegv;
4033 }
4034
4035 /* TODO what is the current->exec_domain stuff and invmap ? */
4036
4037 /* Set up registers for signal handler */
4038 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
4039 env->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
4040 env->gpr[3] = (unsigned long)sig; /* arg 1: signo */
4041 env->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
4042 env->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
4043
4044 /* actually move the usp to reflect the stacked frame */
4045 env->gpr[1] = (unsigned long)frame;
4046
4047 return;
4048
4049give_sigsegv:
4050 unlock_user_struct(frame, frame_addr, 1);
4051 if (sig == TARGET_SIGSEGV) {
4052 ka->_sa_handler = TARGET_SIG_DFL;
4053 }
4054 force_sig(TARGET_SIGSEGV);
4055}
4056
4057long do_sigreturn(CPUOpenRISCState *env)
4058{
c8ee0a44
PB
4059 trace_user_do_sigreturn(env, 0);
4060 fprintf(stderr, "do_sigreturn: not implemented\n");
d962783e
JL
4061 return -TARGET_ENOSYS;
4062}
4063
4064long do_rt_sigreturn(CPUOpenRISCState *env)
4065{
c8ee0a44
PB
4066 trace_user_do_rt_sigreturn(env, 0);
4067 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
d962783e
JL
4068 return -TARGET_ENOSYS;
4069}
4070/* TARGET_OPENRISC */
4071
a4c075f1
UH
4072#elif defined(TARGET_S390X)
4073
4074#define __NUM_GPRS 16
4075#define __NUM_FPRS 16
4076#define __NUM_ACRS 16
4077
4078#define S390_SYSCALL_SIZE 2
4079#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */
4080
4081#define _SIGCONTEXT_NSIG 64
4082#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */
4083#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
4084#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
4085#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */
4086#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
4087
4088typedef struct {
4089 target_psw_t psw;
4090 target_ulong gprs[__NUM_GPRS];
4091 unsigned int acrs[__NUM_ACRS];
4092} target_s390_regs_common;
4093
4094typedef struct {
4095 unsigned int fpc;
4096 double fprs[__NUM_FPRS];
4097} target_s390_fp_regs;
4098
4099typedef struct {
4100 target_s390_regs_common regs;
4101 target_s390_fp_regs fpregs;
4102} target_sigregs;
4103
4104struct target_sigcontext {
4105 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS];
4106 target_sigregs *sregs;
4107};
4108
4109typedef struct {
4110 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4111 struct target_sigcontext sc;
4112 target_sigregs sregs;
4113 int signo;
4114 uint8_t retcode[S390_SYSCALL_SIZE];
4115} sigframe;
4116
4117struct target_ucontext {
6fea2ea4
PM
4118 target_ulong tuc_flags;
4119 struct target_ucontext *tuc_link;
4120 target_stack_t tuc_stack;
4121 target_sigregs tuc_mcontext;
4122 target_sigset_t tuc_sigmask; /* mask last for extensibility */
a4c075f1
UH
4123};
4124
4125typedef struct {
4126 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
4127 uint8_t retcode[S390_SYSCALL_SIZE];
4128 struct target_siginfo info;
4129 struct target_ucontext uc;
4130} rt_sigframe;
4131
4132static inline abi_ulong
05390248 4133get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
a4c075f1
UH
4134{
4135 abi_ulong sp;
4136
4137 /* Default to using normal stack */
4138 sp = env->regs[15];
4139
4140 /* This is the X/Open sanctioned signal stack switching. */
4141 if (ka->sa_flags & TARGET_SA_ONSTACK) {
4142 if (!sas_ss_flags(sp)) {
4143 sp = target_sigaltstack_used.ss_sp +
4144 target_sigaltstack_used.ss_size;
4145 }
4146 }
4147
4148 /* This is the legacy signal stack switching. */
4149 else if (/* FIXME !user_mode(regs) */ 0 &&
4150 !(ka->sa_flags & TARGET_SA_RESTORER) &&
4151 ka->sa_restorer) {
4152 sp = (abi_ulong) ka->sa_restorer;
4153 }
4154
4155 return (sp - frame_size) & -8ul;
4156}
4157
05390248 4158static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
a4c075f1
UH
4159{
4160 int i;
4161 //save_access_regs(current->thread.acrs); FIXME
4162
4163 /* Copy a 'clean' PSW mask to the user to avoid leaking
4164 information about whether PER is currently on. */
4165 __put_user(env->psw.mask, &sregs->regs.psw.mask);
4166 __put_user(env->psw.addr, &sregs->regs.psw.addr);
4167 for (i = 0; i < 16; i++) {
4168 __put_user(env->regs[i], &sregs->regs.gprs[i]);
4169 }
4170 for (i = 0; i < 16; i++) {
4171 __put_user(env->aregs[i], &sregs->regs.acrs[i]);
4172 }
4173 /*
4174 * We have to store the fp registers to current->thread.fp_regs
4175 * to merge them with the emulated registers.
4176 */
4177 //save_fp_regs(&current->thread.fp_regs); FIXME
4178 for (i = 0; i < 16; i++) {
c498d8e3 4179 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]);
a4c075f1
UH
4180 }
4181}
4182
4183static void setup_frame(int sig, struct target_sigaction *ka,
05390248 4184 target_sigset_t *set, CPUS390XState *env)
a4c075f1
UH
4185{
4186 sigframe *frame;
4187 abi_ulong frame_addr;
4188
4189 frame_addr = get_sigframe(ka, env, sizeof(*frame));
c8ee0a44 4190 trace_user_setup_frame(env, frame_addr);
a4c075f1 4191 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
da7c8647 4192 goto give_sigsegv;
a4c075f1
UH
4193 }
4194
0188fadb 4195 __put_user(set->sig[0], &frame->sc.oldmask[0]);
a4c075f1
UH
4196
4197 save_sigregs(env, &frame->sregs);
4198
4199 __put_user((abi_ulong)(unsigned long)&frame->sregs,
4200 (abi_ulong *)&frame->sc.sregs);
4201
4202 /* Set up to return from userspace. If provided, use a stub
4203 already in userspace. */
4204 if (ka->sa_flags & TARGET_SA_RESTORER) {
da7c8647
TB
4205 env->regs[14] = (unsigned long)
4206 ka->sa_restorer | PSW_ADDR_AMODE;
a4c075f1 4207 } else {
5b1d59d0
CG
4208 env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
4209 | PSW_ADDR_AMODE;
da7c8647
TB
4210 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4211 (uint16_t *)(frame->retcode));
a4c075f1
UH
4212 }
4213
4214 /* Set up backchain. */
0188fadb 4215 __put_user(env->regs[15], (abi_ulong *) frame);
a4c075f1
UH
4216
4217 /* Set up registers for signal handler */
cb9c6268 4218 env->regs[15] = frame_addr;
a4c075f1
UH
4219 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4220
4221 env->regs[2] = sig; //map_signal(sig);
cb9c6268 4222 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
a4c075f1
UH
4223
4224 /* We forgot to include these in the sigcontext.
4225 To avoid breaking binary compatibility, they are passed as args. */
4226 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4227 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4228
4229 /* Place signal number on stack to allow backtrace from handler. */
0188fadb 4230 __put_user(env->regs[2], (int *) &frame->signo);
a4c075f1
UH
4231 unlock_user_struct(frame, frame_addr, 1);
4232 return;
4233
4234give_sigsegv:
a4c075f1
UH
4235 force_sig(TARGET_SIGSEGV);
4236}
4237
4238static void setup_rt_frame(int sig, struct target_sigaction *ka,
4239 target_siginfo_t *info,
05390248 4240 target_sigset_t *set, CPUS390XState *env)
a4c075f1
UH
4241{
4242 int i;
4243 rt_sigframe *frame;
4244 abi_ulong frame_addr;
4245
4246 frame_addr = get_sigframe(ka, env, sizeof *frame);
c8ee0a44 4247 trace_user_setup_rt_frame(env, frame_addr);
a4c075f1
UH
4248 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4249 goto give_sigsegv;
4250 }
4251
f6c7a05b 4252 tswap_siginfo(&frame->info, info);
a4c075f1
UH
4253
4254 /* Create the ucontext. */
6fea2ea4
PM
4255 __put_user(0, &frame->uc.tuc_flags);
4256 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4257 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
a4c075f1 4258 __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
da7c8647 4259 &frame->uc.tuc_stack.ss_flags);
6fea2ea4
PM
4260 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4261 save_sigregs(env, &frame->uc.tuc_mcontext);
a4c075f1
UH
4262 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4263 __put_user((abi_ulong)set->sig[i],
da7c8647 4264 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
a4c075f1
UH
4265 }
4266
4267 /* Set up to return from userspace. If provided, use a stub
4268 already in userspace. */
4269 if (ka->sa_flags & TARGET_SA_RESTORER) {
4270 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4271 } else {
4272 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
0188fadb
RV
4273 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4274 (uint16_t *)(frame->retcode));
a4c075f1
UH
4275 }
4276
4277 /* Set up backchain. */
0188fadb 4278 __put_user(env->regs[15], (abi_ulong *) frame);
a4c075f1
UH
4279
4280 /* Set up registers for signal handler */
cb9c6268 4281 env->regs[15] = frame_addr;
a4c075f1
UH
4282 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4283
4284 env->regs[2] = sig; //map_signal(sig);
cb9c6268
EI
4285 env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4286 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
a4c075f1
UH
4287 return;
4288
4289give_sigsegv:
a4c075f1
UH
4290 force_sig(TARGET_SIGSEGV);
4291}
4292
4293static int
05390248 4294restore_sigregs(CPUS390XState *env, target_sigregs *sc)
a4c075f1
UH
4295{
4296 int err = 0;
4297 int i;
4298
4299 for (i = 0; i < 16; i++) {
1d8b512b 4300 __get_user(env->regs[i], &sc->regs.gprs[i]);
a4c075f1
UH
4301 }
4302
1d8b512b 4303 __get_user(env->psw.mask, &sc->regs.psw.mask);
c8ee0a44
PB
4304 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr,
4305 (unsigned long long)env->psw.addr);
1d8b512b 4306 __get_user(env->psw.addr, &sc->regs.psw.addr);
a4c075f1
UH
4307 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4308
4309 for (i = 0; i < 16; i++) {
1d8b512b 4310 __get_user(env->aregs[i], &sc->regs.acrs[i]);
a4c075f1
UH
4311 }
4312 for (i = 0; i < 16; i++) {
c498d8e3 4313 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]);
a4c075f1
UH
4314 }
4315
4316 return err;
4317}
4318
05390248 4319long do_sigreturn(CPUS390XState *env)
a4c075f1
UH
4320{
4321 sigframe *frame;
4322 abi_ulong frame_addr = env->regs[15];
a4c075f1
UH
4323 target_sigset_t target_set;
4324 sigset_t set;
4325
c8ee0a44 4326 trace_user_do_sigreturn(env, frame_addr);
a4c075f1
UH
4327 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4328 goto badframe;
4329 }
f5f601af 4330 __get_user(target_set.sig[0], &frame->sc.oldmask[0]);
a4c075f1
UH
4331
4332 target_to_host_sigset_internal(&set, &target_set);
9eede5b6 4333 set_sigmask(&set); /* ~_BLOCKABLE? */
a4c075f1
UH
4334
4335 if (restore_sigregs(env, &frame->sregs)) {
4336 goto badframe;
4337 }
4338
4339 unlock_user_struct(frame, frame_addr, 0);
47405ab6 4340 return -TARGET_QEMU_ESIGRETURN;
a4c075f1
UH
4341
4342badframe:
a4c075f1
UH
4343 force_sig(TARGET_SIGSEGV);
4344 return 0;
4345}
4346
05390248 4347long do_rt_sigreturn(CPUS390XState *env)
a4c075f1
UH
4348{
4349 rt_sigframe *frame;
4350 abi_ulong frame_addr = env->regs[15];
a4c075f1
UH
4351 sigset_t set;
4352
c8ee0a44 4353 trace_user_do_rt_sigreturn(env, frame_addr);
a4c075f1
UH
4354 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4355 goto badframe;
4356 }
6fea2ea4 4357 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
a4c075f1 4358
9eede5b6 4359 set_sigmask(&set); /* ~_BLOCKABLE? */
a4c075f1 4360
6fea2ea4 4361 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
a4c075f1
UH
4362 goto badframe;
4363 }
4364
6fea2ea4 4365 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
a4c075f1
UH
4366 get_sp_from_cpustate(env)) == -EFAULT) {
4367 goto badframe;
4368 }
4369 unlock_user_struct(frame, frame_addr, 0);
47405ab6 4370 return -TARGET_QEMU_ESIGRETURN;
a4c075f1
UH
4371
4372badframe:
4373 unlock_user_struct(frame, frame_addr, 0);
4374 force_sig(TARGET_SIGSEGV);
4375 return 0;
4376}
4377
61e75fec 4378#elif defined(TARGET_PPC)
bcd4933a
NF
4379
4380/* Size of dummy stack frame allocated when calling signal handler.
4381 See arch/powerpc/include/asm/ptrace.h. */
4382#if defined(TARGET_PPC64)
4383#define SIGNAL_FRAMESIZE 128
4384#else
4385#define SIGNAL_FRAMESIZE 64
4386#endif
4387
61e75fec
TM
4388/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
4389 on 64-bit PPC, sigcontext and mcontext are one and the same. */
4390struct target_mcontext {
4391 target_ulong mc_gregs[48];
4392 /* Includes fpscr. */
4393 uint64_t mc_fregs[33];
4394 target_ulong mc_pad[2];
4395 /* We need to handle Altivec and SPE at the same time, which no
4396 kernel needs to do. Fortunately, the kernel defines this bit to
4397 be Altivec-register-large all the time, rather than trying to
4398 twiddle it based on the specific platform. */
4399 union {
4400 /* SPE vector registers. One extra for SPEFSCR. */
4401 uint32_t spe[33];
4402 /* Altivec vector registers. The packing of VSCR and VRSAVE
4403 varies depending on whether we're PPC64 or not: PPC64 splits
4404 them apart; PPC32 stuffs them together. */
4405#if defined(TARGET_PPC64)
4406#define QEMU_NVRREG 34
4407#else
4408#define QEMU_NVRREG 33
4409#endif
4410 ppc_avr_t altivec[QEMU_NVRREG];
4411#undef QEMU_NVRREG
4412 } mc_vregs __attribute__((__aligned__(16)));
4413};
4414
bcd4933a
NF
4415/* See arch/powerpc/include/asm/sigcontext.h. */
4416struct target_sigcontext {
4417 target_ulong _unused[4];
4418 int32_t signal;
4419#if defined(TARGET_PPC64)
4420 int32_t pad0;
4421#endif
4422 target_ulong handler;
4423 target_ulong oldmask;
4424 target_ulong regs; /* struct pt_regs __user * */
61e75fec
TM
4425#if defined(TARGET_PPC64)
4426 struct target_mcontext mcontext;
4427#endif
bcd4933a
NF
4428};
4429
4430/* Indices for target_mcontext.mc_gregs, below.
4431 See arch/powerpc/include/asm/ptrace.h for details. */
4432enum {
4433 TARGET_PT_R0 = 0,
4434 TARGET_PT_R1 = 1,
4435 TARGET_PT_R2 = 2,
4436 TARGET_PT_R3 = 3,
4437 TARGET_PT_R4 = 4,
4438 TARGET_PT_R5 = 5,
4439 TARGET_PT_R6 = 6,
4440 TARGET_PT_R7 = 7,
4441 TARGET_PT_R8 = 8,
4442 TARGET_PT_R9 = 9,
4443 TARGET_PT_R10 = 10,
4444 TARGET_PT_R11 = 11,
4445 TARGET_PT_R12 = 12,
4446 TARGET_PT_R13 = 13,
4447 TARGET_PT_R14 = 14,
4448 TARGET_PT_R15 = 15,
4449 TARGET_PT_R16 = 16,
4450 TARGET_PT_R17 = 17,
4451 TARGET_PT_R18 = 18,
4452 TARGET_PT_R19 = 19,
4453 TARGET_PT_R20 = 20,
4454 TARGET_PT_R21 = 21,
4455 TARGET_PT_R22 = 22,
4456 TARGET_PT_R23 = 23,
4457 TARGET_PT_R24 = 24,
4458 TARGET_PT_R25 = 25,
4459 TARGET_PT_R26 = 26,
4460 TARGET_PT_R27 = 27,
4461 TARGET_PT_R28 = 28,
4462 TARGET_PT_R29 = 29,
4463 TARGET_PT_R30 = 30,
4464 TARGET_PT_R31 = 31,
4465 TARGET_PT_NIP = 32,
4466 TARGET_PT_MSR = 33,
4467 TARGET_PT_ORIG_R3 = 34,
4468 TARGET_PT_CTR = 35,
4469 TARGET_PT_LNK = 36,
4470 TARGET_PT_XER = 37,
4471 TARGET_PT_CCR = 38,
4472 /* Yes, there are two registers with #39. One is 64-bit only. */
4473 TARGET_PT_MQ = 39,
4474 TARGET_PT_SOFTE = 39,
4475 TARGET_PT_TRAP = 40,
4476 TARGET_PT_DAR = 41,
4477 TARGET_PT_DSISR = 42,
4478 TARGET_PT_RESULT = 43,
4479 TARGET_PT_REGS_COUNT = 44
4480};
4481
bcd4933a
NF
4482
4483struct target_ucontext {
60e99246
AJ
4484 target_ulong tuc_flags;
4485 target_ulong tuc_link; /* struct ucontext __user * */
4486 struct target_sigaltstack tuc_stack;
bcd4933a 4487#if !defined(TARGET_PPC64)
60e99246
AJ
4488 int32_t tuc_pad[7];
4489 target_ulong tuc_regs; /* struct mcontext __user *
bcd4933a
NF
4490 points to uc_mcontext field */
4491#endif
60e99246 4492 target_sigset_t tuc_sigmask;
bcd4933a 4493#if defined(TARGET_PPC64)
c227f099 4494 target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
61e75fec 4495 struct target_sigcontext tuc_sigcontext;
bcd4933a 4496#else
60e99246
AJ
4497 int32_t tuc_maskext[30];
4498 int32_t tuc_pad2[3];
4499 struct target_mcontext tuc_mcontext;
bcd4933a
NF
4500#endif
4501};
4502
4503/* See arch/powerpc/kernel/signal_32.c. */
4504struct target_sigframe {
4505 struct target_sigcontext sctx;
4506 struct target_mcontext mctx;
4507 int32_t abigap[56];
4508};
4509
61e75fec
TM
4510#if defined(TARGET_PPC64)
4511
4512#define TARGET_TRAMP_SIZE 6
4513
4514struct target_rt_sigframe {
da7c8647
TB
4515 /* sys_rt_sigreturn requires the ucontext be the first field */
4516 struct target_ucontext uc;
4517 target_ulong _unused[2];
4518 uint32_t trampoline[TARGET_TRAMP_SIZE];
4519 target_ulong pinfo; /* struct siginfo __user * */
4520 target_ulong puc; /* void __user * */
4521 struct target_siginfo info;
4522 /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
4523 char abigap[288];
61e75fec
TM
4524} __attribute__((aligned(16)));
4525
4526#else
4527
bcd4933a
NF
4528struct target_rt_sigframe {
4529 struct target_siginfo info;
4530 struct target_ucontext uc;
4531 int32_t abigap[56];
4532};
4533
61e75fec
TM
4534#endif
4535
8d6ab333
TM
4536#if defined(TARGET_PPC64)
4537
4538struct target_func_ptr {
4539 target_ulong entry;
4540 target_ulong toc;
4541};
4542
4543#endif
4544
bcd4933a
NF
4545/* We use the mc_pad field for the signal return trampoline. */
4546#define tramp mc_pad
4547
4548/* See arch/powerpc/kernel/signal.c. */
4549static target_ulong get_sigframe(struct target_sigaction *ka,
05390248 4550 CPUPPCState *env,
bcd4933a
NF
4551 int frame_size)
4552{
9be38598 4553 target_ulong oldsp;
bcd4933a
NF
4554
4555 oldsp = env->gpr[1];
4556
4557 if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
da7c8647 4558 (sas_ss_flags(oldsp) == 0)) {
bcd4933a
NF
4559 oldsp = (target_sigaltstack_used.ss_sp
4560 + target_sigaltstack_used.ss_size);
4561 }
4562
9be38598 4563 return (oldsp - frame_size) & ~0xFUL;
bcd4933a
NF
4564}
4565
7678108b 4566static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
bcd4933a
NF
4567{
4568 target_ulong msr = env->msr;
4569 int i;
4570 target_ulong ccr = 0;
4571
4572 /* In general, the kernel attempts to be intelligent about what it
4573 needs to save for Altivec/FP/SPE registers. We don't care that
4574 much, so we just go ahead and save everything. */
4575
4576 /* Save general registers. */
4577 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
da7c8647 4578 __put_user(env->gpr[i], &frame->mc_gregs[i]);
bcd4933a 4579 }
c650c008
RV
4580 __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4581 __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4582 __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4583 __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
bcd4933a
NF
4584
4585 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4586 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4587 }
c650c008 4588 __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
bcd4933a
NF
4589
4590 /* Save Altivec registers if necessary. */
4591 if (env->insns_flags & PPC_ALTIVEC) {
4592 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
c227f099
AL
4593 ppc_avr_t *avr = &env->avr[i];
4594 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
bcd4933a 4595
c650c008
RV
4596 __put_user(avr->u64[0], &vreg->u64[0]);
4597 __put_user(avr->u64[1], &vreg->u64[1]);
bcd4933a
NF
4598 }
4599 /* Set MSR_VR in the saved MSR value to indicate that
4600 frame->mc_vregs contains valid data. */
4601 msr |= MSR_VR;
c650c008
RV
4602 __put_user((uint32_t)env->spr[SPR_VRSAVE],
4603 &frame->mc_vregs.altivec[32].u32[3]);
bcd4933a
NF
4604 }
4605
4606 /* Save floating point registers. */
4607 if (env->insns_flags & PPC_FLOAT) {
4608 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
c650c008 4609 __put_user(env->fpr[i], &frame->mc_fregs[i]);
bcd4933a 4610 }
c650c008 4611 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]);
bcd4933a
NF
4612 }
4613
4614 /* Save SPE registers. The kernel only saves the high half. */
4615 if (env->insns_flags & PPC_SPE) {
4616#if defined(TARGET_PPC64)
4617 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
c650c008 4618 __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]);
bcd4933a
NF
4619 }
4620#else
4621 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
c650c008 4622 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]);
bcd4933a
NF
4623 }
4624#endif
4625 /* Set MSR_SPE in the saved MSR value to indicate that
4626 frame->mc_vregs contains valid data. */
4627 msr |= MSR_SPE;
c650c008 4628 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
bcd4933a
NF
4629 }
4630
4631 /* Store MSR. */
c650c008 4632 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
7678108b 4633}
bcd4933a 4634
7678108b
TM
4635static void encode_trampoline(int sigret, uint32_t *tramp)
4636{
bcd4933a
NF
4637 /* Set up the sigreturn trampoline: li r0,sigret; sc. */
4638 if (sigret) {
7678108b
TM
4639 __put_user(0x38000000 | sigret, &tramp[0]);
4640 __put_user(0x44000002, &tramp[1]);
bcd4933a 4641 }
bcd4933a
NF
4642}
4643
c650c008
RV
4644static void restore_user_regs(CPUPPCState *env,
4645 struct target_mcontext *frame, int sig)
bcd4933a
NF
4646{
4647 target_ulong save_r2 = 0;
4648 target_ulong msr;
4649 target_ulong ccr;
4650
4651 int i;
4652
4653 if (!sig) {
4654 save_r2 = env->gpr[2];
4655 }
4656
4657 /* Restore general registers. */
4658 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
c650c008 4659 __get_user(env->gpr[i], &frame->mc_gregs[i]);
bcd4933a 4660 }
c650c008
RV
4661 __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
4662 __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
4663 __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]);
4664 __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]);
4665 __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]);
bcd4933a
NF
4666
4667 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4668 env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4669 }
4670
4671 if (!sig) {
4672 env->gpr[2] = save_r2;
4673 }
4674 /* Restore MSR. */
c650c008 4675 __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]);
bcd4933a
NF
4676
4677 /* If doing signal return, restore the previous little-endian mode. */
4678 if (sig)
49e55cba 4679 env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
bcd4933a
NF
4680
4681 /* Restore Altivec registers if necessary. */
4682 if (env->insns_flags & PPC_ALTIVEC) {
4683 for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
c227f099
AL
4684 ppc_avr_t *avr = &env->avr[i];
4685 ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
bcd4933a 4686
c650c008
RV
4687 __get_user(avr->u64[0], &vreg->u64[0]);
4688 __get_user(avr->u64[1], &vreg->u64[1]);
bcd4933a
NF
4689 }
4690 /* Set MSR_VEC in the saved MSR value to indicate that
4691 frame->mc_vregs contains valid data. */
c650c008
RV
4692 __get_user(env->spr[SPR_VRSAVE],
4693 (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3]));
bcd4933a
NF
4694 }
4695
4696 /* Restore floating point registers. */
4697 if (env->insns_flags & PPC_FLOAT) {
4698 uint64_t fpscr;
4699 for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
c650c008 4700 __get_user(env->fpr[i], &frame->mc_fregs[i]);
bcd4933a 4701 }
c650c008 4702 __get_user(fpscr, &frame->mc_fregs[32]);
bcd4933a
NF
4703 env->fpscr = (uint32_t) fpscr;
4704 }
4705
4706 /* Save SPE registers. The kernel only saves the high half. */
4707 if (env->insns_flags & PPC_SPE) {
4708#if defined(TARGET_PPC64)
4709 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4710 uint32_t hi;
4711
c650c008 4712 __get_user(hi, &frame->mc_vregs.spe[i]);
bcd4933a
NF
4713 env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4714 }
4715#else
4716 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
c650c008 4717 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]);
bcd4933a
NF
4718 }
4719#endif
c650c008 4720 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]);
bcd4933a 4721 }
bcd4933a
NF
4722}
4723
4724static void setup_frame(int sig, struct target_sigaction *ka,
05390248 4725 target_sigset_t *set, CPUPPCState *env)
bcd4933a
NF
4726{
4727 struct target_sigframe *frame;
4728 struct target_sigcontext *sc;
4729 target_ulong frame_addr, newsp;
4730 int err = 0;
14585580
TM
4731#if defined(TARGET_PPC64)
4732 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4733#endif
bcd4933a
NF
4734
4735 frame_addr = get_sigframe(ka, env, sizeof(*frame));
c8ee0a44 4736 trace_user_setup_frame(env, frame_addr);
bcd4933a
NF
4737 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4738 goto sigsegv;
4739 sc = &frame->sctx;
4740
1d8b512b
RV
4741 __put_user(ka->_sa_handler, &sc->handler);
4742 __put_user(set->sig[0], &sc->oldmask);
61e75fec 4743#if TARGET_ABI_BITS == 64
1d8b512b 4744 __put_user(set->sig[0] >> 32, &sc->_unused[3]);
bcd4933a 4745#else
1d8b512b 4746 __put_user(set->sig[1], &sc->_unused[3]);
bcd4933a 4747#endif
1d8b512b
RV
4748 __put_user(h2g(&frame->mctx), &sc->regs);
4749 __put_user(sig, &sc->signal);
bcd4933a
NF
4750
4751 /* Save user regs. */
7678108b
TM
4752 save_user_regs(env, &frame->mctx);
4753
4754 /* Construct the trampoline code on the stack. */
4755 encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
bcd4933a
NF
4756
4757 /* The kernel checks for the presence of a VDSO here. We don't
4758 emulate a vdso, so use a sigreturn system call. */
4759 env->lr = (target_ulong) h2g(frame->mctx.tramp);
4760
4761 /* Turn off all fp exceptions. */
4762 env->fpscr = 0;
4763
4764 /* Create a stack frame for the caller of the handler. */
4765 newsp = frame_addr - SIGNAL_FRAMESIZE;
beb526b1 4766 err |= put_user(env->gpr[1], newsp, target_ulong);
bcd4933a
NF
4767
4768 if (err)
4769 goto sigsegv;
4770
4771 /* Set up registers for signal handler. */
4772 env->gpr[1] = newsp;
b6e2c935 4773 env->gpr[3] = sig;
61993a67 4774 env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
8d6ab333
TM
4775
4776#if defined(TARGET_PPC64)
14585580
TM
4777 if (get_ppc64_abi(image) < 2) {
4778 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4779 struct target_func_ptr *handler =
4780 (struct target_func_ptr *)g2h(ka->_sa_handler);
4781 env->nip = tswapl(handler->entry);
4782 env->gpr[2] = tswapl(handler->toc);
4783 } else {
4784 /* ELFv2 PPC64 function pointers are entry points, but R12
4785 * must also be set */
4786 env->nip = tswapl((target_ulong) ka->_sa_handler);
4787 env->gpr[12] = env->nip;
4788 }
8d6ab333 4789#else
bcd4933a 4790 env->nip = (target_ulong) ka->_sa_handler;
8d6ab333
TM
4791#endif
4792
bcd4933a 4793 /* Signal handlers are entered in big-endian mode. */
49e55cba 4794 env->msr &= ~(1ull << MSR_LE);
bcd4933a
NF
4795
4796 unlock_user_struct(frame, frame_addr, 1);
4797 return;
4798
4799sigsegv:
4800 unlock_user_struct(frame, frame_addr, 1);
66393fb9 4801 force_sig(TARGET_SIGSEGV);
bcd4933a
NF
4802}
4803
4804static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 4805 target_siginfo_t *info,
05390248 4806 target_sigset_t *set, CPUPPCState *env)
bcd4933a
NF
4807{
4808 struct target_rt_sigframe *rt_sf;
61e75fec
TM
4809 uint32_t *trampptr = 0;
4810 struct target_mcontext *mctx = 0;
bcd4933a
NF
4811 target_ulong rt_sf_addr, newsp = 0;
4812 int i, err = 0;
14585580
TM
4813#if defined(TARGET_PPC64)
4814 struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
4815#endif
bcd4933a
NF
4816
4817 rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4818 if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4819 goto sigsegv;
4820
f6c7a05b 4821 tswap_siginfo(&rt_sf->info, info);
bcd4933a 4822
1d8b512b
RV
4823 __put_user(0, &rt_sf->uc.tuc_flags);
4824 __put_user(0, &rt_sf->uc.tuc_link);
4825 __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4826 &rt_sf->uc.tuc_stack.ss_sp);
4827 __put_user(sas_ss_flags(env->gpr[1]),
4828 &rt_sf->uc.tuc_stack.ss_flags);
4829 __put_user(target_sigaltstack_used.ss_size,
4830 &rt_sf->uc.tuc_stack.ss_size);
61e75fec 4831#if !defined(TARGET_PPC64)
1d8b512b
RV
4832 __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4833 &rt_sf->uc.tuc_regs);
61e75fec 4834#endif
bcd4933a 4835 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1d8b512b 4836 __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
bcd4933a
NF
4837 }
4838
61e75fec
TM
4839#if defined(TARGET_PPC64)
4840 mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
4841 trampptr = &rt_sf->trampoline[0];
4842#else
4843 mctx = &rt_sf->uc.tuc_mcontext;
4844 trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
4845#endif
4846
4847 save_user_regs(env, mctx);
4848 encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
bcd4933a
NF
4849
4850 /* The kernel checks for the presence of a VDSO here. We don't
4851 emulate a vdso, so use a sigreturn system call. */
61e75fec 4852 env->lr = (target_ulong) h2g(trampptr);
bcd4933a
NF
4853
4854 /* Turn off all fp exceptions. */
4855 env->fpscr = 0;
4856
4857 /* Create a stack frame for the caller of the handler. */
4858 newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
fbdc200a 4859 err |= put_user(env->gpr[1], newsp, target_ulong);
bcd4933a
NF
4860
4861 if (err)
4862 goto sigsegv;
4863
4864 /* Set up registers for signal handler. */
4865 env->gpr[1] = newsp;
b6e2c935 4866 env->gpr[3] = (target_ulong) sig;
bcd4933a
NF
4867 env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4868 env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4869 env->gpr[6] = (target_ulong) h2g(rt_sf);
8d6ab333
TM
4870
4871#if defined(TARGET_PPC64)
14585580
TM
4872 if (get_ppc64_abi(image) < 2) {
4873 /* ELFv1 PPC64 function pointers are pointers to OPD entries. */
4874 struct target_func_ptr *handler =
4875 (struct target_func_ptr *)g2h(ka->_sa_handler);
4876 env->nip = tswapl(handler->entry);
4877 env->gpr[2] = tswapl(handler->toc);
4878 } else {
4879 /* ELFv2 PPC64 function pointers are entry points, but R12
4880 * must also be set */
4881 env->nip = tswapl((target_ulong) ka->_sa_handler);
4882 env->gpr[12] = env->nip;
4883 }
8d6ab333 4884#else
bcd4933a 4885 env->nip = (target_ulong) ka->_sa_handler;
8d6ab333
TM
4886#endif
4887
bcd4933a 4888 /* Signal handlers are entered in big-endian mode. */
49e55cba 4889 env->msr &= ~(1ull << MSR_LE);
bcd4933a
NF
4890
4891 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4892 return;
4893
4894sigsegv:
4895 unlock_user_struct(rt_sf, rt_sf_addr, 1);
66393fb9 4896 force_sig(TARGET_SIGSEGV);
bcd4933a
NF
4897
4898}
4899
05390248 4900long do_sigreturn(CPUPPCState *env)
bcd4933a
NF
4901{
4902 struct target_sigcontext *sc = NULL;
4903 struct target_mcontext *sr = NULL;
b04636f8 4904 target_ulong sr_addr = 0, sc_addr;
bcd4933a 4905 sigset_t blocked;
c227f099 4906 target_sigset_t set;
bcd4933a
NF
4907
4908 sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4909 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4910 goto sigsegv;
4911
4912#if defined(TARGET_PPC64)
61e75fec 4913 set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32);
bcd4933a 4914#else
f5f601af
RV
4915 __get_user(set.sig[0], &sc->oldmask);
4916 __get_user(set.sig[1], &sc->_unused[3]);
bcd4933a
NF
4917#endif
4918 target_to_host_sigset_internal(&blocked, &set);
9eede5b6 4919 set_sigmask(&blocked);
bcd4933a 4920
f5f601af 4921 __get_user(sr_addr, &sc->regs);
bcd4933a
NF
4922 if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4923 goto sigsegv;
c650c008 4924 restore_user_regs(env, sr, 1);
bcd4933a
NF
4925
4926 unlock_user_struct(sr, sr_addr, 1);
4927 unlock_user_struct(sc, sc_addr, 1);
4928 return -TARGET_QEMU_ESIGRETURN;
4929
4930sigsegv:
4931 unlock_user_struct(sr, sr_addr, 1);
4932 unlock_user_struct(sc, sc_addr, 1);
66393fb9 4933 force_sig(TARGET_SIGSEGV);
bcd4933a
NF
4934 return 0;
4935}
4936
4937/* See arch/powerpc/kernel/signal_32.c. */
05390248 4938static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
bcd4933a
NF
4939{
4940 struct target_mcontext *mcp;
4941 target_ulong mcp_addr;
4942 sigset_t blocked;
c227f099 4943 target_sigset_t set;
bcd4933a 4944
60e99246 4945 if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
bcd4933a
NF
4946 sizeof (set)))
4947 return 1;
4948
19774ec5
TM
4949#if defined(TARGET_PPC64)
4950 mcp_addr = h2g(ucp) +
4951 offsetof(struct target_ucontext, tuc_sigcontext.mcontext);
4952#else
9e918dc9 4953 __get_user(mcp_addr, &ucp->tuc_regs);
19774ec5 4954#endif
bcd4933a
NF
4955
4956 if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4957 return 1;
4958
4959 target_to_host_sigset_internal(&blocked, &set);
9eede5b6 4960 set_sigmask(&blocked);
c650c008 4961 restore_user_regs(env, mcp, sig);
bcd4933a
NF
4962
4963 unlock_user_struct(mcp, mcp_addr, 1);
4964 return 0;
bcd4933a
NF
4965}
4966
05390248 4967long do_rt_sigreturn(CPUPPCState *env)
bcd4933a
NF
4968{
4969 struct target_rt_sigframe *rt_sf = NULL;
4970 target_ulong rt_sf_addr;
4971
4972 rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4973 if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4974 goto sigsegv;
4975
4976 if (do_setcontext(&rt_sf->uc, env, 1))
4977 goto sigsegv;
4978
4979 do_sigaltstack(rt_sf_addr
60e99246 4980 + offsetof(struct target_rt_sigframe, uc.tuc_stack),
bcd4933a
NF
4981 0, env->gpr[1]);
4982
4983 unlock_user_struct(rt_sf, rt_sf_addr, 1);
4984 return -TARGET_QEMU_ESIGRETURN;
4985
4986sigsegv:
4987 unlock_user_struct(rt_sf, rt_sf_addr, 1);
66393fb9 4988 force_sig(TARGET_SIGSEGV);
bcd4933a
NF
4989 return 0;
4990}
4991
492a8744
LV
4992#elif defined(TARGET_M68K)
4993
4994struct target_sigcontext {
4995 abi_ulong sc_mask;
4996 abi_ulong sc_usp;
4997 abi_ulong sc_d0;
4998 abi_ulong sc_d1;
4999 abi_ulong sc_a0;
5000 abi_ulong sc_a1;
5001 unsigned short sc_sr;
5002 abi_ulong sc_pc;
5003};
5004
5005struct target_sigframe
5006{
5007 abi_ulong pretcode;
5008 int sig;
5009 int code;
5010 abi_ulong psc;
5011 char retcode[8];
5012 abi_ulong extramask[TARGET_NSIG_WORDS-1];
5013 struct target_sigcontext sc;
5014};
da7c8647 5015
c227f099 5016typedef int target_greg_t;
7181155d 5017#define TARGET_NGREG 18
c227f099 5018typedef target_greg_t target_gregset_t[TARGET_NGREG];
7181155d
LV
5019
5020typedef struct target_fpregset {
5021 int f_fpcntl[3];
5022 int f_fpregs[8*3];
c227f099 5023} target_fpregset_t;
7181155d
LV
5024
5025struct target_mcontext {
5026 int version;
c227f099
AL
5027 target_gregset_t gregs;
5028 target_fpregset_t fpregs;
7181155d
LV
5029};
5030
5031#define TARGET_MCONTEXT_VERSION 2
5032
5033struct target_ucontext {
60e99246
AJ
5034 abi_ulong tuc_flags;
5035 abi_ulong tuc_link;
5036 target_stack_t tuc_stack;
5037 struct target_mcontext tuc_mcontext;
5038 abi_long tuc_filler[80];
5039 target_sigset_t tuc_sigmask;
7181155d
LV
5040};
5041
5042struct target_rt_sigframe
5043{
5044 abi_ulong pretcode;
5045 int sig;
5046 abi_ulong pinfo;
5047 abi_ulong puc;
5048 char retcode[8];
5049 struct target_siginfo info;
5050 struct target_ucontext uc;
5051};
492a8744 5052
41ecc72b 5053static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
da7c8647 5054 abi_ulong mask)
492a8744 5055{
1d8b512b
RV
5056 __put_user(mask, &sc->sc_mask);
5057 __put_user(env->aregs[7], &sc->sc_usp);
5058 __put_user(env->dregs[0], &sc->sc_d0);
5059 __put_user(env->dregs[1], &sc->sc_d1);
5060 __put_user(env->aregs[0], &sc->sc_a0);
5061 __put_user(env->aregs[1], &sc->sc_a1);
5062 __put_user(env->sr, &sc->sc_sr);
5063 __put_user(env->pc, &sc->sc_pc);
492a8744
LV
5064}
5065
016d2e1d 5066static void
7ccb84a9 5067restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
492a8744 5068{
492a8744
LV
5069 int temp;
5070
1d8b512b 5071 __get_user(env->aregs[7], &sc->sc_usp);
7ccb84a9 5072 __get_user(env->dregs[0], &sc->sc_d0);
1d8b512b
RV
5073 __get_user(env->dregs[1], &sc->sc_d1);
5074 __get_user(env->aregs[0], &sc->sc_a0);
5075 __get_user(env->aregs[1], &sc->sc_a1);
5076 __get_user(env->pc, &sc->sc_pc);
5077 __get_user(temp, &sc->sc_sr);
492a8744 5078 env->sr = (env->sr & 0xff00) | (temp & 0xff);
492a8744
LV
5079}
5080
5081/*
5082 * Determine which stack to use..
5083 */
5084static inline abi_ulong
05390248
AF
5085get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
5086 size_t frame_size)
492a8744
LV
5087{
5088 unsigned long sp;
5089
5090 sp = regs->aregs[7];
5091
5092 /* This is the X/Open sanctioned signal stack switching. */
5093 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
5094 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5095 }
5096
5097 return ((sp - frame_size) & -8UL);
5098}
5099
5100static void setup_frame(int sig, struct target_sigaction *ka,
05390248 5101 target_sigset_t *set, CPUM68KState *env)
492a8744
LV
5102{
5103 struct target_sigframe *frame;
5104 abi_ulong frame_addr;
5105 abi_ulong retcode_addr;
5106 abi_ulong sc_addr;
492a8744
LV
5107 int i;
5108
5109 frame_addr = get_sigframe(ka, env, sizeof *frame);
c8ee0a44 5110 trace_user_setup_frame(env, frame_addr);
da7c8647
TB
5111 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5112 goto give_sigsegv;
5113 }
492a8744 5114
1d8b512b 5115 __put_user(sig, &frame->sig);
492a8744
LV
5116
5117 sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
1d8b512b 5118 __put_user(sc_addr, &frame->psc);
492a8744 5119
41ecc72b 5120 setup_sigcontext(&frame->sc, env, set->sig[0]);
492a8744
LV
5121
5122 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
0188fadb 5123 __put_user(set->sig[i], &frame->extramask[i - 1]);
492a8744
LV
5124 }
5125
5126 /* Set up to return from userspace. */
5127
5128 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
1d8b512b 5129 __put_user(retcode_addr, &frame->pretcode);
492a8744
LV
5130
5131 /* moveq #,d0; trap #0 */
5132
1d8b512b 5133 __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
da7c8647 5134 (uint32_t *)(frame->retcode));
492a8744 5135
492a8744
LV
5136 /* Set up to return from userspace */
5137
5138 env->aregs[7] = frame_addr;
5139 env->pc = ka->_sa_handler;
5140
5141 unlock_user_struct(frame, frame_addr, 1);
5142 return;
5143
5144give_sigsegv:
66393fb9 5145 force_sig(TARGET_SIGSEGV);
492a8744
LV
5146}
5147
7181155d 5148static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
05390248 5149 CPUM68KState *env)
7181155d 5150{
60e99246 5151 target_greg_t *gregs = uc->tuc_mcontext.gregs;
7181155d 5152
1d8b512b
RV
5153 __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
5154 __put_user(env->dregs[0], &gregs[0]);
5155 __put_user(env->dregs[1], &gregs[1]);
5156 __put_user(env->dregs[2], &gregs[2]);
5157 __put_user(env->dregs[3], &gregs[3]);
5158 __put_user(env->dregs[4], &gregs[4]);
5159 __put_user(env->dregs[5], &gregs[5]);
5160 __put_user(env->dregs[6], &gregs[6]);
5161 __put_user(env->dregs[7], &gregs[7]);
5162 __put_user(env->aregs[0], &gregs[8]);
5163 __put_user(env->aregs[1], &gregs[9]);
5164 __put_user(env->aregs[2], &gregs[10]);
5165 __put_user(env->aregs[3], &gregs[11]);
5166 __put_user(env->aregs[4], &gregs[12]);
5167 __put_user(env->aregs[5], &gregs[13]);
5168 __put_user(env->aregs[6], &gregs[14]);
5169 __put_user(env->aregs[7], &gregs[15]);
5170 __put_user(env->pc, &gregs[16]);
5171 __put_user(env->sr, &gregs[17]);
7181155d 5172
1d8b512b 5173 return 0;
7181155d 5174}
da7c8647 5175
05390248 5176static inline int target_rt_restore_ucontext(CPUM68KState *env,
7ccb84a9 5177 struct target_ucontext *uc)
7181155d
LV
5178{
5179 int temp;
60e99246 5180 target_greg_t *gregs = uc->tuc_mcontext.gregs;
7181155d 5181
1d8b512b 5182 __get_user(temp, &uc->tuc_mcontext.version);
7181155d
LV
5183 if (temp != TARGET_MCONTEXT_VERSION)
5184 goto badframe;
5185
5186 /* restore passed registers */
1d8b512b
RV
5187 __get_user(env->dregs[0], &gregs[0]);
5188 __get_user(env->dregs[1], &gregs[1]);
5189 __get_user(env->dregs[2], &gregs[2]);
5190 __get_user(env->dregs[3], &gregs[3]);
5191 __get_user(env->dregs[4], &gregs[4]);
5192 __get_user(env->dregs[5], &gregs[5]);
5193 __get_user(env->dregs[6], &gregs[6]);
5194 __get_user(env->dregs[7], &gregs[7]);
5195 __get_user(env->aregs[0], &gregs[8]);
5196 __get_user(env->aregs[1], &gregs[9]);
5197 __get_user(env->aregs[2], &gregs[10]);
5198 __get_user(env->aregs[3], &gregs[11]);
5199 __get_user(env->aregs[4], &gregs[12]);
5200 __get_user(env->aregs[5], &gregs[13]);
5201 __get_user(env->aregs[6], &gregs[14]);
5202 __get_user(env->aregs[7], &gregs[15]);
5203 __get_user(env->pc, &gregs[16]);
5204 __get_user(temp, &gregs[17]);
7181155d
LV
5205 env->sr = (env->sr & 0xff00) | (temp & 0xff);
5206
1d8b512b 5207 return 0;
7181155d
LV
5208
5209badframe:
5210 return 1;
5211}
5212
492a8744 5213static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 5214 target_siginfo_t *info,
05390248 5215 target_sigset_t *set, CPUM68KState *env)
492a8744 5216{
7181155d
LV
5217 struct target_rt_sigframe *frame;
5218 abi_ulong frame_addr;
5219 abi_ulong retcode_addr;
5220 abi_ulong info_addr;
5221 abi_ulong uc_addr;
5222 int err = 0;
5223 int i;
5224
5225 frame_addr = get_sigframe(ka, env, sizeof *frame);
c8ee0a44 5226 trace_user_setup_rt_frame(env, frame_addr);
da7c8647
TB
5227 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5228 goto give_sigsegv;
5229 }
7181155d 5230
1d8b512b 5231 __put_user(sig, &frame->sig);
7181155d
LV
5232
5233 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
1d8b512b 5234 __put_user(info_addr, &frame->pinfo);
7181155d
LV
5235
5236 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
1d8b512b 5237 __put_user(uc_addr, &frame->puc);
7181155d 5238
f6c7a05b 5239 tswap_siginfo(&frame->info, info);
7181155d
LV
5240
5241 /* Create the ucontext */
5242
1d8b512b
RV
5243 __put_user(0, &frame->uc.tuc_flags);
5244 __put_user(0, &frame->uc.tuc_link);
5245 __put_user(target_sigaltstack_used.ss_sp,
5246 &frame->uc.tuc_stack.ss_sp);
5247 __put_user(sas_ss_flags(env->aregs[7]),
da7c8647 5248 &frame->uc.tuc_stack.ss_flags);
1d8b512b
RV
5249 __put_user(target_sigaltstack_used.ss_size,
5250 &frame->uc.tuc_stack.ss_size);
7181155d
LV
5251 err |= target_rt_setup_ucontext(&frame->uc, env);
5252
5253 if (err)
da7c8647 5254 goto give_sigsegv;
7181155d
LV
5255
5256 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
0188fadb 5257 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
7181155d
LV
5258 }
5259
5260 /* Set up to return from userspace. */
5261
5262 retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
1d8b512b 5263 __put_user(retcode_addr, &frame->pretcode);
7181155d
LV
5264
5265 /* moveq #,d0; notb d0; trap #0 */
5266
1d8b512b 5267 __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
1669add7
PM
5268 (uint32_t *)(frame->retcode + 0));
5269 __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
7181155d
LV
5270
5271 if (err)
5272 goto give_sigsegv;
5273
5274 /* Set up to return from userspace */
5275
5276 env->aregs[7] = frame_addr;
5277 env->pc = ka->_sa_handler;
5278
5279 unlock_user_struct(frame, frame_addr, 1);
5280 return;
5281
5282give_sigsegv:
5283 unlock_user_struct(frame, frame_addr, 1);
66393fb9 5284 force_sig(TARGET_SIGSEGV);
492a8744
LV
5285}
5286
05390248 5287long do_sigreturn(CPUM68KState *env)
492a8744
LV
5288{
5289 struct target_sigframe *frame;
5290 abi_ulong frame_addr = env->aregs[7] - 4;
c227f099 5291 target_sigset_t target_set;
492a8744 5292 sigset_t set;
7ccb84a9 5293 int i;
492a8744 5294
c8ee0a44 5295 trace_user_do_sigreturn(env, frame_addr);
492a8744
LV
5296 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5297 goto badframe;
5298
5299 /* set blocked signals */
5300
f5f601af 5301 __get_user(target_set.sig[0], &frame->sc.sc_mask);
492a8744
LV
5302
5303 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
f5f601af 5304 __get_user(target_set.sig[i], &frame->extramask[i - 1]);
492a8744
LV
5305 }
5306
5307 target_to_host_sigset_internal(&set, &target_set);
9eede5b6 5308 set_sigmask(&set);
492a8744
LV
5309
5310 /* restore registers */
5311
7ccb84a9 5312 restore_sigcontext(env, &frame->sc);
492a8744
LV
5313
5314 unlock_user_struct(frame, frame_addr, 0);
7ccb84a9 5315 return -TARGET_QEMU_ESIGRETURN;
492a8744
LV
5316
5317badframe:
492a8744
LV
5318 force_sig(TARGET_SIGSEGV);
5319 return 0;
5320}
5321
05390248 5322long do_rt_sigreturn(CPUM68KState *env)
492a8744 5323{
7181155d
LV
5324 struct target_rt_sigframe *frame;
5325 abi_ulong frame_addr = env->aregs[7] - 4;
c227f099 5326 target_sigset_t target_set;
7181155d 5327 sigset_t set;
7181155d 5328
c8ee0a44 5329 trace_user_do_rt_sigreturn(env, frame_addr);
7181155d
LV
5330 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5331 goto badframe;
5332
5333 target_to_host_sigset_internal(&set, &target_set);
9eede5b6 5334 set_sigmask(&set);
7181155d
LV
5335
5336 /* restore registers */
5337
7ccb84a9 5338 if (target_rt_restore_ucontext(env, &frame->uc))
7181155d
LV
5339 goto badframe;
5340
5341 if (do_sigaltstack(frame_addr +
60e99246 5342 offsetof(struct target_rt_sigframe, uc.tuc_stack),
7181155d
LV
5343 0, get_sp_from_cpustate(env)) == -EFAULT)
5344 goto badframe;
5345
5346 unlock_user_struct(frame, frame_addr, 0);
7ccb84a9 5347 return -TARGET_QEMU_ESIGRETURN;
7181155d
LV
5348
5349badframe:
5350 unlock_user_struct(frame, frame_addr, 0);
5351 force_sig(TARGET_SIGSEGV);
5352 return 0;
492a8744
LV
5353}
5354
6049f4f8
RH
5355#elif defined(TARGET_ALPHA)
5356
5357struct target_sigcontext {
5358 abi_long sc_onstack;
5359 abi_long sc_mask;
5360 abi_long sc_pc;
5361 abi_long sc_ps;
5362 abi_long sc_regs[32];
5363 abi_long sc_ownedfp;
5364 abi_long sc_fpregs[32];
5365 abi_ulong sc_fpcr;
5366 abi_ulong sc_fp_control;
5367 abi_ulong sc_reserved1;
5368 abi_ulong sc_reserved2;
5369 abi_ulong sc_ssize;
5370 abi_ulong sc_sbase;
5371 abi_ulong sc_traparg_a0;
5372 abi_ulong sc_traparg_a1;
5373 abi_ulong sc_traparg_a2;
5374 abi_ulong sc_fp_trap_pc;
5375 abi_ulong sc_fp_trigger_sum;
5376 abi_ulong sc_fp_trigger_inst;
5377};
5378
5379struct target_ucontext {
60e99246
AJ
5380 abi_ulong tuc_flags;
5381 abi_ulong tuc_link;
5382 abi_ulong tuc_osf_sigmask;
5383 target_stack_t tuc_stack;
5384 struct target_sigcontext tuc_mcontext;
5385 target_sigset_t tuc_sigmask;
6049f4f8
RH
5386};
5387
5388struct target_sigframe {
5389 struct target_sigcontext sc;
5390 unsigned int retcode[3];
5391};
5392
5393struct target_rt_sigframe {
5394 target_siginfo_t info;
5395 struct target_ucontext uc;
5396 unsigned int retcode[3];
5397};
5398
5399#define INSN_MOV_R30_R16 0x47fe0410
5400#define INSN_LDI_R0 0x201f0000
5401#define INSN_CALLSYS 0x00000083
5402
41ecc72b 5403static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
da7c8647 5404 abi_ulong frame_addr, target_sigset_t *set)
6049f4f8 5405{
41ecc72b 5406 int i;
6049f4f8 5407
1d8b512b
RV
5408 __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5409 __put_user(set->sig[0], &sc->sc_mask);
5410 __put_user(env->pc, &sc->sc_pc);
5411 __put_user(8, &sc->sc_ps);
6049f4f8
RH
5412
5413 for (i = 0; i < 31; ++i) {
1d8b512b 5414 __put_user(env->ir[i], &sc->sc_regs[i]);
6049f4f8 5415 }
1d8b512b 5416 __put_user(0, &sc->sc_regs[31]);
6049f4f8
RH
5417
5418 for (i = 0; i < 31; ++i) {
1d8b512b 5419 __put_user(env->fir[i], &sc->sc_fpregs[i]);
6049f4f8 5420 }
1d8b512b
RV
5421 __put_user(0, &sc->sc_fpregs[31]);
5422 __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
6049f4f8 5423
1d8b512b
RV
5424 __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5425 __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5426 __put_user(0, &sc->sc_traparg_a2); /* FIXME */
6049f4f8
RH
5427}
5428
016d2e1d 5429static void restore_sigcontext(CPUAlphaState *env,
da7c8647 5430 struct target_sigcontext *sc)
6049f4f8
RH
5431{
5432 uint64_t fpcr;
016d2e1d 5433 int i;
6049f4f8 5434
1d8b512b 5435 __get_user(env->pc, &sc->sc_pc);
6049f4f8
RH
5436
5437 for (i = 0; i < 31; ++i) {
1d8b512b 5438 __get_user(env->ir[i], &sc->sc_regs[i]);
6049f4f8
RH
5439 }
5440 for (i = 0; i < 31; ++i) {
1d8b512b 5441 __get_user(env->fir[i], &sc->sc_fpregs[i]);
6049f4f8
RH
5442 }
5443
1d8b512b 5444 __get_user(fpcr, &sc->sc_fpcr);
6049f4f8 5445 cpu_alpha_store_fpcr(env, fpcr);
6049f4f8
RH
5446}
5447
5448static inline abi_ulong get_sigframe(struct target_sigaction *sa,
05390248
AF
5449 CPUAlphaState *env,
5450 unsigned long framesize)
6049f4f8
RH
5451{
5452 abi_ulong sp = env->ir[IR_SP];
5453
5454 /* This is the X/Open sanctioned signal stack switching. */
5455 if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5456 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5457 }
5458 return (sp - framesize) & -32;
5459}
5460
5461static void setup_frame(int sig, struct target_sigaction *ka,
05390248 5462 target_sigset_t *set, CPUAlphaState *env)
6049f4f8
RH
5463{
5464 abi_ulong frame_addr, r26;
5465 struct target_sigframe *frame;
5466 int err = 0;
5467
5468 frame_addr = get_sigframe(ka, env, sizeof(*frame));
c8ee0a44 5469 trace_user_setup_frame(env, frame_addr);
6049f4f8
RH
5470 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5471 goto give_sigsegv;
5472 }
5473
41ecc72b 5474 setup_sigcontext(&frame->sc, env, frame_addr, set);
6049f4f8
RH
5475
5476 if (ka->sa_restorer) {
5477 r26 = ka->sa_restorer;
5478 } else {
1d8b512b
RV
5479 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5480 __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5481 &frame->retcode[1]);
5482 __put_user(INSN_CALLSYS, &frame->retcode[2]);
6049f4f8
RH
5483 /* imb() */
5484 r26 = frame_addr;
5485 }
5486
5487 unlock_user_struct(frame, frame_addr, 1);
5488
5489 if (err) {
da7c8647 5490give_sigsegv:
6049f4f8
RH
5491 if (sig == TARGET_SIGSEGV) {
5492 ka->_sa_handler = TARGET_SIG_DFL;
5493 }
5494 force_sig(TARGET_SIGSEGV);
5495 }
5496
5497 env->ir[IR_RA] = r26;
5498 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5499 env->ir[IR_A0] = sig;
5500 env->ir[IR_A1] = 0;
5501 env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5502 env->ir[IR_SP] = frame_addr;
5503}
5504
5505static void setup_rt_frame(int sig, struct target_sigaction *ka,
5506 target_siginfo_t *info,
05390248 5507 target_sigset_t *set, CPUAlphaState *env)
6049f4f8
RH
5508{
5509 abi_ulong frame_addr, r26;
5510 struct target_rt_sigframe *frame;
5511 int i, err = 0;
5512
5513 frame_addr = get_sigframe(ka, env, sizeof(*frame));
c8ee0a44 5514 trace_user_setup_rt_frame(env, frame_addr);
6049f4f8
RH
5515 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5516 goto give_sigsegv;
5517 }
5518
f6c7a05b 5519 tswap_siginfo(&frame->info, info);
6049f4f8 5520
1d8b512b
RV
5521 __put_user(0, &frame->uc.tuc_flags);
5522 __put_user(0, &frame->uc.tuc_link);
5523 __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5524 __put_user(target_sigaltstack_used.ss_sp,
5525 &frame->uc.tuc_stack.ss_sp);
5526 __put_user(sas_ss_flags(env->ir[IR_SP]),
5527 &frame->uc.tuc_stack.ss_flags);
5528 __put_user(target_sigaltstack_used.ss_size,
5529 &frame->uc.tuc_stack.ss_size);
41ecc72b 5530 setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
6049f4f8 5531 for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
1d8b512b 5532 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
6049f4f8
RH
5533 }
5534
5535 if (ka->sa_restorer) {
5536 r26 = ka->sa_restorer;
5537 } else {
1d8b512b
RV
5538 __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5539 __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5540 &frame->retcode[1]);
5541 __put_user(INSN_CALLSYS, &frame->retcode[2]);
6049f4f8
RH
5542 /* imb(); */
5543 r26 = frame_addr;
5544 }
5545
5546 if (err) {
da7c8647
TB
5547give_sigsegv:
5548 if (sig == TARGET_SIGSEGV) {
6049f4f8
RH
5549 ka->_sa_handler = TARGET_SIG_DFL;
5550 }
5551 force_sig(TARGET_SIGSEGV);
5552 }
5553
5554 env->ir[IR_RA] = r26;
5555 env->ir[IR_PV] = env->pc = ka->_sa_handler;
5556 env->ir[IR_A0] = sig;
5557 env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5558 env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5559 env->ir[IR_SP] = frame_addr;
5560}
5561
05390248 5562long do_sigreturn(CPUAlphaState *env)
6049f4f8
RH
5563{
5564 struct target_sigcontext *sc;
5565 abi_ulong sc_addr = env->ir[IR_A0];
5566 target_sigset_t target_set;
5567 sigset_t set;
5568
5569 if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5570 goto badframe;
5571 }
5572
5573 target_sigemptyset(&target_set);
f5f601af 5574 __get_user(target_set.sig[0], &sc->sc_mask);
6049f4f8
RH
5575
5576 target_to_host_sigset_internal(&set, &target_set);
9eede5b6 5577 set_sigmask(&set);
6049f4f8 5578
016d2e1d 5579 restore_sigcontext(env, sc);
6049f4f8 5580 unlock_user_struct(sc, sc_addr, 0);
338c858c 5581 return -TARGET_QEMU_ESIGRETURN;
6049f4f8 5582
da7c8647 5583badframe:
6049f4f8
RH
5584 force_sig(TARGET_SIGSEGV);
5585}
5586
05390248 5587long do_rt_sigreturn(CPUAlphaState *env)
6049f4f8
RH
5588{
5589 abi_ulong frame_addr = env->ir[IR_A0];
5590 struct target_rt_sigframe *frame;
5591 sigset_t set;
5592
c8ee0a44 5593 trace_user_do_rt_sigreturn(env, frame_addr);
6049f4f8
RH
5594 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5595 goto badframe;
5596 }
60e99246 5597 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
9eede5b6 5598 set_sigmask(&set);
6049f4f8 5599
016d2e1d 5600 restore_sigcontext(env, &frame->uc.tuc_mcontext);
6049f4f8 5601 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
60e99246 5602 uc.tuc_stack),
6049f4f8
RH
5603 0, env->ir[IR_SP]) == -EFAULT) {
5604 goto badframe;
5605 }
5606
5607 unlock_user_struct(frame, frame_addr, 0);
338c858c 5608 return -TARGET_QEMU_ESIGRETURN;
6049f4f8
RH
5609
5610
da7c8647 5611badframe:
6049f4f8
RH
5612 unlock_user_struct(frame, frame_addr, 0);
5613 force_sig(TARGET_SIGSEGV);
5614}
5615
bf0f60a6
CG
5616#elif defined(TARGET_TILEGX)
5617
5618struct target_sigcontext {
5619 union {
5620 /* General-purpose registers. */
5621 abi_ulong gregs[56];
5622 struct {
5623 abi_ulong __gregs[53];
5624 abi_ulong tp; /* Aliases gregs[TREG_TP]. */
5625 abi_ulong sp; /* Aliases gregs[TREG_SP]. */
5626 abi_ulong lr; /* Aliases gregs[TREG_LR]. */
5627 };
5628 };
5629 abi_ulong pc; /* Program counter. */
5630 abi_ulong ics; /* In Interrupt Critical Section? */
5631 abi_ulong faultnum; /* Fault number. */
5632 abi_ulong pad[5];
5633};
5634
5635struct target_ucontext {
5636 abi_ulong tuc_flags;
5637 abi_ulong tuc_link;
5638 target_stack_t tuc_stack;
5639 struct target_sigcontext tuc_mcontext;
5640 target_sigset_t tuc_sigmask; /* mask last for extensibility */
5641};
5642
5643struct target_rt_sigframe {
5644 unsigned char save_area[16]; /* caller save area */
5645 struct target_siginfo info;
5646 struct target_ucontext uc;
f1d9d107 5647 abi_ulong retcode[2];
bf0f60a6
CG
5648};
5649
f1d9d107
CG
5650#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
5651#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
5652
5653
bf0f60a6
CG
5654static void setup_sigcontext(struct target_sigcontext *sc,
5655 CPUArchState *env, int signo)
5656{
5657 int i;
5658
5659 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5660 __put_user(env->regs[i], &sc->gregs[i]);
5661 }
5662
5663 __put_user(env->pc, &sc->pc);
5664 __put_user(0, &sc->ics);
5665 __put_user(signo, &sc->faultnum);
5666}
5667
5668static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc)
5669{
5670 int i;
5671
5672 for (i = 0; i < TILEGX_R_COUNT; ++i) {
5673 __get_user(env->regs[i], &sc->gregs[i]);
5674 }
5675
5676 __get_user(env->pc, &sc->pc);
5677}
5678
5679static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env,
5680 size_t frame_size)
5681{
5682 unsigned long sp = env->regs[TILEGX_R_SP];
5683
5684 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) {
5685 return -1UL;
5686 }
5687
5688 if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) {
5689 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5690 }
5691
5692 sp -= frame_size;
5693 sp &= -16UL;
5694 return sp;
5695}
5696
5697static void setup_rt_frame(int sig, struct target_sigaction *ka,
5698 target_siginfo_t *info,
5699 target_sigset_t *set, CPUArchState *env)
5700{
5701 abi_ulong frame_addr;
5702 struct target_rt_sigframe *frame;
5703 unsigned long restorer;
5704
5705 frame_addr = get_sigframe(ka, env, sizeof(*frame));
c8ee0a44 5706 trace_user_setup_rt_frame(env, frame_addr);
bf0f60a6
CG
5707 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5708 goto give_sigsegv;
5709 }
5710
5711 /* Always write at least the signal number for the stack backtracer. */
5712 if (ka->sa_flags & TARGET_SA_SIGINFO) {
5713 /* At sigreturn time, restore the callee-save registers too. */
5714 tswap_siginfo(&frame->info, info);
5715 /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */
5716 } else {
5717 __put_user(info->si_signo, &frame->info.si_signo);
5718 }
5719
5720 /* Create the ucontext. */
5721 __put_user(0, &frame->uc.tuc_flags);
5722 __put_user(0, &frame->uc.tuc_link);
5723 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
5724 __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]),
5725 &frame->uc.tuc_stack.ss_flags);
5726 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
5727 setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
5728
bf0f60a6 5729 if (ka->sa_flags & TARGET_SA_RESTORER) {
f1d9d107
CG
5730 restorer = (unsigned long) ka->sa_restorer;
5731 } else {
5732 __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
5733 __put_user(INSN_SWINT1, &frame->retcode[1]);
5734 restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
bf0f60a6
CG
5735 }
5736 env->pc = (unsigned long) ka->_sa_handler;
5737 env->regs[TILEGX_R_SP] = (unsigned long) frame;
5738 env->regs[TILEGX_R_LR] = restorer;
5739 env->regs[0] = (unsigned long) sig;
5740 env->regs[1] = (unsigned long) &frame->info;
5741 env->regs[2] = (unsigned long) &frame->uc;
5742 /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */
5743
5744 unlock_user_struct(frame, frame_addr, 1);
5745 return;
5746
5747give_sigsegv:
5748 if (sig == TARGET_SIGSEGV) {
5749 ka->_sa_handler = TARGET_SIG_DFL;
5750 }
5751 force_sig(TARGET_SIGSEGV /* , current */);
5752}
5753
5754long do_rt_sigreturn(CPUTLGState *env)
5755{
5756 abi_ulong frame_addr = env->regs[TILEGX_R_SP];
5757 struct target_rt_sigframe *frame;
5758 sigset_t set;
5759
c8ee0a44 5760 trace_user_do_rt_sigreturn(env, frame_addr);
bf0f60a6
CG
5761 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5762 goto badframe;
5763 }
5764 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
9eede5b6 5765 set_sigmask(&set);
bf0f60a6
CG
5766
5767 restore_sigcontext(env, &frame->uc.tuc_mcontext);
5768 if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
5769 uc.tuc_stack),
5770 0, env->regs[TILEGX_R_SP]) == -EFAULT) {
5771 goto badframe;
5772 }
5773
5774 unlock_user_struct(frame, frame_addr, 0);
a9175169 5775 return -TARGET_QEMU_ESIGRETURN;
bf0f60a6
CG
5776
5777
5778 badframe:
5779 unlock_user_struct(frame, frame_addr, 0);
5780 force_sig(TARGET_SIGSEGV);
5781}
5782
b346ff46
FB
5783#else
5784
624f7979 5785static void setup_frame(int sig, struct target_sigaction *ka,
da7c8647 5786 target_sigset_t *set, CPUArchState *env)
b346ff46
FB
5787{
5788 fprintf(stderr, "setup_frame: not implemented\n");
5789}
5790
624f7979 5791static void setup_rt_frame(int sig, struct target_sigaction *ka,
c227f099 5792 target_siginfo_t *info,
da7c8647 5793 target_sigset_t *set, CPUArchState *env)
b346ff46
FB
5794{
5795 fprintf(stderr, "setup_rt_frame: not implemented\n");
5796}
5797
9349b4f9 5798long do_sigreturn(CPUArchState *env)
b346ff46
FB
5799{
5800 fprintf(stderr, "do_sigreturn: not implemented\n");
f8b0aa25 5801 return -TARGET_ENOSYS;
b346ff46
FB
5802}
5803
9349b4f9 5804long do_rt_sigreturn(CPUArchState *env)
b346ff46
FB
5805{
5806 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 5807 return -TARGET_ENOSYS;
b346ff46
FB
5808}
5809
66fb9763
FB
5810#endif
5811
eb552501
PM
5812static void handle_pending_signal(CPUArchState *cpu_env, int sig)
5813{
5814 CPUState *cpu = ENV_GET_CPU(cpu_env);
5815 abi_ulong handler;
3d3efba0 5816 sigset_t set;
eb552501
PM
5817 target_sigset_t target_old_set;
5818 struct target_sigaction *sa;
eb552501
PM
5819 TaskState *ts = cpu->opaque;
5820 struct emulated_sigtable *k = &ts->sigtab[sig - 1];
66fb9763 5821
c8ee0a44 5822 trace_user_handle_signal(cpu_env, sig);
66fb9763 5823 /* dequeue signal */
907f5fdd 5824 k->pending = 0;
3b46e624 5825
db6b81d4 5826 sig = gdb_handlesig(cpu, sig);
1fddef4b 5827 if (!sig) {
ca587a8e
AJ
5828 sa = NULL;
5829 handler = TARGET_SIG_IGN;
5830 } else {
5831 sa = &sigact_table[sig - 1];
5832 handler = sa->_sa_handler;
1fddef4b 5833 }
66fb9763 5834
66fb9763 5835 if (handler == TARGET_SIG_DFL) {
ca587a8e
AJ
5836 /* default handler : ignore some signal. The other are job control or fatal */
5837 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5838 kill(getpid(),SIGSTOP);
5839 } else if (sig != TARGET_SIGCHLD &&
5840 sig != TARGET_SIGURG &&
5841 sig != TARGET_SIGWINCH &&
5842 sig != TARGET_SIGCONT) {
66fb9763
FB
5843 force_sig(sig);
5844 }
5845 } else if (handler == TARGET_SIG_IGN) {
5846 /* ignore sig */
5847 } else if (handler == TARGET_SIG_ERR) {
5848 force_sig(sig);
5849 } else {
9de5e440 5850 /* compute the blocked signals during the handler execution */
3d3efba0
PM
5851 sigset_t *blocked_set;
5852
624f7979 5853 target_to_host_sigset(&set, &sa->sa_mask);
9de5e440
FB
5854 /* SA_NODEFER indicates that the current signal should not be
5855 blocked during the handler */
624f7979 5856 if (!(sa->sa_flags & TARGET_SA_NODEFER))
9de5e440 5857 sigaddset(&set, target_to_host_signal(sig));
3b46e624 5858
9de5e440
FB
5859 /* save the previous blocked signal state to restore it at the
5860 end of the signal execution (see do_sigreturn) */
3d3efba0
PM
5861 host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
5862
5863 /* block signals in the handler */
5864 blocked_set = ts->in_sigsuspend ?
5865 &ts->sigsuspend_mask : &ts->signal_mask;
5866 sigorset(&ts->signal_mask, blocked_set, &set);
5867 ts->in_sigsuspend = 0;
9de5e440 5868
bc8a22cc 5869 /* if the CPU is in VM86 mode, we restore the 32 bit values */
84409ddb 5870#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bc8a22cc
FB
5871 {
5872 CPUX86State *env = cpu_env;
5873 if (env->eflags & VM_MASK)
5874 save_v86_state(env);
5875 }
5876#endif
9de5e440 5877 /* prepare the stack frame of the virtual CPU */
d0924a26 5878#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
bf0f60a6 5879 || defined(TARGET_OPENRISC) || defined(TARGET_TILEGX)
ff970904 5880 /* These targets do not have traditional signals. */
907f5fdd 5881 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
ff970904 5882#else
624f7979 5883 if (sa->sa_flags & TARGET_SA_SIGINFO)
907f5fdd 5884 setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
66fb9763 5885 else
624f7979 5886 setup_frame(sig, sa, &target_old_set, cpu_env);
ff970904 5887#endif
7ec87e06 5888 if (sa->sa_flags & TARGET_SA_RESETHAND) {
624f7979 5889 sa->_sa_handler = TARGET_SIG_DFL;
7ec87e06 5890 }
31e31b8a 5891 }
66fb9763 5892}
e902d588
PM
5893
5894void process_pending_signals(CPUArchState *cpu_env)
5895{
5896 CPUState *cpu = ENV_GET_CPU(cpu_env);
5897 int sig;
5898 TaskState *ts = cpu->opaque;
3d3efba0
PM
5899 sigset_t set;
5900 sigset_t *blocked_set;
e902d588 5901
3d3efba0
PM
5902 while (atomic_read(&ts->signal_pending)) {
5903 /* FIXME: This is not threadsafe. */
5904 sigfillset(&set);
5905 sigprocmask(SIG_SETMASK, &set, 0);
5906
655ed67c
TB
5907 sig = ts->sync_signal.pending;
5908 if (sig) {
5909 /* Synchronous signals are forced,
5910 * see force_sig_info() and callers in Linux
5911 * Note that not all of our queue_signal() calls in QEMU correspond
5912 * to force_sig_info() calls in Linux (some are send_sig_info()).
5913 * However it seems like a kernel bug to me to allow the process
5914 * to block a synchronous signal since it could then just end up
5915 * looping round and round indefinitely.
5916 */
5917 if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
5918 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
5919 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
5920 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
5921 }
5922
5923 handle_pending_signal(cpu_env, sig);
5924 }
5925
3d3efba0
PM
5926 for (sig = 1; sig <= TARGET_NSIG; sig++) {
5927 blocked_set = ts->in_sigsuspend ?
5928 &ts->sigsuspend_mask : &ts->signal_mask;
5929
5930 if (ts->sigtab[sig - 1].pending &&
5931 (!sigismember(blocked_set,
655ed67c 5932 target_to_host_signal_table[sig]))) {
3d3efba0
PM
5933 handle_pending_signal(cpu_env, sig);
5934 /* Restart scan from the beginning */
5935 sig = 1;
5936 }
e902d588 5937 }
3d3efba0
PM
5938
5939 /* if no signal is pending, unblock signals and recheck (the act
5940 * of unblocking might cause us to take another host signal which
5941 * will set signal_pending again).
5942 */
5943 atomic_set(&ts->signal_pending, 0);
5944 ts->in_sigsuspend = 0;
5945 set = ts->signal_mask;
5946 sigdelset(&set, SIGSEGV);
5947 sigdelset(&set, SIGBUS);
5948 sigprocmask(SIG_SETMASK, &set, 0);
5949 }
5950 ts->in_sigsuspend = 0;
e902d588 5951}
This page took 1.685474 seconds and 4 git commands to generate.