signal.c 90.8 KB
Newer Older
1
/*
B
bellard 已提交
2
 *  Emulation of Linux signals
3
 *
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *  Copyright (c) 2003 Fabrice Bellard
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include <stdlib.h>
#include <stdio.h>
B
bellard 已提交
22
#include <string.h>
23
#include <stdarg.h>
B
bellard 已提交
24
#include <unistd.h>
25
#include <signal.h>
B
bellard 已提交
26
#include <errno.h>
27 28
#include <sys/ucontext.h>

B
bellard 已提交
29
#include "qemu.h"
30
#include "target_signal.h"
B
bellard 已提交
31 32 33

//#define DEBUG_SIGNAL

34 35 36 37 38 39
struct target_sigaltstack target_sigaltstack_used = {
    .ss_sp = 0,
    .ss_size = 0,
    .ss_flags = TARGET_SS_DISABLE,
};

P
pbrook 已提交
40
static struct target_sigaction sigact_table[TARGET_NSIG];
41

42
static void host_signal_handler(int host_signum, siginfo_t *info,
B
bellard 已提交
43 44
                                void *puc);

B
bellard 已提交
45 46 47 48 49 50 51
static uint8_t host_to_target_signal_table[65] = {
    [SIGHUP] = TARGET_SIGHUP,
    [SIGINT] = TARGET_SIGINT,
    [SIGQUIT] = TARGET_SIGQUIT,
    [SIGILL] = TARGET_SIGILL,
    [SIGTRAP] = TARGET_SIGTRAP,
    [SIGABRT] = TARGET_SIGABRT,
B
bellard 已提交
52
/*    [SIGIOT] = TARGET_SIGIOT,*/
B
bellard 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
    [SIGBUS] = TARGET_SIGBUS,
    [SIGFPE] = TARGET_SIGFPE,
    [SIGKILL] = TARGET_SIGKILL,
    [SIGUSR1] = TARGET_SIGUSR1,
    [SIGSEGV] = TARGET_SIGSEGV,
    [SIGUSR2] = TARGET_SIGUSR2,
    [SIGPIPE] = TARGET_SIGPIPE,
    [SIGALRM] = TARGET_SIGALRM,
    [SIGTERM] = TARGET_SIGTERM,
#ifdef SIGSTKFLT
    [SIGSTKFLT] = TARGET_SIGSTKFLT,
#endif
    [SIGCHLD] = TARGET_SIGCHLD,
    [SIGCONT] = TARGET_SIGCONT,
    [SIGSTOP] = TARGET_SIGSTOP,
    [SIGTSTP] = TARGET_SIGTSTP,
    [SIGTTIN] = TARGET_SIGTTIN,
    [SIGTTOU] = TARGET_SIGTTOU,
    [SIGURG] = TARGET_SIGURG,
    [SIGXCPU] = TARGET_SIGXCPU,
    [SIGXFSZ] = TARGET_SIGXFSZ,
    [SIGVTALRM] = TARGET_SIGVTALRM,
    [SIGPROF] = TARGET_SIGPROF,
    [SIGWINCH] = TARGET_SIGWINCH,
    [SIGIO] = TARGET_SIGIO,
    [SIGPWR] = TARGET_SIGPWR,
    [SIGSYS] = TARGET_SIGSYS,
    /* next signals stay the same */
P
pbrook 已提交
81 82 83 84 85 86
    /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
       host libpthread signals.  This assumes noone actually uses SIGRTMAX :-/
       To fix this properly we need to do manual signal delivery multiplexed
       over a single host signal.  */
    [__SIGRTMIN] = __SIGRTMAX,
    [__SIGRTMAX] = __SIGRTMIN,
B
bellard 已提交
87 88 89
};
static uint8_t target_to_host_signal_table[65];

90 91 92 93 94 95 96 97 98 99 100 101
static inline int on_sig_stack(unsigned long sp)
{
    return (sp - target_sigaltstack_used.ss_sp
            < target_sigaltstack_used.ss_size);
}

static inline int sas_ss_flags(unsigned long sp)
{
    return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
            : on_sig_stack(sp) ? SS_ONSTACK : 0);
}

102 103
static inline int host_to_target_signal(int sig)
{
104 105
    if (sig > 64)
        return sig;
B
bellard 已提交
106
    return host_to_target_signal_table[sig];
107 108
}

109
int target_to_host_signal(int sig)
110
{
111 112
    if (sig > 64)
        return sig;
B
bellard 已提交
113
    return target_to_host_signal_table[sig];
114 115
}

116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
static inline void target_sigemptyset(target_sigset_t *set)
{
    memset(set, 0, sizeof(*set));
}

static inline void target_sigaddset(target_sigset_t *set, int signum)
{
    signum--;
    abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
    set->sig[signum / TARGET_NSIG_BPW] |= mask;
}

static inline int target_sigismember(const target_sigset_t *set, int signum)
{
    signum--;
    abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
    return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
}

135
static void host_to_target_sigset_internal(target_sigset_t *d,
136
                                           const sigset_t *s)
B
bellard 已提交
137 138
{
    int i;
139 140 141 142 143
    target_sigemptyset(d);
    for (i = 1; i <= TARGET_NSIG; i++) {
        if (sigismember(s, i)) {
            target_sigaddset(d, host_to_target_signal(i));
        }
B
bellard 已提交
144 145 146
    }
}

147 148 149 150 151 152 153
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
{
    target_sigset_t d1;
    int i;

    host_to_target_sigset_internal(&d1, s);
    for(i = 0;i < TARGET_NSIG_WORDS; i++)
154
        d->sig[i] = tswapl(d1.sig[i]);
155 156 157
}

void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s)
B
bellard 已提交
158 159
{
    int i;
160 161 162 163 164 165
    sigemptyset(d);
    for (i = 1; i <= TARGET_NSIG; i++) {
        if (target_sigismember(s, i)) {
            sigaddset(d, target_to_host_signal(i));
        }
     }
B
bellard 已提交
166 167
}

168 169 170 171 172 173
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
{
    target_sigset_t s1;
    int i;

    for(i = 0;i < TARGET_NSIG_WORDS; i++)
174
        s1.sig[i] = tswapl(s->sig[i]);
175 176
    target_to_host_sigset_internal(d, &s1);
}
177

178
void host_to_target_old_sigset(abi_ulong *old_sigset,
B
bellard 已提交
179 180
                               const sigset_t *sigset)
{
B
bellard 已提交
181 182 183
    target_sigset_t d;
    host_to_target_sigset(&d, sigset);
    *old_sigset = d.sig[0];
B
bellard 已提交
184 185
}

186
void target_to_host_old_sigset(sigset_t *sigset,
187
                               const abi_ulong *old_sigset)
B
bellard 已提交
188
{
B
bellard 已提交
189 190 191 192 193 194 195
    target_sigset_t d;
    int i;

    d.sig[0] = *old_sigset;
    for(i = 1;i < TARGET_NSIG_WORDS; i++)
        d.sig[i] = 0;
    target_to_host_sigset(sigset, &d);
B
bellard 已提交
196 197
}

B
bellard 已提交
198 199
/* siginfo conversion */

200
static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
B
bellard 已提交
201
                                                 const siginfo_t *info)
B
bellard 已提交
202
{
B
bellard 已提交
203 204 205 206
    int sig;
    sig = host_to_target_signal(info->si_signo);
    tinfo->si_signo = sig;
    tinfo->si_errno = 0;
P
pbrook 已提交
207
    tinfo->si_code = info->si_code;
208
    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
B
bellard 已提交
209
        sig == SIGBUS || sig == SIGTRAP) {
B
bellard 已提交
210 211 212
        /* should never come here, but who knows. The information for
           the target is irrelevant */
        tinfo->_sifields._sigfault._addr = 0;
T
ths 已提交
213 214
    } else if (sig == SIGIO) {
	tinfo->_sifields._sigpoll._fd = info->si_fd;
B
bellard 已提交
215 216 217 218
    } else if (sig >= TARGET_SIGRTMIN) {
        tinfo->_sifields._rt._pid = info->si_pid;
        tinfo->_sifields._rt._uid = info->si_uid;
        /* XXX: potential problem if 64 bit */
219
        tinfo->_sifields._rt._sigval.sival_ptr =
220
            (abi_ulong)(unsigned long)info->si_value.sival_ptr;
B
bellard 已提交
221 222 223
    }
}

224
static void tswap_siginfo(target_siginfo_t *tinfo,
B
bellard 已提交
225 226 227 228 229
                          const target_siginfo_t *info)
{
    int sig;
    sig = info->si_signo;
    tinfo->si_signo = tswap32(sig);
B
bellard 已提交
230 231
    tinfo->si_errno = tswap32(info->si_errno);
    tinfo->si_code = tswap32(info->si_code);
232
    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
B
bellard 已提交
233
        sig == SIGBUS || sig == SIGTRAP) {
234
        tinfo->_sifields._sigfault._addr =
B
bellard 已提交
235
            tswapl(info->_sifields._sigfault._addr);
T
ths 已提交
236 237
    } else if (sig == SIGIO) {
	tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
B
bellard 已提交
238 239 240
    } else if (sig >= TARGET_SIGRTMIN) {
        tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
        tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
241
        tinfo->_sifields._rt._sigval.sival_ptr =
B
bellard 已提交
242 243 244 245 246 247 248 249 250
            tswapl(info->_sifields._rt._sigval.sival_ptr);
    }
}


void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
{
    host_to_target_siginfo_noswap(tinfo, info);
    tswap_siginfo(tinfo, tinfo);
B
bellard 已提交
251 252
}

B
bellard 已提交
253
/* XXX: we support only POSIX RT signals are used. */
T
ths 已提交
254
/* XXX: find a solution for 64 bit (additional malloced data is needed) */
B
bellard 已提交
255
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
B
bellard 已提交
256 257 258 259
{
    info->si_signo = tswap32(tinfo->si_signo);
    info->si_errno = tswap32(tinfo->si_errno);
    info->si_code = tswap32(tinfo->si_code);
B
bellard 已提交
260 261
    info->si_pid = tswap32(tinfo->_sifields._rt._pid);
    info->si_uid = tswap32(tinfo->_sifields._rt._uid);
262
    info->si_value.sival_ptr =
263
            (void *)(long)tswapl(tinfo->_sifields._rt._sigval.sival_ptr);
B
bellard 已提交
264 265
}

266 267 268
void signal_init(void)
{
    struct sigaction act;
P
pbrook 已提交
269
    struct sigaction oact;
B
bellard 已提交
270
    int i, j;
P
pbrook 已提交
271
    int host_sig;
272

B
bellard 已提交
273 274 275 276 277 278 279 280 281
    /* generate signal conversion tables */
    for(i = 1; i <= 64; i++) {
        if (host_to_target_signal_table[i] == 0)
            host_to_target_signal_table[i] = i;
    }
    for(i = 1; i <= 64; i++) {
        j = host_to_target_signal_table[i];
        target_to_host_signal_table[j] = i;
    }
282

B
bellard 已提交
283 284
    /* set all host signal handlers. ALL signals are blocked during
       the handlers to serialize them. */
P
pbrook 已提交
285 286
    memset(sigact_table, 0, sizeof(sigact_table));

B
bellard 已提交
287
    sigfillset(&act.sa_mask);
288 289
    act.sa_flags = SA_SIGINFO;
    act.sa_sigaction = host_signal_handler;
P
pbrook 已提交
290 291 292 293 294 295 296 297 298 299 300 301 302 303
    for(i = 1; i <= TARGET_NSIG; i++) {
        host_sig = target_to_host_signal(i);
        sigaction(host_sig, NULL, &oact);
        if (oact.sa_sigaction == (void *)SIG_IGN) {
            sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
        } else if (oact.sa_sigaction == (void *)SIG_DFL) {
            sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
        }
        /* If there's already a handler installed then something has
           gone horribly wrong, so don't even try to handle that case.  */
        /* Install some handlers for our own use.  */
        if (host_sig == SIGSEGV || host_sig == SIGBUS) {
            sigaction(host_sig, &act, NULL);
        }
304
    }
B
bellard 已提交
305 306 307 308
}

/* signal queue handling */

P
pbrook 已提交
309
static inline struct sigqueue *alloc_sigqueue(CPUState *env)
B
bellard 已提交
310
{
P
pbrook 已提交
311 312
    TaskState *ts = env->opaque;
    struct sigqueue *q = ts->first_free;
B
bellard 已提交
313 314
    if (!q)
        return NULL;
P
pbrook 已提交
315
    ts->first_free = q->next;
B
bellard 已提交
316
    return q;
317 318
}

P
pbrook 已提交
319
static inline void free_sigqueue(CPUState *env, struct sigqueue *q)
B
bellard 已提交
320
{
P
pbrook 已提交
321 322 323
    TaskState *ts = env->opaque;
    q->next = ts->first_free;
    ts->first_free = q;
B
bellard 已提交
324 325
}

B
bellard 已提交
326 327
/* abort execution with signal */
void __attribute((noreturn)) force_sig(int sig)
B
bellard 已提交
328 329 330
{
    int host_sig;
    host_sig = target_to_host_signal(sig);
331
    fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
B
bellard 已提交
332
            sig, strsignal(host_sig));
B
bellard 已提交
333
#if 1
B
bellard 已提交
334
    _exit(-host_sig);
B
bellard 已提交
335 336 337 338 339 340 341 342 343 344
#else
    {
        struct sigaction act;
        sigemptyset(&act.sa_mask);
        act.sa_flags = SA_SIGINFO;
        act.sa_sigaction = SIG_DFL;
        sigaction(SIGABRT, &act, NULL);
        abort();
    }
#endif
B
bellard 已提交
345 346
}

B
bellard 已提交
347 348
/* queue a signal so that it will be send to the virtual CPU as soon
   as possible */
P
pbrook 已提交
349
int queue_signal(CPUState *env, int sig, target_siginfo_t *info)
350
{
P
pbrook 已提交
351 352
    TaskState *ts = env->opaque;
    struct emulated_sigtable *k;
B
bellard 已提交
353
    struct sigqueue *q, **pq;
354
    abi_ulong handler;
B
bellard 已提交
355

B
bellard 已提交
356
#if defined(DEBUG_SIGNAL)
357
    fprintf(stderr, "queue_signal: sig=%d\n",
B
bellard 已提交
358
            sig);
B
bellard 已提交
359
#endif
P
pbrook 已提交
360 361
    k = &ts->sigtab[sig - 1];
    handler = sigact_table[sig - 1]._sa_handler;
B
bellard 已提交
362 363
    if (handler == TARGET_SIG_DFL) {
        /* default handler : ignore some signal. The other are fatal */
364 365
        if (sig != TARGET_SIGCHLD &&
            sig != TARGET_SIGURG &&
B
bellard 已提交
366 367
            sig != TARGET_SIGWINCH) {
            force_sig(sig);
B
bellard 已提交
368 369
        } else {
            return 0; /* indicate ignored */
B
bellard 已提交
370 371 372
        }
    } else if (handler == TARGET_SIG_IGN) {
        /* ignore signal */
B
bellard 已提交
373
        return 0;
B
bellard 已提交
374 375 376
    } else if (handler == TARGET_SIG_ERR) {
        force_sig(sig);
    } else {
B
bellard 已提交
377 378 379 380 381 382 383 384 385 386 387 388
        pq = &k->first;
        if (sig < TARGET_SIGRTMIN) {
            /* if non real time signal, we queue exactly one signal */
            if (!k->pending)
                q = &k->info;
            else
                return 0;
        } else {
            if (!k->pending) {
                /* first signal */
                q = &k->info;
            } else {
P
pbrook 已提交
389
                q = alloc_sigqueue(env);
B
bellard 已提交
390 391 392 393 394 395 396 397 398 399 400
                if (!q)
                    return -EAGAIN;
                while (*pq != NULL)
                    pq = &(*pq)->next;
            }
        }
        *pq = q;
        q->info = *info;
        q->next = NULL;
        k->pending = 1;
        /* signal that a new signal is pending */
P
pbrook 已提交
401
        ts->signal_pending = 1;
B
bellard 已提交
402 403 404 405
        return 1; /* indicates that the signal was queued */
    }
}

406
static void host_signal_handler(int host_signum, siginfo_t *info,
B
bellard 已提交
407 408 409 410 411 412 413
                                void *puc)
{
    int sig;
    target_siginfo_t tinfo;

    /* the CPU emulator uses some host signals to detect exceptions,
       we we forward to it some signals */
B
bellard 已提交
414
    if (host_signum == SIGSEGV || host_signum == SIGBUS) {
B
bellard 已提交
415
        if (cpu_signal_handler(host_signum, info, puc))
B
bellard 已提交
416 417 418 419 420 421 422 423
            return;
    }

    /* get target signal number */
    sig = host_to_target_signal(host_signum);
    if (sig < 1 || sig > TARGET_NSIG)
        return;
#if defined(DEBUG_SIGNAL)
B
bellard 已提交
424
    fprintf(stderr, "qemu: got signal %d\n", sig);
B
bellard 已提交
425 426
#endif
    host_to_target_siginfo_noswap(&tinfo, info);
P
pbrook 已提交
427
    if (queue_signal(thread_env, sig, &tinfo) == 1) {
B
bellard 已提交
428
        /* interrupt the virtual CPU as soon as possible */
P
pbrook 已提交
429
        cpu_interrupt(thread_env, CPU_INTERRUPT_EXIT);
B
bellard 已提交
430 431 432
    }
}

433
/* do_sigaltstack() returns target values and errnos. */
434 435
/* compare linux/kernel/signal.c:do_sigaltstack() */
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
436 437 438 439 440
{
    int ret;
    struct target_sigaltstack oss;

    /* XXX: test errors */
441
    if(uoss_addr)
442 443 444 445 446 447
    {
        __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
        __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
        __put_user(sas_ss_flags(sp), &oss.ss_flags);
    }

448
    if(uss_addr)
449
    {
450 451
        struct target_sigaltstack *uss;
        struct target_sigaltstack ss;
452

453
	ret = -TARGET_EFAULT;
454
        if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)
455 456 457 458
	    || __get_user(ss.ss_sp, &uss->ss_sp)
	    || __get_user(ss.ss_size, &uss->ss_size)
	    || __get_user(ss.ss_flags, &uss->ss_flags))
            goto out;
459
        unlock_user_struct(uss, uss_addr, 0);
460

461
	ret = -TARGET_EPERM;
462 463 464
	if (on_sig_stack(sp))
            goto out;

465
	ret = -TARGET_EINVAL;
466 467 468 469 470 471 472 473 474
	if (ss.ss_flags != TARGET_SS_DISABLE
            && ss.ss_flags != TARGET_SS_ONSTACK
            && ss.ss_flags != 0)
            goto out;

	if (ss.ss_flags == TARGET_SS_DISABLE) {
            ss.ss_size = 0;
            ss.ss_sp = 0;
	} else {
475
            ret = -TARGET_ENOMEM;
476 477 478 479 480 481 482 483
            if (ss.ss_size < MINSIGSTKSZ)
                goto out;
	}

        target_sigaltstack_used.ss_sp = ss.ss_sp;
        target_sigaltstack_used.ss_size = ss.ss_size;
    }

484
    if (uoss_addr) {
485
        ret = -TARGET_EFAULT;
486
        if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
487 488 489 490 491 492 493 494
            goto out;
    }

    ret = 0;
out:
    return ret;
}

495
/* do_sigaction() return host values and errnos */
B
bellard 已提交
496 497 498
int do_sigaction(int sig, const struct target_sigaction *act,
                 struct target_sigaction *oact)
{
P
pbrook 已提交
499
    struct target_sigaction *k;
500 501
    struct sigaction act1;
    int host_sig;
502
    int ret = 0;
B
bellard 已提交
503

504
    if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP)
B
bellard 已提交
505 506
        return -EINVAL;
    k = &sigact_table[sig - 1];
507
#if defined(DEBUG_SIGNAL)
508
    fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n",
B
bellard 已提交
509 510 511
            sig, (int)act, (int)oact);
#endif
    if (oact) {
P
pbrook 已提交
512 513
        oact->_sa_handler = tswapl(k->_sa_handler);
        oact->sa_flags = tswapl(k->sa_flags);
T
ths 已提交
514
#if !defined(TARGET_MIPS)
P
pbrook 已提交
515
        oact->sa_restorer = tswapl(k->sa_restorer);
T
ths 已提交
516
#endif
P
pbrook 已提交
517
        oact->sa_mask = k->sa_mask;
B
bellard 已提交
518 519
    }
    if (act) {
P
pbrook 已提交
520 521 522
        /* FIXME: This is not threadsafe.  */
        k->_sa_handler = tswapl(act->_sa_handler);
        k->sa_flags = tswapl(act->sa_flags);
T
ths 已提交
523
#if !defined(TARGET_MIPS)
P
pbrook 已提交
524
        k->sa_restorer = tswapl(act->sa_restorer);
T
ths 已提交
525
#endif
P
pbrook 已提交
526
        k->sa_mask = act->sa_mask;
527 528 529 530 531 532

        /* we update the host linux signal state */
        host_sig = target_to_host_signal(sig);
        if (host_sig != SIGSEGV && host_sig != SIGBUS) {
            sigfillset(&act1.sa_mask);
            act1.sa_flags = SA_SIGINFO;
P
pbrook 已提交
533
            if (k->sa_flags & TARGET_SA_RESTART)
534 535 536 537
                act1.sa_flags |= SA_RESTART;
            /* NOTE: it is important to update the host kernel signal
               ignore state to avoid getting unexpected interrupted
               syscalls */
P
pbrook 已提交
538
            if (k->_sa_handler == TARGET_SIG_IGN) {
539
                act1.sa_sigaction = (void *)SIG_IGN;
P
pbrook 已提交
540
            } else if (k->_sa_handler == TARGET_SIG_DFL) {
541 542 543 544
                act1.sa_sigaction = (void *)SIG_DFL;
            } else {
                act1.sa_sigaction = host_signal_handler;
            }
545
            ret = sigaction(host_sig, &act1, NULL);
546
        }
B
bellard 已提交
547
    }
548
    return ret;
B
bellard 已提交
549 550
}

B
bellard 已提交
551 552 553 554
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif

555
static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,
B
bellard 已提交
556 557 558 559 560 561
                                       const target_siginfo_t *info)
{
    tswap_siginfo(tinfo, info);
    return 0;
}

562 563 564 565 566 567
static inline int current_exec_domain_sig(int sig)
{
    return /* current->exec_domain && current->exec_domain->signal_invmap
	      && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig;
}

568
#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
B
bellard 已提交
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583

/* from the Linux kernel */

struct target_fpreg {
	uint16_t significand[4];
	uint16_t exponent;
};

struct target_fpxreg {
	uint16_t significand[4];
	uint16_t exponent;
	uint16_t padding[3];
};

struct target_xmmreg {
584
	abi_ulong element[4];
B
bellard 已提交
585 586 587 588
};

struct target_fpstate {
	/* Regular FPU environment */
589 590 591 592 593 594 595
        abi_ulong       cw;
        abi_ulong       sw;
        abi_ulong       tag;
        abi_ulong       ipoff;
        abi_ulong       cssel;
        abi_ulong       dataoff;
        abi_ulong       datasel;
B
bellard 已提交
596 597 598 599 600
	struct target_fpreg	_st[8];
	uint16_t	status;
	uint16_t	magic;		/* 0xffff = regular FPU data only */

	/* FXSR FPU environment */
601 602 603
        abi_ulong       _fxsr_env[6];   /* FXSR FPU env is ignored */
        abi_ulong       mxcsr;
        abi_ulong       reserved;
B
bellard 已提交
604 605
	struct target_fpxreg	_fxsr_st[8];	/* FXSR FPU reg data is ignored */
	struct target_xmmreg	_xmm[8];
606
        abi_ulong       padding[56];
B
bellard 已提交
607 608 609 610 611 612 613 614 615
};

#define X86_FXSR_MAGIC		0x0000

struct target_sigcontext {
	uint16_t gs, __gsh;
	uint16_t fs, __fsh;
	uint16_t es, __esh;
	uint16_t ds, __dsh;
616 617 618 619 620 621 622 623 624 625 626
        abi_ulong edi;
        abi_ulong esi;
        abi_ulong ebp;
        abi_ulong esp;
        abi_ulong ebx;
        abi_ulong edx;
        abi_ulong ecx;
        abi_ulong eax;
        abi_ulong trapno;
        abi_ulong err;
        abi_ulong eip;
B
bellard 已提交
627
	uint16_t cs, __csh;
628 629
        abi_ulong eflags;
        abi_ulong esp_at_signal;
B
bellard 已提交
630
	uint16_t ss, __ssh;
631 632 633
        abi_ulong fpstate; /* pointer */
        abi_ulong oldmask;
        abi_ulong cr2;
B
bellard 已提交
634 635 636
};

struct target_ucontext {
637 638
        abi_ulong         tuc_flags;
        abi_ulong         tuc_link;
B
bellard 已提交
639 640 641
	target_stack_t	  tuc_stack;
	struct target_sigcontext tuc_mcontext;
	target_sigset_t	  tuc_sigmask;	/* mask last for extensibility */
B
bellard 已提交
642 643 644 645
};

struct sigframe
{
646
    abi_ulong pretcode;
B
bellard 已提交
647 648 649
    int sig;
    struct target_sigcontext sc;
    struct target_fpstate fpstate;
650
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
B
bellard 已提交
651 652 653 654 655
    char retcode[8];
};

struct rt_sigframe
{
656
    abi_ulong pretcode;
B
bellard 已提交
657
    int sig;
658 659
    abi_ulong pinfo;
    abi_ulong puc;
B
bellard 已提交
660 661 662 663 664 665 666 667 668 669 670 671 672
    struct target_siginfo info;
    struct target_ucontext uc;
    struct target_fpstate fpstate;
    char retcode[8];
};

/*
 * Set up a signal frame.
 */

/* XXX: save x87 state */
static int
setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
B
bellard 已提交
673
		 CPUX86State *env, abi_ulong mask, abi_ulong fpstate_addr)
B
bellard 已提交
674 675
{
	int err = 0;
676
        uint16_t magic;
B
bellard 已提交
677

678
	/* already locked in setup_frame() */
679 680 681 682
	err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
	err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
	err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
	err |= __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
B
bellard 已提交
683 684 685 686 687 688 689 690
	err |= __put_user(env->regs[R_EDI], &sc->edi);
	err |= __put_user(env->regs[R_ESI], &sc->esi);
	err |= __put_user(env->regs[R_EBP], &sc->ebp);
	err |= __put_user(env->regs[R_ESP], &sc->esp);
	err |= __put_user(env->regs[R_EBX], &sc->ebx);
	err |= __put_user(env->regs[R_EDX], &sc->edx);
	err |= __put_user(env->regs[R_ECX], &sc->ecx);
	err |= __put_user(env->regs[R_EAX], &sc->eax);
691 692
	err |= __put_user(env->exception_index, &sc->trapno);
	err |= __put_user(env->error_code, &sc->err);
B
bellard 已提交
693
	err |= __put_user(env->eip, &sc->eip);
694
	err |= __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
B
bellard 已提交
695 696
	err |= __put_user(env->eflags, &sc->eflags);
	err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal);
697
	err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
B
bellard 已提交
698

B
bellard 已提交
699
        cpu_x86_fsave(env, fpstate_addr, 1);
B
bellard 已提交
700
        fpstate->status = fpstate->sw;
701 702
        magic = 0xffff;
        err |= __put_user(magic, &fpstate->magic);
B
bellard 已提交
703
        err |= __put_user(fpstate_addr, &sc->fpstate);
B
bellard 已提交
704

B
bellard 已提交
705 706
	/* non-iBCS2 extensions.. */
	err |= __put_user(mask, &sc->oldmask);
707
	err |= __put_user(env->cr[2], &sc->cr2);
B
bellard 已提交
708
	return err;
709 710
}

B
bellard 已提交
711 712 713
/*
 * Determine which stack to use..
 */
714

715
static inline abi_ulong
P
pbrook 已提交
716
get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
717
{
B
bellard 已提交
718 719 720 721 722
	unsigned long esp;

	/* Default to using normal stack */
	esp = env->regs[R_ESP];
	/* This is the X/Open sanctioned signal stack switching.  */
P
pbrook 已提交
723
        if (ka->sa_flags & TARGET_SA_ONSTACK) {
724 725 726
            if (sas_ss_flags(esp) == 0)
                esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
        }
B
bellard 已提交
727 728

	/* This is the legacy signal stack switching. */
729
	else
730
        if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
P
pbrook 已提交
731 732 733
            !(ka->sa_flags & TARGET_SA_RESTORER) &&
            ka->sa_restorer) {
            esp = (unsigned long) ka->sa_restorer;
734
	}
735
        return (esp - frame_size) & -8ul;
B
bellard 已提交
736 737
}

738
/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
P
pbrook 已提交
739
static void setup_frame(int sig, struct target_sigaction *ka,
B
bellard 已提交
740 741
			target_sigset_t *set, CPUX86State *env)
{
742
	abi_ulong frame_addr;
B
bellard 已提交
743
	struct sigframe *frame;
744
	int i, err = 0;
B
bellard 已提交
745

746
	frame_addr = get_sigframe(ka, env, sizeof(*frame));
B
bellard 已提交
747

748
	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
B
bellard 已提交
749
		goto give_sigsegv;
750

751
	err |= __put_user(current_exec_domain_sig(sig),
B
bellard 已提交
752 753 754 755
		          &frame->sig);
	if (err)
		goto give_sigsegv;

B
bellard 已提交
756 757
	setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
                         frame_addr + offsetof(struct sigframe, fpstate));
B
bellard 已提交
758 759 760
	if (err)
		goto give_sigsegv;

761 762 763 764
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
            if (__put_user(set->sig[i], &frame->extramask[i - 1]))
                goto give_sigsegv;
        }
B
bellard 已提交
765 766 767

	/* Set up to return from userspace.  If provided, use a stub
	   already in userspace.  */
P
pbrook 已提交
768 769
	if (ka->sa_flags & TARGET_SA_RESTORER) {
		err |= __put_user(ka->sa_restorer, &frame->pretcode);
B
bellard 已提交
770
	} else {
771
                uint16_t val16;
B
bellard 已提交
772 773 774
                abi_ulong retcode_addr;
                retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
		err |= __put_user(retcode_addr, &frame->pretcode);
B
bellard 已提交
775
		/* This is popl %eax ; movl $,%eax ; int $0x80 */
776 777
                val16 = 0xb858;
		err |= __put_user(val16, (uint16_t *)(frame->retcode+0));
B
bellard 已提交
778
		err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
779 780
                val16 = 0x80cd;
		err |= __put_user(val16, (uint16_t *)(frame->retcode+6));
B
bellard 已提交
781 782 783 784 785 786
	}

	if (err)
		goto give_sigsegv;

	/* Set up registers for signal handler */
B
bellard 已提交
787
	env->regs[R_ESP] = frame_addr;
P
pbrook 已提交
788
	env->eip = ka->_sa_handler;
B
bellard 已提交
789 790 791 792 793 794 795

        cpu_x86_load_seg(env, R_DS, __USER_DS);
        cpu_x86_load_seg(env, R_ES, __USER_DS);
        cpu_x86_load_seg(env, R_SS, __USER_DS);
        cpu_x86_load_seg(env, R_CS, __USER_CS);
	env->eflags &= ~TF_MASK;

796 797
	unlock_user_struct(frame, frame_addr, 1);

B
bellard 已提交
798 799 800
	return;

give_sigsegv:
801
	unlock_user_struct(frame, frame_addr, 1);
B
bellard 已提交
802
	if (sig == TARGET_SIGSEGV)
P
pbrook 已提交
803
		ka->_sa_handler = TARGET_SIG_DFL;
B
bellard 已提交
804 805 806
	force_sig(TARGET_SIGSEGV /* , current */);
}

807
/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
P
pbrook 已提交
808
static void setup_rt_frame(int sig, struct target_sigaction *ka,
B
bellard 已提交
809
                           target_siginfo_t *info,
B
bellard 已提交
810 811
			   target_sigset_t *set, CPUX86State *env)
{
B
bellard 已提交
812
        abi_ulong frame_addr, addr;
B
bellard 已提交
813
	struct rt_sigframe *frame;
814
	int i, err = 0;
B
bellard 已提交
815

816
	frame_addr = get_sigframe(ka, env, sizeof(*frame));
B
bellard 已提交
817

818
	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
B
bellard 已提交
819 820
		goto give_sigsegv;

821
	err |= __put_user(current_exec_domain_sig(sig),
B
bellard 已提交
822
			  &frame->sig);
B
bellard 已提交
823 824 825 826
        addr = frame_addr + offsetof(struct rt_sigframe, info);
	err |= __put_user(addr, &frame->pinfo);
        addr = frame_addr + offsetof(struct rt_sigframe, uc);
	err |= __put_user(addr, &frame->puc);
B
bellard 已提交
827 828 829
	err |= copy_siginfo_to_user(&frame->info, info);
	if (err)
		goto give_sigsegv;
830

B
bellard 已提交
831
	/* Create the ucontext.  */
B
bellard 已提交
832 833
	err |= __put_user(0, &frame->uc.tuc_flags);
	err |= __put_user(0, &frame->uc.tuc_link);
834
	err |= __put_user(target_sigaltstack_used.ss_sp,
B
bellard 已提交
835
			  &frame->uc.tuc_stack.ss_sp);
836
	err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
B
bellard 已提交
837
			  &frame->uc.tuc_stack.ss_flags);
838
	err |= __put_user(target_sigaltstack_used.ss_size,
B
bellard 已提交
839 840
			  &frame->uc.tuc_stack.ss_size);
	err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate,
B
bellard 已提交
841 842
			        env, set->sig[0], 
                                frame_addr + offsetof(struct rt_sigframe, fpstate));
843
        for(i = 0; i < TARGET_NSIG_WORDS; i++) {
B
bellard 已提交
844
            if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
845 846
                goto give_sigsegv;
        }
847

B
bellard 已提交
848 849
	/* Set up to return from userspace.  If provided, use a stub
	   already in userspace.  */
P
pbrook 已提交
850 851
	if (ka->sa_flags & TARGET_SA_RESTORER) {
		err |= __put_user(ka->sa_restorer, &frame->pretcode);
B
bellard 已提交
852
	} else {
853
                uint16_t val16;
B
bellard 已提交
854 855
                addr = frame_addr + offsetof(struct rt_sigframe, retcode);
		err |= __put_user(addr, &frame->pretcode);
B
bellard 已提交
856
		/* This is movl $,%eax ; int $0x80 */
857
                err |= __put_user(0xb8, (char *)(frame->retcode+0));
B
bellard 已提交
858
		err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
859 860
                val16 = 0x80cd;
                err |= __put_user(val16, (uint16_t *)(frame->retcode+5));
B
bellard 已提交
861 862 863 864 865 866
	}

	if (err)
		goto give_sigsegv;

	/* Set up registers for signal handler */
B
bellard 已提交
867
	env->regs[R_ESP] = frame_addr;
P
pbrook 已提交
868
	env->eip = ka->_sa_handler;
B
bellard 已提交
869 870 871 872 873 874 875

        cpu_x86_load_seg(env, R_DS, __USER_DS);
        cpu_x86_load_seg(env, R_ES, __USER_DS);
        cpu_x86_load_seg(env, R_SS, __USER_DS);
        cpu_x86_load_seg(env, R_CS, __USER_CS);
	env->eflags &= ~TF_MASK;

876 877
	unlock_user_struct(frame, frame_addr, 1);

B
bellard 已提交
878 879 880
	return;

give_sigsegv:
881
	unlock_user_struct(frame, frame_addr, 1);
B
bellard 已提交
882
	if (sig == TARGET_SIGSEGV)
P
pbrook 已提交
883
		ka->_sa_handler = TARGET_SIG_DFL;
B
bellard 已提交
884 885 886 887 888 889 890
	force_sig(TARGET_SIGSEGV /* , current */);
}

static int
restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
{
	unsigned int err = 0;
B
bellard 已提交
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
        abi_ulong fpstate_addr;
        unsigned int tmpflags;

        cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
        cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
        cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
        cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));

        env->regs[R_EDI] = tswapl(sc->edi);
        env->regs[R_ESI] = tswapl(sc->esi);
        env->regs[R_EBP] = tswapl(sc->ebp);
        env->regs[R_ESP] = tswapl(sc->esp);
        env->regs[R_EBX] = tswapl(sc->ebx);
        env->regs[R_EDX] = tswapl(sc->edx);
        env->regs[R_ECX] = tswapl(sc->ecx);
        env->eip = tswapl(sc->eip);
B
bellard 已提交
907 908 909

        cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3);
        cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3);
910

B
bellard 已提交
911 912 913
        tmpflags = tswapl(sc->eflags);
        env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
        //		regs->orig_eax = -1;		/* disable syscall checks */
B
bellard 已提交
914

B
bellard 已提交
915 916 917 918 919 920
        fpstate_addr = tswapl(sc->fpstate);
	if (fpstate_addr != 0) {
                if (!access_ok(VERIFY_READ, fpstate_addr, 
                               sizeof(struct target_fpstate)))
                        goto badframe;
                cpu_x86_frstor(env, fpstate_addr, 1);
B
bellard 已提交
921
	}
B
bellard 已提交
922

B
bellard 已提交
923
        *peax = tswapl(sc->eax);
B
bellard 已提交
924 925 926 927 928 929 930
	return err;
badframe:
	return 1;
}

long do_sigreturn(CPUX86State *env)
{
931 932
    struct sigframe *frame;
    abi_ulong frame_addr = env->regs[R_ESP] - 8;
B
bellard 已提交
933 934 935 936
    target_sigset_t target_set;
    sigset_t set;
    int eax, i;

B
bellard 已提交
937 938 939
#if defined(DEBUG_SIGNAL)
    fprintf(stderr, "do_sigreturn\n");
#endif
940 941
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
        goto badframe;
B
bellard 已提交
942
    /* set blocked signals */
943 944 945 946 947 948
    if (__get_user(target_set.sig[0], &frame->sc.oldmask))
        goto badframe;
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
            goto badframe;
    }
B
bellard 已提交
949

950
    target_to_host_sigset_internal(&set, &target_set);
B
bellard 已提交
951
    sigprocmask(SIG_SETMASK, &set, NULL);
952

B
bellard 已提交
953 954 955
    /* restore registers */
    if (restore_sigcontext(env, &frame->sc, &eax))
        goto badframe;
956
    unlock_user_struct(frame, frame_addr, 0);
B
bellard 已提交
957 958 959
    return eax;

badframe:
960
    unlock_user_struct(frame, frame_addr, 0);
B
bellard 已提交
961 962 963 964 965 966
    force_sig(TARGET_SIGSEGV);
    return 0;
}

long do_rt_sigreturn(CPUX86State *env)
{
B
bellard 已提交
967 968
        abi_ulong frame_addr;
	struct rt_sigframe *frame;
B
bellard 已提交
969 970 971
        sigset_t set;
	int eax;

B
bellard 已提交
972 973 974
        frame_addr = env->regs[R_ESP] - 4;
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
                goto badframe;
B
bellard 已提交
975
        target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
B
bellard 已提交
976
        sigprocmask(SIG_SETMASK, &set, NULL);
977

B
bellard 已提交
978
	if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
B
bellard 已提交
979 980
		goto badframe;

B
bellard 已提交
981 982
	if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0, 
                           get_sp_from_cpustate(env)) == -EFAULT)
B
bellard 已提交
983
		goto badframe;
984

B
bellard 已提交
985
        unlock_user_struct(frame, frame_addr, 0);
B
bellard 已提交
986 987 988
	return eax;

badframe:
B
bellard 已提交
989 990
        unlock_user_struct(frame, frame_addr, 0);
        force_sig(TARGET_SIGSEGV);
B
bellard 已提交
991 992 993
	return 0;
}

B
bellard 已提交
994 995 996
#elif defined(TARGET_ARM)

struct target_sigcontext {
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
	abi_ulong trap_no;
	abi_ulong error_code;
	abi_ulong oldmask;
	abi_ulong arm_r0;
	abi_ulong arm_r1;
	abi_ulong arm_r2;
	abi_ulong arm_r3;
	abi_ulong arm_r4;
	abi_ulong arm_r5;
	abi_ulong arm_r6;
	abi_ulong arm_r7;
	abi_ulong arm_r8;
	abi_ulong arm_r9;
	abi_ulong arm_r10;
	abi_ulong arm_fp;
	abi_ulong arm_ip;
	abi_ulong arm_sp;
	abi_ulong arm_lr;
	abi_ulong arm_pc;
	abi_ulong arm_cpsr;
	abi_ulong fault_address;
B
bellard 已提交
1018 1019
};

P
pbrook 已提交
1020 1021 1022 1023 1024 1025 1026 1027 1028
struct target_ucontext_v1 {
    abi_ulong tuc_flags;
    abi_ulong tuc_link;
    target_stack_t tuc_stack;
    struct target_sigcontext tuc_mcontext;
    target_sigset_t  tuc_sigmask;	/* mask last for extensibility */
};

struct target_ucontext_v2 {
1029 1030
    abi_ulong tuc_flags;
    abi_ulong tuc_link;
B
bellard 已提交
1031 1032 1033
    target_stack_t tuc_stack;
    struct target_sigcontext tuc_mcontext;
    target_sigset_t  tuc_sigmask;	/* mask last for extensibility */
P
pbrook 已提交
1034 1035
    char __unused[128 - sizeof(sigset_t)];
    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
B
bellard 已提交
1036 1037
};

P
pbrook 已提交
1038
struct sigframe_v1
B
bellard 已提交
1039 1040
{
    struct target_sigcontext sc;
1041 1042
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
    abi_ulong retcode;
B
bellard 已提交
1043 1044
};

P
pbrook 已提交
1045 1046 1047 1048 1049 1050
struct sigframe_v2
{
    struct target_ucontext_v2 uc;
    abi_ulong retcode;
};

P
pbrook 已提交
1051
struct rt_sigframe_v1
B
bellard 已提交
1052
{
B
bellard 已提交
1053 1054
    abi_ulong pinfo;
    abi_ulong puc;
B
bellard 已提交
1055
    struct target_siginfo info;
P
pbrook 已提交
1056 1057 1058 1059 1060 1061 1062 1063
    struct target_ucontext_v1 uc;
    abi_ulong retcode;
};

struct rt_sigframe_v2
{
    struct target_siginfo info;
    struct target_ucontext_v2 uc;
1064
    abi_ulong retcode;
B
bellard 已提交
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
};

#define TARGET_CONFIG_CPU_32 1

/*
 * For ARM syscalls, we encode the syscall number into the instruction.
 */
#define SWI_SYS_SIGRETURN	(0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
#define SWI_SYS_RT_SIGRETURN	(0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))

/*
 * For Thumb syscalls, we pass the syscall number via r7.  We therefore
 * need two 16-bit instructions.
 */
#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))

1082
static const abi_ulong retcodes[4] = {
B
bellard 已提交
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
};


#define __get_user_error(x,p,e) __get_user(x, p)

static inline int valid_user_regs(CPUState *regs)
{
    return 1;
}

P
pbrook 已提交
1095
static void
B
bellard 已提交
1096
setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
B
bellard 已提交
1097
		 CPUState *env, abi_ulong mask)
B
bellard 已提交
1098
{
P
pbrook 已提交
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114
	__put_user(env->regs[0], &sc->arm_r0);
	__put_user(env->regs[1], &sc->arm_r1);
	__put_user(env->regs[2], &sc->arm_r2);
	__put_user(env->regs[3], &sc->arm_r3);
	__put_user(env->regs[4], &sc->arm_r4);
	__put_user(env->regs[5], &sc->arm_r5);
	__put_user(env->regs[6], &sc->arm_r6);
	__put_user(env->regs[7], &sc->arm_r7);
	__put_user(env->regs[8], &sc->arm_r8);
	__put_user(env->regs[9], &sc->arm_r9);
	__put_user(env->regs[10], &sc->arm_r10);
	__put_user(env->regs[11], &sc->arm_fp);
	__put_user(env->regs[12], &sc->arm_ip);
	__put_user(env->regs[13], &sc->arm_sp);
	__put_user(env->regs[14], &sc->arm_lr);
	__put_user(env->regs[15], &sc->arm_pc);
B
bellard 已提交
1115
#ifdef TARGET_CONFIG_CPU_32
P
pbrook 已提交
1116
	__put_user(cpsr_read(env), &sc->arm_cpsr);
B
bellard 已提交
1117 1118
#endif

P
pbrook 已提交
1119 1120 1121 1122
	__put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
	__put_user(/* current->thread.error_code */ 0, &sc->error_code);
	__put_user(/* current->thread.address */ 0, &sc->fault_address);
	__put_user(mask, &sc->oldmask);
B
bellard 已提交
1123 1124
}

1125
static inline abi_ulong
P
pbrook 已提交
1126
get_sigframe(struct target_sigaction *ka, CPUState *regs, int framesize)
B
bellard 已提交
1127 1128 1129 1130 1131 1132
{
	unsigned long sp = regs->regs[13];

	/*
	 * This is the X/Open sanctioned signal stack switching.
	 */
P
pbrook 已提交
1133
	if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
1134
            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
B
bellard 已提交
1135 1136 1137
	/*
	 * ATPCS B01 mandates 8-byte alignment
	 */
1138
	return (sp - framesize) & ~7;
B
bellard 已提交
1139 1140 1141
}

static int
P
pbrook 已提交
1142
setup_return(CPUState *env, struct target_sigaction *ka,
B
bellard 已提交
1143
	     abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
B
bellard 已提交
1144
{
P
pbrook 已提交
1145
	abi_ulong handler = ka->_sa_handler;
1146
	abi_ulong retcode;
P
pbrook 已提交
1147
	int thumb = handler & 1;
B
bellard 已提交
1148

P
pbrook 已提交
1149 1150
	if (ka->sa_flags & TARGET_SA_RESTORER) {
		retcode = ka->sa_restorer;
B
bellard 已提交
1151 1152 1153
	} else {
		unsigned int idx = thumb;

P
pbrook 已提交
1154
		if (ka->sa_flags & TARGET_SA_SIGINFO)
B
bellard 已提交
1155 1156 1157 1158 1159
			idx += 2;

		if (__put_user(retcodes[idx], rc))
			return 1;
#if 0
1160 1161
		flush_icache_range((abi_ulong)rc,
				   (abi_ulong)(rc + 1));
B
bellard 已提交
1162
#endif
B
bellard 已提交
1163
		retcode = rc_addr + thumb;
B
bellard 已提交
1164 1165 1166
	}

	env->regs[0] = usig;
B
bellard 已提交
1167
	env->regs[13] = frame_addr;
B
bellard 已提交
1168 1169
	env->regs[14] = retcode;
	env->regs[15] = handler & (thumb ? ~1 : ~3);
P
pbrook 已提交
1170
	env->thumb = thumb;
B
bellard 已提交
1171

B
bellard 已提交
1172
#if 0
B
bellard 已提交
1173 1174
#ifdef TARGET_CONFIG_CPU_32
	env->cpsr = cpsr;
B
bellard 已提交
1175
#endif
B
bellard 已提交
1176 1177 1178 1179 1180
#endif

	return 0;
}

P
pbrook 已提交
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
                              target_sigset_t *set, CPUState *env)
{
    struct target_sigaltstack stack;
    int i;

    /* Clear all the bits of the ucontext we don't use.  */
    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));

    memset(&stack, 0, sizeof(stack));
    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
    memcpy(&uc->tuc_stack, &stack, sizeof(stack));

    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
    /* FIXME: Save coprocessor signal frame.  */
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
    }
}

1203
/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
P
pbrook 已提交
1204
static void setup_frame_v1(int usig, struct target_sigaction *ka,
P
pbrook 已提交
1205
			   target_sigset_t *set, CPUState *regs)
B
bellard 已提交
1206
{
P
pbrook 已提交
1207
	struct sigframe_v1 *frame;
1208
	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
P
pbrook 已提交
1209
	int i;
B
bellard 已提交
1210

1211 1212 1213
	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
		return;

P
pbrook 已提交
1214
	setup_sigcontext(&frame->sc, regs, set->sig[0]);
B
bellard 已提交
1215

1216 1217
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
            if (__put_user(set->sig[i], &frame->extramask[i - 1]))
1218
                goto end;
B
bellard 已提交
1219 1220
	}

P
pbrook 已提交
1221 1222
        setup_return(regs, ka, &frame->retcode, frame_addr, usig,
                     frame_addr + offsetof(struct sigframe_v1, retcode));
1223 1224 1225

end:
	unlock_user_struct(frame, frame_addr, 1);
P
pbrook 已提交
1226 1227
}

P
pbrook 已提交
1228
static void setup_frame_v2(int usig, struct target_sigaction *ka,
P
pbrook 已提交
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
			   target_sigset_t *set, CPUState *regs)
{
	struct sigframe_v2 *frame;
	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));

	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
		return;

        setup_sigframe_v2(&frame->uc, set, regs);

        setup_return(regs, ka, &frame->retcode, frame_addr, usig,
                     frame_addr + offsetof(struct sigframe_v2, retcode));

	unlock_user_struct(frame, frame_addr, 1);
}

P
pbrook 已提交
1245
static void setup_frame(int usig, struct target_sigaction *ka,
P
pbrook 已提交
1246 1247 1248 1249 1250 1251 1252
			target_sigset_t *set, CPUState *regs)
{
    if (get_osversion() >= 0x020612) {
        setup_frame_v2(usig, ka, set, regs);
    } else {
        setup_frame_v1(usig, ka, set, regs);
    }
B
bellard 已提交
1253 1254
}

1255
/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
P
pbrook 已提交
1256
static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
P
pbrook 已提交
1257 1258
                              target_siginfo_t *info,
			      target_sigset_t *set, CPUState *env)
B
bellard 已提交
1259
{
P
pbrook 已提交
1260
	struct rt_sigframe_v1 *frame;
1261
	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1262
	struct target_sigaltstack stack;
P
pbrook 已提交
1263
	int i;
B
bellard 已提交
1264
        abi_ulong info_addr, uc_addr;
B
bellard 已提交
1265

1266
	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1267 1268
            return /* 1 */;

P
pbrook 已提交
1269
        info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
P
pbrook 已提交
1270
	__put_user(info_addr, &frame->pinfo);
P
pbrook 已提交
1271
        uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
P
pbrook 已提交
1272 1273
	__put_user(uc_addr, &frame->puc);
	copy_siginfo_to_user(&frame->info, info);
B
bellard 已提交
1274 1275

	/* Clear all the bits of the ucontext we don't use.  */
P
pbrook 已提交
1276
	memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
B
bellard 已提交
1277

1278 1279 1280 1281
        memset(&stack, 0, sizeof(stack));
        __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
        __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
        __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1282
        memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
1283

P
pbrook 已提交
1284
	setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1285
        for(i = 0; i < TARGET_NSIG_WORDS; i++) {
B
bellard 已提交
1286
            if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
1287
                goto end;
1288
        }
B
bellard 已提交
1289

P
pbrook 已提交
1290 1291
        setup_return(env, ka, &frame->retcode, frame_addr, usig,
                     frame_addr + offsetof(struct rt_sigframe_v1, retcode));
P
pbrook 已提交
1292

P
pbrook 已提交
1293 1294
        env->regs[1] = info_addr;
        env->regs[2] = uc_addr;
P
pbrook 已提交
1295 1296 1297 1298 1299

end:
	unlock_user_struct(frame, frame_addr, 1);
}

P
pbrook 已提交
1300
static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
P
pbrook 已提交
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
                              target_siginfo_t *info,
                              target_sigset_t *set, CPUState *env)
{
	struct rt_sigframe_v2 *frame;
	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
        abi_ulong info_addr, uc_addr;

	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
            return /* 1 */;

        info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
        uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
P
pbrook 已提交
1313
	copy_siginfo_to_user(&frame->info, info);
P
pbrook 已提交
1314

P
pbrook 已提交
1315
        setup_sigframe_v2(&frame->uc, set, env);
P
pbrook 已提交
1316

P
pbrook 已提交
1317 1318
        setup_return(env, ka, &frame->retcode, frame_addr, usig,
                     frame_addr + offsetof(struct rt_sigframe_v2, retcode));
P
pbrook 已提交
1319

P
pbrook 已提交
1320 1321
        env->regs[1] = info_addr;
        env->regs[2] = uc_addr;
B
bellard 已提交
1322

1323
	unlock_user_struct(frame, frame_addr, 1);
B
bellard 已提交
1324 1325
}

P
pbrook 已提交
1326
static void setup_rt_frame(int usig, struct target_sigaction *ka,
P
pbrook 已提交
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
                           target_siginfo_t *info,
			   target_sigset_t *set, CPUState *env)
{
    if (get_osversion() >= 0x020612) {
        setup_rt_frame_v2(usig, ka, info, set, env);
    } else {
        setup_rt_frame_v1(usig, ka, info, set, env);
    }
}

B
bellard 已提交
1337 1338 1339 1340
static int
restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
{
	int err = 0;
B
bellard 已提交
1341
        uint32_t cpsr;
B
bellard 已提交
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359

	__get_user_error(env->regs[0], &sc->arm_r0, err);
	__get_user_error(env->regs[1], &sc->arm_r1, err);
	__get_user_error(env->regs[2], &sc->arm_r2, err);
	__get_user_error(env->regs[3], &sc->arm_r3, err);
	__get_user_error(env->regs[4], &sc->arm_r4, err);
	__get_user_error(env->regs[5], &sc->arm_r5, err);
	__get_user_error(env->regs[6], &sc->arm_r6, err);
	__get_user_error(env->regs[7], &sc->arm_r7, err);
	__get_user_error(env->regs[8], &sc->arm_r8, err);
	__get_user_error(env->regs[9], &sc->arm_r9, err);
	__get_user_error(env->regs[10], &sc->arm_r10, err);
	__get_user_error(env->regs[11], &sc->arm_fp, err);
	__get_user_error(env->regs[12], &sc->arm_ip, err);
	__get_user_error(env->regs[13], &sc->arm_sp, err);
	__get_user_error(env->regs[14], &sc->arm_lr, err);
	__get_user_error(env->regs[15], &sc->arm_pc, err);
#ifdef TARGET_CONFIG_CPU_32
B
bellard 已提交
1360
	__get_user_error(cpsr, &sc->arm_cpsr, err);
P
pbrook 已提交
1361
        cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
B
bellard 已提交
1362 1363 1364 1365 1366 1367 1368
#endif

	err |= !valid_user_regs(env);

	return err;
}

P
pbrook 已提交
1369
long do_sigreturn_v1(CPUState *env)
B
bellard 已提交
1370
{
B
bellard 已提交
1371
        abi_ulong frame_addr;
P
pbrook 已提交
1372
	struct sigframe_v1 *frame;
B
bellard 已提交
1373 1374
	target_sigset_t set;
        sigset_t host_set;
1375
        int i;
B
bellard 已提交
1376 1377 1378 1379 1380 1381 1382 1383 1384

	/*
	 * Since we stacked the signal on a 64-bit boundary,
	 * then 'sp' should be word aligned here.  If it's
	 * not, then the user is trying to mess with us.
	 */
	if (env->regs[13] & 7)
		goto badframe;

B
bellard 已提交
1385 1386 1387
        frame_addr = env->regs[13];
	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
                goto badframe;
B
bellard 已提交
1388

1389 1390 1391 1392 1393 1394
	if (__get_user(set.sig[0], &frame->sc.oldmask))
            goto badframe;
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
            if (__get_user(set.sig[i], &frame->extramask[i - 1]))
                goto badframe;
        }
B
bellard 已提交
1395

1396
        target_to_host_sigset_internal(&host_set, &set);
B
bellard 已提交
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
        sigprocmask(SIG_SETMASK, &host_set, NULL);

	if (restore_sigcontext(env, &frame->sc))
		goto badframe;

#if 0
	/* Send SIGTRAP if we're single-stepping */
	if (ptrace_cancel_bpt(current))
		send_sig(SIGTRAP, current, 1);
#endif
B
bellard 已提交
1407 1408
	unlock_user_struct(frame, frame_addr, 0);
        return env->regs[0];
B
bellard 已提交
1409 1410

badframe:
B
bellard 已提交
1411
	unlock_user_struct(frame, frame_addr, 0);
B
bellard 已提交
1412 1413 1414 1415
        force_sig(SIGSEGV /* , current */);
	return 0;
}

P
pbrook 已提交
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
                                 struct target_ucontext_v2 *uc)
{
    sigset_t host_set;

    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
    sigprocmask(SIG_SETMASK, &host_set, NULL);

    if (restore_sigcontext(env, &uc->tuc_mcontext))
        return 1;

    if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
        return 1;

#if 0
    /* Send SIGTRAP if we're single-stepping */
    if (ptrace_cancel_bpt(current))
            send_sig(SIGTRAP, current, 1);
#endif

    return 0;
}

long do_sigreturn_v2(CPUState *env)
{
        abi_ulong frame_addr;
	struct sigframe_v2 *frame;

	/*
	 * Since we stacked the signal on a 64-bit boundary,
	 * then 'sp' should be word aligned here.  If it's
	 * not, then the user is trying to mess with us.
	 */
	if (env->regs[13] & 7)
		goto badframe;

        frame_addr = env->regs[13];
	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
                goto badframe;

        if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
                goto badframe;

	unlock_user_struct(frame, frame_addr, 0);
	return env->regs[0];

badframe:
	unlock_user_struct(frame, frame_addr, 0);
        force_sig(SIGSEGV /* , current */);
	return 0;
}

long do_sigreturn(CPUState *env)
{
    if (get_osversion() >= 0x020612) {
        return do_sigreturn_v2(env);
    } else {
        return do_sigreturn_v1(env);
    }
}

P
pbrook 已提交
1477
long do_rt_sigreturn_v1(CPUState *env)
B
bellard 已提交
1478
{
B
bellard 已提交
1479
        abi_ulong frame_addr;
P
pbrook 已提交
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521
	struct rt_sigframe_v1 *frame;
        sigset_t host_set;

	/*
	 * Since we stacked the signal on a 64-bit boundary,
	 * then 'sp' should be word aligned here.  If it's
	 * not, then the user is trying to mess with us.
	 */
	if (env->regs[13] & 7)
		goto badframe;

        frame_addr = env->regs[13];
	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
                goto badframe;

        target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
        sigprocmask(SIG_SETMASK, &host_set, NULL);

	if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
		goto badframe;

	if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
		goto badframe;

#if 0
	/* Send SIGTRAP if we're single-stepping */
	if (ptrace_cancel_bpt(current))
		send_sig(SIGTRAP, current, 1);
#endif
	unlock_user_struct(frame, frame_addr, 0);
	return env->regs[0];

badframe:
	unlock_user_struct(frame, frame_addr, 0);
        force_sig(SIGSEGV /* , current */);
	return 0;
}

long do_rt_sigreturn_v2(CPUState *env)
{
        abi_ulong frame_addr;
	struct rt_sigframe_v2 *frame;
B
bellard 已提交
1522 1523 1524 1525 1526 1527 1528 1529 1530

	/*
	 * Since we stacked the signal on a 64-bit boundary,
	 * then 'sp' should be word aligned here.  If it's
	 * not, then the user is trying to mess with us.
	 */
	if (env->regs[13] & 7)
		goto badframe;

B
bellard 已提交
1531 1532 1533
        frame_addr = env->regs[13];
	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
                goto badframe;
B
bellard 已提交
1534

P
pbrook 已提交
1535 1536
        if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
                goto badframe;
1537

B
bellard 已提交
1538
	unlock_user_struct(frame, frame_addr, 0);
B
bellard 已提交
1539 1540 1541
	return env->regs[0];

badframe:
B
bellard 已提交
1542
	unlock_user_struct(frame, frame_addr, 0);
B
bellard 已提交
1543 1544 1545 1546
        force_sig(SIGSEGV /* , current */);
	return 0;
}

P
pbrook 已提交
1547 1548 1549 1550 1551 1552 1553 1554 1555
long do_rt_sigreturn(CPUState *env)
{
    if (get_osversion() >= 0x020612) {
        return do_rt_sigreturn_v2(env);
    } else {
        return do_rt_sigreturn_v1(env);
    }
}

B
bellard 已提交
1556
#elif defined(TARGET_SPARC)
B
bellard 已提交
1557

B
bellard 已提交
1558 1559 1560 1561
#define __SUNOS_MAXWIN   31

/* This is what SunOS does, so shall I. */
struct target_sigcontext {
1562
        abi_ulong sigc_onstack;      /* state to restore */
B
bellard 已提交
1563

1564 1565 1566 1567 1568 1569 1570
        abi_ulong sigc_mask;         /* sigmask to restore */
        abi_ulong sigc_sp;           /* stack pointer */
        abi_ulong sigc_pc;           /* program counter */
        abi_ulong sigc_npc;          /* next program counter */
        abi_ulong sigc_psr;          /* for condition codes etc */
        abi_ulong sigc_g1;           /* User uses these two registers */
        abi_ulong sigc_o0;           /* within the trampoline code. */
B
bellard 已提交
1571 1572 1573 1574

        /* Now comes information regarding the users window set
         * at the time of the signal.
         */
1575
        abi_ulong sigc_oswins;       /* outstanding windows */
B
bellard 已提交
1576 1577 1578 1579 1580 1581

        /* stack ptrs for each regwin buf */
        char *sigc_spbuf[__SUNOS_MAXWIN];

        /* Windows to restore after signal */
        struct {
1582 1583
                abi_ulong locals[8];
                abi_ulong ins[8];
B
bellard 已提交
1584 1585 1586 1587
        } sigc_wbuf[__SUNOS_MAXWIN];
};
/* A Sparc stack frame */
struct sparc_stackf {
1588 1589
        abi_ulong locals[8];
        abi_ulong ins[6];
B
bellard 已提交
1590
        struct sparc_stackf *fp;
1591
        abi_ulong callers_pc;
B
bellard 已提交
1592
        char *structptr;
1593 1594
        abi_ulong xargs[6];
        abi_ulong xxargs[1];
B
bellard 已提交
1595 1596 1597 1598
};

typedef struct {
        struct {
1599 1600 1601 1602 1603
                abi_ulong psr;
                abi_ulong pc;
                abi_ulong npc;
                abi_ulong y;
                abi_ulong u_regs[16]; /* globals and ins */
B
bellard 已提交
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
        }               si_regs;
        int             si_mask;
} __siginfo_t;

typedef struct {
        unsigned   long si_float_regs [32];
        unsigned   long si_fsr;
        unsigned   long si_fpqdepth;
        struct {
                unsigned long *insn_addr;
                unsigned long insn;
        } si_fpqueue [16];
B
bellard 已提交
1616
} qemu_siginfo_fpu_t;
B
bellard 已提交
1617 1618 1619 1620 1621


struct target_signal_frame {
	struct sparc_stackf	ss;
	__siginfo_t		info;
B
bellard 已提交
1622
	abi_ulong               fpu_save;
1623 1624 1625
	abi_ulong		insns[2] __attribute__ ((aligned (8)));
	abi_ulong		extramask[TARGET_NSIG_WORDS - 1];
	abi_ulong		extra_size; /* Should be 0 */
B
bellard 已提交
1626
	qemu_siginfo_fpu_t	fpu_state;
B
bellard 已提交
1627 1628 1629 1630
};
struct target_rt_signal_frame {
	struct sparc_stackf	ss;
	siginfo_t		info;
1631
	abi_ulong		regs[20];
B
bellard 已提交
1632
	sigset_t		mask;
B
bellard 已提交
1633
	abi_ulong               fpu_save;
B
bellard 已提交
1634 1635 1636
	unsigned int		insns[2];
	stack_t			stack;
	unsigned int		extra_size; /* Should be 0 */
B
bellard 已提交
1637
	qemu_siginfo_fpu_t	fpu_state;
B
bellard 已提交
1638 1639
};

B
bellard 已提交
1640 1641 1642 1643 1644
#define UREG_O0        16
#define UREG_O6        22
#define UREG_I0        0
#define UREG_I1        1
#define UREG_I2        2
B
blueswir1 已提交
1645 1646 1647
#define UREG_I3        3
#define UREG_I4        4
#define UREG_I5        5
B
bellard 已提交
1648 1649 1650
#define UREG_I6        6
#define UREG_I7        7
#define UREG_L0	       8
B
bellard 已提交
1651 1652 1653
#define UREG_FP        UREG_I6
#define UREG_SP        UREG_O6

P
pbrook 已提交
1654
static inline abi_ulong get_sigframe(struct target_sigaction *sa, 
1655
                                     CPUState *env, unsigned long framesize)
B
bellard 已提交
1656
{
1657
	abi_ulong sp;
B
bellard 已提交
1658 1659 1660 1661

	sp = env->regwptr[UREG_FP];

	/* This is the X/Open sanctioned signal stack switching.  */
P
pbrook 已提交
1662
	if (sa->sa_flags & TARGET_SA_ONSTACK) {
1663 1664 1665
            if (!on_sig_stack(sp)
                && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
                sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
B
bellard 已提交
1666
	}
1667
	return sp - framesize;
B
bellard 已提交
1668 1669 1670
}

static int
1671
setup___siginfo(__siginfo_t *si, CPUState *env, abi_ulong mask)
B
bellard 已提交
1672 1673 1674 1675 1676 1677 1678
{
	int err = 0, i;

	err |= __put_user(env->psr, &si->si_regs.psr);
	err |= __put_user(env->pc, &si->si_regs.pc);
	err |= __put_user(env->npc, &si->si_regs.npc);
	err |= __put_user(env->y, &si->si_regs.y);
B
bellard 已提交
1679
	for (i=0; i < 8; i++) {
B
bellard 已提交
1680 1681
		err |= __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
	}
B
bellard 已提交
1682
	for (i=0; i < 8; i++) {
B
bellard 已提交
1683
		err |= __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
B
bellard 已提交
1684 1685 1686 1687
	}
	err |= __put_user(mask, &si->si_mask);
	return err;
}
B
bellard 已提交
1688

B
bellard 已提交
1689
#if 0
B
bellard 已提交
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705
static int
setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
		 CPUState *env, unsigned long mask)
{
	int err = 0;

	err |= __put_user(mask, &sc->sigc_mask);
	err |= __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
	err |= __put_user(env->pc, &sc->sigc_pc);
	err |= __put_user(env->npc, &sc->sigc_npc);
	err |= __put_user(env->psr, &sc->sigc_psr);
	err |= __put_user(env->gregs[1], &sc->sigc_g1);
	err |= __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);

	return err;
}
B
bellard 已提交
1706
#endif
B
bellard 已提交
1707 1708
#define NF_ALIGNEDSZ  (((sizeof(struct target_signal_frame) + 7) & (~7)))

P
pbrook 已提交
1709
static void setup_frame(int sig, struct target_sigaction *ka,
B
bellard 已提交
1710 1711
			target_sigset_t *set, CPUState *env)
{
1712
        abi_ulong sf_addr;
B
bellard 已提交
1713 1714 1715 1716 1717 1718 1719
	struct target_signal_frame *sf;
	int sigframe_size, err, i;

	/* 1. Make sure everything is clean */
	//synchronize_user_stack();

        sigframe_size = NF_ALIGNEDSZ;
1720
	sf_addr = get_sigframe(ka, env, sigframe_size);
B
bellard 已提交
1721

1722 1723 1724 1725 1726
        sf = lock_user(VERIFY_WRITE, sf_addr, 
                       sizeof(struct target_signal_frame), 0);
        if (!sf)
		goto sigsegv;
                
B
bellard 已提交
1727
	//fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
B
bellard 已提交
1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743
#if 0
	if (invalid_frame_pointer(sf, sigframe_size))
		goto sigill_and_return;
#endif
	/* 2. Save the current process state */
	err = setup___siginfo(&sf->info, env, set->sig[0]);
	err |= __put_user(0, &sf->extra_size);

	//err |= save_fpu_state(regs, &sf->fpu_state);
	//err |= __put_user(&sf->fpu_state, &sf->fpu_save);

	err |= __put_user(set->sig[0], &sf->info.si_mask);
	for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
		err |= __put_user(set->sig[i + 1], &sf->extramask[i]);
	}

B
bellard 已提交
1744
	for (i = 0; i < 8; i++) {
B
bellard 已提交
1745
	  	err |= __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
B
bellard 已提交
1746
	}
B
bellard 已提交
1747
	for (i = 0; i < 8; i++) {
B
bellard 已提交
1748
	  	err |= __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
B
bellard 已提交
1749 1750 1751 1752 1753
	}
	if (err)
		goto sigsegv;

	/* 3. signal handler back-trampoline and parameters */
1754
	env->regwptr[UREG_FP] = sf_addr;
B
bellard 已提交
1755
	env->regwptr[UREG_I0] = sig;
1756 1757 1758 1759
	env->regwptr[UREG_I1] = sf_addr + 
                offsetof(struct target_signal_frame, info);
	env->regwptr[UREG_I2] = sf_addr + 
                offsetof(struct target_signal_frame, info);
B
bellard 已提交
1760 1761

	/* 4. signal handler */
P
pbrook 已提交
1762
	env->pc = ka->_sa_handler;
B
bellard 已提交
1763 1764
	env->npc = (env->pc + 4);
	/* 5. return to kernel instructions */
P
pbrook 已提交
1765 1766
	if (ka->sa_restorer)
		env->regwptr[UREG_I7] = ka->sa_restorer;
B
bellard 已提交
1767
	else {
1768
                uint32_t val32;
1769 1770 1771

		env->regwptr[UREG_I7] = sf_addr + 
                        offsetof(struct target_signal_frame, insns) - 2 * 4;
B
bellard 已提交
1772 1773

		/* mov __NR_sigreturn, %g1 */
1774 1775
                val32 = 0x821020d8;
		err |= __put_user(val32, &sf->insns[0]);
B
bellard 已提交
1776 1777

		/* t 0x10 */
1778 1779
                val32 = 0x91d02010;
		err |= __put_user(val32, &sf->insns[1]);
B
bellard 已提交
1780 1781 1782 1783 1784
		if (err)
			goto sigsegv;

		/* Flush instruction space. */
		//flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
B
bellard 已提交
1785
                //		tb_flush(env);
B
bellard 已提交
1786
	}
1787
        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
B
bellard 已提交
1788
	return;
1789 1790
#if 0
sigill_and_return:
B
bellard 已提交
1791
	force_sig(TARGET_SIGILL);
1792
#endif
B
bellard 已提交
1793
sigsegv:
B
bellard 已提交
1794
	//fprintf(stderr, "force_sig\n");
1795
        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
B
bellard 已提交
1796 1797 1798
	force_sig(TARGET_SIGSEGV);
}
static inline int
B
bellard 已提交
1799
restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu)
B
bellard 已提交
1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819
{
        int err;
#if 0
#ifdef CONFIG_SMP
        if (current->flags & PF_USEDFPU)
                regs->psr &= ~PSR_EF;
#else
        if (current == last_task_used_math) {
                last_task_used_math = 0;
                regs->psr &= ~PSR_EF;
        }
#endif
        current->used_math = 1;
        current->flags &= ~PF_USEDFPU;
#endif
#if 0
        if (verify_area (VERIFY_READ, fpu, sizeof(*fpu)))
                return -EFAULT;
#endif

B
bellard 已提交
1820 1821
#if 0
        /* XXX: incorrect */
B
bellard 已提交
1822 1823
        err = __copy_from_user(&env->fpr[0], &fpu->si_float_regs[0],
	                             (sizeof(unsigned long) * 32));
B
bellard 已提交
1824
#endif
B
bellard 已提交
1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837
        err |= __get_user(env->fsr, &fpu->si_fsr);
#if 0
        err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
        if (current->thread.fpqdepth != 0)
                err |= __copy_from_user(&current->thread.fpqueue[0],
                                        &fpu->si_fpqueue[0],
                                        ((sizeof(unsigned long) +
                                        (sizeof(unsigned long *)))*16));
#endif
        return err;
}


P
pbrook 已提交
1838
static void setup_rt_frame(int sig, struct target_sigaction *ka,
B
bellard 已提交
1839 1840 1841 1842 1843 1844 1845 1846
                           target_siginfo_t *info,
			   target_sigset_t *set, CPUState *env)
{
    fprintf(stderr, "setup_rt_frame: not implemented\n");
}

long do_sigreturn(CPUState *env)
{
B
bellard 已提交
1847
        abi_ulong sf_addr;
B
bellard 已提交
1848
        struct target_signal_frame *sf;
B
bellard 已提交
1849
        uint32_t up_psr, pc, npc;
B
bellard 已提交
1850
        target_sigset_t set;
B
bellard 已提交
1851
        sigset_t host_set;
B
bellard 已提交
1852
        abi_ulong fpu_save_addr;
B
bellard 已提交
1853
        int err, i;
B
bellard 已提交
1854

B
bellard 已提交
1855 1856 1857
        sf_addr = env->regwptr[UREG_FP];
        if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
                goto segv_and_exit;
B
bellard 已提交
1858
#if 0
B
bellard 已提交
1859 1860
	fprintf(stderr, "sigreturn\n");
	fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
B
bellard 已提交
1861
#endif
B
bellard 已提交
1862
	//cpu_dump_state(env, stderr, fprintf, 0);
B
bellard 已提交
1863 1864 1865

        /* 1. Make sure we are not getting garbage from the user */

B
bellard 已提交
1866
        if (sf_addr & 3)
B
bellard 已提交
1867 1868 1869 1870 1871 1872 1873 1874 1875
                goto segv_and_exit;

        err = __get_user(pc,  &sf->info.si_regs.pc);
        err |= __get_user(npc, &sf->info.si_regs.npc);

        if ((pc | npc) & 3)
                goto segv_and_exit;

        /* 2. Restore the state */
B
bellard 已提交
1876 1877
        err |= __get_user(up_psr, &sf->info.si_regs.psr);

B
bellard 已提交
1878
        /* User can only change condition codes and FPU enabling in %psr. */
B
bellard 已提交
1879 1880 1881 1882 1883
        env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
                  | (env->psr & ~(PSR_ICC /* | PSR_EF */));

	env->pc = pc;
	env->npc = npc;
B
bellard 已提交
1884
        err |= __get_user(env->y, &sf->info.si_regs.y);
B
bellard 已提交
1885
	for (i=0; i < 8; i++) {
B
bellard 已提交
1886 1887
		err |= __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
	}
B
bellard 已提交
1888
	for (i=0; i < 8; i++) {
B
bellard 已提交
1889 1890
		err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
	}
B
bellard 已提交
1891

B
bellard 已提交
1892
        err |= __get_user(fpu_save_addr, &sf->fpu_save);
B
bellard 已提交
1893

B
bellard 已提交
1894 1895
        //if (fpu_save)
        //        err |= restore_fpu_state(env, fpu_save);
B
bellard 已提交
1896 1897 1898 1899 1900

        /* This is pretty much atomic, no amount locking would prevent
         * the races which exist anyways.
         */
        err |= __get_user(set.sig[0], &sf->info.si_mask);
B
bellard 已提交
1901 1902 1903 1904 1905 1906
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
            err |= (__get_user(set.sig[i], &sf->extramask[i - 1]));
        }

        target_to_host_sigset_internal(&host_set, &set);
        sigprocmask(SIG_SETMASK, &host_set, NULL);
B
bellard 已提交
1907 1908 1909

        if (err)
                goto segv_and_exit;
B
bellard 已提交
1910
        unlock_user_struct(sf, sf_addr, 0);
B
bellard 已提交
1911 1912 1913
        return env->regwptr[0];

segv_and_exit:
B
bellard 已提交
1914
        unlock_user_struct(sf, sf_addr, 0);
B
bellard 已提交
1915 1916 1917 1918 1919 1920
	force_sig(TARGET_SIGSEGV);
}

long do_rt_sigreturn(CPUState *env)
{
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
B
bellard 已提交
1921
    return -TARGET_ENOSYS;
B
bellard 已提交
1922 1923
}

1924
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
B
blueswir1 已提交
1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
#define MC_TSTATE 0
#define MC_PC 1
#define MC_NPC 2
#define MC_Y 3
#define MC_G1 4
#define MC_G2 5
#define MC_G3 6
#define MC_G4 7
#define MC_G5 8
#define MC_G6 9
#define MC_G7 10
#define MC_O0 11
#define MC_O1 12
#define MC_O2 13
#define MC_O3 14
#define MC_O4 15
#define MC_O5 16
#define MC_O6 17
#define MC_O7 18
#define MC_NGREG 19

1946
typedef abi_ulong target_mc_greg_t;
B
blueswir1 已提交
1947 1948 1949
typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];

struct target_mc_fq {
1950
    abi_ulong *mcfq_addr;
B
blueswir1 已提交
1951 1952 1953 1954 1955 1956 1957 1958 1959
    uint32_t mcfq_insn;
};

struct target_mc_fpu {
    union {
        uint32_t sregs[32];
        uint64_t dregs[32];
        //uint128_t qregs[16];
    } mcfpu_fregs;
1960 1961 1962
    abi_ulong mcfpu_fsr;
    abi_ulong mcfpu_fprs;
    abi_ulong mcfpu_gsr;
B
blueswir1 已提交
1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978
    struct target_mc_fq *mcfpu_fq;
    unsigned char mcfpu_qcnt;
    unsigned char mcfpu_qentsz;
    unsigned char mcfpu_enab;
};
typedef struct target_mc_fpu target_mc_fpu_t;

typedef struct {
    target_mc_gregset_t mc_gregs;
    target_mc_greg_t mc_fp;
    target_mc_greg_t mc_i7;
    target_mc_fpu_t mc_fpregs;
} target_mcontext_t;

struct target_ucontext {
    struct target_ucontext *uc_link;
1979
    abi_ulong uc_flags;
B
blueswir1 已提交
1980 1981 1982 1983 1984 1985
    target_sigset_t uc_sigmask;
    target_mcontext_t uc_mcontext;
};

/* A V9 register window */
struct target_reg_window {
1986 1987
    abi_ulong locals[8];
    abi_ulong ins[8];
B
blueswir1 已提交
1988 1989 1990 1991 1992 1993 1994
};

#define TARGET_STACK_BIAS 2047

/* {set, get}context() needed for 64-bit SparcLinux userland. */
void sparc64_set_context(CPUSPARCState *env)
{
1995 1996
    abi_ulong ucp_addr;
    struct target_ucontext *ucp;
B
blueswir1 已提交
1997
    target_mc_gregset_t *grp;
1998
    abi_ulong pc, npc, tstate;
1999
    abi_ulong fp, i7, w_addr;
B
blueswir1 已提交
2000 2001 2002 2003
    unsigned char fenab;
    int err;
    unsigned int i;

2004 2005 2006
    ucp_addr = env->regwptr[UREG_I0];
    if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
        goto do_sigsegv;
B
blueswir1 已提交
2007
    grp  = &ucp->uc_mcontext.mc_gregs;
2008 2009
    err  = __get_user(pc, &((*grp)[MC_PC]));
    err |= __get_user(npc, &((*grp)[MC_NPC]));
B
blueswir1 已提交
2010 2011 2012 2013 2014 2015 2016
    if (err || ((pc | npc) & 3))
        goto do_sigsegv;
    if (env->regwptr[UREG_I1]) {
        target_sigset_t target_set;
        sigset_t set;

        if (TARGET_NSIG_WORDS == 1) {
2017
            if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
B
blueswir1 已提交
2018 2019
                goto do_sigsegv;
        } else {
2020 2021 2022
            abi_ulong *src, *dst;
            src = ucp->uc_sigmask.sig;
            dst = target_set.sig;
2023
            for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
B
blueswir1 已提交
2024
                 i++, dst++, src++)
2025
                err |= __get_user(*dst, src);
B
blueswir1 已提交
2026 2027 2028 2029 2030 2031 2032 2033
            if (err)
                goto do_sigsegv;
        }
        target_to_host_sigset_internal(&set, &target_set);
        sigprocmask(SIG_SETMASK, &set, NULL);
    }
    env->pc = pc;
    env->npc = npc;
2034 2035
    err |= __get_user(env->y, &((*grp)[MC_Y]));
    err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
B
blueswir1 已提交
2036 2037 2038
    env->asi = (tstate >> 24) & 0xff;
    PUT_CCR(env, tstate >> 32);
    PUT_CWP64(env, tstate & 0x1f);
2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057
    err |= __get_user(env->gregs[1], (&(*grp)[MC_G1]));
    err |= __get_user(env->gregs[2], (&(*grp)[MC_G2]));
    err |= __get_user(env->gregs[3], (&(*grp)[MC_G3]));
    err |= __get_user(env->gregs[4], (&(*grp)[MC_G4]));
    err |= __get_user(env->gregs[5], (&(*grp)[MC_G5]));
    err |= __get_user(env->gregs[6], (&(*grp)[MC_G6]));
    err |= __get_user(env->gregs[7], (&(*grp)[MC_G7]));
    err |= __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
    err |= __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
    err |= __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
    err |= __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
    err |= __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
    err |= __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
    err |= __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
    err |= __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));

    err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp));
    err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7));

2058 2059 2060 2061 2062 2063 2064
    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
    if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
                 abi_ulong) != 0)
        goto do_sigsegv;
    if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
                 abi_ulong) != 0)
        goto do_sigsegv;
2065 2066
    err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
    err |= __get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
2067 2068 2069 2070 2071 2072 2073 2074
    {
        uint32_t *src, *dst;
        src = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
        dst = env->fpr;
        /* XXX: check that the CPU storage is the same as user context */
        for (i = 0; i < 64; i++, dst++, src++)
            err |= __get_user(*dst, src);
    }
2075 2076 2077 2078
    err |= __get_user(env->fsr,
                      &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
    err |= __get_user(env->gsr,
                      &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
B
blueswir1 已提交
2079 2080
    if (err)
        goto do_sigsegv;
2081
    unlock_user_struct(ucp, ucp_addr, 0);
B
blueswir1 已提交
2082 2083
    return;
 do_sigsegv:
2084
    unlock_user_struct(ucp, ucp_addr, 0);
B
blueswir1 已提交
2085 2086 2087 2088 2089
    force_sig(SIGSEGV);
}

void sparc64_get_context(CPUSPARCState *env)
{
2090 2091
    abi_ulong ucp_addr;
    struct target_ucontext *ucp;
B
blueswir1 已提交
2092 2093
    target_mc_gregset_t *grp;
    target_mcontext_t *mcp;
2094
    abi_ulong fp, i7, w_addr;
B
blueswir1 已提交
2095 2096 2097 2098 2099
    int err;
    unsigned int i;
    target_sigset_t target_set;
    sigset_t set;

2100 2101 2102 2103
    ucp_addr = env->regwptr[UREG_I0];
    if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
        goto do_sigsegv;
    
B
blueswir1 已提交
2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114
    mcp = &ucp->uc_mcontext;
    grp = &mcp->mc_gregs;

    /* Skip over the trap instruction, first. */
    env->pc = env->npc;
    env->npc += 4;

    err = 0;

    sigprocmask(0, NULL, &set);
    host_to_target_sigset_internal(&target_set, &set);
2115
    if (TARGET_NSIG_WORDS == 1) {
2116 2117
        err |= __put_user(target_set.sig[0],
                          (abi_ulong *)&ucp->uc_sigmask);
2118 2119 2120 2121
    } else {
        abi_ulong *src, *dst;
        src = target_set.sig;
        dst = ucp->uc_sigmask.sig;
2122
        for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
B
blueswir1 已提交
2123
             i++, dst++, src++)
2124
            err |= __put_user(*src, dst);
B
blueswir1 已提交
2125 2126 2127 2128
        if (err)
            goto do_sigsegv;
    }

2129 2130
    /* XXX: tstate must be saved properly */
    //    err |= __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149
    err |= __put_user(env->pc, &((*grp)[MC_PC]));
    err |= __put_user(env->npc, &((*grp)[MC_NPC]));
    err |= __put_user(env->y, &((*grp)[MC_Y]));
    err |= __put_user(env->gregs[1], &((*grp)[MC_G1]));
    err |= __put_user(env->gregs[2], &((*grp)[MC_G2]));
    err |= __put_user(env->gregs[3], &((*grp)[MC_G3]));
    err |= __put_user(env->gregs[4], &((*grp)[MC_G4]));
    err |= __put_user(env->gregs[5], &((*grp)[MC_G5]));
    err |= __put_user(env->gregs[6], &((*grp)[MC_G6]));
    err |= __put_user(env->gregs[7], &((*grp)[MC_G7]));
    err |= __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
    err |= __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
    err |= __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
    err |= __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
    err |= __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
    err |= __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
    err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
    err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));

2150 2151 2152 2153 2154 2155 2156 2157
    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
    fp = i7 = 0;
    if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
                 abi_ulong) != 0)
        goto do_sigsegv;
    if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
                 abi_ulong) != 0)
        goto do_sigsegv;
2158 2159
    err |= __put_user(fp, &(mcp->mc_fp));
    err |= __put_user(i7, &(mcp->mc_i7));
B
blueswir1 已提交
2160

2161 2162 2163 2164 2165 2166 2167 2168
    {
        uint32_t *src, *dst;
        src = env->fpr;
        dst = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
        /* XXX: check that the CPU storage is the same as user context */
        for (i = 0; i < 64; i++, dst++, src++)
            err |= __put_user(*src, dst);
    }
2169 2170 2171
    err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
    err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
    err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
B
blueswir1 已提交
2172 2173 2174

    if (err)
        goto do_sigsegv;
2175
    unlock_user_struct(ucp, ucp_addr, 1);
B
blueswir1 已提交
2176 2177
    return;
 do_sigsegv:
2178
    unlock_user_struct(ucp, ucp_addr, 1);
B
blueswir1 已提交
2179 2180 2181
    force_sig(SIGSEGV);
}
#endif
2182
#elif defined(TARGET_ABI_MIPSN64)
2183 2184 2185

# warning signal handling not implemented

P
pbrook 已提交
2186
static void setup_frame(int sig, struct target_sigaction *ka,
2187 2188 2189 2190 2191
			target_sigset_t *set, CPUState *env)
{
    fprintf(stderr, "setup_frame: not implemented\n");
}

P
pbrook 已提交
2192
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2193 2194 2195 2196 2197 2198 2199 2200 2201
                           target_siginfo_t *info,
			   target_sigset_t *set, CPUState *env)
{
    fprintf(stderr, "setup_rt_frame: not implemented\n");
}

long do_sigreturn(CPUState *env)
{
    fprintf(stderr, "do_sigreturn: not implemented\n");
B
bellard 已提交
2202
    return -TARGET_ENOSYS;
2203 2204 2205 2206 2207
}

long do_rt_sigreturn(CPUState *env)
{
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
B
bellard 已提交
2208
    return -TARGET_ENOSYS;
2209 2210
}

2211
#elif defined(TARGET_ABI_MIPSN32)
2212 2213 2214

# warning signal handling not implemented

P
pbrook 已提交
2215
static void setup_frame(int sig, struct target_sigaction *ka,
2216 2217 2218 2219 2220
			target_sigset_t *set, CPUState *env)
{
    fprintf(stderr, "setup_frame: not implemented\n");
}

P
pbrook 已提交
2221
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2222 2223 2224 2225 2226 2227 2228 2229 2230
                           target_siginfo_t *info,
			   target_sigset_t *set, CPUState *env)
{
    fprintf(stderr, "setup_rt_frame: not implemented\n");
}

long do_sigreturn(CPUState *env)
{
    fprintf(stderr, "do_sigreturn: not implemented\n");
B
bellard 已提交
2231
    return -TARGET_ENOSYS;
2232 2233 2234 2235 2236
}

long do_rt_sigreturn(CPUState *env)
{
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
B
bellard 已提交
2237
    return -TARGET_ENOSYS;
2238 2239
}

2240
#elif defined(TARGET_ABI_MIPSO32)
2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292

struct target_sigcontext {
    uint32_t   sc_regmask;     /* Unused */
    uint32_t   sc_status;
    uint64_t   sc_pc;
    uint64_t   sc_regs[32];
    uint64_t   sc_fpregs[32];
    uint32_t   sc_ownedfp;     /* Unused */
    uint32_t   sc_fpc_csr;
    uint32_t   sc_fpc_eir;     /* Unused */
    uint32_t   sc_used_math;
    uint32_t   sc_dsp;         /* dsp status, was sc_ssflags */
    uint64_t   sc_mdhi;
    uint64_t   sc_mdlo;
    target_ulong   sc_hi1;         /* Was sc_cause */
    target_ulong   sc_lo1;         /* Was sc_badvaddr */
    target_ulong   sc_hi2;         /* Was sc_sigset[4] */
    target_ulong   sc_lo2;
    target_ulong   sc_hi3;
    target_ulong   sc_lo3;
};

struct sigframe {
    uint32_t sf_ass[4];			/* argument save space for o32 */
    uint32_t sf_code[2];			/* signal trampoline */
    struct target_sigcontext sf_sc;
    target_sigset_t sf_mask;
};

/* Install trampoline to jump back from signal handler */
static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
{
    int err;

    /*
    * Set up the return code ...
    *
    *         li      v0, __NR__foo_sigreturn
    *         syscall
    */

    err = __put_user(0x24020000 + syscall, tramp + 0);
    err |= __put_user(0x0000000c          , tramp + 1);
    /* flush_cache_sigtramp((unsigned long) tramp); */
    return err;
}

static inline int
setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
{
    int err = 0;

2293
    err |= __put_user(regs->PC[regs->current_tc], &sc->sc_pc);
2294

2295
#define save_gp_reg(i) do {   							\
2296
        err |= __put_user(regs->gpr[regs->current_tc][i], &sc->sc_regs[i]);	\
2297 2298 2299 2300 2301 2302 2303 2304 2305 2306
    } while(0)
    __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
    save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
    save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
    save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
    save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
    save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
    save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
    save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
    save_gp_reg(31);
T
ths 已提交
2307
#undef save_gp_reg
2308

2309 2310
    err |= __put_user(regs->HI[regs->current_tc][0], &sc->sc_mdhi);
    err |= __put_user(regs->LO[regs->current_tc][0], &sc->sc_mdlo);
2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323

    /* Not used yet, but might be useful if we ever have DSP suppport */
#if 0
    if (cpu_has_dsp) {
	err |= __put_user(mfhi1(), &sc->sc_hi1);
	err |= __put_user(mflo1(), &sc->sc_lo1);
	err |= __put_user(mfhi2(), &sc->sc_hi2);
	err |= __put_user(mflo2(), &sc->sc_lo2);
	err |= __put_user(mfhi3(), &sc->sc_hi3);
	err |= __put_user(mflo3(), &sc->sc_lo3);
	err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
    }
    /* same with 64 bit */
T
ths 已提交
2324
#ifdef CONFIG_64BIT
2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335
    err |= __put_user(regs->hi, &sc->sc_hi[0]);
    err |= __put_user(regs->lo, &sc->sc_lo[0]);
    if (cpu_has_dsp) {
	err |= __put_user(mfhi1(), &sc->sc_hi[1]);
	err |= __put_user(mflo1(), &sc->sc_lo[1]);
	err |= __put_user(mfhi2(), &sc->sc_hi[2]);
	err |= __put_user(mflo2(), &sc->sc_lo[2]);
	err |= __put_user(mfhi3(), &sc->sc_hi[3]);
	err |= __put_user(mflo3(), &sc->sc_lo[3]);
	err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
    }
T
ths 已提交
2336 2337
#endif
#endif
2338

T
ths 已提交
2339
#if 0
2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369
    err |= __put_user(!!used_math(), &sc->sc_used_math);

    if (!used_math())
	goto out;

    /*
    * Save FPU state to signal context.  Signal handler will "inherit"
    * current FPU state.
    */
    preempt_disable();

    if (!is_fpu_owner()) {
	own_fpu();
	restore_fp(current);
    }
    err |= save_fp_context(sc);

    preempt_enable();
    out:
#endif
    return err;
}

static inline int
restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
{
    int err = 0;

    err |= __get_user(regs->CP0_EPC, &sc->sc_pc);

2370 2371
    err |= __get_user(regs->HI[regs->current_tc][0], &sc->sc_mdhi);
    err |= __get_user(regs->LO[regs->current_tc][0], &sc->sc_mdlo);
2372

2373
#define restore_gp_reg(i) do {   							\
2374
        err |= __get_user(regs->gpr[regs->current_tc][i], &sc->sc_regs[i]);		\
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386
    } while(0)
    restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
    restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
    restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
    restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
    restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
    restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
    restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
    restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
    restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
    restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
    restore_gp_reg(31);
T
ths 已提交
2387
#undef restore_gp_reg
2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398

#if 0
    if (cpu_has_dsp) {
	err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
	err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
	err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
	err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
	err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
	err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
	err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
    }
T
ths 已提交
2399
#ifdef CONFIG_64BIT
2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
    err |= __get_user(regs->hi, &sc->sc_hi[0]);
    err |= __get_user(regs->lo, &sc->sc_lo[0]);
    if (cpu_has_dsp) {
	err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
	err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
	err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
	err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
	err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
	err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
	err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
    }
T
ths 已提交
2411
#endif
2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433

    err |= __get_user(used_math, &sc->sc_used_math);
    conditional_used_math(used_math);

    preempt_disable();

    if (used_math()) {
	/* restore fpu context if we have used it before */
	own_fpu();
	err |= restore_fp_context(sc);
    } else {
	/* signal handler may have used FPU.  Give it up. */
	lose_fpu();
    }

    preempt_enable();
#endif
    return err;
}
/*
 * Determine which stack to use..
 */
2434
static inline abi_ulong
P
pbrook 已提交
2435
get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
2436 2437 2438 2439
{
    unsigned long sp;

    /* Default to using normal stack */
2440
    sp = regs->gpr[regs->current_tc][29];
2441 2442 2443 2444 2445 2446 2447 2448 2449

    /*
     * FPU emulator may have it's own trampoline active just
     * above the user stack, 16-bytes before the next lowest
     * 16 byte boundary.  Try to avoid trashing it.
     */
    sp -= 32;

    /* This is the X/Open sanctioned signal stack switching.  */
P
pbrook 已提交
2450
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
2451 2452
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
    }
2453

2454
    return (sp - frame_size) & ~7;
2455 2456
}

2457
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
P
pbrook 已提交
2458
static void setup_frame(int sig, struct target_sigaction * ka,
2459
                        target_sigset_t *set, CPUState *regs)
2460 2461
{
    struct sigframe *frame;
2462
    abi_ulong frame_addr;
2463 2464
    int i;

2465 2466
    frame_addr = get_sigframe(ka, regs, sizeof(*frame));
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488
	goto give_sigsegv;

    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);

    if(setup_sigcontext(regs, &frame->sf_sc))
	goto give_sigsegv;

    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
	if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))
	    goto give_sigsegv;
    }

    /*
    * Arguments to signal handler:
    *
    *   a0 = signal number
    *   a1 = 0 (should be cause)
    *   a2 = pointer to struct sigcontext
    *
    * $25 and PC point to the signal handler, $29 points to the
    * struct sigframe.
    */
2489 2490 2491 2492 2493
    regs->gpr[regs->current_tc][ 4] = sig;
    regs->gpr[regs->current_tc][ 5] = 0;
    regs->gpr[regs->current_tc][ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
    regs->gpr[regs->current_tc][29] = frame_addr;
    regs->gpr[regs->current_tc][31] = frame_addr + offsetof(struct sigframe, sf_code);
2494 2495 2496
    /* The original kernel code sets CP0_EPC to the handler
    * since it returns to userland using eret
    * we cannot do this here, and we must set PC directly */
P
pbrook 已提交
2497
    regs->PC[regs->current_tc] = regs->gpr[regs->current_tc][25] = ka->_sa_handler;
2498
    unlock_user_struct(frame, frame_addr, 1);
2499 2500 2501
    return;

give_sigsegv:
2502
    unlock_user_struct(frame, frame_addr, 1);
2503
    force_sig(TARGET_SIGSEGV/*, current*/);
2504
    return;
2505 2506 2507 2508
}

long do_sigreturn(CPUState *regs)
{
T
ths 已提交
2509
    struct sigframe *frame;
2510
    abi_ulong frame_addr;
T
ths 已提交
2511 2512 2513
    sigset_t blocked;
    target_sigset_t target_set;
    int i;
2514 2515

#if defined(DEBUG_SIGNAL)
T
ths 已提交
2516
    fprintf(stderr, "do_sigreturn\n");
2517
#endif
2518
    frame_addr = regs->gpr[regs->current_tc][29];
2519
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2520 2521
   	goto badframe;

T
ths 已提交
2522
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2523 2524
   	if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
	    goto badframe;
T
ths 已提交
2525
    }
2526

T
ths 已提交
2527 2528
    target_to_host_sigset_internal(&blocked, &target_set);
    sigprocmask(SIG_SETMASK, &blocked, NULL);
2529

T
ths 已提交
2530
    if (restore_sigcontext(regs, &frame->sf_sc))
2531 2532 2533
   	goto badframe;

#if 0
T
ths 已提交
2534 2535 2536 2537
    /*
     * Don't let your children do this ...
     */
    __asm__ __volatile__(
2538 2539 2540 2541
   	"move\t$29, %0\n\t"
   	"j\tsyscall_exit"
   	:/* no outputs */
   	:"r" (&regs));
T
ths 已提交
2542
    /* Unreached */
2543
#endif
2544

2545
    regs->PC[regs->current_tc] = regs->CP0_EPC;
T
ths 已提交
2546
    /* I am not sure this is right, but it seems to work
2547 2548 2549 2550 2551
    * maybe a problem with nested signals ? */
    regs->CP0_EPC = 0;
    return 0;

badframe:
T
ths 已提交
2552 2553
    force_sig(TARGET_SIGSEGV/*, current*/);
    return 0;
2554 2555
}

P
pbrook 已提交
2556
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2557 2558 2559 2560 2561 2562 2563 2564 2565
                           target_siginfo_t *info,
			   target_sigset_t *set, CPUState *env)
{
    fprintf(stderr, "setup_rt_frame: not implemented\n");
}

long do_rt_sigreturn(CPUState *env)
{
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
B
bellard 已提交
2566
    return -TARGET_ENOSYS;
2567
}
B
bellard 已提交
2568

2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623
#elif defined(TARGET_SH4)

/*
 * code and data structures from linux kernel:
 * include/asm-sh/sigcontext.h
 * arch/sh/kernel/signal.c
 */

struct target_sigcontext {
    target_ulong  oldmask;

    /* CPU registers */
    target_ulong  sc_gregs[16];
    target_ulong  sc_pc;
    target_ulong  sc_pr;
    target_ulong  sc_sr;
    target_ulong  sc_gbr;
    target_ulong  sc_mach;
    target_ulong  sc_macl;

    /* FPU registers */
    target_ulong  sc_fpregs[16];
    target_ulong  sc_xfpregs[16];
    unsigned int sc_fpscr;
    unsigned int sc_fpul;
    unsigned int sc_ownedfp;
};

struct target_sigframe
{
    struct target_sigcontext sc;
    target_ulong extramask[TARGET_NSIG_WORDS-1];
    uint16_t retcode[3];
};


struct target_ucontext {
    target_ulong uc_flags;
    struct target_ucontext *uc_link;
    target_stack_t uc_stack;
    struct target_sigcontext uc_mcontext;
    target_sigset_t uc_sigmask;	/* mask last for extensibility */
};

struct target_rt_sigframe
{
    struct target_siginfo info;
    struct target_ucontext uc;
    uint16_t retcode[3];
};


#define MOVW(n)  (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
#define TRAP_NOARG 0xc310         /* Syscall w/no args (NR in R3) SH3/4 */

P
pbrook 已提交
2624
static abi_ulong get_sigframe(struct target_sigaction *ka,
2625 2626
                         unsigned long sp, size_t frame_size)
{
P
pbrook 已提交
2627
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
    }

    return (sp - frame_size) & -8ul;
}

static int setup_sigcontext(struct target_sigcontext *sc,
			    CPUState *regs, unsigned long mask)
{
    int err = 0;

#define COPY(x)         err |= __put_user(regs->x, &sc->sc_##x)
    COPY(gregs[0]); COPY(gregs[1]);
    COPY(gregs[2]); COPY(gregs[3]);
    COPY(gregs[4]); COPY(gregs[5]);
    COPY(gregs[6]); COPY(gregs[7]);
    COPY(gregs[8]); COPY(gregs[9]);
    COPY(gregs[10]); COPY(gregs[11]);
    COPY(gregs[12]); COPY(gregs[13]);
    COPY(gregs[14]); COPY(gregs[15]);
    COPY(gbr); COPY(mach);
    COPY(macl); COPY(pr);
    COPY(sr); COPY(pc);
#undef COPY

    /* todo: save FPU registers here */

    /* non-iBCS2 extensions.. */
    err |= __put_user(mask, &sc->oldmask);

    return err;
}

static int restore_sigcontext(struct CPUState *regs,
			      struct target_sigcontext *sc)
{
    unsigned int err = 0;

#define COPY(x)         err |= __get_user(regs->x, &sc->sc_##x)
    COPY(gregs[1]);
    COPY(gregs[2]); COPY(gregs[3]);
    COPY(gregs[4]); COPY(gregs[5]);
    COPY(gregs[6]); COPY(gregs[7]);
    COPY(gregs[8]); COPY(gregs[9]);
    COPY(gregs[10]); COPY(gregs[11]);
    COPY(gregs[12]); COPY(gregs[13]);
    COPY(gregs[14]); COPY(gregs[15]);
    COPY(gbr); COPY(mach);
    COPY(macl); COPY(pr);
    COPY(sr); COPY(pc);
#undef COPY

    /* todo: restore FPU registers here */

    regs->tra = -1;         /* disable syscall checks */
    return err;
}

P
pbrook 已提交
2686
static void setup_frame(int sig, struct target_sigaction *ka,
2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708
			target_sigset_t *set, CPUState *regs)
{
    struct target_sigframe *frame;
    abi_ulong frame_addr;
    int i;
    int err = 0;
    int signal;

    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
	goto give_sigsegv;

    signal = current_exec_domain_sig(sig);

    err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);

    for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
        err |= __put_user(set->sig[i + 1], &frame->extramask[i]);
    }

    /* Set up to return from userspace.  If provided, use a stub
       already in userspace.  */
P
pbrook 已提交
2709 2710
    if (ka->sa_flags & TARGET_SA_RESTORER) {
        regs->pr = (unsigned long) ka->sa_restorer;
2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726
    } else {
        /* Generate return code (system call to sigreturn) */
        err |= __put_user(MOVW(2), &frame->retcode[0]);
        err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
        err |= __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
        regs->pr = (unsigned long) frame->retcode;
    }

    if (err)
        goto give_sigsegv;

    /* Set up registers for signal handler */
    regs->gregs[15] = (unsigned long) frame;
    regs->gregs[4] = signal; /* Arg for signal handler */
    regs->gregs[5] = 0;
    regs->gregs[6] = (unsigned long) &frame->sc;
P
pbrook 已提交
2727
    regs->pc = (unsigned long) ka->_sa_handler;
2728 2729 2730 2731 2732 2733 2734 2735 2736

    unlock_user_struct(frame, frame_addr, 1);
    return;

give_sigsegv:
    unlock_user_struct(frame, frame_addr, 1);
    force_sig(SIGSEGV);
}

P
pbrook 已提交
2737
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771
                           target_siginfo_t *info,
			   target_sigset_t *set, CPUState *regs)
{
    struct target_rt_sigframe *frame;
    abi_ulong frame_addr;
    int i;
    int err = 0;
    int signal;

    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
	goto give_sigsegv;

    signal = current_exec_domain_sig(sig);

    err |= copy_siginfo_to_user(&frame->info, info);

    /* Create the ucontext.  */
    err |= __put_user(0, &frame->uc.uc_flags);
    err |= __put_user(0, (unsigned long *)&frame->uc.uc_link);
    err |= __put_user((void *)target_sigaltstack_used.ss_sp,
		      &frame->uc.uc_stack.ss_sp);
    err |= __put_user(sas_ss_flags(regs->gregs[15]),
		      &frame->uc.uc_stack.ss_flags);
    err |= __put_user(target_sigaltstack_used.ss_size,
		      &frame->uc.uc_stack.ss_size);
    err |= setup_sigcontext(&frame->uc.uc_mcontext,
			    regs, set->sig[0]);
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
        err |= __put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]);
    }

    /* Set up to return from userspace.  If provided, use a stub
       already in userspace.  */
P
pbrook 已提交
2772 2773
    if (ka->sa_flags & TARGET_SA_RESTORER) {
        regs->pr = (unsigned long) ka->sa_restorer;
2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789
    } else {
        /* Generate return code (system call to sigreturn) */
        err |= __put_user(MOVW(2), &frame->retcode[0]);
        err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
        err |= __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
        regs->pr = (unsigned long) frame->retcode;
    }

    if (err)
        goto give_sigsegv;

    /* Set up registers for signal handler */
    regs->gregs[15] = (unsigned long) frame;
    regs->gregs[4] = signal; /* Arg for signal handler */
    regs->gregs[5] = (unsigned long) &frame->info;
    regs->gregs[6] = (unsigned long) &frame->uc;
P
pbrook 已提交
2790
    regs->pc = (unsigned long) ka->_sa_handler;
2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870

    unlock_user_struct(frame, frame_addr, 1);
    return;

give_sigsegv:
    unlock_user_struct(frame, frame_addr, 1);
    force_sig(SIGSEGV);
}

long do_sigreturn(CPUState *regs)
{
    struct target_sigframe *frame;
    abi_ulong frame_addr;
    sigset_t blocked;
    target_sigset_t target_set;
    int i;
    int err = 0;

#if defined(DEBUG_SIGNAL)
    fprintf(stderr, "do_sigreturn\n");
#endif
    frame_addr = regs->gregs[15];
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
   	goto badframe;

    err |= __get_user(target_set.sig[0], &frame->sc.oldmask);
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
        err |= (__get_user(target_set.sig[i], &frame->extramask[i - 1]));
    }

    if (err)
        goto badframe;

    target_to_host_sigset_internal(&blocked, &target_set);
    sigprocmask(SIG_SETMASK, &blocked, NULL);

    if (restore_sigcontext(regs, &frame->sc))
        goto badframe;

    unlock_user_struct(frame, frame_addr, 0);
    return regs->gregs[0];

badframe:
    unlock_user_struct(frame, frame_addr, 0);
    force_sig(TARGET_SIGSEGV);
    return 0;
}

long do_rt_sigreturn(CPUState *regs)
{
    struct target_rt_sigframe *frame;
    abi_ulong frame_addr;
    sigset_t blocked;

#if defined(DEBUG_SIGNAL)
    fprintf(stderr, "do_rt_sigreturn\n");
#endif
    frame_addr = regs->gregs[15];
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
   	goto badframe;

    target_to_host_sigset(&blocked, &frame->uc.uc_sigmask);
    sigprocmask(SIG_SETMASK, &blocked, NULL);

    if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
        goto badframe;

    if (do_sigaltstack(frame_addr +
		       offsetof(struct target_rt_sigframe, uc.uc_stack),
		       0, get_sp_from_cpustate(regs)) == -EFAULT)
        goto badframe;

    unlock_user_struct(frame, frame_addr, 0);
    return regs->gregs[0];

badframe:
    unlock_user_struct(frame, frame_addr, 0);
    force_sig(TARGET_SIGSEGV);
    return 0;
}
2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895
#elif defined(TARGET_CRIS)

struct target_sigcontext {
        struct target_pt_regs regs;  /* needs to be first */
        uint32_t oldmask;
        uint32_t usp;    /* usp before stacking this gunk on it */
};

/* Signal frames. */
struct target_signal_frame {
        struct target_sigcontext sc;
        uint32_t extramask[TARGET_NSIG_WORDS - 1];
        uint8_t retcode[8];       /* Trampoline code. */
};

struct rt_signal_frame {
        struct siginfo *pinfo;
        void *puc;
        struct siginfo info;
        struct ucontext uc;
        uint8_t retcode[8];       /* Trampoline code. */
};

static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
{
E
edgar_igl 已提交
2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914
	__put_user(env->regs[0], &sc->regs.r0);
	__put_user(env->regs[1], &sc->regs.r1);
	__put_user(env->regs[2], &sc->regs.r2);
	__put_user(env->regs[3], &sc->regs.r3);
	__put_user(env->regs[4], &sc->regs.r4);
	__put_user(env->regs[5], &sc->regs.r5);
	__put_user(env->regs[6], &sc->regs.r6);
	__put_user(env->regs[7], &sc->regs.r7);
	__put_user(env->regs[8], &sc->regs.r8);
	__put_user(env->regs[9], &sc->regs.r9);
	__put_user(env->regs[10], &sc->regs.r10);
	__put_user(env->regs[11], &sc->regs.r11);
	__put_user(env->regs[12], &sc->regs.r12);
	__put_user(env->regs[13], &sc->regs.r13);
	__put_user(env->regs[14], &sc->usp);
	__put_user(env->regs[15], &sc->regs.acr);
	__put_user(env->pregs[PR_MOF], &sc->regs.mof);
	__put_user(env->pregs[PR_SRP], &sc->regs.srp);
	__put_user(env->pc, &sc->regs.erp);
2915
}
E
edgar_igl 已提交
2916

2917 2918
static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
{
E
edgar_igl 已提交
2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942
	__get_user(env->regs[0], &sc->regs.r0);
	__get_user(env->regs[1], &sc->regs.r1);
	__get_user(env->regs[2], &sc->regs.r2);
	__get_user(env->regs[3], &sc->regs.r3);
	__get_user(env->regs[4], &sc->regs.r4);
	__get_user(env->regs[5], &sc->regs.r5);
	__get_user(env->regs[6], &sc->regs.r6);
	__get_user(env->regs[7], &sc->regs.r7);
	__get_user(env->regs[8], &sc->regs.r8);
	__get_user(env->regs[9], &sc->regs.r9);
	__get_user(env->regs[10], &sc->regs.r10);
	__get_user(env->regs[11], &sc->regs.r11);
	__get_user(env->regs[12], &sc->regs.r12);
	__get_user(env->regs[13], &sc->regs.r13);
	__get_user(env->regs[14], &sc->usp);
	__get_user(env->regs[15], &sc->regs.acr);
	__get_user(env->pregs[PR_MOF], &sc->regs.mof);
	__get_user(env->pregs[PR_SRP], &sc->regs.srp);
	__get_user(env->pc, &sc->regs.erp);
}

static abi_ulong get_sigframe(CPUState *env, int framesize)
{
	abi_ulong sp;
2943
	/* Align the stack downwards to 4.  */
E
edgar_igl 已提交
2944 2945
	sp = (env->regs[R_SP] & ~3);
	return sp - framesize;
2946 2947
}

P
pbrook 已提交
2948
static void setup_frame(int sig, struct target_sigaction *ka,
2949 2950 2951
			target_sigset_t *set, CPUState *env)
{
	struct target_signal_frame *frame;
E
edgar_igl 已提交
2952
	abi_ulong frame_addr;
2953 2954 2955
	int err = 0;
	int i;

E
edgar_igl 已提交
2956 2957
	frame_addr = get_sigframe(env, sizeof *frame);
	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
		goto badframe;

	/*
	 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
	 * use this trampoline anymore but it sets it up for GDB.
	 * In QEMU, using the trampoline simplifies things a bit so we use it.
	 *
	 * This is movu.w __NR_sigreturn, r9; break 13;
	 */
	err |= __put_user(0x9c5f, frame->retcode+0);
	err |= __put_user(TARGET_NR_sigreturn, 
			  frame->retcode+2);
	err |= __put_user(0xe93d, frame->retcode+4);

	/* Save the mask.  */
	err |= __put_user(set->sig[0], &frame->sc.oldmask);
	if (err)
		goto badframe;

	for(i = 1; i < TARGET_NSIG_WORDS; i++) {
		if (__put_user(set->sig[i], &frame->extramask[i - 1]))
			goto badframe;
	}

	setup_sigcontext(&frame->sc, env);

	/* Move the stack and setup the arguments for the handler.  */
	env->regs[R_SP] = (uint32_t) frame;
	env->regs[10] = sig;
P
pbrook 已提交
2987
	env->pc = (unsigned long) ka->_sa_handler;
2988 2989 2990
	/* Link SRP so the guest returns through the trampoline.  */
	env->pregs[PR_SRP] = (uint32_t) &frame->retcode[0];

E
edgar_igl 已提交
2991
	unlock_user_struct(frame, frame_addr, 1);
2992 2993
	return;
  badframe:
E
edgar_igl 已提交
2994
	unlock_user_struct(frame, frame_addr, 1);
2995 2996 2997
	force_sig(TARGET_SIGSEGV);
}

P
pbrook 已提交
2998
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2999 3000 3001 3002 3003 3004 3005 3006 3007
                           target_siginfo_t *info,
			   target_sigset_t *set, CPUState *env)
{
    fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
}

long do_sigreturn(CPUState *env)
{
	struct target_signal_frame *frame;
E
edgar_igl 已提交
3008
	abi_ulong frame_addr;
3009 3010 3011 3012
	target_sigset_t target_set;
	sigset_t set;
	int i;

E
edgar_igl 已提交
3013
	frame_addr = env->regs[R_SP];
3014
	/* Make sure the guest isn't playing games.  */
E
edgar_igl 已提交
3015
	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028
		goto badframe;

	/* Restore blocked signals */
	if (__get_user(target_set.sig[0], &frame->sc.oldmask))
		goto badframe;
	for(i = 1; i < TARGET_NSIG_WORDS; i++) {
		if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
			goto badframe;
	}
	target_to_host_sigset_internal(&set, &target_set);
	sigprocmask(SIG_SETMASK, &set, NULL);

	restore_sigcontext(&frame->sc, env);
E
edgar_igl 已提交
3029 3030
	/* Compensate for the syscall return path advancing brk.  */
	env->pc -= 2;
3031

E
edgar_igl 已提交
3032
	unlock_user_struct(frame, frame_addr, 0);
3033 3034
	return env->regs[10];
  badframe:
E
edgar_igl 已提交
3035
	unlock_user_struct(frame, frame_addr, 0);
3036 3037 3038 3039 3040 3041 3042 3043
	force_sig(TARGET_SIGSEGV);
}

long do_rt_sigreturn(CPUState *env)
{
    fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
    return -TARGET_ENOSYS;
}
3044

B
bellard 已提交
3045 3046
#else

P
pbrook 已提交
3047
static void setup_frame(int sig, struct target_sigaction *ka,
B
bellard 已提交
3048 3049 3050 3051 3052
			target_sigset_t *set, CPUState *env)
{
    fprintf(stderr, "setup_frame: not implemented\n");
}

P
pbrook 已提交
3053
static void setup_rt_frame(int sig, struct target_sigaction *ka,
B
bellard 已提交
3054 3055 3056 3057 3058 3059 3060 3061 3062
                           target_siginfo_t *info,
			   target_sigset_t *set, CPUState *env)
{
    fprintf(stderr, "setup_rt_frame: not implemented\n");
}

long do_sigreturn(CPUState *env)
{
    fprintf(stderr, "do_sigreturn: not implemented\n");
B
bellard 已提交
3063
    return -TARGET_ENOSYS;
B
bellard 已提交
3064 3065 3066 3067 3068
}

long do_rt_sigreturn(CPUState *env)
{
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
B
bellard 已提交
3069
    return -TARGET_ENOSYS;
B
bellard 已提交
3070 3071
}

B
bellard 已提交
3072 3073
#endif

P
pbrook 已提交
3074
void process_pending_signals(CPUState *cpu_env)
B
bellard 已提交
3075 3076
{
    int sig;
3077
    abi_ulong handler;
B
bellard 已提交
3078 3079
    sigset_t set, old_set;
    target_sigset_t target_old_set;
P
pbrook 已提交
3080 3081
    struct emulated_sigtable *k;
    struct target_sigaction *sa;
B
bellard 已提交
3082
    struct sigqueue *q;
P
pbrook 已提交
3083
    TaskState *ts = cpu_env->opaque;
3084

P
pbrook 已提交
3085
    if (!ts->signal_pending)
3086 3087
        return;

P
pbrook 已提交
3088 3089
    /* FIXME: This is not threadsafe.  */
    k = ts->sigtab;
B
bellard 已提交
3090 3091
    for(sig = 1; sig <= TARGET_NSIG; sig++) {
        if (k->pending)
3092
            goto handle_signal;
B
bellard 已提交
3093
        k++;
3094 3095
    }
    /* if no signal is pending, just return */
P
pbrook 已提交
3096
    ts->signal_pending = 0;
3097
    return;
B
bellard 已提交
3098

3099
 handle_signal:
B
bellard 已提交
3100
#ifdef DEBUG_SIGNAL
B
bellard 已提交
3101
    fprintf(stderr, "qemu: process signal %d\n", sig);
B
bellard 已提交
3102 3103 3104 3105 3106 3107
#endif
    /* dequeue signal */
    q = k->first;
    k->first = q->next;
    if (!k->first)
        k->pending = 0;
3108

B
bellard 已提交
3109 3110 3111 3112 3113
    sig = gdb_handlesig (cpu_env, sig);
    if (!sig) {
        fprintf (stderr, "Lost signal\n");
        abort();
    }
B
bellard 已提交
3114

P
pbrook 已提交
3115 3116
    sa = &sigact_table[sig - 1];
    handler = sa->_sa_handler;
B
bellard 已提交
3117 3118
    if (handler == TARGET_SIG_DFL) {
        /* default handler : ignore some signal. The other are fatal */
3119 3120
        if (sig != TARGET_SIGCHLD &&
            sig != TARGET_SIGURG &&
B
bellard 已提交
3121 3122 3123 3124 3125 3126 3127 3128
            sig != TARGET_SIGWINCH) {
            force_sig(sig);
        }
    } else if (handler == TARGET_SIG_IGN) {
        /* ignore sig */
    } else if (handler == TARGET_SIG_ERR) {
        force_sig(sig);
    } else {
B
bellard 已提交
3129
        /* compute the blocked signals during the handler execution */
P
pbrook 已提交
3130
        target_to_host_sigset(&set, &sa->sa_mask);
B
bellard 已提交
3131 3132
        /* SA_NODEFER indicates that the current signal should not be
           blocked during the handler */
P
pbrook 已提交
3133
        if (!(sa->sa_flags & TARGET_SA_NODEFER))
B
bellard 已提交
3134
            sigaddset(&set, target_to_host_signal(sig));
3135

B
bellard 已提交
3136 3137 3138 3139
        /* block signals in the handler using Linux */
        sigprocmask(SIG_BLOCK, &set, &old_set);
        /* save the previous blocked signal state to restore it at the
           end of the signal execution (see do_sigreturn) */
3140
        host_to_target_sigset_internal(&target_old_set, &old_set);
B
bellard 已提交
3141

B
bellard 已提交
3142
        /* if the CPU is in VM86 mode, we restore the 32 bit values */
3143
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
B
bellard 已提交
3144 3145 3146 3147 3148 3149
        {
            CPUX86State *env = cpu_env;
            if (env->eflags & VM_MASK)
                save_v86_state(env);
        }
#endif
B
bellard 已提交
3150
        /* prepare the stack frame of the virtual CPU */
P
pbrook 已提交
3151 3152
        if (sa->sa_flags & TARGET_SA_SIGINFO)
            setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
B
bellard 已提交
3153
        else
P
pbrook 已提交
3154 3155 3156
            setup_frame(sig, sa, &target_old_set, cpu_env);
	if (sa->sa_flags & TARGET_SA_RESETHAND)
            sa->_sa_handler = TARGET_SIG_DFL;
3157
    }
B
bellard 已提交
3158
    if (q != &k->info)
P
pbrook 已提交
3159
        free_sigqueue(cpu_env, q);
B
bellard 已提交
3160
}