]> git.proxmox.com Git - qemu.git/blame - linux-user/signal.c
Replace noreturn with QEMU_NORETURN
[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
17 * along with this program; if not, write to the Free Software
530e7615
BS
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 * MA 02110-1301, USA.
31e31b8a
FB
20 */
21#include <stdlib.h>
22#include <stdio.h>
66fb9763 23#include <string.h>
31e31b8a 24#include <stdarg.h>
2677e107 25#include <unistd.h>
31e31b8a 26#include <signal.h>
66fb9763 27#include <errno.h>
31e31b8a
FB
28#include <sys/ucontext.h>
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
9e5f5284
FB
47static uint8_t host_to_target_signal_table[65] = {
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
FB
89};
90static uint8_t target_to_host_signal_table[65];
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
31e31b8a
FB
104static inline int host_to_target_signal(int sig)
105{
4cb05961
PB
106 if (sig > 64)
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{
4cb05961
PB
113 if (sig > 64)
114 return sig;
9e5f5284 115 return target_to_host_signal_table[sig];
31e31b8a
FB
116}
117
f5545b5c
PB
118static inline void target_sigemptyset(target_sigset_t *set)
119{
120 memset(set, 0, sizeof(*set));
121}
122
123static inline void target_sigaddset(target_sigset_t *set, int signum)
124{
125 signum--;
126 abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 set->sig[signum / TARGET_NSIG_BPW] |= mask;
128}
129
130static inline int target_sigismember(const target_sigset_t *set, int signum)
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
5fafdf24 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
9231944d
FB
149void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
150{
151 target_sigset_t d1;
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
BS
159static void target_to_host_sigset_internal(sigset_t *d,
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
9231944d
FB
171void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
172{
173 target_sigset_t s1;
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{
9e5f5284
FB
184 target_sigset_t d;
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{
9e5f5284
FB
192 target_sigset_t d;
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
5fafdf24 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
5fafdf24 227static void tswap_siginfo(target_siginfo_t *tinfo,
9de5e440
FB
228 const target_siginfo_t *info)
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
250void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
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) */
9de5e440 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
31e31b8a
FB
289void signal_init(void)
290{
291 struct sigaction act;
624f7979 292 struct sigaction oact;
9e5f5284 293 int i, j;
624f7979 294 int host_sig;
31e31b8a 295
9e5f5284
FB
296 /* generate signal conversion tables */
297 for(i = 1; i <= 64; i++) {
298 if (host_to_target_signal_table[i] == 0)
299 host_to_target_signal_table[i] = i;
300 }
301 for(i = 1; i <= 64; i++) {
302 j = host_to_target_signal_table[i];
303 target_to_host_signal_table[j] = i;
304 }
3b46e624 305
9de5e440
FB
306 /* set all host signal handlers. ALL signals are blocked during
307 the handlers to serialize them. */
624f7979
PB
308 memset(sigact_table, 0, sizeof(sigact_table));
309
9de5e440 310 sigfillset(&act.sa_mask);
31e31b8a
FB
311 act.sa_flags = SA_SIGINFO;
312 act.sa_sigaction = host_signal_handler;
624f7979
PB
313 for(i = 1; i <= TARGET_NSIG; i++) {
314 host_sig = target_to_host_signal(i);
315 sigaction(host_sig, NULL, &oact);
316 if (oact.sa_sigaction == (void *)SIG_IGN) {
317 sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
318 } else if (oact.sa_sigaction == (void *)SIG_DFL) {
319 sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
320 }
321 /* If there's already a handler installed then something has
322 gone horribly wrong, so don't even try to handle that case. */
ca587a8e
AJ
323 /* Install some handlers for our own use. We need at least
324 SIGSEGV and SIGBUS, to detect exceptions. We can not just
325 trap all signals because it affects syscall interrupt
326 behavior. But do trap all default-fatal signals. */
327 if (fatal_signal (i))
624f7979 328 sigaction(host_sig, &act, NULL);
31e31b8a 329 }
66fb9763
FB
330}
331
332/* signal queue handling */
333
624f7979 334static inline struct sigqueue *alloc_sigqueue(CPUState *env)
66fb9763 335{
624f7979
PB
336 TaskState *ts = env->opaque;
337 struct sigqueue *q = ts->first_free;
66fb9763
FB
338 if (!q)
339 return NULL;
624f7979 340 ts->first_free = q->next;
66fb9763 341 return q;
31e31b8a
FB
342}
343
624f7979 344static inline void free_sigqueue(CPUState *env, struct sigqueue *q)
66fb9763 345{
624f7979
PB
346 TaskState *ts = env->opaque;
347 q->next = ts->first_free;
348 ts->first_free = q;
66fb9763
FB
349}
350
9de5e440 351/* abort execution with signal */
a5e50b26 352static void QEMU_NORETURN force_sig(int sig)
66fb9763
FB
353{
354 int host_sig;
66fb9763 355 host_sig = target_to_host_signal(sig);
5fafdf24 356 fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
66fb9763 357 sig, strsignal(host_sig));
9de5e440 358#if 1
ca587a8e 359 gdb_signalled(thread_env, sig);
66fb9763 360 _exit(-host_sig);
9de5e440
FB
361#else
362 {
363 struct sigaction act;
364 sigemptyset(&act.sa_mask);
365 act.sa_flags = SA_SIGINFO;
366 act.sa_sigaction = SIG_DFL;
367 sigaction(SIGABRT, &act, NULL);
368 abort();
369 }
370#endif
66fb9763
FB
371}
372
9de5e440
FB
373/* queue a signal so that it will be send to the virtual CPU as soon
374 as possible */
624f7979 375int queue_signal(CPUState *env, int sig, target_siginfo_t *info)
31e31b8a 376{
624f7979
PB
377 TaskState *ts = env->opaque;
378 struct emulated_sigtable *k;
9de5e440 379 struct sigqueue *q, **pq;
992f48a0 380 abi_ulong handler;
ca587a8e 381 int queue;
66fb9763 382
9de5e440 383#if defined(DEBUG_SIGNAL)
5fafdf24 384 fprintf(stderr, "queue_signal: sig=%d\n",
9de5e440 385 sig);
66fb9763 386#endif
624f7979 387 k = &ts->sigtab[sig - 1];
ca587a8e 388 queue = gdb_queuesig ();
624f7979 389 handler = sigact_table[sig - 1]._sa_handler;
ca587a8e 390 if (!queue && handler == TARGET_SIG_DFL) {
60b19691
TS
391 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
392 kill(getpid(),SIGSTOP);
393 return 0;
394 } else
66fb9763 395 /* default handler : ignore some signal. The other are fatal */
5fafdf24
TS
396 if (sig != TARGET_SIGCHLD &&
397 sig != TARGET_SIGURG &&
60b19691
TS
398 sig != TARGET_SIGWINCH &&
399 sig != TARGET_SIGCONT) {
66fb9763 400 force_sig(sig);
9de5e440
FB
401 } else {
402 return 0; /* indicate ignored */
66fb9763 403 }
ca587a8e 404 } else if (!queue && handler == TARGET_SIG_IGN) {
66fb9763 405 /* ignore signal */
9de5e440 406 return 0;
ca587a8e 407 } else if (!queue && handler == TARGET_SIG_ERR) {
66fb9763
FB
408 force_sig(sig);
409 } else {
9de5e440
FB
410 pq = &k->first;
411 if (sig < TARGET_SIGRTMIN) {
412 /* if non real time signal, we queue exactly one signal */
413 if (!k->pending)
414 q = &k->info;
415 else
416 return 0;
417 } else {
418 if (!k->pending) {
419 /* first signal */
420 q = &k->info;
421 } else {
624f7979 422 q = alloc_sigqueue(env);
9de5e440
FB
423 if (!q)
424 return -EAGAIN;
425 while (*pq != NULL)
426 pq = &(*pq)->next;
427 }
428 }
429 *pq = q;
430 q->info = *info;
431 q->next = NULL;
432 k->pending = 1;
433 /* signal that a new signal is pending */
624f7979 434 ts->signal_pending = 1;
9de5e440
FB
435 return 1; /* indicates that the signal was queued */
436 }
437}
438
5fafdf24 439static void host_signal_handler(int host_signum, siginfo_t *info,
9de5e440
FB
440 void *puc)
441{
442 int sig;
443 target_siginfo_t tinfo;
444
445 /* the CPU emulator uses some host signals to detect exceptions,
eaa449b9 446 we forward to it some signals */
ca587a8e 447 if ((host_signum == SIGSEGV || host_signum == SIGBUS)
eaa449b9 448 && info->si_code > 0) {
b346ff46 449 if (cpu_signal_handler(host_signum, info, puc))
9de5e440
FB
450 return;
451 }
452
453 /* get target signal number */
454 sig = host_to_target_signal(host_signum);
455 if (sig < 1 || sig > TARGET_NSIG)
456 return;
457#if defined(DEBUG_SIGNAL)
bc8a22cc 458 fprintf(stderr, "qemu: got signal %d\n", sig);
9de5e440
FB
459#endif
460 host_to_target_siginfo_noswap(&tinfo, info);
d5975363 461 if (queue_signal(thread_env, sig, &tinfo) == 1) {
9de5e440 462 /* interrupt the virtual CPU as soon as possible */
d5975363 463 cpu_interrupt(thread_env, CPU_INTERRUPT_EXIT);
66fb9763
FB
464 }
465}
466
0da46a6e 467/* do_sigaltstack() returns target values and errnos. */
579a97f7
FB
468/* compare linux/kernel/signal.c:do_sigaltstack() */
469abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
a04e134a
TS
470{
471 int ret;
472 struct target_sigaltstack oss;
473
474 /* XXX: test errors */
579a97f7 475 if(uoss_addr)
a04e134a
TS
476 {
477 __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
478 __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
479 __put_user(sas_ss_flags(sp), &oss.ss_flags);
480 }
481
579a97f7 482 if(uss_addr)
a04e134a 483 {
579a97f7
FB
484 struct target_sigaltstack *uss;
485 struct target_sigaltstack ss;
a04e134a 486
0da46a6e 487 ret = -TARGET_EFAULT;
579a97f7 488 if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)
a04e134a
TS
489 || __get_user(ss.ss_sp, &uss->ss_sp)
490 || __get_user(ss.ss_size, &uss->ss_size)
491 || __get_user(ss.ss_flags, &uss->ss_flags))
492 goto out;
579a97f7 493 unlock_user_struct(uss, uss_addr, 0);
a04e134a 494
0da46a6e 495 ret = -TARGET_EPERM;
a04e134a
TS
496 if (on_sig_stack(sp))
497 goto out;
498
0da46a6e 499 ret = -TARGET_EINVAL;
a04e134a
TS
500 if (ss.ss_flags != TARGET_SS_DISABLE
501 && ss.ss_flags != TARGET_SS_ONSTACK
502 && ss.ss_flags != 0)
503 goto out;
504
505 if (ss.ss_flags == TARGET_SS_DISABLE) {
506 ss.ss_size = 0;
507 ss.ss_sp = 0;
508 } else {
0da46a6e 509 ret = -TARGET_ENOMEM;
a04e134a
TS
510 if (ss.ss_size < MINSIGSTKSZ)
511 goto out;
512 }
513
514 target_sigaltstack_used.ss_sp = ss.ss_sp;
515 target_sigaltstack_used.ss_size = ss.ss_size;
516 }
517
579a97f7 518 if (uoss_addr) {
0da46a6e 519 ret = -TARGET_EFAULT;
579a97f7 520 if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
a04e134a 521 goto out;
a04e134a
TS
522 }
523
524 ret = 0;
525out:
526 return ret;
527}
528
0da46a6e 529/* do_sigaction() return host values and errnos */
66fb9763
FB
530int do_sigaction(int sig, const struct target_sigaction *act,
531 struct target_sigaction *oact)
532{
624f7979 533 struct target_sigaction *k;
773b93ee
FB
534 struct sigaction act1;
535 int host_sig;
0da46a6e 536 int ret = 0;
66fb9763 537
2a913eb1 538 if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
66fb9763
FB
539 return -EINVAL;
540 k = &sigact_table[sig - 1];
773b93ee 541#if defined(DEBUG_SIGNAL)
5fafdf24 542 fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n",
66fb9763
FB
543 sig, (int)act, (int)oact);
544#endif
545 if (oact) {
624f7979
PB
546 oact->_sa_handler = tswapl(k->_sa_handler);
547 oact->sa_flags = tswapl(k->sa_flags);
388bb21a 548#if !defined(TARGET_MIPS)
624f7979 549 oact->sa_restorer = tswapl(k->sa_restorer);
388bb21a 550#endif
624f7979 551 oact->sa_mask = k->sa_mask;
66fb9763
FB
552 }
553 if (act) {
624f7979
PB
554 /* FIXME: This is not threadsafe. */
555 k->_sa_handler = tswapl(act->_sa_handler);
556 k->sa_flags = tswapl(act->sa_flags);
388bb21a 557#if !defined(TARGET_MIPS)
624f7979 558 k->sa_restorer = tswapl(act->sa_restorer);
388bb21a 559#endif
624f7979 560 k->sa_mask = act->sa_mask;
773b93ee
FB
561
562 /* we update the host linux signal state */
563 host_sig = target_to_host_signal(sig);
564 if (host_sig != SIGSEGV && host_sig != SIGBUS) {
565 sigfillset(&act1.sa_mask);
566 act1.sa_flags = SA_SIGINFO;
624f7979 567 if (k->sa_flags & TARGET_SA_RESTART)
773b93ee
FB
568 act1.sa_flags |= SA_RESTART;
569 /* NOTE: it is important to update the host kernel signal
570 ignore state to avoid getting unexpected interrupted
571 syscalls */
624f7979 572 if (k->_sa_handler == TARGET_SIG_IGN) {
773b93ee 573 act1.sa_sigaction = (void *)SIG_IGN;
624f7979 574 } else if (k->_sa_handler == TARGET_SIG_DFL) {
ca587a8e
AJ
575 if (fatal_signal (sig))
576 act1.sa_sigaction = host_signal_handler;
577 else
578 act1.sa_sigaction = (void *)SIG_DFL;
773b93ee
FB
579 } else {
580 act1.sa_sigaction = host_signal_handler;
581 }
0da46a6e 582 ret = sigaction(host_sig, &act1, NULL);
773b93ee 583 }
66fb9763 584 }
0da46a6e 585 return ret;
66fb9763
FB
586}
587
5fafdf24 588static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,
43fff238
FB
589 const target_siginfo_t *info)
590{
591 tswap_siginfo(tinfo, info);
592 return 0;
593}
594
c3b5bc8a
TS
595static inline int current_exec_domain_sig(int sig)
596{
597 return /* current->exec_domain && current->exec_domain->signal_invmap
598 && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig;
599}
600
459a4017 601#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
66fb9763
FB
602
603/* from the Linux kernel */
604
605struct target_fpreg {
606 uint16_t significand[4];
607 uint16_t exponent;
608};
609
610struct target_fpxreg {
611 uint16_t significand[4];
612 uint16_t exponent;
613 uint16_t padding[3];
614};
615
616struct target_xmmreg {
992f48a0 617 abi_ulong element[4];
66fb9763
FB
618};
619
620struct target_fpstate {
621 /* Regular FPU environment */
992f48a0
BS
622 abi_ulong cw;
623 abi_ulong sw;
624 abi_ulong tag;
625 abi_ulong ipoff;
626 abi_ulong cssel;
627 abi_ulong dataoff;
628 abi_ulong datasel;
66fb9763
FB
629 struct target_fpreg _st[8];
630 uint16_t status;
631 uint16_t magic; /* 0xffff = regular FPU data only */
632
633 /* FXSR FPU environment */
992f48a0
BS
634 abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
635 abi_ulong mxcsr;
636 abi_ulong reserved;
66fb9763
FB
637 struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
638 struct target_xmmreg _xmm[8];
992f48a0 639 abi_ulong padding[56];
66fb9763
FB
640};
641
642#define X86_FXSR_MAGIC 0x0000
643
644struct target_sigcontext {
645 uint16_t gs, __gsh;
646 uint16_t fs, __fsh;
647 uint16_t es, __esh;
648 uint16_t ds, __dsh;
992f48a0
BS
649 abi_ulong edi;
650 abi_ulong esi;
651 abi_ulong ebp;
652 abi_ulong esp;
653 abi_ulong ebx;
654 abi_ulong edx;
655 abi_ulong ecx;
656 abi_ulong eax;
657 abi_ulong trapno;
658 abi_ulong err;
659 abi_ulong eip;
66fb9763 660 uint16_t cs, __csh;
992f48a0
BS
661 abi_ulong eflags;
662 abi_ulong esp_at_signal;
66fb9763 663 uint16_t ss, __ssh;
992f48a0
BS
664 abi_ulong fpstate; /* pointer */
665 abi_ulong oldmask;
666 abi_ulong cr2;
66fb9763
FB
667};
668
66fb9763 669struct target_ucontext {
992f48a0
BS
670 abi_ulong tuc_flags;
671 abi_ulong tuc_link;
b8076a74
FB
672 target_stack_t tuc_stack;
673 struct target_sigcontext tuc_mcontext;
674 target_sigset_t tuc_sigmask; /* mask last for extensibility */
66fb9763
FB
675};
676
677struct sigframe
678{
992f48a0 679 abi_ulong pretcode;
66fb9763
FB
680 int sig;
681 struct target_sigcontext sc;
682 struct target_fpstate fpstate;
992f48a0 683 abi_ulong extramask[TARGET_NSIG_WORDS-1];
66fb9763
FB
684 char retcode[8];
685};
686
687struct rt_sigframe
688{
992f48a0 689 abi_ulong pretcode;
66fb9763 690 int sig;
992f48a0
BS
691 abi_ulong pinfo;
692 abi_ulong puc;
66fb9763
FB
693 struct target_siginfo info;
694 struct target_ucontext uc;
695 struct target_fpstate fpstate;
696 char retcode[8];
697};
698
699/*
700 * Set up a signal frame.
701 */
702
66fb9763
FB
703/* XXX: save x87 state */
704static int
705setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
28be6234 706 CPUX86State *env, abi_ulong mask, abi_ulong fpstate_addr)
66fb9763
FB
707{
708 int err = 0;
775b58d8 709 uint16_t magic;
66fb9763 710
579a97f7 711 /* already locked in setup_frame() */
a52c757c
FB
712 err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
713 err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
714 err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
715 err |= __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
66fb9763
FB
716 err |= __put_user(env->regs[R_EDI], &sc->edi);
717 err |= __put_user(env->regs[R_ESI], &sc->esi);
718 err |= __put_user(env->regs[R_EBP], &sc->ebp);
719 err |= __put_user(env->regs[R_ESP], &sc->esp);
720 err |= __put_user(env->regs[R_EBX], &sc->ebx);
721 err |= __put_user(env->regs[R_EDX], &sc->edx);
722 err |= __put_user(env->regs[R_ECX], &sc->ecx);
723 err |= __put_user(env->regs[R_EAX], &sc->eax);
66099dd9
FB
724 err |= __put_user(env->exception_index, &sc->trapno);
725 err |= __put_user(env->error_code, &sc->err);
66fb9763 726 err |= __put_user(env->eip, &sc->eip);
a52c757c 727 err |= __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
66fb9763
FB
728 err |= __put_user(env->eflags, &sc->eflags);
729 err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal);
a52c757c 730 err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
ed2dcdf6 731
28be6234 732 cpu_x86_fsave(env, fpstate_addr, 1);
ed2dcdf6 733 fpstate->status = fpstate->sw;
775b58d8
FB
734 magic = 0xffff;
735 err |= __put_user(magic, &fpstate->magic);
28be6234 736 err |= __put_user(fpstate_addr, &sc->fpstate);
ed2dcdf6 737
66fb9763
FB
738 /* non-iBCS2 extensions.. */
739 err |= __put_user(mask, &sc->oldmask);
a52c757c 740 err |= __put_user(env->cr[2], &sc->cr2);
66fb9763 741 return err;
31e31b8a
FB
742}
743
66fb9763
FB
744/*
745 * Determine which stack to use..
746 */
31e31b8a 747
579a97f7 748static inline abi_ulong
624f7979 749get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
31e31b8a 750{
66fb9763
FB
751 unsigned long esp;
752
753 /* Default to using normal stack */
754 esp = env->regs[R_ESP];
66fb9763 755 /* This is the X/Open sanctioned signal stack switching. */
624f7979 756 if (ka->sa_flags & TARGET_SA_ONSTACK) {
a04e134a
TS
757 if (sas_ss_flags(esp) == 0)
758 esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
759 }
66fb9763
FB
760
761 /* This is the legacy signal stack switching. */
5fafdf24 762 else
a52c757c 763 if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
624f7979
PB
764 !(ka->sa_flags & TARGET_SA_RESTORER) &&
765 ka->sa_restorer) {
766 esp = (unsigned long) ka->sa_restorer;
a52c757c 767 }
579a97f7 768 return (esp - frame_size) & -8ul;
66fb9763
FB
769}
770
579a97f7 771/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
624f7979 772static void setup_frame(int sig, struct target_sigaction *ka,
66fb9763
FB
773 target_sigset_t *set, CPUX86State *env)
774{
579a97f7 775 abi_ulong frame_addr;
66fb9763 776 struct sigframe *frame;
9231944d 777 int i, err = 0;
66fb9763 778
579a97f7 779 frame_addr = get_sigframe(ka, env, sizeof(*frame));
66fb9763 780
579a97f7 781 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
66fb9763 782 goto give_sigsegv;
579a97f7 783
c3b5bc8a 784 err |= __put_user(current_exec_domain_sig(sig),
66fb9763
FB
785 &frame->sig);
786 if (err)
787 goto give_sigsegv;
788
28be6234
FB
789 setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
790 frame_addr + offsetof(struct sigframe, fpstate));
66fb9763
FB
791 if (err)
792 goto give_sigsegv;
793
9231944d
FB
794 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
795 if (__put_user(set->sig[i], &frame->extramask[i - 1]))
796 goto give_sigsegv;
797 }
66fb9763
FB
798
799 /* Set up to return from userspace. If provided, use a stub
800 already in userspace. */
624f7979
PB
801 if (ka->sa_flags & TARGET_SA_RESTORER) {
802 err |= __put_user(ka->sa_restorer, &frame->pretcode);
66fb9763 803 } else {
775b58d8 804 uint16_t val16;
28be6234
FB
805 abi_ulong retcode_addr;
806 retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
807 err |= __put_user(retcode_addr, &frame->pretcode);
66fb9763 808 /* This is popl %eax ; movl $,%eax ; int $0x80 */
775b58d8
FB
809 val16 = 0xb858;
810 err |= __put_user(val16, (uint16_t *)(frame->retcode+0));
66fb9763 811 err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
775b58d8
FB
812 val16 = 0x80cd;
813 err |= __put_user(val16, (uint16_t *)(frame->retcode+6));
66fb9763
FB
814 }
815
816 if (err)
817 goto give_sigsegv;
818
819 /* Set up registers for signal handler */
28be6234 820 env->regs[R_ESP] = frame_addr;
624f7979 821 env->eip = ka->_sa_handler;
66fb9763
FB
822
823 cpu_x86_load_seg(env, R_DS, __USER_DS);
824 cpu_x86_load_seg(env, R_ES, __USER_DS);
825 cpu_x86_load_seg(env, R_SS, __USER_DS);
826 cpu_x86_load_seg(env, R_CS, __USER_CS);
827 env->eflags &= ~TF_MASK;
828
579a97f7
FB
829 unlock_user_struct(frame, frame_addr, 1);
830
66fb9763
FB
831 return;
832
833give_sigsegv:
579a97f7 834 unlock_user_struct(frame, frame_addr, 1);
66fb9763 835 if (sig == TARGET_SIGSEGV)
624f7979 836 ka->_sa_handler = TARGET_SIG_DFL;
66fb9763
FB
837 force_sig(TARGET_SIGSEGV /* , current */);
838}
839
579a97f7 840/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
624f7979 841static void setup_rt_frame(int sig, struct target_sigaction *ka,
9de5e440 842 target_siginfo_t *info,
66fb9763
FB
843 target_sigset_t *set, CPUX86State *env)
844{
28be6234 845 abi_ulong frame_addr, addr;
66fb9763 846 struct rt_sigframe *frame;
9231944d 847 int i, err = 0;
66fb9763 848
579a97f7 849 frame_addr = get_sigframe(ka, env, sizeof(*frame));
66fb9763 850
579a97f7 851 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
66fb9763 852 goto give_sigsegv;
66fb9763 853
c3b5bc8a 854 err |= __put_user(current_exec_domain_sig(sig),
66fb9763 855 &frame->sig);
28be6234
FB
856 addr = frame_addr + offsetof(struct rt_sigframe, info);
857 err |= __put_user(addr, &frame->pinfo);
858 addr = frame_addr + offsetof(struct rt_sigframe, uc);
859 err |= __put_user(addr, &frame->puc);
66fb9763
FB
860 err |= copy_siginfo_to_user(&frame->info, info);
861 if (err)
862 goto give_sigsegv;
31e31b8a 863
66fb9763 864 /* Create the ucontext. */
b8076a74
FB
865 err |= __put_user(0, &frame->uc.tuc_flags);
866 err |= __put_user(0, &frame->uc.tuc_link);
a04e134a 867 err |= __put_user(target_sigaltstack_used.ss_sp,
b8076a74 868 &frame->uc.tuc_stack.ss_sp);
a04e134a 869 err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
b8076a74 870 &frame->uc.tuc_stack.ss_flags);
a04e134a 871 err |= __put_user(target_sigaltstack_used.ss_size,
b8076a74
FB
872 &frame->uc.tuc_stack.ss_size);
873 err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate,
28be6234
FB
874 env, set->sig[0],
875 frame_addr + offsetof(struct rt_sigframe, fpstate));
9231944d 876 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
b8076a74 877 if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
9231944d
FB
878 goto give_sigsegv;
879 }
31e31b8a 880
66fb9763
FB
881 /* Set up to return from userspace. If provided, use a stub
882 already in userspace. */
624f7979
PB
883 if (ka->sa_flags & TARGET_SA_RESTORER) {
884 err |= __put_user(ka->sa_restorer, &frame->pretcode);
66fb9763 885 } else {
775b58d8 886 uint16_t val16;
28be6234
FB
887 addr = frame_addr + offsetof(struct rt_sigframe, retcode);
888 err |= __put_user(addr, &frame->pretcode);
66fb9763 889 /* This is movl $,%eax ; int $0x80 */
775b58d8 890 err |= __put_user(0xb8, (char *)(frame->retcode+0));
66fb9763 891 err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
775b58d8
FB
892 val16 = 0x80cd;
893 err |= __put_user(val16, (uint16_t *)(frame->retcode+5));
66fb9763
FB
894 }
895
896 if (err)
897 goto give_sigsegv;
898
899 /* Set up registers for signal handler */
28be6234 900 env->regs[R_ESP] = frame_addr;
624f7979 901 env->eip = ka->_sa_handler;
66fb9763
FB
902
903 cpu_x86_load_seg(env, R_DS, __USER_DS);
904 cpu_x86_load_seg(env, R_ES, __USER_DS);
905 cpu_x86_load_seg(env, R_SS, __USER_DS);
906 cpu_x86_load_seg(env, R_CS, __USER_CS);
907 env->eflags &= ~TF_MASK;
908
579a97f7
FB
909 unlock_user_struct(frame, frame_addr, 1);
910
66fb9763
FB
911 return;
912
913give_sigsegv:
579a97f7 914 unlock_user_struct(frame, frame_addr, 1);
66fb9763 915 if (sig == TARGET_SIGSEGV)
624f7979 916 ka->_sa_handler = TARGET_SIG_DFL;
66fb9763
FB
917 force_sig(TARGET_SIGSEGV /* , current */);
918}
919
920static int
921restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
922{
923 unsigned int err = 0;
28be6234
FB
924 abi_ulong fpstate_addr;
925 unsigned int tmpflags;
926
927 cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
928 cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
929 cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
930 cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
931
932 env->regs[R_EDI] = tswapl(sc->edi);
933 env->regs[R_ESI] = tswapl(sc->esi);
934 env->regs[R_EBP] = tswapl(sc->ebp);
935 env->regs[R_ESP] = tswapl(sc->esp);
936 env->regs[R_EBX] = tswapl(sc->ebx);
937 env->regs[R_EDX] = tswapl(sc->edx);
938 env->regs[R_ECX] = tswapl(sc->ecx);
939 env->eip = tswapl(sc->eip);
66fb9763
FB
940
941 cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3);
942 cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3);
5fafdf24 943
28be6234
FB
944 tmpflags = tswapl(sc->eflags);
945 env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
946 // regs->orig_eax = -1; /* disable syscall checks */
66fb9763 947
28be6234
FB
948 fpstate_addr = tswapl(sc->fpstate);
949 if (fpstate_addr != 0) {
950 if (!access_ok(VERIFY_READ, fpstate_addr,
951 sizeof(struct target_fpstate)))
952 goto badframe;
953 cpu_x86_frstor(env, fpstate_addr, 1);
66fb9763 954 }
ed2dcdf6 955
28be6234 956 *peax = tswapl(sc->eax);
66fb9763 957 return err;
66fb9763
FB
958badframe:
959 return 1;
66fb9763
FB
960}
961
962long do_sigreturn(CPUX86State *env)
963{
579a97f7
FB
964 struct sigframe *frame;
965 abi_ulong frame_addr = env->regs[R_ESP] - 8;
66fb9763
FB
966 target_sigset_t target_set;
967 sigset_t set;
968 int eax, i;
969
447db213
FB
970#if defined(DEBUG_SIGNAL)
971 fprintf(stderr, "do_sigreturn\n");
972#endif
579a97f7
FB
973 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
974 goto badframe;
66fb9763 975 /* set blocked signals */
9231944d
FB
976 if (__get_user(target_set.sig[0], &frame->sc.oldmask))
977 goto badframe;
978 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
979 if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
980 goto badframe;
981 }
66fb9763 982
9231944d 983 target_to_host_sigset_internal(&set, &target_set);
66fb9763 984 sigprocmask(SIG_SETMASK, &set, NULL);
3b46e624 985
66fb9763
FB
986 /* restore registers */
987 if (restore_sigcontext(env, &frame->sc, &eax))
988 goto badframe;
579a97f7 989 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
990 return eax;
991
992badframe:
579a97f7 993 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
994 force_sig(TARGET_SIGSEGV);
995 return 0;
996}
997
998long do_rt_sigreturn(CPUX86State *env)
999{
28be6234
FB
1000 abi_ulong frame_addr;
1001 struct rt_sigframe *frame;
66fb9763 1002 sigset_t set;
66fb9763
FB
1003 int eax;
1004
28be6234
FB
1005 frame_addr = env->regs[R_ESP] - 4;
1006 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1007 goto badframe;
b8076a74 1008 target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
66fb9763 1009 sigprocmask(SIG_SETMASK, &set, NULL);
5fafdf24 1010
b8076a74 1011 if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
66fb9763
FB
1012 goto badframe;
1013
28be6234
FB
1014 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
1015 get_sp_from_cpustate(env)) == -EFAULT)
66fb9763 1016 goto badframe;
a04e134a 1017
28be6234 1018 unlock_user_struct(frame, frame_addr, 0);
66fb9763
FB
1019 return eax;
1020
1021badframe:
28be6234
FB
1022 unlock_user_struct(frame, frame_addr, 0);
1023 force_sig(TARGET_SIGSEGV);
66fb9763
FB
1024 return 0;
1025}
1026
43fff238
FB
1027#elif defined(TARGET_ARM)
1028
1029struct target_sigcontext {
992f48a0
BS
1030 abi_ulong trap_no;
1031 abi_ulong error_code;
1032 abi_ulong oldmask;
1033 abi_ulong arm_r0;
1034 abi_ulong arm_r1;
1035 abi_ulong arm_r2;
1036 abi_ulong arm_r3;
1037 abi_ulong arm_r4;
1038 abi_ulong arm_r5;
1039 abi_ulong arm_r6;
1040 abi_ulong arm_r7;
1041 abi_ulong arm_r8;
1042 abi_ulong arm_r9;
1043 abi_ulong arm_r10;
1044 abi_ulong arm_fp;
1045 abi_ulong arm_ip;
1046 abi_ulong arm_sp;
1047 abi_ulong arm_lr;
1048 abi_ulong arm_pc;
1049 abi_ulong arm_cpsr;
1050 abi_ulong fault_address;
43fff238
FB
1051};
1052
a745ec6d
PB
1053struct target_ucontext_v1 {
1054 abi_ulong tuc_flags;
1055 abi_ulong tuc_link;
1056 target_stack_t tuc_stack;
1057 struct target_sigcontext tuc_mcontext;
1058 target_sigset_t tuc_sigmask; /* mask last for extensibility */
1059};
1060
1061struct target_ucontext_v2 {
992f48a0
BS
1062 abi_ulong tuc_flags;
1063 abi_ulong tuc_link;
b8076a74
FB
1064 target_stack_t tuc_stack;
1065 struct target_sigcontext tuc_mcontext;
1066 target_sigset_t tuc_sigmask; /* mask last for extensibility */
a745ec6d
PB
1067 char __unused[128 - sizeof(sigset_t)];
1068 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
43fff238
FB
1069};
1070
a8c33204 1071struct sigframe_v1
43fff238
FB
1072{
1073 struct target_sigcontext sc;
992f48a0
BS
1074 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1075 abi_ulong retcode;
43fff238
FB
1076};
1077
a8c33204
PB
1078struct sigframe_v2
1079{
1080 struct target_ucontext_v2 uc;
1081 abi_ulong retcode;
1082};
1083
a745ec6d 1084struct rt_sigframe_v1
43fff238 1085{
f8b0aa25
FB
1086 abi_ulong pinfo;
1087 abi_ulong puc;
43fff238 1088 struct target_siginfo info;
a745ec6d
PB
1089 struct target_ucontext_v1 uc;
1090 abi_ulong retcode;
1091};
1092
1093struct rt_sigframe_v2
1094{
1095 struct target_siginfo info;
1096 struct target_ucontext_v2 uc;
992f48a0 1097 abi_ulong retcode;
43fff238
FB
1098};
1099
1100#define TARGET_CONFIG_CPU_32 1
1101
1102/*
1103 * For ARM syscalls, we encode the syscall number into the instruction.
1104 */
1105#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1106#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1107
1108/*
1109 * For Thumb syscalls, we pass the syscall number via r7. We therefore
1110 * need two 16-bit instructions.
1111 */
1112#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1113#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1114
992f48a0 1115static const abi_ulong retcodes[4] = {
43fff238
FB
1116 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
1117 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
1118};
1119
1120
43fff238
FB
1121#define __get_user_error(x,p,e) __get_user(x, p)
1122
1123static inline int valid_user_regs(CPUState *regs)
1124{
1125 return 1;
1126}
1127
a8c33204 1128static void
43fff238 1129setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
f8b0aa25 1130 CPUState *env, abi_ulong mask)
43fff238 1131{
a8c33204
PB
1132 __put_user(env->regs[0], &sc->arm_r0);
1133 __put_user(env->regs[1], &sc->arm_r1);
1134 __put_user(env->regs[2], &sc->arm_r2);
1135 __put_user(env->regs[3], &sc->arm_r3);
1136 __put_user(env->regs[4], &sc->arm_r4);
1137 __put_user(env->regs[5], &sc->arm_r5);
1138 __put_user(env->regs[6], &sc->arm_r6);
1139 __put_user(env->regs[7], &sc->arm_r7);
1140 __put_user(env->regs[8], &sc->arm_r8);
1141 __put_user(env->regs[9], &sc->arm_r9);
1142 __put_user(env->regs[10], &sc->arm_r10);
1143 __put_user(env->regs[11], &sc->arm_fp);
1144 __put_user(env->regs[12], &sc->arm_ip);
1145 __put_user(env->regs[13], &sc->arm_sp);
1146 __put_user(env->regs[14], &sc->arm_lr);
1147 __put_user(env->regs[15], &sc->arm_pc);
43fff238 1148#ifdef TARGET_CONFIG_CPU_32
a8c33204 1149 __put_user(cpsr_read(env), &sc->arm_cpsr);
43fff238
FB
1150#endif
1151
a8c33204
PB
1152 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1153 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1154 __put_user(/* current->thread.address */ 0, &sc->fault_address);
1155 __put_user(mask, &sc->oldmask);
43fff238
FB
1156}
1157
579a97f7 1158static inline abi_ulong
624f7979 1159get_sigframe(struct target_sigaction *ka, CPUState *regs, int framesize)
43fff238
FB
1160{
1161 unsigned long sp = regs->regs[13];
1162
43fff238
FB
1163 /*
1164 * This is the X/Open sanctioned signal stack switching.
1165 */
624f7979 1166 if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
a04e134a 1167 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
43fff238
FB
1168 /*
1169 * ATPCS B01 mandates 8-byte alignment
1170 */
579a97f7 1171 return (sp - framesize) & ~7;
43fff238
FB
1172}
1173
1174static int
624f7979 1175setup_return(CPUState *env, struct target_sigaction *ka,
f8b0aa25 1176 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
43fff238 1177{
624f7979 1178 abi_ulong handler = ka->_sa_handler;
992f48a0 1179 abi_ulong retcode;
75b680e5 1180 int thumb = handler & 1;
43fff238 1181
624f7979
PB
1182 if (ka->sa_flags & TARGET_SA_RESTORER) {
1183 retcode = ka->sa_restorer;
43fff238
FB
1184 } else {
1185 unsigned int idx = thumb;
1186
624f7979 1187 if (ka->sa_flags & TARGET_SA_SIGINFO)
43fff238
FB
1188 idx += 2;
1189
1190 if (__put_user(retcodes[idx], rc))
1191 return 1;
1192#if 0
992f48a0
BS
1193 flush_icache_range((abi_ulong)rc,
1194 (abi_ulong)(rc + 1));
43fff238 1195#endif
f8b0aa25 1196 retcode = rc_addr + thumb;
43fff238
FB
1197 }
1198
1199 env->regs[0] = usig;
f8b0aa25 1200 env->regs[13] = frame_addr;
43fff238
FB
1201 env->regs[14] = retcode;
1202 env->regs[15] = handler & (thumb ? ~1 : ~3);
75b680e5 1203 env->thumb = thumb;
43fff238 1204
b5ff1b31 1205#if 0
43fff238
FB
1206#ifdef TARGET_CONFIG_CPU_32
1207 env->cpsr = cpsr;
b5ff1b31 1208#endif
43fff238
FB
1209#endif
1210
1211 return 0;
1212}
1213
a8c33204
PB
1214static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
1215 target_sigset_t *set, CPUState *env)
1216{
1217 struct target_sigaltstack stack;
1218 int i;
1219
1220 /* Clear all the bits of the ucontext we don't use. */
1221 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1222
1223 memset(&stack, 0, sizeof(stack));
1224 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1225 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1226 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1227 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1228
1229 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
1230 /* FIXME: Save coprocessor signal frame. */
1231 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1232 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1233 }
1234}
1235
579a97f7 1236/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
624f7979 1237static void setup_frame_v1(int usig, struct target_sigaction *ka,
a8c33204 1238 target_sigset_t *set, CPUState *regs)
43fff238 1239{
a8c33204 1240 struct sigframe_v1 *frame;
579a97f7 1241 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
a8c33204 1242 int i;
43fff238 1243
579a97f7
FB
1244 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1245 return;
1246
a8c33204 1247 setup_sigcontext(&frame->sc, regs, set->sig[0]);
43fff238 1248
9231944d
FB
1249 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1250 if (__put_user(set->sig[i], &frame->extramask[i - 1]))
579a97f7 1251 goto end;
43fff238
FB
1252 }
1253
a8c33204
PB
1254 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1255 frame_addr + offsetof(struct sigframe_v1, retcode));
579a97f7
FB
1256
1257end:
1258 unlock_user_struct(frame, frame_addr, 1);
a8c33204
PB
1259}
1260
624f7979 1261static void setup_frame_v2(int usig, struct target_sigaction *ka,
a8c33204
PB
1262 target_sigset_t *set, CPUState *regs)
1263{
1264 struct sigframe_v2 *frame;
1265 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1266
1267 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1268 return;
1269
1270 setup_sigframe_v2(&frame->uc, set, regs);
1271
1272 setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1273 frame_addr + offsetof(struct sigframe_v2, retcode));
1274
1275 unlock_user_struct(frame, frame_addr, 1);
1276}
1277
624f7979 1278static void setup_frame(int usig, struct target_sigaction *ka,
a8c33204
PB
1279 target_sigset_t *set, CPUState *regs)
1280{
1281 if (get_osversion() >= 0x020612) {
1282 setup_frame_v2(usig, ka, set, regs);
1283 } else {
1284 setup_frame_v1(usig, ka, set, regs);
1285 }
43fff238
FB
1286}
1287
579a97f7 1288/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
624f7979 1289static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
a745ec6d
PB
1290 target_siginfo_t *info,
1291 target_sigset_t *set, CPUState *env)
43fff238 1292{
a745ec6d 1293 struct rt_sigframe_v1 *frame;
579a97f7 1294 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
a04e134a 1295 struct target_sigaltstack stack;
a8c33204 1296 int i;
f8b0aa25 1297 abi_ulong info_addr, uc_addr;
43fff238 1298
579a97f7 1299 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
edf779ff
FB
1300 return /* 1 */;
1301
a745ec6d 1302 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
a8c33204 1303 __put_user(info_addr, &frame->pinfo);
a745ec6d 1304 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
a8c33204
PB
1305 __put_user(uc_addr, &frame->puc);
1306 copy_siginfo_to_user(&frame->info, info);
43fff238
FB
1307
1308 /* Clear all the bits of the ucontext we don't use. */
a745ec6d 1309 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
43fff238 1310
a04e134a
TS
1311 memset(&stack, 0, sizeof(stack));
1312 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1313 __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1314 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
775b58d8 1315 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
a04e134a 1316
a8c33204 1317 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
9231944d 1318 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
b8076a74 1319 if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
579a97f7 1320 goto end;
9231944d 1321 }
43fff238 1322
a8c33204
PB
1323 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1324 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
a745ec6d 1325
a8c33204
PB
1326 env->regs[1] = info_addr;
1327 env->regs[2] = uc_addr;
a745ec6d
PB
1328
1329end:
1330 unlock_user_struct(frame, frame_addr, 1);
a745ec6d
PB
1331}
1332
624f7979 1333static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
a745ec6d
PB
1334 target_siginfo_t *info,
1335 target_sigset_t *set, CPUState *env)
1336{
1337 struct rt_sigframe_v2 *frame;
1338 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
a745ec6d
PB
1339 abi_ulong info_addr, uc_addr;
1340
1341 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1342 return /* 1 */;
1343
1344 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1345 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
a8c33204 1346 copy_siginfo_to_user(&frame->info, info);
a745ec6d 1347
a8c33204 1348 setup_sigframe_v2(&frame->uc, set, env);
a745ec6d 1349
a8c33204
PB
1350 setup_return(env, ka, &frame->retcode, frame_addr, usig,
1351 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
a745ec6d 1352
a8c33204
PB
1353 env->regs[1] = info_addr;
1354 env->regs[2] = uc_addr;
43fff238 1355
579a97f7 1356 unlock_user_struct(frame, frame_addr, 1);
43fff238
FB
1357}
1358
624f7979 1359static void setup_rt_frame(int usig, struct target_sigaction *ka,
a745ec6d
PB
1360 target_siginfo_t *info,
1361 target_sigset_t *set, CPUState *env)
1362{
1363 if (get_osversion() >= 0x020612) {
1364 setup_rt_frame_v2(usig, ka, info, set, env);
1365 } else {
1366 setup_rt_frame_v1(usig, ka, info, set, env);
1367 }
1368}
1369
43fff238
FB
1370static int
1371restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
1372{
1373 int err = 0;
b5ff1b31 1374 uint32_t cpsr;
43fff238
FB
1375
1376 __get_user_error(env->regs[0], &sc->arm_r0, err);
1377 __get_user_error(env->regs[1], &sc->arm_r1, err);
1378 __get_user_error(env->regs[2], &sc->arm_r2, err);
1379 __get_user_error(env->regs[3], &sc->arm_r3, err);
1380 __get_user_error(env->regs[4], &sc->arm_r4, err);
1381 __get_user_error(env->regs[5], &sc->arm_r5, err);
1382 __get_user_error(env->regs[6], &sc->arm_r6, err);
1383 __get_user_error(env->regs[7], &sc->arm_r7, err);
1384 __get_user_error(env->regs[8], &sc->arm_r8, err);
1385 __get_user_error(env->regs[9], &sc->arm_r9, err);
1386 __get_user_error(env->regs[10], &sc->arm_r10, err);
1387 __get_user_error(env->regs[11], &sc->arm_fp, err);
1388 __get_user_error(env->regs[12], &sc->arm_ip, err);
1389 __get_user_error(env->regs[13], &sc->arm_sp, err);
1390 __get_user_error(env->regs[14], &sc->arm_lr, err);
1391 __get_user_error(env->regs[15], &sc->arm_pc, err);
1392#ifdef TARGET_CONFIG_CPU_32
b5ff1b31 1393 __get_user_error(cpsr, &sc->arm_cpsr, err);
75b680e5 1394 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
43fff238
FB
1395#endif
1396
1397 err |= !valid_user_regs(env);
1398
1399 return err;
1400}
1401
dc7eea67 1402static long do_sigreturn_v1(CPUState *env)
43fff238 1403{
f8b0aa25 1404 abi_ulong frame_addr;
a8c33204 1405 struct sigframe_v1 *frame;
43fff238
FB
1406 target_sigset_t set;
1407 sigset_t host_set;
9231944d 1408 int i;
43fff238
FB
1409
1410 /*
1411 * Since we stacked the signal on a 64-bit boundary,
1412 * then 'sp' should be word aligned here. If it's
1413 * not, then the user is trying to mess with us.
1414 */
1415 if (env->regs[13] & 7)
1416 goto badframe;
1417
f8b0aa25
FB
1418 frame_addr = env->regs[13];
1419 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1420 goto badframe;
43fff238 1421
9231944d
FB
1422 if (__get_user(set.sig[0], &frame->sc.oldmask))
1423 goto badframe;
1424 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1425 if (__get_user(set.sig[i], &frame->extramask[i - 1]))
1426 goto badframe;
1427 }
43fff238 1428
9231944d 1429 target_to_host_sigset_internal(&host_set, &set);
43fff238
FB
1430 sigprocmask(SIG_SETMASK, &host_set, NULL);
1431
1432 if (restore_sigcontext(env, &frame->sc))
1433 goto badframe;
1434
1435#if 0
1436 /* Send SIGTRAP if we're single-stepping */
1437 if (ptrace_cancel_bpt(current))
1438 send_sig(SIGTRAP, current, 1);
1439#endif
f8b0aa25
FB
1440 unlock_user_struct(frame, frame_addr, 0);
1441 return env->regs[0];
43fff238
FB
1442
1443badframe:
f8b0aa25 1444 unlock_user_struct(frame, frame_addr, 0);
43fff238
FB
1445 force_sig(SIGSEGV /* , current */);
1446 return 0;
1447}
1448
a8c33204
PB
1449static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
1450 struct target_ucontext_v2 *uc)
1451{
1452 sigset_t host_set;
1453
1454 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
1455 sigprocmask(SIG_SETMASK, &host_set, NULL);
1456
1457 if (restore_sigcontext(env, &uc->tuc_mcontext))
1458 return 1;
1459
1460 if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1461 return 1;
1462
1463#if 0
1464 /* Send SIGTRAP if we're single-stepping */
1465 if (ptrace_cancel_bpt(current))
1466 send_sig(SIGTRAP, current, 1);
1467#endif
1468
1469 return 0;
1470}
1471
dc7eea67 1472static long do_sigreturn_v2(CPUState *env)
a8c33204
PB
1473{
1474 abi_ulong frame_addr;
1475 struct sigframe_v2 *frame;
1476
1477 /*
1478 * Since we stacked the signal on a 64-bit boundary,
1479 * then 'sp' should be word aligned here. If it's
1480 * not, then the user is trying to mess with us.
1481 */
1482 if (env->regs[13] & 7)
1483 goto badframe;
1484
1485 frame_addr = env->regs[13];
1486 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1487 goto badframe;
1488
1489 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
1490 goto badframe;
1491
1492 unlock_user_struct(frame, frame_addr, 0);
1493 return env->regs[0];
1494
1495badframe:
1496 unlock_user_struct(frame, frame_addr, 0);
1497 force_sig(SIGSEGV /* , current */);
1498 return 0;
1499}
1500
1501long do_sigreturn(CPUState *env)
1502{
1503 if (get_osversion() >= 0x020612) {
1504 return do_sigreturn_v2(env);
1505 } else {
1506 return do_sigreturn_v1(env);
1507 }
1508}
1509
dc7eea67 1510static long do_rt_sigreturn_v1(CPUState *env)
43fff238 1511{
f8b0aa25 1512 abi_ulong frame_addr;
a745ec6d
PB
1513 struct rt_sigframe_v1 *frame;
1514 sigset_t host_set;
1515
1516 /*
1517 * Since we stacked the signal on a 64-bit boundary,
1518 * then 'sp' should be word aligned here. If it's
1519 * not, then the user is trying to mess with us.
1520 */
1521 if (env->regs[13] & 7)
1522 goto badframe;
1523
1524 frame_addr = env->regs[13];
1525 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1526 goto badframe;
1527
1528 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
1529 sigprocmask(SIG_SETMASK, &host_set, NULL);
1530
1531 if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
1532 goto badframe;
1533
1534 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1535 goto badframe;
1536
1537#if 0
1538 /* Send SIGTRAP if we're single-stepping */
1539 if (ptrace_cancel_bpt(current))
1540 send_sig(SIGTRAP, current, 1);
1541#endif
1542 unlock_user_struct(frame, frame_addr, 0);
1543 return env->regs[0];
1544
1545badframe:
1546 unlock_user_struct(frame, frame_addr, 0);
1547 force_sig(SIGSEGV /* , current */);
1548 return 0;
1549}
1550
dc7eea67 1551static long do_rt_sigreturn_v2(CPUState *env)
a745ec6d
PB
1552{
1553 abi_ulong frame_addr;
1554 struct rt_sigframe_v2 *frame;
43fff238
FB
1555
1556 /*
1557 * Since we stacked the signal on a 64-bit boundary,
1558 * then 'sp' should be word aligned here. If it's
1559 * not, then the user is trying to mess with us.
1560 */
1561 if (env->regs[13] & 7)
1562 goto badframe;
1563
f8b0aa25
FB
1564 frame_addr = env->regs[13];
1565 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1566 goto badframe;
43fff238 1567
a8c33204
PB
1568 if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
1569 goto badframe;
a04e134a 1570
f8b0aa25 1571 unlock_user_struct(frame, frame_addr, 0);
43fff238
FB
1572 return env->regs[0];
1573
1574badframe:
f8b0aa25 1575 unlock_user_struct(frame, frame_addr, 0);
43fff238
FB
1576 force_sig(SIGSEGV /* , current */);
1577 return 0;
1578}
1579
a745ec6d
PB
1580long do_rt_sigreturn(CPUState *env)
1581{
1582 if (get_osversion() >= 0x020612) {
1583 return do_rt_sigreturn_v2(env);
1584 } else {
1585 return do_rt_sigreturn_v1(env);
1586 }
1587}
1588
6d5e216d 1589#elif defined(TARGET_SPARC)
80a9d035 1590
6d5e216d
FB
1591#define __SUNOS_MAXWIN 31
1592
1593/* This is what SunOS does, so shall I. */
1594struct target_sigcontext {
992f48a0 1595 abi_ulong sigc_onstack; /* state to restore */
6d5e216d 1596
992f48a0
BS
1597 abi_ulong sigc_mask; /* sigmask to restore */
1598 abi_ulong sigc_sp; /* stack pointer */
1599 abi_ulong sigc_pc; /* program counter */
1600 abi_ulong sigc_npc; /* next program counter */
1601 abi_ulong sigc_psr; /* for condition codes etc */
1602 abi_ulong sigc_g1; /* User uses these two registers */
1603 abi_ulong sigc_o0; /* within the trampoline code. */
6d5e216d
FB
1604
1605 /* Now comes information regarding the users window set
1606 * at the time of the signal.
1607 */
992f48a0 1608 abi_ulong sigc_oswins; /* outstanding windows */
6d5e216d
FB
1609
1610 /* stack ptrs for each regwin buf */
1611 char *sigc_spbuf[__SUNOS_MAXWIN];
1612
1613 /* Windows to restore after signal */
1614 struct {
992f48a0
BS
1615 abi_ulong locals[8];
1616 abi_ulong ins[8];
6d5e216d
FB
1617 } sigc_wbuf[__SUNOS_MAXWIN];
1618};
1619/* A Sparc stack frame */
1620struct sparc_stackf {
992f48a0
BS
1621 abi_ulong locals[8];
1622 abi_ulong ins[6];
6d5e216d 1623 struct sparc_stackf *fp;
992f48a0 1624 abi_ulong callers_pc;
6d5e216d 1625 char *structptr;
992f48a0
BS
1626 abi_ulong xargs[6];
1627 abi_ulong xxargs[1];
6d5e216d
FB
1628};
1629
1630typedef struct {
1631 struct {
992f48a0
BS
1632 abi_ulong psr;
1633 abi_ulong pc;
1634 abi_ulong npc;
1635 abi_ulong y;
1636 abi_ulong u_regs[16]; /* globals and ins */
6d5e216d
FB
1637 } si_regs;
1638 int si_mask;
1639} __siginfo_t;
1640
1641typedef struct {
1642 unsigned long si_float_regs [32];
1643 unsigned long si_fsr;
1644 unsigned long si_fpqdepth;
1645 struct {
1646 unsigned long *insn_addr;
1647 unsigned long insn;
1648 } si_fpqueue [16];
74ccb34e 1649} qemu_siginfo_fpu_t;
6d5e216d
FB
1650
1651
1652struct target_signal_frame {
1653 struct sparc_stackf ss;
1654 __siginfo_t info;
f8b0aa25 1655 abi_ulong fpu_save;
992f48a0
BS
1656 abi_ulong insns[2] __attribute__ ((aligned (8)));
1657 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
1658 abi_ulong extra_size; /* Should be 0 */
74ccb34e 1659 qemu_siginfo_fpu_t fpu_state;
6d5e216d
FB
1660};
1661struct target_rt_signal_frame {
1662 struct sparc_stackf ss;
1663 siginfo_t info;
992f48a0 1664 abi_ulong regs[20];
6d5e216d 1665 sigset_t mask;
f8b0aa25 1666 abi_ulong fpu_save;
6d5e216d
FB
1667 unsigned int insns[2];
1668 stack_t stack;
1669 unsigned int extra_size; /* Should be 0 */
74ccb34e 1670 qemu_siginfo_fpu_t fpu_state;
6d5e216d
FB
1671};
1672
e80cfcfc
FB
1673#define UREG_O0 16
1674#define UREG_O6 22
1675#define UREG_I0 0
1676#define UREG_I1 1
1677#define UREG_I2 2
5bfb56b2
BS
1678#define UREG_I3 3
1679#define UREG_I4 4
1680#define UREG_I5 5
e80cfcfc
FB
1681#define UREG_I6 6
1682#define UREG_I7 7
1683#define UREG_L0 8
6d5e216d
FB
1684#define UREG_FP UREG_I6
1685#define UREG_SP UREG_O6
1686
624f7979 1687static inline abi_ulong get_sigframe(struct target_sigaction *sa,
459a4017 1688 CPUState *env, unsigned long framesize)
6d5e216d 1689{
459a4017 1690 abi_ulong sp;
6d5e216d
FB
1691
1692 sp = env->regwptr[UREG_FP];
6d5e216d
FB
1693
1694 /* This is the X/Open sanctioned signal stack switching. */
624f7979 1695 if (sa->sa_flags & TARGET_SA_ONSTACK) {
a04e134a
TS
1696 if (!on_sig_stack(sp)
1697 && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
1698 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
6d5e216d 1699 }
459a4017 1700 return sp - framesize;
6d5e216d
FB
1701}
1702
1703static int
992f48a0 1704setup___siginfo(__siginfo_t *si, CPUState *env, abi_ulong mask)
6d5e216d
FB
1705{
1706 int err = 0, i;
1707
6d5e216d 1708 err |= __put_user(env->psr, &si->si_regs.psr);
6d5e216d
FB
1709 err |= __put_user(env->pc, &si->si_regs.pc);
1710 err |= __put_user(env->npc, &si->si_regs.npc);
1711 err |= __put_user(env->y, &si->si_regs.y);
a315a145 1712 for (i=0; i < 8; i++) {
6d5e216d
FB
1713 err |= __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
1714 }
a315a145 1715 for (i=0; i < 8; i++) {
e80cfcfc 1716 err |= __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
6d5e216d 1717 }
6d5e216d
FB
1718 err |= __put_user(mask, &si->si_mask);
1719 return err;
1720}
e80cfcfc 1721
80a9d035 1722#if 0
6d5e216d
FB
1723static int
1724setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
1725 CPUState *env, unsigned long mask)
1726{
1727 int err = 0;
1728
1729 err |= __put_user(mask, &sc->sigc_mask);
1730 err |= __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
1731 err |= __put_user(env->pc, &sc->sigc_pc);
1732 err |= __put_user(env->npc, &sc->sigc_npc);
1733 err |= __put_user(env->psr, &sc->sigc_psr);
1734 err |= __put_user(env->gregs[1], &sc->sigc_g1);
1735 err |= __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
1736
1737 return err;
1738}
80a9d035 1739#endif
6d5e216d
FB
1740#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
1741
624f7979 1742static void setup_frame(int sig, struct target_sigaction *ka,
6d5e216d
FB
1743 target_sigset_t *set, CPUState *env)
1744{
459a4017 1745 abi_ulong sf_addr;
6d5e216d
FB
1746 struct target_signal_frame *sf;
1747 int sigframe_size, err, i;
1748
1749 /* 1. Make sure everything is clean */
1750 //synchronize_user_stack();
1751
1752 sigframe_size = NF_ALIGNEDSZ;
459a4017 1753 sf_addr = get_sigframe(ka, env, sigframe_size);
6d5e216d 1754
459a4017
FB
1755 sf = lock_user(VERIFY_WRITE, sf_addr,
1756 sizeof(struct target_signal_frame), 0);
1757 if (!sf)
1758 goto sigsegv;
1759
e80cfcfc 1760 //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
6d5e216d
FB
1761#if 0
1762 if (invalid_frame_pointer(sf, sigframe_size))
1763 goto sigill_and_return;
1764#endif
1765 /* 2. Save the current process state */
1766 err = setup___siginfo(&sf->info, env, set->sig[0]);
1767 err |= __put_user(0, &sf->extra_size);
1768
1769 //err |= save_fpu_state(regs, &sf->fpu_state);
1770 //err |= __put_user(&sf->fpu_state, &sf->fpu_save);
1771
1772 err |= __put_user(set->sig[0], &sf->info.si_mask);
1773 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
1774 err |= __put_user(set->sig[i + 1], &sf->extramask[i]);
1775 }
1776
a315a145 1777 for (i = 0; i < 8; i++) {
e80cfcfc 1778 err |= __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
6d5e216d 1779 }
a315a145 1780 for (i = 0; i < 8; i++) {
e80cfcfc 1781 err |= __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
6d5e216d 1782 }
6d5e216d
FB
1783 if (err)
1784 goto sigsegv;
1785
1786 /* 3. signal handler back-trampoline and parameters */
459a4017 1787 env->regwptr[UREG_FP] = sf_addr;
6d5e216d 1788 env->regwptr[UREG_I0] = sig;
459a4017
FB
1789 env->regwptr[UREG_I1] = sf_addr +
1790 offsetof(struct target_signal_frame, info);
1791 env->regwptr[UREG_I2] = sf_addr +
1792 offsetof(struct target_signal_frame, info);
6d5e216d
FB
1793
1794 /* 4. signal handler */
624f7979 1795 env->pc = ka->_sa_handler;
6d5e216d
FB
1796 env->npc = (env->pc + 4);
1797 /* 5. return to kernel instructions */
624f7979
PB
1798 if (ka->sa_restorer)
1799 env->regwptr[UREG_I7] = ka->sa_restorer;
6d5e216d 1800 else {
775b58d8 1801 uint32_t val32;
459a4017
FB
1802
1803 env->regwptr[UREG_I7] = sf_addr +
1804 offsetof(struct target_signal_frame, insns) - 2 * 4;
6d5e216d
FB
1805
1806 /* mov __NR_sigreturn, %g1 */
775b58d8
FB
1807 val32 = 0x821020d8;
1808 err |= __put_user(val32, &sf->insns[0]);
6d5e216d
FB
1809
1810 /* t 0x10 */
775b58d8
FB
1811 val32 = 0x91d02010;
1812 err |= __put_user(val32, &sf->insns[1]);
6d5e216d
FB
1813 if (err)
1814 goto sigsegv;
1815
1816 /* Flush instruction space. */
1817 //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
80a9d035 1818 // tb_flush(env);
6d5e216d 1819 }
459a4017 1820 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
6d5e216d 1821 return;
459a4017
FB
1822#if 0
1823sigill_and_return:
6d5e216d 1824 force_sig(TARGET_SIGILL);
459a4017 1825#endif
6d5e216d 1826sigsegv:
e80cfcfc 1827 //fprintf(stderr, "force_sig\n");
459a4017 1828 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
6d5e216d
FB
1829 force_sig(TARGET_SIGSEGV);
1830}
1831static inline int
74ccb34e 1832restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu)
6d5e216d
FB
1833{
1834 int err;
1835#if 0
1836#ifdef CONFIG_SMP
1837 if (current->flags & PF_USEDFPU)
1838 regs->psr &= ~PSR_EF;
1839#else
1840 if (current == last_task_used_math) {
1841 last_task_used_math = 0;
1842 regs->psr &= ~PSR_EF;
1843 }
1844#endif
1845 current->used_math = 1;
1846 current->flags &= ~PF_USEDFPU;
1847#endif
1848#if 0
1849 if (verify_area (VERIFY_READ, fpu, sizeof(*fpu)))
1850 return -EFAULT;
1851#endif
1852
fafffaef
FB
1853#if 0
1854 /* XXX: incorrect */
6d5e216d
FB
1855 err = __copy_from_user(&env->fpr[0], &fpu->si_float_regs[0],
1856 (sizeof(unsigned long) * 32));
fafffaef 1857#endif
6d5e216d
FB
1858 err |= __get_user(env->fsr, &fpu->si_fsr);
1859#if 0
1860 err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
1861 if (current->thread.fpqdepth != 0)
1862 err |= __copy_from_user(&current->thread.fpqueue[0],
1863 &fpu->si_fpqueue[0],
1864 ((sizeof(unsigned long) +
1865 (sizeof(unsigned long *)))*16));
1866#endif
1867 return err;
1868}
1869
1870
624f7979 1871static void setup_rt_frame(int sig, struct target_sigaction *ka,
6d5e216d
FB
1872 target_siginfo_t *info,
1873 target_sigset_t *set, CPUState *env)
1874{
1875 fprintf(stderr, "setup_rt_frame: not implemented\n");
1876}
1877
1878long do_sigreturn(CPUState *env)
1879{
f8b0aa25 1880 abi_ulong sf_addr;
6d5e216d 1881 struct target_signal_frame *sf;
e80cfcfc 1882 uint32_t up_psr, pc, npc;
6d5e216d 1883 target_sigset_t set;
e80cfcfc 1884 sigset_t host_set;
f8b0aa25 1885 abi_ulong fpu_save_addr;
e80cfcfc 1886 int err, i;
6d5e216d 1887
f8b0aa25
FB
1888 sf_addr = env->regwptr[UREG_FP];
1889 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
1890 goto segv_and_exit;
80a9d035 1891#if 0
e80cfcfc
FB
1892 fprintf(stderr, "sigreturn\n");
1893 fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
80a9d035 1894#endif
e80cfcfc 1895 //cpu_dump_state(env, stderr, fprintf, 0);
6d5e216d
FB
1896
1897 /* 1. Make sure we are not getting garbage from the user */
6d5e216d 1898
f8b0aa25 1899 if (sf_addr & 3)
6d5e216d
FB
1900 goto segv_and_exit;
1901
1902 err = __get_user(pc, &sf->info.si_regs.pc);
1903 err |= __get_user(npc, &sf->info.si_regs.npc);
1904
6d5e216d
FB
1905 if ((pc | npc) & 3)
1906 goto segv_and_exit;
1907
1908 /* 2. Restore the state */
e80cfcfc
FB
1909 err |= __get_user(up_psr, &sf->info.si_regs.psr);
1910
6d5e216d 1911 /* User can only change condition codes and FPU enabling in %psr. */
a315a145
FB
1912 env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
1913 | (env->psr & ~(PSR_ICC /* | PSR_EF */));
1914
1915 env->pc = pc;
1916 env->npc = npc;
e80cfcfc 1917 err |= __get_user(env->y, &sf->info.si_regs.y);
a315a145 1918 for (i=0; i < 8; i++) {
e80cfcfc
FB
1919 err |= __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
1920 }
a315a145 1921 for (i=0; i < 8; i++) {
e80cfcfc
FB
1922 err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
1923 }
6d5e216d 1924
f8b0aa25 1925 err |= __get_user(fpu_save_addr, &sf->fpu_save);
6d5e216d 1926
e80cfcfc
FB
1927 //if (fpu_save)
1928 // err |= restore_fpu_state(env, fpu_save);
6d5e216d
FB
1929
1930 /* This is pretty much atomic, no amount locking would prevent
1931 * the races which exist anyways.
1932 */
1933 err |= __get_user(set.sig[0], &sf->info.si_mask);
e80cfcfc
FB
1934 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1935 err |= (__get_user(set.sig[i], &sf->extramask[i - 1]));
1936 }
1937
1938 target_to_host_sigset_internal(&host_set, &set);
1939 sigprocmask(SIG_SETMASK, &host_set, NULL);
6d5e216d
FB
1940
1941 if (err)
1942 goto segv_and_exit;
f8b0aa25 1943 unlock_user_struct(sf, sf_addr, 0);
6d5e216d
FB
1944 return env->regwptr[0];
1945
1946segv_and_exit:
f8b0aa25 1947 unlock_user_struct(sf, sf_addr, 0);
6d5e216d
FB
1948 force_sig(TARGET_SIGSEGV);
1949}
1950
1951long do_rt_sigreturn(CPUState *env)
1952{
1953 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 1954 return -TARGET_ENOSYS;
6d5e216d
FB
1955}
1956
459a4017 1957#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
5bfb56b2
BS
1958#define MC_TSTATE 0
1959#define MC_PC 1
1960#define MC_NPC 2
1961#define MC_Y 3
1962#define MC_G1 4
1963#define MC_G2 5
1964#define MC_G3 6
1965#define MC_G4 7
1966#define MC_G5 8
1967#define MC_G6 9
1968#define MC_G7 10
1969#define MC_O0 11
1970#define MC_O1 12
1971#define MC_O2 13
1972#define MC_O3 14
1973#define MC_O4 15
1974#define MC_O5 16
1975#define MC_O6 17
1976#define MC_O7 18
1977#define MC_NGREG 19
1978
992f48a0 1979typedef abi_ulong target_mc_greg_t;
5bfb56b2
BS
1980typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
1981
1982struct target_mc_fq {
992f48a0 1983 abi_ulong *mcfq_addr;
5bfb56b2
BS
1984 uint32_t mcfq_insn;
1985};
1986
1987struct target_mc_fpu {
1988 union {
1989 uint32_t sregs[32];
1990 uint64_t dregs[32];
1991 //uint128_t qregs[16];
1992 } mcfpu_fregs;
992f48a0
BS
1993 abi_ulong mcfpu_fsr;
1994 abi_ulong mcfpu_fprs;
1995 abi_ulong mcfpu_gsr;
5bfb56b2
BS
1996 struct target_mc_fq *mcfpu_fq;
1997 unsigned char mcfpu_qcnt;
1998 unsigned char mcfpu_qentsz;
1999 unsigned char mcfpu_enab;
2000};
2001typedef struct target_mc_fpu target_mc_fpu_t;
2002
2003typedef struct {
2004 target_mc_gregset_t mc_gregs;
2005 target_mc_greg_t mc_fp;
2006 target_mc_greg_t mc_i7;
2007 target_mc_fpu_t mc_fpregs;
2008} target_mcontext_t;
2009
2010struct target_ucontext {
2011 struct target_ucontext *uc_link;
992f48a0 2012 abi_ulong uc_flags;
5bfb56b2
BS
2013 target_sigset_t uc_sigmask;
2014 target_mcontext_t uc_mcontext;
2015};
2016
2017/* A V9 register window */
2018struct target_reg_window {
992f48a0
BS
2019 abi_ulong locals[8];
2020 abi_ulong ins[8];
5bfb56b2
BS
2021};
2022
2023#define TARGET_STACK_BIAS 2047
2024
2025/* {set, get}context() needed for 64-bit SparcLinux userland. */
2026void sparc64_set_context(CPUSPARCState *env)
2027{
459a4017
FB
2028 abi_ulong ucp_addr;
2029 struct target_ucontext *ucp;
5bfb56b2 2030 target_mc_gregset_t *grp;
992f48a0 2031 abi_ulong pc, npc, tstate;
459a4017 2032 abi_ulong fp, i7, w_addr;
5bfb56b2
BS
2033 unsigned char fenab;
2034 int err;
2035 unsigned int i;
5bfb56b2 2036
459a4017
FB
2037 ucp_addr = env->regwptr[UREG_I0];
2038 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
2039 goto do_sigsegv;
5bfb56b2 2040 grp = &ucp->uc_mcontext.mc_gregs;
579a97f7
FB
2041 err = __get_user(pc, &((*grp)[MC_PC]));
2042 err |= __get_user(npc, &((*grp)[MC_NPC]));
5bfb56b2
BS
2043 if (err || ((pc | npc) & 3))
2044 goto do_sigsegv;
2045 if (env->regwptr[UREG_I1]) {
2046 target_sigset_t target_set;
2047 sigset_t set;
2048
2049 if (TARGET_NSIG_WORDS == 1) {
579a97f7 2050 if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
5bfb56b2
BS
2051 goto do_sigsegv;
2052 } else {
459a4017
FB
2053 abi_ulong *src, *dst;
2054 src = ucp->uc_sigmask.sig;
2055 dst = target_set.sig;
992f48a0 2056 for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
5bfb56b2 2057 i++, dst++, src++)
459a4017 2058 err |= __get_user(*dst, src);
5bfb56b2
BS
2059 if (err)
2060 goto do_sigsegv;
2061 }
2062 target_to_host_sigset_internal(&set, &target_set);
2063 sigprocmask(SIG_SETMASK, &set, NULL);
2064 }
2065 env->pc = pc;
2066 env->npc = npc;
579a97f7
FB
2067 err |= __get_user(env->y, &((*grp)[MC_Y]));
2068 err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
5bfb56b2
BS
2069 env->asi = (tstate >> 24) & 0xff;
2070 PUT_CCR(env, tstate >> 32);
2071 PUT_CWP64(env, tstate & 0x1f);
579a97f7
FB
2072 err |= __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2073 err |= __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2074 err |= __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2075 err |= __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2076 err |= __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2077 err |= __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2078 err |= __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2079 err |= __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2080 err |= __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2081 err |= __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2082 err |= __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2083 err |= __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2084 err |= __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2085 err |= __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2086 err |= __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
2087
2088 err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp));
2089 err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7));
579a97f7 2090
459a4017
FB
2091 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2092 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2093 abi_ulong) != 0)
2094 goto do_sigsegv;
2095 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2096 abi_ulong) != 0)
2097 goto do_sigsegv;
579a97f7
FB
2098 err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
2099 err |= __get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
459a4017
FB
2100 {
2101 uint32_t *src, *dst;
2102 src = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2103 dst = env->fpr;
2104 /* XXX: check that the CPU storage is the same as user context */
2105 for (i = 0; i < 64; i++, dst++, src++)
2106 err |= __get_user(*dst, src);
2107 }
579a97f7
FB
2108 err |= __get_user(env->fsr,
2109 &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
2110 err |= __get_user(env->gsr,
2111 &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
5bfb56b2
BS
2112 if (err)
2113 goto do_sigsegv;
459a4017 2114 unlock_user_struct(ucp, ucp_addr, 0);
5bfb56b2
BS
2115 return;
2116 do_sigsegv:
459a4017 2117 unlock_user_struct(ucp, ucp_addr, 0);
5bfb56b2
BS
2118 force_sig(SIGSEGV);
2119}
2120
2121void sparc64_get_context(CPUSPARCState *env)
2122{
459a4017
FB
2123 abi_ulong ucp_addr;
2124 struct target_ucontext *ucp;
5bfb56b2
BS
2125 target_mc_gregset_t *grp;
2126 target_mcontext_t *mcp;
459a4017 2127 abi_ulong fp, i7, w_addr;
5bfb56b2
BS
2128 int err;
2129 unsigned int i;
5bfb56b2
BS
2130 target_sigset_t target_set;
2131 sigset_t set;
2132
459a4017
FB
2133 ucp_addr = env->regwptr[UREG_I0];
2134 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
2135 goto do_sigsegv;
2136
5bfb56b2
BS
2137 mcp = &ucp->uc_mcontext;
2138 grp = &mcp->mc_gregs;
2139
2140 /* Skip over the trap instruction, first. */
2141 env->pc = env->npc;
2142 env->npc += 4;
2143
2144 err = 0;
2145
2146 sigprocmask(0, NULL, &set);
2147 host_to_target_sigset_internal(&target_set, &set);
459a4017 2148 if (TARGET_NSIG_WORDS == 1) {
579a97f7
FB
2149 err |= __put_user(target_set.sig[0],
2150 (abi_ulong *)&ucp->uc_sigmask);
459a4017
FB
2151 } else {
2152 abi_ulong *src, *dst;
2153 src = target_set.sig;
2154 dst = ucp->uc_sigmask.sig;
992f48a0 2155 for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
5bfb56b2 2156 i++, dst++, src++)
459a4017 2157 err |= __put_user(*src, dst);
5bfb56b2
BS
2158 if (err)
2159 goto do_sigsegv;
2160 }
2161
459a4017
FB
2162 /* XXX: tstate must be saved properly */
2163 // err |= __put_user(env->tstate, &((*grp)[MC_TSTATE]));
579a97f7
FB
2164 err |= __put_user(env->pc, &((*grp)[MC_PC]));
2165 err |= __put_user(env->npc, &((*grp)[MC_NPC]));
2166 err |= __put_user(env->y, &((*grp)[MC_Y]));
2167 err |= __put_user(env->gregs[1], &((*grp)[MC_G1]));
2168 err |= __put_user(env->gregs[2], &((*grp)[MC_G2]));
2169 err |= __put_user(env->gregs[3], &((*grp)[MC_G3]));
2170 err |= __put_user(env->gregs[4], &((*grp)[MC_G4]));
2171 err |= __put_user(env->gregs[5], &((*grp)[MC_G5]));
2172 err |= __put_user(env->gregs[6], &((*grp)[MC_G6]));
2173 err |= __put_user(env->gregs[7], &((*grp)[MC_G7]));
2174 err |= __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2175 err |= __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2176 err |= __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2177 err |= __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2178 err |= __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2179 err |= __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2180 err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2181 err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
2182
459a4017
FB
2183 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2184 fp = i7 = 0;
2185 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
2186 abi_ulong) != 0)
2187 goto do_sigsegv;
2188 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
2189 abi_ulong) != 0)
2190 goto do_sigsegv;
579a97f7
FB
2191 err |= __put_user(fp, &(mcp->mc_fp));
2192 err |= __put_user(i7, &(mcp->mc_i7));
5bfb56b2 2193
459a4017
FB
2194 {
2195 uint32_t *src, *dst;
2196 src = env->fpr;
2197 dst = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2198 /* XXX: check that the CPU storage is the same as user context */
2199 for (i = 0; i < 64; i++, dst++, src++)
2200 err |= __put_user(*src, dst);
2201 }
579a97f7
FB
2202 err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2203 err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2204 err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
5bfb56b2
BS
2205
2206 if (err)
2207 goto do_sigsegv;
459a4017 2208 unlock_user_struct(ucp, ucp_addr, 1);
5bfb56b2
BS
2209 return;
2210 do_sigsegv:
459a4017 2211 unlock_user_struct(ucp, ucp_addr, 1);
5bfb56b2
BS
2212 force_sig(SIGSEGV);
2213}
2214#endif
d26bc211 2215#elif defined(TARGET_ABI_MIPSN64)
540635ba
TS
2216
2217# warning signal handling not implemented
2218
624f7979 2219static void setup_frame(int sig, struct target_sigaction *ka,
540635ba
TS
2220 target_sigset_t *set, CPUState *env)
2221{
2222 fprintf(stderr, "setup_frame: not implemented\n");
2223}
2224
624f7979 2225static void setup_rt_frame(int sig, struct target_sigaction *ka,
540635ba
TS
2226 target_siginfo_t *info,
2227 target_sigset_t *set, CPUState *env)
2228{
2229 fprintf(stderr, "setup_rt_frame: not implemented\n");
2230}
2231
2232long do_sigreturn(CPUState *env)
2233{
2234 fprintf(stderr, "do_sigreturn: not implemented\n");
f8b0aa25 2235 return -TARGET_ENOSYS;
540635ba
TS
2236}
2237
2238long do_rt_sigreturn(CPUState *env)
2239{
2240 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 2241 return -TARGET_ENOSYS;
540635ba
TS
2242}
2243
d26bc211 2244#elif defined(TARGET_ABI_MIPSN32)
540635ba
TS
2245
2246# warning signal handling not implemented
2247
624f7979 2248static void setup_frame(int sig, struct target_sigaction *ka,
540635ba
TS
2249 target_sigset_t *set, CPUState *env)
2250{
2251 fprintf(stderr, "setup_frame: not implemented\n");
2252}
2253
624f7979 2254static void setup_rt_frame(int sig, struct target_sigaction *ka,
540635ba
TS
2255 target_siginfo_t *info,
2256 target_sigset_t *set, CPUState *env)
2257{
2258 fprintf(stderr, "setup_rt_frame: not implemented\n");
2259}
2260
2261long do_sigreturn(CPUState *env)
2262{
2263 fprintf(stderr, "do_sigreturn: not implemented\n");
f8b0aa25 2264 return -TARGET_ENOSYS;
540635ba
TS
2265}
2266
2267long do_rt_sigreturn(CPUState *env)
2268{
2269 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 2270 return -TARGET_ENOSYS;
540635ba
TS
2271}
2272
d26bc211 2273#elif defined(TARGET_ABI_MIPSO32)
106ec879
FB
2274
2275struct target_sigcontext {
2276 uint32_t sc_regmask; /* Unused */
2277 uint32_t sc_status;
2278 uint64_t sc_pc;
2279 uint64_t sc_regs[32];
2280 uint64_t sc_fpregs[32];
2281 uint32_t sc_ownedfp; /* Unused */
2282 uint32_t sc_fpc_csr;
2283 uint32_t sc_fpc_eir; /* Unused */
2284 uint32_t sc_used_math;
2285 uint32_t sc_dsp; /* dsp status, was sc_ssflags */
2286 uint64_t sc_mdhi;
2287 uint64_t sc_mdlo;
2288 target_ulong sc_hi1; /* Was sc_cause */
2289 target_ulong sc_lo1; /* Was sc_badvaddr */
2290 target_ulong sc_hi2; /* Was sc_sigset[4] */
2291 target_ulong sc_lo2;
2292 target_ulong sc_hi3;
2293 target_ulong sc_lo3;
2294};
2295
2296struct sigframe {
2297 uint32_t sf_ass[4]; /* argument save space for o32 */
2298 uint32_t sf_code[2]; /* signal trampoline */
2299 struct target_sigcontext sf_sc;
2300 target_sigset_t sf_mask;
2301};
2302
2303/* Install trampoline to jump back from signal handler */
2304static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
2305{
2306 int err;
2307
2308 /*
2309 * Set up the return code ...
2310 *
2311 * li v0, __NR__foo_sigreturn
2312 * syscall
2313 */
2314
2315 err = __put_user(0x24020000 + syscall, tramp + 0);
2316 err |= __put_user(0x0000000c , tramp + 1);
2317 /* flush_cache_sigtramp((unsigned long) tramp); */
2318 return err;
2319}
2320
2321static inline int
2322setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
2323{
2324 int err = 0;
2325
b5dc7732 2326 err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
106ec879 2327
b5dc7732
TS
2328#define save_gp_reg(i) do { \
2329 err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \
106ec879
FB
2330 } while(0)
2331 __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
2332 save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
2333 save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
2334 save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
2335 save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
2336 save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
2337 save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
2338 save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
2339 save_gp_reg(31);
388bb21a 2340#undef save_gp_reg
106ec879 2341
b5dc7732
TS
2342 err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2343 err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
106ec879
FB
2344
2345 /* Not used yet, but might be useful if we ever have DSP suppport */
2346#if 0
2347 if (cpu_has_dsp) {
2348 err |= __put_user(mfhi1(), &sc->sc_hi1);
2349 err |= __put_user(mflo1(), &sc->sc_lo1);
2350 err |= __put_user(mfhi2(), &sc->sc_hi2);
2351 err |= __put_user(mflo2(), &sc->sc_lo2);
2352 err |= __put_user(mfhi3(), &sc->sc_hi3);
2353 err |= __put_user(mflo3(), &sc->sc_lo3);
2354 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2355 }
2356 /* same with 64 bit */
388bb21a 2357#ifdef CONFIG_64BIT
106ec879
FB
2358 err |= __put_user(regs->hi, &sc->sc_hi[0]);
2359 err |= __put_user(regs->lo, &sc->sc_lo[0]);
2360 if (cpu_has_dsp) {
2361 err |= __put_user(mfhi1(), &sc->sc_hi[1]);
2362 err |= __put_user(mflo1(), &sc->sc_lo[1]);
2363 err |= __put_user(mfhi2(), &sc->sc_hi[2]);
2364 err |= __put_user(mflo2(), &sc->sc_lo[2]);
2365 err |= __put_user(mfhi3(), &sc->sc_hi[3]);
2366 err |= __put_user(mflo3(), &sc->sc_lo[3]);
2367 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2368 }
388bb21a
TS
2369#endif
2370#endif
106ec879 2371
388bb21a 2372#if 0
106ec879
FB
2373 err |= __put_user(!!used_math(), &sc->sc_used_math);
2374
2375 if (!used_math())
2376 goto out;
2377
2378 /*
2379 * Save FPU state to signal context. Signal handler will "inherit"
2380 * current FPU state.
2381 */
2382 preempt_disable();
2383
2384 if (!is_fpu_owner()) {
2385 own_fpu();
2386 restore_fp(current);
2387 }
2388 err |= save_fp_context(sc);
2389
2390 preempt_enable();
2391 out:
2392#endif
2393 return err;
2394}
2395
2396static inline int
2397restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
2398{
2399 int err = 0;
2400
2401 err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
2402
b5dc7732
TS
2403 err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2404 err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
106ec879 2405
ead9360e 2406#define restore_gp_reg(i) do { \
b5dc7732 2407 err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \
106ec879
FB
2408 } while(0)
2409 restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
2410 restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
2411 restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
2412 restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
2413 restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
2414 restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
2415 restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
2416 restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
2417 restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
2418 restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
2419 restore_gp_reg(31);
388bb21a 2420#undef restore_gp_reg
106ec879
FB
2421
2422#if 0
2423 if (cpu_has_dsp) {
2424 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
2425 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
2426 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
2427 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
2428 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
2429 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
2430 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2431 }
388bb21a 2432#ifdef CONFIG_64BIT
106ec879
FB
2433 err |= __get_user(regs->hi, &sc->sc_hi[0]);
2434 err |= __get_user(regs->lo, &sc->sc_lo[0]);
2435 if (cpu_has_dsp) {
2436 err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
2437 err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
2438 err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
2439 err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
2440 err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
2441 err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
2442 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2443 }
388bb21a 2444#endif
106ec879
FB
2445
2446 err |= __get_user(used_math, &sc->sc_used_math);
2447 conditional_used_math(used_math);
2448
2449 preempt_disable();
2450
2451 if (used_math()) {
2452 /* restore fpu context if we have used it before */
2453 own_fpu();
2454 err |= restore_fp_context(sc);
2455 } else {
2456 /* signal handler may have used FPU. Give it up. */
2457 lose_fpu();
2458 }
2459
2460 preempt_enable();
2461#endif
2462 return err;
2463}
2464/*
2465 * Determine which stack to use..
2466 */
579a97f7 2467static inline abi_ulong
624f7979 2468get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
106ec879
FB
2469{
2470 unsigned long sp;
2471
2472 /* Default to using normal stack */
b5dc7732 2473 sp = regs->active_tc.gpr[29];
106ec879
FB
2474
2475 /*
2476 * FPU emulator may have it's own trampoline active just
2477 * above the user stack, 16-bytes before the next lowest
2478 * 16 byte boundary. Try to avoid trashing it.
2479 */
2480 sp -= 32;
2481
106ec879 2482 /* This is the X/Open sanctioned signal stack switching. */
624f7979 2483 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
a04e134a
TS
2484 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2485 }
106ec879 2486
579a97f7 2487 return (sp - frame_size) & ~7;
106ec879
FB
2488}
2489
579a97f7 2490/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
624f7979 2491static void setup_frame(int sig, struct target_sigaction * ka,
579a97f7 2492 target_sigset_t *set, CPUState *regs)
106ec879
FB
2493{
2494 struct sigframe *frame;
579a97f7 2495 abi_ulong frame_addr;
106ec879
FB
2496 int i;
2497
579a97f7
FB
2498 frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2499 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
106ec879
FB
2500 goto give_sigsegv;
2501
2502 install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2503
2504 if(setup_sigcontext(regs, &frame->sf_sc))
2505 goto give_sigsegv;
2506
2507 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2508 if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))
2509 goto give_sigsegv;
2510 }
2511
2512 /*
2513 * Arguments to signal handler:
2514 *
2515 * a0 = signal number
2516 * a1 = 0 (should be cause)
2517 * a2 = pointer to struct sigcontext
2518 *
2519 * $25 and PC point to the signal handler, $29 points to the
2520 * struct sigframe.
2521 */
b5dc7732
TS
2522 regs->active_tc.gpr[ 4] = sig;
2523 regs->active_tc.gpr[ 5] = 0;
2524 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2525 regs->active_tc.gpr[29] = frame_addr;
2526 regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
106ec879
FB
2527 /* The original kernel code sets CP0_EPC to the handler
2528 * since it returns to userland using eret
2529 * we cannot do this here, and we must set PC directly */
b5dc7732 2530 regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
579a97f7 2531 unlock_user_struct(frame, frame_addr, 1);
106ec879
FB
2532 return;
2533
2534give_sigsegv:
579a97f7 2535 unlock_user_struct(frame, frame_addr, 1);
106ec879 2536 force_sig(TARGET_SIGSEGV/*, current*/);
5fafdf24 2537 return;
106ec879
FB
2538}
2539
2540long do_sigreturn(CPUState *regs)
2541{
388bb21a 2542 struct sigframe *frame;
579a97f7 2543 abi_ulong frame_addr;
388bb21a
TS
2544 sigset_t blocked;
2545 target_sigset_t target_set;
2546 int i;
106ec879
FB
2547
2548#if defined(DEBUG_SIGNAL)
388bb21a 2549 fprintf(stderr, "do_sigreturn\n");
106ec879 2550#endif
b5dc7732 2551 frame_addr = regs->active_tc.gpr[29];
579a97f7 2552 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
106ec879
FB
2553 goto badframe;
2554
388bb21a 2555 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
106ec879
FB
2556 if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
2557 goto badframe;
388bb21a 2558 }
106ec879 2559
388bb21a
TS
2560 target_to_host_sigset_internal(&blocked, &target_set);
2561 sigprocmask(SIG_SETMASK, &blocked, NULL);
106ec879 2562
388bb21a 2563 if (restore_sigcontext(regs, &frame->sf_sc))
106ec879
FB
2564 goto badframe;
2565
2566#if 0
388bb21a
TS
2567 /*
2568 * Don't let your children do this ...
2569 */
2570 __asm__ __volatile__(
106ec879
FB
2571 "move\t$29, %0\n\t"
2572 "j\tsyscall_exit"
2573 :/* no outputs */
2574 :"r" (&regs));
388bb21a 2575 /* Unreached */
106ec879 2576#endif
3b46e624 2577
b5dc7732 2578 regs->active_tc.PC = regs->CP0_EPC;
388bb21a 2579 /* I am not sure this is right, but it seems to work
106ec879
FB
2580 * maybe a problem with nested signals ? */
2581 regs->CP0_EPC = 0;
2582 return 0;
2583
2584badframe:
388bb21a
TS
2585 force_sig(TARGET_SIGSEGV/*, current*/);
2586 return 0;
106ec879
FB
2587}
2588
624f7979 2589static void setup_rt_frame(int sig, struct target_sigaction *ka,
106ec879
FB
2590 target_siginfo_t *info,
2591 target_sigset_t *set, CPUState *env)
2592{
2593 fprintf(stderr, "setup_rt_frame: not implemented\n");
2594}
2595
2596long do_rt_sigreturn(CPUState *env)
2597{
2598 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 2599 return -TARGET_ENOSYS;
106ec879 2600}
6d5e216d 2601
c3b5bc8a
TS
2602#elif defined(TARGET_SH4)
2603
2604/*
2605 * code and data structures from linux kernel:
2606 * include/asm-sh/sigcontext.h
2607 * arch/sh/kernel/signal.c
2608 */
2609
2610struct target_sigcontext {
2611 target_ulong oldmask;
2612
2613 /* CPU registers */
2614 target_ulong sc_gregs[16];
2615 target_ulong sc_pc;
2616 target_ulong sc_pr;
2617 target_ulong sc_sr;
2618 target_ulong sc_gbr;
2619 target_ulong sc_mach;
2620 target_ulong sc_macl;
2621
2622 /* FPU registers */
2623 target_ulong sc_fpregs[16];
2624 target_ulong sc_xfpregs[16];
2625 unsigned int sc_fpscr;
2626 unsigned int sc_fpul;
2627 unsigned int sc_ownedfp;
2628};
2629
2630struct target_sigframe
2631{
2632 struct target_sigcontext sc;
2633 target_ulong extramask[TARGET_NSIG_WORDS-1];
2634 uint16_t retcode[3];
2635};
2636
2637
2638struct target_ucontext {
2639 target_ulong uc_flags;
2640 struct target_ucontext *uc_link;
2641 target_stack_t uc_stack;
2642 struct target_sigcontext uc_mcontext;
2643 target_sigset_t uc_sigmask; /* mask last for extensibility */
2644};
2645
2646struct target_rt_sigframe
2647{
2648 struct target_siginfo info;
2649 struct target_ucontext uc;
2650 uint16_t retcode[3];
2651};
2652
2653
2654#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
2655#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
2656
624f7979 2657static abi_ulong get_sigframe(struct target_sigaction *ka,
c3b5bc8a
TS
2658 unsigned long sp, size_t frame_size)
2659{
624f7979 2660 if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
c3b5bc8a
TS
2661 sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2662 }
2663
2664 return (sp - frame_size) & -8ul;
2665}
2666
2667static int setup_sigcontext(struct target_sigcontext *sc,
2668 CPUState *regs, unsigned long mask)
2669{
2670 int err = 0;
2671
2672#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
2673 COPY(gregs[0]); COPY(gregs[1]);
2674 COPY(gregs[2]); COPY(gregs[3]);
2675 COPY(gregs[4]); COPY(gregs[5]);
2676 COPY(gregs[6]); COPY(gregs[7]);
2677 COPY(gregs[8]); COPY(gregs[9]);
2678 COPY(gregs[10]); COPY(gregs[11]);
2679 COPY(gregs[12]); COPY(gregs[13]);
2680 COPY(gregs[14]); COPY(gregs[15]);
2681 COPY(gbr); COPY(mach);
2682 COPY(macl); COPY(pr);
2683 COPY(sr); COPY(pc);
2684#undef COPY
2685
2686 /* todo: save FPU registers here */
2687
2688 /* non-iBCS2 extensions.. */
2689 err |= __put_user(mask, &sc->oldmask);
2690
2691 return err;
2692}
2693
2694static int restore_sigcontext(struct CPUState *regs,
2695 struct target_sigcontext *sc)
2696{
2697 unsigned int err = 0;
2698
2699#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
2700 COPY(gregs[1]);
2701 COPY(gregs[2]); COPY(gregs[3]);
2702 COPY(gregs[4]); COPY(gregs[5]);
2703 COPY(gregs[6]); COPY(gregs[7]);
2704 COPY(gregs[8]); COPY(gregs[9]);
2705 COPY(gregs[10]); COPY(gregs[11]);
2706 COPY(gregs[12]); COPY(gregs[13]);
2707 COPY(gregs[14]); COPY(gregs[15]);
2708 COPY(gbr); COPY(mach);
2709 COPY(macl); COPY(pr);
2710 COPY(sr); COPY(pc);
2711#undef COPY
2712
2713 /* todo: restore FPU registers here */
2714
2715 regs->tra = -1; /* disable syscall checks */
2716 return err;
2717}
2718
624f7979 2719static void setup_frame(int sig, struct target_sigaction *ka,
c3b5bc8a
TS
2720 target_sigset_t *set, CPUState *regs)
2721{
2722 struct target_sigframe *frame;
2723 abi_ulong frame_addr;
2724 int i;
2725 int err = 0;
2726 int signal;
2727
2728 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
2729 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2730 goto give_sigsegv;
2731
2732 signal = current_exec_domain_sig(sig);
2733
2734 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
2735
2736 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
2737 err |= __put_user(set->sig[i + 1], &frame->extramask[i]);
2738 }
2739
2740 /* Set up to return from userspace. If provided, use a stub
2741 already in userspace. */
624f7979
PB
2742 if (ka->sa_flags & TARGET_SA_RESTORER) {
2743 regs->pr = (unsigned long) ka->sa_restorer;
c3b5bc8a
TS
2744 } else {
2745 /* Generate return code (system call to sigreturn) */
2746 err |= __put_user(MOVW(2), &frame->retcode[0]);
2747 err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
2748 err |= __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
2749 regs->pr = (unsigned long) frame->retcode;
2750 }
2751
2752 if (err)
2753 goto give_sigsegv;
2754
2755 /* Set up registers for signal handler */
2756 regs->gregs[15] = (unsigned long) frame;
2757 regs->gregs[4] = signal; /* Arg for signal handler */
2758 regs->gregs[5] = 0;
2759 regs->gregs[6] = (unsigned long) &frame->sc;
624f7979 2760 regs->pc = (unsigned long) ka->_sa_handler;
c3b5bc8a
TS
2761
2762 unlock_user_struct(frame, frame_addr, 1);
2763 return;
2764
2765give_sigsegv:
2766 unlock_user_struct(frame, frame_addr, 1);
2767 force_sig(SIGSEGV);
2768}
2769
624f7979 2770static void setup_rt_frame(int sig, struct target_sigaction *ka,
c3b5bc8a
TS
2771 target_siginfo_t *info,
2772 target_sigset_t *set, CPUState *regs)
2773{
2774 struct target_rt_sigframe *frame;
2775 abi_ulong frame_addr;
2776 int i;
2777 int err = 0;
2778 int signal;
2779
2780 frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
2781 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2782 goto give_sigsegv;
2783
2784 signal = current_exec_domain_sig(sig);
2785
2786 err |= copy_siginfo_to_user(&frame->info, info);
2787
2788 /* Create the ucontext. */
2789 err |= __put_user(0, &frame->uc.uc_flags);
2790 err |= __put_user(0, (unsigned long *)&frame->uc.uc_link);
526ccb7a 2791 err |= __put_user((unsigned long)target_sigaltstack_used.ss_sp,
c3b5bc8a
TS
2792 &frame->uc.uc_stack.ss_sp);
2793 err |= __put_user(sas_ss_flags(regs->gregs[15]),
2794 &frame->uc.uc_stack.ss_flags);
2795 err |= __put_user(target_sigaltstack_used.ss_size,
2796 &frame->uc.uc_stack.ss_size);
2797 err |= setup_sigcontext(&frame->uc.uc_mcontext,
2798 regs, set->sig[0]);
2799 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2800 err |= __put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]);
2801 }
2802
2803 /* Set up to return from userspace. If provided, use a stub
2804 already in userspace. */
624f7979
PB
2805 if (ka->sa_flags & TARGET_SA_RESTORER) {
2806 regs->pr = (unsigned long) ka->sa_restorer;
c3b5bc8a
TS
2807 } else {
2808 /* Generate return code (system call to sigreturn) */
2809 err |= __put_user(MOVW(2), &frame->retcode[0]);
2810 err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
2811 err |= __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
2812 regs->pr = (unsigned long) frame->retcode;
2813 }
2814
2815 if (err)
2816 goto give_sigsegv;
2817
2818 /* Set up registers for signal handler */
2819 regs->gregs[15] = (unsigned long) frame;
2820 regs->gregs[4] = signal; /* Arg for signal handler */
2821 regs->gregs[5] = (unsigned long) &frame->info;
2822 regs->gregs[6] = (unsigned long) &frame->uc;
624f7979 2823 regs->pc = (unsigned long) ka->_sa_handler;
c3b5bc8a
TS
2824
2825 unlock_user_struct(frame, frame_addr, 1);
2826 return;
2827
2828give_sigsegv:
2829 unlock_user_struct(frame, frame_addr, 1);
2830 force_sig(SIGSEGV);
2831}
2832
2833long do_sigreturn(CPUState *regs)
2834{
2835 struct target_sigframe *frame;
2836 abi_ulong frame_addr;
2837 sigset_t blocked;
2838 target_sigset_t target_set;
2839 int i;
2840 int err = 0;
2841
2842#if defined(DEBUG_SIGNAL)
2843 fprintf(stderr, "do_sigreturn\n");
2844#endif
2845 frame_addr = regs->gregs[15];
2846 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2847 goto badframe;
2848
2849 err |= __get_user(target_set.sig[0], &frame->sc.oldmask);
2850 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2851 err |= (__get_user(target_set.sig[i], &frame->extramask[i - 1]));
2852 }
2853
2854 if (err)
2855 goto badframe;
2856
2857 target_to_host_sigset_internal(&blocked, &target_set);
2858 sigprocmask(SIG_SETMASK, &blocked, NULL);
2859
2860 if (restore_sigcontext(regs, &frame->sc))
2861 goto badframe;
2862
2863 unlock_user_struct(frame, frame_addr, 0);
2864 return regs->gregs[0];
2865
2866badframe:
2867 unlock_user_struct(frame, frame_addr, 0);
2868 force_sig(TARGET_SIGSEGV);
2869 return 0;
2870}
2871
2872long do_rt_sigreturn(CPUState *regs)
2873{
2874 struct target_rt_sigframe *frame;
2875 abi_ulong frame_addr;
2876 sigset_t blocked;
2877
2878#if defined(DEBUG_SIGNAL)
2879 fprintf(stderr, "do_rt_sigreturn\n");
2880#endif
2881 frame_addr = regs->gregs[15];
2882 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2883 goto badframe;
2884
2885 target_to_host_sigset(&blocked, &frame->uc.uc_sigmask);
2886 sigprocmask(SIG_SETMASK, &blocked, NULL);
2887
2888 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
2889 goto badframe;
2890
2891 if (do_sigaltstack(frame_addr +
2892 offsetof(struct target_rt_sigframe, uc.uc_stack),
2893 0, get_sp_from_cpustate(regs)) == -EFAULT)
2894 goto badframe;
2895
2896 unlock_user_struct(frame, frame_addr, 0);
2897 return regs->gregs[0];
2898
2899badframe:
2900 unlock_user_struct(frame, frame_addr, 0);
2901 force_sig(TARGET_SIGSEGV);
2902 return 0;
2903}
b6d3abda
EI
2904#elif defined(TARGET_CRIS)
2905
2906struct target_sigcontext {
2907 struct target_pt_regs regs; /* needs to be first */
2908 uint32_t oldmask;
2909 uint32_t usp; /* usp before stacking this gunk on it */
2910};
2911
2912/* Signal frames. */
2913struct target_signal_frame {
2914 struct target_sigcontext sc;
2915 uint32_t extramask[TARGET_NSIG_WORDS - 1];
2916 uint8_t retcode[8]; /* Trampoline code. */
2917};
2918
2919struct rt_signal_frame {
2920 struct siginfo *pinfo;
2921 void *puc;
2922 struct siginfo info;
2923 struct ucontext uc;
2924 uint8_t retcode[8]; /* Trampoline code. */
2925};
2926
2927static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
2928{
9664d928
EI
2929 __put_user(env->regs[0], &sc->regs.r0);
2930 __put_user(env->regs[1], &sc->regs.r1);
2931 __put_user(env->regs[2], &sc->regs.r2);
2932 __put_user(env->regs[3], &sc->regs.r3);
2933 __put_user(env->regs[4], &sc->regs.r4);
2934 __put_user(env->regs[5], &sc->regs.r5);
2935 __put_user(env->regs[6], &sc->regs.r6);
2936 __put_user(env->regs[7], &sc->regs.r7);
2937 __put_user(env->regs[8], &sc->regs.r8);
2938 __put_user(env->regs[9], &sc->regs.r9);
2939 __put_user(env->regs[10], &sc->regs.r10);
2940 __put_user(env->regs[11], &sc->regs.r11);
2941 __put_user(env->regs[12], &sc->regs.r12);
2942 __put_user(env->regs[13], &sc->regs.r13);
2943 __put_user(env->regs[14], &sc->usp);
2944 __put_user(env->regs[15], &sc->regs.acr);
2945 __put_user(env->pregs[PR_MOF], &sc->regs.mof);
2946 __put_user(env->pregs[PR_SRP], &sc->regs.srp);
2947 __put_user(env->pc, &sc->regs.erp);
b6d3abda 2948}
9664d928 2949
b6d3abda
EI
2950static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
2951{
9664d928
EI
2952 __get_user(env->regs[0], &sc->regs.r0);
2953 __get_user(env->regs[1], &sc->regs.r1);
2954 __get_user(env->regs[2], &sc->regs.r2);
2955 __get_user(env->regs[3], &sc->regs.r3);
2956 __get_user(env->regs[4], &sc->regs.r4);
2957 __get_user(env->regs[5], &sc->regs.r5);
2958 __get_user(env->regs[6], &sc->regs.r6);
2959 __get_user(env->regs[7], &sc->regs.r7);
2960 __get_user(env->regs[8], &sc->regs.r8);
2961 __get_user(env->regs[9], &sc->regs.r9);
2962 __get_user(env->regs[10], &sc->regs.r10);
2963 __get_user(env->regs[11], &sc->regs.r11);
2964 __get_user(env->regs[12], &sc->regs.r12);
2965 __get_user(env->regs[13], &sc->regs.r13);
2966 __get_user(env->regs[14], &sc->usp);
2967 __get_user(env->regs[15], &sc->regs.acr);
2968 __get_user(env->pregs[PR_MOF], &sc->regs.mof);
2969 __get_user(env->pregs[PR_SRP], &sc->regs.srp);
2970 __get_user(env->pc, &sc->regs.erp);
2971}
2972
2973static abi_ulong get_sigframe(CPUState *env, int framesize)
2974{
2975 abi_ulong sp;
b6d3abda 2976 /* Align the stack downwards to 4. */
9664d928
EI
2977 sp = (env->regs[R_SP] & ~3);
2978 return sp - framesize;
b6d3abda
EI
2979}
2980
624f7979 2981static void setup_frame(int sig, struct target_sigaction *ka,
b6d3abda
EI
2982 target_sigset_t *set, CPUState *env)
2983{
2984 struct target_signal_frame *frame;
9664d928 2985 abi_ulong frame_addr;
b6d3abda
EI
2986 int err = 0;
2987 int i;
b6d3abda 2988
9664d928
EI
2989 frame_addr = get_sigframe(env, sizeof *frame);
2990 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
b6d3abda
EI
2991 goto badframe;
2992
2993 /*
2994 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
2995 * use this trampoline anymore but it sets it up for GDB.
2996 * In QEMU, using the trampoline simplifies things a bit so we use it.
2997 *
2998 * This is movu.w __NR_sigreturn, r9; break 13;
2999 */
3000 err |= __put_user(0x9c5f, frame->retcode+0);
3001 err |= __put_user(TARGET_NR_sigreturn,
3002 frame->retcode+2);
3003 err |= __put_user(0xe93d, frame->retcode+4);
3004
3005 /* Save the mask. */
3006 err |= __put_user(set->sig[0], &frame->sc.oldmask);
3007 if (err)
3008 goto badframe;
3009
3010 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3011 if (__put_user(set->sig[i], &frame->extramask[i - 1]))
3012 goto badframe;
3013 }
3014
3015 setup_sigcontext(&frame->sc, env);
3016
3017 /* Move the stack and setup the arguments for the handler. */
526ccb7a 3018 env->regs[R_SP] = (uint32_t) (unsigned long) frame;
b6d3abda 3019 env->regs[10] = sig;
624f7979 3020 env->pc = (unsigned long) ka->_sa_handler;
b6d3abda 3021 /* Link SRP so the guest returns through the trampoline. */
526ccb7a 3022 env->pregs[PR_SRP] = (uint32_t) (unsigned long) &frame->retcode[0];
b6d3abda 3023
9664d928 3024 unlock_user_struct(frame, frame_addr, 1);
b6d3abda
EI
3025 return;
3026 badframe:
9664d928 3027 unlock_user_struct(frame, frame_addr, 1);
b6d3abda
EI
3028 force_sig(TARGET_SIGSEGV);
3029}
3030
624f7979 3031static void setup_rt_frame(int sig, struct target_sigaction *ka,
b6d3abda
EI
3032 target_siginfo_t *info,
3033 target_sigset_t *set, CPUState *env)
3034{
3035 fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3036}
3037
3038long do_sigreturn(CPUState *env)
3039{
3040 struct target_signal_frame *frame;
9664d928 3041 abi_ulong frame_addr;
b6d3abda
EI
3042 target_sigset_t target_set;
3043 sigset_t set;
3044 int i;
3045
9664d928 3046 frame_addr = env->regs[R_SP];
b6d3abda 3047 /* Make sure the guest isn't playing games. */
9664d928 3048 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
b6d3abda
EI
3049 goto badframe;
3050
3051 /* Restore blocked signals */
3052 if (__get_user(target_set.sig[0], &frame->sc.oldmask))
3053 goto badframe;
3054 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3055 if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
3056 goto badframe;
3057 }
3058 target_to_host_sigset_internal(&set, &target_set);
3059 sigprocmask(SIG_SETMASK, &set, NULL);
3060
3061 restore_sigcontext(&frame->sc, env);
9664d928 3062 unlock_user_struct(frame, frame_addr, 0);
b6d3abda
EI
3063 return env->regs[10];
3064 badframe:
9664d928 3065 unlock_user_struct(frame, frame_addr, 0);
b6d3abda
EI
3066 force_sig(TARGET_SIGSEGV);
3067}
3068
3069long do_rt_sigreturn(CPUState *env)
3070{
3071 fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3072 return -TARGET_ENOSYS;
3073}
c3b5bc8a 3074
b346ff46
FB
3075#else
3076
624f7979 3077static void setup_frame(int sig, struct target_sigaction *ka,
b346ff46
FB
3078 target_sigset_t *set, CPUState *env)
3079{
3080 fprintf(stderr, "setup_frame: not implemented\n");
3081}
3082
624f7979 3083static void setup_rt_frame(int sig, struct target_sigaction *ka,
b346ff46
FB
3084 target_siginfo_t *info,
3085 target_sigset_t *set, CPUState *env)
3086{
3087 fprintf(stderr, "setup_rt_frame: not implemented\n");
3088}
3089
3090long do_sigreturn(CPUState *env)
3091{
3092 fprintf(stderr, "do_sigreturn: not implemented\n");
f8b0aa25 3093 return -TARGET_ENOSYS;
b346ff46
FB
3094}
3095
3096long do_rt_sigreturn(CPUState *env)
3097{
3098 fprintf(stderr, "do_rt_sigreturn: not implemented\n");
f8b0aa25 3099 return -TARGET_ENOSYS;
b346ff46
FB
3100}
3101
66fb9763
FB
3102#endif
3103
624f7979 3104void process_pending_signals(CPUState *cpu_env)
66fb9763
FB
3105{
3106 int sig;
992f48a0 3107 abi_ulong handler;
9de5e440
FB
3108 sigset_t set, old_set;
3109 target_sigset_t target_old_set;
624f7979
PB
3110 struct emulated_sigtable *k;
3111 struct target_sigaction *sa;
66fb9763 3112 struct sigqueue *q;
624f7979 3113 TaskState *ts = cpu_env->opaque;
3b46e624 3114
624f7979 3115 if (!ts->signal_pending)
31e31b8a
FB
3116 return;
3117
624f7979
PB
3118 /* FIXME: This is not threadsafe. */
3119 k = ts->sigtab;
66fb9763
FB
3120 for(sig = 1; sig <= TARGET_NSIG; sig++) {
3121 if (k->pending)
31e31b8a 3122 goto handle_signal;
66fb9763 3123 k++;
31e31b8a
FB
3124 }
3125 /* if no signal is pending, just return */
624f7979 3126 ts->signal_pending = 0;
31e31b8a 3127 return;
66fb9763 3128
31e31b8a 3129 handle_signal:
66fb9763 3130#ifdef DEBUG_SIGNAL
bc8a22cc 3131 fprintf(stderr, "qemu: process signal %d\n", sig);
66fb9763
FB
3132#endif
3133 /* dequeue signal */
3134 q = k->first;
3135 k->first = q->next;
3136 if (!k->first)
3137 k->pending = 0;
3b46e624 3138
1fddef4b
FB
3139 sig = gdb_handlesig (cpu_env, sig);
3140 if (!sig) {
ca587a8e
AJ
3141 sa = NULL;
3142 handler = TARGET_SIG_IGN;
3143 } else {
3144 sa = &sigact_table[sig - 1];
3145 handler = sa->_sa_handler;
1fddef4b 3146 }
66fb9763 3147
66fb9763 3148 if (handler == TARGET_SIG_DFL) {
ca587a8e
AJ
3149 /* default handler : ignore some signal. The other are job control or fatal */
3150 if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
3151 kill(getpid(),SIGSTOP);
3152 } else if (sig != TARGET_SIGCHLD &&
3153 sig != TARGET_SIGURG &&
3154 sig != TARGET_SIGWINCH &&
3155 sig != TARGET_SIGCONT) {
66fb9763
FB
3156 force_sig(sig);
3157 }
3158 } else if (handler == TARGET_SIG_IGN) {
3159 /* ignore sig */
3160 } else if (handler == TARGET_SIG_ERR) {
3161 force_sig(sig);
3162 } else {
9de5e440 3163 /* compute the blocked signals during the handler execution */
624f7979 3164 target_to_host_sigset(&set, &sa->sa_mask);
9de5e440
FB
3165 /* SA_NODEFER indicates that the current signal should not be
3166 blocked during the handler */
624f7979 3167 if (!(sa->sa_flags & TARGET_SA_NODEFER))
9de5e440 3168 sigaddset(&set, target_to_host_signal(sig));
3b46e624 3169
9de5e440
FB
3170 /* block signals in the handler using Linux */
3171 sigprocmask(SIG_BLOCK, &set, &old_set);
3172 /* save the previous blocked signal state to restore it at the
3173 end of the signal execution (see do_sigreturn) */
9231944d 3174 host_to_target_sigset_internal(&target_old_set, &old_set);
9de5e440 3175
bc8a22cc 3176 /* if the CPU is in VM86 mode, we restore the 32 bit values */
84409ddb 3177#if defined(TARGET_I386) && !defined(TARGET_X86_64)
bc8a22cc
FB
3178 {
3179 CPUX86State *env = cpu_env;
3180 if (env->eflags & VM_MASK)
3181 save_v86_state(env);
3182 }
3183#endif
9de5e440 3184 /* prepare the stack frame of the virtual CPU */
624f7979
PB
3185 if (sa->sa_flags & TARGET_SA_SIGINFO)
3186 setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
66fb9763 3187 else
624f7979
PB
3188 setup_frame(sig, sa, &target_old_set, cpu_env);
3189 if (sa->sa_flags & TARGET_SA_RESETHAND)
3190 sa->_sa_handler = TARGET_SIG_DFL;
31e31b8a 3191 }
66fb9763 3192 if (q != &k->info)
624f7979 3193 free_sigqueue(cpu_env, q);
66fb9763 3194}