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