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