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