Statistics
| Branch: | Revision:

root / linux-user / signal.c @ ae017a5b

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

1956 6d5e216d bellard
        err |= __put_user(mask, &sc->sigc_mask);
1957 6d5e216d bellard
        err |= __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
1958 6d5e216d bellard
        err |= __put_user(env->pc, &sc->sigc_pc);
1959 6d5e216d bellard
        err |= __put_user(env->npc, &sc->sigc_npc);
1960 6d5e216d bellard
        err |= __put_user(env->psr, &sc->sigc_psr);
1961 6d5e216d bellard
        err |= __put_user(env->gregs[1], &sc->sigc_g1);
1962 6d5e216d bellard
        err |= __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
1963 6d5e216d bellard

1964 6d5e216d bellard
        return err;
1965 6d5e216d bellard
}
1966 80a9d035 bellard
#endif
1967 6d5e216d bellard
#define NF_ALIGNEDSZ  (((sizeof(struct target_signal_frame) + 7) & (~7)))
1968 6d5e216d bellard
1969 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
1970 05390248 Andreas Färber
                        target_sigset_t *set, CPUSPARCState *env)
1971 6d5e216d bellard
{
1972 459a4017 bellard
        abi_ulong sf_addr;
1973 6d5e216d bellard
        struct target_signal_frame *sf;
1974 6d5e216d bellard
        int sigframe_size, err, i;
1975 6d5e216d bellard
1976 6d5e216d bellard
        /* 1. Make sure everything is clean */
1977 6d5e216d bellard
        //synchronize_user_stack();
1978 6d5e216d bellard
1979 6d5e216d bellard
        sigframe_size = NF_ALIGNEDSZ;
1980 459a4017 bellard
        sf_addr = get_sigframe(ka, env, sigframe_size);
1981 6d5e216d bellard
1982 459a4017 bellard
        sf = lock_user(VERIFY_WRITE, sf_addr, 
1983 459a4017 bellard
                       sizeof(struct target_signal_frame), 0);
1984 459a4017 bellard
        if (!sf)
1985 459a4017 bellard
                goto sigsegv;
1986 459a4017 bellard
                
1987 e80cfcfc bellard
        //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
1988 6d5e216d bellard
#if 0
1989 6d5e216d bellard
        if (invalid_frame_pointer(sf, sigframe_size))
1990 6d5e216d bellard
                goto sigill_and_return;
1991 6d5e216d bellard
#endif
1992 6d5e216d bellard
        /* 2. Save the current process state */
1993 6d5e216d bellard
        err = setup___siginfo(&sf->info, env, set->sig[0]);
1994 6d5e216d bellard
        err |= __put_user(0, &sf->extra_size);
1995 6d5e216d bellard
1996 6d5e216d bellard
        //err |= save_fpu_state(regs, &sf->fpu_state);
1997 6d5e216d bellard
        //err |= __put_user(&sf->fpu_state, &sf->fpu_save);
1998 6d5e216d bellard
1999 6d5e216d bellard
        err |= __put_user(set->sig[0], &sf->info.si_mask);
2000 6d5e216d bellard
        for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
2001 6d5e216d bellard
                err |= __put_user(set->sig[i + 1], &sf->extramask[i]);
2002 6d5e216d bellard
        }
2003 6d5e216d bellard
2004 a315a145 bellard
        for (i = 0; i < 8; i++) {
2005 e80cfcfc bellard
                  err |= __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
2006 6d5e216d bellard
        }
2007 a315a145 bellard
        for (i = 0; i < 8; i++) {
2008 e80cfcfc bellard
                  err |= __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
2009 6d5e216d bellard
        }
2010 6d5e216d bellard
        if (err)
2011 6d5e216d bellard
                goto sigsegv;
2012 6d5e216d bellard
2013 6d5e216d bellard
        /* 3. signal handler back-trampoline and parameters */
2014 459a4017 bellard
        env->regwptr[UREG_FP] = sf_addr;
2015 6d5e216d bellard
        env->regwptr[UREG_I0] = sig;
2016 459a4017 bellard
        env->regwptr[UREG_I1] = sf_addr + 
2017 459a4017 bellard
                offsetof(struct target_signal_frame, info);
2018 459a4017 bellard
        env->regwptr[UREG_I2] = sf_addr + 
2019 459a4017 bellard
                offsetof(struct target_signal_frame, info);
2020 6d5e216d bellard
2021 6d5e216d bellard
        /* 4. signal handler */
2022 624f7979 pbrook
        env->pc = ka->_sa_handler;
2023 6d5e216d bellard
        env->npc = (env->pc + 4);
2024 6d5e216d bellard
        /* 5. return to kernel instructions */
2025 624f7979 pbrook
        if (ka->sa_restorer)
2026 624f7979 pbrook
                env->regwptr[UREG_I7] = ka->sa_restorer;
2027 6d5e216d bellard
        else {
2028 775b58d8 bellard
                uint32_t val32;
2029 459a4017 bellard
2030 459a4017 bellard
                env->regwptr[UREG_I7] = sf_addr + 
2031 459a4017 bellard
                        offsetof(struct target_signal_frame, insns) - 2 * 4;
2032 6d5e216d bellard
2033 6d5e216d bellard
                /* mov __NR_sigreturn, %g1 */
2034 775b58d8 bellard
                val32 = 0x821020d8;
2035 775b58d8 bellard
                err |= __put_user(val32, &sf->insns[0]);
2036 6d5e216d bellard
2037 6d5e216d bellard
                /* t 0x10 */
2038 775b58d8 bellard
                val32 = 0x91d02010;
2039 775b58d8 bellard
                err |= __put_user(val32, &sf->insns[1]);
2040 6d5e216d bellard
                if (err)
2041 6d5e216d bellard
                        goto sigsegv;
2042 6d5e216d bellard
2043 6d5e216d bellard
                /* Flush instruction space. */
2044 6d5e216d bellard
                //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
2045 80a9d035 bellard
                //                tb_flush(env);
2046 6d5e216d bellard
        }
2047 459a4017 bellard
        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2048 6d5e216d bellard
        return;
2049 459a4017 bellard
#if 0
2050 459a4017 bellard
sigill_and_return:
2051 6d5e216d bellard
        force_sig(TARGET_SIGILL);
2052 459a4017 bellard
#endif
2053 6d5e216d bellard
sigsegv:
2054 e80cfcfc bellard
        //fprintf(stderr, "force_sig\n");
2055 459a4017 bellard
        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
2056 6d5e216d bellard
        force_sig(TARGET_SIGSEGV);
2057 6d5e216d bellard
}
2058 6d5e216d bellard
static inline int
2059 05390248 Andreas Färber
restore_fpu_state(CPUSPARCState *env, qemu_siginfo_fpu_t *fpu)
2060 6d5e216d bellard
{
2061 6d5e216d bellard
        int err;
2062 6d5e216d bellard
#if 0
2063 6d5e216d bellard
#ifdef CONFIG_SMP
2064 6d5e216d bellard
        if (current->flags & PF_USEDFPU)
2065 6d5e216d bellard
                regs->psr &= ~PSR_EF;
2066 6d5e216d bellard
#else
2067 6d5e216d bellard
        if (current == last_task_used_math) {
2068 6d5e216d bellard
                last_task_used_math = 0;
2069 6d5e216d bellard
                regs->psr &= ~PSR_EF;
2070 6d5e216d bellard
        }
2071 6d5e216d bellard
#endif
2072 6d5e216d bellard
        current->used_math = 1;
2073 6d5e216d bellard
        current->flags &= ~PF_USEDFPU;
2074 6d5e216d bellard
#endif
2075 6d5e216d bellard
#if 0
2076 6d5e216d bellard
        if (verify_area (VERIFY_READ, fpu, sizeof(*fpu)))
2077 6d5e216d bellard
                return -EFAULT;
2078 6d5e216d bellard
#endif
2079 6d5e216d bellard
2080 fafffaef bellard
        /* XXX: incorrect */
2081 8954bae3 Blue Swirl
        err = copy_from_user(&env->fpr[0], fpu->si_float_regs[0],
2082 8954bae3 Blue Swirl
                             (sizeof(abi_ulong) * 32));
2083 6d5e216d bellard
        err |= __get_user(env->fsr, &fpu->si_fsr);
2084 6d5e216d bellard
#if 0
2085 6d5e216d bellard
        err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
2086 6d5e216d bellard
        if (current->thread.fpqdepth != 0)
2087 6d5e216d bellard
                err |= __copy_from_user(&current->thread.fpqueue[0],
2088 6d5e216d bellard
                                        &fpu->si_fpqueue[0],
2089 6d5e216d bellard
                                        ((sizeof(unsigned long) +
2090 6d5e216d bellard
                                        (sizeof(unsigned long *)))*16));
2091 6d5e216d bellard
#endif
2092 6d5e216d bellard
        return err;
2093 6d5e216d bellard
}
2094 6d5e216d bellard
2095 6d5e216d bellard
2096 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2097 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2098 05390248 Andreas Färber
                           target_sigset_t *set, CPUSPARCState *env)
2099 6d5e216d bellard
{
2100 6d5e216d bellard
    fprintf(stderr, "setup_rt_frame: not implemented\n");
2101 6d5e216d bellard
}
2102 6d5e216d bellard
2103 05390248 Andreas Färber
long do_sigreturn(CPUSPARCState *env)
2104 6d5e216d bellard
{
2105 f8b0aa25 bellard
        abi_ulong sf_addr;
2106 6d5e216d bellard
        struct target_signal_frame *sf;
2107 e80cfcfc bellard
        uint32_t up_psr, pc, npc;
2108 c227f099 Anthony Liguori
        target_sigset_t set;
2109 e80cfcfc bellard
        sigset_t host_set;
2110 e80cfcfc bellard
        int err, i;
2111 6d5e216d bellard
2112 f8b0aa25 bellard
        sf_addr = env->regwptr[UREG_FP];
2113 f8b0aa25 bellard
        if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
2114 f8b0aa25 bellard
                goto segv_and_exit;
2115 80a9d035 bellard
#if 0
2116 e80cfcfc bellard
        fprintf(stderr, "sigreturn\n");
2117 e80cfcfc bellard
        fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
2118 80a9d035 bellard
#endif
2119 e80cfcfc bellard
        //cpu_dump_state(env, stderr, fprintf, 0);
2120 6d5e216d bellard
2121 6d5e216d bellard
        /* 1. Make sure we are not getting garbage from the user */
2122 6d5e216d bellard
2123 f8b0aa25 bellard
        if (sf_addr & 3)
2124 6d5e216d bellard
                goto segv_and_exit;
2125 6d5e216d bellard
2126 6d5e216d bellard
        err = __get_user(pc,  &sf->info.si_regs.pc);
2127 6d5e216d bellard
        err |= __get_user(npc, &sf->info.si_regs.npc);
2128 6d5e216d bellard
2129 6d5e216d bellard
        if ((pc | npc) & 3)
2130 6d5e216d bellard
                goto segv_and_exit;
2131 6d5e216d bellard
2132 6d5e216d bellard
        /* 2. Restore the state */
2133 e80cfcfc bellard
        err |= __get_user(up_psr, &sf->info.si_regs.psr);
2134 e80cfcfc bellard
2135 6d5e216d bellard
        /* User can only change condition codes and FPU enabling in %psr. */
2136 a315a145 bellard
        env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
2137 a315a145 bellard
                  | (env->psr & ~(PSR_ICC /* | PSR_EF */));
2138 a315a145 bellard
2139 a315a145 bellard
        env->pc = pc;
2140 a315a145 bellard
        env->npc = npc;
2141 e80cfcfc bellard
        err |= __get_user(env->y, &sf->info.si_regs.y);
2142 a315a145 bellard
        for (i=0; i < 8; i++) {
2143 e80cfcfc bellard
                err |= __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
2144 e80cfcfc bellard
        }
2145 a315a145 bellard
        for (i=0; i < 8; i++) {
2146 e80cfcfc bellard
                err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
2147 e80cfcfc bellard
        }
2148 6d5e216d bellard
2149 2aec3a27 Peter Maydell
        /* FIXME: implement FPU save/restore:
2150 2aec3a27 Peter Maydell
         * __get_user(fpu_save, &sf->fpu_save);
2151 2aec3a27 Peter Maydell
         * if (fpu_save)
2152 2aec3a27 Peter Maydell
         *        err |= restore_fpu_state(env, fpu_save);
2153 2aec3a27 Peter Maydell
         */
2154 6d5e216d bellard
2155 6d5e216d bellard
        /* This is pretty much atomic, no amount locking would prevent
2156 6d5e216d bellard
         * the races which exist anyways.
2157 6d5e216d bellard
         */
2158 6d5e216d bellard
        err |= __get_user(set.sig[0], &sf->info.si_mask);
2159 e80cfcfc bellard
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
2160 e80cfcfc bellard
            err |= (__get_user(set.sig[i], &sf->extramask[i - 1]));
2161 e80cfcfc bellard
        }
2162 e80cfcfc bellard
2163 e80cfcfc bellard
        target_to_host_sigset_internal(&host_set, &set);
2164 e80cfcfc bellard
        sigprocmask(SIG_SETMASK, &host_set, NULL);
2165 6d5e216d bellard
2166 6d5e216d bellard
        if (err)
2167 6d5e216d bellard
                goto segv_and_exit;
2168 f8b0aa25 bellard
        unlock_user_struct(sf, sf_addr, 0);
2169 6d5e216d bellard
        return env->regwptr[0];
2170 6d5e216d bellard
2171 6d5e216d bellard
segv_and_exit:
2172 f8b0aa25 bellard
        unlock_user_struct(sf, sf_addr, 0);
2173 6d5e216d bellard
        force_sig(TARGET_SIGSEGV);
2174 6d5e216d bellard
}
2175 6d5e216d bellard
2176 05390248 Andreas Färber
long do_rt_sigreturn(CPUSPARCState *env)
2177 6d5e216d bellard
{
2178 6d5e216d bellard
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
2179 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2180 6d5e216d bellard
}
2181 6d5e216d bellard
2182 459a4017 bellard
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
2183 5bfb56b2 blueswir1
#define MC_TSTATE 0
2184 5bfb56b2 blueswir1
#define MC_PC 1
2185 5bfb56b2 blueswir1
#define MC_NPC 2
2186 5bfb56b2 blueswir1
#define MC_Y 3
2187 5bfb56b2 blueswir1
#define MC_G1 4
2188 5bfb56b2 blueswir1
#define MC_G2 5
2189 5bfb56b2 blueswir1
#define MC_G3 6
2190 5bfb56b2 blueswir1
#define MC_G4 7
2191 5bfb56b2 blueswir1
#define MC_G5 8
2192 5bfb56b2 blueswir1
#define MC_G6 9
2193 5bfb56b2 blueswir1
#define MC_G7 10
2194 5bfb56b2 blueswir1
#define MC_O0 11
2195 5bfb56b2 blueswir1
#define MC_O1 12
2196 5bfb56b2 blueswir1
#define MC_O2 13
2197 5bfb56b2 blueswir1
#define MC_O3 14
2198 5bfb56b2 blueswir1
#define MC_O4 15
2199 5bfb56b2 blueswir1
#define MC_O5 16
2200 5bfb56b2 blueswir1
#define MC_O6 17
2201 5bfb56b2 blueswir1
#define MC_O7 18
2202 5bfb56b2 blueswir1
#define MC_NGREG 19
2203 5bfb56b2 blueswir1
2204 c227f099 Anthony Liguori
typedef abi_ulong target_mc_greg_t;
2205 c227f099 Anthony Liguori
typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
2206 5bfb56b2 blueswir1
2207 5bfb56b2 blueswir1
struct target_mc_fq {
2208 992f48a0 blueswir1
    abi_ulong *mcfq_addr;
2209 5bfb56b2 blueswir1
    uint32_t mcfq_insn;
2210 5bfb56b2 blueswir1
};
2211 5bfb56b2 blueswir1
2212 5bfb56b2 blueswir1
struct target_mc_fpu {
2213 5bfb56b2 blueswir1
    union {
2214 5bfb56b2 blueswir1
        uint32_t sregs[32];
2215 5bfb56b2 blueswir1
        uint64_t dregs[32];
2216 5bfb56b2 blueswir1
        //uint128_t qregs[16];
2217 5bfb56b2 blueswir1
    } mcfpu_fregs;
2218 992f48a0 blueswir1
    abi_ulong mcfpu_fsr;
2219 992f48a0 blueswir1
    abi_ulong mcfpu_fprs;
2220 992f48a0 blueswir1
    abi_ulong mcfpu_gsr;
2221 5bfb56b2 blueswir1
    struct target_mc_fq *mcfpu_fq;
2222 5bfb56b2 blueswir1
    unsigned char mcfpu_qcnt;
2223 5bfb56b2 blueswir1
    unsigned char mcfpu_qentsz;
2224 5bfb56b2 blueswir1
    unsigned char mcfpu_enab;
2225 5bfb56b2 blueswir1
};
2226 c227f099 Anthony Liguori
typedef struct target_mc_fpu target_mc_fpu_t;
2227 5bfb56b2 blueswir1
2228 5bfb56b2 blueswir1
typedef struct {
2229 c227f099 Anthony Liguori
    target_mc_gregset_t mc_gregs;
2230 c227f099 Anthony Liguori
    target_mc_greg_t mc_fp;
2231 c227f099 Anthony Liguori
    target_mc_greg_t mc_i7;
2232 c227f099 Anthony Liguori
    target_mc_fpu_t mc_fpregs;
2233 c227f099 Anthony Liguori
} target_mcontext_t;
2234 5bfb56b2 blueswir1
2235 5bfb56b2 blueswir1
struct target_ucontext {
2236 60e99246 Aurelien Jarno
    struct target_ucontext *tuc_link;
2237 60e99246 Aurelien Jarno
    abi_ulong tuc_flags;
2238 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
2239 60e99246 Aurelien Jarno
    target_mcontext_t tuc_mcontext;
2240 5bfb56b2 blueswir1
};
2241 5bfb56b2 blueswir1
2242 5bfb56b2 blueswir1
/* A V9 register window */
2243 5bfb56b2 blueswir1
struct target_reg_window {
2244 992f48a0 blueswir1
    abi_ulong locals[8];
2245 992f48a0 blueswir1
    abi_ulong ins[8];
2246 5bfb56b2 blueswir1
};
2247 5bfb56b2 blueswir1
2248 5bfb56b2 blueswir1
#define TARGET_STACK_BIAS 2047
2249 5bfb56b2 blueswir1
2250 5bfb56b2 blueswir1
/* {set, get}context() needed for 64-bit SparcLinux userland. */
2251 5bfb56b2 blueswir1
void sparc64_set_context(CPUSPARCState *env)
2252 5bfb56b2 blueswir1
{
2253 459a4017 bellard
    abi_ulong ucp_addr;
2254 459a4017 bellard
    struct target_ucontext *ucp;
2255 c227f099 Anthony Liguori
    target_mc_gregset_t *grp;
2256 992f48a0 blueswir1
    abi_ulong pc, npc, tstate;
2257 459a4017 bellard
    abi_ulong fp, i7, w_addr;
2258 5bfb56b2 blueswir1
    int err;
2259 5bfb56b2 blueswir1
    unsigned int i;
2260 5bfb56b2 blueswir1
2261 459a4017 bellard
    ucp_addr = env->regwptr[UREG_I0];
2262 459a4017 bellard
    if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
2263 459a4017 bellard
        goto do_sigsegv;
2264 60e99246 Aurelien Jarno
    grp  = &ucp->tuc_mcontext.mc_gregs;
2265 579a97f7 bellard
    err  = __get_user(pc, &((*grp)[MC_PC]));
2266 579a97f7 bellard
    err |= __get_user(npc, &((*grp)[MC_NPC]));
2267 5bfb56b2 blueswir1
    if (err || ((pc | npc) & 3))
2268 5bfb56b2 blueswir1
        goto do_sigsegv;
2269 5bfb56b2 blueswir1
    if (env->regwptr[UREG_I1]) {
2270 c227f099 Anthony Liguori
        target_sigset_t target_set;
2271 5bfb56b2 blueswir1
        sigset_t set;
2272 5bfb56b2 blueswir1
2273 5bfb56b2 blueswir1
        if (TARGET_NSIG_WORDS == 1) {
2274 60e99246 Aurelien Jarno
            if (__get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]))
2275 5bfb56b2 blueswir1
                goto do_sigsegv;
2276 5bfb56b2 blueswir1
        } else {
2277 459a4017 bellard
            abi_ulong *src, *dst;
2278 60e99246 Aurelien Jarno
            src = ucp->tuc_sigmask.sig;
2279 459a4017 bellard
            dst = target_set.sig;
2280 c227f099 Anthony Liguori
            for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
2281 5bfb56b2 blueswir1
                 i++, dst++, src++)
2282 459a4017 bellard
                err |= __get_user(*dst, src);
2283 5bfb56b2 blueswir1
            if (err)
2284 5bfb56b2 blueswir1
                goto do_sigsegv;
2285 5bfb56b2 blueswir1
        }
2286 5bfb56b2 blueswir1
        target_to_host_sigset_internal(&set, &target_set);
2287 5bfb56b2 blueswir1
        sigprocmask(SIG_SETMASK, &set, NULL);
2288 5bfb56b2 blueswir1
    }
2289 5bfb56b2 blueswir1
    env->pc = pc;
2290 5bfb56b2 blueswir1
    env->npc = npc;
2291 579a97f7 bellard
    err |= __get_user(env->y, &((*grp)[MC_Y]));
2292 579a97f7 bellard
    err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
2293 5bfb56b2 blueswir1
    env->asi = (tstate >> 24) & 0xff;
2294 5a834bb4 Blue Swirl
    cpu_put_ccr(env, tstate >> 32);
2295 5a834bb4 Blue Swirl
    cpu_put_cwp64(env, tstate & 0x1f);
2296 579a97f7 bellard
    err |= __get_user(env->gregs[1], (&(*grp)[MC_G1]));
2297 579a97f7 bellard
    err |= __get_user(env->gregs[2], (&(*grp)[MC_G2]));
2298 579a97f7 bellard
    err |= __get_user(env->gregs[3], (&(*grp)[MC_G3]));
2299 579a97f7 bellard
    err |= __get_user(env->gregs[4], (&(*grp)[MC_G4]));
2300 579a97f7 bellard
    err |= __get_user(env->gregs[5], (&(*grp)[MC_G5]));
2301 579a97f7 bellard
    err |= __get_user(env->gregs[6], (&(*grp)[MC_G6]));
2302 579a97f7 bellard
    err |= __get_user(env->gregs[7], (&(*grp)[MC_G7]));
2303 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
2304 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
2305 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
2306 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
2307 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
2308 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
2309 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
2310 579a97f7 bellard
    err |= __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
2311 579a97f7 bellard
2312 60e99246 Aurelien Jarno
    err |= __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
2313 60e99246 Aurelien Jarno
    err |= __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
2314 579a97f7 bellard
2315 459a4017 bellard
    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2316 459a4017 bellard
    if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
2317 459a4017 bellard
                 abi_ulong) != 0)
2318 459a4017 bellard
        goto do_sigsegv;
2319 459a4017 bellard
    if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
2320 459a4017 bellard
                 abi_ulong) != 0)
2321 459a4017 bellard
        goto do_sigsegv;
2322 c7b016ba Peter Maydell
    /* FIXME this does not match how the kernel handles the FPU in
2323 c7b016ba Peter Maydell
     * its sparc64_set_context implementation. In particular the FPU
2324 c7b016ba Peter Maydell
     * is only restored if fenab is non-zero in:
2325 c7b016ba Peter Maydell
     *   __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
2326 c7b016ba Peter Maydell
     */
2327 60e99246 Aurelien Jarno
    err |= __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
2328 459a4017 bellard
    {
2329 30038fd8 Richard Henderson
        uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2330 30038fd8 Richard Henderson
        for (i = 0; i < 64; i++, src++) {
2331 30038fd8 Richard Henderson
            if (i & 1) {
2332 30038fd8 Richard Henderson
                err |= __get_user(env->fpr[i/2].l.lower, src);
2333 30038fd8 Richard Henderson
            } else {
2334 30038fd8 Richard Henderson
                err |= __get_user(env->fpr[i/2].l.upper, src);
2335 30038fd8 Richard Henderson
            }
2336 30038fd8 Richard Henderson
        }
2337 459a4017 bellard
    }
2338 579a97f7 bellard
    err |= __get_user(env->fsr,
2339 60e99246 Aurelien Jarno
                      &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
2340 579a97f7 bellard
    err |= __get_user(env->gsr,
2341 60e99246 Aurelien Jarno
                      &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
2342 5bfb56b2 blueswir1
    if (err)
2343 5bfb56b2 blueswir1
        goto do_sigsegv;
2344 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 0);
2345 5bfb56b2 blueswir1
    return;
2346 5bfb56b2 blueswir1
 do_sigsegv:
2347 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 0);
2348 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
2349 5bfb56b2 blueswir1
}
2350 5bfb56b2 blueswir1
2351 5bfb56b2 blueswir1
void sparc64_get_context(CPUSPARCState *env)
2352 5bfb56b2 blueswir1
{
2353 459a4017 bellard
    abi_ulong ucp_addr;
2354 459a4017 bellard
    struct target_ucontext *ucp;
2355 c227f099 Anthony Liguori
    target_mc_gregset_t *grp;
2356 c227f099 Anthony Liguori
    target_mcontext_t *mcp;
2357 459a4017 bellard
    abi_ulong fp, i7, w_addr;
2358 5bfb56b2 blueswir1
    int err;
2359 5bfb56b2 blueswir1
    unsigned int i;
2360 c227f099 Anthony Liguori
    target_sigset_t target_set;
2361 5bfb56b2 blueswir1
    sigset_t set;
2362 5bfb56b2 blueswir1
2363 459a4017 bellard
    ucp_addr = env->regwptr[UREG_I0];
2364 459a4017 bellard
    if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
2365 459a4017 bellard
        goto do_sigsegv;
2366 459a4017 bellard
    
2367 60e99246 Aurelien Jarno
    mcp = &ucp->tuc_mcontext;
2368 5bfb56b2 blueswir1
    grp = &mcp->mc_gregs;
2369 5bfb56b2 blueswir1
2370 5bfb56b2 blueswir1
    /* Skip over the trap instruction, first. */
2371 5bfb56b2 blueswir1
    env->pc = env->npc;
2372 5bfb56b2 blueswir1
    env->npc += 4;
2373 5bfb56b2 blueswir1
2374 5bfb56b2 blueswir1
    err = 0;
2375 5bfb56b2 blueswir1
2376 5bfb56b2 blueswir1
    sigprocmask(0, NULL, &set);
2377 5bfb56b2 blueswir1
    host_to_target_sigset_internal(&target_set, &set);
2378 459a4017 bellard
    if (TARGET_NSIG_WORDS == 1) {
2379 579a97f7 bellard
        err |= __put_user(target_set.sig[0],
2380 60e99246 Aurelien Jarno
                          (abi_ulong *)&ucp->tuc_sigmask);
2381 459a4017 bellard
    } else {
2382 459a4017 bellard
        abi_ulong *src, *dst;
2383 459a4017 bellard
        src = target_set.sig;
2384 60e99246 Aurelien Jarno
        dst = ucp->tuc_sigmask.sig;
2385 c227f099 Anthony Liguori
        for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
2386 5bfb56b2 blueswir1
             i++, dst++, src++)
2387 459a4017 bellard
            err |= __put_user(*src, dst);
2388 5bfb56b2 blueswir1
        if (err)
2389 5bfb56b2 blueswir1
            goto do_sigsegv;
2390 5bfb56b2 blueswir1
    }
2391 5bfb56b2 blueswir1
2392 459a4017 bellard
    /* XXX: tstate must be saved properly */
2393 459a4017 bellard
    //    err |= __put_user(env->tstate, &((*grp)[MC_TSTATE]));
2394 579a97f7 bellard
    err |= __put_user(env->pc, &((*grp)[MC_PC]));
2395 579a97f7 bellard
    err |= __put_user(env->npc, &((*grp)[MC_NPC]));
2396 579a97f7 bellard
    err |= __put_user(env->y, &((*grp)[MC_Y]));
2397 579a97f7 bellard
    err |= __put_user(env->gregs[1], &((*grp)[MC_G1]));
2398 579a97f7 bellard
    err |= __put_user(env->gregs[2], &((*grp)[MC_G2]));
2399 579a97f7 bellard
    err |= __put_user(env->gregs[3], &((*grp)[MC_G3]));
2400 579a97f7 bellard
    err |= __put_user(env->gregs[4], &((*grp)[MC_G4]));
2401 579a97f7 bellard
    err |= __put_user(env->gregs[5], &((*grp)[MC_G5]));
2402 579a97f7 bellard
    err |= __put_user(env->gregs[6], &((*grp)[MC_G6]));
2403 579a97f7 bellard
    err |= __put_user(env->gregs[7], &((*grp)[MC_G7]));
2404 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
2405 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
2406 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
2407 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
2408 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
2409 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
2410 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
2411 579a97f7 bellard
    err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
2412 579a97f7 bellard
2413 459a4017 bellard
    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
2414 459a4017 bellard
    fp = i7 = 0;
2415 459a4017 bellard
    if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
2416 459a4017 bellard
                 abi_ulong) != 0)
2417 459a4017 bellard
        goto do_sigsegv;
2418 459a4017 bellard
    if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
2419 459a4017 bellard
                 abi_ulong) != 0)
2420 459a4017 bellard
        goto do_sigsegv;
2421 579a97f7 bellard
    err |= __put_user(fp, &(mcp->mc_fp));
2422 579a97f7 bellard
    err |= __put_user(i7, &(mcp->mc_i7));
2423 5bfb56b2 blueswir1
2424 459a4017 bellard
    {
2425 30038fd8 Richard Henderson
        uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
2426 30038fd8 Richard Henderson
        for (i = 0; i < 64; i++, dst++) {
2427 30038fd8 Richard Henderson
            if (i & 1) {
2428 30038fd8 Richard Henderson
                err |= __put_user(env->fpr[i/2].l.lower, dst);
2429 30038fd8 Richard Henderson
            } else {
2430 30038fd8 Richard Henderson
                err |= __put_user(env->fpr[i/2].l.upper, dst);
2431 30038fd8 Richard Henderson
            }
2432 30038fd8 Richard Henderson
        }
2433 459a4017 bellard
    }
2434 579a97f7 bellard
    err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
2435 579a97f7 bellard
    err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
2436 579a97f7 bellard
    err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
2437 5bfb56b2 blueswir1
2438 5bfb56b2 blueswir1
    if (err)
2439 5bfb56b2 blueswir1
        goto do_sigsegv;
2440 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 1);
2441 5bfb56b2 blueswir1
    return;
2442 5bfb56b2 blueswir1
 do_sigsegv:
2443 459a4017 bellard
    unlock_user_struct(ucp, ucp_addr, 1);
2444 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
2445 5bfb56b2 blueswir1
}
2446 5bfb56b2 blueswir1
#endif
2447 d26bc211 ths
#elif defined(TARGET_ABI_MIPSN64)
2448 540635ba ths
2449 540635ba ths
# warning signal handling not implemented
2450 540635ba ths
2451 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
2452 05390248 Andreas Färber
                        target_sigset_t *set, CPUMIPSState *env)
2453 540635ba ths
{
2454 540635ba ths
    fprintf(stderr, "setup_frame: not implemented\n");
2455 540635ba ths
}
2456 540635ba ths
2457 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2458 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2459 05390248 Andreas Färber
                           target_sigset_t *set, CPUMIPSState *env)
2460 540635ba ths
{
2461 540635ba ths
    fprintf(stderr, "setup_rt_frame: not implemented\n");
2462 540635ba ths
}
2463 540635ba ths
2464 05390248 Andreas Färber
long do_sigreturn(CPUMIPSState *env)
2465 540635ba ths
{
2466 540635ba ths
    fprintf(stderr, "do_sigreturn: not implemented\n");
2467 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2468 540635ba ths
}
2469 540635ba ths
2470 05390248 Andreas Färber
long do_rt_sigreturn(CPUMIPSState *env)
2471 540635ba ths
{
2472 540635ba ths
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
2473 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2474 540635ba ths
}
2475 540635ba ths
2476 d26bc211 ths
#elif defined(TARGET_ABI_MIPSN32)
2477 540635ba ths
2478 540635ba ths
# warning signal handling not implemented
2479 540635ba ths
2480 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
2481 05390248 Andreas Färber
                        target_sigset_t *set, CPUMIPSState *env)
2482 540635ba ths
{
2483 540635ba ths
    fprintf(stderr, "setup_frame: not implemented\n");
2484 540635ba ths
}
2485 540635ba ths
2486 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2487 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2488 05390248 Andreas Färber
                           target_sigset_t *set, CPUMIPSState *env)
2489 540635ba ths
{
2490 540635ba ths
    fprintf(stderr, "setup_rt_frame: not implemented\n");
2491 540635ba ths
}
2492 540635ba ths
2493 05390248 Andreas Färber
long do_sigreturn(CPUMIPSState *env)
2494 540635ba ths
{
2495 540635ba ths
    fprintf(stderr, "do_sigreturn: not implemented\n");
2496 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2497 540635ba ths
}
2498 540635ba ths
2499 05390248 Andreas Färber
long do_rt_sigreturn(CPUMIPSState *env)
2500 540635ba ths
{
2501 540635ba ths
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
2502 f8b0aa25 bellard
    return -TARGET_ENOSYS;
2503 540635ba ths
}
2504 540635ba ths
2505 d26bc211 ths
#elif defined(TARGET_ABI_MIPSO32)
2506 106ec879 bellard
2507 106ec879 bellard
struct target_sigcontext {
2508 106ec879 bellard
    uint32_t   sc_regmask;     /* Unused */
2509 106ec879 bellard
    uint32_t   sc_status;
2510 106ec879 bellard
    uint64_t   sc_pc;
2511 106ec879 bellard
    uint64_t   sc_regs[32];
2512 106ec879 bellard
    uint64_t   sc_fpregs[32];
2513 106ec879 bellard
    uint32_t   sc_ownedfp;     /* Unused */
2514 106ec879 bellard
    uint32_t   sc_fpc_csr;
2515 106ec879 bellard
    uint32_t   sc_fpc_eir;     /* Unused */
2516 106ec879 bellard
    uint32_t   sc_used_math;
2517 106ec879 bellard
    uint32_t   sc_dsp;         /* dsp status, was sc_ssflags */
2518 94c5495d Paul Brook
    uint32_t   pad0;
2519 106ec879 bellard
    uint64_t   sc_mdhi;
2520 106ec879 bellard
    uint64_t   sc_mdlo;
2521 106ec879 bellard
    target_ulong   sc_hi1;         /* Was sc_cause */
2522 106ec879 bellard
    target_ulong   sc_lo1;         /* Was sc_badvaddr */
2523 106ec879 bellard
    target_ulong   sc_hi2;         /* Was sc_sigset[4] */
2524 106ec879 bellard
    target_ulong   sc_lo2;
2525 106ec879 bellard
    target_ulong   sc_hi3;
2526 106ec879 bellard
    target_ulong   sc_lo3;
2527 106ec879 bellard
};
2528 106ec879 bellard
2529 106ec879 bellard
struct sigframe {
2530 106ec879 bellard
    uint32_t sf_ass[4];                        /* argument save space for o32 */
2531 106ec879 bellard
    uint32_t sf_code[2];                        /* signal trampoline */
2532 106ec879 bellard
    struct target_sigcontext sf_sc;
2533 c227f099 Anthony Liguori
    target_sigset_t sf_mask;
2534 106ec879 bellard
};
2535 106ec879 bellard
2536 0b1bcb00 pbrook
struct target_ucontext {
2537 60e99246 Aurelien Jarno
    target_ulong tuc_flags;
2538 60e99246 Aurelien Jarno
    target_ulong tuc_link;
2539 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
2540 94c5495d Paul Brook
    target_ulong pad0;
2541 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
2542 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
2543 0b1bcb00 pbrook
};
2544 0b1bcb00 pbrook
2545 0b1bcb00 pbrook
struct target_rt_sigframe {
2546 0b1bcb00 pbrook
    uint32_t rs_ass[4];               /* argument save space for o32 */
2547 0b1bcb00 pbrook
    uint32_t rs_code[2];              /* signal trampoline */
2548 0b1bcb00 pbrook
    struct target_siginfo rs_info;
2549 0b1bcb00 pbrook
    struct target_ucontext rs_uc;
2550 0b1bcb00 pbrook
};
2551 0b1bcb00 pbrook
2552 106ec879 bellard
/* Install trampoline to jump back from signal handler */
2553 106ec879 bellard
static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
2554 106ec879 bellard
{
2555 106ec879 bellard
    int err;
2556 106ec879 bellard
2557 106ec879 bellard
    /*
2558 106ec879 bellard
    * Set up the return code ...
2559 106ec879 bellard
    *
2560 106ec879 bellard
    *         li      v0, __NR__foo_sigreturn
2561 106ec879 bellard
    *         syscall
2562 106ec879 bellard
    */
2563 106ec879 bellard
2564 106ec879 bellard
    err = __put_user(0x24020000 + syscall, tramp + 0);
2565 106ec879 bellard
    err |= __put_user(0x0000000c          , tramp + 1);
2566 106ec879 bellard
    /* flush_cache_sigtramp((unsigned long) tramp); */
2567 106ec879 bellard
    return err;
2568 106ec879 bellard
}
2569 106ec879 bellard
2570 106ec879 bellard
static inline int
2571 05390248 Andreas Färber
setup_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
2572 106ec879 bellard
{
2573 106ec879 bellard
    int err = 0;
2574 106ec879 bellard
2575 b5dc7732 ths
    err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
2576 106ec879 bellard
2577 b5dc7732 ths
#define save_gp_reg(i) do {                                                   \
2578 b5dc7732 ths
        err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);        \
2579 106ec879 bellard
    } while(0)
2580 106ec879 bellard
    __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
2581 106ec879 bellard
    save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
2582 106ec879 bellard
    save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
2583 106ec879 bellard
    save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
2584 106ec879 bellard
    save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
2585 106ec879 bellard
    save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
2586 106ec879 bellard
    save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
2587 106ec879 bellard
    save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
2588 106ec879 bellard
    save_gp_reg(31);
2589 388bb21a ths
#undef save_gp_reg
2590 106ec879 bellard
2591 b5dc7732 ths
    err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2592 b5dc7732 ths
    err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
2593 106ec879 bellard
2594 106ec879 bellard
    /* Not used yet, but might be useful if we ever have DSP suppport */
2595 106ec879 bellard
#if 0
2596 106ec879 bellard
    if (cpu_has_dsp) {
2597 106ec879 bellard
        err |= __put_user(mfhi1(), &sc->sc_hi1);
2598 106ec879 bellard
        err |= __put_user(mflo1(), &sc->sc_lo1);
2599 106ec879 bellard
        err |= __put_user(mfhi2(), &sc->sc_hi2);
2600 106ec879 bellard
        err |= __put_user(mflo2(), &sc->sc_lo2);
2601 106ec879 bellard
        err |= __put_user(mfhi3(), &sc->sc_hi3);
2602 106ec879 bellard
        err |= __put_user(mflo3(), &sc->sc_lo3);
2603 106ec879 bellard
        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2604 106ec879 bellard
    }
2605 106ec879 bellard
    /* same with 64 bit */
2606 388bb21a ths
#ifdef CONFIG_64BIT
2607 106ec879 bellard
    err |= __put_user(regs->hi, &sc->sc_hi[0]);
2608 106ec879 bellard
    err |= __put_user(regs->lo, &sc->sc_lo[0]);
2609 106ec879 bellard
    if (cpu_has_dsp) {
2610 106ec879 bellard
        err |= __put_user(mfhi1(), &sc->sc_hi[1]);
2611 106ec879 bellard
        err |= __put_user(mflo1(), &sc->sc_lo[1]);
2612 106ec879 bellard
        err |= __put_user(mfhi2(), &sc->sc_hi[2]);
2613 106ec879 bellard
        err |= __put_user(mflo2(), &sc->sc_lo[2]);
2614 106ec879 bellard
        err |= __put_user(mfhi3(), &sc->sc_hi[3]);
2615 106ec879 bellard
        err |= __put_user(mflo3(), &sc->sc_lo[3]);
2616 106ec879 bellard
        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
2617 106ec879 bellard
    }
2618 388bb21a ths
#endif
2619 388bb21a ths
#endif
2620 106ec879 bellard
2621 388bb21a ths
#if 0
2622 106ec879 bellard
    err |= __put_user(!!used_math(), &sc->sc_used_math);
2623 106ec879 bellard

2624 106ec879 bellard
    if (!used_math())
2625 106ec879 bellard
        goto out;
2626 106ec879 bellard

2627 106ec879 bellard
    /*
2628 106ec879 bellard
    * Save FPU state to signal context.  Signal handler will "inherit"
2629 106ec879 bellard
    * current FPU state.
2630 106ec879 bellard
    */
2631 106ec879 bellard
    preempt_disable();
2632 106ec879 bellard

2633 106ec879 bellard
    if (!is_fpu_owner()) {
2634 106ec879 bellard
        own_fpu();
2635 106ec879 bellard
        restore_fp(current);
2636 106ec879 bellard
    }
2637 106ec879 bellard
    err |= save_fp_context(sc);
2638 106ec879 bellard

2639 106ec879 bellard
    preempt_enable();
2640 106ec879 bellard
    out:
2641 106ec879 bellard
#endif
2642 106ec879 bellard
    return err;
2643 106ec879 bellard
}
2644 106ec879 bellard
2645 106ec879 bellard
static inline int
2646 05390248 Andreas Färber
restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
2647 106ec879 bellard
{
2648 106ec879 bellard
    int err = 0;
2649 106ec879 bellard
2650 106ec879 bellard
    err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
2651 106ec879 bellard
2652 b5dc7732 ths
    err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
2653 b5dc7732 ths
    err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
2654 106ec879 bellard
2655 ead9360e ths
#define restore_gp_reg(i) do {                                                           \
2656 b5dc7732 ths
        err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);                \
2657 106ec879 bellard
    } while(0)
2658 106ec879 bellard
    restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
2659 106ec879 bellard
    restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
2660 106ec879 bellard
    restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
2661 106ec879 bellard
    restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
2662 106ec879 bellard
    restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
2663 106ec879 bellard
    restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
2664 106ec879 bellard
    restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
2665 106ec879 bellard
    restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
2666 106ec879 bellard
    restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
2667 106ec879 bellard
    restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
2668 106ec879 bellard
    restore_gp_reg(31);
2669 388bb21a ths
#undef restore_gp_reg
2670 106ec879 bellard
2671 106ec879 bellard
#if 0
2672 106ec879 bellard
    if (cpu_has_dsp) {
2673 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
2674 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
2675 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
2676 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
2677 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
2678 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
2679 106ec879 bellard
        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2680 106ec879 bellard
    }
2681 388bb21a ths
#ifdef CONFIG_64BIT
2682 106ec879 bellard
    err |= __get_user(regs->hi, &sc->sc_hi[0]);
2683 106ec879 bellard
    err |= __get_user(regs->lo, &sc->sc_lo[0]);
2684 106ec879 bellard
    if (cpu_has_dsp) {
2685 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
2686 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
2687 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
2688 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
2689 106ec879 bellard
        err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
2690 106ec879 bellard
        err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
2691 106ec879 bellard
        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
2692 106ec879 bellard
    }
2693 388bb21a ths
#endif
2694 106ec879 bellard
2695 106ec879 bellard
    err |= __get_user(used_math, &sc->sc_used_math);
2696 106ec879 bellard
    conditional_used_math(used_math);
2697 106ec879 bellard
2698 106ec879 bellard
    preempt_disable();
2699 106ec879 bellard
2700 106ec879 bellard
    if (used_math()) {
2701 106ec879 bellard
        /* restore fpu context if we have used it before */
2702 106ec879 bellard
        own_fpu();
2703 106ec879 bellard
        err |= restore_fp_context(sc);
2704 106ec879 bellard
    } else {
2705 106ec879 bellard
        /* signal handler may have used FPU.  Give it up. */
2706 106ec879 bellard
        lose_fpu();
2707 106ec879 bellard
    }
2708 106ec879 bellard
2709 106ec879 bellard
    preempt_enable();
2710 106ec879 bellard
#endif
2711 106ec879 bellard
    return err;
2712 106ec879 bellard
}
2713 106ec879 bellard
/*
2714 106ec879 bellard
 * Determine which stack to use..
2715 106ec879 bellard
 */
2716 579a97f7 bellard
static inline abi_ulong
2717 05390248 Andreas Färber
get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
2718 106ec879 bellard
{
2719 106ec879 bellard
    unsigned long sp;
2720 106ec879 bellard
2721 106ec879 bellard
    /* Default to using normal stack */
2722 b5dc7732 ths
    sp = regs->active_tc.gpr[29];
2723 106ec879 bellard
2724 106ec879 bellard
    /*
2725 93148aa5 Stefan Weil
     * FPU emulator may have its own trampoline active just
2726 106ec879 bellard
     * above the user stack, 16-bytes before the next lowest
2727 106ec879 bellard
     * 16 byte boundary.  Try to avoid trashing it.
2728 106ec879 bellard
     */
2729 106ec879 bellard
    sp -= 32;
2730 106ec879 bellard
2731 106ec879 bellard
    /* This is the X/Open sanctioned signal stack switching.  */
2732 624f7979 pbrook
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
2733 a04e134a ths
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2734 a04e134a ths
    }
2735 106ec879 bellard
2736 579a97f7 bellard
    return (sp - frame_size) & ~7;
2737 106ec879 bellard
}
2738 106ec879 bellard
2739 579a97f7 bellard
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
2740 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction * ka,
2741 05390248 Andreas Färber
                        target_sigset_t *set, CPUMIPSState *regs)
2742 106ec879 bellard
{
2743 106ec879 bellard
    struct sigframe *frame;
2744 579a97f7 bellard
    abi_ulong frame_addr;
2745 106ec879 bellard
    int i;
2746 106ec879 bellard
2747 579a97f7 bellard
    frame_addr = get_sigframe(ka, regs, sizeof(*frame));
2748 579a97f7 bellard
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2749 106ec879 bellard
        goto give_sigsegv;
2750 106ec879 bellard
2751 106ec879 bellard
    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
2752 106ec879 bellard
2753 106ec879 bellard
    if(setup_sigcontext(regs, &frame->sf_sc))
2754 106ec879 bellard
        goto give_sigsegv;
2755 106ec879 bellard
2756 106ec879 bellard
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2757 106ec879 bellard
        if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))
2758 106ec879 bellard
            goto give_sigsegv;
2759 106ec879 bellard
    }
2760 106ec879 bellard
2761 106ec879 bellard
    /*
2762 106ec879 bellard
    * Arguments to signal handler:
2763 106ec879 bellard
    *
2764 106ec879 bellard
    *   a0 = signal number
2765 106ec879 bellard
    *   a1 = 0 (should be cause)
2766 106ec879 bellard
    *   a2 = pointer to struct sigcontext
2767 106ec879 bellard
    *
2768 106ec879 bellard
    * $25 and PC point to the signal handler, $29 points to the
2769 106ec879 bellard
    * struct sigframe.
2770 106ec879 bellard
    */
2771 b5dc7732 ths
    regs->active_tc.gpr[ 4] = sig;
2772 b5dc7732 ths
    regs->active_tc.gpr[ 5] = 0;
2773 b5dc7732 ths
    regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
2774 b5dc7732 ths
    regs->active_tc.gpr[29] = frame_addr;
2775 b5dc7732 ths
    regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
2776 106ec879 bellard
    /* The original kernel code sets CP0_EPC to the handler
2777 106ec879 bellard
    * since it returns to userland using eret
2778 106ec879 bellard
    * we cannot do this here, and we must set PC directly */
2779 b5dc7732 ths
    regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
2780 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 1);
2781 106ec879 bellard
    return;
2782 106ec879 bellard
2783 106ec879 bellard
give_sigsegv:
2784 579a97f7 bellard
    unlock_user_struct(frame, frame_addr, 1);
2785 106ec879 bellard
    force_sig(TARGET_SIGSEGV/*, current*/);
2786 106ec879 bellard
}
2787 106ec879 bellard
2788 05390248 Andreas Färber
long do_sigreturn(CPUMIPSState *regs)
2789 106ec879 bellard
{
2790 388bb21a ths
    struct sigframe *frame;
2791 579a97f7 bellard
    abi_ulong frame_addr;
2792 388bb21a ths
    sigset_t blocked;
2793 c227f099 Anthony Liguori
    target_sigset_t target_set;
2794 388bb21a ths
    int i;
2795 106ec879 bellard
2796 106ec879 bellard
#if defined(DEBUG_SIGNAL)
2797 388bb21a ths
    fprintf(stderr, "do_sigreturn\n");
2798 106ec879 bellard
#endif
2799 b5dc7732 ths
    frame_addr = regs->active_tc.gpr[29];
2800 579a97f7 bellard
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2801 106ec879 bellard
           goto badframe;
2802 106ec879 bellard
2803 388bb21a ths
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2804 106ec879 bellard
           if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
2805 106ec879 bellard
            goto badframe;
2806 388bb21a ths
    }
2807 106ec879 bellard
2808 388bb21a ths
    target_to_host_sigset_internal(&blocked, &target_set);
2809 388bb21a ths
    sigprocmask(SIG_SETMASK, &blocked, NULL);
2810 106ec879 bellard
2811 388bb21a ths
    if (restore_sigcontext(regs, &frame->sf_sc))
2812 106ec879 bellard
           goto badframe;
2813 106ec879 bellard
2814 106ec879 bellard
#if 0
2815 388bb21a ths
    /*
2816 388bb21a ths
     * Don't let your children do this ...
2817 388bb21a ths
     */
2818 388bb21a ths
    __asm__ __volatile__(
2819 106ec879 bellard
           "move\t$29, %0\n\t"
2820 106ec879 bellard
           "j\tsyscall_exit"
2821 106ec879 bellard
           :/* no outputs */
2822 106ec879 bellard
           :"r" (&regs));
2823 388bb21a ths
    /* Unreached */
2824 106ec879 bellard
#endif
2825 3b46e624 ths
2826 b5dc7732 ths
    regs->active_tc.PC = regs->CP0_EPC;
2827 388bb21a ths
    /* I am not sure this is right, but it seems to work
2828 106ec879 bellard
    * maybe a problem with nested signals ? */
2829 106ec879 bellard
    regs->CP0_EPC = 0;
2830 0b1bcb00 pbrook
    return -TARGET_QEMU_ESIGRETURN;
2831 106ec879 bellard
2832 106ec879 bellard
badframe:
2833 388bb21a ths
    force_sig(TARGET_SIGSEGV/*, current*/);
2834 388bb21a ths
    return 0;
2835 106ec879 bellard
}
2836 106ec879 bellard
2837 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
2838 c227f099 Anthony Liguori
                           target_siginfo_t *info,
2839 05390248 Andreas Färber
                           target_sigset_t *set, CPUMIPSState *env)
2840 106ec879 bellard
{
2841 0b1bcb00 pbrook
    struct target_rt_sigframe *frame;
2842 0b1bcb00 pbrook
    abi_ulong frame_addr;
2843 0b1bcb00 pbrook
    int i;
2844 0b1bcb00 pbrook
2845 0b1bcb00 pbrook
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
2846 0b1bcb00 pbrook
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
2847 0b1bcb00 pbrook
        goto give_sigsegv;
2848 0b1bcb00 pbrook
2849 0b1bcb00 pbrook
    install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
2850 0b1bcb00 pbrook
2851 0b1bcb00 pbrook
    copy_siginfo_to_user(&frame->rs_info, info);
2852 0b1bcb00 pbrook
2853 60e99246 Aurelien Jarno
    __put_user(0, &frame->rs_uc.tuc_flags);
2854 60e99246 Aurelien Jarno
    __put_user(0, &frame->rs_uc.tuc_link);
2855 60e99246 Aurelien Jarno
    __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
2856 60e99246 Aurelien Jarno
    __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
2857 0b1bcb00 pbrook
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
2858 60e99246 Aurelien Jarno
               &frame->rs_uc.tuc_stack.ss_flags);
2859 0b1bcb00 pbrook
2860 60e99246 Aurelien Jarno
    setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
2861 0b1bcb00 pbrook
2862 0b1bcb00 pbrook
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
2863 60e99246 Aurelien Jarno
        __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
2864 0b1bcb00 pbrook
    }
2865 0b1bcb00 pbrook
2866 0b1bcb00 pbrook
    /*
2867 0b1bcb00 pbrook
    * Arguments to signal handler:
2868 0b1bcb00 pbrook
    *
2869 0b1bcb00 pbrook
    *   a0 = signal number
2870 02d2bd5d Richard W.M. Jones
    *   a1 = pointer to siginfo_t
2871 0b1bcb00 pbrook
    *   a2 = pointer to struct ucontext
2872 0b1bcb00 pbrook
    *
2873 0b1bcb00 pbrook
    * $25 and PC point to the signal handler, $29 points to the
2874 0b1bcb00 pbrook
    * struct sigframe.
2875 0b1bcb00 pbrook
    */
2876 0b1bcb00 pbrook
    env->active_tc.gpr[ 4] = sig;
2877 0b1bcb00 pbrook
    env->active_tc.gpr[ 5] = frame_addr
2878 0b1bcb00 pbrook
                             + offsetof(struct target_rt_sigframe, rs_info);
2879 0b1bcb00 pbrook
    env->active_tc.gpr[ 6] = frame_addr
2880 0b1bcb00 pbrook
                             + offsetof(struct target_rt_sigframe, rs_uc);
2881 0b1bcb00 pbrook
    env->active_tc.gpr[29] = frame_addr;
2882 0b1bcb00 pbrook
    env->active_tc.gpr[31] = frame_addr
2883 0b1bcb00 pbrook
                             + offsetof(struct target_rt_sigframe, rs_code);
2884 0b1bcb00 pbrook
    /* The original kernel code sets CP0_EPC to the handler
2885 0b1bcb00 pbrook
    * since it returns to userland using eret
2886 0b1bcb00 pbrook
    * we cannot do this here, and we must set PC directly */
2887 0b1bcb00 pbrook
    env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
2888 0b1bcb00 pbrook
    unlock_user_struct(frame, frame_addr, 1);
2889 0b1bcb00 pbrook
    return;
2890 0b1bcb00 pbrook
2891 0b1bcb00 pbrook
give_sigsegv:
2892 0b1bcb00 pbrook
    unlock_user_struct(frame, frame_addr, 1);
2893 0b1bcb00 pbrook
    force_sig(TARGET_SIGSEGV/*, current*/);
2894 106ec879 bellard
}
2895 106ec879 bellard
2896 05390248 Andreas Färber
long do_rt_sigreturn(CPUMIPSState *env)
2897 106ec879 bellard
{
2898 0b1bcb00 pbrook
    struct target_rt_sigframe *frame;
2899 0b1bcb00 pbrook
    abi_ulong frame_addr;
2900 0b1bcb00 pbrook
    sigset_t blocked;
2901 0b1bcb00 pbrook
2902 0b1bcb00 pbrook
#if defined(DEBUG_SIGNAL)
2903 0b1bcb00 pbrook
    fprintf(stderr, "do_rt_sigreturn\n");
2904 0b1bcb00 pbrook
#endif
2905 0b1bcb00 pbrook
    frame_addr = env->active_tc.gpr[29];
2906 0b1bcb00 pbrook
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
2907 0b1bcb00 pbrook
           goto badframe;
2908 0b1bcb00 pbrook
2909 60e99246 Aurelien Jarno
    target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
2910 0b1bcb00 pbrook
    sigprocmask(SIG_SETMASK, &blocked, NULL);
2911 0b1bcb00 pbrook
2912 60e99246 Aurelien Jarno
    if (restore_sigcontext(env, &frame->rs_uc.tuc_mcontext))
2913 0b1bcb00 pbrook
        goto badframe;
2914 0b1bcb00 pbrook
2915 0b1bcb00 pbrook
    if (do_sigaltstack(frame_addr +
2916 60e99246 Aurelien Jarno
                       offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
2917 0b1bcb00 pbrook
                       0, get_sp_from_cpustate(env)) == -EFAULT)
2918 0b1bcb00 pbrook
        goto badframe;
2919 0b1bcb00 pbrook
2920 0b1bcb00 pbrook
    env->active_tc.PC = env->CP0_EPC;
2921 0b1bcb00 pbrook
    /* I am not sure this is right, but it seems to work
2922 0b1bcb00 pbrook
    * maybe a problem with nested signals ? */
2923 0b1bcb00 pbrook
    env->CP0_EPC = 0;
2924 0b1bcb00 pbrook
    return -TARGET_QEMU_ESIGRETURN;
2925 0b1bcb00 pbrook
2926 0b1bcb00 pbrook
badframe:
2927 0b1bcb00 pbrook
    force_sig(TARGET_SIGSEGV/*, current*/);
2928 0b1bcb00 pbrook
    return 0;
2929 106ec879 bellard
}
2930 6d5e216d bellard
2931 c3b5bc8a ths
#elif defined(TARGET_SH4)
2932 c3b5bc8a ths
2933 c3b5bc8a ths
/*
2934 c3b5bc8a ths
 * code and data structures from linux kernel:
2935 c3b5bc8a ths
 * include/asm-sh/sigcontext.h
2936 c3b5bc8a ths
 * arch/sh/kernel/signal.c
2937 c3b5bc8a ths
 */
2938 c3b5bc8a ths
2939 c3b5bc8a ths
struct target_sigcontext {
2940 c3b5bc8a ths
    target_ulong  oldmask;
2941 c3b5bc8a ths
2942 c3b5bc8a ths
    /* CPU registers */
2943 c3b5bc8a ths
    target_ulong  sc_gregs[16];
2944 c3b5bc8a ths
    target_ulong  sc_pc;
2945 c3b5bc8a ths
    target_ulong  sc_pr;
2946 c3b5bc8a ths
    target_ulong  sc_sr;
2947 c3b5bc8a ths
    target_ulong  sc_gbr;
2948 c3b5bc8a ths
    target_ulong  sc_mach;
2949 c3b5bc8a ths
    target_ulong  sc_macl;
2950 c3b5bc8a ths
2951 c3b5bc8a ths
    /* FPU registers */
2952 c3b5bc8a ths
    target_ulong  sc_fpregs[16];
2953 c3b5bc8a ths
    target_ulong  sc_xfpregs[16];
2954 c3b5bc8a ths
    unsigned int sc_fpscr;
2955 c3b5bc8a ths
    unsigned int sc_fpul;
2956 c3b5bc8a ths
    unsigned int sc_ownedfp;
2957 c3b5bc8a ths
};
2958 c3b5bc8a ths
2959 c3b5bc8a ths
struct target_sigframe
2960 c3b5bc8a ths
{
2961 c3b5bc8a ths
    struct target_sigcontext sc;
2962 c3b5bc8a ths
    target_ulong extramask[TARGET_NSIG_WORDS-1];
2963 c3b5bc8a ths
    uint16_t retcode[3];
2964 c3b5bc8a ths
};
2965 c3b5bc8a ths
2966 c3b5bc8a ths
2967 c3b5bc8a ths
struct target_ucontext {
2968 60e99246 Aurelien Jarno
    target_ulong tuc_flags;
2969 60e99246 Aurelien Jarno
    struct target_ucontext *tuc_link;
2970 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
2971 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
2972 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;        /* mask last for extensibility */
2973 c3b5bc8a ths
};
2974 c3b5bc8a ths
2975 c3b5bc8a ths
struct target_rt_sigframe
2976 c3b5bc8a ths
{
2977 c3b5bc8a ths
    struct target_siginfo info;
2978 c3b5bc8a ths
    struct target_ucontext uc;
2979 c3b5bc8a ths
    uint16_t retcode[3];
2980 c3b5bc8a ths
};
2981 c3b5bc8a ths
2982 c3b5bc8a ths
2983 c3b5bc8a ths
#define MOVW(n)  (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
2984 c3b5bc8a ths
#define TRAP_NOARG 0xc310         /* Syscall w/no args (NR in R3) SH3/4 */
2985 c3b5bc8a ths
2986 624f7979 pbrook
static abi_ulong get_sigframe(struct target_sigaction *ka,
2987 c3b5bc8a ths
                         unsigned long sp, size_t frame_size)
2988 c3b5bc8a ths
{
2989 624f7979 pbrook
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
2990 c3b5bc8a ths
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
2991 c3b5bc8a ths
    }
2992 c3b5bc8a ths
2993 c3b5bc8a ths
    return (sp - frame_size) & -8ul;
2994 c3b5bc8a ths
}
2995 c3b5bc8a ths
2996 c3b5bc8a ths
static int setup_sigcontext(struct target_sigcontext *sc,
2997 05390248 Andreas Färber
                            CPUSH4State *regs, unsigned long mask)
2998 c3b5bc8a ths
{
2999 c3b5bc8a ths
    int err = 0;
3000 d8714436 takasi-y@ops.dti.ne.jp
    int i;
3001 c3b5bc8a ths
3002 c3b5bc8a ths
#define COPY(x)         err |= __put_user(regs->x, &sc->sc_##x)
3003 c3b5bc8a ths
    COPY(gregs[0]); COPY(gregs[1]);
3004 c3b5bc8a ths
    COPY(gregs[2]); COPY(gregs[3]);
3005 c3b5bc8a ths
    COPY(gregs[4]); COPY(gregs[5]);
3006 c3b5bc8a ths
    COPY(gregs[6]); COPY(gregs[7]);
3007 c3b5bc8a ths
    COPY(gregs[8]); COPY(gregs[9]);
3008 c3b5bc8a ths
    COPY(gregs[10]); COPY(gregs[11]);
3009 c3b5bc8a ths
    COPY(gregs[12]); COPY(gregs[13]);
3010 c3b5bc8a ths
    COPY(gregs[14]); COPY(gregs[15]);
3011 c3b5bc8a ths
    COPY(gbr); COPY(mach);
3012 c3b5bc8a ths
    COPY(macl); COPY(pr);
3013 c3b5bc8a ths
    COPY(sr); COPY(pc);
3014 c3b5bc8a ths
#undef COPY
3015 c3b5bc8a ths
3016 d8714436 takasi-y@ops.dti.ne.jp
    for (i=0; i<16; i++) {
3017 d8714436 takasi-y@ops.dti.ne.jp
        err |= __put_user(regs->fregs[i], &sc->sc_fpregs[i]);
3018 d8714436 takasi-y@ops.dti.ne.jp
    }
3019 d8714436 takasi-y@ops.dti.ne.jp
    err |= __put_user(regs->fpscr, &sc->sc_fpscr);
3020 d8714436 takasi-y@ops.dti.ne.jp
    err |= __put_user(regs->fpul, &sc->sc_fpul);
3021 c3b5bc8a ths
3022 c3b5bc8a ths
    /* non-iBCS2 extensions.. */
3023 c3b5bc8a ths
    err |= __put_user(mask, &sc->oldmask);
3024 c3b5bc8a ths
3025 c3b5bc8a ths
    return err;
3026 c3b5bc8a ths
}
3027 c3b5bc8a ths
3028 05390248 Andreas Färber
static int restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
3029 d8714436 takasi-y@ops.dti.ne.jp
                              target_ulong *r0_p)
3030 c3b5bc8a ths
{
3031 c3b5bc8a ths
    unsigned int err = 0;
3032 d8714436 takasi-y@ops.dti.ne.jp
    int i;
3033 c3b5bc8a ths
3034 c3b5bc8a ths
#define COPY(x)         err |= __get_user(regs->x, &sc->sc_##x)
3035 c3b5bc8a ths
    COPY(gregs[1]);
3036 c3b5bc8a ths
    COPY(gregs[2]); COPY(gregs[3]);
3037 c3b5bc8a ths
    COPY(gregs[4]); COPY(gregs[5]);
3038 c3b5bc8a ths
    COPY(gregs[6]); COPY(gregs[7]);
3039 c3b5bc8a ths
    COPY(gregs[8]); COPY(gregs[9]);
3040 c3b5bc8a ths
    COPY(gregs[10]); COPY(gregs[11]);
3041 c3b5bc8a ths
    COPY(gregs[12]); COPY(gregs[13]);
3042 c3b5bc8a ths
    COPY(gregs[14]); COPY(gregs[15]);
3043 c3b5bc8a ths
    COPY(gbr); COPY(mach);
3044 c3b5bc8a ths
    COPY(macl); COPY(pr);
3045 c3b5bc8a ths
    COPY(sr); COPY(pc);
3046 c3b5bc8a ths
#undef COPY
3047 c3b5bc8a ths
3048 d8714436 takasi-y@ops.dti.ne.jp
    for (i=0; i<16; i++) {
3049 d8714436 takasi-y@ops.dti.ne.jp
        err |= __get_user(regs->fregs[i], &sc->sc_fpregs[i]);
3050 d8714436 takasi-y@ops.dti.ne.jp
    }
3051 d8714436 takasi-y@ops.dti.ne.jp
    err |= __get_user(regs->fpscr, &sc->sc_fpscr);
3052 d8714436 takasi-y@ops.dti.ne.jp
    err |= __get_user(regs->fpul, &sc->sc_fpul);
3053 c3b5bc8a ths
3054 c3b5bc8a ths
    regs->tra = -1;         /* disable syscall checks */
3055 d8714436 takasi-y@ops.dti.ne.jp
    err |= __get_user(*r0_p, &sc->sc_gregs[0]);
3056 c3b5bc8a ths
    return err;
3057 c3b5bc8a ths
}
3058 c3b5bc8a ths
3059 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
3060 05390248 Andreas Färber
                        target_sigset_t *set, CPUSH4State *regs)
3061 c3b5bc8a ths
{
3062 c3b5bc8a ths
    struct target_sigframe *frame;
3063 c3b5bc8a ths
    abi_ulong frame_addr;
3064 c3b5bc8a ths
    int i;
3065 c3b5bc8a ths
    int err = 0;
3066 c3b5bc8a ths
    int signal;
3067 c3b5bc8a ths
3068 c3b5bc8a ths
    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3069 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3070 c3b5bc8a ths
        goto give_sigsegv;
3071 c3b5bc8a ths
3072 c3b5bc8a ths
    signal = current_exec_domain_sig(sig);
3073 c3b5bc8a ths
3074 c3b5bc8a ths
    err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
3075 c3b5bc8a ths
3076 c3b5bc8a ths
    for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
3077 c3b5bc8a ths
        err |= __put_user(set->sig[i + 1], &frame->extramask[i]);
3078 c3b5bc8a ths
    }
3079 c3b5bc8a ths
3080 c3b5bc8a ths
    /* Set up to return from userspace.  If provided, use a stub
3081 c3b5bc8a ths
       already in userspace.  */
3082 624f7979 pbrook
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3083 624f7979 pbrook
        regs->pr = (unsigned long) ka->sa_restorer;
3084 c3b5bc8a ths
    } else {
3085 c3b5bc8a ths
        /* Generate return code (system call to sigreturn) */
3086 c3b5bc8a ths
        err |= __put_user(MOVW(2), &frame->retcode[0]);
3087 c3b5bc8a ths
        err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
3088 c3b5bc8a ths
        err |= __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
3089 c3b5bc8a ths
        regs->pr = (unsigned long) frame->retcode;
3090 c3b5bc8a ths
    }
3091 c3b5bc8a ths
3092 c3b5bc8a ths
    if (err)
3093 c3b5bc8a ths
        goto give_sigsegv;
3094 c3b5bc8a ths
3095 c3b5bc8a ths
    /* Set up registers for signal handler */
3096 cb9c6268 Edgar E. Iglesias
    regs->gregs[15] = frame_addr;
3097 c3b5bc8a ths
    regs->gregs[4] = signal; /* Arg for signal handler */
3098 c3b5bc8a ths
    regs->gregs[5] = 0;
3099 cb9c6268 Edgar E. Iglesias
    regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
3100 624f7979 pbrook
    regs->pc = (unsigned long) ka->_sa_handler;
3101 c3b5bc8a ths
3102 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
3103 c3b5bc8a ths
    return;
3104 c3b5bc8a ths
3105 c3b5bc8a ths
give_sigsegv:
3106 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
3107 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
3108 c3b5bc8a ths
}
3109 c3b5bc8a ths
3110 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3111 c227f099 Anthony Liguori
                           target_siginfo_t *info,
3112 05390248 Andreas Färber
                           target_sigset_t *set, CPUSH4State *regs)
3113 c3b5bc8a ths
{
3114 c3b5bc8a ths
    struct target_rt_sigframe *frame;
3115 c3b5bc8a ths
    abi_ulong frame_addr;
3116 c3b5bc8a ths
    int i;
3117 c3b5bc8a ths
    int err = 0;
3118 c3b5bc8a ths
    int signal;
3119 c3b5bc8a ths
3120 c3b5bc8a ths
    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
3121 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3122 c3b5bc8a ths
        goto give_sigsegv;
3123 c3b5bc8a ths
3124 c3b5bc8a ths
    signal = current_exec_domain_sig(sig);
3125 c3b5bc8a ths
3126 c3b5bc8a ths
    err |= copy_siginfo_to_user(&frame->info, info);
3127 c3b5bc8a ths
3128 c3b5bc8a ths
    /* Create the ucontext.  */
3129 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_flags);
3130 60e99246 Aurelien Jarno
    err |= __put_user(0, (unsigned long *)&frame->uc.tuc_link);
3131 526ccb7a balrog
    err |= __put_user((unsigned long)target_sigaltstack_used.ss_sp,
3132 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_sp);
3133 c3b5bc8a ths
    err |= __put_user(sas_ss_flags(regs->gregs[15]),
3134 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_flags);
3135 c3b5bc8a ths
    err |= __put_user(target_sigaltstack_used.ss_size,
3136 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_size);
3137 60e99246 Aurelien Jarno
    err |= setup_sigcontext(&frame->uc.tuc_mcontext,
3138 c3b5bc8a ths
                            regs, set->sig[0]);
3139 c3b5bc8a ths
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
3140 60e99246 Aurelien Jarno
        err |= __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
3141 c3b5bc8a ths
    }
3142 c3b5bc8a ths
3143 c3b5bc8a ths
    /* Set up to return from userspace.  If provided, use a stub
3144 c3b5bc8a ths
       already in userspace.  */
3145 624f7979 pbrook
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3146 624f7979 pbrook
        regs->pr = (unsigned long) ka->sa_restorer;
3147 c3b5bc8a ths
    } else {
3148 c3b5bc8a ths
        /* Generate return code (system call to sigreturn) */
3149 c3b5bc8a ths
        err |= __put_user(MOVW(2), &frame->retcode[0]);
3150 c3b5bc8a ths
        err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
3151 c3b5bc8a ths
        err |= __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
3152 c3b5bc8a ths
        regs->pr = (unsigned long) frame->retcode;
3153 c3b5bc8a ths
    }
3154 c3b5bc8a ths
3155 c3b5bc8a ths
    if (err)
3156 c3b5bc8a ths
        goto give_sigsegv;
3157 c3b5bc8a ths
3158 c3b5bc8a ths
    /* Set up registers for signal handler */
3159 cb9c6268 Edgar E. Iglesias
    regs->gregs[15] = frame_addr;
3160 c3b5bc8a ths
    regs->gregs[4] = signal; /* Arg for signal handler */
3161 cb9c6268 Edgar E. Iglesias
    regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
3162 cb9c6268 Edgar E. Iglesias
    regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
3163 624f7979 pbrook
    regs->pc = (unsigned long) ka->_sa_handler;
3164 c3b5bc8a ths
3165 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
3166 c3b5bc8a ths
    return;
3167 c3b5bc8a ths
3168 c3b5bc8a ths
give_sigsegv:
3169 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 1);
3170 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
3171 c3b5bc8a ths
}
3172 c3b5bc8a ths
3173 05390248 Andreas Färber
long do_sigreturn(CPUSH4State *regs)
3174 c3b5bc8a ths
{
3175 c3b5bc8a ths
    struct target_sigframe *frame;
3176 c3b5bc8a ths
    abi_ulong frame_addr;
3177 c3b5bc8a ths
    sigset_t blocked;
3178 c227f099 Anthony Liguori
    target_sigset_t target_set;
3179 d8714436 takasi-y@ops.dti.ne.jp
    target_ulong r0;
3180 c3b5bc8a ths
    int i;
3181 c3b5bc8a ths
    int err = 0;
3182 c3b5bc8a ths
3183 c3b5bc8a ths
#if defined(DEBUG_SIGNAL)
3184 c3b5bc8a ths
    fprintf(stderr, "do_sigreturn\n");
3185 c3b5bc8a ths
#endif
3186 c3b5bc8a ths
    frame_addr = regs->gregs[15];
3187 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3188 c3b5bc8a ths
           goto badframe;
3189 c3b5bc8a ths
3190 c3b5bc8a ths
    err |= __get_user(target_set.sig[0], &frame->sc.oldmask);
3191 c3b5bc8a ths
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3192 c3b5bc8a ths
        err |= (__get_user(target_set.sig[i], &frame->extramask[i - 1]));
3193 c3b5bc8a ths
    }
3194 c3b5bc8a ths
3195 c3b5bc8a ths
    if (err)
3196 c3b5bc8a ths
        goto badframe;
3197 c3b5bc8a ths
3198 c3b5bc8a ths
    target_to_host_sigset_internal(&blocked, &target_set);
3199 c3b5bc8a ths
    sigprocmask(SIG_SETMASK, &blocked, NULL);
3200 c3b5bc8a ths
3201 d8714436 takasi-y@ops.dti.ne.jp
    if (restore_sigcontext(regs, &frame->sc, &r0))
3202 c3b5bc8a ths
        goto badframe;
3203 c3b5bc8a ths
3204 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3205 d8714436 takasi-y@ops.dti.ne.jp
    return r0;
3206 c3b5bc8a ths
3207 c3b5bc8a ths
badframe:
3208 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3209 c3b5bc8a ths
    force_sig(TARGET_SIGSEGV);
3210 c3b5bc8a ths
    return 0;
3211 c3b5bc8a ths
}
3212 c3b5bc8a ths
3213 05390248 Andreas Färber
long do_rt_sigreturn(CPUSH4State *regs)
3214 c3b5bc8a ths
{
3215 c3b5bc8a ths
    struct target_rt_sigframe *frame;
3216 c3b5bc8a ths
    abi_ulong frame_addr;
3217 c3b5bc8a ths
    sigset_t blocked;
3218 d8714436 takasi-y@ops.dti.ne.jp
    target_ulong r0;
3219 c3b5bc8a ths
3220 c3b5bc8a ths
#if defined(DEBUG_SIGNAL)
3221 c3b5bc8a ths
    fprintf(stderr, "do_rt_sigreturn\n");
3222 c3b5bc8a ths
#endif
3223 c3b5bc8a ths
    frame_addr = regs->gregs[15];
3224 c3b5bc8a ths
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
3225 c3b5bc8a ths
           goto badframe;
3226 c3b5bc8a ths
3227 60e99246 Aurelien Jarno
    target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
3228 c3b5bc8a ths
    sigprocmask(SIG_SETMASK, &blocked, NULL);
3229 c3b5bc8a ths
3230 60e99246 Aurelien Jarno
    if (restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0))
3231 c3b5bc8a ths
        goto badframe;
3232 c3b5bc8a ths
3233 c3b5bc8a ths
    if (do_sigaltstack(frame_addr +
3234 60e99246 Aurelien Jarno
                       offsetof(struct target_rt_sigframe, uc.tuc_stack),
3235 c3b5bc8a ths
                       0, get_sp_from_cpustate(regs)) == -EFAULT)
3236 c3b5bc8a ths
        goto badframe;
3237 c3b5bc8a ths
3238 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3239 d8714436 takasi-y@ops.dti.ne.jp
    return r0;
3240 c3b5bc8a ths
3241 c3b5bc8a ths
badframe:
3242 c3b5bc8a ths
    unlock_user_struct(frame, frame_addr, 0);
3243 c3b5bc8a ths
    force_sig(TARGET_SIGSEGV);
3244 c3b5bc8a ths
    return 0;
3245 c3b5bc8a ths
}
3246 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
3247 b779e29e Edgar E. Iglesias
3248 b779e29e Edgar E. Iglesias
struct target_sigcontext {
3249 b779e29e Edgar E. Iglesias
    struct target_pt_regs regs;  /* needs to be first */
3250 b779e29e Edgar E. Iglesias
    uint32_t oldmask;
3251 b779e29e Edgar E. Iglesias
};
3252 b779e29e Edgar E. Iglesias
3253 b2178704 Edgar E. Iglesias
struct target_stack_t {
3254 b2178704 Edgar E. Iglesias
    abi_ulong ss_sp;
3255 b2178704 Edgar E. Iglesias
    int ss_flags;
3256 b2178704 Edgar E. Iglesias
    unsigned int ss_size;
3257 b2178704 Edgar E. Iglesias
};
3258 b2178704 Edgar E. Iglesias
3259 b2178704 Edgar E. Iglesias
struct target_ucontext {
3260 f711df67 Richard Henderson
    abi_ulong tuc_flags;
3261 f711df67 Richard Henderson
    abi_ulong tuc_link;
3262 f711df67 Richard Henderson
    struct target_stack_t tuc_stack;
3263 f711df67 Richard Henderson
    struct target_sigcontext tuc_mcontext;
3264 f711df67 Richard Henderson
    uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1];
3265 b2178704 Edgar E. Iglesias
};
3266 b2178704 Edgar E. Iglesias
3267 b779e29e Edgar E. Iglesias
/* Signal frames. */
3268 b779e29e Edgar E. Iglesias
struct target_signal_frame {
3269 b2178704 Edgar E. Iglesias
    struct target_ucontext uc;
3270 b779e29e Edgar E. Iglesias
    uint32_t extramask[TARGET_NSIG_WORDS - 1];
3271 b779e29e Edgar E. Iglesias
    uint32_t tramp[2];
3272 b779e29e Edgar E. Iglesias
};
3273 b779e29e Edgar E. Iglesias
3274 b779e29e Edgar E. Iglesias
struct rt_signal_frame {
3275 02d2bd5d Richard W.M. Jones
    siginfo_t info;
3276 b779e29e Edgar E. Iglesias
    struct ucontext uc;
3277 b779e29e Edgar E. Iglesias
    uint32_t tramp[2];
3278 b779e29e Edgar E. Iglesias
};
3279 b779e29e Edgar E. Iglesias
3280 05390248 Andreas Färber
static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
3281 b779e29e Edgar E. Iglesias
{
3282 b779e29e Edgar E. Iglesias
    __put_user(env->regs[0], &sc->regs.r0);
3283 b779e29e Edgar E. Iglesias
    __put_user(env->regs[1], &sc->regs.r1);
3284 b779e29e Edgar E. Iglesias
    __put_user(env->regs[2], &sc->regs.r2);
3285 b779e29e Edgar E. Iglesias
    __put_user(env->regs[3], &sc->regs.r3);
3286 b779e29e Edgar E. Iglesias
    __put_user(env->regs[4], &sc->regs.r4);
3287 b779e29e Edgar E. Iglesias
    __put_user(env->regs[5], &sc->regs.r5);
3288 b779e29e Edgar E. Iglesias
    __put_user(env->regs[6], &sc->regs.r6);
3289 b779e29e Edgar E. Iglesias
    __put_user(env->regs[7], &sc->regs.r7);
3290 b779e29e Edgar E. Iglesias
    __put_user(env->regs[8], &sc->regs.r8);
3291 b779e29e Edgar E. Iglesias
    __put_user(env->regs[9], &sc->regs.r9);
3292 b779e29e Edgar E. Iglesias
    __put_user(env->regs[10], &sc->regs.r10);
3293 b779e29e Edgar E. Iglesias
    __put_user(env->regs[11], &sc->regs.r11);
3294 b779e29e Edgar E. Iglesias
    __put_user(env->regs[12], &sc->regs.r12);
3295 b779e29e Edgar E. Iglesias
    __put_user(env->regs[13], &sc->regs.r13);
3296 b779e29e Edgar E. Iglesias
    __put_user(env->regs[14], &sc->regs.r14);
3297 b779e29e Edgar E. Iglesias
    __put_user(env->regs[15], &sc->regs.r15);
3298 b779e29e Edgar E. Iglesias
    __put_user(env->regs[16], &sc->regs.r16);
3299 b779e29e Edgar E. Iglesias
    __put_user(env->regs[17], &sc->regs.r17);
3300 b779e29e Edgar E. Iglesias
    __put_user(env->regs[18], &sc->regs.r18);
3301 b779e29e Edgar E. Iglesias
    __put_user(env->regs[19], &sc->regs.r19);
3302 b779e29e Edgar E. Iglesias
    __put_user(env->regs[20], &sc->regs.r20);
3303 b779e29e Edgar E. Iglesias
    __put_user(env->regs[21], &sc->regs.r21);
3304 b779e29e Edgar E. Iglesias
    __put_user(env->regs[22], &sc->regs.r22);
3305 b779e29e Edgar E. Iglesias
    __put_user(env->regs[23], &sc->regs.r23);
3306 b779e29e Edgar E. Iglesias
    __put_user(env->regs[24], &sc->regs.r24);
3307 b779e29e Edgar E. Iglesias
    __put_user(env->regs[25], &sc->regs.r25);
3308 b779e29e Edgar E. Iglesias
    __put_user(env->regs[26], &sc->regs.r26);
3309 b779e29e Edgar E. Iglesias
    __put_user(env->regs[27], &sc->regs.r27);
3310 b779e29e Edgar E. Iglesias
    __put_user(env->regs[28], &sc->regs.r28);
3311 b779e29e Edgar E. Iglesias
    __put_user(env->regs[29], &sc->regs.r29);
3312 b779e29e Edgar E. Iglesias
    __put_user(env->regs[30], &sc->regs.r30);
3313 b779e29e Edgar E. Iglesias
    __put_user(env->regs[31], &sc->regs.r31);
3314 b779e29e Edgar E. Iglesias
    __put_user(env->sregs[SR_PC], &sc->regs.pc);
3315 b779e29e Edgar E. Iglesias
}
3316 b779e29e Edgar E. Iglesias
3317 05390248 Andreas Färber
static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
3318 b779e29e Edgar E. Iglesias
{
3319 b779e29e Edgar E. Iglesias
    __get_user(env->regs[0], &sc->regs.r0);
3320 b779e29e Edgar E. Iglesias
    __get_user(env->regs[1], &sc->regs.r1);
3321 b779e29e Edgar E. Iglesias
    __get_user(env->regs[2], &sc->regs.r2);
3322 b779e29e Edgar E. Iglesias
    __get_user(env->regs[3], &sc->regs.r3);
3323 b779e29e Edgar E. Iglesias
    __get_user(env->regs[4], &sc->regs.r4);
3324 b779e29e Edgar E. Iglesias
    __get_user(env->regs[5], &sc->regs.r5);
3325 b779e29e Edgar E. Iglesias
    __get_user(env->regs[6], &sc->regs.r6);
3326 b779e29e Edgar E. Iglesias
    __get_user(env->regs[7], &sc->regs.r7);
3327 b779e29e Edgar E. Iglesias
    __get_user(env->regs[8], &sc->regs.r8);
3328 b779e29e Edgar E. Iglesias
    __get_user(env->regs[9], &sc->regs.r9);
3329 b779e29e Edgar E. Iglesias
    __get_user(env->regs[10], &sc->regs.r10);
3330 b779e29e Edgar E. Iglesias
    __get_user(env->regs[11], &sc->regs.r11);
3331 b779e29e Edgar E. Iglesias
    __get_user(env->regs[12], &sc->regs.r12);
3332 b779e29e Edgar E. Iglesias
    __get_user(env->regs[13], &sc->regs.r13);
3333 b779e29e Edgar E. Iglesias
    __get_user(env->regs[14], &sc->regs.r14);
3334 b779e29e Edgar E. Iglesias
    __get_user(env->regs[15], &sc->regs.r15);
3335 b779e29e Edgar E. Iglesias
    __get_user(env->regs[16], &sc->regs.r16);
3336 b779e29e Edgar E. Iglesias
    __get_user(env->regs[17], &sc->regs.r17);
3337 b779e29e Edgar E. Iglesias
    __get_user(env->regs[18], &sc->regs.r18);
3338 b779e29e Edgar E. Iglesias
    __get_user(env->regs[19], &sc->regs.r19);
3339 b779e29e Edgar E. Iglesias
    __get_user(env->regs[20], &sc->regs.r20);
3340 b779e29e Edgar E. Iglesias
    __get_user(env->regs[21], &sc->regs.r21);
3341 b779e29e Edgar E. Iglesias
    __get_user(env->regs[22], &sc->regs.r22);
3342 b779e29e Edgar E. Iglesias
    __get_user(env->regs[23], &sc->regs.r23);
3343 b779e29e Edgar E. Iglesias
    __get_user(env->regs[24], &sc->regs.r24);
3344 b779e29e Edgar E. Iglesias
    __get_user(env->regs[25], &sc->regs.r25);
3345 b779e29e Edgar E. Iglesias
    __get_user(env->regs[26], &sc->regs.r26);
3346 b779e29e Edgar E. Iglesias
    __get_user(env->regs[27], &sc->regs.r27);
3347 b779e29e Edgar E. Iglesias
    __get_user(env->regs[28], &sc->regs.r28);
3348 b779e29e Edgar E. Iglesias
    __get_user(env->regs[29], &sc->regs.r29);
3349 b779e29e Edgar E. Iglesias
    __get_user(env->regs[30], &sc->regs.r30);
3350 b779e29e Edgar E. Iglesias
    __get_user(env->regs[31], &sc->regs.r31);
3351 b779e29e Edgar E. Iglesias
    __get_user(env->sregs[SR_PC], &sc->regs.pc);
3352 b779e29e Edgar E. Iglesias
}
3353 b779e29e Edgar E. Iglesias
3354 b779e29e Edgar E. Iglesias
static abi_ulong get_sigframe(struct target_sigaction *ka,
3355 05390248 Andreas Färber
                              CPUMBState *env, int frame_size)
3356 b779e29e Edgar E. Iglesias
{
3357 b779e29e Edgar E. Iglesias
    abi_ulong sp = env->regs[1];
3358 b779e29e Edgar E. Iglesias
3359 b779e29e Edgar E. Iglesias
    if ((ka->sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
3360 b779e29e Edgar E. Iglesias
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3361 b779e29e Edgar E. Iglesias
3362 b779e29e Edgar E. Iglesias
    return ((sp - frame_size) & -8UL);
3363 b779e29e Edgar E. Iglesias
}
3364 b779e29e Edgar E. Iglesias
3365 b779e29e Edgar E. Iglesias
static void setup_frame(int sig, struct target_sigaction *ka,
3366 05390248 Andreas Färber
                        target_sigset_t *set, CPUMBState *env)
3367 b779e29e Edgar E. Iglesias
{
3368 b779e29e Edgar E. Iglesias
    struct target_signal_frame *frame;
3369 b779e29e Edgar E. Iglesias
    abi_ulong frame_addr;
3370 b779e29e Edgar E. Iglesias
    int err = 0;
3371 b779e29e Edgar E. Iglesias
    int i;
3372 b779e29e Edgar E. Iglesias
3373 b779e29e Edgar E. Iglesias
    frame_addr = get_sigframe(ka, env, sizeof *frame);
3374 b779e29e Edgar E. Iglesias
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3375 b779e29e Edgar E. Iglesias
        goto badframe;
3376 b779e29e Edgar E. Iglesias
3377 b779e29e Edgar E. Iglesias
    /* Save the mask.  */
3378 f711df67 Richard Henderson
    err |= __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask);
3379 b779e29e Edgar E. Iglesias
    if (err)
3380 b779e29e Edgar E. Iglesias
        goto badframe;
3381 b779e29e Edgar E. Iglesias
3382 b779e29e Edgar E. Iglesias
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3383 b779e29e Edgar E. Iglesias
        if (__put_user(set->sig[i], &frame->extramask[i - 1]))
3384 b779e29e Edgar E. Iglesias
            goto badframe;
3385 b779e29e Edgar E. Iglesias
    }
3386 b779e29e Edgar E. Iglesias
3387 f711df67 Richard Henderson
    setup_sigcontext(&frame->uc.tuc_mcontext, env);
3388 b779e29e Edgar E. Iglesias
3389 b779e29e Edgar E. Iglesias
    /* Set up to return from userspace. If provided, use a stub
3390 b779e29e Edgar E. Iglesias
       already in userspace. */
3391 b779e29e Edgar E. Iglesias
    /* minus 8 is offset to cater for "rtsd r15,8" offset */
3392 b779e29e Edgar E. Iglesias
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3393 b779e29e Edgar E. Iglesias
        env->regs[15] = ((unsigned long)ka->sa_restorer)-8;
3394 b779e29e Edgar E. Iglesias
    } else {
3395 b779e29e Edgar E. Iglesias
        uint32_t t;
3396 b779e29e Edgar E. Iglesias
        /* Note, these encodings are _big endian_! */
3397 b779e29e Edgar E. Iglesias
        /* addi r12, r0, __NR_sigreturn */
3398 b779e29e Edgar E. Iglesias
        t = 0x31800000UL | TARGET_NR_sigreturn;
3399 b779e29e Edgar E. Iglesias
        err |= __put_user(t, frame->tramp + 0);
3400 b779e29e Edgar E. Iglesias
        /* brki r14, 0x8 */
3401 b779e29e Edgar E. Iglesias
        t = 0xb9cc0008UL;
3402 b779e29e Edgar E. Iglesias
        err |= __put_user(t, frame->tramp + 1);
3403 b779e29e Edgar E. Iglesias
3404 b779e29e Edgar E. Iglesias
        /* Return from sighandler will jump to the tramp.
3405 b779e29e Edgar E. Iglesias
           Negative 8 offset because return is rtsd r15, 8 */
3406 b779e29e Edgar E. Iglesias
        env->regs[15] = ((unsigned long)frame->tramp) - 8;
3407 b779e29e Edgar E. Iglesias
    }
3408 b779e29e Edgar E. Iglesias
3409 b779e29e Edgar E. Iglesias
    if (err)
3410 b779e29e Edgar E. Iglesias
        goto badframe;
3411 b779e29e Edgar E. Iglesias
3412 b779e29e Edgar E. Iglesias
    /* Set up registers for signal handler */
3413 cb9c6268 Edgar E. Iglesias
    env->regs[1] = frame_addr;
3414 b779e29e Edgar E. Iglesias
    /* Signal handler args: */
3415 b779e29e Edgar E. Iglesias
    env->regs[5] = sig; /* Arg 0: signum */
3416 187b4e08 Edgar E. Iglesias
    env->regs[6] = 0;
3417 cb9c6268 Edgar E. Iglesias
    /* arg 1: sigcontext */
3418 cb9c6268 Edgar E. Iglesias
    env->regs[7] = frame_addr += offsetof(typeof(*frame), uc);
3419 b779e29e Edgar E. Iglesias
3420 b779e29e Edgar E. Iglesias
    /* Offset of 4 to handle microblaze rtid r14, 0 */
3421 b779e29e Edgar E. Iglesias
    env->sregs[SR_PC] = (unsigned long)ka->_sa_handler;
3422 b779e29e Edgar E. Iglesias
3423 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 1);
3424 b779e29e Edgar E. Iglesias
    return;
3425 b779e29e Edgar E. Iglesias
  badframe:
3426 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 1);
3427 b779e29e Edgar E. Iglesias
    force_sig(TARGET_SIGSEGV);
3428 b779e29e Edgar E. Iglesias
}
3429 b779e29e Edgar E. Iglesias
3430 b779e29e Edgar E. Iglesias
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3431 c227f099 Anthony Liguori
                           target_siginfo_t *info,
3432 05390248 Andreas Färber
                           target_sigset_t *set, CPUMBState *env)
3433 b779e29e Edgar E. Iglesias
{
3434 b779e29e Edgar E. Iglesias
    fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n");
3435 b779e29e Edgar E. Iglesias
}
3436 b779e29e Edgar E. Iglesias
3437 05390248 Andreas Färber
long do_sigreturn(CPUMBState *env)
3438 b779e29e Edgar E. Iglesias
{
3439 b779e29e Edgar E. Iglesias
    struct target_signal_frame *frame;
3440 b779e29e Edgar E. Iglesias
    abi_ulong frame_addr;
3441 c227f099 Anthony Liguori
    target_sigset_t target_set;
3442 b779e29e Edgar E. Iglesias
    sigset_t set;
3443 b779e29e Edgar E. Iglesias
    int i;
3444 b779e29e Edgar E. Iglesias
3445 b779e29e Edgar E. Iglesias
    frame_addr = env->regs[R_SP];
3446 b779e29e Edgar E. Iglesias
    /* Make sure the guest isn't playing games.  */
3447 b779e29e Edgar E. Iglesias
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3448 b779e29e Edgar E. Iglesias
        goto badframe;
3449 b779e29e Edgar E. Iglesias
3450 b779e29e Edgar E. Iglesias
    /* Restore blocked signals */
3451 f711df67 Richard Henderson
    if (__get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask))
3452 b779e29e Edgar E. Iglesias
        goto badframe;
3453 b779e29e Edgar E. Iglesias
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3454 b779e29e Edgar E. Iglesias
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
3455 b779e29e Edgar E. Iglesias
            goto badframe;
3456 b779e29e Edgar E. Iglesias
    }
3457 b779e29e Edgar E. Iglesias
    target_to_host_sigset_internal(&set, &target_set);
3458 b779e29e Edgar E. Iglesias
    sigprocmask(SIG_SETMASK, &set, NULL);
3459 b779e29e Edgar E. Iglesias
3460 f711df67 Richard Henderson
    restore_sigcontext(&frame->uc.tuc_mcontext, env);
3461 b779e29e Edgar E. Iglesias
    /* We got here through a sigreturn syscall, our path back is via an
3462 b779e29e Edgar E. Iglesias
       rtb insn so setup r14 for that.  */
3463 b779e29e Edgar E. Iglesias
    env->regs[14] = env->sregs[SR_PC];
3464 b779e29e Edgar E. Iglesias
 
3465 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 0);
3466 b779e29e Edgar E. Iglesias
    return env->regs[10];
3467 b779e29e Edgar E. Iglesias
  badframe:
3468 b779e29e Edgar E. Iglesias
    unlock_user_struct(frame, frame_addr, 0);
3469 b779e29e Edgar E. Iglesias
    force_sig(TARGET_SIGSEGV);
3470 b779e29e Edgar E. Iglesias
}
3471 b779e29e Edgar E. Iglesias
3472 05390248 Andreas Färber
long do_rt_sigreturn(CPUMBState *env)
3473 b779e29e Edgar E. Iglesias
{
3474 b779e29e Edgar E. Iglesias
    fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n");
3475 b779e29e Edgar E. Iglesias
    return -TARGET_ENOSYS;
3476 b779e29e Edgar E. Iglesias
}
3477 b779e29e Edgar E. Iglesias
3478 b6d3abda edgar_igl
#elif defined(TARGET_CRIS)
3479 b6d3abda edgar_igl
3480 b6d3abda edgar_igl
struct target_sigcontext {
3481 b6d3abda edgar_igl
        struct target_pt_regs regs;  /* needs to be first */
3482 b6d3abda edgar_igl
        uint32_t oldmask;
3483 b6d3abda edgar_igl
        uint32_t usp;    /* usp before stacking this gunk on it */
3484 b6d3abda edgar_igl
};
3485 b6d3abda edgar_igl
3486 b6d3abda edgar_igl
/* Signal frames. */
3487 b6d3abda edgar_igl
struct target_signal_frame {
3488 b6d3abda edgar_igl
        struct target_sigcontext sc;
3489 b6d3abda edgar_igl
        uint32_t extramask[TARGET_NSIG_WORDS - 1];
3490 b6d3abda edgar_igl
        uint8_t retcode[8];       /* Trampoline code. */
3491 b6d3abda edgar_igl
};
3492 b6d3abda edgar_igl
3493 b6d3abda edgar_igl
struct rt_signal_frame {
3494 02d2bd5d Richard W.M. Jones
        siginfo_t *pinfo;
3495 b6d3abda edgar_igl
        void *puc;
3496 02d2bd5d Richard W.M. Jones
        siginfo_t info;
3497 b6d3abda edgar_igl
        struct ucontext uc;
3498 b6d3abda edgar_igl
        uint8_t retcode[8];       /* Trampoline code. */
3499 b6d3abda edgar_igl
};
3500 b6d3abda edgar_igl
3501 05390248 Andreas Färber
static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
3502 b6d3abda edgar_igl
{
3503 9664d928 edgar_igl
        __put_user(env->regs[0], &sc->regs.r0);
3504 9664d928 edgar_igl
        __put_user(env->regs[1], &sc->regs.r1);
3505 9664d928 edgar_igl
        __put_user(env->regs[2], &sc->regs.r2);
3506 9664d928 edgar_igl
        __put_user(env->regs[3], &sc->regs.r3);
3507 9664d928 edgar_igl
        __put_user(env->regs[4], &sc->regs.r4);
3508 9664d928 edgar_igl
        __put_user(env->regs[5], &sc->regs.r5);
3509 9664d928 edgar_igl
        __put_user(env->regs[6], &sc->regs.r6);
3510 9664d928 edgar_igl
        __put_user(env->regs[7], &sc->regs.r7);
3511 9664d928 edgar_igl
        __put_user(env->regs[8], &sc->regs.r8);
3512 9664d928 edgar_igl
        __put_user(env->regs[9], &sc->regs.r9);
3513 9664d928 edgar_igl
        __put_user(env->regs[10], &sc->regs.r10);
3514 9664d928 edgar_igl
        __put_user(env->regs[11], &sc->regs.r11);
3515 9664d928 edgar_igl
        __put_user(env->regs[12], &sc->regs.r12);
3516 9664d928 edgar_igl
        __put_user(env->regs[13], &sc->regs.r13);
3517 9664d928 edgar_igl
        __put_user(env->regs[14], &sc->usp);
3518 9664d928 edgar_igl
        __put_user(env->regs[15], &sc->regs.acr);
3519 9664d928 edgar_igl
        __put_user(env->pregs[PR_MOF], &sc->regs.mof);
3520 9664d928 edgar_igl
        __put_user(env->pregs[PR_SRP], &sc->regs.srp);
3521 9664d928 edgar_igl
        __put_user(env->pc, &sc->regs.erp);
3522 b6d3abda edgar_igl
}
3523 9664d928 edgar_igl
3524 05390248 Andreas Färber
static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
3525 b6d3abda edgar_igl
{
3526 9664d928 edgar_igl
        __get_user(env->regs[0], &sc->regs.r0);
3527 9664d928 edgar_igl
        __get_user(env->regs[1], &sc->regs.r1);
3528 9664d928 edgar_igl
        __get_user(env->regs[2], &sc->regs.r2);
3529 9664d928 edgar_igl
        __get_user(env->regs[3], &sc->regs.r3);
3530 9664d928 edgar_igl
        __get_user(env->regs[4], &sc->regs.r4);
3531 9664d928 edgar_igl
        __get_user(env->regs[5], &sc->regs.r5);
3532 9664d928 edgar_igl
        __get_user(env->regs[6], &sc->regs.r6);
3533 9664d928 edgar_igl
        __get_user(env->regs[7], &sc->regs.r7);
3534 9664d928 edgar_igl
        __get_user(env->regs[8], &sc->regs.r8);
3535 9664d928 edgar_igl
        __get_user(env->regs[9], &sc->regs.r9);
3536 9664d928 edgar_igl
        __get_user(env->regs[10], &sc->regs.r10);
3537 9664d928 edgar_igl
        __get_user(env->regs[11], &sc->regs.r11);
3538 9664d928 edgar_igl
        __get_user(env->regs[12], &sc->regs.r12);
3539 9664d928 edgar_igl
        __get_user(env->regs[13], &sc->regs.r13);
3540 9664d928 edgar_igl
        __get_user(env->regs[14], &sc->usp);
3541 9664d928 edgar_igl
        __get_user(env->regs[15], &sc->regs.acr);
3542 9664d928 edgar_igl
        __get_user(env->pregs[PR_MOF], &sc->regs.mof);
3543 9664d928 edgar_igl
        __get_user(env->pregs[PR_SRP], &sc->regs.srp);
3544 9664d928 edgar_igl
        __get_user(env->pc, &sc->regs.erp);
3545 9664d928 edgar_igl
}
3546 9664d928 edgar_igl
3547 05390248 Andreas Färber
static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
3548 9664d928 edgar_igl
{
3549 9664d928 edgar_igl
        abi_ulong sp;
3550 b6d3abda edgar_igl
        /* Align the stack downwards to 4.  */
3551 9664d928 edgar_igl
        sp = (env->regs[R_SP] & ~3);
3552 9664d928 edgar_igl
        return sp - framesize;
3553 b6d3abda edgar_igl
}
3554 b6d3abda edgar_igl
3555 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
3556 05390248 Andreas Färber
                        target_sigset_t *set, CPUCRISState *env)
3557 b6d3abda edgar_igl
{
3558 b6d3abda edgar_igl
        struct target_signal_frame *frame;
3559 9664d928 edgar_igl
        abi_ulong frame_addr;
3560 b6d3abda edgar_igl
        int err = 0;
3561 b6d3abda edgar_igl
        int i;
3562 b6d3abda edgar_igl
3563 9664d928 edgar_igl
        frame_addr = get_sigframe(env, sizeof *frame);
3564 9664d928 edgar_igl
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
3565 b6d3abda edgar_igl
                goto badframe;
3566 b6d3abda edgar_igl
3567 b6d3abda edgar_igl
        /*
3568 b6d3abda edgar_igl
         * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
3569 b6d3abda edgar_igl
         * use this trampoline anymore but it sets it up for GDB.
3570 b6d3abda edgar_igl
         * In QEMU, using the trampoline simplifies things a bit so we use it.
3571 b6d3abda edgar_igl
         *
3572 b6d3abda edgar_igl
         * This is movu.w __NR_sigreturn, r9; break 13;
3573 b6d3abda edgar_igl
         */
3574 b6d3abda edgar_igl
        err |= __put_user(0x9c5f, frame->retcode+0);
3575 b6d3abda edgar_igl
        err |= __put_user(TARGET_NR_sigreturn, 
3576 b6d3abda edgar_igl
                          frame->retcode+2);
3577 b6d3abda edgar_igl
        err |= __put_user(0xe93d, frame->retcode+4);
3578 b6d3abda edgar_igl
3579 b6d3abda edgar_igl
        /* Save the mask.  */
3580 b6d3abda edgar_igl
        err |= __put_user(set->sig[0], &frame->sc.oldmask);
3581 b6d3abda edgar_igl
        if (err)
3582 b6d3abda edgar_igl
                goto badframe;
3583 b6d3abda edgar_igl
3584 b6d3abda edgar_igl
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3585 b6d3abda edgar_igl
                if (__put_user(set->sig[i], &frame->extramask[i - 1]))
3586 b6d3abda edgar_igl
                        goto badframe;
3587 b6d3abda edgar_igl
        }
3588 b6d3abda edgar_igl
3589 b6d3abda edgar_igl
        setup_sigcontext(&frame->sc, env);
3590 b6d3abda edgar_igl
3591 b6d3abda edgar_igl
        /* Move the stack and setup the arguments for the handler.  */
3592 cb9c6268 Edgar E. Iglesias
        env->regs[R_SP] = frame_addr;
3593 b6d3abda edgar_igl
        env->regs[10] = sig;
3594 624f7979 pbrook
        env->pc = (unsigned long) ka->_sa_handler;
3595 b6d3abda edgar_igl
        /* Link SRP so the guest returns through the trampoline.  */
3596 cb9c6268 Edgar E. Iglesias
        env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
3597 b6d3abda edgar_igl
3598 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 1);
3599 b6d3abda edgar_igl
        return;
3600 b6d3abda edgar_igl
  badframe:
3601 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 1);
3602 b6d3abda edgar_igl
        force_sig(TARGET_SIGSEGV);
3603 b6d3abda edgar_igl
}
3604 b6d3abda edgar_igl
3605 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3606 c227f099 Anthony Liguori
                           target_siginfo_t *info,
3607 05390248 Andreas Färber
                           target_sigset_t *set, CPUCRISState *env)
3608 b6d3abda edgar_igl
{
3609 b6d3abda edgar_igl
    fprintf(stderr, "CRIS setup_rt_frame: not implemented\n");
3610 b6d3abda edgar_igl
}
3611 b6d3abda edgar_igl
3612 05390248 Andreas Färber
long do_sigreturn(CPUCRISState *env)
3613 b6d3abda edgar_igl
{
3614 b6d3abda edgar_igl
        struct target_signal_frame *frame;
3615 9664d928 edgar_igl
        abi_ulong frame_addr;
3616 c227f099 Anthony Liguori
        target_sigset_t target_set;
3617 b6d3abda edgar_igl
        sigset_t set;
3618 b6d3abda edgar_igl
        int i;
3619 b6d3abda edgar_igl
3620 9664d928 edgar_igl
        frame_addr = env->regs[R_SP];
3621 b6d3abda edgar_igl
        /* Make sure the guest isn't playing games.  */
3622 9664d928 edgar_igl
        if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
3623 b6d3abda edgar_igl
                goto badframe;
3624 b6d3abda edgar_igl
3625 b6d3abda edgar_igl
        /* Restore blocked signals */
3626 b6d3abda edgar_igl
        if (__get_user(target_set.sig[0], &frame->sc.oldmask))
3627 b6d3abda edgar_igl
                goto badframe;
3628 b6d3abda edgar_igl
        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
3629 b6d3abda edgar_igl
                if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
3630 b6d3abda edgar_igl
                        goto badframe;
3631 b6d3abda edgar_igl
        }
3632 b6d3abda edgar_igl
        target_to_host_sigset_internal(&set, &target_set);
3633 b6d3abda edgar_igl
        sigprocmask(SIG_SETMASK, &set, NULL);
3634 b6d3abda edgar_igl
3635 b6d3abda edgar_igl
        restore_sigcontext(&frame->sc, env);
3636 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 0);
3637 b6d3abda edgar_igl
        return env->regs[10];
3638 b6d3abda edgar_igl
  badframe:
3639 9664d928 edgar_igl
        unlock_user_struct(frame, frame_addr, 0);
3640 b6d3abda edgar_igl
        force_sig(TARGET_SIGSEGV);
3641 b6d3abda edgar_igl
}
3642 b6d3abda edgar_igl
3643 05390248 Andreas Färber
long do_rt_sigreturn(CPUCRISState *env)
3644 b6d3abda edgar_igl
{
3645 b6d3abda edgar_igl
    fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n");
3646 b6d3abda edgar_igl
    return -TARGET_ENOSYS;
3647 b6d3abda edgar_igl
}
3648 c3b5bc8a ths
3649 d962783e Jia Liu
#elif defined(TARGET_OPENRISC)
3650 d962783e Jia Liu
3651 d962783e Jia Liu
struct target_sigcontext {
3652 d962783e Jia Liu
    struct target_pt_regs regs;
3653 d962783e Jia Liu
    abi_ulong oldmask;
3654 d962783e Jia Liu
    abi_ulong usp;
3655 d962783e Jia Liu
};
3656 d962783e Jia Liu
3657 d962783e Jia Liu
struct target_ucontext {
3658 d962783e Jia Liu
    abi_ulong tuc_flags;
3659 d962783e Jia Liu
    abi_ulong tuc_link;
3660 d962783e Jia Liu
    target_stack_t tuc_stack;
3661 d962783e Jia Liu
    struct target_sigcontext tuc_mcontext;
3662 d962783e Jia Liu
    target_sigset_t tuc_sigmask;   /* mask last for extensibility */
3663 d962783e Jia Liu
};
3664 d962783e Jia Liu
3665 d962783e Jia Liu
struct target_rt_sigframe {
3666 d962783e Jia Liu
    abi_ulong pinfo;
3667 d962783e Jia Liu
    uint64_t puc;
3668 d962783e Jia Liu
    struct target_siginfo info;
3669 d962783e Jia Liu
    struct target_sigcontext sc;
3670 d962783e Jia Liu
    struct target_ucontext uc;
3671 d962783e Jia Liu
    unsigned char retcode[16];  /* trampoline code */
3672 d962783e Jia Liu
};
3673 d962783e Jia Liu
3674 d962783e Jia Liu
/* This is the asm-generic/ucontext.h version */
3675 d962783e Jia Liu
#if 0
3676 d962783e Jia Liu
static int restore_sigcontext(CPUOpenRISCState *regs,
3677 d962783e Jia Liu
                              struct target_sigcontext *sc)
3678 d962783e Jia Liu
{
3679 d962783e Jia Liu
    unsigned int err = 0;
3680 d962783e Jia Liu
    unsigned long old_usp;
3681 d962783e Jia Liu

3682 d962783e Jia Liu
    /* Alwys make any pending restarted system call return -EINTR */
3683 d962783e Jia Liu
    current_thread_info()->restart_block.fn = do_no_restart_syscall;
3684 d962783e Jia Liu

3685 d962783e Jia Liu
    /* restore the regs from &sc->regs (same as sc, since regs is first)
3686 d962783e Jia Liu
     * (sc is already checked for VERIFY_READ since the sigframe was
3687 d962783e Jia Liu
     *  checked in sys_sigreturn previously)
3688 d962783e Jia Liu
     */
3689 d962783e Jia Liu

3690 d962783e Jia Liu
    if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) {
3691 d962783e Jia Liu
        goto badframe;
3692 d962783e Jia Liu
    }
3693 d962783e Jia Liu

3694 d962783e Jia Liu
    /* make sure the U-flag is set so user-mode cannot fool us */
3695 d962783e Jia Liu

3696 d962783e Jia Liu
    regs->sr &= ~SR_SM;
3697 d962783e Jia Liu

3698 d962783e Jia Liu
    /* restore the old USP as it was before we stacked the sc etc.
3699 d962783e Jia Liu
     * (we cannot just pop the sigcontext since we aligned the sp and
3700 d962783e Jia Liu
     *  stuff after pushing it)
3701 d962783e Jia Liu
     */
3702 d962783e Jia Liu

3703 d962783e Jia Liu
    err |= __get_user(old_usp, &sc->usp);
3704 d962783e Jia Liu
    phx_signal("old_usp 0x%lx", old_usp);
3705 d962783e Jia Liu

3706 d962783e Jia Liu
    __PHX__ REALLY           /* ??? */
3707 d962783e Jia Liu
    wrusp(old_usp);
3708 d962783e Jia Liu
    regs->gpr[1] = old_usp;
3709 d962783e Jia Liu

3710 d962783e Jia Liu
    /* TODO: the other ports use regs->orig_XX to disable syscall checks
3711 d962783e Jia Liu
     * after this completes, but we don't use that mechanism. maybe we can
3712 d962783e Jia Liu
     * use it now ?
3713 d962783e Jia Liu
     */
3714 d962783e Jia Liu

3715 d962783e Jia Liu
    return err;
3716 d962783e Jia Liu

3717 d962783e Jia Liu
badframe:
3718 d962783e Jia Liu
    return 1;
3719 d962783e Jia Liu
}
3720 d962783e Jia Liu
#endif
3721 d962783e Jia Liu
3722 d962783e Jia Liu
/* Set up a signal frame.  */
3723 d962783e Jia Liu
3724 d962783e Jia Liu
static int setup_sigcontext(struct target_sigcontext *sc,
3725 d962783e Jia Liu
                            CPUOpenRISCState *regs,
3726 d962783e Jia Liu
                            unsigned long mask)
3727 d962783e Jia Liu
{
3728 d962783e Jia Liu
    int err = 0;
3729 d962783e Jia Liu
    unsigned long usp = regs->gpr[1];
3730 d962783e Jia Liu
3731 d962783e Jia Liu
    /* copy the regs. they are first in sc so we can use sc directly */
3732 d962783e Jia Liu
3733 d962783e Jia Liu
    /*err |= copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/
3734 d962783e Jia Liu
3735 d962783e Jia Liu
    /* Set the frametype to CRIS_FRAME_NORMAL for the execution of
3736 d962783e Jia Liu
       the signal handler. The frametype will be restored to its previous
3737 d962783e Jia Liu
       value in restore_sigcontext. */
3738 d962783e Jia Liu
    /*regs->frametype = CRIS_FRAME_NORMAL;*/
3739 d962783e Jia Liu
3740 d962783e Jia Liu
    /* then some other stuff */
3741 d962783e Jia Liu
    err |= __put_user(mask, &sc->oldmask);
3742 d962783e Jia Liu
    err |= __put_user(usp, &sc->usp); return err;
3743 d962783e Jia Liu
}
3744 d962783e Jia Liu
3745 d962783e Jia Liu
static inline unsigned long align_sigframe(unsigned long sp)
3746 d962783e Jia Liu
{
3747 d962783e Jia Liu
    unsigned long i;
3748 d962783e Jia Liu
    i = sp & ~3UL;
3749 d962783e Jia Liu
    return i;
3750 d962783e Jia Liu
}
3751 d962783e Jia Liu
3752 d962783e Jia Liu
static inline abi_ulong get_sigframe(struct target_sigaction *ka,
3753 d962783e Jia Liu
                                     CPUOpenRISCState *regs,
3754 d962783e Jia Liu
                                     size_t frame_size)
3755 d962783e Jia Liu
{
3756 d962783e Jia Liu
    unsigned long sp = regs->gpr[1];
3757 d962783e Jia Liu
    int onsigstack = on_sig_stack(sp);
3758 d962783e Jia Liu
3759 d962783e Jia Liu
    /* redzone */
3760 d962783e Jia Liu
    /* This is the X/Open sanctioned signal stack switching.  */
3761 d962783e Jia Liu
    if ((ka->sa_flags & SA_ONSTACK) != 0 && !onsigstack) {
3762 d962783e Jia Liu
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
3763 d962783e Jia Liu
    }
3764 d962783e Jia Liu
3765 d962783e Jia Liu
    sp = align_sigframe(sp - frame_size);
3766 d962783e Jia Liu
3767 d962783e Jia Liu
    /*
3768 d962783e Jia Liu
     * If we are on the alternate signal stack and would overflow it, don't.
3769 d962783e Jia Liu
     * Return an always-bogus address instead so we will die with SIGSEGV.
3770 d962783e Jia Liu
     */
3771 d962783e Jia Liu
3772 d962783e Jia Liu
    if (onsigstack && !likely(on_sig_stack(sp))) {
3773 d962783e Jia Liu
        return -1L;
3774 d962783e Jia Liu
    }
3775 d962783e Jia Liu
3776 d962783e Jia Liu
    return sp;
3777 d962783e Jia Liu
}
3778 d962783e Jia Liu
3779 d962783e Jia Liu
static void setup_frame(int sig, struct target_sigaction *ka,
3780 d962783e Jia Liu
                        target_sigset_t *set, CPUOpenRISCState *env)
3781 d962783e Jia Liu
{
3782 d962783e Jia Liu
    qemu_log("Not implement.\n");
3783 d962783e Jia Liu
}
3784 d962783e Jia Liu
3785 d962783e Jia Liu
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3786 d962783e Jia Liu
                           target_siginfo_t *info,
3787 d962783e Jia Liu
                           target_sigset_t *set, CPUOpenRISCState *env)
3788 d962783e Jia Liu
{
3789 d962783e Jia Liu
    int err = 0;
3790 d962783e Jia Liu
    abi_ulong frame_addr;
3791 d962783e Jia Liu
    unsigned long return_ip;
3792 d962783e Jia Liu
    struct target_rt_sigframe *frame;
3793 d962783e Jia Liu
    abi_ulong info_addr, uc_addr;
3794 d962783e Jia Liu
3795 d962783e Jia Liu
    frame_addr = get_sigframe(ka, env, sizeof *frame);
3796 d962783e Jia Liu
3797 d962783e Jia Liu
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
3798 d962783e Jia Liu
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3799 d962783e Jia Liu
        goto give_sigsegv;
3800 d962783e Jia Liu
    }
3801 d962783e Jia Liu
3802 d962783e Jia Liu
    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
3803 d962783e Jia Liu
    err |= __put_user(info_addr, &frame->pinfo);
3804 d962783e Jia Liu
    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
3805 d962783e Jia Liu
    err |= __put_user(uc_addr, &frame->puc);
3806 d962783e Jia Liu
3807 d962783e Jia Liu
    if (ka->sa_flags & SA_SIGINFO) {
3808 d962783e Jia Liu
        err |= copy_siginfo_to_user(&frame->info, info);
3809 d962783e Jia Liu
    }
3810 d962783e Jia Liu
    if (err) {
3811 d962783e Jia Liu
        goto give_sigsegv;
3812 d962783e Jia Liu
    }
3813 d962783e Jia Liu
3814 d962783e Jia Liu
    /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/
3815 d962783e Jia Liu
    err |= __put_user(0, &frame->uc.tuc_flags);
3816 d962783e Jia Liu
    err |= __put_user(0, &frame->uc.tuc_link);
3817 d962783e Jia Liu
    err |= __put_user(target_sigaltstack_used.ss_sp,
3818 d962783e Jia Liu
                      &frame->uc.tuc_stack.ss_sp);
3819 d962783e Jia Liu
    err |= __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
3820 d962783e Jia Liu
    err |= __put_user(target_sigaltstack_used.ss_size,
3821 d962783e Jia Liu
                      &frame->uc.tuc_stack.ss_size);
3822 d962783e Jia Liu
    err |= setup_sigcontext(&frame->sc, env, set->sig[0]);
3823 d962783e Jia Liu
3824 d962783e Jia Liu
    /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/
3825 d962783e Jia Liu
3826 d962783e Jia Liu
    if (err) {
3827 d962783e Jia Liu
        goto give_sigsegv;
3828 d962783e Jia Liu
    }
3829 d962783e Jia Liu
3830 d962783e Jia Liu
    /* trampoline - the desired return ip is the retcode itself */
3831 d962783e Jia Liu
    return_ip = (unsigned long)&frame->retcode;
3832 d962783e Jia Liu
    /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
3833 d962783e Jia Liu
    err |= __put_user(0xa960, (short *)(frame->retcode + 0));
3834 d962783e Jia Liu
    err |= __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2));
3835 d962783e Jia Liu
    err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
3836 d962783e Jia Liu
    err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
3837 d962783e Jia Liu
3838 d962783e Jia Liu
    if (err) {
3839 d962783e Jia Liu
        goto give_sigsegv;
3840 d962783e Jia Liu
    }
3841 d962783e Jia Liu
3842 d962783e Jia Liu
    /* TODO what is the current->exec_domain stuff and invmap ? */
3843 d962783e Jia Liu
3844 d962783e Jia Liu
    /* Set up registers for signal handler */
3845 d962783e Jia Liu
    env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
3846 d962783e Jia Liu
    env->gpr[9] = (unsigned long)return_ip;     /* what we enter LATER */
3847 d962783e Jia Liu
    env->gpr[3] = (unsigned long)sig;           /* arg 1: signo */
3848 d962783e Jia Liu
    env->gpr[4] = (unsigned long)&frame->info;  /* arg 2: (siginfo_t*) */
3849 d962783e Jia Liu
    env->gpr[5] = (unsigned long)&frame->uc;    /* arg 3: ucontext */
3850 d962783e Jia Liu
3851 d962783e Jia Liu
    /* actually move the usp to reflect the stacked frame */
3852 d962783e Jia Liu
    env->gpr[1] = (unsigned long)frame;
3853 d962783e Jia Liu
3854 d962783e Jia Liu
    return;
3855 d962783e Jia Liu
3856 d962783e Jia Liu
give_sigsegv:
3857 d962783e Jia Liu
    unlock_user_struct(frame, frame_addr, 1);
3858 d962783e Jia Liu
    if (sig == TARGET_SIGSEGV) {
3859 d962783e Jia Liu
        ka->_sa_handler = TARGET_SIG_DFL;
3860 d962783e Jia Liu
    }
3861 d962783e Jia Liu
    force_sig(TARGET_SIGSEGV);
3862 d962783e Jia Liu
}
3863 d962783e Jia Liu
3864 d962783e Jia Liu
long do_sigreturn(CPUOpenRISCState *env)
3865 d962783e Jia Liu
{
3866 d962783e Jia Liu
3867 d962783e Jia Liu
    qemu_log("do_sigreturn: not implemented\n");
3868 d962783e Jia Liu
    return -TARGET_ENOSYS;
3869 d962783e Jia Liu
}
3870 d962783e Jia Liu
3871 d962783e Jia Liu
long do_rt_sigreturn(CPUOpenRISCState *env)
3872 d962783e Jia Liu
{
3873 d962783e Jia Liu
    qemu_log("do_rt_sigreturn: not implemented\n");
3874 d962783e Jia Liu
    return -TARGET_ENOSYS;
3875 d962783e Jia Liu
}
3876 d962783e Jia Liu
/* TARGET_OPENRISC */
3877 d962783e Jia Liu
3878 a4c075f1 Ulrich Hecht
#elif defined(TARGET_S390X)
3879 a4c075f1 Ulrich Hecht
3880 a4c075f1 Ulrich Hecht
#define __NUM_GPRS 16
3881 a4c075f1 Ulrich Hecht
#define __NUM_FPRS 16
3882 a4c075f1 Ulrich Hecht
#define __NUM_ACRS 16
3883 a4c075f1 Ulrich Hecht
3884 a4c075f1 Ulrich Hecht
#define S390_SYSCALL_SIZE   2
3885 a4c075f1 Ulrich Hecht
#define __SIGNAL_FRAMESIZE      160 /* FIXME: 31-bit mode -> 96 */
3886 a4c075f1 Ulrich Hecht
3887 a4c075f1 Ulrich Hecht
#define _SIGCONTEXT_NSIG        64
3888 a4c075f1 Ulrich Hecht
#define _SIGCONTEXT_NSIG_BPW    64 /* FIXME: 31-bit mode -> 32 */
3889 a4c075f1 Ulrich Hecht
#define _SIGCONTEXT_NSIG_WORDS  (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
3890 a4c075f1 Ulrich Hecht
#define _SIGMASK_COPY_SIZE    (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
3891 a4c075f1 Ulrich Hecht
#define PSW_ADDR_AMODE            0x0000000000000000UL /* 0x80000000UL for 31-bit */
3892 a4c075f1 Ulrich Hecht
#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
3893 a4c075f1 Ulrich Hecht
3894 a4c075f1 Ulrich Hecht
typedef struct {
3895 a4c075f1 Ulrich Hecht
    target_psw_t psw;
3896 a4c075f1 Ulrich Hecht
    target_ulong gprs[__NUM_GPRS];
3897 a4c075f1 Ulrich Hecht
    unsigned int acrs[__NUM_ACRS];
3898 a4c075f1 Ulrich Hecht
} target_s390_regs_common;
3899 a4c075f1 Ulrich Hecht
3900 a4c075f1 Ulrich Hecht
typedef struct {
3901 a4c075f1 Ulrich Hecht
    unsigned int fpc;
3902 a4c075f1 Ulrich Hecht
    double   fprs[__NUM_FPRS];
3903 a4c075f1 Ulrich Hecht
} target_s390_fp_regs;
3904 a4c075f1 Ulrich Hecht
3905 a4c075f1 Ulrich Hecht
typedef struct {
3906 a4c075f1 Ulrich Hecht
    target_s390_regs_common regs;
3907 a4c075f1 Ulrich Hecht
    target_s390_fp_regs     fpregs;
3908 a4c075f1 Ulrich Hecht
} target_sigregs;
3909 a4c075f1 Ulrich Hecht
3910 a4c075f1 Ulrich Hecht
struct target_sigcontext {
3911 a4c075f1 Ulrich Hecht
    target_ulong   oldmask[_SIGCONTEXT_NSIG_WORDS];
3912 a4c075f1 Ulrich Hecht
    target_sigregs *sregs;
3913 a4c075f1 Ulrich Hecht
};
3914 a4c075f1 Ulrich Hecht
3915 a4c075f1 Ulrich Hecht
typedef struct {
3916 a4c075f1 Ulrich Hecht
    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
3917 a4c075f1 Ulrich Hecht
    struct target_sigcontext sc;
3918 a4c075f1 Ulrich Hecht
    target_sigregs sregs;
3919 a4c075f1 Ulrich Hecht
    int signo;
3920 a4c075f1 Ulrich Hecht
    uint8_t retcode[S390_SYSCALL_SIZE];
3921 a4c075f1 Ulrich Hecht
} sigframe;
3922 a4c075f1 Ulrich Hecht
3923 a4c075f1 Ulrich Hecht
struct target_ucontext {
3924 6fea2ea4 Peter Maydell
    target_ulong tuc_flags;
3925 6fea2ea4 Peter Maydell
    struct target_ucontext *tuc_link;
3926 6fea2ea4 Peter Maydell
    target_stack_t tuc_stack;
3927 6fea2ea4 Peter Maydell
    target_sigregs tuc_mcontext;
3928 6fea2ea4 Peter Maydell
    target_sigset_t tuc_sigmask;   /* mask last for extensibility */
3929 a4c075f1 Ulrich Hecht
};
3930 a4c075f1 Ulrich Hecht
3931 a4c075f1 Ulrich Hecht
typedef struct {
3932 a4c075f1 Ulrich Hecht
    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
3933 a4c075f1 Ulrich Hecht
    uint8_t retcode[S390_SYSCALL_SIZE];
3934 a4c075f1 Ulrich Hecht
    struct target_siginfo info;
3935 a4c075f1 Ulrich Hecht
    struct target_ucontext uc;
3936 a4c075f1 Ulrich Hecht
} rt_sigframe;
3937 a4c075f1 Ulrich Hecht
3938 a4c075f1 Ulrich Hecht
static inline abi_ulong
3939 05390248 Andreas Färber
get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size)
3940 a4c075f1 Ulrich Hecht
{
3941 a4c075f1 Ulrich Hecht
    abi_ulong sp;
3942 a4c075f1 Ulrich Hecht
3943 a4c075f1 Ulrich Hecht
    /* Default to using normal stack */
3944 a4c075f1 Ulrich Hecht
    sp = env->regs[15];
3945 a4c075f1 Ulrich Hecht
3946 a4c075f1 Ulrich Hecht
    /* This is the X/Open sanctioned signal stack switching.  */
3947 a4c075f1 Ulrich Hecht
    if (ka->sa_flags & TARGET_SA_ONSTACK) {
3948 a4c075f1 Ulrich Hecht
        if (!sas_ss_flags(sp)) {
3949 a4c075f1 Ulrich Hecht
            sp = target_sigaltstack_used.ss_sp +
3950 a4c075f1 Ulrich Hecht
                 target_sigaltstack_used.ss_size;
3951 a4c075f1 Ulrich Hecht
        }
3952 a4c075f1 Ulrich Hecht
    }
3953 a4c075f1 Ulrich Hecht
3954 a4c075f1 Ulrich Hecht
    /* This is the legacy signal stack switching. */
3955 a4c075f1 Ulrich Hecht
    else if (/* FIXME !user_mode(regs) */ 0 &&
3956 a4c075f1 Ulrich Hecht
             !(ka->sa_flags & TARGET_SA_RESTORER) &&
3957 a4c075f1 Ulrich Hecht
             ka->sa_restorer) {
3958 a4c075f1 Ulrich Hecht
        sp = (abi_ulong) ka->sa_restorer;
3959 a4c075f1 Ulrich Hecht
    }
3960 a4c075f1 Ulrich Hecht
3961 a4c075f1 Ulrich Hecht
    return (sp - frame_size) & -8ul;
3962 a4c075f1 Ulrich Hecht
}
3963 a4c075f1 Ulrich Hecht
3964 05390248 Andreas Färber
static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
3965 a4c075f1 Ulrich Hecht
{
3966 a4c075f1 Ulrich Hecht
    int i;
3967 a4c075f1 Ulrich Hecht
    //save_access_regs(current->thread.acrs); FIXME
3968 a4c075f1 Ulrich Hecht
3969 a4c075f1 Ulrich Hecht
    /* Copy a 'clean' PSW mask to the user to avoid leaking
3970 a4c075f1 Ulrich Hecht
       information about whether PER is currently on.  */
3971 a4c075f1 Ulrich Hecht
    __put_user(env->psw.mask, &sregs->regs.psw.mask);
3972 a4c075f1 Ulrich Hecht
    __put_user(env->psw.addr, &sregs->regs.psw.addr);
3973 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
3974 a4c075f1 Ulrich Hecht
        __put_user(env->regs[i], &sregs->regs.gprs[i]);
3975 a4c075f1 Ulrich Hecht
    }
3976 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
3977 a4c075f1 Ulrich Hecht
        __put_user(env->aregs[i], &sregs->regs.acrs[i]);
3978 a4c075f1 Ulrich Hecht
    }
3979 a4c075f1 Ulrich Hecht
    /*
3980 a4c075f1 Ulrich Hecht
     * We have to store the fp registers to current->thread.fp_regs
3981 a4c075f1 Ulrich Hecht
     * to merge them with the emulated registers.
3982 a4c075f1 Ulrich Hecht
     */
3983 a4c075f1 Ulrich Hecht
    //save_fp_regs(&current->thread.fp_regs); FIXME
3984 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
3985 a4c075f1 Ulrich Hecht
        __put_user(env->fregs[i].ll, &sregs->fpregs.fprs[i]);
3986 a4c075f1 Ulrich Hecht
    }
3987 a4c075f1 Ulrich Hecht
}
3988 a4c075f1 Ulrich Hecht
3989 a4c075f1 Ulrich Hecht
static void setup_frame(int sig, struct target_sigaction *ka,
3990 05390248 Andreas Färber
                        target_sigset_t *set, CPUS390XState *env)
3991 a4c075f1 Ulrich Hecht
{
3992 a4c075f1 Ulrich Hecht
    sigframe *frame;
3993 a4c075f1 Ulrich Hecht
    abi_ulong frame_addr;
3994 a4c075f1 Ulrich Hecht
3995 a4c075f1 Ulrich Hecht
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
3996 a4c075f1 Ulrich Hecht
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
3997 a4c075f1 Ulrich Hecht
             (unsigned long long)frame_addr);
3998 a4c075f1 Ulrich Hecht
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3999 a4c075f1 Ulrich Hecht
            goto give_sigsegv;
4000 a4c075f1 Ulrich Hecht
    }
4001 a4c075f1 Ulrich Hecht
4002 a4c075f1 Ulrich Hecht
    qemu_log("%s: 1\n", __FUNCTION__);
4003 a4c075f1 Ulrich Hecht
    if (__put_user(set->sig[0], &frame->sc.oldmask[0])) {
4004 a4c075f1 Ulrich Hecht
              goto give_sigsegv;
4005 a4c075f1 Ulrich Hecht
    }
4006 a4c075f1 Ulrich Hecht
4007 a4c075f1 Ulrich Hecht
    save_sigregs(env, &frame->sregs);
4008 a4c075f1 Ulrich Hecht
4009 a4c075f1 Ulrich Hecht
    __put_user((abi_ulong)(unsigned long)&frame->sregs,
4010 a4c075f1 Ulrich Hecht
               (abi_ulong *)&frame->sc.sregs);
4011 a4c075f1 Ulrich Hecht
4012 a4c075f1 Ulrich Hecht
    /* Set up to return from userspace.  If provided, use a stub
4013 a4c075f1 Ulrich Hecht
       already in userspace.  */
4014 a4c075f1 Ulrich Hecht
    if (ka->sa_flags & TARGET_SA_RESTORER) {
4015 a4c075f1 Ulrich Hecht
            env->regs[14] = (unsigned long)
4016 a4c075f1 Ulrich Hecht
                    ka->sa_restorer | PSW_ADDR_AMODE;
4017 a4c075f1 Ulrich Hecht
    } else {
4018 a4c075f1 Ulrich Hecht
            env->regs[14] = (unsigned long)
4019 a4c075f1 Ulrich Hecht
                    frame->retcode | PSW_ADDR_AMODE;
4020 a4c075f1 Ulrich Hecht
            if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
4021 a4c075f1 Ulrich Hecht
                           (uint16_t *)(frame->retcode)))
4022 a4c075f1 Ulrich Hecht
                    goto give_sigsegv;
4023 a4c075f1 Ulrich Hecht
    }
4024 a4c075f1 Ulrich Hecht
4025 a4c075f1 Ulrich Hecht
    /* Set up backchain. */
4026 a4c075f1 Ulrich Hecht
    if (__put_user(env->regs[15], (abi_ulong *) frame)) {
4027 a4c075f1 Ulrich Hecht
            goto give_sigsegv;
4028 a4c075f1 Ulrich Hecht
    }
4029 a4c075f1 Ulrich Hecht
4030 a4c075f1 Ulrich Hecht
    /* Set up registers for signal handler */
4031 cb9c6268 Edgar E. Iglesias
    env->regs[15] = frame_addr;
4032 a4c075f1 Ulrich Hecht
    env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4033 a4c075f1 Ulrich Hecht
4034 a4c075f1 Ulrich Hecht
    env->regs[2] = sig; //map_signal(sig);
4035 cb9c6268 Edgar E. Iglesias
    env->regs[3] = frame_addr += offsetof(typeof(*frame), sc);
4036 a4c075f1 Ulrich Hecht
4037 a4c075f1 Ulrich Hecht
    /* We forgot to include these in the sigcontext.
4038 a4c075f1 Ulrich Hecht
       To avoid breaking binary compatibility, they are passed as args. */
4039 a4c075f1 Ulrich Hecht
    env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
4040 a4c075f1 Ulrich Hecht
    env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
4041 a4c075f1 Ulrich Hecht
4042 a4c075f1 Ulrich Hecht
    /* Place signal number on stack to allow backtrace from handler.  */
4043 a4c075f1 Ulrich Hecht
    if (__put_user(env->regs[2], (int *) &frame->signo)) {
4044 a4c075f1 Ulrich Hecht
            goto give_sigsegv;
4045 a4c075f1 Ulrich Hecht
    }
4046 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 1);
4047 a4c075f1 Ulrich Hecht
    return;
4048 a4c075f1 Ulrich Hecht
4049 a4c075f1 Ulrich Hecht
give_sigsegv:
4050 a4c075f1 Ulrich Hecht
    qemu_log("%s: give_sigsegv\n", __FUNCTION__);
4051 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 1);
4052 a4c075f1 Ulrich Hecht
    force_sig(TARGET_SIGSEGV);
4053 a4c075f1 Ulrich Hecht
}
4054 a4c075f1 Ulrich Hecht
4055 a4c075f1 Ulrich Hecht
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4056 a4c075f1 Ulrich Hecht
                           target_siginfo_t *info,
4057 05390248 Andreas Färber
                           target_sigset_t *set, CPUS390XState *env)
4058 a4c075f1 Ulrich Hecht
{
4059 a4c075f1 Ulrich Hecht
    int i;
4060 a4c075f1 Ulrich Hecht
    rt_sigframe *frame;
4061 a4c075f1 Ulrich Hecht
    abi_ulong frame_addr;
4062 a4c075f1 Ulrich Hecht
4063 a4c075f1 Ulrich Hecht
    frame_addr = get_sigframe(ka, env, sizeof *frame);
4064 a4c075f1 Ulrich Hecht
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4065 a4c075f1 Ulrich Hecht
             (unsigned long long)frame_addr);
4066 a4c075f1 Ulrich Hecht
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
4067 a4c075f1 Ulrich Hecht
        goto give_sigsegv;
4068 a4c075f1 Ulrich Hecht
    }
4069 a4c075f1 Ulrich Hecht
4070 a4c075f1 Ulrich Hecht
    qemu_log("%s: 1\n", __FUNCTION__);
4071 a4c075f1 Ulrich Hecht
    if (copy_siginfo_to_user(&frame->info, info)) {
4072 a4c075f1 Ulrich Hecht
        goto give_sigsegv;
4073 a4c075f1 Ulrich Hecht
    }
4074 a4c075f1 Ulrich Hecht
4075 a4c075f1 Ulrich Hecht
    /* Create the ucontext.  */
4076 6fea2ea4 Peter Maydell
    __put_user(0, &frame->uc.tuc_flags);
4077 6fea2ea4 Peter Maydell
    __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
4078 6fea2ea4 Peter Maydell
    __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
4079 a4c075f1 Ulrich Hecht
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
4080 6fea2ea4 Peter Maydell
                      &frame->uc.tuc_stack.ss_flags);
4081 6fea2ea4 Peter Maydell
    __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
4082 6fea2ea4 Peter Maydell
    save_sigregs(env, &frame->uc.tuc_mcontext);
4083 a4c075f1 Ulrich Hecht
    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
4084 a4c075f1 Ulrich Hecht
        __put_user((abi_ulong)set->sig[i],
4085 6fea2ea4 Peter Maydell
        (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
4086 a4c075f1 Ulrich Hecht
    }
4087 a4c075f1 Ulrich Hecht
4088 a4c075f1 Ulrich Hecht
    /* Set up to return from userspace.  If provided, use a stub
4089 a4c075f1 Ulrich Hecht
       already in userspace.  */
4090 a4c075f1 Ulrich Hecht
    if (ka->sa_flags & TARGET_SA_RESTORER) {
4091 a4c075f1 Ulrich Hecht
        env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
4092 a4c075f1 Ulrich Hecht
    } else {
4093 a4c075f1 Ulrich Hecht
        env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
4094 a4c075f1 Ulrich Hecht
        if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
4095 a4c075f1 Ulrich Hecht
                       (uint16_t *)(frame->retcode))) {
4096 a4c075f1 Ulrich Hecht
            goto give_sigsegv;
4097 a4c075f1 Ulrich Hecht
        }
4098 a4c075f1 Ulrich Hecht
    }
4099 a4c075f1 Ulrich Hecht
4100 a4c075f1 Ulrich Hecht
    /* Set up backchain. */
4101 a4c075f1 Ulrich Hecht
    if (__put_user(env->regs[15], (abi_ulong *) frame)) {
4102 a4c075f1 Ulrich Hecht
        goto give_sigsegv;
4103 a4c075f1 Ulrich Hecht
    }
4104 a4c075f1 Ulrich Hecht
4105 a4c075f1 Ulrich Hecht
    /* Set up registers for signal handler */
4106 cb9c6268 Edgar E. Iglesias
    env->regs[15] = frame_addr;
4107 a4c075f1 Ulrich Hecht
    env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
4108 a4c075f1 Ulrich Hecht
4109 a4c075f1 Ulrich Hecht
    env->regs[2] = sig; //map_signal(sig);
4110 cb9c6268 Edgar E. Iglesias
    env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
4111 cb9c6268 Edgar E. Iglesias
    env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
4112 a4c075f1 Ulrich Hecht
    return;
4113 a4c075f1 Ulrich Hecht
4114 a4c075f1 Ulrich Hecht
give_sigsegv:
4115 a4c075f1 Ulrich Hecht
    qemu_log("%s: give_sigsegv\n", __FUNCTION__);
4116 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 1);
4117 a4c075f1 Ulrich Hecht
    force_sig(TARGET_SIGSEGV);
4118 a4c075f1 Ulrich Hecht
}
4119 a4c075f1 Ulrich Hecht
4120 a4c075f1 Ulrich Hecht
static int
4121 05390248 Andreas Färber
restore_sigregs(CPUS390XState *env, target_sigregs *sc)
4122 a4c075f1 Ulrich Hecht
{
4123 a4c075f1 Ulrich Hecht
    int err = 0;
4124 a4c075f1 Ulrich Hecht
    int i;
4125 a4c075f1 Ulrich Hecht
4126 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
4127 a4c075f1 Ulrich Hecht
        err |= __get_user(env->regs[i], &sc->regs.gprs[i]);
4128 a4c075f1 Ulrich Hecht
    }
4129 a4c075f1 Ulrich Hecht
4130 a4c075f1 Ulrich Hecht
    err |= __get_user(env->psw.mask, &sc->regs.psw.mask);
4131 a4c075f1 Ulrich Hecht
    qemu_log("%s: sc->regs.psw.addr 0x%llx env->psw.addr 0x%llx\n",
4132 a4c075f1 Ulrich Hecht
             __FUNCTION__, (unsigned long long)sc->regs.psw.addr,
4133 a4c075f1 Ulrich Hecht
             (unsigned long long)env->psw.addr);
4134 a4c075f1 Ulrich Hecht
    err |= __get_user(env->psw.addr, &sc->regs.psw.addr);
4135 a4c075f1 Ulrich Hecht
    /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
4136 a4c075f1 Ulrich Hecht
4137 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
4138 a4c075f1 Ulrich Hecht
        err |= __get_user(env->aregs[i], &sc->regs.acrs[i]);
4139 a4c075f1 Ulrich Hecht
    }
4140 a4c075f1 Ulrich Hecht
    for (i = 0; i < 16; i++) {
4141 a4c075f1 Ulrich Hecht
        err |= __get_user(env->fregs[i].ll, &sc->fpregs.fprs[i]);
4142 a4c075f1 Ulrich Hecht
    }
4143 a4c075f1 Ulrich Hecht
4144 a4c075f1 Ulrich Hecht
    return err;
4145 a4c075f1 Ulrich Hecht
}
4146 a4c075f1 Ulrich Hecht
4147 05390248 Andreas Färber
long do_sigreturn(CPUS390XState *env)
4148 a4c075f1 Ulrich Hecht
{
4149 a4c075f1 Ulrich Hecht
    sigframe *frame;
4150 a4c075f1 Ulrich Hecht
    abi_ulong frame_addr = env->regs[15];
4151 a4c075f1 Ulrich Hecht
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4152 a4c075f1 Ulrich Hecht
             (unsigned long long)frame_addr);
4153 a4c075f1 Ulrich Hecht
    target_sigset_t target_set;
4154 a4c075f1 Ulrich Hecht
    sigset_t set;
4155 a4c075f1 Ulrich Hecht
4156 a4c075f1 Ulrich Hecht
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4157 a4c075f1 Ulrich Hecht
        goto badframe;
4158 a4c075f1 Ulrich Hecht
    }
4159 a4c075f1 Ulrich Hecht
    if (__get_user(target_set.sig[0], &frame->sc.oldmask[0])) {
4160 a4c075f1 Ulrich Hecht
        goto badframe;
4161 a4c075f1 Ulrich Hecht
    }
4162 a4c075f1 Ulrich Hecht
4163 a4c075f1 Ulrich Hecht
    target_to_host_sigset_internal(&set, &target_set);
4164 a4c075f1 Ulrich Hecht
    sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
4165 a4c075f1 Ulrich Hecht
4166 a4c075f1 Ulrich Hecht
    if (restore_sigregs(env, &frame->sregs)) {
4167 a4c075f1 Ulrich Hecht
        goto badframe;
4168 a4c075f1 Ulrich Hecht
    }
4169 a4c075f1 Ulrich Hecht
4170 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 0);
4171 a4c075f1 Ulrich Hecht
    return env->regs[2];
4172 a4c075f1 Ulrich Hecht
4173 a4c075f1 Ulrich Hecht
badframe:
4174 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 0);
4175 a4c075f1 Ulrich Hecht
    force_sig(TARGET_SIGSEGV);
4176 a4c075f1 Ulrich Hecht
    return 0;
4177 a4c075f1 Ulrich Hecht
}
4178 a4c075f1 Ulrich Hecht
4179 05390248 Andreas Färber
long do_rt_sigreturn(CPUS390XState *env)
4180 a4c075f1 Ulrich Hecht
{
4181 a4c075f1 Ulrich Hecht
    rt_sigframe *frame;
4182 a4c075f1 Ulrich Hecht
    abi_ulong frame_addr = env->regs[15];
4183 a4c075f1 Ulrich Hecht
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
4184 a4c075f1 Ulrich Hecht
             (unsigned long long)frame_addr);
4185 a4c075f1 Ulrich Hecht
    sigset_t set;
4186 a4c075f1 Ulrich Hecht
4187 a4c075f1 Ulrich Hecht
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
4188 a4c075f1 Ulrich Hecht
        goto badframe;
4189 a4c075f1 Ulrich Hecht
    }
4190 6fea2ea4 Peter Maydell
    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
4191 a4c075f1 Ulrich Hecht
4192 a4c075f1 Ulrich Hecht
    sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
4193 a4c075f1 Ulrich Hecht
4194 6fea2ea4 Peter Maydell
    if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
4195 a4c075f1 Ulrich Hecht
        goto badframe;
4196 a4c075f1 Ulrich Hecht
    }
4197 a4c075f1 Ulrich Hecht
4198 6fea2ea4 Peter Maydell
    if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
4199 a4c075f1 Ulrich Hecht
                       get_sp_from_cpustate(env)) == -EFAULT) {
4200 a4c075f1 Ulrich Hecht
        goto badframe;
4201 a4c075f1 Ulrich Hecht
    }
4202 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 0);
4203 a4c075f1 Ulrich Hecht
    return env->regs[2];
4204 a4c075f1 Ulrich Hecht
4205 a4c075f1 Ulrich Hecht
badframe:
4206 a4c075f1 Ulrich Hecht
    unlock_user_struct(frame, frame_addr, 0);
4207 a4c075f1 Ulrich Hecht
    force_sig(TARGET_SIGSEGV);
4208 a4c075f1 Ulrich Hecht
    return 0;
4209 a4c075f1 Ulrich Hecht
}
4210 a4c075f1 Ulrich Hecht
4211 bcd4933a Nathan Froyd
#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
4212 bcd4933a Nathan Froyd
4213 bcd4933a Nathan Froyd
/* FIXME: Many of the structures are defined for both PPC and PPC64, but
4214 bcd4933a Nathan Froyd
   the signal handling is different enough that we haven't implemented
4215 bcd4933a Nathan Froyd
   support for PPC64 yet.  Hence the restriction above.
4216 bcd4933a Nathan Froyd

4217 bcd4933a Nathan Froyd
   There are various #if'd blocks for code for TARGET_PPC64.  These
4218 bcd4933a Nathan Froyd
   blocks should go away so that we can successfully run 32-bit and
4219 bcd4933a Nathan Froyd
   64-bit binaries on a QEMU configured for PPC64.  */
4220 bcd4933a Nathan Froyd
4221 bcd4933a Nathan Froyd
/* Size of dummy stack frame allocated when calling signal handler.
4222 bcd4933a Nathan Froyd
   See arch/powerpc/include/asm/ptrace.h.  */
4223 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4224 bcd4933a Nathan Froyd
#define SIGNAL_FRAMESIZE 128
4225 bcd4933a Nathan Froyd
#else
4226 bcd4933a Nathan Froyd
#define SIGNAL_FRAMESIZE 64
4227 bcd4933a Nathan Froyd
#endif
4228 bcd4933a Nathan Froyd
4229 bcd4933a Nathan Froyd
/* See arch/powerpc/include/asm/sigcontext.h.  */
4230 bcd4933a Nathan Froyd
struct target_sigcontext {
4231 bcd4933a Nathan Froyd
    target_ulong _unused[4];
4232 bcd4933a Nathan Froyd
    int32_t signal;
4233 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4234 bcd4933a Nathan Froyd
    int32_t pad0;
4235 bcd4933a Nathan Froyd
#endif
4236 bcd4933a Nathan Froyd
    target_ulong handler;
4237 bcd4933a Nathan Froyd
    target_ulong oldmask;
4238 bcd4933a Nathan Froyd
    target_ulong regs;      /* struct pt_regs __user * */
4239 bcd4933a Nathan Froyd
    /* TODO: PPC64 includes extra bits here.  */
4240 bcd4933a Nathan Froyd
};
4241 bcd4933a Nathan Froyd
4242 bcd4933a Nathan Froyd
/* Indices for target_mcontext.mc_gregs, below.
4243 bcd4933a Nathan Froyd
   See arch/powerpc/include/asm/ptrace.h for details.  */
4244 bcd4933a Nathan Froyd
enum {
4245 bcd4933a Nathan Froyd
    TARGET_PT_R0 = 0,
4246 bcd4933a Nathan Froyd
    TARGET_PT_R1 = 1,
4247 bcd4933a Nathan Froyd
    TARGET_PT_R2 = 2,
4248 bcd4933a Nathan Froyd
    TARGET_PT_R3 = 3,
4249 bcd4933a Nathan Froyd
    TARGET_PT_R4 = 4,
4250 bcd4933a Nathan Froyd
    TARGET_PT_R5 = 5,
4251 bcd4933a Nathan Froyd
    TARGET_PT_R6 = 6,
4252 bcd4933a Nathan Froyd
    TARGET_PT_R7 = 7,
4253 bcd4933a Nathan Froyd
    TARGET_PT_R8 = 8,
4254 bcd4933a Nathan Froyd
    TARGET_PT_R9 = 9,
4255 bcd4933a Nathan Froyd
    TARGET_PT_R10 = 10,
4256 bcd4933a Nathan Froyd
    TARGET_PT_R11 = 11,
4257 bcd4933a Nathan Froyd
    TARGET_PT_R12 = 12,
4258 bcd4933a Nathan Froyd
    TARGET_PT_R13 = 13,
4259 bcd4933a Nathan Froyd
    TARGET_PT_R14 = 14,
4260 bcd4933a Nathan Froyd
    TARGET_PT_R15 = 15,
4261 bcd4933a Nathan Froyd
    TARGET_PT_R16 = 16,
4262 bcd4933a Nathan Froyd
    TARGET_PT_R17 = 17,
4263 bcd4933a Nathan Froyd
    TARGET_PT_R18 = 18,
4264 bcd4933a Nathan Froyd
    TARGET_PT_R19 = 19,
4265 bcd4933a Nathan Froyd
    TARGET_PT_R20 = 20,
4266 bcd4933a Nathan Froyd
    TARGET_PT_R21 = 21,
4267 bcd4933a Nathan Froyd
    TARGET_PT_R22 = 22,
4268 bcd4933a Nathan Froyd
    TARGET_PT_R23 = 23,
4269 bcd4933a Nathan Froyd
    TARGET_PT_R24 = 24,
4270 bcd4933a Nathan Froyd
    TARGET_PT_R25 = 25,
4271 bcd4933a Nathan Froyd
    TARGET_PT_R26 = 26,
4272 bcd4933a Nathan Froyd
    TARGET_PT_R27 = 27,
4273 bcd4933a Nathan Froyd
    TARGET_PT_R28 = 28,
4274 bcd4933a Nathan Froyd
    TARGET_PT_R29 = 29,
4275 bcd4933a Nathan Froyd
    TARGET_PT_R30 = 30,
4276 bcd4933a Nathan Froyd
    TARGET_PT_R31 = 31,
4277 bcd4933a Nathan Froyd
    TARGET_PT_NIP = 32,
4278 bcd4933a Nathan Froyd
    TARGET_PT_MSR = 33,
4279 bcd4933a Nathan Froyd
    TARGET_PT_ORIG_R3 = 34,
4280 bcd4933a Nathan Froyd
    TARGET_PT_CTR = 35,
4281 bcd4933a Nathan Froyd
    TARGET_PT_LNK = 36,
4282 bcd4933a Nathan Froyd
    TARGET_PT_XER = 37,
4283 bcd4933a Nathan Froyd
    TARGET_PT_CCR = 38,
4284 bcd4933a Nathan Froyd
    /* Yes, there are two registers with #39.  One is 64-bit only.  */
4285 bcd4933a Nathan Froyd
    TARGET_PT_MQ = 39,
4286 bcd4933a Nathan Froyd
    TARGET_PT_SOFTE = 39,
4287 bcd4933a Nathan Froyd
    TARGET_PT_TRAP = 40,
4288 bcd4933a Nathan Froyd
    TARGET_PT_DAR = 41,
4289 bcd4933a Nathan Froyd
    TARGET_PT_DSISR = 42,
4290 bcd4933a Nathan Froyd
    TARGET_PT_RESULT = 43,
4291 bcd4933a Nathan Froyd
    TARGET_PT_REGS_COUNT = 44
4292 bcd4933a Nathan Froyd
};
4293 bcd4933a Nathan Froyd
4294 bcd4933a Nathan Froyd
/* See arch/powerpc/include/asm/ucontext.h.  Only used for 32-bit PPC;
4295 bcd4933a Nathan Froyd
   on 64-bit PPC, sigcontext and mcontext are one and the same.  */
4296 bcd4933a Nathan Froyd
struct target_mcontext {
4297 bcd4933a Nathan Froyd
    target_ulong mc_gregs[48];
4298 bcd4933a Nathan Froyd
    /* Includes fpscr.  */
4299 bcd4933a Nathan Froyd
    uint64_t mc_fregs[33];
4300 bcd4933a Nathan Froyd
    target_ulong mc_pad[2];
4301 bcd4933a Nathan Froyd
    /* We need to handle Altivec and SPE at the same time, which no
4302 bcd4933a Nathan Froyd
       kernel needs to do.  Fortunately, the kernel defines this bit to
4303 bcd4933a Nathan Froyd
       be Altivec-register-large all the time, rather than trying to
4304 bcd4933a Nathan Froyd
       twiddle it based on the specific platform.  */
4305 bcd4933a Nathan Froyd
    union {
4306 bcd4933a Nathan Froyd
        /* SPE vector registers.  One extra for SPEFSCR.  */
4307 bcd4933a Nathan Froyd
        uint32_t spe[33];
4308 bcd4933a Nathan Froyd
        /* Altivec vector registers.  The packing of VSCR and VRSAVE
4309 bcd4933a Nathan Froyd
           varies depending on whether we're PPC64 or not: PPC64 splits
4310 bcd4933a Nathan Froyd
           them apart; PPC32 stuffs them together.  */
4311 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4312 3efa9a67 malc
#define QEMU_NVRREG 34
4313 bcd4933a Nathan Froyd
#else
4314 3efa9a67 malc
#define QEMU_NVRREG 33
4315 bcd4933a Nathan Froyd
#endif
4316 c227f099 Anthony Liguori
        ppc_avr_t altivec[QEMU_NVRREG];
4317 3efa9a67 malc
#undef QEMU_NVRREG
4318 bcd4933a Nathan Froyd
    } mc_vregs __attribute__((__aligned__(16)));
4319 bcd4933a Nathan Froyd
};
4320 bcd4933a Nathan Froyd
4321 bcd4933a Nathan Froyd
struct target_ucontext {
4322 60e99246 Aurelien Jarno
    target_ulong tuc_flags;
4323 60e99246 Aurelien Jarno
    target_ulong tuc_link;    /* struct ucontext __user * */
4324 60e99246 Aurelien Jarno
    struct target_sigaltstack tuc_stack;
4325 bcd4933a Nathan Froyd
#if !defined(TARGET_PPC64)
4326 60e99246 Aurelien Jarno
    int32_t tuc_pad[7];
4327 60e99246 Aurelien Jarno
    target_ulong tuc_regs;    /* struct mcontext __user *
4328 bcd4933a Nathan Froyd
                                points to uc_mcontext field */
4329 bcd4933a Nathan Froyd
#endif
4330 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
4331 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4332 c227f099 Anthony Liguori
    target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
4333 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
4334 bcd4933a Nathan Froyd
#else
4335 60e99246 Aurelien Jarno
    int32_t tuc_maskext[30];
4336 60e99246 Aurelien Jarno
    int32_t tuc_pad2[3];
4337 60e99246 Aurelien Jarno
    struct target_mcontext tuc_mcontext;
4338 bcd4933a Nathan Froyd
#endif
4339 bcd4933a Nathan Froyd
};
4340 bcd4933a Nathan Froyd
4341 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal_32.c.  */
4342 bcd4933a Nathan Froyd
struct target_sigframe {
4343 bcd4933a Nathan Froyd
    struct target_sigcontext sctx;
4344 bcd4933a Nathan Froyd
    struct target_mcontext mctx;
4345 bcd4933a Nathan Froyd
    int32_t abigap[56];
4346 bcd4933a Nathan Froyd
};
4347 bcd4933a Nathan Froyd
4348 bcd4933a Nathan Froyd
struct target_rt_sigframe {
4349 bcd4933a Nathan Froyd
    struct target_siginfo info;
4350 bcd4933a Nathan Froyd
    struct target_ucontext uc;
4351 bcd4933a Nathan Froyd
    int32_t abigap[56];
4352 bcd4933a Nathan Froyd
};
4353 bcd4933a Nathan Froyd
4354 bcd4933a Nathan Froyd
/* We use the mc_pad field for the signal return trampoline.  */
4355 bcd4933a Nathan Froyd
#define tramp mc_pad
4356 bcd4933a Nathan Froyd
4357 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal.c.  */
4358 bcd4933a Nathan Froyd
static target_ulong get_sigframe(struct target_sigaction *ka,
4359 05390248 Andreas Färber
                                 CPUPPCState *env,
4360 bcd4933a Nathan Froyd
                                 int frame_size)
4361 bcd4933a Nathan Froyd
{
4362 bcd4933a Nathan Froyd
    target_ulong oldsp, newsp;
4363 bcd4933a Nathan Froyd
4364 bcd4933a Nathan Froyd
    oldsp = env->gpr[1];
4365 bcd4933a Nathan Froyd
4366 bcd4933a Nathan Froyd
    if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
4367 32a2003a Alex Barcelo
        (sas_ss_flags(oldsp) == 0)) {
4368 bcd4933a Nathan Froyd
        oldsp = (target_sigaltstack_used.ss_sp
4369 bcd4933a Nathan Froyd
                 + target_sigaltstack_used.ss_size);
4370 bcd4933a Nathan Froyd
    }
4371 bcd4933a Nathan Froyd
4372 bcd4933a Nathan Froyd
    newsp = (oldsp - frame_size) & ~0xFUL;
4373 bcd4933a Nathan Froyd
4374 bcd4933a Nathan Froyd
    return newsp;
4375 bcd4933a Nathan Froyd
}
4376 bcd4933a Nathan Froyd
4377 05390248 Andreas Färber
static int save_user_regs(CPUPPCState *env, struct target_mcontext *frame,
4378 bcd4933a Nathan Froyd
                          int sigret)
4379 bcd4933a Nathan Froyd
{
4380 bcd4933a Nathan Froyd
    target_ulong msr = env->msr;
4381 bcd4933a Nathan Froyd
    int i;
4382 bcd4933a Nathan Froyd
    target_ulong ccr = 0;
4383 bcd4933a Nathan Froyd
4384 bcd4933a Nathan Froyd
    /* In general, the kernel attempts to be intelligent about what it
4385 bcd4933a Nathan Froyd
       needs to save for Altivec/FP/SPE registers.  We don't care that
4386 bcd4933a Nathan Froyd
       much, so we just go ahead and save everything.  */
4387 bcd4933a Nathan Froyd
4388 bcd4933a Nathan Froyd
    /* Save general registers.  */
4389 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4390 bcd4933a Nathan Froyd
        if (__put_user(env->gpr[i], &frame->mc_gregs[i])) {
4391 bcd4933a Nathan Froyd
            return 1;
4392 bcd4933a Nathan Froyd
        }
4393 bcd4933a Nathan Froyd
    }
4394 bcd4933a Nathan Froyd
    if (__put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
4395 bcd4933a Nathan Froyd
        || __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
4396 bcd4933a Nathan Froyd
        || __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
4397 bcd4933a Nathan Froyd
        || __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
4398 bcd4933a Nathan Froyd
        return 1;
4399 bcd4933a Nathan Froyd
4400 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4401 bcd4933a Nathan Froyd
        ccr |= env->crf[i] << (32 - ((i + 1) * 4));
4402 bcd4933a Nathan Froyd
    }
4403 bcd4933a Nathan Froyd
    if (__put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
4404 bcd4933a Nathan Froyd
        return 1;
4405 bcd4933a Nathan Froyd
4406 bcd4933a Nathan Froyd
    /* Save Altivec registers if necessary.  */
4407 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_ALTIVEC) {
4408 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
4409 c227f099 Anthony Liguori
            ppc_avr_t *avr = &env->avr[i];
4410 c227f099 Anthony Liguori
            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
4411 bcd4933a Nathan Froyd
4412 bcd4933a Nathan Froyd
            if (__put_user(avr->u64[0], &vreg->u64[0]) ||
4413 bcd4933a Nathan Froyd
                __put_user(avr->u64[1], &vreg->u64[1])) {
4414 bcd4933a Nathan Froyd
                return 1;
4415 bcd4933a Nathan Froyd
            }
4416 bcd4933a Nathan Froyd
        }
4417 bcd4933a Nathan Froyd
        /* Set MSR_VR in the saved MSR value to indicate that
4418 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
4419 bcd4933a Nathan Froyd
        msr |= MSR_VR;
4420 bcd4933a Nathan Froyd
        if (__put_user((uint32_t)env->spr[SPR_VRSAVE],
4421 bcd4933a Nathan Froyd
                       &frame->mc_vregs.altivec[32].u32[3]))
4422 bcd4933a Nathan Froyd
            return 1;
4423 bcd4933a Nathan Froyd
    }
4424 bcd4933a Nathan Froyd
4425 bcd4933a Nathan Froyd
    /* Save floating point registers.  */
4426 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_FLOAT) {
4427 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
4428 bcd4933a Nathan Froyd
            if (__put_user(env->fpr[i], &frame->mc_fregs[i])) {
4429 bcd4933a Nathan Froyd
                return 1;
4430 bcd4933a Nathan Froyd
            }
4431 bcd4933a Nathan Froyd
        }
4432 bcd4933a Nathan Froyd
        if (__put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]))
4433 bcd4933a Nathan Froyd
            return 1;
4434 bcd4933a Nathan Froyd
    }
4435 bcd4933a Nathan Froyd
4436 bcd4933a Nathan Froyd
    /* Save SPE registers.  The kernel only saves the high half.  */
4437 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_SPE) {
4438 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4439 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4440 bcd4933a Nathan Froyd
            if (__put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i])) {
4441 bcd4933a Nathan Froyd
                return 1;
4442 bcd4933a Nathan Froyd
            }
4443 bcd4933a Nathan Froyd
        }
4444 bcd4933a Nathan Froyd
#else
4445 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
4446 bcd4933a Nathan Froyd
            if (__put_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
4447 bcd4933a Nathan Froyd
                return 1;
4448 bcd4933a Nathan Froyd
            }
4449 bcd4933a Nathan Froyd
        }
4450 bcd4933a Nathan Froyd
#endif
4451 bcd4933a Nathan Froyd
        /* Set MSR_SPE in the saved MSR value to indicate that
4452 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
4453 bcd4933a Nathan Froyd
        msr |= MSR_SPE;
4454 bcd4933a Nathan Froyd
        if (__put_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
4455 bcd4933a Nathan Froyd
            return 1;
4456 bcd4933a Nathan Froyd
    }
4457 bcd4933a Nathan Froyd
4458 bcd4933a Nathan Froyd
    /* Store MSR.  */
4459 bcd4933a Nathan Froyd
    if (__put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
4460 bcd4933a Nathan Froyd
        return 1;
4461 bcd4933a Nathan Froyd
4462 bcd4933a Nathan Froyd
    /* Set up the sigreturn trampoline: li r0,sigret; sc.  */
4463 bcd4933a Nathan Froyd
    if (sigret) {
4464 bcd4933a Nathan Froyd
        if (__put_user(0x38000000UL | sigret, &frame->tramp[0]) ||
4465 bcd4933a Nathan Froyd
            __put_user(0x44000002UL, &frame->tramp[1])) {
4466 bcd4933a Nathan Froyd
            return 1;
4467 bcd4933a Nathan Froyd
        }
4468 bcd4933a Nathan Froyd
    }
4469 bcd4933a Nathan Froyd
4470 bcd4933a Nathan Froyd
    return 0;
4471 bcd4933a Nathan Froyd
}
4472 bcd4933a Nathan Froyd
4473 05390248 Andreas Färber
static int restore_user_regs(CPUPPCState *env,
4474 bcd4933a Nathan Froyd
                             struct target_mcontext *frame, int sig)
4475 bcd4933a Nathan Froyd
{
4476 bcd4933a Nathan Froyd
    target_ulong save_r2 = 0;
4477 bcd4933a Nathan Froyd
    target_ulong msr;
4478 bcd4933a Nathan Froyd
    target_ulong ccr;
4479 bcd4933a Nathan Froyd
4480 bcd4933a Nathan Froyd
    int i;
4481 bcd4933a Nathan Froyd
4482 bcd4933a Nathan Froyd
    if (!sig) {
4483 bcd4933a Nathan Froyd
        save_r2 = env->gpr[2];
4484 bcd4933a Nathan Froyd
    }
4485 bcd4933a Nathan Froyd
4486 bcd4933a Nathan Froyd
    /* Restore general registers.  */
4487 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4488 bcd4933a Nathan Froyd
        if (__get_user(env->gpr[i], &frame->mc_gregs[i])) {
4489 bcd4933a Nathan Froyd
            return 1;
4490 bcd4933a Nathan Froyd
        }
4491 bcd4933a Nathan Froyd
    }
4492 bcd4933a Nathan Froyd
    if (__get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
4493 bcd4933a Nathan Froyd
        || __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
4494 bcd4933a Nathan Froyd
        || __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
4495 bcd4933a Nathan Froyd
        || __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
4496 bcd4933a Nathan Froyd
        return 1;
4497 bcd4933a Nathan Froyd
    if (__get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
4498 bcd4933a Nathan Froyd
        return 1;
4499 bcd4933a Nathan Froyd
4500 bcd4933a Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
4501 bcd4933a Nathan Froyd
        env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
4502 bcd4933a Nathan Froyd
    }
4503 bcd4933a Nathan Froyd
4504 bcd4933a Nathan Froyd
    if (!sig) {
4505 bcd4933a Nathan Froyd
        env->gpr[2] = save_r2;
4506 bcd4933a Nathan Froyd
    }
4507 bcd4933a Nathan Froyd
    /* Restore MSR.  */
4508 bcd4933a Nathan Froyd
    if (__get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
4509 bcd4933a Nathan Froyd
        return 1;
4510 bcd4933a Nathan Froyd
4511 bcd4933a Nathan Froyd
    /* If doing signal return, restore the previous little-endian mode.  */
4512 bcd4933a Nathan Froyd
    if (sig)
4513 bcd4933a Nathan Froyd
        env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
4514 bcd4933a Nathan Froyd
4515 bcd4933a Nathan Froyd
    /* Restore Altivec registers if necessary.  */
4516 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_ALTIVEC) {
4517 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
4518 c227f099 Anthony Liguori
            ppc_avr_t *avr = &env->avr[i];
4519 c227f099 Anthony Liguori
            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
4520 bcd4933a Nathan Froyd
4521 bcd4933a Nathan Froyd
            if (__get_user(avr->u64[0], &vreg->u64[0]) ||
4522 bcd4933a Nathan Froyd
                __get_user(avr->u64[1], &vreg->u64[1])) {
4523 bcd4933a Nathan Froyd
                return 1;
4524 bcd4933a Nathan Froyd
            }
4525 bcd4933a Nathan Froyd
        }
4526 bcd4933a Nathan Froyd
        /* Set MSR_VEC in the saved MSR value to indicate that
4527 bcd4933a Nathan Froyd
           frame->mc_vregs contains valid data.  */
4528 bcd4933a Nathan Froyd
        if (__get_user(env->spr[SPR_VRSAVE],
4529 bcd4933a Nathan Froyd
                       (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3])))
4530 bcd4933a Nathan Froyd
            return 1;
4531 bcd4933a Nathan Froyd
    }
4532 bcd4933a Nathan Froyd
4533 bcd4933a Nathan Froyd
    /* Restore floating point registers.  */
4534 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_FLOAT) {
4535 bcd4933a Nathan Froyd
        uint64_t fpscr;
4536 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
4537 bcd4933a Nathan Froyd
            if (__get_user(env->fpr[i], &frame->mc_fregs[i])) {
4538 bcd4933a Nathan Froyd
                return 1;
4539 bcd4933a Nathan Froyd
            }
4540 bcd4933a Nathan Froyd
        }
4541 bcd4933a Nathan Froyd
        if (__get_user(fpscr, &frame->mc_fregs[32]))
4542 bcd4933a Nathan Froyd
            return 1;
4543 bcd4933a Nathan Froyd
        env->fpscr = (uint32_t) fpscr;
4544 bcd4933a Nathan Froyd
    }
4545 bcd4933a Nathan Froyd
4546 bcd4933a Nathan Froyd
    /* Save SPE registers.  The kernel only saves the high half.  */
4547 bcd4933a Nathan Froyd
    if (env->insns_flags & PPC_SPE) {
4548 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4549 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
4550 bcd4933a Nathan Froyd
            uint32_t hi;
4551 bcd4933a Nathan Froyd
4552 bcd4933a Nathan Froyd
            if (__get_user(hi, &frame->mc_vregs.spe[i])) {
4553 bcd4933a Nathan Froyd
                return 1;
4554 bcd4933a Nathan Froyd
            }
4555 bcd4933a Nathan Froyd
            env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
4556 bcd4933a Nathan Froyd
        }
4557 bcd4933a Nathan Froyd
#else
4558 bcd4933a Nathan Froyd
        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
4559 bcd4933a Nathan Froyd
            if (__get_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
4560 bcd4933a Nathan Froyd
                return 1;
4561 bcd4933a Nathan Froyd
            }
4562 bcd4933a Nathan Froyd
        }
4563 bcd4933a Nathan Froyd
#endif
4564 bcd4933a Nathan Froyd
        if (__get_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
4565 bcd4933a Nathan Froyd
            return 1;
4566 bcd4933a Nathan Froyd
    }
4567 bcd4933a Nathan Froyd
4568 bcd4933a Nathan Froyd
    return 0;
4569 bcd4933a Nathan Froyd
}
4570 bcd4933a Nathan Froyd
4571 bcd4933a Nathan Froyd
static void setup_frame(int sig, struct target_sigaction *ka,
4572 05390248 Andreas Färber
                        target_sigset_t *set, CPUPPCState *env)
4573 bcd4933a Nathan Froyd
{
4574 bcd4933a Nathan Froyd
    struct target_sigframe *frame;
4575 bcd4933a Nathan Froyd
    struct target_sigcontext *sc;
4576 bcd4933a Nathan Froyd
    target_ulong frame_addr, newsp;
4577 bcd4933a Nathan Froyd
    int err = 0;
4578 bcd4933a Nathan Froyd
    int signal;
4579 bcd4933a Nathan Froyd
4580 bcd4933a Nathan Froyd
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
4581 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
4582 bcd4933a Nathan Froyd
        goto sigsegv;
4583 bcd4933a Nathan Froyd
    sc = &frame->sctx;
4584 bcd4933a Nathan Froyd
4585 bcd4933a Nathan Froyd
    signal = current_exec_domain_sig(sig);
4586 bcd4933a Nathan Froyd
4587 bcd4933a Nathan Froyd
    err |= __put_user(h2g(ka->_sa_handler), &sc->handler);
4588 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[0], &sc->oldmask);
4589 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4590 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[0] >> 32, &sc->_unused[3]);
4591 bcd4933a Nathan Froyd
#else
4592 bcd4933a Nathan Froyd
    err |= __put_user(set->sig[1], &sc->_unused[3]);
4593 bcd4933a Nathan Froyd
#endif
4594 bcd4933a Nathan Froyd
    err |= __put_user(h2g(&frame->mctx), &sc->regs);
4595 bcd4933a Nathan Froyd
    err |= __put_user(sig, &sc->signal);
4596 bcd4933a Nathan Froyd
4597 bcd4933a Nathan Froyd
    /* Save user regs.  */
4598 bcd4933a Nathan Froyd
    err |= save_user_regs(env, &frame->mctx, TARGET_NR_sigreturn);
4599 bcd4933a Nathan Froyd
4600 bcd4933a Nathan Froyd
    /* The kernel checks for the presence of a VDSO here.  We don't
4601 bcd4933a Nathan Froyd
       emulate a vdso, so use a sigreturn system call.  */
4602 bcd4933a Nathan Froyd
    env->lr = (target_ulong) h2g(frame->mctx.tramp);
4603 bcd4933a Nathan Froyd
4604 bcd4933a Nathan Froyd
    /* Turn off all fp exceptions.  */
4605 bcd4933a Nathan Froyd
    env->fpscr = 0;
4606 bcd4933a Nathan Froyd
4607 bcd4933a Nathan Froyd
    /* Create a stack frame for the caller of the handler.  */
4608 bcd4933a Nathan Froyd
    newsp = frame_addr - SIGNAL_FRAMESIZE;
4609 bcd4933a Nathan Froyd
    err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
4610 bcd4933a Nathan Froyd
4611 bcd4933a Nathan Froyd
    if (err)
4612 bcd4933a Nathan Froyd
        goto sigsegv;
4613 bcd4933a Nathan Froyd
4614 bcd4933a Nathan Froyd
    /* Set up registers for signal handler.  */
4615 bcd4933a Nathan Froyd
    env->gpr[1] = newsp;
4616 bcd4933a Nathan Froyd
    env->gpr[3] = signal;
4617 bcd4933a Nathan Froyd
    env->gpr[4] = (target_ulong) h2g(sc);
4618 bcd4933a Nathan Froyd
    env->nip = (target_ulong) ka->_sa_handler;
4619 bcd4933a Nathan Froyd
    /* Signal handlers are entered in big-endian mode.  */
4620 bcd4933a Nathan Froyd
    env->msr &= ~MSR_LE;
4621 bcd4933a Nathan Froyd
4622 bcd4933a Nathan Froyd
    unlock_user_struct(frame, frame_addr, 1);
4623 bcd4933a Nathan Froyd
    return;
4624 bcd4933a Nathan Froyd
4625 bcd4933a Nathan Froyd
sigsegv:
4626 bcd4933a Nathan Froyd
    unlock_user_struct(frame, frame_addr, 1);
4627 eeacee4d Blue Swirl
    qemu_log("segfaulting from setup_frame\n");
4628 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4629 bcd4933a Nathan Froyd
}
4630 bcd4933a Nathan Froyd
4631 bcd4933a Nathan Froyd
static void setup_rt_frame(int sig, struct target_sigaction *ka,
4632 c227f099 Anthony Liguori
                           target_siginfo_t *info,
4633 05390248 Andreas Färber
                           target_sigset_t *set, CPUPPCState *env)
4634 bcd4933a Nathan Froyd
{
4635 bcd4933a Nathan Froyd
    struct target_rt_sigframe *rt_sf;
4636 bcd4933a Nathan Froyd
    struct target_mcontext *frame;
4637 bcd4933a Nathan Froyd
    target_ulong rt_sf_addr, newsp = 0;
4638 bcd4933a Nathan Froyd
    int i, err = 0;
4639 bcd4933a Nathan Froyd
    int signal;
4640 bcd4933a Nathan Froyd
4641 bcd4933a Nathan Froyd
    rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
4642 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
4643 bcd4933a Nathan Froyd
        goto sigsegv;
4644 bcd4933a Nathan Froyd
4645 bcd4933a Nathan Froyd
    signal = current_exec_domain_sig(sig);
4646 bcd4933a Nathan Froyd
4647 bcd4933a Nathan Froyd
    err |= copy_siginfo_to_user(&rt_sf->info, info);
4648 bcd4933a Nathan Froyd
4649 60e99246 Aurelien Jarno
    err |= __put_user(0, &rt_sf->uc.tuc_flags);
4650 60e99246 Aurelien Jarno
    err |= __put_user(0, &rt_sf->uc.tuc_link);
4651 bcd4933a Nathan Froyd
    err |= __put_user((target_ulong)target_sigaltstack_used.ss_sp,
4652 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_stack.ss_sp);
4653 bcd4933a Nathan Froyd
    err |= __put_user(sas_ss_flags(env->gpr[1]),
4654 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_stack.ss_flags);
4655 bcd4933a Nathan Froyd
    err |= __put_user(target_sigaltstack_used.ss_size,
4656 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_stack.ss_size);
4657 60e99246 Aurelien Jarno
    err |= __put_user(h2g (&rt_sf->uc.tuc_mcontext),
4658 60e99246 Aurelien Jarno
                      &rt_sf->uc.tuc_regs);
4659 bcd4933a Nathan Froyd
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
4660 60e99246 Aurelien Jarno
        err |= __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]);
4661 bcd4933a Nathan Froyd
    }
4662 bcd4933a Nathan Froyd
4663 60e99246 Aurelien Jarno
    frame = &rt_sf->uc.tuc_mcontext;
4664 bcd4933a Nathan Froyd
    err |= save_user_regs(env, frame, TARGET_NR_rt_sigreturn);
4665 bcd4933a Nathan Froyd
4666 bcd4933a Nathan Froyd
    /* The kernel checks for the presence of a VDSO here.  We don't
4667 bcd4933a Nathan Froyd
       emulate a vdso, so use a sigreturn system call.  */
4668 bcd4933a Nathan Froyd
    env->lr = (target_ulong) h2g(frame->tramp);
4669 bcd4933a Nathan Froyd
4670 bcd4933a Nathan Froyd
    /* Turn off all fp exceptions.  */
4671 bcd4933a Nathan Froyd
    env->fpscr = 0;
4672 bcd4933a Nathan Froyd
4673 bcd4933a Nathan Froyd
    /* Create a stack frame for the caller of the handler.  */
4674 bcd4933a Nathan Froyd
    newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
4675 bcd4933a Nathan Froyd
    err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
4676 bcd4933a Nathan Froyd
4677 bcd4933a Nathan Froyd
    if (err)
4678 bcd4933a Nathan Froyd
        goto sigsegv;
4679 bcd4933a Nathan Froyd
4680 bcd4933a Nathan Froyd
    /* Set up registers for signal handler.  */
4681 bcd4933a Nathan Froyd
    env->gpr[1] = newsp;
4682 bcd4933a Nathan Froyd
    env->gpr[3] = (target_ulong) signal;
4683 bcd4933a Nathan Froyd
    env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
4684 bcd4933a Nathan Froyd
    env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
4685 bcd4933a Nathan Froyd
    env->gpr[6] = (target_ulong) h2g(rt_sf);
4686 bcd4933a Nathan Froyd
    env->nip = (target_ulong) ka->_sa_handler;
4687 bcd4933a Nathan Froyd
    /* Signal handlers are entered in big-endian mode.  */
4688 bcd4933a Nathan Froyd
    env->msr &= ~MSR_LE;
4689 bcd4933a Nathan Froyd
4690 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4691 bcd4933a Nathan Froyd
    return;
4692 bcd4933a Nathan Froyd
4693 bcd4933a Nathan Froyd
sigsegv:
4694 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4695 eeacee4d Blue Swirl
    qemu_log("segfaulting from setup_rt_frame\n");
4696 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4697 bcd4933a Nathan Froyd
4698 bcd4933a Nathan Froyd
}
4699 bcd4933a Nathan Froyd
4700 05390248 Andreas Färber
long do_sigreturn(CPUPPCState *env)
4701 bcd4933a Nathan Froyd
{
4702 bcd4933a Nathan Froyd
    struct target_sigcontext *sc = NULL;
4703 bcd4933a Nathan Froyd
    struct target_mcontext *sr = NULL;
4704 bcd4933a Nathan Froyd
    target_ulong sr_addr, sc_addr;
4705 bcd4933a Nathan Froyd
    sigset_t blocked;
4706 c227f099 Anthony Liguori
    target_sigset_t set;
4707 bcd4933a Nathan Froyd
4708 bcd4933a Nathan Froyd
    sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
4709 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
4710 bcd4933a Nathan Froyd
        goto sigsegv;
4711 bcd4933a Nathan Froyd
4712 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4713 bcd4933a Nathan Froyd
    set.sig[0] = sc->oldmask + ((long)(sc->_unused[3]) << 32);
4714 bcd4933a Nathan Froyd
#else
4715 bcd4933a Nathan Froyd
    if(__get_user(set.sig[0], &sc->oldmask) ||
4716 bcd4933a Nathan Froyd
       __get_user(set.sig[1], &sc->_unused[3]))
4717 bcd4933a Nathan Froyd
       goto sigsegv;
4718 bcd4933a Nathan Froyd
#endif
4719 bcd4933a Nathan Froyd
    target_to_host_sigset_internal(&blocked, &set);
4720 bcd4933a Nathan Froyd
    sigprocmask(SIG_SETMASK, &blocked, NULL);
4721 bcd4933a Nathan Froyd
4722 bcd4933a Nathan Froyd
    if (__get_user(sr_addr, &sc->regs))
4723 bcd4933a Nathan Froyd
        goto sigsegv;
4724 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
4725 bcd4933a Nathan Froyd
        goto sigsegv;
4726 bcd4933a Nathan Froyd
    if (restore_user_regs(env, sr, 1))
4727 bcd4933a Nathan Froyd
        goto sigsegv;
4728 bcd4933a Nathan Froyd
4729 bcd4933a Nathan Froyd
    unlock_user_struct(sr, sr_addr, 1);
4730 bcd4933a Nathan Froyd
    unlock_user_struct(sc, sc_addr, 1);
4731 bcd4933a Nathan Froyd
    return -TARGET_QEMU_ESIGRETURN;
4732 bcd4933a Nathan Froyd
4733 bcd4933a Nathan Froyd
sigsegv:
4734 bcd4933a Nathan Froyd
    unlock_user_struct(sr, sr_addr, 1);
4735 bcd4933a Nathan Froyd
    unlock_user_struct(sc, sc_addr, 1);
4736 eeacee4d Blue Swirl
    qemu_log("segfaulting from do_sigreturn\n");
4737 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4738 bcd4933a Nathan Froyd
    return 0;
4739 bcd4933a Nathan Froyd
}
4740 bcd4933a Nathan Froyd
4741 bcd4933a Nathan Froyd
/* See arch/powerpc/kernel/signal_32.c.  */
4742 05390248 Andreas Färber
static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
4743 bcd4933a Nathan Froyd
{
4744 bcd4933a Nathan Froyd
    struct target_mcontext *mcp;
4745 bcd4933a Nathan Froyd
    target_ulong mcp_addr;
4746 bcd4933a Nathan Froyd
    sigset_t blocked;
4747 c227f099 Anthony Liguori
    target_sigset_t set;
4748 bcd4933a Nathan Froyd
4749 60e99246 Aurelien Jarno
    if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask),
4750 bcd4933a Nathan Froyd
                       sizeof (set)))
4751 bcd4933a Nathan Froyd
        return 1;
4752 bcd4933a Nathan Froyd
4753 bcd4933a Nathan Froyd
#if defined(TARGET_PPC64)
4754 bcd4933a Nathan Froyd
    fprintf (stderr, "do_setcontext: not implemented\n");
4755 bcd4933a Nathan Froyd
    return 0;
4756 bcd4933a Nathan Froyd
#else
4757 60e99246 Aurelien Jarno
    if (__get_user(mcp_addr, &ucp->tuc_regs))
4758 bcd4933a Nathan Froyd
        return 1;
4759 bcd4933a Nathan Froyd
4760 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
4761 bcd4933a Nathan Froyd
        return 1;
4762 bcd4933a Nathan Froyd
4763 bcd4933a Nathan Froyd
    target_to_host_sigset_internal(&blocked, &set);
4764 bcd4933a Nathan Froyd
    sigprocmask(SIG_SETMASK, &blocked, NULL);
4765 bcd4933a Nathan Froyd
    if (restore_user_regs(env, mcp, sig))
4766 bcd4933a Nathan Froyd
        goto sigsegv;
4767 bcd4933a Nathan Froyd
4768 bcd4933a Nathan Froyd
    unlock_user_struct(mcp, mcp_addr, 1);
4769 bcd4933a Nathan Froyd
    return 0;
4770 bcd4933a Nathan Froyd
4771 bcd4933a Nathan Froyd
sigsegv:
4772 bcd4933a Nathan Froyd
    unlock_user_struct(mcp, mcp_addr, 1);
4773 bcd4933a Nathan Froyd
    return 1;
4774 bcd4933a Nathan Froyd
#endif
4775 bcd4933a Nathan Froyd
}
4776 bcd4933a Nathan Froyd
4777 05390248 Andreas Färber
long do_rt_sigreturn(CPUPPCState *env)
4778 bcd4933a Nathan Froyd
{
4779 bcd4933a Nathan Froyd
    struct target_rt_sigframe *rt_sf = NULL;
4780 bcd4933a Nathan Froyd
    target_ulong rt_sf_addr;
4781 bcd4933a Nathan Froyd
4782 bcd4933a Nathan Froyd
    rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
4783 bcd4933a Nathan Froyd
    if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
4784 bcd4933a Nathan Froyd
        goto sigsegv;
4785 bcd4933a Nathan Froyd
4786 bcd4933a Nathan Froyd
    if (do_setcontext(&rt_sf->uc, env, 1))
4787 bcd4933a Nathan Froyd
        goto sigsegv;
4788 bcd4933a Nathan Froyd
4789 bcd4933a Nathan Froyd
    do_sigaltstack(rt_sf_addr
4790 60e99246 Aurelien Jarno
                   + offsetof(struct target_rt_sigframe, uc.tuc_stack),
4791 bcd4933a Nathan Froyd
                   0, env->gpr[1]);
4792 bcd4933a Nathan Froyd
4793 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4794 bcd4933a Nathan Froyd
    return -TARGET_QEMU_ESIGRETURN;
4795 bcd4933a Nathan Froyd
4796 bcd4933a Nathan Froyd
sigsegv:
4797 bcd4933a Nathan Froyd
    unlock_user_struct(rt_sf, rt_sf_addr, 1);
4798 eeacee4d Blue Swirl
    qemu_log("segfaulting from do_rt_sigreturn\n");
4799 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4800 bcd4933a Nathan Froyd
    return 0;
4801 bcd4933a Nathan Froyd
}
4802 bcd4933a Nathan Froyd
4803 492a8744 Laurent Vivier
#elif defined(TARGET_M68K)
4804 492a8744 Laurent Vivier
4805 492a8744 Laurent Vivier
struct target_sigcontext {
4806 492a8744 Laurent Vivier
    abi_ulong  sc_mask;
4807 492a8744 Laurent Vivier
    abi_ulong  sc_usp;
4808 492a8744 Laurent Vivier
    abi_ulong  sc_d0;
4809 492a8744 Laurent Vivier
    abi_ulong  sc_d1;
4810 492a8744 Laurent Vivier
    abi_ulong  sc_a0;
4811 492a8744 Laurent Vivier
    abi_ulong  sc_a1;
4812 492a8744 Laurent Vivier
    unsigned short sc_sr;
4813 492a8744 Laurent Vivier
    abi_ulong  sc_pc;
4814 492a8744 Laurent Vivier
};
4815 492a8744 Laurent Vivier
4816 492a8744 Laurent Vivier
struct target_sigframe
4817 492a8744 Laurent Vivier
{
4818 492a8744 Laurent Vivier
    abi_ulong pretcode;
4819 492a8744 Laurent Vivier
    int sig;
4820 492a8744 Laurent Vivier
    int code;
4821 492a8744 Laurent Vivier
    abi_ulong psc;
4822 492a8744 Laurent Vivier
    char retcode[8];
4823 492a8744 Laurent Vivier
    abi_ulong extramask[TARGET_NSIG_WORDS-1];
4824 492a8744 Laurent Vivier
    struct target_sigcontext sc;
4825 492a8744 Laurent Vivier
};
4826 7181155d Laurent Vivier
 
4827 c227f099 Anthony Liguori
typedef int target_greg_t;
4828 7181155d Laurent Vivier
#define TARGET_NGREG 18
4829 c227f099 Anthony Liguori
typedef target_greg_t target_gregset_t[TARGET_NGREG];
4830 7181155d Laurent Vivier
4831 7181155d Laurent Vivier
typedef struct target_fpregset {
4832 7181155d Laurent Vivier
    int f_fpcntl[3];
4833 7181155d Laurent Vivier
    int f_fpregs[8*3];
4834 c227f099 Anthony Liguori
} target_fpregset_t;
4835 7181155d Laurent Vivier
4836 7181155d Laurent Vivier
struct target_mcontext {
4837 7181155d Laurent Vivier
    int version;
4838 c227f099 Anthony Liguori
    target_gregset_t gregs;
4839 c227f099 Anthony Liguori
    target_fpregset_t fpregs;
4840 7181155d Laurent Vivier
};
4841 7181155d Laurent Vivier
4842 7181155d Laurent Vivier
#define TARGET_MCONTEXT_VERSION 2
4843 7181155d Laurent Vivier
4844 7181155d Laurent Vivier
struct target_ucontext {
4845 60e99246 Aurelien Jarno
    abi_ulong tuc_flags;
4846 60e99246 Aurelien Jarno
    abi_ulong tuc_link;
4847 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
4848 60e99246 Aurelien Jarno
    struct target_mcontext tuc_mcontext;
4849 60e99246 Aurelien Jarno
    abi_long tuc_filler[80];
4850 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
4851 7181155d Laurent Vivier
};
4852 7181155d Laurent Vivier
4853 7181155d Laurent Vivier
struct target_rt_sigframe
4854 7181155d Laurent Vivier
{
4855 7181155d Laurent Vivier
    abi_ulong pretcode;
4856 7181155d Laurent Vivier
    int sig;
4857 7181155d Laurent Vivier
    abi_ulong pinfo;
4858 7181155d Laurent Vivier
    abi_ulong puc;
4859 7181155d Laurent Vivier
    char retcode[8];
4860 7181155d Laurent Vivier
    struct target_siginfo info;
4861 7181155d Laurent Vivier
    struct target_ucontext uc;
4862 7181155d Laurent Vivier
};
4863 492a8744 Laurent Vivier
4864 492a8744 Laurent Vivier
static int
4865 05390248 Andreas Färber
setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
4866 05390248 Andreas Färber
                 abi_ulong mask)
4867 492a8744 Laurent Vivier
{
4868 492a8744 Laurent Vivier
    int err = 0;
4869 492a8744 Laurent Vivier
4870 492a8744 Laurent Vivier
    err |= __put_user(mask, &sc->sc_mask);
4871 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[7], &sc->sc_usp);
4872 492a8744 Laurent Vivier
    err |= __put_user(env->dregs[0], &sc->sc_d0);
4873 492a8744 Laurent Vivier
    err |= __put_user(env->dregs[1], &sc->sc_d1);
4874 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[0], &sc->sc_a0);
4875 492a8744 Laurent Vivier
    err |= __put_user(env->aregs[1], &sc->sc_a1);
4876 492a8744 Laurent Vivier
    err |= __put_user(env->sr, &sc->sc_sr);
4877 492a8744 Laurent Vivier
    err |= __put_user(env->pc, &sc->sc_pc);
4878 492a8744 Laurent Vivier
4879 492a8744 Laurent Vivier
    return err;
4880 492a8744 Laurent Vivier
}
4881 492a8744 Laurent Vivier
4882 492a8744 Laurent Vivier
static int
4883 05390248 Andreas Färber
restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0)
4884 492a8744 Laurent Vivier
{
4885 492a8744 Laurent Vivier
    int err = 0;
4886 492a8744 Laurent Vivier
    int temp;
4887 492a8744 Laurent Vivier
4888 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[7], &sc->sc_usp);
4889 492a8744 Laurent Vivier
    err |= __get_user(env->dregs[1], &sc->sc_d1);
4890 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[0], &sc->sc_a0);
4891 492a8744 Laurent Vivier
    err |= __get_user(env->aregs[1], &sc->sc_a1);
4892 492a8744 Laurent Vivier
    err |= __get_user(env->pc, &sc->sc_pc);
4893 492a8744 Laurent Vivier
    err |= __get_user(temp, &sc->sc_sr);
4894 492a8744 Laurent Vivier
    env->sr = (env->sr & 0xff00) | (temp & 0xff);
4895 492a8744 Laurent Vivier
4896 492a8744 Laurent Vivier
    *pd0 = tswapl(sc->sc_d0);
4897 492a8744 Laurent Vivier
4898 492a8744 Laurent Vivier
    return err;
4899 492a8744 Laurent Vivier
}
4900 492a8744 Laurent Vivier
4901 492a8744 Laurent Vivier
/*
4902 492a8744 Laurent Vivier
 * Determine which stack to use..
4903 492a8744 Laurent Vivier
 */
4904 492a8744 Laurent Vivier
static inline abi_ulong
4905 05390248 Andreas Färber
get_sigframe(struct target_sigaction *ka, CPUM68KState *regs,
4906 05390248 Andreas Färber
             size_t frame_size)
4907 492a8744 Laurent Vivier
{
4908 492a8744 Laurent Vivier
    unsigned long sp;
4909 492a8744 Laurent Vivier
4910 492a8744 Laurent Vivier
    sp = regs->aregs[7];
4911 492a8744 Laurent Vivier
4912 492a8744 Laurent Vivier
    /* This is the X/Open sanctioned signal stack switching.  */
4913 492a8744 Laurent Vivier
    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
4914 492a8744 Laurent Vivier
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
4915 492a8744 Laurent Vivier
    }
4916 492a8744 Laurent Vivier
4917 492a8744 Laurent Vivier
    return ((sp - frame_size) & -8UL);
4918 492a8744 Laurent Vivier
}
4919 492a8744 Laurent Vivier
4920 492a8744 Laurent Vivier
static void setup_frame(int sig, struct target_sigaction *ka,
4921 05390248 Andreas Färber
                        target_sigset_t *set, CPUM68KState *env)
4922 492a8744 Laurent Vivier
{
4923 492a8744 Laurent Vivier
    struct target_sigframe *frame;
4924 492a8744 Laurent Vivier
    abi_ulong frame_addr;
4925 492a8744 Laurent Vivier
    abi_ulong retcode_addr;
4926 492a8744 Laurent Vivier
    abi_ulong sc_addr;
4927 492a8744 Laurent Vivier
    int err = 0;
4928 492a8744 Laurent Vivier
    int i;
4929 492a8744 Laurent Vivier
4930 492a8744 Laurent Vivier
    frame_addr = get_sigframe(ka, env, sizeof *frame);
4931 492a8744 Laurent Vivier
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
4932 492a8744 Laurent Vivier
        goto give_sigsegv;
4933 492a8744 Laurent Vivier
4934 492a8744 Laurent Vivier
    err |= __put_user(sig, &frame->sig);
4935 492a8744 Laurent Vivier
4936 492a8744 Laurent Vivier
    sc_addr = frame_addr + offsetof(struct target_sigframe, sc);
4937 492a8744 Laurent Vivier
    err |= __put_user(sc_addr, &frame->psc);
4938 492a8744 Laurent Vivier
4939 492a8744 Laurent Vivier
    err |= setup_sigcontext(&frame->sc, env, set->sig[0]);
4940 492a8744 Laurent Vivier
    if (err)
4941 492a8744 Laurent Vivier
        goto give_sigsegv;
4942 492a8744 Laurent Vivier
4943 492a8744 Laurent Vivier
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
4944 492a8744 Laurent Vivier
        if (__put_user(set->sig[i], &frame->extramask[i - 1]))
4945 492a8744 Laurent Vivier
            goto give_sigsegv;
4946 492a8744 Laurent Vivier
    }
4947 492a8744 Laurent Vivier
4948 492a8744 Laurent Vivier
    /* Set up to return from userspace.  */
4949 492a8744 Laurent Vivier
4950 492a8744 Laurent Vivier
    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
4951 492a8744 Laurent Vivier
    err |= __put_user(retcode_addr, &frame->pretcode);
4952 492a8744 Laurent Vivier
4953 492a8744 Laurent Vivier
    /* moveq #,d0; trap #0 */
4954 492a8744 Laurent Vivier
4955 492a8744 Laurent Vivier
    err |= __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
4956 492a8744 Laurent Vivier
                      (long *)(frame->retcode));
4957 492a8744 Laurent Vivier
4958 492a8744 Laurent Vivier
    if (err)
4959 492a8744 Laurent Vivier
        goto give_sigsegv;
4960 492a8744 Laurent Vivier
4961 492a8744 Laurent Vivier
    /* Set up to return from userspace */
4962 492a8744 Laurent Vivier
4963 492a8744 Laurent Vivier
    env->aregs[7] = frame_addr;
4964 492a8744 Laurent Vivier
    env->pc = ka->_sa_handler;
4965 492a8744 Laurent Vivier
4966 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4967 492a8744 Laurent Vivier
    return;
4968 492a8744 Laurent Vivier
4969 492a8744 Laurent Vivier
give_sigsegv:
4970 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
4971 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
4972 492a8744 Laurent Vivier
}
4973 492a8744 Laurent Vivier
4974 7181155d Laurent Vivier
static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
4975 05390248 Andreas Färber
                                           CPUM68KState *env)
4976 7181155d Laurent Vivier
{
4977 60e99246 Aurelien Jarno
    target_greg_t *gregs = uc->tuc_mcontext.gregs;
4978 7181155d Laurent Vivier
    int err;
4979 7181155d Laurent Vivier
4980 60e99246 Aurelien Jarno
    err = __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
4981 7181155d Laurent Vivier
    err |= __put_user(env->dregs[0], &gregs[0]);
4982 7181155d Laurent Vivier
    err |= __put_user(env->dregs[1], &gregs[1]);
4983 7181155d Laurent Vivier
    err |= __put_user(env->dregs[2], &gregs[2]);
4984 7181155d Laurent Vivier
    err |= __put_user(env->dregs[3], &gregs[3]);
4985 7181155d Laurent Vivier
    err |= __put_user(env->dregs[4], &gregs[4]);
4986 7181155d Laurent Vivier
    err |= __put_user(env->dregs[5], &gregs[5]);
4987 7181155d Laurent Vivier
    err |= __put_user(env->dregs[6], &gregs[6]);
4988 7181155d Laurent Vivier
    err |= __put_user(env->dregs[7], &gregs[7]);
4989 7181155d Laurent Vivier
    err |= __put_user(env->aregs[0], &gregs[8]);
4990 7181155d Laurent Vivier
    err |= __put_user(env->aregs[1], &gregs[9]);
4991 7181155d Laurent Vivier
    err |= __put_user(env->aregs[2], &gregs[10]);
4992 7181155d Laurent Vivier
    err |= __put_user(env->aregs[3], &gregs[11]);
4993 7181155d Laurent Vivier
    err |= __put_user(env->aregs[4], &gregs[12]);
4994 7181155d Laurent Vivier
    err |= __put_user(env->aregs[5], &gregs[13]);
4995 7181155d Laurent Vivier
    err |= __put_user(env->aregs[6], &gregs[14]);
4996 7181155d Laurent Vivier
    err |= __put_user(env->aregs[7], &gregs[15]);
4997 7181155d Laurent Vivier
    err |= __put_user(env->pc, &gregs[16]);
4998 7181155d Laurent Vivier
    err |= __put_user(env->sr, &gregs[17]);
4999 7181155d Laurent Vivier
5000 7181155d Laurent Vivier
    return err;
5001 7181155d Laurent Vivier
}
5002 7181155d Laurent Vivier
 
5003 05390248 Andreas Färber
static inline int target_rt_restore_ucontext(CPUM68KState *env,
5004 7181155d Laurent Vivier
                                             struct target_ucontext *uc,
5005 7181155d Laurent Vivier
                                             int *pd0)
5006 7181155d Laurent Vivier
{
5007 7181155d Laurent Vivier
    int temp;
5008 7181155d Laurent Vivier
    int err;
5009 60e99246 Aurelien Jarno
    target_greg_t *gregs = uc->tuc_mcontext.gregs;
5010 7181155d Laurent Vivier
    
5011 60e99246 Aurelien Jarno
    err = __get_user(temp, &uc->tuc_mcontext.version);
5012 7181155d Laurent Vivier
    if (temp != TARGET_MCONTEXT_VERSION)
5013 7181155d Laurent Vivier
        goto badframe;
5014 7181155d Laurent Vivier
5015 7181155d Laurent Vivier
    /* restore passed registers */
5016 7181155d Laurent Vivier
    err |= __get_user(env->dregs[0], &gregs[0]);
5017 7181155d Laurent Vivier
    err |= __get_user(env->dregs[1], &gregs[1]);
5018 7181155d Laurent Vivier
    err |= __get_user(env->dregs[2], &gregs[2]);
5019 7181155d Laurent Vivier
    err |= __get_user(env->dregs[3], &gregs[3]);
5020 7181155d Laurent Vivier
    err |= __get_user(env->dregs[4], &gregs[4]);
5021 7181155d Laurent Vivier
    err |= __get_user(env->dregs[5], &gregs[5]);
5022 7181155d Laurent Vivier
    err |= __get_user(env->dregs[6], &gregs[6]);
5023 7181155d Laurent Vivier
    err |= __get_user(env->dregs[7], &gregs[7]);
5024 7181155d Laurent Vivier
    err |= __get_user(env->aregs[0], &gregs[8]);
5025 7181155d Laurent Vivier
    err |= __get_user(env->aregs[1], &gregs[9]);
5026 7181155d Laurent Vivier
    err |= __get_user(env->aregs[2], &gregs[10]);
5027 7181155d Laurent Vivier
    err |= __get_user(env->aregs[3], &gregs[11]);
5028 7181155d Laurent Vivier
    err |= __get_user(env->aregs[4], &gregs[12]);
5029 7181155d Laurent Vivier
    err |= __get_user(env->aregs[5], &gregs[13]);
5030 7181155d Laurent Vivier
    err |= __get_user(env->aregs[6], &gregs[14]);
5031 7181155d Laurent Vivier
    err |= __get_user(env->aregs[7], &gregs[15]);
5032 7181155d Laurent Vivier
    err |= __get_user(env->pc, &gregs[16]);
5033 7181155d Laurent Vivier
    err |= __get_user(temp, &gregs[17]);
5034 7181155d Laurent Vivier
    env->sr = (env->sr & 0xff00) | (temp & 0xff);
5035 7181155d Laurent Vivier
5036 7181155d Laurent Vivier
    *pd0 = env->dregs[0];
5037 7181155d Laurent Vivier
    return err;
5038 7181155d Laurent Vivier
5039 7181155d Laurent Vivier
badframe:
5040 7181155d Laurent Vivier
    return 1;
5041 7181155d Laurent Vivier
}
5042 7181155d Laurent Vivier
5043 492a8744 Laurent Vivier
static void setup_rt_frame(int sig, struct target_sigaction *ka,
5044 c227f099 Anthony Liguori
                           target_siginfo_t *info,
5045 05390248 Andreas Färber
                           target_sigset_t *set, CPUM68KState *env)
5046 492a8744 Laurent Vivier
{
5047 7181155d Laurent Vivier
    struct target_rt_sigframe *frame;
5048 7181155d Laurent Vivier
    abi_ulong frame_addr;
5049 7181155d Laurent Vivier
    abi_ulong retcode_addr;
5050 7181155d Laurent Vivier
    abi_ulong info_addr;
5051 7181155d Laurent Vivier
    abi_ulong uc_addr;
5052 7181155d Laurent Vivier
    int err = 0;
5053 7181155d Laurent Vivier
    int i;
5054 7181155d Laurent Vivier
5055 7181155d Laurent Vivier
    frame_addr = get_sigframe(ka, env, sizeof *frame);
5056 7181155d Laurent Vivier
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
5057 7181155d Laurent Vivier
        goto give_sigsegv;
5058 7181155d Laurent Vivier
5059 7181155d Laurent Vivier
    err |= __put_user(sig, &frame->sig);
5060 7181155d Laurent Vivier
5061 7181155d Laurent Vivier
    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);
5062 7181155d Laurent Vivier
    err |= __put_user(info_addr, &frame->pinfo);
5063 7181155d Laurent Vivier
5064 7181155d Laurent Vivier
    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);
5065 7181155d Laurent Vivier
    err |= __put_user(uc_addr, &frame->puc);
5066 7181155d Laurent Vivier
5067 7181155d Laurent Vivier
    err |= copy_siginfo_to_user(&frame->info, info);
5068 7181155d Laurent Vivier
5069 7181155d Laurent Vivier
    /* Create the ucontext */
5070 7181155d Laurent Vivier
5071 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_flags);
5072 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_link);
5073 7181155d Laurent Vivier
    err |= __put_user(target_sigaltstack_used.ss_sp,
5074 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_sp);
5075 7181155d Laurent Vivier
    err |= __put_user(sas_ss_flags(env->aregs[7]),
5076 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_flags);
5077 7181155d Laurent Vivier
    err |= __put_user(target_sigaltstack_used.ss_size,
5078 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_size);
5079 7181155d Laurent Vivier
    err |= target_rt_setup_ucontext(&frame->uc, env);
5080 7181155d Laurent Vivier
5081 7181155d Laurent Vivier
    if (err)
5082 7181155d Laurent Vivier
            goto give_sigsegv;
5083 7181155d Laurent Vivier
5084 7181155d Laurent Vivier
    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
5085 60e99246 Aurelien Jarno
        if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
5086 7181155d Laurent Vivier
            goto give_sigsegv;
5087 7181155d Laurent Vivier
    }
5088 7181155d Laurent Vivier
5089 7181155d Laurent Vivier
    /* Set up to return from userspace.  */
5090 7181155d Laurent Vivier
5091 7181155d Laurent Vivier
    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
5092 7181155d Laurent Vivier
    err |= __put_user(retcode_addr, &frame->pretcode);
5093 7181155d Laurent Vivier
5094 7181155d Laurent Vivier
    /* moveq #,d0; notb d0; trap #0 */
5095 7181155d Laurent Vivier
5096 7181155d Laurent Vivier
    err |= __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
5097 7181155d Laurent Vivier
                      (long *)(frame->retcode + 0));
5098 7181155d Laurent Vivier
    err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
5099 7181155d Laurent Vivier
5100 7181155d Laurent Vivier
    if (err)
5101 7181155d Laurent Vivier
        goto give_sigsegv;
5102 7181155d Laurent Vivier
5103 7181155d Laurent Vivier
    /* Set up to return from userspace */
5104 7181155d Laurent Vivier
5105 7181155d Laurent Vivier
    env->aregs[7] = frame_addr;
5106 7181155d Laurent Vivier
    env->pc = ka->_sa_handler;
5107 7181155d Laurent Vivier
5108 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
5109 7181155d Laurent Vivier
    return;
5110 7181155d Laurent Vivier
5111 7181155d Laurent Vivier
give_sigsegv:
5112 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 1);
5113 66393fb9 Riku Voipio
    force_sig(TARGET_SIGSEGV);
5114 492a8744 Laurent Vivier
}
5115 492a8744 Laurent Vivier
5116 05390248 Andreas Färber
long do_sigreturn(CPUM68KState *env)
5117 492a8744 Laurent Vivier
{
5118 492a8744 Laurent Vivier
    struct target_sigframe *frame;
5119 492a8744 Laurent Vivier
    abi_ulong frame_addr = env->aregs[7] - 4;
5120 c227f099 Anthony Liguori
    target_sigset_t target_set;
5121 492a8744 Laurent Vivier
    sigset_t set;
5122 492a8744 Laurent Vivier
    int d0, i;
5123 492a8744 Laurent Vivier
5124 492a8744 Laurent Vivier
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5125 492a8744 Laurent Vivier
        goto badframe;
5126 492a8744 Laurent Vivier
5127 492a8744 Laurent Vivier
    /* set blocked signals */
5128 492a8744 Laurent Vivier
5129 492a8744 Laurent Vivier
    if (__get_user(target_set.sig[0], &frame->sc.sc_mask))
5130 492a8744 Laurent Vivier
        goto badframe;
5131 492a8744 Laurent Vivier
5132 492a8744 Laurent Vivier
    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
5133 492a8744 Laurent Vivier
        if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
5134 492a8744 Laurent Vivier
            goto badframe;
5135 492a8744 Laurent Vivier
    }
5136 492a8744 Laurent Vivier
5137 492a8744 Laurent Vivier
    target_to_host_sigset_internal(&set, &target_set);
5138 492a8744 Laurent Vivier
    sigprocmask(SIG_SETMASK, &set, NULL);
5139 492a8744 Laurent Vivier
5140 492a8744 Laurent Vivier
    /* restore registers */
5141 492a8744 Laurent Vivier
5142 492a8744 Laurent Vivier
    if (restore_sigcontext(env, &frame->sc, &d0))
5143 492a8744 Laurent Vivier
        goto badframe;
5144 492a8744 Laurent Vivier
5145 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
5146 492a8744 Laurent Vivier
    return d0;
5147 492a8744 Laurent Vivier
5148 492a8744 Laurent Vivier
badframe:
5149 492a8744 Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
5150 492a8744 Laurent Vivier
    force_sig(TARGET_SIGSEGV);
5151 492a8744 Laurent Vivier
    return 0;
5152 492a8744 Laurent Vivier
}
5153 492a8744 Laurent Vivier
5154 05390248 Andreas Färber
long do_rt_sigreturn(CPUM68KState *env)
5155 492a8744 Laurent Vivier
{
5156 7181155d Laurent Vivier
    struct target_rt_sigframe *frame;
5157 7181155d Laurent Vivier
    abi_ulong frame_addr = env->aregs[7] - 4;
5158 c227f099 Anthony Liguori
    target_sigset_t target_set;
5159 7181155d Laurent Vivier
    sigset_t set;
5160 7181155d Laurent Vivier
    int d0;
5161 7181155d Laurent Vivier
5162 7181155d Laurent Vivier
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
5163 7181155d Laurent Vivier
        goto badframe;
5164 7181155d Laurent Vivier
5165 7181155d Laurent Vivier
    target_to_host_sigset_internal(&set, &target_set);
5166 7181155d Laurent Vivier
    sigprocmask(SIG_SETMASK, &set, NULL);
5167 7181155d Laurent Vivier
5168 7181155d Laurent Vivier
    /* restore registers */
5169 7181155d Laurent Vivier
5170 7181155d Laurent Vivier
    if (target_rt_restore_ucontext(env, &frame->uc, &d0))
5171 7181155d Laurent Vivier
        goto badframe;
5172 7181155d Laurent Vivier
5173 7181155d Laurent Vivier
    if (do_sigaltstack(frame_addr +
5174 60e99246 Aurelien Jarno
                       offsetof(struct target_rt_sigframe, uc.tuc_stack),
5175 7181155d Laurent Vivier
                       0, get_sp_from_cpustate(env)) == -EFAULT)
5176 7181155d Laurent Vivier
        goto badframe;
5177 7181155d Laurent Vivier
5178 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
5179 7181155d Laurent Vivier
    return d0;
5180 7181155d Laurent Vivier
5181 7181155d Laurent Vivier
badframe:
5182 7181155d Laurent Vivier
    unlock_user_struct(frame, frame_addr, 0);
5183 7181155d Laurent Vivier
    force_sig(TARGET_SIGSEGV);
5184 7181155d Laurent Vivier
    return 0;
5185 492a8744 Laurent Vivier
}
5186 492a8744 Laurent Vivier
5187 6049f4f8 Richard Henderson
#elif defined(TARGET_ALPHA)
5188 6049f4f8 Richard Henderson
5189 6049f4f8 Richard Henderson
struct target_sigcontext {
5190 6049f4f8 Richard Henderson
    abi_long sc_onstack;
5191 6049f4f8 Richard Henderson
    abi_long sc_mask;
5192 6049f4f8 Richard Henderson
    abi_long sc_pc;
5193 6049f4f8 Richard Henderson
    abi_long sc_ps;
5194 6049f4f8 Richard Henderson
    abi_long sc_regs[32];
5195 6049f4f8 Richard Henderson
    abi_long sc_ownedfp;
5196 6049f4f8 Richard Henderson
    abi_long sc_fpregs[32];
5197 6049f4f8 Richard Henderson
    abi_ulong sc_fpcr;
5198 6049f4f8 Richard Henderson
    abi_ulong sc_fp_control;
5199 6049f4f8 Richard Henderson
    abi_ulong sc_reserved1;
5200 6049f4f8 Richard Henderson
    abi_ulong sc_reserved2;
5201 6049f4f8 Richard Henderson
    abi_ulong sc_ssize;
5202 6049f4f8 Richard Henderson
    abi_ulong sc_sbase;
5203 6049f4f8 Richard Henderson
    abi_ulong sc_traparg_a0;
5204 6049f4f8 Richard Henderson
    abi_ulong sc_traparg_a1;
5205 6049f4f8 Richard Henderson
    abi_ulong sc_traparg_a2;
5206 6049f4f8 Richard Henderson
    abi_ulong sc_fp_trap_pc;
5207 6049f4f8 Richard Henderson
    abi_ulong sc_fp_trigger_sum;
5208 6049f4f8 Richard Henderson
    abi_ulong sc_fp_trigger_inst;
5209 6049f4f8 Richard Henderson
};
5210 6049f4f8 Richard Henderson
5211 6049f4f8 Richard Henderson
struct target_ucontext {
5212 60e99246 Aurelien Jarno
    abi_ulong tuc_flags;
5213 60e99246 Aurelien Jarno
    abi_ulong tuc_link;
5214 60e99246 Aurelien Jarno
    abi_ulong tuc_osf_sigmask;
5215 60e99246 Aurelien Jarno
    target_stack_t tuc_stack;
5216 60e99246 Aurelien Jarno
    struct target_sigcontext tuc_mcontext;
5217 60e99246 Aurelien Jarno
    target_sigset_t tuc_sigmask;
5218 6049f4f8 Richard Henderson
};
5219 6049f4f8 Richard Henderson
5220 6049f4f8 Richard Henderson
struct target_sigframe {
5221 6049f4f8 Richard Henderson
    struct target_sigcontext sc;
5222 6049f4f8 Richard Henderson
    unsigned int retcode[3];
5223 6049f4f8 Richard Henderson
};
5224 6049f4f8 Richard Henderson
5225 6049f4f8 Richard Henderson
struct target_rt_sigframe {
5226 6049f4f8 Richard Henderson
    target_siginfo_t info;
5227 6049f4f8 Richard Henderson
    struct target_ucontext uc;
5228 6049f4f8 Richard Henderson
    unsigned int retcode[3];
5229 6049f4f8 Richard Henderson
};
5230 6049f4f8 Richard Henderson
5231 6049f4f8 Richard Henderson
#define INSN_MOV_R30_R16        0x47fe0410
5232 6049f4f8 Richard Henderson
#define INSN_LDI_R0             0x201f0000
5233 6049f4f8 Richard Henderson
#define INSN_CALLSYS            0x00000083
5234 6049f4f8 Richard Henderson
5235 05390248 Andreas Färber
static int setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
5236 6049f4f8 Richard Henderson
                            abi_ulong frame_addr, target_sigset_t *set)
5237 6049f4f8 Richard Henderson
{
5238 6049f4f8 Richard Henderson
    int i, err = 0;
5239 6049f4f8 Richard Henderson
5240 6049f4f8 Richard Henderson
    err |= __put_user(on_sig_stack(frame_addr), &sc->sc_onstack);
5241 6049f4f8 Richard Henderson
    err |= __put_user(set->sig[0], &sc->sc_mask);
5242 6049f4f8 Richard Henderson
    err |= __put_user(env->pc, &sc->sc_pc);
5243 6049f4f8 Richard Henderson
    err |= __put_user(8, &sc->sc_ps);
5244 6049f4f8 Richard Henderson
5245 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
5246 6049f4f8 Richard Henderson
        err |= __put_user(env->ir[i], &sc->sc_regs[i]);
5247 6049f4f8 Richard Henderson
    }
5248 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_regs[31]);
5249 6049f4f8 Richard Henderson
5250 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
5251 6049f4f8 Richard Henderson
        err |= __put_user(env->fir[i], &sc->sc_fpregs[i]);
5252 6049f4f8 Richard Henderson
    }
5253 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_fpregs[31]);
5254 6049f4f8 Richard Henderson
    err |= __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr);
5255 6049f4f8 Richard Henderson
5256 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_traparg_a0); /* FIXME */
5257 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_traparg_a1); /* FIXME */
5258 6049f4f8 Richard Henderson
    err |= __put_user(0, &sc->sc_traparg_a2); /* FIXME */
5259 6049f4f8 Richard Henderson
5260 6049f4f8 Richard Henderson
    return err;
5261 6049f4f8 Richard Henderson
}
5262 6049f4f8 Richard Henderson
5263 05390248 Andreas Färber
static int restore_sigcontext(CPUAlphaState *env,
5264 05390248 Andreas Färber
                              struct target_sigcontext *sc)
5265 6049f4f8 Richard Henderson
{
5266 6049f4f8 Richard Henderson
    uint64_t fpcr;
5267 6049f4f8 Richard Henderson
    int i, err = 0;
5268 6049f4f8 Richard Henderson
5269 6049f4f8 Richard Henderson
    err |= __get_user(env->pc, &sc->sc_pc);
5270 6049f4f8 Richard Henderson
5271 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
5272 6049f4f8 Richard Henderson
        err |= __get_user(env->ir[i], &sc->sc_regs[i]);
5273 6049f4f8 Richard Henderson
    }
5274 6049f4f8 Richard Henderson
    for (i = 0; i < 31; ++i) {
5275 6049f4f8 Richard Henderson
        err |= __get_user(env->fir[i], &sc->sc_fpregs[i]);
5276 6049f4f8 Richard Henderson
    }
5277 6049f4f8 Richard Henderson
5278 6049f4f8 Richard Henderson
    err |= __get_user(fpcr, &sc->sc_fpcr);
5279 6049f4f8 Richard Henderson
    cpu_alpha_store_fpcr(env, fpcr);
5280 6049f4f8 Richard Henderson
5281 6049f4f8 Richard Henderson
    return err;
5282 6049f4f8 Richard Henderson
}
5283 6049f4f8 Richard Henderson
5284 6049f4f8 Richard Henderson
static inline abi_ulong get_sigframe(struct target_sigaction *sa,
5285 05390248 Andreas Färber
                                     CPUAlphaState *env,
5286 05390248 Andreas Färber
                                     unsigned long framesize)
5287 6049f4f8 Richard Henderson
{
5288 6049f4f8 Richard Henderson
    abi_ulong sp = env->ir[IR_SP];
5289 6049f4f8 Richard Henderson
5290 6049f4f8 Richard Henderson
    /* This is the X/Open sanctioned signal stack switching.  */
5291 6049f4f8 Richard Henderson
    if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) {
5292 6049f4f8 Richard Henderson
        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
5293 6049f4f8 Richard Henderson
    }
5294 6049f4f8 Richard Henderson
    return (sp - framesize) & -32;
5295 6049f4f8 Richard Henderson
}
5296 6049f4f8 Richard Henderson
5297 6049f4f8 Richard Henderson
static void setup_frame(int sig, struct target_sigaction *ka,
5298 05390248 Andreas Färber
                        target_sigset_t *set, CPUAlphaState *env)
5299 6049f4f8 Richard Henderson
{
5300 6049f4f8 Richard Henderson
    abi_ulong frame_addr, r26;
5301 6049f4f8 Richard Henderson
    struct target_sigframe *frame;
5302 6049f4f8 Richard Henderson
    int err = 0;
5303 6049f4f8 Richard Henderson
5304 6049f4f8 Richard Henderson
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
5305 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5306 6049f4f8 Richard Henderson
        goto give_sigsegv;
5307 6049f4f8 Richard Henderson
    }
5308 6049f4f8 Richard Henderson
5309 6049f4f8 Richard Henderson
    err |= setup_sigcontext(&frame->sc, env, frame_addr, set);
5310 6049f4f8 Richard Henderson
5311 6049f4f8 Richard Henderson
    if (ka->sa_restorer) {
5312 6049f4f8 Richard Henderson
        r26 = ka->sa_restorer;
5313 6049f4f8 Richard Henderson
    } else {
5314 6049f4f8 Richard Henderson
        err |= __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5315 6049f4f8 Richard Henderson
        err |= __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
5316 6049f4f8 Richard Henderson
                          &frame->retcode[1]);
5317 6049f4f8 Richard Henderson
        err |= __put_user(INSN_CALLSYS, &frame->retcode[2]);
5318 6049f4f8 Richard Henderson
        /* imb() */
5319 6049f4f8 Richard Henderson
        r26 = frame_addr;
5320 6049f4f8 Richard Henderson
    }
5321 6049f4f8 Richard Henderson
5322 6049f4f8 Richard Henderson
    unlock_user_struct(frame, frame_addr, 1);
5323 6049f4f8 Richard Henderson
5324 6049f4f8 Richard Henderson
    if (err) {
5325 6049f4f8 Richard Henderson
    give_sigsegv:
5326 6049f4f8 Richard Henderson
        if (sig == TARGET_SIGSEGV) {
5327 6049f4f8 Richard Henderson
            ka->_sa_handler = TARGET_SIG_DFL;
5328 6049f4f8 Richard Henderson
        }
5329 6049f4f8 Richard Henderson
        force_sig(TARGET_SIGSEGV);
5330 6049f4f8 Richard Henderson
    }
5331 6049f4f8 Richard Henderson
5332 6049f4f8 Richard Henderson
    env->ir[IR_RA] = r26;
5333 6049f4f8 Richard Henderson
    env->ir[IR_PV] = env->pc = ka->_sa_handler;
5334 6049f4f8 Richard Henderson
    env->ir[IR_A0] = sig;
5335 6049f4f8 Richard Henderson
    env->ir[IR_A1] = 0;
5336 6049f4f8 Richard Henderson
    env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
5337 6049f4f8 Richard Henderson
    env->ir[IR_SP] = frame_addr;
5338 6049f4f8 Richard Henderson
}
5339 6049f4f8 Richard Henderson
5340 6049f4f8 Richard Henderson
static void setup_rt_frame(int sig, struct target_sigaction *ka,
5341 6049f4f8 Richard Henderson
                           target_siginfo_t *info,
5342 05390248 Andreas Färber
                           target_sigset_t *set, CPUAlphaState *env)
5343 6049f4f8 Richard Henderson
{
5344 6049f4f8 Richard Henderson
    abi_ulong frame_addr, r26;
5345 6049f4f8 Richard Henderson
    struct target_rt_sigframe *frame;
5346 6049f4f8 Richard Henderson
    int i, err = 0;
5347 6049f4f8 Richard Henderson
5348 6049f4f8 Richard Henderson
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
5349 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
5350 6049f4f8 Richard Henderson
        goto give_sigsegv;
5351 6049f4f8 Richard Henderson
    }
5352 6049f4f8 Richard Henderson
5353 6049f4f8 Richard Henderson
    err |= copy_siginfo_to_user(&frame->info, info);
5354 6049f4f8 Richard Henderson
5355 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_flags);
5356 60e99246 Aurelien Jarno
    err |= __put_user(0, &frame->uc.tuc_link);
5357 60e99246 Aurelien Jarno
    err |= __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask);
5358 6049f4f8 Richard Henderson
    err |= __put_user(target_sigaltstack_used.ss_sp,
5359 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_sp);
5360 6049f4f8 Richard Henderson
    err |= __put_user(sas_ss_flags(env->ir[IR_SP]),
5361 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_flags);
5362 6049f4f8 Richard Henderson
    err |= __put_user(target_sigaltstack_used.ss_size,
5363 60e99246 Aurelien Jarno
                      &frame->uc.tuc_stack.ss_size);
5364 60e99246 Aurelien Jarno
    err |= setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set);
5365 6049f4f8 Richard Henderson
    for (i = 0; i < TARGET_NSIG_WORDS; ++i) {
5366 60e99246 Aurelien Jarno
        err |= __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
5367 6049f4f8 Richard Henderson
    }
5368 6049f4f8 Richard Henderson
5369 6049f4f8 Richard Henderson
    if (ka->sa_restorer) {
5370 6049f4f8 Richard Henderson
        r26 = ka->sa_restorer;
5371 6049f4f8 Richard Henderson
    } else {
5372 6049f4f8 Richard Henderson
        err |= __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
5373 6049f4f8 Richard Henderson
        err |= __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
5374 6049f4f8 Richard Henderson
                          &frame->retcode[1]);
5375 6049f4f8 Richard Henderson
        err |= __put_user(INSN_CALLSYS, &frame->retcode[2]);
5376 6049f4f8 Richard Henderson
        /* imb(); */
5377 6049f4f8 Richard Henderson
        r26 = frame_addr;
5378 6049f4f8 Richard Henderson
    }
5379 6049f4f8 Richard Henderson
5380 6049f4f8 Richard Henderson
    if (err) {
5381 6049f4f8 Richard Henderson
    give_sigsegv:
5382 6049f4f8 Richard Henderson
       if (sig == TARGET_SIGSEGV) {
5383 6049f4f8 Richard Henderson
            ka->_sa_handler = TARGET_SIG_DFL;
5384 6049f4f8 Richard Henderson
        }
5385 6049f4f8 Richard Henderson
        force_sig(TARGET_SIGSEGV);
5386 6049f4f8 Richard Henderson
    }
5387 6049f4f8 Richard Henderson
5388 6049f4f8 Richard Henderson
    env->ir[IR_RA] = r26;
5389 6049f4f8 Richard Henderson
    env->ir[IR_PV] = env->pc = ka->_sa_handler;
5390 6049f4f8 Richard Henderson
    env->ir[IR_A0] = sig;
5391 6049f4f8 Richard Henderson
    env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
5392 6049f4f8 Richard Henderson
    env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
5393 6049f4f8 Richard Henderson
    env->ir[IR_SP] = frame_addr;
5394 6049f4f8 Richard Henderson
}
5395 6049f4f8 Richard Henderson
5396 05390248 Andreas Färber
long do_sigreturn(CPUAlphaState *env)
5397 6049f4f8 Richard Henderson
{
5398 6049f4f8 Richard Henderson
    struct target_sigcontext *sc;
5399 6049f4f8 Richard Henderson
    abi_ulong sc_addr = env->ir[IR_A0];
5400 6049f4f8 Richard Henderson
    target_sigset_t target_set;
5401 6049f4f8 Richard Henderson
    sigset_t set;
5402 6049f4f8 Richard Henderson
5403 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
5404 6049f4f8 Richard Henderson
        goto badframe;
5405 6049f4f8 Richard Henderson
    }
5406 6049f4f8 Richard Henderson
5407 6049f4f8 Richard Henderson
    target_sigemptyset(&target_set);
5408 6049f4f8 Richard Henderson
    if (__get_user(target_set.sig[0], &sc->sc_mask)) {
5409 6049f4f8 Richard Henderson
        goto badframe;
5410 6049f4f8 Richard Henderson
    }
5411 6049f4f8 Richard Henderson
5412 6049f4f8 Richard Henderson
    target_to_host_sigset_internal(&set, &target_set);
5413 6049f4f8 Richard Henderson
    sigprocmask(SIG_SETMASK, &set, NULL);
5414 6049f4f8 Richard Henderson
5415 6049f4f8 Richard Henderson
    if (restore_sigcontext(env, sc)) {
5416 6049f4f8 Richard Henderson
        goto badframe;
5417 6049f4f8 Richard Henderson
    }
5418 6049f4f8 Richard Henderson
    unlock_user_struct(sc, sc_addr, 0);
5419 6049f4f8 Richard Henderson
    return env->ir[IR_V0];
5420 6049f4f8 Richard Henderson
5421 6049f4f8 Richard Henderson
 badframe:
5422 6049f4f8 Richard Henderson
    unlock_user_struct(sc, sc_addr, 0);
5423 6049f4f8 Richard Henderson
    force_sig(TARGET_SIGSEGV);
5424 6049f4f8 Richard Henderson
}
5425 6049f4f8 Richard Henderson
5426 05390248 Andreas Färber
long do_rt_sigreturn(CPUAlphaState *env)
5427 6049f4f8 Richard Henderson
{
5428 6049f4f8 Richard Henderson
    abi_ulong frame_addr = env->ir[IR_A0];
5429 6049f4f8 Richard Henderson
    struct target_rt_sigframe *frame;
5430 6049f4f8 Richard Henderson
    sigset_t set;
5431 6049f4f8 Richard Henderson
5432 6049f4f8 Richard Henderson
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
5433 6049f4f8 Richard Henderson
        goto badframe;
5434 6049f4f8 Richard Henderson
    }
5435 60e99246 Aurelien Jarno
    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
5436 6049f4f8 Richard Henderson
    sigprocmask(SIG_SETMASK, &set, NULL);
5437 6049f4f8 Richard Henderson
5438 60e99246 Aurelien Jarno
    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
5439 6049f4f8 Richard Henderson
        goto badframe;
5440 6049f4f8 Richard Henderson
    }
5441 6049f4f8 Richard Henderson
    if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
5442 60e99246 Aurelien Jarno
                                             uc.tuc_stack),
5443 6049f4f8 Richard Henderson
                       0, env->ir[IR_SP]) == -EFAULT) {
5444 6049f4f8 Richard Henderson
        goto badframe;
5445 6049f4f8 Richard Henderson
    }
5446 6049f4f8 Richard Henderson
5447 6049f4f8 Richard Henderson
    unlock_user_struct(frame, frame_addr, 0);
5448 6049f4f8 Richard Henderson
    return env->ir[IR_V0];
5449 6049f4f8 Richard Henderson
5450 6049f4f8 Richard Henderson
5451 6049f4f8 Richard Henderson
 badframe:
5452 6049f4f8 Richard Henderson
    unlock_user_struct(frame, frame_addr, 0);
5453 6049f4f8 Richard Henderson
    force_sig(TARGET_SIGSEGV);
5454 6049f4f8 Richard Henderson
}
5455 6049f4f8 Richard Henderson
5456 b346ff46 bellard
#else
5457 b346ff46 bellard
5458 624f7979 pbrook
static void setup_frame(int sig, struct target_sigaction *ka,
5459 9349b4f9 Andreas Färber
                        target_sigset_t *set, CPUArchState *env)
5460 b346ff46 bellard
{
5461 b346ff46 bellard
    fprintf(stderr, "setup_frame: not implemented\n");
5462 b346ff46 bellard
}
5463 b346ff46 bellard
5464 624f7979 pbrook
static void setup_rt_frame(int sig, struct target_sigaction *ka,
5465 c227f099 Anthony Liguori
                           target_siginfo_t *info,
5466 9349b4f9 Andreas Färber
                           target_sigset_t *set, CPUArchState *env)
5467 b346ff46 bellard
{
5468 b346ff46 bellard
    fprintf(stderr, "setup_rt_frame: not implemented\n");
5469 b346ff46 bellard
}
5470 b346ff46 bellard
5471 9349b4f9 Andreas Färber
long do_sigreturn(CPUArchState *env)
5472 b346ff46 bellard
{
5473 b346ff46 bellard
    fprintf(stderr, "do_sigreturn: not implemented\n");
5474 f8b0aa25 bellard
    return -TARGET_ENOSYS;
5475 b346ff46 bellard
}
5476 b346ff46 bellard
5477 9349b4f9 Andreas Färber
long do_rt_sigreturn(CPUArchState *env)
5478 b346ff46 bellard
{
5479 b346ff46 bellard
    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
5480 f8b0aa25 bellard
    return -TARGET_ENOSYS;
5481 b346ff46 bellard
}
5482 b346ff46 bellard
5483 66fb9763 bellard
#endif
5484 66fb9763 bellard
5485 9349b4f9 Andreas Färber
void process_pending_signals(CPUArchState *cpu_env)
5486 66fb9763 bellard
{
5487 66fb9763 bellard
    int sig;
5488 992f48a0 blueswir1
    abi_ulong handler;
5489 9de5e440 bellard
    sigset_t set, old_set;
5490 c227f099 Anthony Liguori
    target_sigset_t target_old_set;
5491 624f7979 pbrook
    struct emulated_sigtable *k;
5492 624f7979 pbrook
    struct target_sigaction *sa;
5493 66fb9763 bellard
    struct sigqueue *q;
5494 624f7979 pbrook
    TaskState *ts = cpu_env->opaque;
5495 3b46e624 ths
5496 624f7979 pbrook
    if (!ts->signal_pending)
5497 31e31b8a bellard
        return;
5498 31e31b8a bellard
5499 624f7979 pbrook
    /* FIXME: This is not threadsafe.  */
5500 624f7979 pbrook
    k = ts->sigtab;
5501 66fb9763 bellard
    for(sig = 1; sig <= TARGET_NSIG; sig++) {
5502 66fb9763 bellard
        if (k->pending)
5503 31e31b8a bellard
            goto handle_signal;
5504 66fb9763 bellard
        k++;
5505 31e31b8a bellard
    }
5506 31e31b8a bellard
    /* if no signal is pending, just return */
5507 624f7979 pbrook
    ts->signal_pending = 0;
5508 31e31b8a bellard
    return;
5509 66fb9763 bellard
5510 31e31b8a bellard
 handle_signal:
5511 66fb9763 bellard
#ifdef DEBUG_SIGNAL
5512 bc8a22cc bellard
    fprintf(stderr, "qemu: process signal %d\n", sig);
5513 66fb9763 bellard
#endif
5514 66fb9763 bellard
    /* dequeue signal */
5515 66fb9763 bellard
    q = k->first;
5516 66fb9763 bellard
    k->first = q->next;
5517 66fb9763 bellard
    if (!k->first)
5518 66fb9763 bellard
        k->pending = 0;
5519 3b46e624 ths
5520 1fddef4b bellard
    sig = gdb_handlesig (cpu_env, sig);
5521 1fddef4b bellard
    if (!sig) {
5522 ca587a8e aurel32
        sa = NULL;
5523 ca587a8e aurel32
        handler = TARGET_SIG_IGN;
5524 ca587a8e aurel32
    } else {
5525 ca587a8e aurel32
        sa = &sigact_table[sig - 1];
5526 ca587a8e aurel32
        handler = sa->_sa_handler;
5527 1fddef4b bellard
    }
5528 66fb9763 bellard
5529 66fb9763 bellard
    if (handler == TARGET_SIG_DFL) {
5530 ca587a8e aurel32
        /* default handler : ignore some signal. The other are job control or fatal */
5531 ca587a8e aurel32
        if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
5532 ca587a8e aurel32
            kill(getpid(),SIGSTOP);
5533 ca587a8e aurel32
        } else if (sig != TARGET_SIGCHLD &&
5534 ca587a8e aurel32
                   sig != TARGET_SIGURG &&
5535 ca587a8e aurel32
                   sig != TARGET_SIGWINCH &&
5536 ca587a8e aurel32
                   sig != TARGET_SIGCONT) {
5537 66fb9763 bellard
            force_sig(sig);
5538 66fb9763 bellard
        }
5539 66fb9763 bellard
    } else if (handler == TARGET_SIG_IGN) {
5540 66fb9763 bellard
        /* ignore sig */
5541 66fb9763 bellard
    } else if (handler == TARGET_SIG_ERR) {
5542 66fb9763 bellard
        force_sig(sig);
5543 66fb9763 bellard
    } else {
5544 9de5e440 bellard
        /* compute the blocked signals during the handler execution */
5545 624f7979 pbrook
        target_to_host_sigset(&set, &sa->sa_mask);
5546 9de5e440 bellard
        /* SA_NODEFER indicates that the current signal should not be
5547 9de5e440 bellard
           blocked during the handler */
5548 624f7979 pbrook
        if (!(sa->sa_flags & TARGET_SA_NODEFER))
5549 9de5e440 bellard
            sigaddset(&set, target_to_host_signal(sig));
5550 3b46e624 ths
5551 9de5e440 bellard
        /* block signals in the handler using Linux */
5552 9de5e440 bellard
        sigprocmask(SIG_BLOCK, &set, &old_set);
5553 9de5e440 bellard
        /* save the previous blocked signal state to restore it at the
5554 9de5e440 bellard
           end of the signal execution (see do_sigreturn) */
5555 9231944d bellard
        host_to_target_sigset_internal(&target_old_set, &old_set);
5556 9de5e440 bellard
5557 bc8a22cc bellard
        /* if the CPU is in VM86 mode, we restore the 32 bit values */
5558 84409ddb j_mayer
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
5559 bc8a22cc bellard
        {
5560 bc8a22cc bellard
            CPUX86State *env = cpu_env;
5561 bc8a22cc bellard
            if (env->eflags & VM_MASK)
5562 bc8a22cc bellard
                save_v86_state(env);
5563 bc8a22cc bellard
        }
5564 bc8a22cc bellard
#endif
5565 9de5e440 bellard
        /* prepare the stack frame of the virtual CPU */
5566 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_SIGINFO)
5567 624f7979 pbrook
            setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
5568 66fb9763 bellard
        else
5569 624f7979 pbrook
            setup_frame(sig, sa, &target_old_set, cpu_env);
5570 624f7979 pbrook
        if (sa->sa_flags & TARGET_SA_RESETHAND)
5571 624f7979 pbrook
            sa->_sa_handler = TARGET_SIG_DFL;
5572 31e31b8a bellard
    }
5573 66fb9763 bellard
    if (q != &k->info)
5574 624f7979 pbrook
        free_sigqueue(cpu_env, q);
5575 66fb9763 bellard
}