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