Statistics
| Branch: | Revision:

root / linux-user / signal.c @ 3ca05588

History | View | Annotate | Download (131.5 kB)

1 31e31b8a bellard
/*
2 66fb9763 bellard
 *  Emulation of Linux signals
3 5fafdf24 ths
 *
4 31e31b8a bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 31e31b8a bellard
 *
6 31e31b8a bellard
 *  This program is free software; you can redistribute it and/or modify
7 31e31b8a bellard
 *  it under the terms of the GNU General Public License as published by
8 31e31b8a bellard
 *  the Free Software Foundation; either version 2 of the License, or
9 31e31b8a bellard
 *  (at your option) any later version.
10 31e31b8a bellard
 *
11 31e31b8a bellard
 *  This program is distributed in the hope that it will be useful,
12 31e31b8a bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 31e31b8a bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 31e31b8a bellard
 *  GNU General Public License for more details.
15 31e31b8a bellard
 *
16 31e31b8a bellard
 *  You should have received a copy of the GNU General Public License
17 8167ee88 Blue Swirl
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18 31e31b8a bellard
 */
19 31e31b8a bellard
#include <stdlib.h>
20 31e31b8a bellard
#include <stdio.h>
21 66fb9763 bellard
#include <string.h>
22 31e31b8a bellard
#include <stdarg.h>
23 2677e107 bellard
#include <unistd.h>
24 31e31b8a bellard
#include <signal.h>
25 66fb9763 bellard
#include <errno.h>
26 603e4fd7 aurel32
#include <assert.h>
27 31e31b8a bellard
#include <sys/ucontext.h>
28 edf8e2af Mika Westerberg
#include <sys/resource.h>
29 31e31b8a bellard
30 3ef693a0 bellard
#include "qemu.h"
31 7d99a001 blueswir1
#include "qemu-common.h"
32 992f48a0 blueswir1
#include "target_signal.h"
33 66fb9763 bellard
34 66fb9763 bellard
//#define DEBUG_SIGNAL
35 66fb9763 bellard
36 249c4c32 blueswir1
static struct target_sigaltstack target_sigaltstack_used = {
37 a04e134a ths
    .ss_sp = 0,
38 a04e134a ths
    .ss_size = 0,
39 a04e134a ths
    .ss_flags = TARGET_SS_DISABLE,
40 a04e134a ths
};
41 a04e134a ths
42 624f7979 pbrook
static struct target_sigaction sigact_table[TARGET_NSIG];
43 31e31b8a bellard
44 5fafdf24 ths
static void host_signal_handler(int host_signum, siginfo_t *info,
45 66fb9763 bellard
                                void *puc);
46 66fb9763 bellard
47 3ca05588 Arnaud Patard
static uint8_t host_to_target_signal_table[_NSIG] = {
48 9e5f5284 bellard
    [SIGHUP] = TARGET_SIGHUP,
49 9e5f5284 bellard
    [SIGINT] = TARGET_SIGINT,
50 9e5f5284 bellard
    [SIGQUIT] = TARGET_SIGQUIT,
51 9e5f5284 bellard
    [SIGILL] = TARGET_SIGILL,
52 9e5f5284 bellard
    [SIGTRAP] = TARGET_SIGTRAP,
53 9e5f5284 bellard
    [SIGABRT] = TARGET_SIGABRT,
54 01e3b763 bellard
/*    [SIGIOT] = TARGET_SIGIOT,*/
55 9e5f5284 bellard
    [SIGBUS] = TARGET_SIGBUS,
56 9e5f5284 bellard
    [SIGFPE] = TARGET_SIGFPE,
57 9e5f5284 bellard
    [SIGKILL] = TARGET_SIGKILL,
58 9e5f5284 bellard
    [SIGUSR1] = TARGET_SIGUSR1,
59 9e5f5284 bellard
    [SIGSEGV] = TARGET_SIGSEGV,
60 9e5f5284 bellard
    [SIGUSR2] = TARGET_SIGUSR2,
61 9e5f5284 bellard
    [SIGPIPE] = TARGET_SIGPIPE,
62 9e5f5284 bellard
    [SIGALRM] = TARGET_SIGALRM,
63 9e5f5284 bellard
    [SIGTERM] = TARGET_SIGTERM,
64 9e5f5284 bellard
#ifdef SIGSTKFLT
65 9e5f5284 bellard
    [SIGSTKFLT] = TARGET_SIGSTKFLT,
66 9e5f5284 bellard
#endif
67 9e5f5284 bellard
    [SIGCHLD] = TARGET_SIGCHLD,
68 9e5f5284 bellard
    [SIGCONT] = TARGET_SIGCONT,
69 9e5f5284 bellard
    [SIGSTOP] = TARGET_SIGSTOP,
70 9e5f5284 bellard
    [SIGTSTP] = TARGET_SIGTSTP,
71 9e5f5284 bellard
    [SIGTTIN] = TARGET_SIGTTIN,
72 9e5f5284 bellard
    [SIGTTOU] = TARGET_SIGTTOU,
73 9e5f5284 bellard
    [SIGURG] = TARGET_SIGURG,
74 9e5f5284 bellard
    [SIGXCPU] = TARGET_SIGXCPU,
75 9e5f5284 bellard
    [SIGXFSZ] = TARGET_SIGXFSZ,
76 9e5f5284 bellard
    [SIGVTALRM] = TARGET_SIGVTALRM,
77 9e5f5284 bellard
    [SIGPROF] = TARGET_SIGPROF,
78 9e5f5284 bellard
    [SIGWINCH] = TARGET_SIGWINCH,
79 9e5f5284 bellard
    [SIGIO] = TARGET_SIGIO,
80 9e5f5284 bellard
    [SIGPWR] = TARGET_SIGPWR,
81 9e5f5284 bellard
    [SIGSYS] = TARGET_SIGSYS,
82 9e5f5284 bellard
    /* next signals stay the same */
83 624f7979 pbrook
    /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
84 624f7979 pbrook
       host libpthread signals.  This assumes noone actually uses SIGRTMAX :-/
85 624f7979 pbrook
       To fix this properly we need to do manual signal delivery multiplexed
86 624f7979 pbrook
       over a single host signal.  */
87 624f7979 pbrook
    [__SIGRTMIN] = __SIGRTMAX,
88 624f7979 pbrook
    [__SIGRTMAX] = __SIGRTMIN,
89 9e5f5284 bellard
};
90 3ca05588 Arnaud Patard
static uint8_t target_to_host_signal_table[_NSIG];
91 9e5f5284 bellard
92 a04e134a ths
static inline int on_sig_stack(unsigned long sp)
93 a04e134a ths
{
94 a04e134a ths
    return (sp - target_sigaltstack_used.ss_sp
95 a04e134a ths
            < target_sigaltstack_used.ss_size);
96 a04e134a ths
}
97 a04e134a ths
98 a04e134a ths
static inline int sas_ss_flags(unsigned long sp)
99 a04e134a ths
{
100 a04e134a ths
    return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
101 a04e134a ths
            : on_sig_stack(sp) ? SS_ONSTACK : 0);
102 a04e134a ths
}
103 a04e134a ths
104 1d9d8b55 pbrook
int host_to_target_signal(int sig)
105 31e31b8a bellard
{
106 3ca05588 Arnaud Patard
    if (sig >= _NSIG)
107 4cb05961 pbrook
        return sig;
108 9e5f5284 bellard
    return host_to_target_signal_table[sig];
109 31e31b8a bellard
}
110 31e31b8a bellard
111 4cb05961 pbrook
int target_to_host_signal(int sig)
112 31e31b8a bellard
{
113 3ca05588 Arnaud Patard
    if (sig >= _NSIG)
114 4cb05961 pbrook
        return sig;
115 9e5f5284 bellard
    return target_to_host_signal_table[sig];
116 31e31b8a bellard
}
117 31e31b8a bellard
118 c227f099 Anthony Liguori
static inline void target_sigemptyset(target_sigset_t *set)
119 f5545b5c pbrook
{
120 f5545b5c pbrook
    memset(set, 0, sizeof(*set));
121 f5545b5c pbrook
}
122 f5545b5c pbrook
123 c227f099 Anthony Liguori
static inline void target_sigaddset(target_sigset_t *set, int signum)
124 f5545b5c pbrook
{
125 f5545b5c pbrook
    signum--;
126 f5545b5c pbrook
    abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
127 f5545b5c pbrook
    set->sig[signum / TARGET_NSIG_BPW] |= mask;
128 f5545b5c pbrook
}
129 f5545b5c pbrook
130 c227f099 Anthony Liguori
static inline int target_sigismember(const target_sigset_t *set, int signum)
131 f5545b5c pbrook
{
132 f5545b5c pbrook
    signum--;
133 f5545b5c pbrook
    abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
134 f5545b5c pbrook
    return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
135 f5545b5c pbrook
}
136 f5545b5c pbrook
137 c227f099 Anthony Liguori
static void host_to_target_sigset_internal(target_sigset_t *d,
138 9231944d bellard
                                           const sigset_t *s)
139 66fb9763 bellard
{
140 66fb9763 bellard
    int i;
141 f5545b5c pbrook
    target_sigemptyset(d);
142 f5545b5c pbrook
    for (i = 1; i <= TARGET_NSIG; i++) {
143 f5545b5c pbrook
        if (sigismember(s, i)) {
144 f5545b5c pbrook
            target_sigaddset(d, host_to_target_signal(i));
145 f5545b5c pbrook
        }
146 66fb9763 bellard
    }
147 66fb9763 bellard
}
148 66fb9763 bellard
149 c227f099 Anthony Liguori
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
150 9231944d bellard
{
151 c227f099 Anthony Liguori
    target_sigset_t d1;
152 9231944d bellard
    int i;
153 9231944d bellard
154 9231944d bellard
    host_to_target_sigset_internal(&d1, s);
155 9231944d bellard
    for(i = 0;i < TARGET_NSIG_WORDS; i++)
156 53a5960a pbrook
        d->sig[i] = tswapl(d1.sig[i]);
157 9231944d bellard
}
158 9231944d bellard
159 8fcd3692 blueswir1
static void target_to_host_sigset_internal(sigset_t *d,
160 c227f099 Anthony Liguori
                                           const target_sigset_t *s)
161 66fb9763 bellard
{
162 66fb9763 bellard
    int i;
163 f5545b5c pbrook
    sigemptyset(d);
164 f5545b5c pbrook
    for (i = 1; i <= TARGET_NSIG; i++) {
165 f5545b5c pbrook
        if (target_sigismember(s, i)) {
166 f5545b5c pbrook
            sigaddset(d, target_to_host_signal(i));
167 f5545b5c pbrook
        }
168 f5545b5c pbrook
     }
169 66fb9763 bellard
}
170 66fb9763 bellard
171 c227f099 Anthony Liguori
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
172 9231944d bellard
{
173 c227f099 Anthony Liguori
    target_sigset_t s1;
174 9231944d bellard
    int i;
175 9231944d bellard
176 9231944d bellard
    for(i = 0;i < TARGET_NSIG_WORDS; i++)
177 53a5960a pbrook
        s1.sig[i] = tswapl(s->sig[i]);
178 9231944d bellard
    target_to_host_sigset_internal(d, &s1);
179 9231944d bellard
}
180 3b46e624 ths
181 992f48a0 blueswir1
void host_to_target_old_sigset(abi_ulong *old_sigset,
182 66fb9763 bellard
                               const sigset_t *sigset)
183 66fb9763 bellard
{
184 c227f099 Anthony Liguori
    target_sigset_t d;
185 9e5f5284 bellard
    host_to_target_sigset(&d, sigset);
186 9e5f5284 bellard
    *old_sigset = d.sig[0];
187 66fb9763 bellard
}
188 66fb9763 bellard
189 5fafdf24 ths
void target_to_host_old_sigset(sigset_t *sigset,
190 992f48a0 blueswir1
                               const abi_ulong *old_sigset)
191 66fb9763 bellard
{
192 c227f099 Anthony Liguori
    target_sigset_t d;
193 9e5f5284 bellard
    int i;
194 9e5f5284 bellard
195 9e5f5284 bellard
    d.sig[0] = *old_sigset;
196 9e5f5284 bellard
    for(i = 1;i < TARGET_NSIG_WORDS; i++)
197 9e5f5284 bellard
        d.sig[i] = 0;
198 9e5f5284 bellard
    target_to_host_sigset(sigset, &d);
199 66fb9763 bellard
}
200 66fb9763 bellard
201 9de5e440 bellard
/* siginfo conversion */
202 9de5e440 bellard
203 c227f099 Anthony Liguori
static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
204 9de5e440 bellard
                                                 const siginfo_t *info)
205 66fb9763 bellard
{
206 9de5e440 bellard
    int sig;
207 9de5e440 bellard
    sig = host_to_target_signal(info->si_signo);
208 9de5e440 bellard
    tinfo->si_signo = sig;
209 9de5e440 bellard
    tinfo->si_errno = 0;
210 afd7cd92 pbrook
    tinfo->si_code = info->si_code;
211 5fafdf24 ths
    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
212 447db213 bellard
        sig == SIGBUS || sig == SIGTRAP) {
213 9de5e440 bellard
        /* should never come here, but who knows. The information for
214 9de5e440 bellard
           the target is irrelevant */
215 9de5e440 bellard
        tinfo->_sifields._sigfault._addr = 0;
216 7f7f7c84 ths
    } else if (sig == SIGIO) {
217 7f7f7c84 ths
        tinfo->_sifields._sigpoll._fd = info->si_fd;
218 9de5e440 bellard
    } else if (sig >= TARGET_SIGRTMIN) {
219 9de5e440 bellard
        tinfo->_sifields._rt._pid = info->si_pid;
220 9de5e440 bellard
        tinfo->_sifields._rt._uid = info->si_uid;
221 9de5e440 bellard
        /* XXX: potential problem if 64 bit */
222 5fafdf24 ths
        tinfo->_sifields._rt._sigval.sival_ptr =
223 459a4017 bellard
            (abi_ulong)(unsigned long)info->si_value.sival_ptr;
224 9de5e440 bellard
    }
225 9de5e440 bellard
}
226 9de5e440 bellard
227 c227f099 Anthony Liguori
static void tswap_siginfo(target_siginfo_t *tinfo,
228 c227f099 Anthony Liguori
                          const target_siginfo_t *info)
229 9de5e440 bellard
{
230 9de5e440 bellard
    int sig;
231 9de5e440 bellard
    sig = info->si_signo;
232 9de5e440 bellard
    tinfo->si_signo = tswap32(sig);
233 66fb9763 bellard
    tinfo->si_errno = tswap32(info->si_errno);
234 66fb9763 bellard
    tinfo->si_code = tswap32(info->si_code);
235 5fafdf24 ths
    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
236 447db213 bellard
        sig == SIGBUS || sig == SIGTRAP) {
237 5fafdf24 ths
        tinfo->_sifields._sigfault._addr =
238 9de5e440 bellard
            tswapl(info->_sifields._sigfault._addr);
239 7f7f7c84 ths
    } else if (sig == SIGIO) {
240 7f7f7c84 ths
        tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
241 9de5e440 bellard
    } else if (sig >= TARGET_SIGRTMIN) {
242 9de5e440 bellard
        tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
243 9de5e440 bellard
        tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
244 5fafdf24 ths
        tinfo->_sifields._rt._sigval.sival_ptr =
245 9de5e440 bellard
            tswapl(info->_sifields._rt._sigval.sival_ptr);
246 9de5e440 bellard
    }
247 9de5e440 bellard
}
248 9de5e440 bellard
249 9de5e440 bellard
250 c227f099 Anthony Liguori
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
251 9de5e440 bellard
{
252 9de5e440 bellard
    host_to_target_siginfo_noswap(tinfo, info);
253 9de5e440 bellard
    tswap_siginfo(tinfo, tinfo);
254 66fb9763 bellard
}
255 66fb9763 bellard
256 9de5e440 bellard
/* XXX: we support only POSIX RT signals are used. */
257 aa1f17c1 ths
/* XXX: find a solution for 64 bit (additional malloced data is needed) */
258 c227f099 Anthony Liguori
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
259 66fb9763 bellard
{
260 66fb9763 bellard
    info->si_signo = tswap32(tinfo->si_signo);
261 66fb9763 bellard
    info->si_errno = tswap32(tinfo->si_errno);
262 66fb9763 bellard
    info->si_code = tswap32(tinfo->si_code);
263 9de5e440 bellard
    info->si_pid = tswap32(tinfo->_sifields._rt._pid);
264 9de5e440 bellard
    info->si_uid = tswap32(tinfo->_sifields._rt._uid);
265 5fafdf24 ths
    info->si_value.sival_ptr =
266 459a4017 bellard
            (void *)(long)tswapl(tinfo->_sifields._rt._sigval.sival_ptr);
267 66fb9763 bellard
}
268 66fb9763 bellard
269 ca587a8e aurel32
static int fatal_signal (int sig)
270 ca587a8e aurel32
{
271 ca587a8e aurel32
    switch (sig) {
272 ca587a8e aurel32
    case TARGET_SIGCHLD:
273 ca587a8e aurel32
    case TARGET_SIGURG:
274 ca587a8e aurel32
    case TARGET_SIGWINCH:
275 ca587a8e aurel32
        /* Ignored by default.  */
276 ca587a8e aurel32
        return 0;
277 ca587a8e aurel32
    case TARGET_SIGCONT:
278 ca587a8e aurel32
    case TARGET_SIGSTOP:
279 ca587a8e aurel32
    case TARGET_SIGTSTP:
280 ca587a8e aurel32
    case TARGET_SIGTTIN:
281 ca587a8e aurel32
    case TARGET_SIGTTOU:
282 ca587a8e aurel32
        /* Job control signals.  */
283 ca587a8e aurel32
        return 0;
284 ca587a8e aurel32
    default:
285 ca587a8e aurel32
        return 1;
286 ca587a8e aurel32
    }
287 ca587a8e aurel32
}
288 ca587a8e aurel32
289 edf8e2af Mika Westerberg
/* returns 1 if given signal should dump core if not handled */
290 edf8e2af Mika Westerberg
static int core_dump_signal(int sig)
291 edf8e2af Mika Westerberg
{
292 edf8e2af Mika Westerberg
    switch (sig) {
293 edf8e2af Mika Westerberg
    case TARGET_SIGABRT:
294 edf8e2af Mika Westerberg
    case TARGET_SIGFPE:
295 edf8e2af Mika Westerberg
    case TARGET_SIGILL:
296 edf8e2af Mika Westerberg
    case TARGET_SIGQUIT:
297 edf8e2af Mika Westerberg
    case TARGET_SIGSEGV:
298 edf8e2af Mika Westerberg
    case TARGET_SIGTRAP:
299 edf8e2af Mika Westerberg
    case TARGET_SIGBUS:
300 edf8e2af Mika Westerberg
        return (1);
301 edf8e2af Mika Westerberg
    default:
302 edf8e2af Mika Westerberg
        return (0);
303 edf8e2af Mika Westerberg
    }
304 edf8e2af Mika Westerberg
}
305 edf8e2af Mika Westerberg
306 31e31b8a bellard
void signal_init(void)
307 31e31b8a bellard
{
308 31e31b8a bellard
    struct sigaction act;
309 624f7979 pbrook
    struct sigaction oact;
310 9e5f5284 bellard
    int i, j;
311 624f7979 pbrook
    int host_sig;
312 31e31b8a bellard
313 9e5f5284 bellard
    /* generate signal conversion tables */
314 3ca05588 Arnaud Patard
    for(i = 1; i < _NSIG; i++) {
315 9e5f5284 bellard
        if (host_to_target_signal_table[i] == 0)
316 9e5f5284 bellard
            host_to_target_signal_table[i] = i;
317 9e5f5284 bellard
    }
318 3ca05588 Arnaud Patard
    for(i = 1; i < _NSIG; i++) {
319 9e5f5284 bellard
        j = host_to_target_signal_table[i];
320 9e5f5284 bellard
        target_to_host_signal_table[j] = i;
321 9e5f5284 bellard
    }
322 3b46e624 ths
323 9de5e440 bellard
    /* set all host signal handlers. ALL signals are blocked during
324 9de5e440 bellard
       the handlers to serialize them. */
325 624f7979 pbrook
    memset(sigact_table, 0, sizeof(sigact_table));
326 624f7979 pbrook
327 9de5e440 bellard
    sigfillset(&act.sa_mask);
328 31e31b8a bellard
    act.sa_flags = SA_SIGINFO;
329 31e31b8a bellard
    act.sa_sigaction = host_signal_handler;
330 624f7979 pbrook
    for(i = 1; i <= TARGET_NSIG; i++) {
331 624f7979 pbrook
        host_sig = target_to_host_signal(i);
332 624f7979 pbrook
        sigaction(host_sig, NULL, &oact);
333 624f7979 pbrook
        if (oact.sa_sigaction == (void *)SIG_IGN) {
334 624f7979 pbrook
            sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
335 624f7979 pbrook
        } else if (oact.sa_sigaction == (void *)SIG_DFL) {
336 624f7979 pbrook
            sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
337 624f7979 pbrook
        }
338 624f7979 pbrook
        /* If there's already a handler installed then something has
339 624f7979 pbrook
           gone horribly wrong, so don't even try to handle that case.  */
340 ca587a8e aurel32
        /* Install some handlers for our own use.  We need at least
341 ca587a8e aurel32
           SIGSEGV and SIGBUS, to detect exceptions.  We can not just
342 ca587a8e aurel32
           trap all signals because it affects syscall interrupt
343 ca587a8e aurel32
           behavior.  But do trap all default-fatal signals.  */
344 ca587a8e aurel32
        if (fatal_signal (i))
345 624f7979 pbrook
            sigaction(host_sig, &act, NULL);
346 31e31b8a bellard
    }
347 66fb9763 bellard
}
348 66fb9763 bellard
349 66fb9763 bellard
/* signal queue handling */
350 66fb9763 bellard
351 624f7979 pbrook
static inline struct sigqueue *alloc_sigqueue(CPUState *env)
352 66fb9763 bellard
{
353 624f7979 pbrook
    TaskState *ts = env->opaque;
354 624f7979 pbrook
    struct sigqueue *q = ts->first_free;
355 66fb9763 bellard
    if (!q)
356 66fb9763 bellard
        return NULL;
357 624f7979 pbrook
    ts->first_free = q->next;
358 66fb9763 bellard
    return q;
359 31e31b8a bellard
}
360 31e31b8a bellard
361 624f7979 pbrook
static inline void free_sigqueue(CPUState *env, struct sigqueue *q)
362 66fb9763 bellard
{
363 624f7979 pbrook
    TaskState *ts = env->opaque;
364 624f7979 pbrook
    q->next = ts->first_free;
365 624f7979 pbrook
    ts->first_free = q;
366 66fb9763 bellard
}
367 66fb9763 bellard
368 9de5e440 bellard
/* abort execution with signal */
369 a5e50b26 malc
static void QEMU_NORETURN force_sig(int sig)
370 66fb9763 bellard
{
371 edf8e2af Mika Westerberg
    TaskState *ts = (TaskState *)thread_env->opaque;
372 edf8e2af Mika Westerberg
    int host_sig, core_dumped = 0;
373 603e4fd7 aurel32
    struct sigaction act;
374 66fb9763 bellard
    host_sig = target_to_host_signal(sig);
375 ca587a8e aurel32
    gdb_signalled(thread_env, sig);
376 603e4fd7 aurel32
377 edf8e2af Mika Westerberg
    /* dump core if supported by target binary format */
378 edf8e2af Mika Westerberg
    if (core_dump_signal(sig) && (ts->bprm->core_dump != NULL)) {
379 edf8e2af Mika Westerberg
        stop_all_tasks();
380 edf8e2af Mika Westerberg
        core_dumped =
381 edf8e2af Mika Westerberg
            ((*ts->bprm->core_dump)(sig, thread_env) == 0);
382 edf8e2af Mika Westerberg
    }
383 edf8e2af Mika Westerberg
    if (core_dumped) {
384 edf8e2af Mika Westerberg
        /* we already dumped the core of target process, we don't want
385 edf8e2af Mika Westerberg
         * a coredump of qemu itself */
386 edf8e2af Mika Westerberg
        struct rlimit nodump;
387 edf8e2af Mika Westerberg
        getrlimit(RLIMIT_CORE, &nodump);
388 edf8e2af Mika Westerberg
        nodump.rlim_cur=0;
389 edf8e2af Mika Westerberg
        setrlimit(RLIMIT_CORE, &nodump);
390 edf8e2af Mika Westerberg
        (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n",
391 edf8e2af Mika Westerberg
            sig, strsignal(host_sig), "core dumped" );
392 edf8e2af Mika Westerberg
    }
393 edf8e2af Mika Westerberg
394 603e4fd7 aurel32
    /* The proper exit code for dieing from an uncaught signal is
395 603e4fd7 aurel32
     * -<signal>.  The kernel doesn't allow exit() or _exit() to pass
396 603e4fd7 aurel32
     * a negative value.  To get the proper exit code we need to
397 603e4fd7 aurel32
     * actually die from an uncaught signal.  Here the default signal
398 603e4fd7 aurel32
     * handler is installed, we send ourself a signal and we wait for
399 603e4fd7 aurel32
     * it to arrive. */
400 603e4fd7 aurel32
    sigfillset(&act.sa_mask);
401 603e4fd7 aurel32
    act.sa_handler = SIG_DFL;
402 603e4fd7 aurel32
    sigaction(host_sig, &act, NULL);
403 603e4fd7 aurel32
404 603e4fd7 aurel32
    /* For some reason raise(host_sig) doesn't send the signal when
405 603e4fd7 aurel32
     * statically linked on x86-64. */
406 603e4fd7 aurel32
    kill(getpid(), host_sig);
407 603e4fd7 aurel32
408 603e4fd7 aurel32
    /* Make sure the signal isn't masked (just reuse the mask inside
409 603e4fd7 aurel32
    of act) */
410 603e4fd7 aurel32
    sigdelset(&act.sa_mask, host_sig);
411 603e4fd7 aurel32
    sigsuspend(&act.sa_mask);
412 603e4fd7 aurel32
413 603e4fd7 aurel32
    /* unreachable */
414 603e4fd7 aurel32
    assert(0);
415 603e4fd7 aurel32
416 66fb9763 bellard
}
417 66fb9763 bellard
418 9de5e440 bellard
/* queue a signal so that it will be send to the virtual CPU as soon
419 9de5e440 bellard
   as possible */
420 c227f099 Anthony Liguori
int queue_signal(CPUState *env, int sig, target_siginfo_t *info)
421 31e31b8a bellard
{
422 624f7979 pbrook
    TaskState *ts = env->opaque;
423 624f7979 pbrook
    struct emulated_sigtable *k;
424 9de5e440 bellard
    struct sigqueue *q, **pq;
425 992f48a0 blueswir1
    abi_ulong handler;
426 ca587a8e aurel32
    int queue;
427 66fb9763 bellard
428 9de5e440 bellard
#if defined(DEBUG_SIGNAL)
429 5fafdf24 ths
    fprintf(stderr, "queue_signal: sig=%d\n",
430 9de5e440 bellard
            sig);
431 66fb9763 bellard
#endif
432 624f7979 pbrook
    k = &ts->sigtab[sig - 1];
433 ca587a8e aurel32
    queue = gdb_queuesig ();
434 624f7979 pbrook
    handler = sigact_table[sig - 1]._sa_handler;
435 ca587a8e aurel32
    if (!queue && handler == TARGET_SIG_DFL) {
436 60b19691 ths
        if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
437 60b19691 ths
            kill(getpid(),SIGSTOP);
438 60b19691 ths
            return 0;
439 60b19691 ths
        } else
440 66fb9763 bellard
        /* default handler : ignore some signal. The other are fatal */
441 5fafdf24 ths
        if (sig != TARGET_SIGCHLD &&
442 5fafdf24 ths
            sig != TARGET_SIGURG &&
443 60b19691 ths
            sig != TARGET_SIGWINCH &&
444 60b19691 ths
            sig != TARGET_SIGCONT) {
445 66fb9763 bellard
            force_sig(sig);
446 9de5e440 bellard
        } else {
447 9de5e440 bellard
            return 0; /* indicate ignored */
448 66fb9763 bellard
        }
449 ca587a8e aurel32
    } else if (!queue && handler == TARGET_SIG_IGN) {
450 66fb9763 bellard
        /* ignore signal */
451 9de5e440 bellard
        return 0;
452 ca587a8e aurel32
    } else if (!queue && handler == TARGET_SIG_ERR) {
453 66fb9763 bellard
        force_sig(sig);
454 66fb9763 bellard
    } else {
455 9de5e440 bellard
        pq = &k->first;
456 9de5e440 bellard
        if (sig < TARGET_SIGRTMIN) {
457 9de5e440 bellard
            /* if non real time signal, we queue exactly one signal */
458 9de5e440 bellard
            if (!k->pending)
459 9de5e440 bellard
                q = &k->info;
460 9de5e440 bellard
            else
461 9de5e440 bellard
                return 0;
462 9de5e440 bellard
        } else {
463 9de5e440 bellard
            if (!k->pending) {
464 9de5e440 bellard
                /* first signal */
465 9de5e440 bellard
                q = &k->info;
466 9de5e440 bellard
            } else {
467 624f7979 pbrook
                q = alloc_sigqueue(env);
468 9de5e440 bellard
                if (!q)
469 9de5e440 bellard
                    return -EAGAIN;
470 9de5e440 bellard
                while (*pq != NULL)
471 9de5e440 bellard
                    pq = &(*pq)->next;
472 9de5e440 bellard
            }
473 9de5e440 bellard
        }
474 9de5e440 bellard
        *pq = q;
475 9de5e440 bellard
        q->info = *info;
476 9de5e440 bellard
        q->next = NULL;
477 9de5e440 bellard
        k->pending = 1;
478 9de5e440 bellard
        /* signal that a new signal is pending */
479 624f7979 pbrook
        ts->signal_pending = 1;
480 9de5e440 bellard
        return 1; /* indicates that the signal was queued */
481 9de5e440 bellard
    }
482 9de5e440 bellard
}
483 9de5e440 bellard
484 5fafdf24 ths
static void host_signal_handler(int host_signum, siginfo_t *info,
485 9de5e440 bellard
                                void *puc)
486 9de5e440 bellard
{
487 9de5e440 bellard
    int sig;
488 c227f099 Anthony Liguori
    target_siginfo_t tinfo;
489 9de5e440 bellard
490 9de5e440 bellard
    /* the CPU emulator uses some host signals to detect exceptions,
491 eaa449b9 aurel32
       we forward to it some signals */
492 ca587a8e aurel32
    if ((host_signum == SIGSEGV || host_signum == SIGBUS)
493 eaa449b9 aurel32
        && info->si_code > 0) {
494 b346ff46 bellard
        if (cpu_signal_handler(host_signum, info, puc))
495 9de5e440 bellard
            return;
496 9de5e440 bellard
    }
497 9de5e440 bellard
498 9de5e440 bellard
    /* get target signal number */
499 9de5e440 bellard
    sig = host_to_target_signal(host_signum);
500 9de5e440 bellard
    if (sig < 1 || sig > TARGET_NSIG)
501 9de5e440 bellard
        return;
502 9de5e440 bellard
#if defined(DEBUG_SIGNAL)
503 bc8a22cc bellard
    fprintf(stderr, "qemu: got signal %d\n", sig);
504 9de5e440 bellard
#endif
505 9de5e440 bellard
    host_to_target_siginfo_noswap(&tinfo, info);
506 d5975363 pbrook
    if (queue_signal(thread_env, sig, &tinfo) == 1) {
507 9de5e440 bellard
        /* interrupt the virtual CPU as soon as possible */
508 3098dba0 aurel32
        cpu_exit(thread_env);
509 66fb9763 bellard
    }
510 66fb9763 bellard
}
511 66fb9763 bellard
512 0da46a6e ths
/* do_sigaltstack() returns target values and errnos. */
513 579a97f7 bellard
/* compare linux/kernel/signal.c:do_sigaltstack() */
514 579a97f7 bellard
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
515 a04e134a ths
{
516 a04e134a ths
    int ret;
517 a04e134a ths
    struct target_sigaltstack oss;
518 a04e134a ths
519 a04e134a ths
    /* XXX: test errors */
520 579a97f7 bellard
    if(uoss_addr)
521 a04e134a ths
    {
522 a04e134a ths
        __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
523 a04e134a ths
        __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
524 a04e134a ths
        __put_user(sas_ss_flags(sp), &oss.ss_flags);
525 a04e134a ths
    }
526 a04e134a ths
527 579a97f7 bellard
    if(uss_addr)
528 a04e134a ths
    {
529 579a97f7 bellard
        struct target_sigaltstack *uss;
530 579a97f7 bellard
        struct target_sigaltstack ss;
531 a04e134a ths
532 0da46a6e ths
        ret = -TARGET_EFAULT;
533 579a97f7 bellard
        if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)
534 a04e134a ths
            || __get_user(ss.ss_sp, &uss->ss_sp)
535 a04e134a ths
            || __get_user(ss.ss_size, &uss->ss_size)
536 a04e134a ths
            || __get_user(ss.ss_flags, &uss->ss_flags))
537 a04e134a ths
            goto out;
538 579a97f7 bellard
        unlock_user_struct(uss, uss_addr, 0);
539 a04e134a ths
540 0da46a6e ths
        ret = -TARGET_EPERM;
541 a04e134a ths
        if (on_sig_stack(sp))
542 a04e134a ths
            goto out;
543 a04e134a ths
544 0da46a6e ths
        ret = -TARGET_EINVAL;
545 a04e134a ths
        if (ss.ss_flags != TARGET_SS_DISABLE
546 a04e134a ths
            && ss.ss_flags != TARGET_SS_ONSTACK
547 a04e134a ths
            && ss.ss_flags != 0)
548 a04e134a ths
            goto out;
549 a04e134a ths
550 a04e134a ths
        if (ss.ss_flags == TARGET_SS_DISABLE) {
551 a04e134a ths
            ss.ss_size = 0;
552 a04e134a ths
            ss.ss_sp = 0;
553 a04e134a ths
        } else {
554 0da46a6e ths
            ret = -TARGET_ENOMEM;
555 a04e134a ths
            if (ss.ss_size < MINSIGSTKSZ)
556 a04e134a ths
                goto out;
557 a04e134a ths
        }
558 a04e134a ths
559 a04e134a ths
        target_sigaltstack_used.ss_sp = ss.ss_sp;
560 a04e134a ths
        target_sigaltstack_used.ss_size = ss.ss_size;
561 a04e134a ths
    }
562 a04e134a ths
563 579a97f7 bellard
    if (uoss_addr) {
564 0da46a6e ths
        ret = -TARGET_EFAULT;
565 579a97f7 bellard
        if (copy_to_user(uoss_addr, &oss, sizeof(oss)))
566 a04e134a ths
            goto out;
567 a04e134a ths
    }
568 a04e134a ths
569 a04e134a ths
    ret = 0;
570 a04e134a ths
out:
571 a04e134a ths
    return ret;
572 a04e134a ths
}
573 a04e134a ths
574 0da46a6e ths
/* do_sigaction() return host values and errnos */
575 66fb9763 bellard
int do_sigaction(int sig, const struct target_sigaction *act,
576 66fb9763 bellard
                 struct target_sigaction *oact)
577 66fb9763 bellard
{
578 624f7979 pbrook
    struct target_sigaction *k;
579 773b93ee bellard
    struct sigaction act1;
580 773b93ee bellard
    int host_sig;
581 0da46a6e ths
    int ret = 0;
582 66fb9763 bellard
583 2a913eb1 ths
    if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
584 66fb9763 bellard
        return -EINVAL;
585 66fb9763 bellard
    k = &sigact_table[sig - 1];
586 773b93ee bellard
#if defined(DEBUG_SIGNAL)
587 0bf9e31a Blue Swirl
    fprintf(stderr, "sigaction sig=%d act=0x%p, oact=0x%p\n",
588 0bf9e31a Blue Swirl
            sig, act, oact);
589 66fb9763 bellard
#endif
590 66fb9763 bellard
    if (oact) {
591 624f7979 pbrook
        oact->_sa_handler = tswapl(k->_sa_handler);
592 624f7979 pbrook
        oact->sa_flags = tswapl(k->sa_flags);
593 388bb21a ths
#if !defined(TARGET_MIPS)
594 624f7979 pbrook
        oact->sa_restorer = tswapl(k->sa_restorer);
595 388bb21a ths
#endif
596 624f7979 pbrook
        oact->sa_mask = k->sa_mask;
597 66fb9763 bellard
    }
598 66fb9763 bellard
    if (act) {
599 624f7979 pbrook
        /* FIXME: This is not threadsafe.  */
600 624f7979 pbrook
        k->_sa_handler = tswapl(act->_sa_handler);
601 624f7979 pbrook
        k->sa_flags = tswapl(act->sa_flags);
602 388bb21a ths
#if !defined(TARGET_MIPS)
603 624f7979 pbrook
        k->sa_restorer = tswapl(act->sa_restorer);
604 388bb21a ths
#endif
605 624f7979 pbrook
        k->sa_mask = act->sa_mask;
606 773b93ee bellard
607 773b93ee bellard
        /* we update the host linux signal state */
608 773b93ee bellard
        host_sig = target_to_host_signal(sig);
609 773b93ee bellard
        if (host_sig != SIGSEGV && host_sig != SIGBUS) {
610 773b93ee bellard
            sigfillset(&act1.sa_mask);
611 773b93ee bellard
            act1.sa_flags = SA_SIGINFO;
612 624f7979 pbrook
            if (k->sa_flags & TARGET_SA_RESTART)
613 773b93ee bellard
                act1.sa_flags |= SA_RESTART;
614 773b93ee bellard
            /* NOTE: it is important to update the host kernel signal
615 773b93ee bellard
               ignore state to avoid getting unexpected interrupted
616 773b93ee bellard
               syscalls */
617 624f7979 pbrook
            if (k->_sa_handler == TARGET_SIG_IGN) {
618 773b93ee bellard
                act1.sa_sigaction = (void *)SIG_IGN;
619 624f7979 pbrook
            } else if (k->_sa_handler == TARGET_SIG_DFL) {
620 ca587a8e aurel32
                if (fatal_signal (sig))
621 ca587a8e aurel32
                    act1.sa_sigaction = host_signal_handler;
622 ca587a8e aurel32
                else
623 ca587a8e aurel32
                    act1.sa_sigaction = (void *)SIG_DFL;
624 773b93ee bellard
            } else {
625 773b93ee bellard
                act1.sa_sigaction = host_signal_handler;
626 773b93ee bellard
            }
627 0da46a6e ths
            ret = sigaction(host_sig, &act1, NULL);
628 773b93ee bellard
        }
629 66fb9763 bellard
    }
630 0da46a6e ths
    return ret;
631 66fb9763 bellard
}
632 66fb9763 bellard
633 c227f099 Anthony Liguori
static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,
634 c227f099 Anthony Liguori
                                       const target_siginfo_t *info)
635 43fff238 bellard
{
636 43fff238 bellard
    tswap_siginfo(tinfo, info);
637 43fff238 bellard
    return 0;
638 43fff238 bellard
}
639 43fff238 bellard
640 c3b5bc8a ths
static inline int current_exec_domain_sig(int sig)
641 c3b5bc8a ths
{
642 c3b5bc8a ths
    return /* current->exec_domain && current->exec_domain->signal_invmap
643 c3b5bc8a ths
              && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig;
644 c3b5bc8a ths
}
645 c3b5bc8a ths
646 459a4017 bellard
#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
647 66fb9763 bellard
648 66fb9763 bellard
/* from the Linux kernel */
649 66fb9763 bellard
650 66fb9763 bellard
struct target_fpreg {
651 66fb9763 bellard
        uint16_t significand[4];
652 66fb9763 bellard
        uint16_t exponent;
653 66fb9763 bellard
};
654 66fb9763 bellard
655 66fb9763 bellard
struct target_fpxreg {
656 66fb9763 bellard
        uint16_t significand[4];
657 66fb9763 bellard
        uint16_t exponent;
658 66fb9763 bellard
        uint16_t padding[3];
659 66fb9763 bellard
};
660 66fb9763 bellard
661 66fb9763 bellard
struct target_xmmreg {
662 992f48a0 blueswir1
        abi_ulong element[4];
663 66fb9763 bellard
};
664 66fb9763 bellard
665 66fb9763 bellard
struct target_fpstate {
666 66fb9763 bellard
        /* Regular FPU environment */
667 992f48a0 blueswir1
        abi_ulong       cw;
668 992f48a0 blueswir1
        abi_ulong       sw;
669 992f48a0 blueswir1
        abi_ulong       tag;
670 992f48a0 blueswir1
        abi_ulong       ipoff;
671 992f48a0 blueswir1
        abi_ulong       cssel;
672 992f48a0 blueswir1
        abi_ulong       dataoff;
673 992f48a0 blueswir1
        abi_ulong       datasel;
674 66fb9763 bellard
        struct target_fpreg        _st[8];
675 66fb9763 bellard
        uint16_t        status;
676 66fb9763 bellard
        uint16_t        magic;                /* 0xffff = regular FPU data only */
677 66fb9763 bellard
678 66fb9763 bellard
        /* FXSR FPU environment */
679 992f48a0 blueswir1
        abi_ulong       _fxsr_env[6];   /* FXSR FPU env is ignored */
680 992f48a0 blueswir1
        abi_ulong       mxcsr;
681 992f48a0 blueswir1
        abi_ulong       reserved;
682 66fb9763 bellard
        struct target_fpxreg        _fxsr_st[8];        /* FXSR FPU reg data is ignored */
683 66fb9763 bellard
        struct target_xmmreg        _xmm[8];
684 992f48a0 blueswir1
        abi_ulong       padding[56];
685 66fb9763 bellard
};
686 66fb9763 bellard
687 66fb9763 bellard
#define X86_FXSR_MAGIC                0x0000
688 66fb9763 bellard
689 66fb9763 bellard
struct target_sigcontext {
690 66fb9763 bellard
        uint16_t gs, __gsh;
691 66fb9763 bellard
        uint16_t fs, __fsh;
692 66fb9763 bellard
        uint16_t es, __esh;
693 66fb9763 bellard
        uint16_t ds, __dsh;
694 992f48a0 blueswir1
        abi_ulong edi;
695 992f48a0 blueswir1
        abi_ulong esi;
696 992f48a0 blueswir1
        abi_ulong ebp;
697 992f48a0 blueswir1
        abi_ulong esp;
698 992f48a0 blueswir1
        abi_ulong ebx;
699 992f48a0 blueswir1
        abi_ulong edx;
700 992f48a0 blueswir1
        abi_ulong ecx;
701 992f48a0 blueswir1
        abi_ulong eax;
702 992f48a0 blueswir1
        abi_ulong trapno;
703 992f48a0 blueswir1
        abi_ulong err;
704 992f48a0 blueswir1
        abi_ulong eip;
705 66fb9763 bellard
        uint16_t cs, __csh;
706 992f48a0 blueswir1
        abi_ulong eflags;
707 992f48a0 blueswir1
        abi_ulong esp_at_signal;
708 66fb9763 bellard
        uint16_t ss, __ssh;
709 992f48a0 blueswir1
        abi_ulong fpstate; /* pointer */
710 992f48a0 blueswir1
        abi_ulong oldmask;
711 992f48a0 blueswir1
        abi_ulong cr2;
712 66fb9763 bellard
};
713 66fb9763 bellard
714 66fb9763 bellard
struct target_ucontext {
715 992f48a0 blueswir1
        abi_ulong         tuc_flags;
716 992f48a0 blueswir1
        abi_ulong         tuc_link;
717 c227f099 Anthony Liguori
        target_stack_t          tuc_stack;
718 b8076a74 bellard
        struct target_sigcontext tuc_mcontext;
719 c227f099 Anthony Liguori
        target_sigset_t          tuc_sigmask;        /* mask last for extensibility */
720 66fb9763 bellard
};
721 66fb9763 bellard
722 66fb9763 bellard
struct sigframe
723 66fb9763 bellard
{
724 992f48a0 blueswir1
    abi_ulong pretcode;
725 66fb9763 bellard
    int sig;
726 66fb9763 bellard
    struct target_sigcontext sc;
727 66fb9763 bellard
    struct target_fpstate fpstate;
728 992f48a0 blueswir1
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
729 66fb9763 bellard
    char retcode[8];
730 66fb9763 bellard
};
731 66fb9763 bellard
732 66fb9763 bellard
struct rt_sigframe
733 66fb9763 bellard
{
734 992f48a0 blueswir1
    abi_ulong pretcode;
735 66fb9763 bellard
    int sig;
736 992f48a0 blueswir1
    abi_ulong pinfo;
737 992f48a0 blueswir1
    abi_ulong puc;
738 66fb9763 bellard
    struct target_siginfo info;
739 66fb9763 bellard
    struct target_ucontext uc;
740 66fb9763 bellard
    struct target_fpstate fpstate;
741 66fb9763 bellard
    char retcode[8];
742 66fb9763 bellard
};
743 66fb9763 bellard
744 66fb9763 bellard
/*
745 66fb9763 bellard
 * Set up a signal frame.
746 66fb9763 bellard
 */
747 66fb9763 bellard
748 66fb9763 bellard
/* XXX: save x87 state */
749 66fb9763 bellard
static int
750 66fb9763 bellard
setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
751 28be6234 bellard
                 CPUX86State *env, abi_ulong mask, abi_ulong fpstate_addr)
752 66fb9763 bellard
{
753 66fb9763 bellard
        int err = 0;
754 775b58d8 bellard
        uint16_t magic;
755 66fb9763 bellard
756 579a97f7 bellard
        /* already locked in setup_frame() */
757 a52c757c bellard
        err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
758 a52c757c bellard
        err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
759 a52c757c bellard
        err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
760 a52c757c bellard
        err |= __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
761 66fb9763 bellard
        err |= __put_user(env->regs[R_EDI], &sc->edi);
762 66fb9763 bellard
        err |= __put_user(env->regs[R_ESI], &sc->esi);
763 66fb9763 bellard
        err |= __put_user(env->regs[R_EBP], &sc->ebp);
764 66fb9763 bellard
        err |= __put_user(env->regs[R_ESP], &sc->esp);
765 66fb9763 bellard
        err |= __put_user(env->regs[R_EBX], &sc->ebx);
766 66fb9763 bellard
        err |= __put_user(env->regs[R_EDX], &sc->edx);
767 66fb9763 bellard
        err |= __put_user(env->regs[R_ECX], &sc->ecx);
768 66fb9763 bellard
        err |= __put_user(env->regs[R_EAX], &sc->eax);
769 66099dd9 bellard
        err |= __put_user(env->exception_index, &sc->trapno);
770 66099dd9 bellard
        err |= __put_user(env->error_code, &sc->err);
771 66fb9763 bellard
        err |= __put_user(env->eip, &sc->eip);
772 a52c757c bellard
        err |= __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
773 66fb9763 bellard
        err |= __put_user(env->eflags, &sc->eflags);
774 66fb9763 bellard
        err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal);
775 a52c757c bellard
        err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
776 ed2dcdf6 bellard
777 28be6234 bellard
        cpu_x86_fsave(env, fpstate_addr, 1);
778 ed2dcdf6 bellard
        fpstate->status = fpstate->sw;
779 775b58d8 bellard
        magic = 0xffff;
780 775b58d8 bellard
        err |= __put_user(magic, &fpstate->magic);
781 28be6234 bellard
        err |= __put_user(fpstate_addr, &sc->fpstate);
782 ed2dcdf6 bellard
783 66fb9763 bellard
        /* non-iBCS2 extensions.. */
784 66fb9763 bellard
        err |= __put_user(mask, &sc->oldmask);
785 a52c757c bellard
        err |= __put_user(env->cr[2], &sc->cr2);
786 66fb9763 bellard
        return err;
787 31e31b8a bellard
}
788 31e31b8a bellard
789 66fb9763 bellard
/*
790 66fb9763 bellard
 * Determine which stack to use..
791 66fb9763 bellard
 */
792 31e31b8a bellard
793 579a97f7 bellard
static inline abi_ulong
794 624f7979 pbrook
get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
795 31e31b8a bellard
{
796 66fb9763 bellard
        unsigned long esp;
797 66fb9763 bellard
798 66fb9763 bellard
        /* Default to using normal stack */
799 66fb9763 bellard
        esp = env->regs[R_ESP];
800 66fb9763 bellard
        /* This is the X/Open sanctioned signal stack switching.  */
801 624f7979 pbrook
        if (ka->sa_flags & TARGET_SA_ONSTACK) {
802 a04e134a ths
            if (sas_ss_flags(esp) == 0)
803 a04e134a ths
                esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
804 a04e134a ths
        }
805 66fb9763 bellard
806 66fb9763 bellard
        /* This is the legacy signal stack switching. */
807 5fafdf24 ths
        else
808 a52c757c bellard
        if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
809 624f7979 pbrook
            !(ka->sa_flags & TARGET_SA_RESTORER) &&
810 624f7979 pbrook
            ka->sa_restorer) {
811 624f7979 pbrook
            esp = (unsigned long) ka->sa_restorer;
812 a52c757c bellard
        }
813 579a97f7 bellard
        return (esp - frame_size) & -8ul;
814 66fb9763 bellard
}
815 66fb9763 bellard
816 579a97f7 bellard
/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
817 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
818 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUX86State *env)
819 66fb9763 bellard
{
820 579a97f7 bellard
        abi_ulong frame_addr;
821 66fb9763 bellard
        struct sigframe *frame;
822 9231944d bellard
        int i, err = 0;
823 66fb9763 bellard
824 579a97f7 bellard
        frame_addr = get_sigframe(ka, env, sizeof(*frame));
825 66fb9763 bellard
826 579a97f7 bellard
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
827 66fb9763 bellard
                goto give_sigsegv;
828 579a97f7 bellard
829 c3b5bc8a ths
        err |= __put_user(current_exec_domain_sig(sig),
830 66fb9763 bellard
                          &frame->sig);
831 66fb9763 bellard
        if (err)
832 66fb9763 bellard
                goto give_sigsegv;
833 66fb9763 bellard
834 28be6234 bellard
        setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
835 28be6234 bellard
                         frame_addr + offsetof(struct sigframe, fpstate));
836 66fb9763 bellard
        if (err)
837 66fb9763 bellard
                goto give_sigsegv;
838 66fb9763 bellard
839 9231944d bellard
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
840 9231944d bellard
            if (__put_user(set->sig[i], &frame->extramask[i - 1]))
841 9231944d bellard
                goto give_sigsegv;
842 9231944d bellard
        }
843 66fb9763 bellard
844 66fb9763 bellard
        /* Set up to return from userspace.  If provided, use a stub
845 66fb9763 bellard
           already in userspace.  */
846 624f7979 pbrook
        if (ka->sa_flags & TARGET_SA_RESTORER) {
847 624f7979 pbrook
                err |= __put_user(ka->sa_restorer, &frame->pretcode);
848 66fb9763 bellard
        } else {
849 775b58d8 bellard
                uint16_t val16;
850 28be6234 bellard
                abi_ulong retcode_addr;
851 28be6234 bellard
                retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
852 28be6234 bellard
                err |= __put_user(retcode_addr, &frame->pretcode);
853 66fb9763 bellard
                /* This is popl %eax ; movl $,%eax ; int $0x80 */
854 775b58d8 bellard
                val16 = 0xb858;
855 775b58d8 bellard
                err |= __put_user(val16, (uint16_t *)(frame->retcode+0));
856 66fb9763 bellard
                err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
857 775b58d8 bellard
                val16 = 0x80cd;
858 775b58d8 bellard
                err |= __put_user(val16, (uint16_t *)(frame->retcode+6));
859 66fb9763 bellard
        }
860 66fb9763 bellard
861 66fb9763 bellard
        if (err)
862 66fb9763 bellard
                goto give_sigsegv;
863 66fb9763 bellard
864 66fb9763 bellard
        /* Set up registers for signal handler */
865 28be6234 bellard
        env->regs[R_ESP] = frame_addr;
866 624f7979 pbrook
        env->eip = ka->_sa_handler;
867 66fb9763 bellard
868 66fb9763 bellard
        cpu_x86_load_seg(env, R_DS, __USER_DS);
869 66fb9763 bellard
        cpu_x86_load_seg(env, R_ES, __USER_DS);
870 66fb9763 bellard
        cpu_x86_load_seg(env, R_SS, __USER_DS);
871 66fb9763 bellard
        cpu_x86_load_seg(env, R_CS, __USER_CS);
872 66fb9763 bellard
        env->eflags &= ~TF_MASK;
873 66fb9763 bellard
874 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
875 579a97f7 bellard
876 66fb9763 bellard
        return;
877 66fb9763 bellard
878 66fb9763 bellard
give_sigsegv:
879 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
880 66fb9763 bellard
        if (sig == TARGET_SIGSEGV)
881 624f7979 pbrook
                ka->_sa_handler = TARGET_SIG_DFL;
882 66fb9763 bellard
        force_sig(TARGET_SIGSEGV /* , current */);
883 66fb9763 bellard
}
884 66fb9763 bellard
885 579a97f7 bellard
/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
886 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
887 c227f099 Anthony Liguori
                           target_siginfo_t *info,
888 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUX86State *env)
889 66fb9763 bellard
{
890 28be6234 bellard
        abi_ulong frame_addr, addr;
891 66fb9763 bellard
        struct rt_sigframe *frame;
892 9231944d bellard
        int i, err = 0;
893 66fb9763 bellard
894 579a97f7 bellard
        frame_addr = get_sigframe(ka, env, sizeof(*frame));
895 66fb9763 bellard
896 579a97f7 bellard
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
897 66fb9763 bellard
                goto give_sigsegv;
898 66fb9763 bellard
899 c3b5bc8a ths
        err |= __put_user(current_exec_domain_sig(sig),
900 66fb9763 bellard
                          &frame->sig);
901 28be6234 bellard
        addr = frame_addr + offsetof(struct rt_sigframe, info);
902 28be6234 bellard
        err |= __put_user(addr, &frame->pinfo);
903 28be6234 bellard
        addr = frame_addr + offsetof(struct rt_sigframe, uc);
904 28be6234 bellard
        err |= __put_user(addr, &frame->puc);
905 66fb9763 bellard
        err |= copy_siginfo_to_user(&frame->info, info);
906 66fb9763 bellard
        if (err)
907 66fb9763 bellard
                goto give_sigsegv;
908 31e31b8a bellard
909 66fb9763 bellard
        /* Create the ucontext.  */
910 b8076a74 bellard
        err |= __put_user(0, &frame->uc.tuc_flags);
911 b8076a74 bellard
        err |= __put_user(0, &frame->uc.tuc_link);
912 a04e134a ths
        err |= __put_user(target_sigaltstack_used.ss_sp,
913 b8076a74 bellard
                          &frame->uc.tuc_stack.ss_sp);
914 a04e134a ths
        err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
915 b8076a74 bellard
                          &frame->uc.tuc_stack.ss_flags);
916 a04e134a ths
        err |= __put_user(target_sigaltstack_used.ss_size,
917 b8076a74 bellard
                          &frame->uc.tuc_stack.ss_size);
918 b8076a74 bellard
        err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate,
919 28be6234 bellard
                                env, set->sig[0], 
920 28be6234 bellard
                                frame_addr + offsetof(struct rt_sigframe, fpstate));
921 9231944d bellard
        for(i = 0; i < TARGET_NSIG_WORDS; i++) {
922 b8076a74 bellard
            if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
923 9231944d bellard
                goto give_sigsegv;
924 9231944d bellard
        }
925 31e31b8a bellard
926 66fb9763 bellard
        /* Set up to return from userspace.  If provided, use a stub
927 66fb9763 bellard
           already in userspace.  */
928 624f7979 pbrook
        if (ka->sa_flags & TARGET_SA_RESTORER) {
929 624f7979 pbrook
                err |= __put_user(ka->sa_restorer, &frame->pretcode);
930 66fb9763 bellard
        } else {
931 775b58d8 bellard
                uint16_t val16;
932 28be6234 bellard
                addr = frame_addr + offsetof(struct rt_sigframe, retcode);
933 28be6234 bellard
                err |= __put_user(addr, &frame->pretcode);
934 66fb9763 bellard
                /* This is movl $,%eax ; int $0x80 */
935 775b58d8 bellard
                err |= __put_user(0xb8, (char *)(frame->retcode+0));
936 66fb9763 bellard
                err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
937 775b58d8 bellard
                val16 = 0x80cd;
938 775b58d8 bellard
                err |= __put_user(val16, (uint16_t *)(frame->retcode+5));
939 66fb9763 bellard
        }
940 66fb9763 bellard
941 66fb9763 bellard
        if (err)
942 66fb9763 bellard
                goto give_sigsegv;
943 66fb9763 bellard
944 66fb9763 bellard
        /* Set up registers for signal handler */
945 28be6234 bellard
        env->regs[R_ESP] = frame_addr;
946 624f7979 pbrook
        env->eip = ka->_sa_handler;
947 66fb9763 bellard
948 66fb9763 bellard
        cpu_x86_load_seg(env, R_DS, __USER_DS);
949 66fb9763 bellard
        cpu_x86_load_seg(env, R_ES, __USER_DS);
950 66fb9763 bellard
        cpu_x86_load_seg(env, R_SS, __USER_DS);
951 66fb9763 bellard
        cpu_x86_load_seg(env, R_CS, __USER_CS);
952 66fb9763 bellard
        env->eflags &= ~TF_MASK;
953 66fb9763 bellard
954 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
955 579a97f7 bellard
956 66fb9763 bellard
        return;
957 66fb9763 bellard
958 66fb9763 bellard
give_sigsegv:
959 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
960 66fb9763 bellard
        if (sig == TARGET_SIGSEGV)
961 624f7979 pbrook
                ka->_sa_handler = TARGET_SIG_DFL;
962 66fb9763 bellard
        force_sig(TARGET_SIGSEGV /* , current */);
963 66fb9763 bellard
}
964 66fb9763 bellard
965 66fb9763 bellard
static int
966 66fb9763 bellard
restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
967 66fb9763 bellard
{
968 66fb9763 bellard
        unsigned int err = 0;
969 28be6234 bellard
        abi_ulong fpstate_addr;
970 28be6234 bellard
        unsigned int tmpflags;
971 28be6234 bellard
972 28be6234 bellard
        cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
973 28be6234 bellard
        cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
974 28be6234 bellard
        cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
975 28be6234 bellard
        cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
976 28be6234 bellard
977 28be6234 bellard
        env->regs[R_EDI] = tswapl(sc->edi);
978 28be6234 bellard
        env->regs[R_ESI] = tswapl(sc->esi);
979 28be6234 bellard
        env->regs[R_EBP] = tswapl(sc->ebp);
980 28be6234 bellard
        env->regs[R_ESP] = tswapl(sc->esp);
981 28be6234 bellard
        env->regs[R_EBX] = tswapl(sc->ebx);
982 28be6234 bellard
        env->regs[R_EDX] = tswapl(sc->edx);
983 28be6234 bellard
        env->regs[R_ECX] = tswapl(sc->ecx);
984 28be6234 bellard
        env->eip = tswapl(sc->eip);
985 66fb9763 bellard
986 66fb9763 bellard
        cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3);
987 66fb9763 bellard
        cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3);
988 5fafdf24 ths
989 28be6234 bellard
        tmpflags = tswapl(sc->eflags);
990 28be6234 bellard
        env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
991 28be6234 bellard
        //                regs->orig_eax = -1;                /* disable syscall checks */
992 66fb9763 bellard
993 28be6234 bellard
        fpstate_addr = tswapl(sc->fpstate);
994 28be6234 bellard
        if (fpstate_addr != 0) {
995 28be6234 bellard
                if (!access_ok(VERIFY_READ, fpstate_addr, 
996 28be6234 bellard
                               sizeof(struct target_fpstate)))
997 28be6234 bellard
                        goto badframe;
998 28be6234 bellard
                cpu_x86_frstor(env, fpstate_addr, 1);
999 66fb9763 bellard
        }
1000 ed2dcdf6 bellard
1001 28be6234 bellard
        *peax = tswapl(sc->eax);
1002 66fb9763 bellard
        return err;
1003 66fb9763 bellard
badframe:
1004 66fb9763 bellard
        return 1;
1005 66fb9763 bellard
}
1006 66fb9763 bellard
1007 66fb9763 bellard
long do_sigreturn(CPUX86State *env)
1008 66fb9763 bellard
{
1009 579a97f7 bellard
    struct sigframe *frame;
1010 579a97f7 bellard
    abi_ulong frame_addr = env->regs[R_ESP] - 8;
1011 c227f099 Anthony Liguori
    target_sigset_t target_set;
1012 66fb9763 bellard
    sigset_t set;
1013 66fb9763 bellard
    int eax, i;
1014 66fb9763 bellard
1015 447db213 bellard
#if defined(DEBUG_SIGNAL)
1016 447db213 bellard
    fprintf(stderr, "do_sigreturn\n");
1017 447db213 bellard
#endif
1018 579a97f7 bellard
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1019 579a97f7 bellard
        goto badframe;
1020 66fb9763 bellard
    /* set blocked signals */
1021 9231944d bellard
    if (__get_user(target_set.sig[0], &frame->sc.oldmask))
1022 9231944d bellard
        goto badframe;
1023 9231944d bellard
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1024 9231944d bellard
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
1025 9231944d bellard
            goto badframe;
1026 9231944d bellard
    }
1027 66fb9763 bellard
1028 9231944d bellard
    target_to_host_sigset_internal(&set, &target_set);
1029 66fb9763 bellard
    sigprocmask(SIG_SETMASK, &set, NULL);
1030 3b46e624 ths
1031 66fb9763 bellard
    /* restore registers */
1032 66fb9763 bellard
    if (restore_sigcontext(env, &frame->sc, &eax))
1033 66fb9763 bellard
        goto badframe;
1034 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 0);
1035 66fb9763 bellard
    return eax;
1036 66fb9763 bellard
1037 66fb9763 bellard
badframe:
1038 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 0);
1039 66fb9763 bellard
    force_sig(TARGET_SIGSEGV);
1040 66fb9763 bellard
    return 0;
1041 66fb9763 bellard
}
1042 66fb9763 bellard
1043 66fb9763 bellard
long do_rt_sigreturn(CPUX86State *env)
1044 66fb9763 bellard
{
1045 28be6234 bellard
        abi_ulong frame_addr;
1046 28be6234 bellard
        struct rt_sigframe *frame;
1047 66fb9763 bellard
        sigset_t set;
1048 66fb9763 bellard
        int eax;
1049 66fb9763 bellard
1050 28be6234 bellard
        frame_addr = env->regs[R_ESP] - 4;
1051 28be6234 bellard
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1052 28be6234 bellard
                goto badframe;
1053 b8076a74 bellard
        target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
1054 66fb9763 bellard
        sigprocmask(SIG_SETMASK, &set, NULL);
1055 5fafdf24 ths
1056 b8076a74 bellard
        if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
1057 66fb9763 bellard
                goto badframe;
1058 66fb9763 bellard
1059 28be6234 bellard
        if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0, 
1060 28be6234 bellard
                           get_sp_from_cpustate(env)) == -EFAULT)
1061 66fb9763 bellard
                goto badframe;
1062 a04e134a ths
1063 28be6234 bellard
        unlock_user_struct(frame, frame_addr, 0);
1064 66fb9763 bellard
        return eax;
1065 66fb9763 bellard
1066 66fb9763 bellard
badframe:
1067 28be6234 bellard
        unlock_user_struct(frame, frame_addr, 0);
1068 28be6234 bellard
        force_sig(TARGET_SIGSEGV);
1069 66fb9763 bellard
        return 0;
1070 66fb9763 bellard
}
1071 66fb9763 bellard
1072 43fff238 bellard
#elif defined(TARGET_ARM)
1073 43fff238 bellard
1074 43fff238 bellard
struct target_sigcontext {
1075 992f48a0 blueswir1
        abi_ulong trap_no;
1076 992f48a0 blueswir1
        abi_ulong error_code;
1077 992f48a0 blueswir1
        abi_ulong oldmask;
1078 992f48a0 blueswir1
        abi_ulong arm_r0;
1079 992f48a0 blueswir1
        abi_ulong arm_r1;
1080 992f48a0 blueswir1
        abi_ulong arm_r2;
1081 992f48a0 blueswir1
        abi_ulong arm_r3;
1082 992f48a0 blueswir1
        abi_ulong arm_r4;
1083 992f48a0 blueswir1
        abi_ulong arm_r5;
1084 992f48a0 blueswir1
        abi_ulong arm_r6;
1085 992f48a0 blueswir1
        abi_ulong arm_r7;
1086 992f48a0 blueswir1
        abi_ulong arm_r8;
1087 992f48a0 blueswir1
        abi_ulong arm_r9;
1088 992f48a0 blueswir1
        abi_ulong arm_r10;
1089 992f48a0 blueswir1
        abi_ulong arm_fp;
1090 992f48a0 blueswir1
        abi_ulong arm_ip;
1091 992f48a0 blueswir1
        abi_ulong arm_sp;
1092 992f48a0 blueswir1
        abi_ulong arm_lr;
1093 992f48a0 blueswir1
        abi_ulong arm_pc;
1094 992f48a0 blueswir1
        abi_ulong arm_cpsr;
1095 992f48a0 blueswir1
        abi_ulong fault_address;
1096 43fff238 bellard
};
1097 43fff238 bellard
1098 a745ec6d pbrook
struct target_ucontext_v1 {
1099 a745ec6d pbrook
    abi_ulong tuc_flags;
1100 a745ec6d pbrook
    abi_ulong tuc_link;
1101 c227f099 Anthony Liguori
    target_stack_t tuc_stack;
1102 a745ec6d pbrook
    struct target_sigcontext tuc_mcontext;
1103 c227f099 Anthony Liguori
    target_sigset_t  tuc_sigmask;        /* mask last for extensibility */
1104 a745ec6d pbrook
};
1105 a745ec6d pbrook
1106 a745ec6d pbrook
struct target_ucontext_v2 {
1107 992f48a0 blueswir1
    abi_ulong tuc_flags;
1108 992f48a0 blueswir1
    abi_ulong tuc_link;
1109 c227f099 Anthony Liguori
    target_stack_t tuc_stack;
1110 b8076a74 bellard
    struct target_sigcontext tuc_mcontext;
1111 c227f099 Anthony Liguori
    target_sigset_t  tuc_sigmask;        /* mask last for extensibility */
1112 a745ec6d pbrook
    char __unused[128 - sizeof(sigset_t)];
1113 a745ec6d pbrook
    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1114 43fff238 bellard
};
1115 43fff238 bellard
1116 a8c33204 pbrook
struct sigframe_v1
1117 43fff238 bellard
{
1118 43fff238 bellard
    struct target_sigcontext sc;
1119 992f48a0 blueswir1
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
1120 992f48a0 blueswir1
    abi_ulong retcode;
1121 43fff238 bellard
};
1122 43fff238 bellard
1123 a8c33204 pbrook
struct sigframe_v2
1124 a8c33204 pbrook
{
1125 a8c33204 pbrook
    struct target_ucontext_v2 uc;
1126 a8c33204 pbrook
    abi_ulong retcode;
1127 a8c33204 pbrook
};
1128 a8c33204 pbrook
1129 a745ec6d pbrook
struct rt_sigframe_v1
1130 43fff238 bellard
{
1131 f8b0aa25 bellard
    abi_ulong pinfo;
1132 f8b0aa25 bellard
    abi_ulong puc;
1133 43fff238 bellard
    struct target_siginfo info;
1134 a745ec6d pbrook
    struct target_ucontext_v1 uc;
1135 a745ec6d pbrook
    abi_ulong retcode;
1136 a745ec6d pbrook
};
1137 a745ec6d pbrook
1138 a745ec6d pbrook
struct rt_sigframe_v2
1139 a745ec6d pbrook
{
1140 a745ec6d pbrook
    struct target_siginfo info;
1141 a745ec6d pbrook
    struct target_ucontext_v2 uc;
1142 992f48a0 blueswir1
    abi_ulong retcode;
1143 43fff238 bellard
};
1144 43fff238 bellard
1145 43fff238 bellard
#define TARGET_CONFIG_CPU_32 1
1146 43fff238 bellard
1147 43fff238 bellard
/*
1148 43fff238 bellard
 * For ARM syscalls, we encode the syscall number into the instruction.
1149 43fff238 bellard
 */
1150 43fff238 bellard
#define SWI_SYS_SIGRETURN        (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
1151 43fff238 bellard
#define SWI_SYS_RT_SIGRETURN        (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
1152 43fff238 bellard
1153 43fff238 bellard
/*
1154 43fff238 bellard
 * For Thumb syscalls, we pass the syscall number via r7.  We therefore
1155 43fff238 bellard
 * need two 16-bit instructions.
1156 43fff238 bellard
 */
1157 43fff238 bellard
#define SWI_THUMB_SIGRETURN        (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
1158 43fff238 bellard
#define SWI_THUMB_RT_SIGRETURN        (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
1159 43fff238 bellard
1160 992f48a0 blueswir1
static const abi_ulong retcodes[4] = {
1161 43fff238 bellard
        SWI_SYS_SIGRETURN,        SWI_THUMB_SIGRETURN,
1162 43fff238 bellard
        SWI_SYS_RT_SIGRETURN,        SWI_THUMB_RT_SIGRETURN
1163 43fff238 bellard
};
1164 43fff238 bellard
1165 43fff238 bellard
1166 43fff238 bellard
#define __get_user_error(x,p,e) __get_user(x, p)
1167 43fff238 bellard
1168 43fff238 bellard
static inline int valid_user_regs(CPUState *regs)
1169 43fff238 bellard
{
1170 43fff238 bellard
    return 1;
1171 43fff238 bellard
}
1172 43fff238 bellard
1173 a8c33204 pbrook
static void
1174 43fff238 bellard
setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
1175 f8b0aa25 bellard
                 CPUState *env, abi_ulong mask)
1176 43fff238 bellard
{
1177 a8c33204 pbrook
        __put_user(env->regs[0], &sc->arm_r0);
1178 a8c33204 pbrook
        __put_user(env->regs[1], &sc->arm_r1);
1179 a8c33204 pbrook
        __put_user(env->regs[2], &sc->arm_r2);
1180 a8c33204 pbrook
        __put_user(env->regs[3], &sc->arm_r3);
1181 a8c33204 pbrook
        __put_user(env->regs[4], &sc->arm_r4);
1182 a8c33204 pbrook
        __put_user(env->regs[5], &sc->arm_r5);
1183 a8c33204 pbrook
        __put_user(env->regs[6], &sc->arm_r6);
1184 a8c33204 pbrook
        __put_user(env->regs[7], &sc->arm_r7);
1185 a8c33204 pbrook
        __put_user(env->regs[8], &sc->arm_r8);
1186 a8c33204 pbrook
        __put_user(env->regs[9], &sc->arm_r9);
1187 a8c33204 pbrook
        __put_user(env->regs[10], &sc->arm_r10);
1188 a8c33204 pbrook
        __put_user(env->regs[11], &sc->arm_fp);
1189 a8c33204 pbrook
        __put_user(env->regs[12], &sc->arm_ip);
1190 a8c33204 pbrook
        __put_user(env->regs[13], &sc->arm_sp);
1191 a8c33204 pbrook
        __put_user(env->regs[14], &sc->arm_lr);
1192 a8c33204 pbrook
        __put_user(env->regs[15], &sc->arm_pc);
1193 43fff238 bellard
#ifdef TARGET_CONFIG_CPU_32
1194 a8c33204 pbrook
        __put_user(cpsr_read(env), &sc->arm_cpsr);
1195 43fff238 bellard
#endif
1196 43fff238 bellard
1197 a8c33204 pbrook
        __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
1198 a8c33204 pbrook
        __put_user(/* current->thread.error_code */ 0, &sc->error_code);
1199 a8c33204 pbrook
        __put_user(/* current->thread.address */ 0, &sc->fault_address);
1200 a8c33204 pbrook
        __put_user(mask, &sc->oldmask);
1201 43fff238 bellard
}
1202 43fff238 bellard
1203 579a97f7 bellard
static inline abi_ulong
1204 624f7979 pbrook
get_sigframe(struct target_sigaction *ka, CPUState *regs, int framesize)
1205 43fff238 bellard
{
1206 43fff238 bellard
        unsigned long sp = regs->regs[13];
1207 43fff238 bellard
1208 43fff238 bellard
        /*
1209 43fff238 bellard
         * This is the X/Open sanctioned signal stack switching.
1210 43fff238 bellard
         */
1211 624f7979 pbrook
        if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
1212 a04e134a ths
            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1213 43fff238 bellard
        /*
1214 43fff238 bellard
         * ATPCS B01 mandates 8-byte alignment
1215 43fff238 bellard
         */
1216 579a97f7 bellard
        return (sp - framesize) & ~7;
1217 43fff238 bellard
}
1218 43fff238 bellard
1219 43fff238 bellard
static int
1220 624f7979 pbrook
setup_return(CPUState *env, struct target_sigaction *ka,
1221 f8b0aa25 bellard
             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
1222 43fff238 bellard
{
1223 624f7979 pbrook
        abi_ulong handler = ka->_sa_handler;
1224 992f48a0 blueswir1
        abi_ulong retcode;
1225 75b680e5 pbrook
        int thumb = handler & 1;
1226 43fff238 bellard
1227 624f7979 pbrook
        if (ka->sa_flags & TARGET_SA_RESTORER) {
1228 624f7979 pbrook
                retcode = ka->sa_restorer;
1229 43fff238 bellard
        } else {
1230 43fff238 bellard
                unsigned int idx = thumb;
1231 43fff238 bellard
1232 624f7979 pbrook
                if (ka->sa_flags & TARGET_SA_SIGINFO)
1233 43fff238 bellard
                        idx += 2;
1234 43fff238 bellard
1235 43fff238 bellard
                if (__put_user(retcodes[idx], rc))
1236 43fff238 bellard
                        return 1;
1237 43fff238 bellard
#if 0
1238 992f48a0 blueswir1
                flush_icache_range((abi_ulong)rc,
1239 992f48a0 blueswir1
                                   (abi_ulong)(rc + 1));
1240 43fff238 bellard
#endif
1241 f8b0aa25 bellard
                retcode = rc_addr + thumb;
1242 43fff238 bellard
        }
1243 43fff238 bellard
1244 43fff238 bellard
        env->regs[0] = usig;
1245 f8b0aa25 bellard
        env->regs[13] = frame_addr;
1246 43fff238 bellard
        env->regs[14] = retcode;
1247 43fff238 bellard
        env->regs[15] = handler & (thumb ? ~1 : ~3);
1248 75b680e5 pbrook
        env->thumb = thumb;
1249 43fff238 bellard
1250 b5ff1b31 bellard
#if 0
1251 43fff238 bellard
#ifdef TARGET_CONFIG_CPU_32
1252 43fff238 bellard
        env->cpsr = cpsr;
1253 43fff238 bellard
#endif
1254 b5ff1b31 bellard
#endif
1255 43fff238 bellard
1256 43fff238 bellard
        return 0;
1257 43fff238 bellard
}
1258 43fff238 bellard
1259 a8c33204 pbrook
static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
1260 c227f099 Anthony Liguori
                              target_sigset_t *set, CPUState *env)
1261 a8c33204 pbrook
{
1262 a8c33204 pbrook
    struct target_sigaltstack stack;
1263 a8c33204 pbrook
    int i;
1264 a8c33204 pbrook
1265 a8c33204 pbrook
    /* Clear all the bits of the ucontext we don't use.  */
1266 a8c33204 pbrook
    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
1267 a8c33204 pbrook
1268 a8c33204 pbrook
    memset(&stack, 0, sizeof(stack));
1269 a8c33204 pbrook
    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1270 a8c33204 pbrook
    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1271 a8c33204 pbrook
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1272 a8c33204 pbrook
    memcpy(&uc->tuc_stack, &stack, sizeof(stack));
1273 a8c33204 pbrook
1274 a8c33204 pbrook
    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
1275 a8c33204 pbrook
    /* FIXME: Save coprocessor signal frame.  */
1276 a8c33204 pbrook
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1277 a8c33204 pbrook
        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
1278 a8c33204 pbrook
    }
1279 a8c33204 pbrook
}
1280 a8c33204 pbrook
1281 579a97f7 bellard
/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
1282 624f7979 pbrook
static void setup_frame_v1(int usig, struct target_sigaction *ka,
1283 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *regs)
1284 43fff238 bellard
{
1285 a8c33204 pbrook
        struct sigframe_v1 *frame;
1286 579a97f7 bellard
        abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1287 a8c33204 pbrook
        int i;
1288 43fff238 bellard
1289 579a97f7 bellard
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1290 579a97f7 bellard
                return;
1291 579a97f7 bellard
1292 a8c33204 pbrook
        setup_sigcontext(&frame->sc, regs, set->sig[0]);
1293 43fff238 bellard
1294 9231944d bellard
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1295 9231944d bellard
            if (__put_user(set->sig[i], &frame->extramask[i - 1]))
1296 579a97f7 bellard
                goto end;
1297 43fff238 bellard
        }
1298 43fff238 bellard
1299 a8c33204 pbrook
        setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1300 a8c33204 pbrook
                     frame_addr + offsetof(struct sigframe_v1, retcode));
1301 579a97f7 bellard
1302 579a97f7 bellard
end:
1303 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
1304 a8c33204 pbrook
}
1305 a8c33204 pbrook
1306 624f7979 pbrook
static void setup_frame_v2(int usig, struct target_sigaction *ka,
1307 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *regs)
1308 a8c33204 pbrook
{
1309 a8c33204 pbrook
        struct sigframe_v2 *frame;
1310 a8c33204 pbrook
        abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1311 a8c33204 pbrook
1312 a8c33204 pbrook
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1313 a8c33204 pbrook
                return;
1314 a8c33204 pbrook
1315 a8c33204 pbrook
        setup_sigframe_v2(&frame->uc, set, regs);
1316 a8c33204 pbrook
1317 a8c33204 pbrook
        setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1318 a8c33204 pbrook
                     frame_addr + offsetof(struct sigframe_v2, retcode));
1319 a8c33204 pbrook
1320 a8c33204 pbrook
        unlock_user_struct(frame, frame_addr, 1);
1321 a8c33204 pbrook
}
1322 a8c33204 pbrook
1323 624f7979 pbrook
static void setup_frame(int usig, struct target_sigaction *ka,
1324 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *regs)
1325 a8c33204 pbrook
{
1326 a8c33204 pbrook
    if (get_osversion() >= 0x020612) {
1327 a8c33204 pbrook
        setup_frame_v2(usig, ka, set, regs);
1328 a8c33204 pbrook
    } else {
1329 a8c33204 pbrook
        setup_frame_v1(usig, ka, set, regs);
1330 a8c33204 pbrook
    }
1331 43fff238 bellard
}
1332 43fff238 bellard
1333 579a97f7 bellard
/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
1334 624f7979 pbrook
static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
1335 c227f099 Anthony Liguori
                              target_siginfo_t *info,
1336 c227f099 Anthony Liguori
                              target_sigset_t *set, CPUState *env)
1337 43fff238 bellard
{
1338 a745ec6d pbrook
        struct rt_sigframe_v1 *frame;
1339 579a97f7 bellard
        abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1340 a04e134a ths
        struct target_sigaltstack stack;
1341 a8c33204 pbrook
        int i;
1342 f8b0aa25 bellard
        abi_ulong info_addr, uc_addr;
1343 43fff238 bellard
1344 579a97f7 bellard
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1345 edf779ff bellard
            return /* 1 */;
1346 edf779ff bellard
1347 a745ec6d pbrook
        info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1348 a8c33204 pbrook
        __put_user(info_addr, &frame->pinfo);
1349 a745ec6d pbrook
        uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1350 a8c33204 pbrook
        __put_user(uc_addr, &frame->puc);
1351 a8c33204 pbrook
        copy_siginfo_to_user(&frame->info, info);
1352 43fff238 bellard
1353 43fff238 bellard
        /* Clear all the bits of the ucontext we don't use.  */
1354 a745ec6d pbrook
        memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
1355 43fff238 bellard
1356 a04e134a ths
        memset(&stack, 0, sizeof(stack));
1357 a04e134a ths
        __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1358 a04e134a ths
        __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1359 a04e134a ths
        __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1360 775b58d8 bellard
        memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
1361 a04e134a ths
1362 a8c33204 pbrook
        setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1363 9231944d bellard
        for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1364 b8076a74 bellard
            if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
1365 579a97f7 bellard
                goto end;
1366 9231944d bellard
        }
1367 43fff238 bellard
1368 a8c33204 pbrook
        setup_return(env, ka, &frame->retcode, frame_addr, usig,
1369 a8c33204 pbrook
                     frame_addr + offsetof(struct rt_sigframe_v1, retcode));
1370 a745ec6d pbrook
1371 a8c33204 pbrook
        env->regs[1] = info_addr;
1372 a8c33204 pbrook
        env->regs[2] = uc_addr;
1373 a745ec6d pbrook
1374 a745ec6d pbrook
end:
1375 a745ec6d pbrook
        unlock_user_struct(frame, frame_addr, 1);
1376 a745ec6d pbrook
}
1377 a745ec6d pbrook
1378 624f7979 pbrook
static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
1379 c227f099 Anthony Liguori
                              target_siginfo_t *info,
1380 c227f099 Anthony Liguori
                              target_sigset_t *set, CPUState *env)
1381 a745ec6d pbrook
{
1382 a745ec6d pbrook
        struct rt_sigframe_v2 *frame;
1383 a745ec6d pbrook
        abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1384 a745ec6d pbrook
        abi_ulong info_addr, uc_addr;
1385 a745ec6d pbrook
1386 a745ec6d pbrook
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1387 a745ec6d pbrook
            return /* 1 */;
1388 a745ec6d pbrook
1389 a745ec6d pbrook
        info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1390 a745ec6d pbrook
        uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1391 a8c33204 pbrook
        copy_siginfo_to_user(&frame->info, info);
1392 a745ec6d pbrook
1393 a8c33204 pbrook
        setup_sigframe_v2(&frame->uc, set, env);
1394 a745ec6d pbrook
1395 a8c33204 pbrook
        setup_return(env, ka, &frame->retcode, frame_addr, usig,
1396 a8c33204 pbrook
                     frame_addr + offsetof(struct rt_sigframe_v2, retcode));
1397 a745ec6d pbrook
1398 a8c33204 pbrook
        env->regs[1] = info_addr;
1399 a8c33204 pbrook
        env->regs[2] = uc_addr;
1400 43fff238 bellard
1401 579a97f7 bellard
        unlock_user_struct(frame, frame_addr, 1);
1402 43fff238 bellard
}
1403 43fff238 bellard
1404 624f7979 pbrook
static void setup_rt_frame(int usig, struct target_sigaction *ka,
1405 c227f099 Anthony Liguori
                           target_siginfo_t *info,
1406 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
1407 a745ec6d pbrook
{
1408 a745ec6d pbrook
    if (get_osversion() >= 0x020612) {
1409 a745ec6d pbrook
        setup_rt_frame_v2(usig, ka, info, set, env);
1410 a745ec6d pbrook
    } else {
1411 a745ec6d pbrook
        setup_rt_frame_v1(usig, ka, info, set, env);
1412 a745ec6d pbrook
    }
1413 a745ec6d pbrook
}
1414 a745ec6d pbrook
1415 43fff238 bellard
static int
1416 43fff238 bellard
restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
1417 43fff238 bellard
{
1418 43fff238 bellard
        int err = 0;
1419 b5ff1b31 bellard
        uint32_t cpsr;
1420 43fff238 bellard
1421 43fff238 bellard
        __get_user_error(env->regs[0], &sc->arm_r0, err);
1422 43fff238 bellard
        __get_user_error(env->regs[1], &sc->arm_r1, err);
1423 43fff238 bellard
        __get_user_error(env->regs[2], &sc->arm_r2, err);
1424 43fff238 bellard
        __get_user_error(env->regs[3], &sc->arm_r3, err);
1425 43fff238 bellard
        __get_user_error(env->regs[4], &sc->arm_r4, err);
1426 43fff238 bellard
        __get_user_error(env->regs[5], &sc->arm_r5, err);
1427 43fff238 bellard
        __get_user_error(env->regs[6], &sc->arm_r6, err);
1428 43fff238 bellard
        __get_user_error(env->regs[7], &sc->arm_r7, err);
1429 43fff238 bellard
        __get_user_error(env->regs[8], &sc->arm_r8, err);
1430 43fff238 bellard
        __get_user_error(env->regs[9], &sc->arm_r9, err);
1431 43fff238 bellard
        __get_user_error(env->regs[10], &sc->arm_r10, err);
1432 43fff238 bellard
        __get_user_error(env->regs[11], &sc->arm_fp, err);
1433 43fff238 bellard
        __get_user_error(env->regs[12], &sc->arm_ip, err);
1434 43fff238 bellard
        __get_user_error(env->regs[13], &sc->arm_sp, err);
1435 43fff238 bellard
        __get_user_error(env->regs[14], &sc->arm_lr, err);
1436 43fff238 bellard
        __get_user_error(env->regs[15], &sc->arm_pc, err);
1437 43fff238 bellard
#ifdef TARGET_CONFIG_CPU_32
1438 b5ff1b31 bellard
        __get_user_error(cpsr, &sc->arm_cpsr, err);
1439 75b680e5 pbrook
        cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
1440 43fff238 bellard
#endif
1441 43fff238 bellard
1442 43fff238 bellard
        err |= !valid_user_regs(env);
1443 43fff238 bellard
1444 43fff238 bellard
        return err;
1445 43fff238 bellard
}
1446 43fff238 bellard
1447 dc7eea67 aurel32
static long do_sigreturn_v1(CPUState *env)
1448 43fff238 bellard
{
1449 f8b0aa25 bellard
        abi_ulong frame_addr;
1450 a8c33204 pbrook
        struct sigframe_v1 *frame;
1451 c227f099 Anthony Liguori
        target_sigset_t set;
1452 43fff238 bellard
        sigset_t host_set;
1453 9231944d bellard
        int i;
1454 43fff238 bellard
1455 43fff238 bellard
        /*
1456 43fff238 bellard
         * Since we stacked the signal on a 64-bit boundary,
1457 43fff238 bellard
         * then 'sp' should be word aligned here.  If it's
1458 43fff238 bellard
         * not, then the user is trying to mess with us.
1459 43fff238 bellard
         */
1460 43fff238 bellard
        if (env->regs[13] & 7)
1461 43fff238 bellard
                goto badframe;
1462 43fff238 bellard
1463 f8b0aa25 bellard
        frame_addr = env->regs[13];
1464 f8b0aa25 bellard
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1465 f8b0aa25 bellard
                goto badframe;
1466 43fff238 bellard
1467 9231944d bellard
        if (__get_user(set.sig[0], &frame->sc.oldmask))
1468 9231944d bellard
            goto badframe;
1469 9231944d bellard
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1470 9231944d bellard
            if (__get_user(set.sig[i], &frame->extramask[i - 1]))
1471 9231944d bellard
                goto badframe;
1472 9231944d bellard
        }
1473 43fff238 bellard
1474 9231944d bellard
        target_to_host_sigset_internal(&host_set, &set);
1475 43fff238 bellard
        sigprocmask(SIG_SETMASK, &host_set, NULL);
1476 43fff238 bellard
1477 43fff238 bellard
        if (restore_sigcontext(env, &frame->sc))
1478 43fff238 bellard
                goto badframe;
1479 43fff238 bellard
1480 43fff238 bellard
#if 0
1481 43fff238 bellard
        /* Send SIGTRAP if we're single-stepping */
1482 43fff238 bellard
        if (ptrace_cancel_bpt(current))
1483 43fff238 bellard
                send_sig(SIGTRAP, current, 1);
1484 43fff238 bellard
#endif
1485 f8b0aa25 bellard
        unlock_user_struct(frame, frame_addr, 0);
1486 f8b0aa25 bellard
        return env->regs[0];
1487 43fff238 bellard
1488 43fff238 bellard
badframe:
1489 f8b0aa25 bellard
        unlock_user_struct(frame, frame_addr, 0);
1490 43fff238 bellard
        force_sig(SIGSEGV /* , current */);
1491 43fff238 bellard
        return 0;
1492 43fff238 bellard
}
1493 43fff238 bellard
1494 a8c33204 pbrook
static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
1495 a8c33204 pbrook
                                 struct target_ucontext_v2 *uc)
1496 a8c33204 pbrook
{
1497 a8c33204 pbrook
    sigset_t host_set;
1498 a8c33204 pbrook
1499 a8c33204 pbrook
    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
1500 a8c33204 pbrook
    sigprocmask(SIG_SETMASK, &host_set, NULL);
1501 a8c33204 pbrook
1502 a8c33204 pbrook
    if (restore_sigcontext(env, &uc->tuc_mcontext))
1503 a8c33204 pbrook
        return 1;
1504 a8c33204 pbrook
1505 a8c33204 pbrook
    if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1506 a8c33204 pbrook
        return 1;
1507 a8c33204 pbrook
1508 a8c33204 pbrook
#if 0
1509 a8c33204 pbrook
    /* Send SIGTRAP if we're single-stepping */
1510 a8c33204 pbrook
    if (ptrace_cancel_bpt(current))
1511 a8c33204 pbrook
            send_sig(SIGTRAP, current, 1);
1512 a8c33204 pbrook
#endif
1513 a8c33204 pbrook
1514 a8c33204 pbrook
    return 0;
1515 a8c33204 pbrook
}
1516 a8c33204 pbrook
1517 dc7eea67 aurel32
static long do_sigreturn_v2(CPUState *env)
1518 a8c33204 pbrook
{
1519 a8c33204 pbrook
        abi_ulong frame_addr;
1520 a8c33204 pbrook
        struct sigframe_v2 *frame;
1521 a8c33204 pbrook
1522 a8c33204 pbrook
        /*
1523 a8c33204 pbrook
         * Since we stacked the signal on a 64-bit boundary,
1524 a8c33204 pbrook
         * then 'sp' should be word aligned here.  If it's
1525 a8c33204 pbrook
         * not, then the user is trying to mess with us.
1526 a8c33204 pbrook
         */
1527 a8c33204 pbrook
        if (env->regs[13] & 7)
1528 a8c33204 pbrook
                goto badframe;
1529 a8c33204 pbrook
1530 a8c33204 pbrook
        frame_addr = env->regs[13];
1531 a8c33204 pbrook
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1532 a8c33204 pbrook
                goto badframe;
1533 a8c33204 pbrook
1534 a8c33204 pbrook
        if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
1535 a8c33204 pbrook
                goto badframe;
1536 a8c33204 pbrook
1537 a8c33204 pbrook
        unlock_user_struct(frame, frame_addr, 0);
1538 a8c33204 pbrook
        return env->regs[0];
1539 a8c33204 pbrook
1540 a8c33204 pbrook
badframe:
1541 a8c33204 pbrook
        unlock_user_struct(frame, frame_addr, 0);
1542 a8c33204 pbrook
        force_sig(SIGSEGV /* , current */);
1543 a8c33204 pbrook
        return 0;
1544 a8c33204 pbrook
}
1545 a8c33204 pbrook
1546 a8c33204 pbrook
long do_sigreturn(CPUState *env)
1547 a8c33204 pbrook
{
1548 a8c33204 pbrook
    if (get_osversion() >= 0x020612) {
1549 a8c33204 pbrook
        return do_sigreturn_v2(env);
1550 a8c33204 pbrook
    } else {
1551 a8c33204 pbrook
        return do_sigreturn_v1(env);
1552 a8c33204 pbrook
    }
1553 a8c33204 pbrook
}
1554 a8c33204 pbrook
1555 dc7eea67 aurel32
static long do_rt_sigreturn_v1(CPUState *env)
1556 43fff238 bellard
{
1557 f8b0aa25 bellard
        abi_ulong frame_addr;
1558 a745ec6d pbrook
        struct rt_sigframe_v1 *frame;
1559 a745ec6d pbrook
        sigset_t host_set;
1560 a745ec6d pbrook
1561 a745ec6d pbrook
        /*
1562 a745ec6d pbrook
         * Since we stacked the signal on a 64-bit boundary,
1563 a745ec6d pbrook
         * then 'sp' should be word aligned here.  If it's
1564 a745ec6d pbrook
         * not, then the user is trying to mess with us.
1565 a745ec6d pbrook
         */
1566 a745ec6d pbrook
        if (env->regs[13] & 7)
1567 a745ec6d pbrook
                goto badframe;
1568 a745ec6d pbrook
1569 a745ec6d pbrook
        frame_addr = env->regs[13];
1570 a745ec6d pbrook
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1571 a745ec6d pbrook
                goto badframe;
1572 a745ec6d pbrook
1573 a745ec6d pbrook
        target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
1574 a745ec6d pbrook
        sigprocmask(SIG_SETMASK, &host_set, NULL);
1575 a745ec6d pbrook
1576 a745ec6d pbrook
        if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
1577 a745ec6d pbrook
                goto badframe;
1578 a745ec6d pbrook
1579 a745ec6d pbrook
        if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1580 a745ec6d pbrook
                goto badframe;
1581 a745ec6d pbrook
1582 a745ec6d pbrook
#if 0
1583 a745ec6d pbrook
        /* Send SIGTRAP if we're single-stepping */
1584 a745ec6d pbrook
        if (ptrace_cancel_bpt(current))
1585 a745ec6d pbrook
                send_sig(SIGTRAP, current, 1);
1586 a745ec6d pbrook
#endif
1587 a745ec6d pbrook
        unlock_user_struct(frame, frame_addr, 0);
1588 a745ec6d pbrook
        return env->regs[0];
1589 a745ec6d pbrook
1590 a745ec6d pbrook
badframe:
1591 a745ec6d pbrook
        unlock_user_struct(frame, frame_addr, 0);
1592 a745ec6d pbrook
        force_sig(SIGSEGV /* , current */);
1593 a745ec6d pbrook
        return 0;
1594 a745ec6d pbrook
}
1595 a745ec6d pbrook
1596 dc7eea67 aurel32
static long do_rt_sigreturn_v2(CPUState *env)
1597 a745ec6d pbrook
{
1598 a745ec6d pbrook
        abi_ulong frame_addr;
1599 a745ec6d pbrook
        struct rt_sigframe_v2 *frame;
1600 43fff238 bellard
1601 43fff238 bellard
        /*
1602 43fff238 bellard
         * Since we stacked the signal on a 64-bit boundary,
1603 43fff238 bellard
         * then 'sp' should be word aligned here.  If it's
1604 43fff238 bellard
         * not, then the user is trying to mess with us.
1605 43fff238 bellard
         */
1606 43fff238 bellard
        if (env->regs[13] & 7)
1607 43fff238 bellard
                goto badframe;
1608 43fff238 bellard
1609 f8b0aa25 bellard
        frame_addr = env->regs[13];
1610 f8b0aa25 bellard
        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1611 f8b0aa25 bellard
                goto badframe;
1612 43fff238 bellard
1613 a8c33204 pbrook
        if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
1614 a8c33204 pbrook
                goto badframe;
1615 a04e134a ths
1616 f8b0aa25 bellard
        unlock_user_struct(frame, frame_addr, 0);
1617 43fff238 bellard
        return env->regs[0];
1618 43fff238 bellard
1619 43fff238 bellard
badframe:
1620 f8b0aa25 bellard
        unlock_user_struct(frame, frame_addr, 0);
1621 43fff238 bellard
        force_sig(SIGSEGV /* , current */);
1622 43fff238 bellard
        return 0;
1623 43fff238 bellard
}
1624 43fff238 bellard
1625 a745ec6d pbrook
long do_rt_sigreturn(CPUState *env)
1626 a745ec6d pbrook
{
1627 a745ec6d pbrook
    if (get_osversion() >= 0x020612) {
1628 a745ec6d pbrook
        return do_rt_sigreturn_v2(env);
1629 a745ec6d pbrook
    } else {
1630 a745ec6d pbrook
        return do_rt_sigreturn_v1(env);
1631 a745ec6d pbrook
    }
1632 a745ec6d pbrook
}
1633 a745ec6d pbrook
1634 6d5e216d bellard
#elif defined(TARGET_SPARC)
1635 80a9d035 bellard
1636 6d5e216d bellard
#define __SUNOS_MAXWIN   31
1637 6d5e216d bellard
1638 6d5e216d bellard
/* This is what SunOS does, so shall I. */
1639 6d5e216d bellard
struct target_sigcontext {
1640 992f48a0 blueswir1
        abi_ulong sigc_onstack;      /* state to restore */
1641 6d5e216d bellard
1642 992f48a0 blueswir1
        abi_ulong sigc_mask;         /* sigmask to restore */
1643 992f48a0 blueswir1
        abi_ulong sigc_sp;           /* stack pointer */
1644 992f48a0 blueswir1
        abi_ulong sigc_pc;           /* program counter */
1645 992f48a0 blueswir1
        abi_ulong sigc_npc;          /* next program counter */
1646 992f48a0 blueswir1
        abi_ulong sigc_psr;          /* for condition codes etc */
1647 992f48a0 blueswir1
        abi_ulong sigc_g1;           /* User uses these two registers */
1648 992f48a0 blueswir1
        abi_ulong sigc_o0;           /* within the trampoline code. */
1649 6d5e216d bellard
1650 6d5e216d bellard
        /* Now comes information regarding the users window set
1651 6d5e216d bellard
         * at the time of the signal.
1652 6d5e216d bellard
         */
1653 992f48a0 blueswir1
        abi_ulong sigc_oswins;       /* outstanding windows */
1654 6d5e216d bellard
1655 6d5e216d bellard
        /* stack ptrs for each regwin buf */
1656 6d5e216d bellard
        char *sigc_spbuf[__SUNOS_MAXWIN];
1657 6d5e216d bellard
1658 6d5e216d bellard
        /* Windows to restore after signal */
1659 6d5e216d bellard
        struct {
1660 992f48a0 blueswir1
                abi_ulong locals[8];
1661 992f48a0 blueswir1
                abi_ulong ins[8];
1662 6d5e216d bellard
        } sigc_wbuf[__SUNOS_MAXWIN];
1663 6d5e216d bellard
};
1664 6d5e216d bellard
/* A Sparc stack frame */
1665 6d5e216d bellard
struct sparc_stackf {
1666 992f48a0 blueswir1
        abi_ulong locals[8];
1667 992f48a0 blueswir1
        abi_ulong ins[6];
1668 6d5e216d bellard
        struct sparc_stackf *fp;
1669 992f48a0 blueswir1
        abi_ulong callers_pc;
1670 6d5e216d bellard
        char *structptr;
1671 992f48a0 blueswir1
        abi_ulong xargs[6];
1672 992f48a0 blueswir1
        abi_ulong xxargs[1];
1673 6d5e216d bellard
};
1674 6d5e216d bellard
1675 6d5e216d bellard
typedef struct {
1676 6d5e216d bellard
        struct {
1677 992f48a0 blueswir1
                abi_ulong psr;
1678 992f48a0 blueswir1
                abi_ulong pc;
1679 992f48a0 blueswir1
                abi_ulong npc;
1680 992f48a0 blueswir1
                abi_ulong y;
1681 992f48a0 blueswir1
                abi_ulong u_regs[16]; /* globals and ins */
1682 6d5e216d bellard
        }               si_regs;
1683 6d5e216d bellard
        int             si_mask;
1684 6d5e216d bellard
} __siginfo_t;
1685 6d5e216d bellard
1686 6d5e216d bellard
typedef struct {
1687 6d5e216d bellard
        unsigned   long si_float_regs [32];
1688 6d5e216d bellard
        unsigned   long si_fsr;
1689 6d5e216d bellard
        unsigned   long si_fpqdepth;
1690 6d5e216d bellard
        struct {
1691 6d5e216d bellard
                unsigned long *insn_addr;
1692 6d5e216d bellard
                unsigned long insn;
1693 6d5e216d bellard
        } si_fpqueue [16];
1694 c227f099 Anthony Liguori
} qemu_siginfo_fpu_t;
1695 6d5e216d bellard
1696 6d5e216d bellard
1697 6d5e216d bellard
struct target_signal_frame {
1698 6d5e216d bellard
        struct sparc_stackf        ss;
1699 6d5e216d bellard
        __siginfo_t                info;
1700 f8b0aa25 bellard
        abi_ulong               fpu_save;
1701 992f48a0 blueswir1
        abi_ulong                insns[2] __attribute__ ((aligned (8)));
1702 992f48a0 blueswir1
        abi_ulong                extramask[TARGET_NSIG_WORDS - 1];
1703 992f48a0 blueswir1
        abi_ulong                extra_size; /* Should be 0 */
1704 c227f099 Anthony Liguori
        qemu_siginfo_fpu_t        fpu_state;
1705 6d5e216d bellard
};
1706 6d5e216d bellard
struct target_rt_signal_frame {
1707 6d5e216d bellard
        struct sparc_stackf        ss;
1708 6d5e216d bellard
        siginfo_t                info;
1709 992f48a0 blueswir1
        abi_ulong                regs[20];
1710 6d5e216d bellard
        sigset_t                mask;
1711 f8b0aa25 bellard
        abi_ulong               fpu_save;
1712 6d5e216d bellard
        unsigned int                insns[2];
1713 6d5e216d bellard
        stack_t                        stack;
1714 6d5e216d bellard
        unsigned int                extra_size; /* Should be 0 */
1715 c227f099 Anthony Liguori
        qemu_siginfo_fpu_t        fpu_state;
1716 6d5e216d bellard
};
1717 6d5e216d bellard
1718 e80cfcfc bellard
#define UREG_O0        16
1719 e80cfcfc bellard
#define UREG_O6        22
1720 e80cfcfc bellard
#define UREG_I0        0
1721 e80cfcfc bellard
#define UREG_I1        1
1722 e80cfcfc bellard
#define UREG_I2        2
1723 5bfb56b2 blueswir1
#define UREG_I3        3
1724 5bfb56b2 blueswir1
#define UREG_I4        4
1725 5bfb56b2 blueswir1
#define UREG_I5        5
1726 e80cfcfc bellard
#define UREG_I6        6
1727 e80cfcfc bellard
#define UREG_I7        7
1728 e80cfcfc bellard
#define UREG_L0               8
1729 6d5e216d bellard
#define UREG_FP        UREG_I6
1730 6d5e216d bellard
#define UREG_SP        UREG_O6
1731 6d5e216d bellard
1732 624f7979 pbrook
static inline abi_ulong get_sigframe(struct target_sigaction *sa, 
1733 459a4017 bellard
                                     CPUState *env, unsigned long framesize)
1734 6d5e216d bellard
{
1735 459a4017 bellard
        abi_ulong sp;
1736 6d5e216d bellard
1737 6d5e216d bellard
        sp = env->regwptr[UREG_FP];
1738 6d5e216d bellard
1739 6d5e216d bellard
        /* This is the X/Open sanctioned signal stack switching.  */
1740 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_ONSTACK) {
1741 a04e134a ths
            if (!on_sig_stack(sp)
1742 a04e134a ths
                && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
1743 a04e134a ths
                sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
1744 6d5e216d bellard
        }
1745 459a4017 bellard
        return sp - framesize;
1746 6d5e216d bellard
}
1747 6d5e216d bellard
1748 6d5e216d bellard
static int
1749 992f48a0 blueswir1
setup___siginfo(__siginfo_t *si, CPUState *env, abi_ulong mask)
1750 6d5e216d bellard
{
1751 6d5e216d bellard
        int err = 0, i;
1752 6d5e216d bellard
1753 6d5e216d bellard
        err |= __put_user(env->psr, &si->si_regs.psr);
1754 6d5e216d bellard
        err |= __put_user(env->pc, &si->si_regs.pc);
1755 6d5e216d bellard
        err |= __put_user(env->npc, &si->si_regs.npc);
1756 6d5e216d bellard
        err |= __put_user(env->y, &si->si_regs.y);
1757 a315a145 bellard
        for (i=0; i < 8; i++) {
1758 6d5e216d bellard
                err |= __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
1759 6d5e216d bellard
        }
1760 a315a145 bellard
        for (i=0; i < 8; i++) {
1761 e80cfcfc bellard
                err |= __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
1762 6d5e216d bellard
        }
1763 6d5e216d bellard
        err |= __put_user(mask, &si->si_mask);
1764 6d5e216d bellard
        return err;
1765 6d5e216d bellard
}
1766 e80cfcfc bellard
1767 80a9d035 bellard
#if 0
1768 6d5e216d bellard
static int
1769 6d5e216d bellard
setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
1770 6d5e216d bellard
                 CPUState *env, unsigned long mask)
1771 6d5e216d bellard
{
1772 6d5e216d bellard
        int err = 0;
1773 6d5e216d bellard

1774 6d5e216d bellard
        err |= __put_user(mask, &sc->sigc_mask);
1775 6d5e216d bellard
        err |= __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
1776 6d5e216d bellard
        err |= __put_user(env->pc, &sc->sigc_pc);
1777 6d5e216d bellard
        err |= __put_user(env->npc, &sc->sigc_npc);
1778 6d5e216d bellard
        err |= __put_user(env->psr, &sc->sigc_psr);
1779 6d5e216d bellard
        err |= __put_user(env->gregs[1], &sc->sigc_g1);
1780 6d5e216d bellard
        err |= __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
1781 6d5e216d bellard

1782 6d5e216d bellard
        return err;
1783 6d5e216d bellard
}
1784 80a9d035 bellard
#endif
1785 6d5e216d bellard
#define NF_ALIGNEDSZ  (((sizeof(struct target_signal_frame) + 7) & (~7)))
1786 6d5e216d bellard
1787 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
1788 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
1789 6d5e216d bellard
{
1790 459a4017 bellard
        abi_ulong sf_addr;
1791 6d5e216d bellard
        struct target_signal_frame *sf;
1792 6d5e216d bellard
        int sigframe_size, err, i;
1793 6d5e216d bellard
1794 6d5e216d bellard
        /* 1. Make sure everything is clean */
1795 6d5e216d bellard
        //synchronize_user_stack();
1796 6d5e216d bellard
1797 6d5e216d bellard
        sigframe_size = NF_ALIGNEDSZ;
1798 459a4017 bellard
        sf_addr = get_sigframe(ka, env, sigframe_size);
1799 6d5e216d bellard
1800 459a4017 bellard
        sf = lock_user(VERIFY_WRITE, sf_addr, 
1801 459a4017 bellard
                       sizeof(struct target_signal_frame), 0);
1802 459a4017 bellard
        if (!sf)
1803 459a4017 bellard
                goto sigsegv;
1804 459a4017 bellard
                
1805 e80cfcfc bellard
        //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
1806 6d5e216d bellard
#if 0
1807 6d5e216d bellard
        if (invalid_frame_pointer(sf, sigframe_size))
1808 6d5e216d bellard
                goto sigill_and_return;
1809 6d5e216d bellard
#endif
1810 6d5e216d bellard
        /* 2. Save the current process state */
1811 6d5e216d bellard
        err = setup___siginfo(&sf->info, env, set->sig[0]);
1812 6d5e216d bellard
        err |= __put_user(0, &sf->extra_size);
1813 6d5e216d bellard
1814 6d5e216d bellard
        //err |= save_fpu_state(regs, &sf->fpu_state);
1815 6d5e216d bellard
        //err |= __put_user(&sf->fpu_state, &sf->fpu_save);
1816 6d5e216d bellard
1817 6d5e216d bellard
        err |= __put_user(set->sig[0], &sf->info.si_mask);
1818 6d5e216d bellard
        for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
1819 6d5e216d bellard
                err |= __put_user(set->sig[i + 1], &sf->extramask[i]);
1820 6d5e216d bellard
        }
1821 6d5e216d bellard
1822 a315a145 bellard
        for (i = 0; i < 8; i++) {
1823 e80cfcfc bellard
                  err |= __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
1824 6d5e216d bellard
        }
1825 a315a145 bellard
        for (i = 0; i < 8; i++) {
1826 e80cfcfc bellard
                  err |= __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
1827 6d5e216d bellard
        }
1828 6d5e216d bellard
        if (err)
1829 6d5e216d bellard
                goto sigsegv;
1830 6d5e216d bellard
1831 6d5e216d bellard
        /* 3. signal handler back-trampoline and parameters */
1832 459a4017 bellard
        env->regwptr[UREG_FP] = sf_addr;
1833 6d5e216d bellard
        env->regwptr[UREG_I0] = sig;
1834 459a4017 bellard
        env->regwptr[UREG_I1] = sf_addr + 
1835 459a4017 bellard
                offsetof(struct target_signal_frame, info);
1836 459a4017 bellard
        env->regwptr[UREG_I2] = sf_addr + 
1837 459a4017 bellard
                offsetof(struct target_signal_frame, info);
1838 6d5e216d bellard
1839 6d5e216d bellard
        /* 4. signal handler */
1840 624f7979 pbrook
        env->pc = ka->_sa_handler;
1841 6d5e216d bellard
        env->npc = (env->pc + 4);
1842 6d5e216d bellard
        /* 5. return to kernel instructions */
1843 624f7979 pbrook
        if (ka->sa_restorer)
1844 624f7979 pbrook
                env->regwptr[UREG_I7] = ka->sa_restorer;
1845 6d5e216d bellard
        else {
1846 775b58d8 bellard
                uint32_t val32;
1847 459a4017 bellard
1848 459a4017 bellard
                env->regwptr[UREG_I7] = sf_addr + 
1849 459a4017 bellard
                        offsetof(struct target_signal_frame, insns) - 2 * 4;
1850 6d5e216d bellard
1851 6d5e216d bellard
                /* mov __NR_sigreturn, %g1 */
1852 775b58d8 bellard
                val32 = 0x821020d8;
1853 775b58d8 bellard
                err |= __put_user(val32, &sf->insns[0]);
1854 6d5e216d bellard
1855 6d5e216d bellard
                /* t 0x10 */
1856 775b58d8 bellard
                val32 = 0x91d02010;
1857 775b58d8 bellard
                err |= __put_user(val32, &sf->insns[1]);
1858 6d5e216d bellard
                if (err)
1859 6d5e216d bellard
                        goto sigsegv;
1860 6d5e216d bellard
1861 6d5e216d bellard
                /* Flush instruction space. */
1862 6d5e216d bellard
                //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
1863 80a9d035 bellard
                //                tb_flush(env);
1864 6d5e216d bellard
        }
1865 459a4017 bellard
        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
1866 6d5e216d bellard
        return;
1867 459a4017 bellard
#if 0
1868 459a4017 bellard
sigill_and_return:
1869 6d5e216d bellard
        force_sig(TARGET_SIGILL);
1870 459a4017 bellard
#endif
1871 6d5e216d bellard
sigsegv:
1872 e80cfcfc bellard
        //fprintf(stderr, "force_sig\n");
1873 459a4017 bellard
        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
1874 6d5e216d bellard
        force_sig(TARGET_SIGSEGV);
1875 6d5e216d bellard
}
1876 6d5e216d bellard
static inline int
1877 c227f099 Anthony Liguori
restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu)
1878 6d5e216d bellard
{
1879 6d5e216d bellard
        int err;
1880 6d5e216d bellard
#if 0
1881 6d5e216d bellard
#ifdef CONFIG_SMP
1882 6d5e216d bellard
        if (current->flags & PF_USEDFPU)
1883 6d5e216d bellard
                regs->psr &= ~PSR_EF;
1884 6d5e216d bellard
#else
1885 6d5e216d bellard
        if (current == last_task_used_math) {
1886 6d5e216d bellard
                last_task_used_math = 0;
1887 6d5e216d bellard
                regs->psr &= ~PSR_EF;
1888 6d5e216d bellard
        }
1889 6d5e216d bellard
#endif
1890 6d5e216d bellard
        current->used_math = 1;
1891 6d5e216d bellard
        current->flags &= ~PF_USEDFPU;
1892 6d5e216d bellard
#endif
1893 6d5e216d bellard
#if 0
1894 6d5e216d bellard
        if (verify_area (VERIFY_READ, fpu, sizeof(*fpu)))
1895 6d5e216d bellard
                return -EFAULT;
1896 6d5e216d bellard
#endif
1897 6d5e216d bellard
1898 fafffaef bellard
#if 0
1899 fafffaef bellard
        /* XXX: incorrect */
1900 6d5e216d bellard
        err = __copy_from_user(&env->fpr[0], &fpu->si_float_regs[0],
1901 6d5e216d bellard
                                     (sizeof(unsigned long) * 32));
1902 fafffaef bellard
#endif
1903 6d5e216d bellard
        err |= __get_user(env->fsr, &fpu->si_fsr);
1904 6d5e216d bellard
#if 0
1905 6d5e216d bellard
        err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
1906 6d5e216d bellard
        if (current->thread.fpqdepth != 0)
1907 6d5e216d bellard
                err |= __copy_from_user(&current->thread.fpqueue[0],
1908 6d5e216d bellard
                                        &fpu->si_fpqueue[0],
1909 6d5e216d bellard
                                        ((sizeof(unsigned long) +
1910 6d5e216d bellard
                                        (sizeof(unsigned long *)))*16));
1911 6d5e216d bellard
#endif
1912 6d5e216d bellard
        return err;
1913 6d5e216d bellard
}
1914 6d5e216d bellard
1915 6d5e216d bellard
1916 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
1917 c227f099 Anthony Liguori
                           target_siginfo_t *info,
1918 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
1919 6d5e216d bellard
{
1920 6d5e216d bellard
    fprintf(stderr, "setup_rt_frame: not implemented\n");
1921 6d5e216d bellard
}
1922 6d5e216d bellard
1923 6d5e216d bellard
long do_sigreturn(CPUState *env)
1924 6d5e216d bellard
{
1925 f8b0aa25 bellard
        abi_ulong sf_addr;
1926 6d5e216d bellard
        struct target_signal_frame *sf;
1927 e80cfcfc bellard
        uint32_t up_psr, pc, npc;
1928 c227f099 Anthony Liguori
        target_sigset_t set;
1929 e80cfcfc bellard
        sigset_t host_set;
1930 f8b0aa25 bellard
        abi_ulong fpu_save_addr;
1931 e80cfcfc bellard
        int err, i;
1932 6d5e216d bellard
1933 f8b0aa25 bellard
        sf_addr = env->regwptr[UREG_FP];
1934 f8b0aa25 bellard
        if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
1935 f8b0aa25 bellard
                goto segv_and_exit;
1936 80a9d035 bellard
#if 0
1937 e80cfcfc bellard
        fprintf(stderr, "sigreturn\n");
1938 e80cfcfc bellard
        fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
1939 80a9d035 bellard
#endif
1940 e80cfcfc bellard
        //cpu_dump_state(env, stderr, fprintf, 0);
1941 6d5e216d bellard
1942 6d5e216d bellard
        /* 1. Make sure we are not getting garbage from the user */
1943 6d5e216d bellard
1944 f8b0aa25 bellard
        if (sf_addr & 3)
1945 6d5e216d bellard
                goto segv_and_exit;
1946 6d5e216d bellard
1947 6d5e216d bellard
        err = __get_user(pc,  &sf->info.si_regs.pc);
1948 6d5e216d bellard
        err |= __get_user(npc, &sf->info.si_regs.npc);
1949 6d5e216d bellard
1950 6d5e216d bellard
        if ((pc | npc) & 3)
1951 6d5e216d bellard
                goto segv_and_exit;
1952 6d5e216d bellard
1953 6d5e216d bellard
        /* 2. Restore the state */
1954 e80cfcfc bellard
        err |= __get_user(up_psr, &sf->info.si_regs.psr);
1955 e80cfcfc bellard
1956 6d5e216d bellard
        /* User can only change condition codes and FPU enabling in %psr. */
1957 a315a145 bellard
        env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
1958 a315a145 bellard
                  | (env->psr & ~(PSR_ICC /* | PSR_EF */));
1959 a315a145 bellard
1960 a315a145 bellard
        env->pc = pc;
1961 a315a145 bellard
        env->npc = npc;
1962 e80cfcfc bellard
        err |= __get_user(env->y, &sf->info.si_regs.y);
1963 a315a145 bellard
        for (i=0; i < 8; i++) {
1964 e80cfcfc bellard
                err |= __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
1965 e80cfcfc bellard
        }
1966 a315a145 bellard
        for (i=0; i < 8; i++) {
1967 e80cfcfc bellard
                err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
1968 e80cfcfc bellard
        }
1969 6d5e216d bellard
1970 f8b0aa25 bellard
        err |= __get_user(fpu_save_addr, &sf->fpu_save);
1971 6d5e216d bellard
1972 e80cfcfc bellard
        //if (fpu_save)
1973 e80cfcfc bellard
        //        err |= restore_fpu_state(env, fpu_save);
1974 6d5e216d bellard
1975 6d5e216d bellard
        /* This is pretty much atomic, no amount locking would prevent
1976 6d5e216d bellard
         * the races which exist anyways.
1977 6d5e216d bellard
         */
1978 6d5e216d bellard
        err |= __get_user(set.sig[0], &sf->info.si_mask);
1979 e80cfcfc bellard
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1980 e80cfcfc bellard
            err |= (__get_user(set.sig[i], &sf->extramask[i - 1]));
1981 e80cfcfc bellard
        }
1982 e80cfcfc bellard
1983 e80cfcfc bellard
        target_to_host_sigset_internal(&host_set, &set);
1984 e80cfcfc bellard
        sigprocmask(SIG_SETMASK, &host_set, NULL);
1985 6d5e216d bellard
1986 6d5e216d bellard
        if (err)
1987 6d5e216d bellard
                goto segv_and_exit;
1988 f8b0aa25 bellard
        unlock_user_struct(sf, sf_addr, 0);
1989 6d5e216d bellard
        return env->regwptr[0];
1990 6d5e216d bellard
1991 6d5e216d bellard
segv_and_exit:
1992 f8b0aa25 bellard
        unlock_user_struct(sf, sf_addr, 0);
1993 6d5e216d bellard
        force_sig(TARGET_SIGSEGV);
1994 6d5e216d bellard
}
1995 6d5e216d bellard
1996 6d5e216d bellard
long do_rt_sigreturn(CPUState *env)
1997 6d5e216d bellard
{
1998 6d5e216d bellard
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
1999 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2000 6d5e216d bellard
}
2001 6d5e216d bellard
2002 459a4017 bellard
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
2003 5bfb56b2 blueswir1
#define MC_TSTATE 0
2004 5bfb56b2 blueswir1
#define MC_PC 1
2005 5bfb56b2 blueswir1
#define MC_NPC 2
2006 5bfb56b2 blueswir1
#define MC_Y 3
2007 5bfb56b2 blueswir1
#define MC_G1 4
2008 5bfb56b2 blueswir1
#define MC_G2 5
2009 5bfb56b2 blueswir1
#define MC_G3 6
2010 5bfb56b2 blueswir1
#define MC_G4 7
2011 5bfb56b2 blueswir1
#define MC_G5 8
2012 5bfb56b2 blueswir1
#define MC_G6 9
2013 5bfb56b2 blueswir1
#define MC_G7 10
2014 5bfb56b2 blueswir1
#define MC_O0 11
2015 5bfb56b2 blueswir1
#define MC_O1 12
2016 5bfb56b2 blueswir1
#define MC_O2 13
2017 5bfb56b2 blueswir1
#define MC_O3 14
2018 5bfb56b2 blueswir1
#define MC_O4 15
2019 5bfb56b2 blueswir1
#define MC_O5 16
2020 5bfb56b2 blueswir1
#define MC_O6 17
2021 5bfb56b2 blueswir1
#define MC_O7 18
2022 5bfb56b2 blueswir1
#define MC_NGREG 19
2023 5bfb56b2 blueswir1
2024 c227f099 Anthony Liguori
typedef abi_ulong target_mc_greg_t;
2025 c227f099 Anthony Liguori
typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
2026 5bfb56b2 blueswir1
2027 5bfb56b2 blueswir1
struct target_mc_fq {
2028 992f48a0 blueswir1
    abi_ulong *mcfq_addr;
2029 5bfb56b2 blueswir1
    uint32_t mcfq_insn;
2030 5bfb56b2 blueswir1
};
2031 5bfb56b2 blueswir1
2032 5bfb56b2 blueswir1
struct target_mc_fpu {
2033 5bfb56b2 blueswir1
    union {
2034 5bfb56b2 blueswir1
        uint32_t sregs[32];
2035 5bfb56b2 blueswir1
        uint64_t dregs[32];
2036 5bfb56b2 blueswir1
        //uint128_t qregs[16];
2037 5bfb56b2 blueswir1
    } mcfpu_fregs;
2038 992f48a0 blueswir1
    abi_ulong mcfpu_fsr;
2039 992f48a0 blueswir1
    abi_ulong mcfpu_fprs;
2040 992f48a0 blueswir1
    abi_ulong mcfpu_gsr;
2041 5bfb56b2 blueswir1
    struct target_mc_fq *mcfpu_fq;
2042 5bfb56b2 blueswir1
    unsigned char mcfpu_qcnt;
2043 5bfb56b2 blueswir1
    unsigned char mcfpu_qentsz;
2044 5bfb56b2 blueswir1
    unsigned char mcfpu_enab;
2045 5bfb56b2 blueswir1
};
2046 c227f099 Anthony Liguori
typedef struct target_mc_fpu target_mc_fpu_t;
2047 5bfb56b2 blueswir1
2048 5bfb56b2 blueswir1
typedef struct {
2049 c227f099 Anthony Liguori
    target_mc_gregset_t mc_gregs;
2050 c227f099 Anthony Liguori
    target_mc_greg_t mc_fp;
2051 c227f099 Anthony Liguori
    target_mc_greg_t mc_i7;
2052 c227f099 Anthony Liguori
    target_mc_fpu_t mc_fpregs;
2053 c227f099 Anthony Liguori
} target_mcontext_t;
2054 5bfb56b2 blueswir1
2055 5bfb56b2 blueswir1
struct target_ucontext {
2056 5bfb56b2 blueswir1
    struct target_ucontext *uc_link;
2057 992f48a0 blueswir1
    abi_ulong uc_flags;
2058 c227f099 Anthony Liguori
    target_sigset_t uc_sigmask;
2059 c227f099 Anthony Liguori
    target_mcontext_t uc_mcontext;
2060 5bfb56b2 blueswir1
};
2061 5bfb56b2 blueswir1
2062 5bfb56b2 blueswir1
/* A V9 register window */
2063 5bfb56b2 blueswir1
struct target_reg_window {
2064 992f48a0 blueswir1
    abi_ulong locals[8];
2065 992f48a0 blueswir1
    abi_ulong ins[8];
2066 5bfb56b2 blueswir1
};
2067 5bfb56b2 blueswir1
2068 5bfb56b2 blueswir1
#define TARGET_STACK_BIAS 2047
2069 5bfb56b2 blueswir1
2070 5bfb56b2 blueswir1
/* {set, get}context() needed for 64-bit SparcLinux userland. */
2071 5bfb56b2 blueswir1
void sparc64_set_context(CPUSPARCState *env)
2072 5bfb56b2 blueswir1
{
2073 459a4017 bellard
    abi_ulong ucp_addr;
2074 459a4017 bellard
    struct target_ucontext *ucp;
2075 c227f099 Anthony Liguori
    target_mc_gregset_t *grp;
2076 992f48a0 blueswir1
    abi_ulong pc, npc, tstate;
2077 459a4017 bellard
    abi_ulong fp, i7, w_addr;
2078 5bfb56b2 blueswir1
    unsigned char fenab;
2079 5bfb56b2 blueswir1
    int err;
2080 5bfb56b2 blueswir1
    unsigned int i;
2081 5bfb56b2 blueswir1
2082 459a4017 bellard
    ucp_addr = env->regwptr[UREG_I0];
2083 459a4017 bellard
    if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
2084 459a4017 bellard
        goto do_sigsegv;
2085 5bfb56b2 blueswir1
    grp  = &ucp->uc_mcontext.mc_gregs;
2086 579a97f7 bellard
    err  = __get_user(pc, &((*grp)[MC_PC]));
2087 579a97f7 bellard
    err |= __get_user(npc, &((*grp)[MC_NPC]));
2088 5bfb56b2 blueswir1
    if (err || ((pc | npc) & 3))
2089 5bfb56b2 blueswir1
        goto do_sigsegv;
2090 5bfb56b2 blueswir1
    if (env->regwptr[UREG_I1]) {
2091 c227f099 Anthony Liguori
        target_sigset_t target_set;
2092 5bfb56b2 blueswir1
        sigset_t set;
2093 5bfb56b2 blueswir1
2094 5bfb56b2 blueswir1
        if (TARGET_NSIG_WORDS == 1) {
2095 579a97f7 bellard
            if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
2096 5bfb56b2 blueswir1
                goto do_sigsegv;
2097 5bfb56b2 blueswir1
        } else {
2098 459a4017 bellard
            abi_ulong *src, *dst;
2099 459a4017 bellard
            src = ucp->uc_sigmask.sig;
2100 459a4017 bellard
            dst = target_set.sig;
2101 c227f099 Anthony Liguori
            for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
2102 5bfb56b2 blueswir1
                 i++, dst++, src++)
2103 459a4017 bellard
                err |= __get_user(*dst, src);
2104 5bfb56b2 blueswir1
            if (err)
2105 5bfb56b2 blueswir1
                goto do_sigsegv;
2106 5bfb56b2 blueswir1
        }
2107 5bfb56b2 blueswir1
        target_to_host_sigset_internal(&set, &target_set);
2108 5bfb56b2 blueswir1
        sigprocmask(SIG_SETMASK, &set, NULL);
2109 5bfb56b2 blueswir1
    }
2110 5bfb56b2 blueswir1
    env->pc = pc;
2111 5bfb56b2 blueswir1
    env->npc = npc;
2112 579a97f7 bellard
    err |= __get_user(env->y, &((*grp)[MC_Y]));
2113 579a97f7 bellard
    err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
2114 5bfb56b2 blueswir1
    env->asi = (tstate >> 24) & 0xff;
2115 5bfb56b2 blueswir1
    PUT_CCR(env, tstate >> 32);
2116 5bfb56b2 blueswir1
    PUT_CWP64(env, tstate & 0x1f);
2117 579a97f7 bellard
    err |= __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2118 579a97f7 bellard
    err |= __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2119 579a97f7 bellard
    err |= __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2120 579a97f7 bellard
    err |= __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2121 579a97f7 bellard
    err |= __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2122 579a97f7 bellard
    err |= __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2123 579a97f7 bellard
    err |= __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2124 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2125 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2126 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2127 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2128 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2129 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2130 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2131 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
2132 579a97f7 bellard
2133 579a97f7 bellard
    err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp));
2134 579a97f7 bellard
    err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7));
2135 579a97f7 bellard
2136 459a4017 bellard
    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2137 459a4017 bellard
    if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
2138 459a4017 bellard
                 abi_ulong) != 0)
2139 459a4017 bellard
        goto do_sigsegv;
2140 459a4017 bellard
    if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
2141 459a4017 bellard
                 abi_ulong) != 0)
2142 459a4017 bellard
        goto do_sigsegv;
2143 579a97f7 bellard
    err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
2144 579a97f7 bellard
    err |= __get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
2145 459a4017 bellard
    {
2146 459a4017 bellard
        uint32_t *src, *dst;
2147 459a4017 bellard
        src = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2148 459a4017 bellard
        dst = env->fpr;
2149 459a4017 bellard
        /* XXX: check that the CPU storage is the same as user context */
2150 459a4017 bellard
        for (i = 0; i < 64; i++, dst++, src++)
2151 459a4017 bellard
            err |= __get_user(*dst, src);
2152 459a4017 bellard
    }
2153 579a97f7 bellard
    err |= __get_user(env->fsr,
2154 579a97f7 bellard
                      &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
2155 579a97f7 bellard
    err |= __get_user(env->gsr,
2156 579a97f7 bellard
                      &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
2157 5bfb56b2 blueswir1
    if (err)
2158 5bfb56b2 blueswir1
        goto do_sigsegv;
2159 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 0);
2160 5bfb56b2 blueswir1
    return;
2161 5bfb56b2 blueswir1
 do_sigsegv:
2162 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 0);
2163 5bfb56b2 blueswir1
    force_sig(SIGSEGV);
2164 5bfb56b2 blueswir1
}
2165 5bfb56b2 blueswir1
2166 5bfb56b2 blueswir1
void sparc64_get_context(CPUSPARCState *env)
2167 5bfb56b2 blueswir1
{
2168 459a4017 bellard
    abi_ulong ucp_addr;
2169 459a4017 bellard
    struct target_ucontext *ucp;
2170 c227f099 Anthony Liguori
    target_mc_gregset_t *grp;
2171 c227f099 Anthony Liguori
    target_mcontext_t *mcp;
2172 459a4017 bellard
    abi_ulong fp, i7, w_addr;
2173 5bfb56b2 blueswir1
    int err;
2174 5bfb56b2 blueswir1
    unsigned int i;
2175 c227f099 Anthony Liguori
    target_sigset_t target_set;
2176 5bfb56b2 blueswir1
    sigset_t set;
2177 5bfb56b2 blueswir1
2178 459a4017 bellard
    ucp_addr = env->regwptr[UREG_I0];
2179 459a4017 bellard
    if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
2180 459a4017 bellard
        goto do_sigsegv;
2181 459a4017 bellard
    
2182 5bfb56b2 blueswir1
    mcp = &ucp->uc_mcontext;
2183 5bfb56b2 blueswir1
    grp = &mcp->mc_gregs;
2184 5bfb56b2 blueswir1
2185 5bfb56b2 blueswir1
    /* Skip over the trap instruction, first. */
2186 5bfb56b2 blueswir1
    env->pc = env->npc;
2187 5bfb56b2 blueswir1
    env->npc += 4;
2188 5bfb56b2 blueswir1
2189 5bfb56b2 blueswir1
    err = 0;
2190 5bfb56b2 blueswir1
2191 5bfb56b2 blueswir1
    sigprocmask(0, NULL, &set);
2192 5bfb56b2 blueswir1
    host_to_target_sigset_internal(&target_set, &set);
2193 459a4017 bellard
    if (TARGET_NSIG_WORDS == 1) {
2194 579a97f7 bellard
        err |= __put_user(target_set.sig[0],
2195 579a97f7 bellard
                          (abi_ulong *)&ucp->uc_sigmask);
2196 459a4017 bellard
    } else {
2197 459a4017 bellard
        abi_ulong *src, *dst;
2198 459a4017 bellard
        src = target_set.sig;
2199 459a4017 bellard
        dst = ucp->uc_sigmask.sig;
2200 c227f099 Anthony Liguori
        for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
2201 5bfb56b2 blueswir1
             i++, dst++, src++)
2202 459a4017 bellard
            err |= __put_user(*src, dst);
2203 5bfb56b2 blueswir1
        if (err)
2204 5bfb56b2 blueswir1
            goto do_sigsegv;
2205 5bfb56b2 blueswir1
    }
2206 5bfb56b2 blueswir1
2207 459a4017 bellard
    /* XXX: tstate must be saved properly */
2208 459a4017 bellard
    //    err |= __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2209 579a97f7 bellard
    err |= __put_user(env->pc, &((*grp)[MC_PC]));
2210 579a97f7 bellard
    err |= __put_user(env->npc, &((*grp)[MC_NPC]));
2211 579a97f7 bellard
    err |= __put_user(env->y, &((*grp)[MC_Y]));
2212 579a97f7 bellard
    err |= __put_user(env->gregs[1], &((*grp)[MC_G1]));
2213 579a97f7 bellard
    err |= __put_user(env->gregs[2], &((*grp)[MC_G2]));
2214 579a97f7 bellard
    err |= __put_user(env->gregs[3], &((*grp)[MC_G3]));
2215 579a97f7 bellard
    err |= __put_user(env->gregs[4], &((*grp)[MC_G4]));
2216 579a97f7 bellard
    err |= __put_user(env->gregs[5], &((*grp)[MC_G5]));
2217 579a97f7 bellard
    err |= __put_user(env->gregs[6], &((*grp)[MC_G6]));
2218 579a97f7 bellard
    err |= __put_user(env->gregs[7], &((*grp)[MC_G7]));
2219 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2220 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2221 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2222 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2223 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2224 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2225 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2226 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
2227 579a97f7 bellard
2228 459a4017 bellard
    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2229 459a4017 bellard
    fp = i7 = 0;
2230 459a4017 bellard
    if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
2231 459a4017 bellard
                 abi_ulong) != 0)
2232 459a4017 bellard
        goto do_sigsegv;
2233 459a4017 bellard
    if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
2234 459a4017 bellard
                 abi_ulong) != 0)
2235 459a4017 bellard
        goto do_sigsegv;
2236 579a97f7 bellard
    err |= __put_user(fp, &(mcp->mc_fp));
2237 579a97f7 bellard
    err |= __put_user(i7, &(mcp->mc_i7));
2238 5bfb56b2 blueswir1
2239 459a4017 bellard
    {
2240 459a4017 bellard
        uint32_t *src, *dst;
2241 459a4017 bellard
        src = env->fpr;
2242 459a4017 bellard
        dst = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2243 459a4017 bellard
        /* XXX: check that the CPU storage is the same as user context */
2244 459a4017 bellard
        for (i = 0; i < 64; i++, dst++, src++)
2245 459a4017 bellard
            err |= __put_user(*src, dst);
2246 459a4017 bellard
    }
2247 579a97f7 bellard
    err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2248 579a97f7 bellard
    err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2249 579a97f7 bellard
    err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
2250 5bfb56b2 blueswir1
2251 5bfb56b2 blueswir1
    if (err)
2252 5bfb56b2 blueswir1
        goto do_sigsegv;
2253 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 1);
2254 5bfb56b2 blueswir1
    return;
2255 5bfb56b2 blueswir1
 do_sigsegv:
2256 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 1);
2257 5bfb56b2 blueswir1
    force_sig(SIGSEGV);
2258 5bfb56b2 blueswir1
}
2259 5bfb56b2 blueswir1
#endif
2260 d26bc211 ths
#elif defined(TARGET_ABI_MIPSN64)
2261 540635ba ths
2262 540635ba ths
# warning signal handling not implemented
2263 540635ba ths
2264 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
2265 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
2266 540635ba ths
{
2267 540635ba ths
    fprintf(stderr, "setup_frame: not implemented\n");
2268 540635ba ths
}
2269 540635ba ths
2270 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2271 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2272 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
2273 540635ba ths
{
2274 540635ba ths
    fprintf(stderr, "setup_rt_frame: not implemented\n");
2275 540635ba ths
}
2276 540635ba ths
2277 540635ba ths
long do_sigreturn(CPUState *env)
2278 540635ba ths
{
2279 540635ba ths
    fprintf(stderr, "do_sigreturn: not implemented\n");
2280 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2281 540635ba ths
}
2282 540635ba ths
2283 540635ba ths
long do_rt_sigreturn(CPUState *env)
2284 540635ba ths
{
2285 540635ba ths
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
2286 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2287 540635ba ths
}
2288 540635ba ths
2289 d26bc211 ths
#elif defined(TARGET_ABI_MIPSN32)
2290 540635ba ths
2291 540635ba ths
# warning signal handling not implemented
2292 540635ba ths
2293 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
2294 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
2295 540635ba ths
{
2296 540635ba ths
    fprintf(stderr, "setup_frame: not implemented\n");
2297 540635ba ths
}
2298 540635ba ths
2299 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2300 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2301 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
2302 540635ba ths
{
2303 540635ba ths
    fprintf(stderr, "setup_rt_frame: not implemented\n");
2304 540635ba ths
}
2305 540635ba ths
2306 540635ba ths
long do_sigreturn(CPUState *env)
2307 540635ba ths
{
2308 540635ba ths
    fprintf(stderr, "do_sigreturn: not implemented\n");
2309 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2310 540635ba ths
}
2311 540635ba ths
2312 540635ba ths
long do_rt_sigreturn(CPUState *env)
2313 540635ba ths
{
2314 540635ba ths
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
2315 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2316 540635ba ths
}
2317 540635ba ths
2318 d26bc211 ths
#elif defined(TARGET_ABI_MIPSO32)
2319 106ec879 bellard
2320 106ec879 bellard
struct target_sigcontext {
2321 106ec879 bellard
    uint32_t   sc_regmask;     /* Unused */
2322 106ec879 bellard
    uint32_t   sc_status;
2323 106ec879 bellard
    uint64_t   sc_pc;
2324 106ec879 bellard
    uint64_t   sc_regs[32];
2325 106ec879 bellard
    uint64_t   sc_fpregs[32];
2326 106ec879 bellard
    uint32_t   sc_ownedfp;     /* Unused */
2327 106ec879 bellard
    uint32_t   sc_fpc_csr;
2328 106ec879 bellard
    uint32_t   sc_fpc_eir;     /* Unused */
2329 106ec879 bellard
    uint32_t   sc_used_math;
2330 106ec879 bellard
    uint32_t   sc_dsp;         /* dsp status, was sc_ssflags */
2331 94c5495d Paul Brook
    uint32_t   pad0;
2332 106ec879 bellard
    uint64_t   sc_mdhi;
2333 106ec879 bellard
    uint64_t   sc_mdlo;
2334 106ec879 bellard
    target_ulong   sc_hi1;         /* Was sc_cause */
2335 106ec879 bellard
    target_ulong   sc_lo1;         /* Was sc_badvaddr */
2336 106ec879 bellard
    target_ulong   sc_hi2;         /* Was sc_sigset[4] */
2337 106ec879 bellard
    target_ulong   sc_lo2;
2338 106ec879 bellard
    target_ulong   sc_hi3;
2339 106ec879 bellard
    target_ulong   sc_lo3;
2340 106ec879 bellard
};
2341 106ec879 bellard
2342 106ec879 bellard
struct sigframe {
2343 106ec879 bellard
    uint32_t sf_ass[4];                        /* argument save space for o32 */
2344 106ec879 bellard
    uint32_t sf_code[2];                        /* signal trampoline */
2345 106ec879 bellard
    struct target_sigcontext sf_sc;
2346 c227f099 Anthony Liguori
    target_sigset_t sf_mask;
2347 106ec879 bellard
};
2348 106ec879 bellard
2349 0b1bcb00 pbrook
struct target_ucontext {
2350 0b1bcb00 pbrook
    target_ulong uc_flags;
2351 0b1bcb00 pbrook
    target_ulong uc_link;
2352 c227f099 Anthony Liguori
    target_stack_t uc_stack;
2353 94c5495d Paul Brook
    target_ulong pad0;
2354 0b1bcb00 pbrook
    struct target_sigcontext uc_mcontext;
2355 c227f099 Anthony Liguori
    target_sigset_t uc_sigmask;
2356 0b1bcb00 pbrook
};
2357 0b1bcb00 pbrook
2358 0b1bcb00 pbrook
struct target_rt_sigframe {
2359 0b1bcb00 pbrook
    uint32_t rs_ass[4];               /* argument save space for o32 */
2360 0b1bcb00 pbrook
    uint32_t rs_code[2];              /* signal trampoline */
2361 0b1bcb00 pbrook
    struct target_siginfo rs_info;
2362 0b1bcb00 pbrook
    struct target_ucontext rs_uc;
2363 0b1bcb00 pbrook
};
2364 0b1bcb00 pbrook
2365 106ec879 bellard
/* Install trampoline to jump back from signal handler */
2366 106ec879 bellard
static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
2367 106ec879 bellard
{
2368 106ec879 bellard
    int err;
2369 106ec879 bellard
2370 106ec879 bellard
    /*
2371 106ec879 bellard
    * Set up the return code ...
2372 106ec879 bellard
    *
2373 106ec879 bellard
    *         li      v0, __NR__foo_sigreturn
2374 106ec879 bellard
    *         syscall
2375 106ec879 bellard
    */
2376 106ec879 bellard
2377 106ec879 bellard
    err = __put_user(0x24020000 + syscall, tramp + 0);
2378 106ec879 bellard
    err |= __put_user(0x0000000c          , tramp + 1);
2379 106ec879 bellard
    /* flush_cache_sigtramp((unsigned long) tramp); */
2380 106ec879 bellard
    return err;
2381 106ec879 bellard
}
2382 106ec879 bellard
2383 106ec879 bellard
static inline int
2384 106ec879 bellard
setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
2385 106ec879 bellard
{
2386 106ec879 bellard
    int err = 0;
2387 106ec879 bellard
2388 b5dc7732 ths
    err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
2389 106ec879 bellard
2390 b5dc7732 ths
#define save_gp_reg(i) do {                                                   \
2391 b5dc7732 ths
        err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);        \
2392 106ec879 bellard
    } while(0)
2393 106ec879 bellard
    __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
2394 106ec879 bellard
    save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
2395 106ec879 bellard
    save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
2396 106ec879 bellard
    save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
2397 106ec879 bellard
    save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
2398 106ec879 bellard
    save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
2399 106ec879 bellard
    save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
2400 106ec879 bellard
    save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
2401 106ec879 bellard
    save_gp_reg(31);
2402 388bb21a ths
#undef save_gp_reg
2403 106ec879 bellard
2404 b5dc7732 ths
    err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2405 b5dc7732 ths
    err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
2406 106ec879 bellard
2407 106ec879 bellard
    /* Not used yet, but might be useful if we ever have DSP suppport */
2408 106ec879 bellard
#if 0
2409 106ec879 bellard
    if (cpu_has_dsp) {
2410 106ec879 bellard
        err |= __put_user(mfhi1(), &sc->sc_hi1);
2411 106ec879 bellard
        err |= __put_user(mflo1(), &sc->sc_lo1);
2412 106ec879 bellard
        err |= __put_user(mfhi2(), &sc->sc_hi2);
2413 106ec879 bellard
        err |= __put_user(mflo2(), &sc->sc_lo2);
2414 106ec879 bellard
        err |= __put_user(mfhi3(), &sc->sc_hi3);
2415 106ec879 bellard
        err |= __put_user(mflo3(), &sc->sc_lo3);
2416 106ec879 bellard
        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2417 106ec879 bellard
    }
2418 106ec879 bellard
    /* same with 64 bit */
2419 388bb21a ths
#ifdef CONFIG_64BIT
2420 106ec879 bellard
    err |= __put_user(regs->hi, &sc->sc_hi[0]);
2421 106ec879 bellard
    err |= __put_user(regs->lo, &sc->sc_lo[0]);
2422 106ec879 bellard
    if (cpu_has_dsp) {
2423 106ec879 bellard
        err |= __put_user(mfhi1(), &sc->sc_hi[1]);
2424 106ec879 bellard
        err |= __put_user(mflo1(), &sc->sc_lo[1]);
2425 106ec879 bellard
        err |= __put_user(mfhi2(), &sc->sc_hi[2]);
2426 106ec879 bellard
        err |= __put_user(mflo2(), &sc->sc_lo[2]);
2427 106ec879 bellard
        err |= __put_user(mfhi3(), &sc->sc_hi[3]);
2428 106ec879 bellard
        err |= __put_user(mflo3(), &sc->sc_lo[3]);
2429 106ec879 bellard
        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2430 106ec879 bellard
    }
2431 388bb21a ths
#endif
2432 388bb21a ths
#endif
2433 106ec879 bellard
2434 388bb21a ths
#if 0
2435 106ec879 bellard
    err |= __put_user(!!used_math(), &sc->sc_used_math);
2436 106ec879 bellard

2437 106ec879 bellard
    if (!used_math())
2438 106ec879 bellard
        goto out;
2439 106ec879 bellard

2440 106ec879 bellard
    /*
2441 106ec879 bellard
    * Save FPU state to signal context.  Signal handler will "inherit"
2442 106ec879 bellard
    * current FPU state.
2443 106ec879 bellard
    */
2444 106ec879 bellard
    preempt_disable();
2445 106ec879 bellard

2446 106ec879 bellard
    if (!is_fpu_owner()) {
2447 106ec879 bellard
        own_fpu();
2448 106ec879 bellard
        restore_fp(current);
2449 106ec879 bellard
    }
2450 106ec879 bellard
    err |= save_fp_context(sc);
2451 106ec879 bellard

2452 106ec879 bellard
    preempt_enable();
2453 106ec879 bellard
    out:
2454 106ec879 bellard
#endif
2455 106ec879 bellard
    return err;
2456 106ec879 bellard
}
2457 106ec879 bellard
2458 106ec879 bellard
static inline int
2459 106ec879 bellard
restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
2460 106ec879 bellard
{
2461 106ec879 bellard
    int err = 0;
2462 106ec879 bellard
2463 106ec879 bellard
    err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
2464 106ec879 bellard
2465 b5dc7732 ths
    err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2466 b5dc7732 ths
    err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
2467 106ec879 bellard
2468 ead9360e ths
#define restore_gp_reg(i) do {                                                           \
2469 b5dc7732 ths
        err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);                \
2470 106ec879 bellard
    } while(0)
2471 106ec879 bellard
    restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
2472 106ec879 bellard
    restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
2473 106ec879 bellard
    restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
2474 106ec879 bellard
    restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
2475 106ec879 bellard
    restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
2476 106ec879 bellard
    restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
2477 106ec879 bellard
    restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
2478 106ec879 bellard
    restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
2479 106ec879 bellard
    restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
2480 106ec879 bellard
    restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
2481 106ec879 bellard
    restore_gp_reg(31);
2482 388bb21a ths
#undef restore_gp_reg
2483 106ec879 bellard
2484 106ec879 bellard
#if 0
2485 106ec879 bellard
    if (cpu_has_dsp) {
2486 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
2487 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
2488 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
2489 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
2490 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
2491 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
2492 106ec879 bellard
        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2493 106ec879 bellard
    }
2494 388bb21a ths
#ifdef CONFIG_64BIT
2495 106ec879 bellard
    err |= __get_user(regs->hi, &sc->sc_hi[0]);
2496 106ec879 bellard
    err |= __get_user(regs->lo, &sc->sc_lo[0]);
2497 106ec879 bellard
    if (cpu_has_dsp) {
2498 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
2499 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
2500 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
2501 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
2502 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
2503 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
2504 106ec879 bellard
        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2505 106ec879 bellard
    }
2506 388bb21a ths
#endif
2507 106ec879 bellard
2508 106ec879 bellard
    err |= __get_user(used_math, &sc->sc_used_math);
2509 106ec879 bellard
    conditional_used_math(used_math);
2510 106ec879 bellard
2511 106ec879 bellard
    preempt_disable();
2512 106ec879 bellard
2513 106ec879 bellard
    if (used_math()) {
2514 106ec879 bellard
        /* restore fpu context if we have used it before */
2515 106ec879 bellard
        own_fpu();
2516 106ec879 bellard
        err |= restore_fp_context(sc);
2517 106ec879 bellard
    } else {
2518 106ec879 bellard
        /* signal handler may have used FPU.  Give it up. */
2519 106ec879 bellard
        lose_fpu();
2520 106ec879 bellard
    }
2521 106ec879 bellard
2522 106ec879 bellard
    preempt_enable();
2523 106ec879 bellard
#endif
2524 106ec879 bellard
    return err;
2525 106ec879 bellard
}
2526 106ec879 bellard
/*
2527 106ec879 bellard
 * Determine which stack to use..
2528 106ec879 bellard
 */
2529 579a97f7 bellard
static inline abi_ulong
2530 624f7979 pbrook
get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
2531 106ec879 bellard
{
2532 106ec879 bellard
    unsigned long sp;
2533 106ec879 bellard
2534 106ec879 bellard
    /* Default to using normal stack */
2535 b5dc7732 ths
    sp = regs->active_tc.gpr[29];
2536 106ec879 bellard
2537 106ec879 bellard
    /*
2538 106ec879 bellard
     * FPU emulator may have it's own trampoline active just
2539 106ec879 bellard
     * above the user stack, 16-bytes before the next lowest
2540 106ec879 bellard
     * 16 byte boundary.  Try to avoid trashing it.
2541 106ec879 bellard
     */
2542 106ec879 bellard
    sp -= 32;
2543 106ec879 bellard
2544 106ec879 bellard
    /* This is the X/Open sanctioned signal stack switching.  */
2545 624f7979 pbrook
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
2546 a04e134a ths
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2547 a04e134a ths
    }
2548 106ec879 bellard
2549 579a97f7 bellard
    return (sp - frame_size) & ~7;
2550 106ec879 bellard
}
2551 106ec879 bellard
2552 579a97f7 bellard
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
2553 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction * ka,
2554 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *regs)
2555 106ec879 bellard
{
2556 106ec879 bellard
    struct sigframe *frame;
2557 579a97f7 bellard
    abi_ulong frame_addr;
2558 106ec879 bellard
    int i;
2559 106ec879 bellard
2560 579a97f7 bellard
    frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2561 579a97f7 bellard
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2562 106ec879 bellard
        goto give_sigsegv;
2563 106ec879 bellard
2564 106ec879 bellard
    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2565 106ec879 bellard
2566 106ec879 bellard
    if(setup_sigcontext(regs, &frame->sf_sc))
2567 106ec879 bellard
        goto give_sigsegv;
2568 106ec879 bellard
2569 106ec879 bellard
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2570 106ec879 bellard
        if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))
2571 106ec879 bellard
            goto give_sigsegv;
2572 106ec879 bellard
    }
2573 106ec879 bellard
2574 106ec879 bellard
    /*
2575 106ec879 bellard
    * Arguments to signal handler:
2576 106ec879 bellard
    *
2577 106ec879 bellard
    *   a0 = signal number
2578 106ec879 bellard
    *   a1 = 0 (should be cause)
2579 106ec879 bellard
    *   a2 = pointer to struct sigcontext
2580 106ec879 bellard
    *
2581 106ec879 bellard
    * $25 and PC point to the signal handler, $29 points to the
2582 106ec879 bellard
    * struct sigframe.
2583 106ec879 bellard
    */
2584 b5dc7732 ths
    regs->active_tc.gpr[ 4] = sig;
2585 b5dc7732 ths
    regs->active_tc.gpr[ 5] = 0;
2586 b5dc7732 ths
    regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2587 b5dc7732 ths
    regs->active_tc.gpr[29] = frame_addr;
2588 b5dc7732 ths
    regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
2589 106ec879 bellard
    /* The original kernel code sets CP0_EPC to the handler
2590 106ec879 bellard
    * since it returns to userland using eret
2591 106ec879 bellard
    * we cannot do this here, and we must set PC directly */
2592 b5dc7732 ths
    regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
2593 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 1);
2594 106ec879 bellard
    return;
2595 106ec879 bellard
2596 106ec879 bellard
give_sigsegv:
2597 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 1);
2598 106ec879 bellard
    force_sig(TARGET_SIGSEGV/*, current*/);
2599 5fafdf24 ths
    return;
2600 106ec879 bellard
}
2601 106ec879 bellard
2602 106ec879 bellard
long do_sigreturn(CPUState *regs)
2603 106ec879 bellard
{
2604 388bb21a ths
    struct sigframe *frame;
2605 579a97f7 bellard
    abi_ulong frame_addr;
2606 388bb21a ths
    sigset_t blocked;
2607 c227f099 Anthony Liguori
    target_sigset_t target_set;
2608 388bb21a ths
    int i;
2609 106ec879 bellard
2610 106ec879 bellard
#if defined(DEBUG_SIGNAL)
2611 388bb21a ths
    fprintf(stderr, "do_sigreturn\n");
2612 106ec879 bellard
#endif
2613 b5dc7732 ths
    frame_addr = regs->active_tc.gpr[29];
2614 579a97f7 bellard
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2615 106ec879 bellard
           goto badframe;
2616 106ec879 bellard
2617 388bb21a ths
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2618 106ec879 bellard
           if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
2619 106ec879 bellard
            goto badframe;
2620 388bb21a ths
    }
2621 106ec879 bellard
2622 388bb21a ths
    target_to_host_sigset_internal(&blocked, &target_set);
2623 388bb21a ths
    sigprocmask(SIG_SETMASK, &blocked, NULL);
2624 106ec879 bellard
2625 388bb21a ths
    if (restore_sigcontext(regs, &frame->sf_sc))
2626 106ec879 bellard
           goto badframe;
2627 106ec879 bellard
2628 106ec879 bellard
#if 0
2629 388bb21a ths
    /*
2630 388bb21a ths
     * Don't let your children do this ...
2631 388bb21a ths
     */
2632 388bb21a ths
    __asm__ __volatile__(
2633 106ec879 bellard
           "move\t$29, %0\n\t"
2634 106ec879 bellard
           "j\tsyscall_exit"
2635 106ec879 bellard
           :/* no outputs */
2636 106ec879 bellard
           :"r" (&regs));
2637 388bb21a ths
    /* Unreached */
2638 106ec879 bellard
#endif
2639 3b46e624 ths
2640 b5dc7732 ths
    regs->active_tc.PC = regs->CP0_EPC;
2641 388bb21a ths
    /* I am not sure this is right, but it seems to work
2642 106ec879 bellard
    * maybe a problem with nested signals ? */
2643 106ec879 bellard
    regs->CP0_EPC = 0;
2644 0b1bcb00 pbrook
    return -TARGET_QEMU_ESIGRETURN;
2645 106ec879 bellard
2646 106ec879 bellard
badframe:
2647 388bb21a ths
    force_sig(TARGET_SIGSEGV/*, current*/);
2648 388bb21a ths
    return 0;
2649 106ec879 bellard
}
2650 106ec879 bellard
2651 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2652 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2653 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
2654 106ec879 bellard
{
2655 0b1bcb00 pbrook
    struct target_rt_sigframe *frame;
2656 0b1bcb00 pbrook
    abi_ulong frame_addr;
2657 0b1bcb00 pbrook
    int i;
2658 0b1bcb00 pbrook
2659 0b1bcb00 pbrook
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
2660 0b1bcb00 pbrook
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2661 0b1bcb00 pbrook
        goto give_sigsegv;
2662 0b1bcb00 pbrook
2663 0b1bcb00 pbrook
    install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
2664 0b1bcb00 pbrook
2665 0b1bcb00 pbrook
    copy_siginfo_to_user(&frame->rs_info, info);
2666 0b1bcb00 pbrook
2667 0b1bcb00 pbrook
    __put_user(0, &frame->rs_uc.uc_flags);
2668 0b1bcb00 pbrook
    __put_user(0, &frame->rs_uc.uc_link);
2669 0b1bcb00 pbrook
    __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.uc_stack.ss_sp);
2670 0b1bcb00 pbrook
    __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.uc_stack.ss_size);
2671 0b1bcb00 pbrook
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
2672 0b1bcb00 pbrook
               &frame->rs_uc.uc_stack.ss_flags);
2673 0b1bcb00 pbrook
2674 0b1bcb00 pbrook
    setup_sigcontext(env, &frame->rs_uc.uc_mcontext);
2675 0b1bcb00 pbrook
2676 0b1bcb00 pbrook
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2677 0b1bcb00 pbrook
        __put_user(set->sig[i], &frame->rs_uc.uc_sigmask.sig[i]);
2678 0b1bcb00 pbrook
    }
2679 0b1bcb00 pbrook
2680 0b1bcb00 pbrook
    /*
2681 0b1bcb00 pbrook
    * Arguments to signal handler:
2682 0b1bcb00 pbrook
    *
2683 0b1bcb00 pbrook
    *   a0 = signal number
2684 0b1bcb00 pbrook
    *   a1 = pointer to struct siginfo
2685 0b1bcb00 pbrook
    *   a2 = pointer to struct ucontext
2686 0b1bcb00 pbrook
    *
2687 0b1bcb00 pbrook
    * $25 and PC point to the signal handler, $29 points to the
2688 0b1bcb00 pbrook
    * struct sigframe.
2689 0b1bcb00 pbrook
    */
2690 0b1bcb00 pbrook
    env->active_tc.gpr[ 4] = sig;
2691 0b1bcb00 pbrook
    env->active_tc.gpr[ 5] = frame_addr
2692 0b1bcb00 pbrook
                             + offsetof(struct target_rt_sigframe, rs_info);
2693 0b1bcb00 pbrook
    env->active_tc.gpr[ 6] = frame_addr
2694 0b1bcb00 pbrook
                             + offsetof(struct target_rt_sigframe, rs_uc);
2695 0b1bcb00 pbrook
    env->active_tc.gpr[29] = frame_addr;
2696 0b1bcb00 pbrook
    env->active_tc.gpr[31] = frame_addr
2697 0b1bcb00 pbrook
                             + offsetof(struct target_rt_sigframe, rs_code);
2698 0b1bcb00 pbrook
    /* The original kernel code sets CP0_EPC to the handler
2699 0b1bcb00 pbrook
    * since it returns to userland using eret
2700 0b1bcb00 pbrook
    * we cannot do this here, and we must set PC directly */
2701 0b1bcb00 pbrook
    env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
2702 0b1bcb00 pbrook
    unlock_user_struct(frame, frame_addr, 1);
2703 0b1bcb00 pbrook
    return;
2704 0b1bcb00 pbrook
2705 0b1bcb00 pbrook
give_sigsegv:
2706 0b1bcb00 pbrook
    unlock_user_struct(frame, frame_addr, 1);
2707 0b1bcb00 pbrook
    force_sig(TARGET_SIGSEGV/*, current*/);
2708 0b1bcb00 pbrook
    return;
2709 106ec879 bellard
}
2710 106ec879 bellard
2711 106ec879 bellard
long do_rt_sigreturn(CPUState *env)
2712 106ec879 bellard
{
2713 0b1bcb00 pbrook
    struct target_rt_sigframe *frame;
2714 0b1bcb00 pbrook
    abi_ulong frame_addr;
2715 0b1bcb00 pbrook
    sigset_t blocked;
2716 0b1bcb00 pbrook
2717 0b1bcb00 pbrook
#if defined(DEBUG_SIGNAL)
2718 0b1bcb00 pbrook
    fprintf(stderr, "do_rt_sigreturn\n");
2719 0b1bcb00 pbrook
#endif
2720 0b1bcb00 pbrook
    frame_addr = env->active_tc.gpr[29];
2721 0b1bcb00 pbrook
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2722 0b1bcb00 pbrook
           goto badframe;
2723 0b1bcb00 pbrook
2724 0b1bcb00 pbrook
    target_to_host_sigset(&blocked, &frame->rs_uc.uc_sigmask);
2725 0b1bcb00 pbrook
    sigprocmask(SIG_SETMASK, &blocked, NULL);
2726 0b1bcb00 pbrook
2727 0b1bcb00 pbrook
    if (restore_sigcontext(env, &frame->rs_uc.uc_mcontext))
2728 0b1bcb00 pbrook
        goto badframe;
2729 0b1bcb00 pbrook
2730 0b1bcb00 pbrook
    if (do_sigaltstack(frame_addr +
2731 0b1bcb00 pbrook
                       offsetof(struct target_rt_sigframe, rs_uc.uc_stack),
2732 0b1bcb00 pbrook
                       0, get_sp_from_cpustate(env)) == -EFAULT)
2733 0b1bcb00 pbrook
        goto badframe;
2734 0b1bcb00 pbrook
2735 0b1bcb00 pbrook
    env->active_tc.PC = env->CP0_EPC;
2736 0b1bcb00 pbrook
    /* I am not sure this is right, but it seems to work
2737 0b1bcb00 pbrook
    * maybe a problem with nested signals ? */
2738 0b1bcb00 pbrook
    env->CP0_EPC = 0;
2739 0b1bcb00 pbrook
    return -TARGET_QEMU_ESIGRETURN;
2740 0b1bcb00 pbrook
2741 0b1bcb00 pbrook
badframe:
2742 0b1bcb00 pbrook
    force_sig(TARGET_SIGSEGV/*, current*/);
2743 0b1bcb00 pbrook
    return 0;
2744 106ec879 bellard
}
2745 6d5e216d bellard
2746 c3b5bc8a ths
#elif defined(TARGET_SH4)
2747 c3b5bc8a ths
2748 c3b5bc8a ths
/*
2749 c3b5bc8a ths
 * code and data structures from linux kernel:
2750 c3b5bc8a ths
 * include/asm-sh/sigcontext.h
2751 c3b5bc8a ths
 * arch/sh/kernel/signal.c
2752 c3b5bc8a ths
 */
2753 c3b5bc8a ths
2754 c3b5bc8a ths
struct target_sigcontext {
2755 c3b5bc8a ths
    target_ulong  oldmask;
2756 c3b5bc8a ths
2757 c3b5bc8a ths
    /* CPU registers */
2758 c3b5bc8a ths
    target_ulong  sc_gregs[16];
2759 c3b5bc8a ths
    target_ulong  sc_pc;
2760 c3b5bc8a ths
    target_ulong  sc_pr;
2761 c3b5bc8a ths
    target_ulong  sc_sr;
2762 c3b5bc8a ths
    target_ulong  sc_gbr;
2763 c3b5bc8a ths
    target_ulong  sc_mach;
2764 c3b5bc8a ths
    target_ulong  sc_macl;
2765 c3b5bc8a ths
2766 c3b5bc8a ths
    /* FPU registers */
2767 c3b5bc8a ths
    target_ulong  sc_fpregs[16];
2768 c3b5bc8a ths
    target_ulong  sc_xfpregs[16];
2769 c3b5bc8a ths
    unsigned int sc_fpscr;
2770 c3b5bc8a ths
    unsigned int sc_fpul;
2771 c3b5bc8a ths
    unsigned int sc_ownedfp;
2772 c3b5bc8a ths
};
2773 c3b5bc8a ths
2774 c3b5bc8a ths
struct target_sigframe
2775 c3b5bc8a ths
{
2776 c3b5bc8a ths
    struct target_sigcontext sc;
2777 c3b5bc8a ths
    target_ulong extramask[TARGET_NSIG_WORDS-1];
2778 c3b5bc8a ths
    uint16_t retcode[3];
2779 c3b5bc8a ths
};
2780 c3b5bc8a ths
2781 c3b5bc8a ths
2782 c3b5bc8a ths
struct target_ucontext {
2783 c3b5bc8a ths
    target_ulong uc_flags;
2784 c3b5bc8a ths
    struct target_ucontext *uc_link;
2785 c227f099 Anthony Liguori
    target_stack_t uc_stack;
2786 c3b5bc8a ths
    struct target_sigcontext uc_mcontext;
2787 c227f099 Anthony Liguori
    target_sigset_t uc_sigmask;        /* mask last for extensibility */
2788 c3b5bc8a ths
};
2789 c3b5bc8a ths
2790 c3b5bc8a ths
struct target_rt_sigframe
2791 c3b5bc8a ths
{
2792 c3b5bc8a ths
    struct target_siginfo info;
2793 c3b5bc8a ths
    struct target_ucontext uc;
2794 c3b5bc8a ths
    uint16_t retcode[3];
2795 c3b5bc8a ths
};
2796 c3b5bc8a ths
2797 c3b5bc8a ths
2798 c3b5bc8a ths
#define MOVW(n)  (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
2799 c3b5bc8a ths
#define TRAP_NOARG 0xc310         /* Syscall w/no args (NR in R3) SH3/4 */
2800 c3b5bc8a ths
2801 624f7979 pbrook
static abi_ulong get_sigframe(struct target_sigaction *ka,
2802 c3b5bc8a ths
                         unsigned long sp, size_t frame_size)
2803 c3b5bc8a ths
{
2804 624f7979 pbrook
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
2805 c3b5bc8a ths
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2806 c3b5bc8a ths
    }
2807 c3b5bc8a ths
2808 c3b5bc8a ths
    return (sp - frame_size) & -8ul;
2809 c3b5bc8a ths
}
2810 c3b5bc8a ths
2811 c3b5bc8a ths
static int setup_sigcontext(struct target_sigcontext *sc,
2812 c3b5bc8a ths
                            CPUState *regs, unsigned long mask)
2813 c3b5bc8a ths
{
2814 c3b5bc8a ths
    int err = 0;
2815 c3b5bc8a ths
2816 c3b5bc8a ths
#define COPY(x)         err |= __put_user(regs->x, &sc->sc_##x)
2817 c3b5bc8a ths
    COPY(gregs[0]); COPY(gregs[1]);
2818 c3b5bc8a ths
    COPY(gregs[2]); COPY(gregs[3]);
2819 c3b5bc8a ths
    COPY(gregs[4]); COPY(gregs[5]);
2820 c3b5bc8a ths
    COPY(gregs[6]); COPY(gregs[7]);
2821 c3b5bc8a ths
    COPY(gregs[8]); COPY(gregs[9]);
2822 c3b5bc8a ths
    COPY(gregs[10]); COPY(gregs[11]);
2823 c3b5bc8a ths
    COPY(gregs[12]); COPY(gregs[13]);
2824 c3b5bc8a ths
    COPY(gregs[14]); COPY(gregs[15]);
2825 c3b5bc8a ths
    COPY(gbr); COPY(mach);
2826 c3b5bc8a ths
    COPY(macl); COPY(pr);
2827 c3b5bc8a ths
    COPY(sr); COPY(pc);
2828 c3b5bc8a ths
#undef COPY
2829 c3b5bc8a ths
2830 c3b5bc8a ths
    /* todo: save FPU registers here */
2831 c3b5bc8a ths
2832 c3b5bc8a ths
    /* non-iBCS2 extensions.. */
2833 c3b5bc8a ths
    err |= __put_user(mask, &sc->oldmask);
2834 c3b5bc8a ths
2835 c3b5bc8a ths
    return err;
2836 c3b5bc8a ths
}
2837 c3b5bc8a ths
2838 c2764719 pbrook
static int restore_sigcontext(CPUState *regs,
2839 c3b5bc8a ths
                              struct target_sigcontext *sc)
2840 c3b5bc8a ths
{
2841 c3b5bc8a ths
    unsigned int err = 0;
2842 c3b5bc8a ths
2843 c3b5bc8a ths
#define COPY(x)         err |= __get_user(regs->x, &sc->sc_##x)
2844 c3b5bc8a ths
    COPY(gregs[1]);
2845 c3b5bc8a ths
    COPY(gregs[2]); COPY(gregs[3]);
2846 c3b5bc8a ths
    COPY(gregs[4]); COPY(gregs[5]);
2847 c3b5bc8a ths
    COPY(gregs[6]); COPY(gregs[7]);
2848 c3b5bc8a ths
    COPY(gregs[8]); COPY(gregs[9]);
2849 c3b5bc8a ths
    COPY(gregs[10]); COPY(gregs[11]);
2850 c3b5bc8a ths
    COPY(gregs[12]); COPY(gregs[13]);
2851 c3b5bc8a ths
    COPY(gregs[14]); COPY(gregs[15]);
2852 c3b5bc8a ths
    COPY(gbr); COPY(mach);
2853 c3b5bc8a ths
    COPY(macl); COPY(pr);
2854 c3b5bc8a ths
    COPY(sr); COPY(pc);
2855 c3b5bc8a ths
#undef COPY
2856 c3b5bc8a ths
2857 c3b5bc8a ths
    /* todo: restore FPU registers here */
2858 c3b5bc8a ths
2859 c3b5bc8a ths
    regs->tra = -1;         /* disable syscall checks */
2860 c3b5bc8a ths
    return err;
2861 c3b5bc8a ths
}
2862 c3b5bc8a ths
2863 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
2864 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *regs)
2865 c3b5bc8a ths
{
2866 c3b5bc8a ths
    struct target_sigframe *frame;
2867 c3b5bc8a ths
    abi_ulong frame_addr;
2868 c3b5bc8a ths
    int i;
2869 c3b5bc8a ths
    int err = 0;
2870 c3b5bc8a ths
    int signal;
2871 c3b5bc8a ths
2872 c3b5bc8a ths
    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
2873 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2874 c3b5bc8a ths
        goto give_sigsegv;
2875 c3b5bc8a ths
2876 c3b5bc8a ths
    signal = current_exec_domain_sig(sig);
2877 c3b5bc8a ths
2878 c3b5bc8a ths
    err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
2879 c3b5bc8a ths
2880 c3b5bc8a ths
    for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
2881 c3b5bc8a ths
        err |= __put_user(set->sig[i + 1], &frame->extramask[i]);
2882 c3b5bc8a ths
    }
2883 c3b5bc8a ths
2884 c3b5bc8a ths
    /* Set up to return from userspace.  If provided, use a stub
2885 c3b5bc8a ths
       already in userspace.  */
2886 624f7979 pbrook
    if (ka->sa_flags & TARGET_SA_RESTORER) {
2887 624f7979 pbrook
        regs->pr = (unsigned long) ka->sa_restorer;
2888 c3b5bc8a ths
    } else {
2889 c3b5bc8a ths
        /* Generate return code (system call to sigreturn) */
2890 c3b5bc8a ths
        err |= __put_user(MOVW(2), &frame->retcode[0]);
2891 c3b5bc8a ths
        err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
2892 c3b5bc8a ths
        err |= __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
2893 c3b5bc8a ths
        regs->pr = (unsigned long) frame->retcode;
2894 c3b5bc8a ths
    }
2895 c3b5bc8a ths
2896 c3b5bc8a ths
    if (err)
2897 c3b5bc8a ths
        goto give_sigsegv;
2898 c3b5bc8a ths
2899 c3b5bc8a ths
    /* Set up registers for signal handler */
2900 c3b5bc8a ths
    regs->gregs[15] = (unsigned long) frame;
2901 c3b5bc8a ths
    regs->gregs[4] = signal; /* Arg for signal handler */
2902 c3b5bc8a ths
    regs->gregs[5] = 0;
2903 c3b5bc8a ths
    regs->gregs[6] = (unsigned long) &frame->sc;
2904 624f7979 pbrook
    regs->pc = (unsigned long) ka->_sa_handler;
2905 c3b5bc8a ths
2906 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
2907 c3b5bc8a ths
    return;
2908 c3b5bc8a ths
2909 c3b5bc8a ths
give_sigsegv:
2910 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
2911 c3b5bc8a ths
    force_sig(SIGSEGV);
2912 c3b5bc8a ths
}
2913 c3b5bc8a ths
2914 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2915 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2916 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *regs)
2917 c3b5bc8a ths
{
2918 c3b5bc8a ths
    struct target_rt_sigframe *frame;
2919 c3b5bc8a ths
    abi_ulong frame_addr;
2920 c3b5bc8a ths
    int i;
2921 c3b5bc8a ths
    int err = 0;
2922 c3b5bc8a ths
    int signal;
2923 c3b5bc8a ths
2924 c3b5bc8a ths
    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
2925 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2926 c3b5bc8a ths
        goto give_sigsegv;
2927 c3b5bc8a ths
2928 c3b5bc8a ths
    signal = current_exec_domain_sig(sig);
2929 c3b5bc8a ths
2930 c3b5bc8a ths
    err |= copy_siginfo_to_user(&frame->info, info);
2931 c3b5bc8a ths
2932 c3b5bc8a ths
    /* Create the ucontext.  */
2933 c3b5bc8a ths
    err |= __put_user(0, &frame->uc.uc_flags);
2934 c3b5bc8a ths
    err |= __put_user(0, (unsigned long *)&frame->uc.uc_link);
2935 526ccb7a balrog
    err |= __put_user((unsigned long)target_sigaltstack_used.ss_sp,
2936 c3b5bc8a ths
                      &frame->uc.uc_stack.ss_sp);
2937 c3b5bc8a ths
    err |= __put_user(sas_ss_flags(regs->gregs[15]),
2938 c3b5bc8a ths
                      &frame->uc.uc_stack.ss_flags);
2939 c3b5bc8a ths
    err |= __put_user(target_sigaltstack_used.ss_size,
2940 c3b5bc8a ths
                      &frame->uc.uc_stack.ss_size);
2941 c3b5bc8a ths
    err |= setup_sigcontext(&frame->uc.uc_mcontext,
2942 c3b5bc8a ths
                            regs, set->sig[0]);
2943 c3b5bc8a ths
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2944 c3b5bc8a ths
        err |= __put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]);
2945 c3b5bc8a ths
    }
2946 c3b5bc8a ths
2947 c3b5bc8a ths
    /* Set up to return from userspace.  If provided, use a stub
2948 c3b5bc8a ths
       already in userspace.  */
2949 624f7979 pbrook
    if (ka->sa_flags & TARGET_SA_RESTORER) {
2950 624f7979 pbrook
        regs->pr = (unsigned long) ka->sa_restorer;
2951 c3b5bc8a ths
    } else {
2952 c3b5bc8a ths
        /* Generate return code (system call to sigreturn) */
2953 c3b5bc8a ths
        err |= __put_user(MOVW(2), &frame->retcode[0]);
2954 c3b5bc8a ths
        err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
2955 c3b5bc8a ths
        err |= __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
2956 c3b5bc8a ths
        regs->pr = (unsigned long) frame->retcode;
2957 c3b5bc8a ths
    }
2958 c3b5bc8a ths
2959 c3b5bc8a ths
    if (err)
2960 c3b5bc8a ths
        goto give_sigsegv;
2961 c3b5bc8a ths
2962 c3b5bc8a ths
    /* Set up registers for signal handler */
2963 c3b5bc8a ths
    regs->gregs[15] = (unsigned long) frame;
2964 c3b5bc8a ths
    regs->gregs[4] = signal; /* Arg for signal handler */
2965 c3b5bc8a ths
    regs->gregs[5] = (unsigned long) &frame->info;
2966 c3b5bc8a ths
    regs->gregs[6] = (unsigned long) &frame->uc;
2967 624f7979 pbrook
    regs->pc = (unsigned long) ka->_sa_handler;
2968 c3b5bc8a ths
2969 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
2970 c3b5bc8a ths
    return;
2971 c3b5bc8a ths
2972 c3b5bc8a ths
give_sigsegv:
2973 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
2974 c3b5bc8a ths
    force_sig(SIGSEGV);
2975 c3b5bc8a ths
}
2976 c3b5bc8a ths
2977 c3b5bc8a ths
long do_sigreturn(CPUState *regs)
2978 c3b5bc8a ths
{
2979 c3b5bc8a ths
    struct target_sigframe *frame;
2980 c3b5bc8a ths
    abi_ulong frame_addr;
2981 c3b5bc8a ths
    sigset_t blocked;
2982 c227f099 Anthony Liguori
    target_sigset_t target_set;
2983 c3b5bc8a ths
    int i;
2984 c3b5bc8a ths
    int err = 0;
2985 c3b5bc8a ths
2986 c3b5bc8a ths
#if defined(DEBUG_SIGNAL)
2987 c3b5bc8a ths
    fprintf(stderr, "do_sigreturn\n");
2988 c3b5bc8a ths
#endif
2989 c3b5bc8a ths
    frame_addr = regs->gregs[15];
2990 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2991 c3b5bc8a ths
           goto badframe;
2992 c3b5bc8a ths
2993 c3b5bc8a ths
    err |= __get_user(target_set.sig[0], &frame->sc.oldmask);
2994 c3b5bc8a ths
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2995 c3b5bc8a ths
        err |= (__get_user(target_set.sig[i], &frame->extramask[i - 1]));
2996 c3b5bc8a ths
    }
2997 c3b5bc8a ths
2998 c3b5bc8a ths
    if (err)
2999 c3b5bc8a ths
        goto badframe;
3000 c3b5bc8a ths
3001 c3b5bc8a ths
    target_to_host_sigset_internal(&blocked, &target_set);
3002 c3b5bc8a ths
    sigprocmask(SIG_SETMASK, &blocked, NULL);
3003 c3b5bc8a ths
3004 c3b5bc8a ths
    if (restore_sigcontext(regs, &frame->sc))
3005 c3b5bc8a ths
        goto badframe;
3006 c3b5bc8a ths
3007 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3008 c3b5bc8a ths
    return regs->gregs[0];
3009 c3b5bc8a ths
3010 c3b5bc8a ths
badframe:
3011 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3012 c3b5bc8a ths
    force_sig(TARGET_SIGSEGV);
3013 c3b5bc8a ths
    return 0;
3014 c3b5bc8a ths
}
3015 c3b5bc8a ths
3016 c3b5bc8a ths
long do_rt_sigreturn(CPUState *regs)
3017 c3b5bc8a ths
{
3018 c3b5bc8a ths
    struct target_rt_sigframe *frame;
3019 c3b5bc8a ths
    abi_ulong frame_addr;
3020 c3b5bc8a ths
    sigset_t blocked;
3021 c3b5bc8a ths
3022 c3b5bc8a ths
#if defined(DEBUG_SIGNAL)
3023 c3b5bc8a ths
    fprintf(stderr, "do_rt_sigreturn\n");
3024 c3b5bc8a ths
#endif
3025 c3b5bc8a ths
    frame_addr = regs->gregs[15];
3026 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3027 c3b5bc8a ths
           goto badframe;
3028 c3b5bc8a ths
3029 c3b5bc8a ths
    target_to_host_sigset(&blocked, &frame->uc.uc_sigmask);
3030 c3b5bc8a ths
    sigprocmask(SIG_SETMASK, &blocked, NULL);
3031 c3b5bc8a ths
3032 c3b5bc8a ths
    if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
3033 c3b5bc8a ths
        goto badframe;
3034 c3b5bc8a ths
3035 c3b5bc8a ths
    if (do_sigaltstack(frame_addr +
3036 c3b5bc8a ths
                       offsetof(struct target_rt_sigframe, uc.uc_stack),
3037 c3b5bc8a ths
                       0, get_sp_from_cpustate(regs)) == -EFAULT)
3038 c3b5bc8a ths
        goto badframe;
3039 c3b5bc8a ths
3040 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3041 c3b5bc8a ths
    return regs->gregs[0];
3042 c3b5bc8a ths
3043 c3b5bc8a ths
badframe:
3044 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3045 c3b5bc8a ths
    force_sig(TARGET_SIGSEGV);
3046 c3b5bc8a ths
    return 0;
3047 c3b5bc8a ths
}
3048 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
3049 b779e29e Edgar E. Iglesias
3050 b779e29e Edgar E. Iglesias
struct target_sigcontext {
3051 b779e29e Edgar E. Iglesias
    struct target_pt_regs regs;  /* needs to be first */
3052 b779e29e Edgar E. Iglesias
    uint32_t oldmask;
3053 b779e29e Edgar E. Iglesias
};
3054 b779e29e Edgar E. Iglesias
3055 b779e29e Edgar E. Iglesias
/* Signal frames. */
3056 b779e29e Edgar E. Iglesias
struct target_signal_frame {
3057 b779e29e Edgar E. Iglesias
    struct target_sigcontext sc;
3058 b779e29e Edgar E. Iglesias
    uint32_t extramask[TARGET_NSIG_WORDS - 1];
3059 b779e29e Edgar E. Iglesias
    uint32_t tramp[2];
3060 b779e29e Edgar E. Iglesias
};
3061 b779e29e Edgar E. Iglesias
3062 b779e29e Edgar E. Iglesias
struct rt_signal_frame {
3063 b779e29e Edgar E. Iglesias
    struct siginfo info;
3064 b779e29e Edgar E. Iglesias
    struct ucontext uc;
3065 b779e29e Edgar E. Iglesias
    uint32_t tramp[2];
3066 b779e29e Edgar E. Iglesias
};
3067 b779e29e Edgar E. Iglesias
3068 b779e29e Edgar E. Iglesias
static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
3069 b779e29e Edgar E. Iglesias
{
3070 b779e29e Edgar E. Iglesias
    __put_user(env->regs[0], &sc->regs.r0);
3071 b779e29e Edgar E. Iglesias
    __put_user(env->regs[1], &sc->regs.r1);
3072 b779e29e Edgar E. Iglesias
    __put_user(env->regs[2], &sc->regs.r2);
3073 b779e29e Edgar E. Iglesias
    __put_user(env->regs[3], &sc->regs.r3);
3074 b779e29e Edgar E. Iglesias
    __put_user(env->regs[4], &sc->regs.r4);
3075 b779e29e Edgar E. Iglesias
    __put_user(env->regs[5], &sc->regs.r5);
3076 b779e29e Edgar E. Iglesias
    __put_user(env->regs[6], &sc->regs.r6);
3077 b779e29e Edgar E. Iglesias
    __put_user(env->regs[7], &sc->regs.r7);
3078 b779e29e Edgar E. Iglesias
    __put_user(env->regs[8], &sc->regs.r8);
3079 b779e29e Edgar E. Iglesias
    __put_user(env->regs[9], &sc->regs.r9);
3080 b779e29e Edgar E. Iglesias
    __put_user(env->regs[10], &sc->regs.r10);
3081 b779e29e Edgar E. Iglesias
    __put_user(env->regs[11], &sc->regs.r11);
3082 b779e29e Edgar E. Iglesias
    __put_user(env->regs[12], &sc->regs.r12);
3083 b779e29e Edgar E. Iglesias
    __put_user(env->regs[13], &sc->regs.r13);
3084 b779e29e Edgar E. Iglesias
    __put_user(env->regs[14], &sc->regs.r14);
3085 b779e29e Edgar E. Iglesias
    __put_user(env->regs[15], &sc->regs.r15);
3086 b779e29e Edgar E. Iglesias
    __put_user(env->regs[16], &sc->regs.r16);
3087 b779e29e Edgar E. Iglesias
    __put_user(env->regs[17], &sc->regs.r17);
3088 b779e29e Edgar E. Iglesias
    __put_user(env->regs[18], &sc->regs.r18);
3089 b779e29e Edgar E. Iglesias
    __put_user(env->regs[19], &sc->regs.r19);
3090 b779e29e Edgar E. Iglesias
    __put_user(env->regs[20], &sc->regs.r20);
3091 b779e29e Edgar E. Iglesias
    __put_user(env->regs[21], &sc->regs.r21);
3092 b779e29e Edgar E. Iglesias
    __put_user(env->regs[22], &sc->regs.r22);
3093 b779e29e Edgar E. Iglesias
    __put_user(env->regs[23], &sc->regs.r23);
3094 b779e29e Edgar E. Iglesias
    __put_user(env->regs[24], &sc->regs.r24);
3095 b779e29e Edgar E. Iglesias
    __put_user(env->regs[25], &sc->regs.r25);
3096 b779e29e Edgar E. Iglesias
    __put_user(env->regs[26], &sc->regs.r26);
3097 b779e29e Edgar E. Iglesias
    __put_user(env->regs[27], &sc->regs.r27);
3098 b779e29e Edgar E. Iglesias
    __put_user(env->regs[28], &sc->regs.r28);
3099 b779e29e Edgar E. Iglesias
    __put_user(env->regs[29], &sc->regs.r29);
3100 b779e29e Edgar E. Iglesias
    __put_user(env->regs[30], &sc->regs.r30);
3101 b779e29e Edgar E. Iglesias
    __put_user(env->regs[31], &sc->regs.r31);
3102 b779e29e Edgar E. Iglesias
    __put_user(env->sregs[SR_PC], &sc->regs.pc);
3103 b779e29e Edgar E. Iglesias
}
3104 b779e29e Edgar E. Iglesias
3105 b779e29e Edgar E. Iglesias
static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
3106 b779e29e Edgar E. Iglesias
{
3107 b779e29e Edgar E. Iglesias
    __get_user(env->regs[0], &sc->regs.r0);
3108 b779e29e Edgar E. Iglesias
    __get_user(env->regs[1], &sc->regs.r1);
3109 b779e29e Edgar E. Iglesias
    __get_user(env->regs[2], &sc->regs.r2);
3110 b779e29e Edgar E. Iglesias
    __get_user(env->regs[3], &sc->regs.r3);
3111 b779e29e Edgar E. Iglesias
    __get_user(env->regs[4], &sc->regs.r4);
3112 b779e29e Edgar E. Iglesias
    __get_user(env->regs[5], &sc->regs.r5);
3113 b779e29e Edgar E. Iglesias
    __get_user(env->regs[6], &sc->regs.r6);
3114 b779e29e Edgar E. Iglesias
    __get_user(env->regs[7], &sc->regs.r7);
3115 b779e29e Edgar E. Iglesias
    __get_user(env->regs[8], &sc->regs.r8);
3116 b779e29e Edgar E. Iglesias
    __get_user(env->regs[9], &sc->regs.r9);
3117 b779e29e Edgar E. Iglesias
    __get_user(env->regs[10], &sc->regs.r10);
3118 b779e29e Edgar E. Iglesias
    __get_user(env->regs[11], &sc->regs.r11);
3119 b779e29e Edgar E. Iglesias
    __get_user(env->regs[12], &sc->regs.r12);
3120 b779e29e Edgar E. Iglesias
    __get_user(env->regs[13], &sc->regs.r13);
3121 b779e29e Edgar E. Iglesias
    __get_user(env->regs[14], &sc->regs.r14);
3122 b779e29e Edgar E. Iglesias
    __get_user(env->regs[15], &sc->regs.r15);
3123 b779e29e Edgar E. Iglesias
    __get_user(env->regs[16], &sc->regs.r16);
3124 b779e29e Edgar E. Iglesias
    __get_user(env->regs[17], &sc->regs.r17);
3125 b779e29e Edgar E. Iglesias
    __get_user(env->regs[18], &sc->regs.r18);
3126 b779e29e Edgar E. Iglesias
    __get_user(env->regs[19], &sc->regs.r19);
3127 b779e29e Edgar E. Iglesias
    __get_user(env->regs[20], &sc->regs.r20);
3128 b779e29e Edgar E. Iglesias
    __get_user(env->regs[21], &sc->regs.r21);
3129 b779e29e Edgar E. Iglesias
    __get_user(env->regs[22], &sc->regs.r22);
3130 b779e29e Edgar E. Iglesias
    __get_user(env->regs[23], &sc->regs.r23);
3131 b779e29e Edgar E. Iglesias
    __get_user(env->regs[24], &sc->regs.r24);
3132 b779e29e Edgar E. Iglesias
    __get_user(env->regs[25], &sc->regs.r25);
3133 b779e29e Edgar E. Iglesias
    __get_user(env->regs[26], &sc->regs.r26);
3134 b779e29e Edgar E. Iglesias
    __get_user(env->regs[27], &sc->regs.r27);
3135 b779e29e Edgar E. Iglesias
    __get_user(env->regs[28], &sc->regs.r28);
3136 b779e29e Edgar E. Iglesias
    __get_user(env->regs[29], &sc->regs.r29);
3137 b779e29e Edgar E. Iglesias
    __get_user(env->regs[30], &sc->regs.r30);
3138 b779e29e Edgar E. Iglesias
    __get_user(env->regs[31], &sc->regs.r31);
3139 b779e29e Edgar E. Iglesias
    __get_user(env->sregs[SR_PC], &sc->regs.pc);
3140 b779e29e Edgar E. Iglesias
}
3141 b779e29e Edgar E. Iglesias
3142 b779e29e Edgar E. Iglesias
static abi_ulong get_sigframe(struct target_sigaction *ka,
3143 b779e29e Edgar E. Iglesias
                              CPUState *env, int frame_size)
3144 b779e29e Edgar E. Iglesias
{
3145 b779e29e Edgar E. Iglesias
    abi_ulong sp = env->regs[1];
3146 b779e29e Edgar E. Iglesias
3147 b779e29e Edgar E. Iglesias
    if ((ka->sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
3148 b779e29e Edgar E. Iglesias
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3149 b779e29e Edgar E. Iglesias
3150 b779e29e Edgar E. Iglesias
    return ((sp - frame_size) & -8UL);
3151 b779e29e Edgar E. Iglesias
}
3152 b779e29e Edgar E. Iglesias
3153 b779e29e Edgar E. Iglesias
static void setup_frame(int sig, struct target_sigaction *ka,
3154 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
3155 b779e29e Edgar E. Iglesias
{
3156 b779e29e Edgar E. Iglesias
    struct target_signal_frame *frame;
3157 b779e29e Edgar E. Iglesias
    abi_ulong frame_addr;
3158 b779e29e Edgar E. Iglesias
    int err = 0;
3159 b779e29e Edgar E. Iglesias
    int i;
3160 b779e29e Edgar E. Iglesias
3161 b779e29e Edgar E. Iglesias
    frame_addr = get_sigframe(ka, env, sizeof *frame);
3162 b779e29e Edgar E. Iglesias
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3163 b779e29e Edgar E. Iglesias
        goto badframe;
3164 b779e29e Edgar E. Iglesias
3165 b779e29e Edgar E. Iglesias
    /* Save the mask.  */
3166 b779e29e Edgar E. Iglesias
    err |= __put_user(set->sig[0], &frame->sc.oldmask);
3167 b779e29e Edgar E. Iglesias
    if (err)
3168 b779e29e Edgar E. Iglesias
        goto badframe;
3169 b779e29e Edgar E. Iglesias
3170 b779e29e Edgar E. Iglesias
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3171 b779e29e Edgar E. Iglesias
        if (__put_user(set->sig[i], &frame->extramask[i - 1]))
3172 b779e29e Edgar E. Iglesias
            goto badframe;
3173 b779e29e Edgar E. Iglesias
    }
3174 b779e29e Edgar E. Iglesias
3175 b779e29e Edgar E. Iglesias
    setup_sigcontext(&frame->sc, env);
3176 b779e29e Edgar E. Iglesias
3177 b779e29e Edgar E. Iglesias
    /* Set up to return from userspace. If provided, use a stub
3178 b779e29e Edgar E. Iglesias
       already in userspace. */
3179 b779e29e Edgar E. Iglesias
    /* minus 8 is offset to cater for "rtsd r15,8" offset */
3180 b779e29e Edgar E. Iglesias
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3181 b779e29e Edgar E. Iglesias
        env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3182 b779e29e Edgar E. Iglesias
    } else {
3183 b779e29e Edgar E. Iglesias
        uint32_t t;
3184 b779e29e Edgar E. Iglesias
        /* Note, these encodings are _big endian_! */
3185 b779e29e Edgar E. Iglesias
        /* addi r12, r0, __NR_sigreturn */
3186 b779e29e Edgar E. Iglesias
        t = 0x31800000UL | TARGET_NR_sigreturn;
3187 b779e29e Edgar E. Iglesias
        err |= __put_user(t, frame->tramp + 0);
3188 b779e29e Edgar E. Iglesias
        /* brki r14, 0x8 */
3189 b779e29e Edgar E. Iglesias
        t = 0xb9cc0008UL;
3190 b779e29e Edgar E. Iglesias
        err |= __put_user(t, frame->tramp + 1);
3191 b779e29e Edgar E. Iglesias
3192 b779e29e Edgar E. Iglesias
        /* Return from sighandler will jump to the tramp.
3193 b779e29e Edgar E. Iglesias
           Negative 8 offset because return is rtsd r15, 8 */
3194 b779e29e Edgar E. Iglesias
        env->regs[15] = ((unsigned long)frame->tramp) - 8;
3195 b779e29e Edgar E. Iglesias
    }
3196 b779e29e Edgar E. Iglesias
3197 b779e29e Edgar E. Iglesias
    if (err)
3198 b779e29e Edgar E. Iglesias
        goto badframe;
3199 b779e29e Edgar E. Iglesias
3200 b779e29e Edgar E. Iglesias
    /* Set up registers for signal handler */
3201 b779e29e Edgar E. Iglesias
    env->regs[1] = (unsigned long) frame;
3202 b779e29e Edgar E. Iglesias
    /* Signal handler args: */
3203 b779e29e Edgar E. Iglesias
    env->regs[5] = sig; /* Arg 0: signum */
3204 b779e29e Edgar E. Iglesias
    env->regs[6] = (unsigned long) &frame->sc; /* arg 1: sigcontext */
3205 b779e29e Edgar E. Iglesias
3206 b779e29e Edgar E. Iglesias
    /* Offset of 4 to handle microblaze rtid r14, 0 */
3207 b779e29e Edgar E. Iglesias
    env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3208 b779e29e Edgar E. Iglesias
3209 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 1);
3210 b779e29e Edgar E. Iglesias
    return;
3211 b779e29e Edgar E. Iglesias
  badframe:
3212 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 1);
3213 b779e29e Edgar E. Iglesias
    force_sig(TARGET_SIGSEGV);
3214 b779e29e Edgar E. Iglesias
}
3215 b779e29e Edgar E. Iglesias
3216 b779e29e Edgar E. Iglesias
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3217 c227f099 Anthony Liguori
                           target_siginfo_t *info,
3218 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
3219 b779e29e Edgar E. Iglesias
{
3220 b779e29e Edgar E. Iglesias
    fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3221 b779e29e Edgar E. Iglesias
}
3222 b779e29e Edgar E. Iglesias
3223 b779e29e Edgar E. Iglesias
long do_sigreturn(CPUState *env)
3224 b779e29e Edgar E. Iglesias
{
3225 b779e29e Edgar E. Iglesias
    struct target_signal_frame *frame;
3226 b779e29e Edgar E. Iglesias
    abi_ulong frame_addr;
3227 c227f099 Anthony Liguori
    target_sigset_t target_set;
3228 b779e29e Edgar E. Iglesias
    sigset_t set;
3229 b779e29e Edgar E. Iglesias
    int i;
3230 b779e29e Edgar E. Iglesias
3231 b779e29e Edgar E. Iglesias
    frame_addr = env->regs[R_SP];
3232 b779e29e Edgar E. Iglesias
    /* Make sure the guest isn't playing games.  */
3233 b779e29e Edgar E. Iglesias
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3234 b779e29e Edgar E. Iglesias
        goto badframe;
3235 b779e29e Edgar E. Iglesias
3236 b779e29e Edgar E. Iglesias
    /* Restore blocked signals */
3237 b779e29e Edgar E. Iglesias
    if (__get_user(target_set.sig[0], &frame->sc.oldmask))
3238 b779e29e Edgar E. Iglesias
        goto badframe;
3239 b779e29e Edgar E. Iglesias
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3240 b779e29e Edgar E. Iglesias
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
3241 b779e29e Edgar E. Iglesias
            goto badframe;
3242 b779e29e Edgar E. Iglesias
    }
3243 b779e29e Edgar E. Iglesias
    target_to_host_sigset_internal(&set, &target_set);
3244 b779e29e Edgar E. Iglesias
    sigprocmask(SIG_SETMASK, &set, NULL);
3245 b779e29e Edgar E. Iglesias
3246 b779e29e Edgar E. Iglesias
    restore_sigcontext(&frame->sc, env);
3247 b779e29e Edgar E. Iglesias
    /* We got here through a sigreturn syscall, our path back is via an
3248 b779e29e Edgar E. Iglesias
       rtb insn so setup r14 for that.  */
3249 b779e29e Edgar E. Iglesias
    env->regs[14] = env->sregs[SR_PC];
3250 b779e29e Edgar E. Iglesias
 
3251 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 0);
3252 b779e29e Edgar E. Iglesias
    return env->regs[10];
3253 b779e29e Edgar E. Iglesias
  badframe:
3254 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 0);
3255 b779e29e Edgar E. Iglesias
    force_sig(TARGET_SIGSEGV);
3256 b779e29e Edgar E. Iglesias
}
3257 b779e29e Edgar E. Iglesias
3258 b779e29e Edgar E. Iglesias
long do_rt_sigreturn(CPUState *env)
3259 b779e29e Edgar E. Iglesias
{
3260 b779e29e Edgar E. Iglesias
    fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3261 b779e29e Edgar E. Iglesias
    return -TARGET_ENOSYS;
3262 b779e29e Edgar E. Iglesias
}
3263 b779e29e Edgar E. Iglesias
3264 b6d3abda edgar_igl
#elif defined(TARGET_CRIS)
3265 b6d3abda edgar_igl
3266 b6d3abda edgar_igl
struct target_sigcontext {
3267 b6d3abda edgar_igl
        struct target_pt_regs regs;  /* needs to be first */
3268 b6d3abda edgar_igl
        uint32_t oldmask;
3269 b6d3abda edgar_igl
        uint32_t usp;    /* usp before stacking this gunk on it */
3270 b6d3abda edgar_igl
};
3271 b6d3abda edgar_igl
3272 b6d3abda edgar_igl
/* Signal frames. */
3273 b6d3abda edgar_igl
struct target_signal_frame {
3274 b6d3abda edgar_igl
        struct target_sigcontext sc;
3275 b6d3abda edgar_igl
        uint32_t extramask[TARGET_NSIG_WORDS - 1];
3276 b6d3abda edgar_igl
        uint8_t retcode[8];       /* Trampoline code. */
3277 b6d3abda edgar_igl
};
3278 b6d3abda edgar_igl
3279 b6d3abda edgar_igl
struct rt_signal_frame {
3280 b6d3abda edgar_igl
        struct siginfo *pinfo;
3281 b6d3abda edgar_igl
        void *puc;
3282 b6d3abda edgar_igl
        struct siginfo info;
3283 b6d3abda edgar_igl
        struct ucontext uc;
3284 b6d3abda edgar_igl
        uint8_t retcode[8];       /* Trampoline code. */
3285 b6d3abda edgar_igl
};
3286 b6d3abda edgar_igl
3287 b6d3abda edgar_igl
static void setup_sigcontext(struct target_sigcontext *sc, CPUState *env)
3288 b6d3abda edgar_igl
{
3289 9664d928 edgar_igl
        __put_user(env->regs[0], &sc->regs.r0);
3290 9664d928 edgar_igl
        __put_user(env->regs[1], &sc->regs.r1);
3291 9664d928 edgar_igl
        __put_user(env->regs[2], &sc->regs.r2);
3292 9664d928 edgar_igl
        __put_user(env->regs[3], &sc->regs.r3);
3293 9664d928 edgar_igl
        __put_user(env->regs[4], &sc->regs.r4);
3294 9664d928 edgar_igl
        __put_user(env->regs[5], &sc->regs.r5);
3295 9664d928 edgar_igl
        __put_user(env->regs[6], &sc->regs.r6);
3296 9664d928 edgar_igl
        __put_user(env->regs[7], &sc->regs.r7);
3297 9664d928 edgar_igl
        __put_user(env->regs[8], &sc->regs.r8);
3298 9664d928 edgar_igl
        __put_user(env->regs[9], &sc->regs.r9);
3299 9664d928 edgar_igl
        __put_user(env->regs[10], &sc->regs.r10);
3300 9664d928 edgar_igl
        __put_user(env->regs[11], &sc->regs.r11);
3301 9664d928 edgar_igl
        __put_user(env->regs[12], &sc->regs.r12);
3302 9664d928 edgar_igl
        __put_user(env->regs[13], &sc->regs.r13);
3303 9664d928 edgar_igl
        __put_user(env->regs[14], &sc->usp);
3304 9664d928 edgar_igl
        __put_user(env->regs[15], &sc->regs.acr);
3305 9664d928 edgar_igl
        __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3306 9664d928 edgar_igl
        __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3307 9664d928 edgar_igl
        __put_user(env->pc, &sc->regs.erp);
3308 b6d3abda edgar_igl
}
3309 9664d928 edgar_igl
3310 b6d3abda edgar_igl
static void restore_sigcontext(struct target_sigcontext *sc, CPUState *env)
3311 b6d3abda edgar_igl
{
3312 9664d928 edgar_igl
        __get_user(env->regs[0], &sc->regs.r0);
3313 9664d928 edgar_igl
        __get_user(env->regs[1], &sc->regs.r1);
3314 9664d928 edgar_igl
        __get_user(env->regs[2], &sc->regs.r2);
3315 9664d928 edgar_igl
        __get_user(env->regs[3], &sc->regs.r3);
3316 9664d928 edgar_igl
        __get_user(env->regs[4], &sc->regs.r4);
3317 9664d928 edgar_igl
        __get_user(env->regs[5], &sc->regs.r5);
3318 9664d928 edgar_igl
        __get_user(env->regs[6], &sc->regs.r6);
3319 9664d928 edgar_igl
        __get_user(env->regs[7], &sc->regs.r7);
3320 9664d928 edgar_igl
        __get_user(env->regs[8], &sc->regs.r8);
3321 9664d928 edgar_igl
        __get_user(env->regs[9], &sc->regs.r9);
3322 9664d928 edgar_igl
        __get_user(env->regs[10], &sc->regs.r10);
3323 9664d928 edgar_igl
        __get_user(env->regs[11], &sc->regs.r11);
3324 9664d928 edgar_igl
        __get_user(env->regs[12], &sc->regs.r12);
3325 9664d928 edgar_igl
        __get_user(env->regs[13], &sc->regs.r13);
3326 9664d928 edgar_igl
        __get_user(env->regs[14], &sc->usp);
3327 9664d928 edgar_igl
        __get_user(env->regs[15], &sc->regs.acr);
3328 9664d928 edgar_igl
        __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3329 9664d928 edgar_igl
        __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3330 9664d928 edgar_igl
        __get_user(env->pc, &sc->regs.erp);
3331 9664d928 edgar_igl
}
3332 9664d928 edgar_igl
3333 9664d928 edgar_igl
static abi_ulong get_sigframe(CPUState *env, int framesize)
3334 9664d928 edgar_igl
{
3335 9664d928 edgar_igl
        abi_ulong sp;
3336 b6d3abda edgar_igl
        /* Align the stack downwards to 4.  */
3337 9664d928 edgar_igl
        sp = (env->regs[R_SP] & ~3);
3338 9664d928 edgar_igl
        return sp - framesize;
3339 b6d3abda edgar_igl
}
3340 b6d3abda edgar_igl
3341 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
3342 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
3343 b6d3abda edgar_igl
{
3344 b6d3abda edgar_igl
        struct target_signal_frame *frame;
3345 9664d928 edgar_igl
        abi_ulong frame_addr;
3346 b6d3abda edgar_igl
        int err = 0;
3347 b6d3abda edgar_igl
        int i;
3348 b6d3abda edgar_igl
3349 9664d928 edgar_igl
        frame_addr = get_sigframe(env, sizeof *frame);
3350 9664d928 edgar_igl
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3351 b6d3abda edgar_igl
                goto badframe;
3352 b6d3abda edgar_igl
3353 b6d3abda edgar_igl
        /*
3354 b6d3abda edgar_igl
         * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3355 b6d3abda edgar_igl
         * use this trampoline anymore but it sets it up for GDB.
3356 b6d3abda edgar_igl
         * In QEMU, using the trampoline simplifies things a bit so we use it.
3357 b6d3abda edgar_igl
         *
3358 b6d3abda edgar_igl
         * This is movu.w __NR_sigreturn, r9; break 13;
3359 b6d3abda edgar_igl
         */
3360 b6d3abda edgar_igl
        err |= __put_user(0x9c5f, frame->retcode+0);
3361 b6d3abda edgar_igl
        err |= __put_user(TARGET_NR_sigreturn, 
3362 b6d3abda edgar_igl
                          frame->retcode+2);
3363 b6d3abda edgar_igl
        err |= __put_user(0xe93d, frame->retcode+4);
3364 b6d3abda edgar_igl
3365 b6d3abda edgar_igl
        /* Save the mask.  */
3366 b6d3abda edgar_igl
        err |= __put_user(set->sig[0], &frame->sc.oldmask);
3367 b6d3abda edgar_igl
        if (err)
3368 b6d3abda edgar_igl
                goto badframe;
3369 b6d3abda edgar_igl
3370 b6d3abda edgar_igl
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3371 b6d3abda edgar_igl
                if (__put_user(set->sig[i], &frame->extramask[i - 1]))
3372 b6d3abda edgar_igl
                        goto badframe;
3373 b6d3abda edgar_igl
        }
3374 b6d3abda edgar_igl
3375 b6d3abda edgar_igl
        setup_sigcontext(&frame->sc, env);
3376 b6d3abda edgar_igl
3377 b6d3abda edgar_igl
        /* Move the stack and setup the arguments for the handler.  */
3378 526ccb7a balrog
        env->regs[R_SP] = (uint32_t) (unsigned long) frame;
3379 b6d3abda edgar_igl
        env->regs[10] = sig;
3380 624f7979 pbrook
        env->pc = (unsigned long) ka->_sa_handler;
3381 b6d3abda edgar_igl
        /* Link SRP so the guest returns through the trampoline.  */
3382 526ccb7a balrog
        env->pregs[PR_SRP] = (uint32_t) (unsigned long) &frame->retcode[0];
3383 b6d3abda edgar_igl
3384 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 1);
3385 b6d3abda edgar_igl
        return;
3386 b6d3abda edgar_igl
  badframe:
3387 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 1);
3388 b6d3abda edgar_igl
        force_sig(TARGET_SIGSEGV);
3389 b6d3abda edgar_igl
}
3390 b6d3abda edgar_igl
3391 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3392 c227f099 Anthony Liguori
                           target_siginfo_t *info,
3393 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
3394 b6d3abda edgar_igl
{
3395 b6d3abda edgar_igl
    fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3396 b6d3abda edgar_igl
}
3397 b6d3abda edgar_igl
3398 b6d3abda edgar_igl
long do_sigreturn(CPUState *env)
3399 b6d3abda edgar_igl
{
3400 b6d3abda edgar_igl
        struct target_signal_frame *frame;
3401 9664d928 edgar_igl
        abi_ulong frame_addr;
3402 c227f099 Anthony Liguori
        target_sigset_t target_set;
3403 b6d3abda edgar_igl
        sigset_t set;
3404 b6d3abda edgar_igl
        int i;
3405 b6d3abda edgar_igl
3406 9664d928 edgar_igl
        frame_addr = env->regs[R_SP];
3407 b6d3abda edgar_igl
        /* Make sure the guest isn't playing games.  */
3408 9664d928 edgar_igl
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3409 b6d3abda edgar_igl
                goto badframe;
3410 b6d3abda edgar_igl
3411 b6d3abda edgar_igl
        /* Restore blocked signals */
3412 b6d3abda edgar_igl
        if (__get_user(target_set.sig[0], &frame->sc.oldmask))
3413 b6d3abda edgar_igl
                goto badframe;
3414 b6d3abda edgar_igl
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3415 b6d3abda edgar_igl
                if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
3416 b6d3abda edgar_igl
                        goto badframe;
3417 b6d3abda edgar_igl
        }
3418 b6d3abda edgar_igl
        target_to_host_sigset_internal(&set, &target_set);
3419 b6d3abda edgar_igl
        sigprocmask(SIG_SETMASK, &set, NULL);
3420 b6d3abda edgar_igl
3421 b6d3abda edgar_igl
        restore_sigcontext(&frame->sc, env);
3422 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 0);
3423 b6d3abda edgar_igl
        return env->regs[10];
3424 b6d3abda edgar_igl
  badframe:
3425 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 0);
3426 b6d3abda edgar_igl
        force_sig(TARGET_SIGSEGV);
3427 b6d3abda edgar_igl
}
3428 b6d3abda edgar_igl
3429 b6d3abda edgar_igl
long do_rt_sigreturn(CPUState *env)
3430 b6d3abda edgar_igl
{
3431 b6d3abda edgar_igl
    fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3432 b6d3abda edgar_igl
    return -TARGET_ENOSYS;
3433 b6d3abda edgar_igl
}
3434 c3b5bc8a ths
3435 bcd4933a Nathan Froyd
#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
3436 bcd4933a Nathan Froyd
3437 bcd4933a Nathan Froyd
/* FIXME: Many of the structures are defined for both PPC and PPC64, but
3438 bcd4933a Nathan Froyd
   the signal handling is different enough that we haven't implemented
3439 bcd4933a Nathan Froyd
   support for PPC64 yet.  Hence the restriction above.
3440 bcd4933a Nathan Froyd

3441 bcd4933a Nathan Froyd
   There are various #if'd blocks for code for TARGET_PPC64.  These
3442 bcd4933a Nathan Froyd
   blocks should go away so that we can successfully run 32-bit and
3443 bcd4933a Nathan Froyd
   64-bit binaries on a QEMU configured for PPC64.  */
3444 bcd4933a Nathan Froyd
3445 bcd4933a Nathan Froyd
/* Size of dummy stack frame allocated when calling signal handler.
3446 bcd4933a Nathan Froyd
   See arch/powerpc/include/asm/ptrace.h.  */
3447 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3448 bcd4933a Nathan Froyd
#define SIGNAL_FRAMESIZE 128
3449 bcd4933a Nathan Froyd
#else
3450 bcd4933a Nathan Froyd
#define SIGNAL_FRAMESIZE 64
3451 bcd4933a Nathan Froyd
#endif
3452 bcd4933a Nathan Froyd
3453 bcd4933a Nathan Froyd
/* See arch/powerpc/include/asm/sigcontext.h.  */
3454 bcd4933a Nathan Froyd
struct target_sigcontext {
3455 bcd4933a Nathan Froyd
    target_ulong _unused[4];
3456 bcd4933a Nathan Froyd
    int32_t signal;
3457 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3458 bcd4933a Nathan Froyd
    int32_t pad0;
3459 bcd4933a Nathan Froyd
#endif
3460 bcd4933a Nathan Froyd
    target_ulong handler;
3461 bcd4933a Nathan Froyd
    target_ulong oldmask;
3462 bcd4933a Nathan Froyd
    target_ulong regs;      /* struct pt_regs __user * */
3463 bcd4933a Nathan Froyd
    /* TODO: PPC64 includes extra bits here.  */
3464 bcd4933a Nathan Froyd
};
3465 bcd4933a Nathan Froyd
3466 bcd4933a Nathan Froyd
/* Indices for target_mcontext.mc_gregs, below.
3467 bcd4933a Nathan Froyd
   See arch/powerpc/include/asm/ptrace.h for details.  */
3468 bcd4933a Nathan Froyd
enum {
3469 bcd4933a Nathan Froyd
    TARGET_PT_R0 = 0,
3470 bcd4933a Nathan Froyd
    TARGET_PT_R1 = 1,
3471 bcd4933a Nathan Froyd
    TARGET_PT_R2 = 2,
3472 bcd4933a Nathan Froyd
    TARGET_PT_R3 = 3,
3473 bcd4933a Nathan Froyd
    TARGET_PT_R4 = 4,
3474 bcd4933a Nathan Froyd
    TARGET_PT_R5 = 5,
3475 bcd4933a Nathan Froyd
    TARGET_PT_R6 = 6,
3476 bcd4933a Nathan Froyd
    TARGET_PT_R7 = 7,
3477 bcd4933a Nathan Froyd
    TARGET_PT_R8 = 8,
3478 bcd4933a Nathan Froyd
    TARGET_PT_R9 = 9,
3479 bcd4933a Nathan Froyd
    TARGET_PT_R10 = 10,
3480 bcd4933a Nathan Froyd
    TARGET_PT_R11 = 11,
3481 bcd4933a Nathan Froyd
    TARGET_PT_R12 = 12,
3482 bcd4933a Nathan Froyd
    TARGET_PT_R13 = 13,
3483 bcd4933a Nathan Froyd
    TARGET_PT_R14 = 14,
3484 bcd4933a Nathan Froyd
    TARGET_PT_R15 = 15,
3485 bcd4933a Nathan Froyd
    TARGET_PT_R16 = 16,
3486 bcd4933a Nathan Froyd
    TARGET_PT_R17 = 17,
3487 bcd4933a Nathan Froyd
    TARGET_PT_R18 = 18,
3488 bcd4933a Nathan Froyd
    TARGET_PT_R19 = 19,
3489 bcd4933a Nathan Froyd
    TARGET_PT_R20 = 20,
3490 bcd4933a Nathan Froyd
    TARGET_PT_R21 = 21,
3491 bcd4933a Nathan Froyd
    TARGET_PT_R22 = 22,
3492 bcd4933a Nathan Froyd
    TARGET_PT_R23 = 23,
3493 bcd4933a Nathan Froyd
    TARGET_PT_R24 = 24,
3494 bcd4933a Nathan Froyd
    TARGET_PT_R25 = 25,
3495 bcd4933a Nathan Froyd
    TARGET_PT_R26 = 26,
3496 bcd4933a Nathan Froyd
    TARGET_PT_R27 = 27,
3497 bcd4933a Nathan Froyd
    TARGET_PT_R28 = 28,
3498 bcd4933a Nathan Froyd
    TARGET_PT_R29 = 29,
3499 bcd4933a Nathan Froyd
    TARGET_PT_R30 = 30,
3500 bcd4933a Nathan Froyd
    TARGET_PT_R31 = 31,
3501 bcd4933a Nathan Froyd
    TARGET_PT_NIP = 32,
3502 bcd4933a Nathan Froyd
    TARGET_PT_MSR = 33,
3503 bcd4933a Nathan Froyd
    TARGET_PT_ORIG_R3 = 34,
3504 bcd4933a Nathan Froyd
    TARGET_PT_CTR = 35,
3505 bcd4933a Nathan Froyd
    TARGET_PT_LNK = 36,
3506 bcd4933a Nathan Froyd
    TARGET_PT_XER = 37,
3507 bcd4933a Nathan Froyd
    TARGET_PT_CCR = 38,
3508 bcd4933a Nathan Froyd
    /* Yes, there are two registers with #39.  One is 64-bit only.  */
3509 bcd4933a Nathan Froyd
    TARGET_PT_MQ = 39,
3510 bcd4933a Nathan Froyd
    TARGET_PT_SOFTE = 39,
3511 bcd4933a Nathan Froyd
    TARGET_PT_TRAP = 40,
3512 bcd4933a Nathan Froyd
    TARGET_PT_DAR = 41,
3513 bcd4933a Nathan Froyd
    TARGET_PT_DSISR = 42,
3514 bcd4933a Nathan Froyd
    TARGET_PT_RESULT = 43,
3515 bcd4933a Nathan Froyd
    TARGET_PT_REGS_COUNT = 44
3516 bcd4933a Nathan Froyd
};
3517 bcd4933a Nathan Froyd
3518 bcd4933a Nathan Froyd
/* See arch/powerpc/include/asm/ucontext.h.  Only used for 32-bit PPC;
3519 bcd4933a Nathan Froyd
   on 64-bit PPC, sigcontext and mcontext are one and the same.  */
3520 bcd4933a Nathan Froyd
struct target_mcontext {
3521 bcd4933a Nathan Froyd
    target_ulong mc_gregs[48];
3522 bcd4933a Nathan Froyd
    /* Includes fpscr.  */
3523 bcd4933a Nathan Froyd
    uint64_t mc_fregs[33];
3524 bcd4933a Nathan Froyd
    target_ulong mc_pad[2];
3525 bcd4933a Nathan Froyd
    /* We need to handle Altivec and SPE at the same time, which no
3526 bcd4933a Nathan Froyd
       kernel needs to do.  Fortunately, the kernel defines this bit to
3527 bcd4933a Nathan Froyd
       be Altivec-register-large all the time, rather than trying to
3528 bcd4933a Nathan Froyd
       twiddle it based on the specific platform.  */
3529 bcd4933a Nathan Froyd
    union {
3530 bcd4933a Nathan Froyd
        /* SPE vector registers.  One extra for SPEFSCR.  */
3531 bcd4933a Nathan Froyd
        uint32_t spe[33];
3532 bcd4933a Nathan Froyd
        /* Altivec vector registers.  The packing of VSCR and VRSAVE
3533 bcd4933a Nathan Froyd
           varies depending on whether we're PPC64 or not: PPC64 splits
3534 bcd4933a Nathan Froyd
           them apart; PPC32 stuffs them together.  */
3535 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3536 3efa9a67 malc
#define QEMU_NVRREG 34
3537 bcd4933a Nathan Froyd
#else
3538 3efa9a67 malc
#define QEMU_NVRREG 33
3539 bcd4933a Nathan Froyd
#endif
3540 c227f099 Anthony Liguori
        ppc_avr_t altivec[QEMU_NVRREG];
3541 3efa9a67 malc
#undef QEMU_NVRREG
3542 bcd4933a Nathan Froyd
    } mc_vregs __attribute__((__aligned__(16)));
3543 bcd4933a Nathan Froyd
};
3544 bcd4933a Nathan Froyd
3545 bcd4933a Nathan Froyd
struct target_ucontext {
3546 bcd4933a Nathan Froyd
    target_ulong uc_flags;
3547 bcd4933a Nathan Froyd
    target_ulong uc_link;    /* struct ucontext __user * */
3548 bcd4933a Nathan Froyd
    struct target_sigaltstack uc_stack;
3549 bcd4933a Nathan Froyd
#if !defined(TARGET_PPC64)
3550 bcd4933a Nathan Froyd
    int32_t uc_pad[7];
3551 bcd4933a Nathan Froyd
    target_ulong uc_regs;    /* struct mcontext __user *
3552 bcd4933a Nathan Froyd
                                points to uc_mcontext field */
3553 bcd4933a Nathan Froyd
#endif
3554 c227f099 Anthony Liguori
    target_sigset_t uc_sigmask;
3555 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3556 c227f099 Anthony Liguori
    target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
3557 bcd4933a Nathan Froyd
    struct target_sigcontext uc_mcontext;
3558 bcd4933a Nathan Froyd
#else
3559 bcd4933a Nathan Froyd
    int32_t uc_maskext[30];
3560 bcd4933a Nathan Froyd
    int32_t uc_pad2[3];
3561 bcd4933a Nathan Froyd
    struct target_mcontext uc_mcontext;
3562 bcd4933a Nathan Froyd
#endif
3563 bcd4933a Nathan Froyd
};
3564 bcd4933a Nathan Froyd
3565 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal_32.c.  */
3566 bcd4933a Nathan Froyd
struct target_sigframe {
3567 bcd4933a Nathan Froyd
    struct target_sigcontext sctx;
3568 bcd4933a Nathan Froyd
    struct target_mcontext mctx;
3569 bcd4933a Nathan Froyd
    int32_t abigap[56];
3570 bcd4933a Nathan Froyd
};
3571 bcd4933a Nathan Froyd
3572 bcd4933a Nathan Froyd
struct target_rt_sigframe {
3573 bcd4933a Nathan Froyd
    struct target_siginfo info;
3574 bcd4933a Nathan Froyd
    struct target_ucontext uc;
3575 bcd4933a Nathan Froyd
    int32_t abigap[56];
3576 bcd4933a Nathan Froyd
};
3577 bcd4933a Nathan Froyd
3578 bcd4933a Nathan Froyd
/* We use the mc_pad field for the signal return trampoline.  */
3579 bcd4933a Nathan Froyd
#define tramp mc_pad
3580 bcd4933a Nathan Froyd
3581 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal.c.  */
3582 bcd4933a Nathan Froyd
static target_ulong get_sigframe(struct target_sigaction *ka,
3583 bcd4933a Nathan Froyd
                                 CPUState *env,
3584 bcd4933a Nathan Froyd
                                 int frame_size)
3585 bcd4933a Nathan Froyd
{
3586 bcd4933a Nathan Froyd
    target_ulong oldsp, newsp;
3587 bcd4933a Nathan Froyd
3588 bcd4933a Nathan Froyd
    oldsp = env->gpr[1];
3589 bcd4933a Nathan Froyd
3590 bcd4933a Nathan Froyd
    if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
3591 bcd4933a Nathan Froyd
        (sas_ss_flags(oldsp))) {
3592 bcd4933a Nathan Froyd
        oldsp = (target_sigaltstack_used.ss_sp
3593 bcd4933a Nathan Froyd
                 + target_sigaltstack_used.ss_size);
3594 bcd4933a Nathan Froyd
    }
3595 bcd4933a Nathan Froyd
3596 bcd4933a Nathan Froyd
    newsp = (oldsp - frame_size) & ~0xFUL;
3597 bcd4933a Nathan Froyd
3598 bcd4933a Nathan Froyd
    return newsp;
3599 bcd4933a Nathan Froyd
}
3600 bcd4933a Nathan Froyd
3601 bcd4933a Nathan Froyd
static int save_user_regs(CPUState *env, struct target_mcontext *frame,
3602 bcd4933a Nathan Froyd
                          int sigret)
3603 bcd4933a Nathan Froyd
{
3604 bcd4933a Nathan Froyd
    target_ulong msr = env->msr;
3605 bcd4933a Nathan Froyd
    int i;
3606 bcd4933a Nathan Froyd
    target_ulong ccr = 0;
3607 bcd4933a Nathan Froyd
3608 bcd4933a Nathan Froyd
    /* In general, the kernel attempts to be intelligent about what it
3609 bcd4933a Nathan Froyd
       needs to save for Altivec/FP/SPE registers.  We don't care that
3610 bcd4933a Nathan Froyd
       much, so we just go ahead and save everything.  */
3611 bcd4933a Nathan Froyd
3612 bcd4933a Nathan Froyd
    /* Save general registers.  */
3613 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
3614 bcd4933a Nathan Froyd
        if (__put_user(env->gpr[i], &frame->mc_gregs[i])) {
3615 bcd4933a Nathan Froyd
            return 1;
3616 bcd4933a Nathan Froyd
        }
3617 bcd4933a Nathan Froyd
    }
3618 bcd4933a Nathan Froyd
    if (__put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
3619 bcd4933a Nathan Froyd
        || __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
3620 bcd4933a Nathan Froyd
        || __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
3621 bcd4933a Nathan Froyd
        || __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
3622 bcd4933a Nathan Froyd
        return 1;
3623 bcd4933a Nathan Froyd
3624 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
3625 bcd4933a Nathan Froyd
        ccr |= env->crf[i] << (32 - ((i + 1) * 4));
3626 bcd4933a Nathan Froyd
    }
3627 bcd4933a Nathan Froyd
    if (__put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
3628 bcd4933a Nathan Froyd
        return 1;
3629 bcd4933a Nathan Froyd
3630 bcd4933a Nathan Froyd
    /* Save Altivec registers if necessary.  */
3631 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_ALTIVEC) {
3632 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
3633 c227f099 Anthony Liguori
            ppc_avr_t *avr = &env->avr[i];
3634 c227f099 Anthony Liguori
            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
3635 bcd4933a Nathan Froyd
3636 bcd4933a Nathan Froyd
            if (__put_user(avr->u64[0], &vreg->u64[0]) ||
3637 bcd4933a Nathan Froyd
                __put_user(avr->u64[1], &vreg->u64[1])) {
3638 bcd4933a Nathan Froyd
                return 1;
3639 bcd4933a Nathan Froyd
            }
3640 bcd4933a Nathan Froyd
        }
3641 bcd4933a Nathan Froyd
        /* Set MSR_VR in the saved MSR value to indicate that
3642 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
3643 bcd4933a Nathan Froyd
        msr |= MSR_VR;
3644 bcd4933a Nathan Froyd
        if (__put_user((uint32_t)env->spr[SPR_VRSAVE],
3645 bcd4933a Nathan Froyd
                       &frame->mc_vregs.altivec[32].u32[3]))
3646 bcd4933a Nathan Froyd
            return 1;
3647 bcd4933a Nathan Froyd
    }
3648 bcd4933a Nathan Froyd
3649 bcd4933a Nathan Froyd
    /* Save floating point registers.  */
3650 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_FLOAT) {
3651 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
3652 bcd4933a Nathan Froyd
            if (__put_user(env->fpr[i], &frame->mc_fregs[i])) {
3653 bcd4933a Nathan Froyd
                return 1;
3654 bcd4933a Nathan Froyd
            }
3655 bcd4933a Nathan Froyd
        }
3656 bcd4933a Nathan Froyd
        if (__put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]))
3657 bcd4933a Nathan Froyd
            return 1;
3658 bcd4933a Nathan Froyd
    }
3659 bcd4933a Nathan Froyd
3660 bcd4933a Nathan Froyd
    /* Save SPE registers.  The kernel only saves the high half.  */
3661 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_SPE) {
3662 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3663 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
3664 bcd4933a Nathan Froyd
            if (__put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i])) {
3665 bcd4933a Nathan Froyd
                return 1;
3666 bcd4933a Nathan Froyd
            }
3667 bcd4933a Nathan Froyd
        }
3668 bcd4933a Nathan Froyd
#else
3669 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
3670 bcd4933a Nathan Froyd
            if (__put_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
3671 bcd4933a Nathan Froyd
                return 1;
3672 bcd4933a Nathan Froyd
            }
3673 bcd4933a Nathan Froyd
        }
3674 bcd4933a Nathan Froyd
#endif
3675 bcd4933a Nathan Froyd
        /* Set MSR_SPE in the saved MSR value to indicate that
3676 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
3677 bcd4933a Nathan Froyd
        msr |= MSR_SPE;
3678 bcd4933a Nathan Froyd
        if (__put_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
3679 bcd4933a Nathan Froyd
            return 1;
3680 bcd4933a Nathan Froyd
    }
3681 bcd4933a Nathan Froyd
3682 bcd4933a Nathan Froyd
    /* Store MSR.  */
3683 bcd4933a Nathan Froyd
    if (__put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
3684 bcd4933a Nathan Froyd
        return 1;
3685 bcd4933a Nathan Froyd
3686 bcd4933a Nathan Froyd
    /* Set up the sigreturn trampoline: li r0,sigret; sc.  */
3687 bcd4933a Nathan Froyd
    if (sigret) {
3688 bcd4933a Nathan Froyd
        if (__put_user(0x38000000UL | sigret, &frame->tramp[0]) ||
3689 bcd4933a Nathan Froyd
            __put_user(0x44000002UL, &frame->tramp[1])) {
3690 bcd4933a Nathan Froyd
            return 1;
3691 bcd4933a Nathan Froyd
        }
3692 bcd4933a Nathan Froyd
    }
3693 bcd4933a Nathan Froyd
3694 bcd4933a Nathan Froyd
    return 0;
3695 bcd4933a Nathan Froyd
}
3696 bcd4933a Nathan Froyd
3697 bcd4933a Nathan Froyd
static int restore_user_regs(CPUState *env,
3698 bcd4933a Nathan Froyd
                             struct target_mcontext *frame, int sig)
3699 bcd4933a Nathan Froyd
{
3700 bcd4933a Nathan Froyd
    target_ulong save_r2 = 0;
3701 bcd4933a Nathan Froyd
    target_ulong msr;
3702 bcd4933a Nathan Froyd
    target_ulong ccr;
3703 bcd4933a Nathan Froyd
3704 bcd4933a Nathan Froyd
    int i;
3705 bcd4933a Nathan Froyd
3706 bcd4933a Nathan Froyd
    if (!sig) {
3707 bcd4933a Nathan Froyd
        save_r2 = env->gpr[2];
3708 bcd4933a Nathan Froyd
    }
3709 bcd4933a Nathan Froyd
3710 bcd4933a Nathan Froyd
    /* Restore general registers.  */
3711 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
3712 bcd4933a Nathan Froyd
        if (__get_user(env->gpr[i], &frame->mc_gregs[i])) {
3713 bcd4933a Nathan Froyd
            return 1;
3714 bcd4933a Nathan Froyd
        }
3715 bcd4933a Nathan Froyd
    }
3716 bcd4933a Nathan Froyd
    if (__get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
3717 bcd4933a Nathan Froyd
        || __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
3718 bcd4933a Nathan Froyd
        || __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
3719 bcd4933a Nathan Froyd
        || __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
3720 bcd4933a Nathan Froyd
        return 1;
3721 bcd4933a Nathan Froyd
    if (__get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
3722 bcd4933a Nathan Froyd
        return 1;
3723 bcd4933a Nathan Froyd
3724 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
3725 bcd4933a Nathan Froyd
        env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
3726 bcd4933a Nathan Froyd
    }
3727 bcd4933a Nathan Froyd
3728 bcd4933a Nathan Froyd
    if (!sig) {
3729 bcd4933a Nathan Froyd
        env->gpr[2] = save_r2;
3730 bcd4933a Nathan Froyd
    }
3731 bcd4933a Nathan Froyd
    /* Restore MSR.  */
3732 bcd4933a Nathan Froyd
    if (__get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
3733 bcd4933a Nathan Froyd
        return 1;
3734 bcd4933a Nathan Froyd
3735 bcd4933a Nathan Froyd
    /* If doing signal return, restore the previous little-endian mode.  */
3736 bcd4933a Nathan Froyd
    if (sig)
3737 bcd4933a Nathan Froyd
        env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
3738 bcd4933a Nathan Froyd
3739 bcd4933a Nathan Froyd
    /* Restore Altivec registers if necessary.  */
3740 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_ALTIVEC) {
3741 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
3742 c227f099 Anthony Liguori
            ppc_avr_t *avr = &env->avr[i];
3743 c227f099 Anthony Liguori
            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
3744 bcd4933a Nathan Froyd
3745 bcd4933a Nathan Froyd
            if (__get_user(avr->u64[0], &vreg->u64[0]) ||
3746 bcd4933a Nathan Froyd
                __get_user(avr->u64[1], &vreg->u64[1])) {
3747 bcd4933a Nathan Froyd
                return 1;
3748 bcd4933a Nathan Froyd
            }
3749 bcd4933a Nathan Froyd
        }
3750 bcd4933a Nathan Froyd
        /* Set MSR_VEC in the saved MSR value to indicate that
3751 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
3752 bcd4933a Nathan Froyd
        if (__get_user(env->spr[SPR_VRSAVE],
3753 bcd4933a Nathan Froyd
                       (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3])))
3754 bcd4933a Nathan Froyd
            return 1;
3755 bcd4933a Nathan Froyd
    }
3756 bcd4933a Nathan Froyd
3757 bcd4933a Nathan Froyd
    /* Restore floating point registers.  */
3758 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_FLOAT) {
3759 bcd4933a Nathan Froyd
        uint64_t fpscr;
3760 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
3761 bcd4933a Nathan Froyd
            if (__get_user(env->fpr[i], &frame->mc_fregs[i])) {
3762 bcd4933a Nathan Froyd
                return 1;
3763 bcd4933a Nathan Froyd
            }
3764 bcd4933a Nathan Froyd
        }
3765 bcd4933a Nathan Froyd
        if (__get_user(fpscr, &frame->mc_fregs[32]))
3766 bcd4933a Nathan Froyd
            return 1;
3767 bcd4933a Nathan Froyd
        env->fpscr = (uint32_t) fpscr;
3768 bcd4933a Nathan Froyd
    }
3769 bcd4933a Nathan Froyd
3770 bcd4933a Nathan Froyd
    /* Save SPE registers.  The kernel only saves the high half.  */
3771 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_SPE) {
3772 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3773 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
3774 bcd4933a Nathan Froyd
            uint32_t hi;
3775 bcd4933a Nathan Froyd
3776 bcd4933a Nathan Froyd
            if (__get_user(hi, &frame->mc_vregs.spe[i])) {
3777 bcd4933a Nathan Froyd
                return 1;
3778 bcd4933a Nathan Froyd
            }
3779 bcd4933a Nathan Froyd
            env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
3780 bcd4933a Nathan Froyd
        }
3781 bcd4933a Nathan Froyd
#else
3782 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
3783 bcd4933a Nathan Froyd
            if (__get_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
3784 bcd4933a Nathan Froyd
                return 1;
3785 bcd4933a Nathan Froyd
            }
3786 bcd4933a Nathan Froyd
        }
3787 bcd4933a Nathan Froyd
#endif
3788 bcd4933a Nathan Froyd
        if (__get_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
3789 bcd4933a Nathan Froyd
            return 1;
3790 bcd4933a Nathan Froyd
    }
3791 bcd4933a Nathan Froyd
3792 bcd4933a Nathan Froyd
    return 0;
3793 bcd4933a Nathan Froyd
}
3794 bcd4933a Nathan Froyd
3795 bcd4933a Nathan Froyd
static void setup_frame(int sig, struct target_sigaction *ka,
3796 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
3797 bcd4933a Nathan Froyd
{
3798 bcd4933a Nathan Froyd
    struct target_sigframe *frame;
3799 bcd4933a Nathan Froyd
    struct target_sigcontext *sc;
3800 bcd4933a Nathan Froyd
    target_ulong frame_addr, newsp;
3801 bcd4933a Nathan Froyd
    int err = 0;
3802 bcd4933a Nathan Froyd
    int signal;
3803 bcd4933a Nathan Froyd
3804 bcd4933a Nathan Froyd
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
3805 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3806 bcd4933a Nathan Froyd
        goto sigsegv;
3807 bcd4933a Nathan Froyd
    sc = &frame->sctx;
3808 bcd4933a Nathan Froyd
3809 bcd4933a Nathan Froyd
    signal = current_exec_domain_sig(sig);
3810 bcd4933a Nathan Froyd
3811 bcd4933a Nathan Froyd
    err |= __put_user(h2g(ka->_sa_handler), &sc->handler);
3812 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[0], &sc->oldmask);
3813 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3814 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[0] >> 32, &sc->_unused[3]);
3815 bcd4933a Nathan Froyd
#else
3816 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[1], &sc->_unused[3]);
3817 bcd4933a Nathan Froyd
#endif
3818 bcd4933a Nathan Froyd
    err |= __put_user(h2g(&frame->mctx), &sc->regs);
3819 bcd4933a Nathan Froyd
    err |= __put_user(sig, &sc->signal);
3820 bcd4933a Nathan Froyd
3821 bcd4933a Nathan Froyd
    /* Save user regs.  */
3822 bcd4933a Nathan Froyd
    err |= save_user_regs(env, &frame->mctx, TARGET_NR_sigreturn);
3823 bcd4933a Nathan Froyd
3824 bcd4933a Nathan Froyd
    /* The kernel checks for the presence of a VDSO here.  We don't
3825 bcd4933a Nathan Froyd
       emulate a vdso, so use a sigreturn system call.  */
3826 bcd4933a Nathan Froyd
    env->lr = (target_ulong) h2g(frame->mctx.tramp);
3827 bcd4933a Nathan Froyd
3828 bcd4933a Nathan Froyd
    /* Turn off all fp exceptions.  */
3829 bcd4933a Nathan Froyd
    env->fpscr = 0;
3830 bcd4933a Nathan Froyd
3831 bcd4933a Nathan Froyd
    /* Create a stack frame for the caller of the handler.  */
3832 bcd4933a Nathan Froyd
    newsp = frame_addr - SIGNAL_FRAMESIZE;
3833 bcd4933a Nathan Froyd
    err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
3834 bcd4933a Nathan Froyd
3835 bcd4933a Nathan Froyd
    if (err)
3836 bcd4933a Nathan Froyd
        goto sigsegv;
3837 bcd4933a Nathan Froyd
3838 bcd4933a Nathan Froyd
    /* Set up registers for signal handler.  */
3839 bcd4933a Nathan Froyd
    env->gpr[1] = newsp;
3840 bcd4933a Nathan Froyd
    env->gpr[3] = signal;
3841 bcd4933a Nathan Froyd
    env->gpr[4] = (target_ulong) h2g(sc);
3842 bcd4933a Nathan Froyd
    env->nip = (target_ulong) ka->_sa_handler;
3843 bcd4933a Nathan Froyd
    /* Signal handlers are entered in big-endian mode.  */
3844 bcd4933a Nathan Froyd
    env->msr &= ~MSR_LE;
3845 bcd4933a Nathan Froyd
3846 bcd4933a Nathan Froyd
    unlock_user_struct(frame, frame_addr, 1);
3847 bcd4933a Nathan Froyd
    return;
3848 bcd4933a Nathan Froyd
3849 bcd4933a Nathan Froyd
sigsegv:
3850 bcd4933a Nathan Froyd
    unlock_user_struct(frame, frame_addr, 1);
3851 bcd4933a Nathan Froyd
    if (logfile)
3852 bcd4933a Nathan Froyd
        fprintf (logfile, "segfaulting from setup_frame\n");
3853 bcd4933a Nathan Froyd
    force_sig(SIGSEGV);
3854 bcd4933a Nathan Froyd
}
3855 bcd4933a Nathan Froyd
3856 bcd4933a Nathan Froyd
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3857 c227f099 Anthony Liguori
                           target_siginfo_t *info,
3858 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
3859 bcd4933a Nathan Froyd
{
3860 bcd4933a Nathan Froyd
    struct target_rt_sigframe *rt_sf;
3861 bcd4933a Nathan Froyd
    struct target_mcontext *frame;
3862 bcd4933a Nathan Froyd
    target_ulong rt_sf_addr, newsp = 0;
3863 bcd4933a Nathan Froyd
    int i, err = 0;
3864 bcd4933a Nathan Froyd
    int signal;
3865 bcd4933a Nathan Froyd
3866 bcd4933a Nathan Froyd
    rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
3867 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
3868 bcd4933a Nathan Froyd
        goto sigsegv;
3869 bcd4933a Nathan Froyd
3870 bcd4933a Nathan Froyd
    signal = current_exec_domain_sig(sig);
3871 bcd4933a Nathan Froyd
3872 bcd4933a Nathan Froyd
    err |= copy_siginfo_to_user(&rt_sf->info, info);
3873 bcd4933a Nathan Froyd
3874 bcd4933a Nathan Froyd
    err |= __put_user(0, &rt_sf->uc.uc_flags);
3875 bcd4933a Nathan Froyd
    err |= __put_user(0, &rt_sf->uc.uc_link);
3876 bcd4933a Nathan Froyd
    err |= __put_user((target_ulong)target_sigaltstack_used.ss_sp,
3877 bcd4933a Nathan Froyd
                      &rt_sf->uc.uc_stack.ss_sp);
3878 bcd4933a Nathan Froyd
    err |= __put_user(sas_ss_flags(env->gpr[1]),
3879 bcd4933a Nathan Froyd
                      &rt_sf->uc.uc_stack.ss_flags);
3880 bcd4933a Nathan Froyd
    err |= __put_user(target_sigaltstack_used.ss_size,
3881 bcd4933a Nathan Froyd
                      &rt_sf->uc.uc_stack.ss_size);
3882 bcd4933a Nathan Froyd
    err |= __put_user(h2g (&rt_sf->uc.uc_mcontext),
3883 bcd4933a Nathan Froyd
                      &rt_sf->uc.uc_regs);
3884 bcd4933a Nathan Froyd
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
3885 bcd4933a Nathan Froyd
        err |= __put_user(set->sig[i], &rt_sf->uc.uc_sigmask.sig[i]);
3886 bcd4933a Nathan Froyd
    }
3887 bcd4933a Nathan Froyd
3888 bcd4933a Nathan Froyd
    frame = &rt_sf->uc.uc_mcontext;
3889 bcd4933a Nathan Froyd
    err |= save_user_regs(env, frame, TARGET_NR_rt_sigreturn);
3890 bcd4933a Nathan Froyd
3891 bcd4933a Nathan Froyd
    /* The kernel checks for the presence of a VDSO here.  We don't
3892 bcd4933a Nathan Froyd
       emulate a vdso, so use a sigreturn system call.  */
3893 bcd4933a Nathan Froyd
    env->lr = (target_ulong) h2g(frame->tramp);
3894 bcd4933a Nathan Froyd
3895 bcd4933a Nathan Froyd
    /* Turn off all fp exceptions.  */
3896 bcd4933a Nathan Froyd
    env->fpscr = 0;
3897 bcd4933a Nathan Froyd
3898 bcd4933a Nathan Froyd
    /* Create a stack frame for the caller of the handler.  */
3899 bcd4933a Nathan Froyd
    newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
3900 bcd4933a Nathan Froyd
    err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
3901 bcd4933a Nathan Froyd
3902 bcd4933a Nathan Froyd
    if (err)
3903 bcd4933a Nathan Froyd
        goto sigsegv;
3904 bcd4933a Nathan Froyd
3905 bcd4933a Nathan Froyd
    /* Set up registers for signal handler.  */
3906 bcd4933a Nathan Froyd
    env->gpr[1] = newsp;
3907 bcd4933a Nathan Froyd
    env->gpr[3] = (target_ulong) signal;
3908 bcd4933a Nathan Froyd
    env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
3909 bcd4933a Nathan Froyd
    env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
3910 bcd4933a Nathan Froyd
    env->gpr[6] = (target_ulong) h2g(rt_sf);
3911 bcd4933a Nathan Froyd
    env->nip = (target_ulong) ka->_sa_handler;
3912 bcd4933a Nathan Froyd
    /* Signal handlers are entered in big-endian mode.  */
3913 bcd4933a Nathan Froyd
    env->msr &= ~MSR_LE;
3914 bcd4933a Nathan Froyd
3915 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
3916 bcd4933a Nathan Froyd
    return;
3917 bcd4933a Nathan Froyd
3918 bcd4933a Nathan Froyd
sigsegv:
3919 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
3920 bcd4933a Nathan Froyd
    if (logfile)
3921 bcd4933a Nathan Froyd
        fprintf (logfile, "segfaulting from setup_rt_frame\n");
3922 bcd4933a Nathan Froyd
    force_sig(SIGSEGV);
3923 bcd4933a Nathan Froyd
3924 bcd4933a Nathan Froyd
}
3925 bcd4933a Nathan Froyd
3926 bcd4933a Nathan Froyd
long do_sigreturn(CPUState *env)
3927 bcd4933a Nathan Froyd
{
3928 bcd4933a Nathan Froyd
    struct target_sigcontext *sc = NULL;
3929 bcd4933a Nathan Froyd
    struct target_mcontext *sr = NULL;
3930 bcd4933a Nathan Froyd
    target_ulong sr_addr, sc_addr;
3931 bcd4933a Nathan Froyd
    sigset_t blocked;
3932 c227f099 Anthony Liguori
    target_sigset_t set;
3933 bcd4933a Nathan Froyd
3934 bcd4933a Nathan Froyd
    sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
3935 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
3936 bcd4933a Nathan Froyd
        goto sigsegv;
3937 bcd4933a Nathan Froyd
3938 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3939 bcd4933a Nathan Froyd
    set.sig[0] = sc->oldmask + ((long)(sc->_unused[3]) << 32);
3940 bcd4933a Nathan Froyd
#else
3941 bcd4933a Nathan Froyd
    if(__get_user(set.sig[0], &sc->oldmask) ||
3942 bcd4933a Nathan Froyd
       __get_user(set.sig[1], &sc->_unused[3]))
3943 bcd4933a Nathan Froyd
       goto sigsegv;
3944 bcd4933a Nathan Froyd
#endif
3945 bcd4933a Nathan Froyd
    target_to_host_sigset_internal(&blocked, &set);
3946 bcd4933a Nathan Froyd
    sigprocmask(SIG_SETMASK, &blocked, NULL);
3947 bcd4933a Nathan Froyd
3948 bcd4933a Nathan Froyd
    if (__get_user(sr_addr, &sc->regs))
3949 bcd4933a Nathan Froyd
        goto sigsegv;
3950 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
3951 bcd4933a Nathan Froyd
        goto sigsegv;
3952 bcd4933a Nathan Froyd
    if (restore_user_regs(env, sr, 1))
3953 bcd4933a Nathan Froyd
        goto sigsegv;
3954 bcd4933a Nathan Froyd
3955 bcd4933a Nathan Froyd
    unlock_user_struct(sr, sr_addr, 1);
3956 bcd4933a Nathan Froyd
    unlock_user_struct(sc, sc_addr, 1);
3957 bcd4933a Nathan Froyd
    return -TARGET_QEMU_ESIGRETURN;
3958 bcd4933a Nathan Froyd
3959 bcd4933a Nathan Froyd
sigsegv:
3960 bcd4933a Nathan Froyd
    unlock_user_struct(sr, sr_addr, 1);
3961 bcd4933a Nathan Froyd
    unlock_user_struct(sc, sc_addr, 1);
3962 bcd4933a Nathan Froyd
    if (logfile)
3963 bcd4933a Nathan Froyd
        fprintf (logfile, "segfaulting from do_sigreturn\n");
3964 bcd4933a Nathan Froyd
    force_sig(SIGSEGV);
3965 bcd4933a Nathan Froyd
    return 0;
3966 bcd4933a Nathan Froyd
}
3967 bcd4933a Nathan Froyd
3968 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal_32.c.  */
3969 bcd4933a Nathan Froyd
static int do_setcontext(struct target_ucontext *ucp, CPUState *env, int sig)
3970 bcd4933a Nathan Froyd
{
3971 bcd4933a Nathan Froyd
    struct target_mcontext *mcp;
3972 bcd4933a Nathan Froyd
    target_ulong mcp_addr;
3973 bcd4933a Nathan Froyd
    sigset_t blocked;
3974 c227f099 Anthony Liguori
    target_sigset_t set;
3975 bcd4933a Nathan Froyd
3976 bcd4933a Nathan Froyd
    if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, uc_sigmask),
3977 bcd4933a Nathan Froyd
                       sizeof (set)))
3978 bcd4933a Nathan Froyd
        return 1;
3979 bcd4933a Nathan Froyd
3980 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
3981 bcd4933a Nathan Froyd
    fprintf (stderr, "do_setcontext: not implemented\n");
3982 bcd4933a Nathan Froyd
    return 0;
3983 bcd4933a Nathan Froyd
#else
3984 bcd4933a Nathan Froyd
    if (__get_user(mcp_addr, &ucp->uc_regs))
3985 bcd4933a Nathan Froyd
        return 1;
3986 bcd4933a Nathan Froyd
3987 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
3988 bcd4933a Nathan Froyd
        return 1;
3989 bcd4933a Nathan Froyd
3990 bcd4933a Nathan Froyd
    target_to_host_sigset_internal(&blocked, &set);
3991 bcd4933a Nathan Froyd
    sigprocmask(SIG_SETMASK, &blocked, NULL);
3992 bcd4933a Nathan Froyd
    if (restore_user_regs(env, mcp, sig))
3993 bcd4933a Nathan Froyd
        goto sigsegv;
3994 bcd4933a Nathan Froyd
3995 bcd4933a Nathan Froyd
    unlock_user_struct(mcp, mcp_addr, 1);
3996 bcd4933a Nathan Froyd
    return 0;
3997 bcd4933a Nathan Froyd
3998 bcd4933a Nathan Froyd
sigsegv:
3999 bcd4933a Nathan Froyd
    unlock_user_struct(mcp, mcp_addr, 1);
4000 bcd4933a Nathan Froyd
    return 1;
4001 bcd4933a Nathan Froyd
#endif
4002 bcd4933a Nathan Froyd
}
4003 bcd4933a Nathan Froyd
4004 bcd4933a Nathan Froyd
long do_rt_sigreturn(CPUState *env)
4005 bcd4933a Nathan Froyd
{
4006 bcd4933a Nathan Froyd
    struct target_rt_sigframe *rt_sf = NULL;
4007 bcd4933a Nathan Froyd
    target_ulong rt_sf_addr;
4008 bcd4933a Nathan Froyd
4009 bcd4933a Nathan Froyd
    rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4010 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4011 bcd4933a Nathan Froyd
        goto sigsegv;
4012 bcd4933a Nathan Froyd
4013 bcd4933a Nathan Froyd
    if (do_setcontext(&rt_sf->uc, env, 1))
4014 bcd4933a Nathan Froyd
        goto sigsegv;
4015 bcd4933a Nathan Froyd
4016 bcd4933a Nathan Froyd
    do_sigaltstack(rt_sf_addr
4017 bcd4933a Nathan Froyd
                   + offsetof(struct target_rt_sigframe, uc.uc_stack),
4018 bcd4933a Nathan Froyd
                   0, env->gpr[1]);
4019 bcd4933a Nathan Froyd
4020 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4021 bcd4933a Nathan Froyd
    return -TARGET_QEMU_ESIGRETURN;
4022 bcd4933a Nathan Froyd
4023 bcd4933a Nathan Froyd
sigsegv:
4024 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4025 bcd4933a Nathan Froyd
    if (logfile)
4026 bcd4933a Nathan Froyd
        fprintf (logfile, "segfaulting from do_rt_sigreturn\n");
4027 bcd4933a Nathan Froyd
    force_sig(SIGSEGV);
4028 bcd4933a Nathan Froyd
    return 0;
4029 bcd4933a Nathan Froyd
}
4030 bcd4933a Nathan Froyd
4031 492a8744 Laurent Vivier
#elif defined(TARGET_M68K)
4032 492a8744 Laurent Vivier
4033 492a8744 Laurent Vivier
struct target_sigcontext {
4034 492a8744 Laurent Vivier
    abi_ulong  sc_mask;
4035 492a8744 Laurent Vivier
    abi_ulong  sc_usp;
4036 492a8744 Laurent Vivier
    abi_ulong  sc_d0;
4037 492a8744 Laurent Vivier
    abi_ulong  sc_d1;
4038 492a8744 Laurent Vivier
    abi_ulong  sc_a0;
4039 492a8744 Laurent Vivier
    abi_ulong  sc_a1;
4040 492a8744 Laurent Vivier
    unsigned short sc_sr;
4041 492a8744 Laurent Vivier
    abi_ulong  sc_pc;
4042 492a8744 Laurent Vivier
};
4043 492a8744 Laurent Vivier
4044 492a8744 Laurent Vivier
struct target_sigframe
4045 492a8744 Laurent Vivier
{
4046 492a8744 Laurent Vivier
    abi_ulong pretcode;
4047 492a8744 Laurent Vivier
    int sig;
4048 492a8744 Laurent Vivier
    int code;
4049 492a8744 Laurent Vivier
    abi_ulong psc;
4050 492a8744 Laurent Vivier
    char retcode[8];
4051 492a8744 Laurent Vivier
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
4052 492a8744 Laurent Vivier
    struct target_sigcontext sc;
4053 492a8744 Laurent Vivier
};
4054 7181155d Laurent Vivier
 
4055 c227f099 Anthony Liguori
typedef int target_greg_t;
4056 7181155d Laurent Vivier
#define TARGET_NGREG 18
4057 c227f099 Anthony Liguori
typedef target_greg_t target_gregset_t[TARGET_NGREG];
4058 7181155d Laurent Vivier
4059 7181155d Laurent Vivier
typedef struct target_fpregset {
4060 7181155d Laurent Vivier
    int f_fpcntl[3];
4061 7181155d Laurent Vivier
    int f_fpregs[8*3];
4062 c227f099 Anthony Liguori
} target_fpregset_t;
4063 7181155d Laurent Vivier
4064 7181155d Laurent Vivier
struct target_mcontext {
4065 7181155d Laurent Vivier
    int version;
4066 c227f099 Anthony Liguori
    target_gregset_t gregs;
4067 c227f099 Anthony Liguori
    target_fpregset_t fpregs;
4068 7181155d Laurent Vivier
};
4069 7181155d Laurent Vivier
4070 7181155d Laurent Vivier
#define TARGET_MCONTEXT_VERSION 2
4071 7181155d Laurent Vivier
4072 7181155d Laurent Vivier
struct target_ucontext {
4073 7181155d Laurent Vivier
    abi_ulong uc_flags;
4074 7181155d Laurent Vivier
    abi_ulong uc_link;
4075 c227f099 Anthony Liguori
    target_stack_t uc_stack;
4076 7181155d Laurent Vivier
    struct target_mcontext uc_mcontext;
4077 7181155d Laurent Vivier
    abi_long uc_filler[80];
4078 c227f099 Anthony Liguori
    target_sigset_t uc_sigmask;
4079 7181155d Laurent Vivier
};
4080 7181155d Laurent Vivier
4081 7181155d Laurent Vivier
struct target_rt_sigframe
4082 7181155d Laurent Vivier
{
4083 7181155d Laurent Vivier
    abi_ulong pretcode;
4084 7181155d Laurent Vivier
    int sig;
4085 7181155d Laurent Vivier
    abi_ulong pinfo;
4086 7181155d Laurent Vivier
    abi_ulong puc;
4087 7181155d Laurent Vivier
    char retcode[8];
4088 7181155d Laurent Vivier
    struct target_siginfo info;
4089 7181155d Laurent Vivier
    struct target_ucontext uc;
4090 7181155d Laurent Vivier
};
4091 492a8744 Laurent Vivier
4092 492a8744 Laurent Vivier
static int
4093 492a8744 Laurent Vivier
setup_sigcontext(struct target_sigcontext *sc, CPUState *env, abi_ulong mask)
4094 492a8744 Laurent Vivier
{
4095 492a8744 Laurent Vivier
    int err = 0;
4096 492a8744 Laurent Vivier
4097 492a8744 Laurent Vivier
    err |= __put_user(mask, &sc->sc_mask);
4098 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[7], &sc->sc_usp);
4099 492a8744 Laurent Vivier
    err |= __put_user(env->dregs[0], &sc->sc_d0);
4100 492a8744 Laurent Vivier
    err |= __put_user(env->dregs[1], &sc->sc_d1);
4101 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[0], &sc->sc_a0);
4102 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[1], &sc->sc_a1);
4103 492a8744 Laurent Vivier
    err |= __put_user(env->sr, &sc->sc_sr);
4104 492a8744 Laurent Vivier
    err |= __put_user(env->pc, &sc->sc_pc);
4105 492a8744 Laurent Vivier
4106 492a8744 Laurent Vivier
    return err;
4107 492a8744 Laurent Vivier
}
4108 492a8744 Laurent Vivier
4109 492a8744 Laurent Vivier
static int
4110 492a8744 Laurent Vivier
restore_sigcontext(CPUState *env, struct target_sigcontext *sc, int *pd0)
4111 492a8744 Laurent Vivier
{
4112 492a8744 Laurent Vivier
    int err = 0;
4113 492a8744 Laurent Vivier
    int temp;
4114 492a8744 Laurent Vivier
4115 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[7], &sc->sc_usp);
4116 492a8744 Laurent Vivier
    err |= __get_user(env->dregs[1], &sc->sc_d1);
4117 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[0], &sc->sc_a0);
4118 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[1], &sc->sc_a1);
4119 492a8744 Laurent Vivier
    err |= __get_user(env->pc, &sc->sc_pc);
4120 492a8744 Laurent Vivier
    err |= __get_user(temp, &sc->sc_sr);
4121 492a8744 Laurent Vivier
    env->sr = (env->sr & 0xff00) | (temp & 0xff);
4122 492a8744 Laurent Vivier
4123 492a8744 Laurent Vivier
    *pd0 = tswapl(sc->sc_d0);
4124 492a8744 Laurent Vivier
4125 492a8744 Laurent Vivier
    return err;
4126 492a8744 Laurent Vivier
}
4127 492a8744 Laurent Vivier
4128 492a8744 Laurent Vivier
/*
4129 492a8744 Laurent Vivier
 * Determine which stack to use..
4130 492a8744 Laurent Vivier
 */
4131 492a8744 Laurent Vivier
static inline abi_ulong
4132 492a8744 Laurent Vivier
get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
4133 492a8744 Laurent Vivier
{
4134 492a8744 Laurent Vivier
    unsigned long sp;
4135 492a8744 Laurent Vivier
4136 492a8744 Laurent Vivier
    sp = regs->aregs[7];
4137 492a8744 Laurent Vivier
4138 492a8744 Laurent Vivier
    /* This is the X/Open sanctioned signal stack switching.  */
4139 492a8744 Laurent Vivier
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
4140 492a8744 Laurent Vivier
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4141 492a8744 Laurent Vivier
    }
4142 492a8744 Laurent Vivier
4143 492a8744 Laurent Vivier
    return ((sp - frame_size) & -8UL);
4144 492a8744 Laurent Vivier
}
4145 492a8744 Laurent Vivier
4146 492a8744 Laurent Vivier
static void setup_frame(int sig, struct target_sigaction *ka,
4147 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
4148 492a8744 Laurent Vivier
{
4149 492a8744 Laurent Vivier
    struct target_sigframe *frame;
4150 492a8744 Laurent Vivier
    abi_ulong frame_addr;
4151 492a8744 Laurent Vivier
    abi_ulong retcode_addr;
4152 492a8744 Laurent Vivier
    abi_ulong sc_addr;
4153 492a8744 Laurent Vivier
    int err = 0;
4154 492a8744 Laurent Vivier
    int i;
4155 492a8744 Laurent Vivier
4156 492a8744 Laurent Vivier
    frame_addr = get_sigframe(ka, env, sizeof *frame);
4157 492a8744 Laurent Vivier
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4158 492a8744 Laurent Vivier
        goto give_sigsegv;
4159 492a8744 Laurent Vivier
4160 492a8744 Laurent Vivier
    err |= __put_user(sig, &frame->sig);
4161 492a8744 Laurent Vivier
4162 492a8744 Laurent Vivier
    sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
4163 492a8744 Laurent Vivier
    err |= __put_user(sc_addr, &frame->psc);
4164 492a8744 Laurent Vivier
4165 492a8744 Laurent Vivier
    err |= setup_sigcontext(&frame->sc, env, set->sig[0]);
4166 492a8744 Laurent Vivier
    if (err)
4167 492a8744 Laurent Vivier
        goto give_sigsegv;
4168 492a8744 Laurent Vivier
4169 492a8744 Laurent Vivier
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4170 492a8744 Laurent Vivier
        if (__put_user(set->sig[i], &frame->extramask[i - 1]))
4171 492a8744 Laurent Vivier
            goto give_sigsegv;
4172 492a8744 Laurent Vivier
    }
4173 492a8744 Laurent Vivier
4174 492a8744 Laurent Vivier
    /* Set up to return from userspace.  */
4175 492a8744 Laurent Vivier
4176 492a8744 Laurent Vivier
    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
4177 492a8744 Laurent Vivier
    err |= __put_user(retcode_addr, &frame->pretcode);
4178 492a8744 Laurent Vivier
4179 492a8744 Laurent Vivier
    /* moveq #,d0; trap #0 */
4180 492a8744 Laurent Vivier
4181 492a8744 Laurent Vivier
    err |= __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
4182 492a8744 Laurent Vivier
                      (long *)(frame->retcode));
4183 492a8744 Laurent Vivier
4184 492a8744 Laurent Vivier
    if (err)
4185 492a8744 Laurent Vivier
        goto give_sigsegv;
4186 492a8744 Laurent Vivier
4187 492a8744 Laurent Vivier
    /* Set up to return from userspace */
4188 492a8744 Laurent Vivier
4189 492a8744 Laurent Vivier
    env->aregs[7] = frame_addr;
4190 492a8744 Laurent Vivier
    env->pc = ka->_sa_handler;
4191 492a8744 Laurent Vivier
4192 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4193 492a8744 Laurent Vivier
    return;
4194 492a8744 Laurent Vivier
4195 492a8744 Laurent Vivier
give_sigsegv:
4196 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4197 492a8744 Laurent Vivier
    force_sig(SIGSEGV);
4198 492a8744 Laurent Vivier
}
4199 492a8744 Laurent Vivier
4200 7181155d Laurent Vivier
static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
4201 7181155d Laurent Vivier
                                           CPUState *env)
4202 7181155d Laurent Vivier
{
4203 c227f099 Anthony Liguori
    target_greg_t *gregs = uc->uc_mcontext.gregs;
4204 7181155d Laurent Vivier
    int err;
4205 7181155d Laurent Vivier
4206 7181155d Laurent Vivier
    err = __put_user(TARGET_MCONTEXT_VERSION, &uc->uc_mcontext.version);
4207 7181155d Laurent Vivier
    err |= __put_user(env->dregs[0], &gregs[0]);
4208 7181155d Laurent Vivier
    err |= __put_user(env->dregs[1], &gregs[1]);
4209 7181155d Laurent Vivier
    err |= __put_user(env->dregs[2], &gregs[2]);
4210 7181155d Laurent Vivier
    err |= __put_user(env->dregs[3], &gregs[3]);
4211 7181155d Laurent Vivier
    err |= __put_user(env->dregs[4], &gregs[4]);
4212 7181155d Laurent Vivier
    err |= __put_user(env->dregs[5], &gregs[5]);
4213 7181155d Laurent Vivier
    err |= __put_user(env->dregs[6], &gregs[6]);
4214 7181155d Laurent Vivier
    err |= __put_user(env->dregs[7], &gregs[7]);
4215 7181155d Laurent Vivier
    err |= __put_user(env->aregs[0], &gregs[8]);
4216 7181155d Laurent Vivier
    err |= __put_user(env->aregs[1], &gregs[9]);
4217 7181155d Laurent Vivier
    err |= __put_user(env->aregs[2], &gregs[10]);
4218 7181155d Laurent Vivier
    err |= __put_user(env->aregs[3], &gregs[11]);
4219 7181155d Laurent Vivier
    err |= __put_user(env->aregs[4], &gregs[12]);
4220 7181155d Laurent Vivier
    err |= __put_user(env->aregs[5], &gregs[13]);
4221 7181155d Laurent Vivier
    err |= __put_user(env->aregs[6], &gregs[14]);
4222 7181155d Laurent Vivier
    err |= __put_user(env->aregs[7], &gregs[15]);
4223 7181155d Laurent Vivier
    err |= __put_user(env->pc, &gregs[16]);
4224 7181155d Laurent Vivier
    err |= __put_user(env->sr, &gregs[17]);
4225 7181155d Laurent Vivier
4226 7181155d Laurent Vivier
    return err;
4227 7181155d Laurent Vivier
}
4228 7181155d Laurent Vivier
 
4229 7181155d Laurent Vivier
static inline int target_rt_restore_ucontext(CPUState *env,
4230 7181155d Laurent Vivier
                                             struct target_ucontext *uc,
4231 7181155d Laurent Vivier
                                             int *pd0)
4232 7181155d Laurent Vivier
{
4233 7181155d Laurent Vivier
    int temp;
4234 7181155d Laurent Vivier
    int err;
4235 c227f099 Anthony Liguori
    target_greg_t *gregs = uc->uc_mcontext.gregs;
4236 7181155d Laurent Vivier
    
4237 7181155d Laurent Vivier
    err = __get_user(temp, &uc->uc_mcontext.version);
4238 7181155d Laurent Vivier
    if (temp != TARGET_MCONTEXT_VERSION)
4239 7181155d Laurent Vivier
        goto badframe;
4240 7181155d Laurent Vivier
4241 7181155d Laurent Vivier
    /* restore passed registers */
4242 7181155d Laurent Vivier
    err |= __get_user(env->dregs[0], &gregs[0]);
4243 7181155d Laurent Vivier
    err |= __get_user(env->dregs[1], &gregs[1]);
4244 7181155d Laurent Vivier
    err |= __get_user(env->dregs[2], &gregs[2]);
4245 7181155d Laurent Vivier
    err |= __get_user(env->dregs[3], &gregs[3]);
4246 7181155d Laurent Vivier
    err |= __get_user(env->dregs[4], &gregs[4]);
4247 7181155d Laurent Vivier
    err |= __get_user(env->dregs[5], &gregs[5]);
4248 7181155d Laurent Vivier
    err |= __get_user(env->dregs[6], &gregs[6]);
4249 7181155d Laurent Vivier
    err |= __get_user(env->dregs[7], &gregs[7]);
4250 7181155d Laurent Vivier
    err |= __get_user(env->aregs[0], &gregs[8]);
4251 7181155d Laurent Vivier
    err |= __get_user(env->aregs[1], &gregs[9]);
4252 7181155d Laurent Vivier
    err |= __get_user(env->aregs[2], &gregs[10]);
4253 7181155d Laurent Vivier
    err |= __get_user(env->aregs[3], &gregs[11]);
4254 7181155d Laurent Vivier
    err |= __get_user(env->aregs[4], &gregs[12]);
4255 7181155d Laurent Vivier
    err |= __get_user(env->aregs[5], &gregs[13]);
4256 7181155d Laurent Vivier
    err |= __get_user(env->aregs[6], &gregs[14]);
4257 7181155d Laurent Vivier
    err |= __get_user(env->aregs[7], &gregs[15]);
4258 7181155d Laurent Vivier
    err |= __get_user(env->pc, &gregs[16]);
4259 7181155d Laurent Vivier
    err |= __get_user(temp, &gregs[17]);
4260 7181155d Laurent Vivier
    env->sr = (env->sr & 0xff00) | (temp & 0xff);
4261 7181155d Laurent Vivier
4262 7181155d Laurent Vivier
    *pd0 = env->dregs[0];
4263 7181155d Laurent Vivier
    return err;
4264 7181155d Laurent Vivier
4265 7181155d Laurent Vivier
badframe:
4266 7181155d Laurent Vivier
    return 1;
4267 7181155d Laurent Vivier
}
4268 7181155d Laurent Vivier
4269 492a8744 Laurent Vivier
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4270 c227f099 Anthony Liguori
                           target_siginfo_t *info,
4271 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
4272 492a8744 Laurent Vivier
{
4273 7181155d Laurent Vivier
    struct target_rt_sigframe *frame;
4274 7181155d Laurent Vivier
    abi_ulong frame_addr;
4275 7181155d Laurent Vivier
    abi_ulong retcode_addr;
4276 7181155d Laurent Vivier
    abi_ulong info_addr;
4277 7181155d Laurent Vivier
    abi_ulong uc_addr;
4278 7181155d Laurent Vivier
    int err = 0;
4279 7181155d Laurent Vivier
    int i;
4280 7181155d Laurent Vivier
4281 7181155d Laurent Vivier
    frame_addr = get_sigframe(ka, env, sizeof *frame);
4282 7181155d Laurent Vivier
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4283 7181155d Laurent Vivier
        goto give_sigsegv;
4284 7181155d Laurent Vivier
4285 7181155d Laurent Vivier
    err |= __put_user(sig, &frame->sig);
4286 7181155d Laurent Vivier
4287 7181155d Laurent Vivier
    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
4288 7181155d Laurent Vivier
    err |= __put_user(info_addr, &frame->pinfo);
4289 7181155d Laurent Vivier
4290 7181155d Laurent Vivier
    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
4291 7181155d Laurent Vivier
    err |= __put_user(uc_addr, &frame->puc);
4292 7181155d Laurent Vivier
4293 7181155d Laurent Vivier
    err |= copy_siginfo_to_user(&frame->info, info);
4294 7181155d Laurent Vivier
4295 7181155d Laurent Vivier
    /* Create the ucontext */
4296 7181155d Laurent Vivier
4297 7181155d Laurent Vivier
    err |= __put_user(0, &frame->uc.uc_flags);
4298 7181155d Laurent Vivier
    err |= __put_user(0, &frame->uc.uc_link);
4299 7181155d Laurent Vivier
    err |= __put_user(target_sigaltstack_used.ss_sp,
4300 7181155d Laurent Vivier
                      &frame->uc.uc_stack.ss_sp);
4301 7181155d Laurent Vivier
    err |= __put_user(sas_ss_flags(env->aregs[7]),
4302 7181155d Laurent Vivier
                      &frame->uc.uc_stack.ss_flags);
4303 7181155d Laurent Vivier
    err |= __put_user(target_sigaltstack_used.ss_size,
4304 7181155d Laurent Vivier
                      &frame->uc.uc_stack.ss_size);
4305 7181155d Laurent Vivier
    err |= target_rt_setup_ucontext(&frame->uc, env);
4306 7181155d Laurent Vivier
4307 7181155d Laurent Vivier
    if (err)
4308 7181155d Laurent Vivier
            goto give_sigsegv;
4309 7181155d Laurent Vivier
4310 7181155d Laurent Vivier
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
4311 7181155d Laurent Vivier
        if (__put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]))
4312 7181155d Laurent Vivier
            goto give_sigsegv;
4313 7181155d Laurent Vivier
    }
4314 7181155d Laurent Vivier
4315 7181155d Laurent Vivier
    /* Set up to return from userspace.  */
4316 7181155d Laurent Vivier
4317 7181155d Laurent Vivier
    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
4318 7181155d Laurent Vivier
    err |= __put_user(retcode_addr, &frame->pretcode);
4319 7181155d Laurent Vivier
4320 7181155d Laurent Vivier
    /* moveq #,d0; notb d0; trap #0 */
4321 7181155d Laurent Vivier
4322 7181155d Laurent Vivier
    err |= __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
4323 7181155d Laurent Vivier
                      (long *)(frame->retcode + 0));
4324 7181155d Laurent Vivier
    err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
4325 7181155d Laurent Vivier
4326 7181155d Laurent Vivier
    if (err)
4327 7181155d Laurent Vivier
        goto give_sigsegv;
4328 7181155d Laurent Vivier
4329 7181155d Laurent Vivier
    /* Set up to return from userspace */
4330 7181155d Laurent Vivier
4331 7181155d Laurent Vivier
    env->aregs[7] = frame_addr;
4332 7181155d Laurent Vivier
    env->pc = ka->_sa_handler;
4333 7181155d Laurent Vivier
4334 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4335 7181155d Laurent Vivier
    return;
4336 7181155d Laurent Vivier
4337 7181155d Laurent Vivier
give_sigsegv:
4338 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4339 7181155d Laurent Vivier
    force_sig(SIGSEGV);
4340 492a8744 Laurent Vivier
}
4341 492a8744 Laurent Vivier
4342 492a8744 Laurent Vivier
long do_sigreturn(CPUState *env)
4343 492a8744 Laurent Vivier
{
4344 492a8744 Laurent Vivier
    struct target_sigframe *frame;
4345 492a8744 Laurent Vivier
    abi_ulong frame_addr = env->aregs[7] - 4;
4346 c227f099 Anthony Liguori
    target_sigset_t target_set;
4347 492a8744 Laurent Vivier
    sigset_t set;
4348 492a8744 Laurent Vivier
    int d0, i;
4349 492a8744 Laurent Vivier
4350 492a8744 Laurent Vivier
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
4351 492a8744 Laurent Vivier
        goto badframe;
4352 492a8744 Laurent Vivier
4353 492a8744 Laurent Vivier
    /* set blocked signals */
4354 492a8744 Laurent Vivier
4355 492a8744 Laurent Vivier
    if (__get_user(target_set.sig[0], &frame->sc.sc_mask))
4356 492a8744 Laurent Vivier
        goto badframe;
4357 492a8744 Laurent Vivier
4358 492a8744 Laurent Vivier
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4359 492a8744 Laurent Vivier
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
4360 492a8744 Laurent Vivier
            goto badframe;
4361 492a8744 Laurent Vivier
    }
4362 492a8744 Laurent Vivier
4363 492a8744 Laurent Vivier
    target_to_host_sigset_internal(&set, &target_set);
4364 492a8744 Laurent Vivier
    sigprocmask(SIG_SETMASK, &set, NULL);
4365 492a8744 Laurent Vivier
4366 492a8744 Laurent Vivier
    /* restore registers */
4367 492a8744 Laurent Vivier
4368 492a8744 Laurent Vivier
    if (restore_sigcontext(env, &frame->sc, &d0))
4369 492a8744 Laurent Vivier
        goto badframe;
4370 492a8744 Laurent Vivier
4371 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
4372 492a8744 Laurent Vivier
    return d0;
4373 492a8744 Laurent Vivier
4374 492a8744 Laurent Vivier
badframe:
4375 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
4376 492a8744 Laurent Vivier
    force_sig(TARGET_SIGSEGV);
4377 492a8744 Laurent Vivier
    return 0;
4378 492a8744 Laurent Vivier
}
4379 492a8744 Laurent Vivier
4380 492a8744 Laurent Vivier
long do_rt_sigreturn(CPUState *env)
4381 492a8744 Laurent Vivier
{
4382 7181155d Laurent Vivier
    struct target_rt_sigframe *frame;
4383 7181155d Laurent Vivier
    abi_ulong frame_addr = env->aregs[7] - 4;
4384 c227f099 Anthony Liguori
    target_sigset_t target_set;
4385 7181155d Laurent Vivier
    sigset_t set;
4386 7181155d Laurent Vivier
    int d0;
4387 7181155d Laurent Vivier
4388 7181155d Laurent Vivier
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
4389 7181155d Laurent Vivier
        goto badframe;
4390 7181155d Laurent Vivier
4391 7181155d Laurent Vivier
    target_to_host_sigset_internal(&set, &target_set);
4392 7181155d Laurent Vivier
    sigprocmask(SIG_SETMASK, &set, NULL);
4393 7181155d Laurent Vivier
4394 7181155d Laurent Vivier
    /* restore registers */
4395 7181155d Laurent Vivier
4396 7181155d Laurent Vivier
    if (target_rt_restore_ucontext(env, &frame->uc, &d0))
4397 7181155d Laurent Vivier
        goto badframe;
4398 7181155d Laurent Vivier
4399 7181155d Laurent Vivier
    if (do_sigaltstack(frame_addr +
4400 7181155d Laurent Vivier
                       offsetof(struct target_rt_sigframe, uc.uc_stack),
4401 7181155d Laurent Vivier
                       0, get_sp_from_cpustate(env)) == -EFAULT)
4402 7181155d Laurent Vivier
        goto badframe;
4403 7181155d Laurent Vivier
4404 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
4405 7181155d Laurent Vivier
    return d0;
4406 7181155d Laurent Vivier
4407 7181155d Laurent Vivier
badframe:
4408 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
4409 7181155d Laurent Vivier
    force_sig(TARGET_SIGSEGV);
4410 7181155d Laurent Vivier
    return 0;
4411 492a8744 Laurent Vivier
}
4412 492a8744 Laurent Vivier
4413 b346ff46 bellard
#else
4414 b346ff46 bellard
4415 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
4416 c227f099 Anthony Liguori
                        target_sigset_t *set, CPUState *env)
4417 b346ff46 bellard
{
4418 b346ff46 bellard
    fprintf(stderr, "setup_frame: not implemented\n");
4419 b346ff46 bellard
}
4420 b346ff46 bellard
4421 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4422 c227f099 Anthony Liguori
                           target_siginfo_t *info,
4423 c227f099 Anthony Liguori
                           target_sigset_t *set, CPUState *env)
4424 b346ff46 bellard
{
4425 b346ff46 bellard
    fprintf(stderr, "setup_rt_frame: not implemented\n");
4426 b346ff46 bellard
}
4427 b346ff46 bellard
4428 b346ff46 bellard
long do_sigreturn(CPUState *env)
4429 b346ff46 bellard
{
4430 b346ff46 bellard
    fprintf(stderr, "do_sigreturn: not implemented\n");
4431 f8b0aa25 bellard
    return -TARGET_ENOSYS;
4432 b346ff46 bellard
}
4433 b346ff46 bellard
4434 b346ff46 bellard
long do_rt_sigreturn(CPUState *env)
4435 b346ff46 bellard
{
4436 b346ff46 bellard
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
4437 f8b0aa25 bellard
    return -TARGET_ENOSYS;
4438 b346ff46 bellard
}
4439 b346ff46 bellard
4440 66fb9763 bellard
#endif
4441 66fb9763 bellard
4442 624f7979 pbrook
void process_pending_signals(CPUState *cpu_env)
4443 66fb9763 bellard
{
4444 66fb9763 bellard
    int sig;
4445 992f48a0 blueswir1
    abi_ulong handler;
4446 9de5e440 bellard
    sigset_t set, old_set;
4447 c227f099 Anthony Liguori
    target_sigset_t target_old_set;
4448 624f7979 pbrook
    struct emulated_sigtable *k;
4449 624f7979 pbrook
    struct target_sigaction *sa;
4450 66fb9763 bellard
    struct sigqueue *q;
4451 624f7979 pbrook
    TaskState *ts = cpu_env->opaque;
4452 3b46e624 ths
4453 624f7979 pbrook
    if (!ts->signal_pending)
4454 31e31b8a bellard
        return;
4455 31e31b8a bellard
4456 624f7979 pbrook
    /* FIXME: This is not threadsafe.  */
4457 624f7979 pbrook
    k = ts->sigtab;
4458 66fb9763 bellard
    for(sig = 1; sig <= TARGET_NSIG; sig++) {
4459 66fb9763 bellard
        if (k->pending)
4460 31e31b8a bellard
            goto handle_signal;
4461 66fb9763 bellard
        k++;
4462 31e31b8a bellard
    }
4463 31e31b8a bellard
    /* if no signal is pending, just return */
4464 624f7979 pbrook
    ts->signal_pending = 0;
4465 31e31b8a bellard
    return;
4466 66fb9763 bellard
4467 31e31b8a bellard
 handle_signal:
4468 66fb9763 bellard
#ifdef DEBUG_SIGNAL
4469 bc8a22cc bellard
    fprintf(stderr, "qemu: process signal %d\n", sig);
4470 66fb9763 bellard
#endif
4471 66fb9763 bellard
    /* dequeue signal */
4472 66fb9763 bellard
    q = k->first;
4473 66fb9763 bellard
    k->first = q->next;
4474 66fb9763 bellard
    if (!k->first)
4475 66fb9763 bellard
        k->pending = 0;
4476 3b46e624 ths
4477 1fddef4b bellard
    sig = gdb_handlesig (cpu_env, sig);
4478 1fddef4b bellard
    if (!sig) {
4479 ca587a8e aurel32
        sa = NULL;
4480 ca587a8e aurel32
        handler = TARGET_SIG_IGN;
4481 ca587a8e aurel32
    } else {
4482 ca587a8e aurel32
        sa = &sigact_table[sig - 1];
4483 ca587a8e aurel32
        handler = sa->_sa_handler;
4484 1fddef4b bellard
    }
4485 66fb9763 bellard
4486 66fb9763 bellard
    if (handler == TARGET_SIG_DFL) {
4487 ca587a8e aurel32
        /* default handler : ignore some signal. The other are job control or fatal */
4488 ca587a8e aurel32
        if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
4489 ca587a8e aurel32
            kill(getpid(),SIGSTOP);
4490 ca587a8e aurel32
        } else if (sig != TARGET_SIGCHLD &&
4491 ca587a8e aurel32
                   sig != TARGET_SIGURG &&
4492 ca587a8e aurel32
                   sig != TARGET_SIGWINCH &&
4493 ca587a8e aurel32
                   sig != TARGET_SIGCONT) {
4494 66fb9763 bellard
            force_sig(sig);
4495 66fb9763 bellard
        }
4496 66fb9763 bellard
    } else if (handler == TARGET_SIG_IGN) {
4497 66fb9763 bellard
        /* ignore sig */
4498 66fb9763 bellard
    } else if (handler == TARGET_SIG_ERR) {
4499 66fb9763 bellard
        force_sig(sig);
4500 66fb9763 bellard
    } else {
4501 9de5e440 bellard
        /* compute the blocked signals during the handler execution */
4502 624f7979 pbrook
        target_to_host_sigset(&set, &sa->sa_mask);
4503 9de5e440 bellard
        /* SA_NODEFER indicates that the current signal should not be
4504 9de5e440 bellard
           blocked during the handler */
4505 624f7979 pbrook
        if (!(sa->sa_flags & TARGET_SA_NODEFER))
4506 9de5e440 bellard
            sigaddset(&set, target_to_host_signal(sig));
4507 3b46e624 ths
4508 9de5e440 bellard
        /* block signals in the handler using Linux */
4509 9de5e440 bellard
        sigprocmask(SIG_BLOCK, &set, &old_set);
4510 9de5e440 bellard
        /* save the previous blocked signal state to restore it at the
4511 9de5e440 bellard
           end of the signal execution (see do_sigreturn) */
4512 9231944d bellard
        host_to_target_sigset_internal(&target_old_set, &old_set);
4513 9de5e440 bellard
4514 bc8a22cc bellard
        /* if the CPU is in VM86 mode, we restore the 32 bit values */
4515 84409ddb j_mayer
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
4516 bc8a22cc bellard
        {
4517 bc8a22cc bellard
            CPUX86State *env = cpu_env;
4518 bc8a22cc bellard
            if (env->eflags & VM_MASK)
4519 bc8a22cc bellard
                save_v86_state(env);
4520 bc8a22cc bellard
        }
4521 bc8a22cc bellard
#endif
4522 9de5e440 bellard
        /* prepare the stack frame of the virtual CPU */
4523 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_SIGINFO)
4524 624f7979 pbrook
            setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
4525 66fb9763 bellard
        else
4526 624f7979 pbrook
            setup_frame(sig, sa, &target_old_set, cpu_env);
4527 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_RESETHAND)
4528 624f7979 pbrook
            sa->_sa_handler = TARGET_SIG_DFL;
4529 31e31b8a bellard
    }
4530 66fb9763 bellard
    if (q != &k->info)
4531 624f7979 pbrook
        free_sigqueue(cpu_env, q);
4532 66fb9763 bellard
}