docs/devel/testing.rst: add missing newlines after code block
[qemu/ar7.git] / linux-user / arm / signal.c
blobb0e753801b6cc42d0be4da13639e5425cd9251e0
1 /*
2 * Emulation of Linux signals
4 * Copyright (c) 2003 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
20 #include "qemu.h"
21 #include "signal-common.h"
22 #include "linux-user/trace.h"
24 struct target_sigcontext {
25 abi_ulong trap_no;
26 abi_ulong error_code;
27 abi_ulong oldmask;
28 abi_ulong arm_r0;
29 abi_ulong arm_r1;
30 abi_ulong arm_r2;
31 abi_ulong arm_r3;
32 abi_ulong arm_r4;
33 abi_ulong arm_r5;
34 abi_ulong arm_r6;
35 abi_ulong arm_r7;
36 abi_ulong arm_r8;
37 abi_ulong arm_r9;
38 abi_ulong arm_r10;
39 abi_ulong arm_fp;
40 abi_ulong arm_ip;
41 abi_ulong arm_sp;
42 abi_ulong arm_lr;
43 abi_ulong arm_pc;
44 abi_ulong arm_cpsr;
45 abi_ulong fault_address;
48 struct target_ucontext_v1 {
49 abi_ulong tuc_flags;
50 abi_ulong tuc_link;
51 target_stack_t tuc_stack;
52 struct target_sigcontext tuc_mcontext;
53 target_sigset_t tuc_sigmask; /* mask last for extensibility */
56 struct target_ucontext_v2 {
57 abi_ulong tuc_flags;
58 abi_ulong tuc_link;
59 target_stack_t tuc_stack;
60 struct target_sigcontext tuc_mcontext;
61 target_sigset_t tuc_sigmask; /* mask last for extensibility */
62 char __unused[128 - sizeof(target_sigset_t)];
63 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
66 struct target_user_vfp {
67 uint64_t fpregs[32];
68 abi_ulong fpscr;
71 struct target_user_vfp_exc {
72 abi_ulong fpexc;
73 abi_ulong fpinst;
74 abi_ulong fpinst2;
77 struct target_vfp_sigframe {
78 abi_ulong magic;
79 abi_ulong size;
80 struct target_user_vfp ufp;
81 struct target_user_vfp_exc ufp_exc;
82 } __attribute__((__aligned__(8)));
84 struct target_iwmmxt_sigframe {
85 abi_ulong magic;
86 abi_ulong size;
87 uint64_t regs[16];
88 /* Note that not all the coprocessor control registers are stored here */
89 uint32_t wcssf;
90 uint32_t wcasf;
91 uint32_t wcgr0;
92 uint32_t wcgr1;
93 uint32_t wcgr2;
94 uint32_t wcgr3;
95 } __attribute__((__aligned__(8)));
97 #define TARGET_VFP_MAGIC 0x56465001
98 #define TARGET_IWMMXT_MAGIC 0x12ef842a
100 struct sigframe_v1
102 struct target_sigcontext sc;
103 abi_ulong extramask[TARGET_NSIG_WORDS-1];
104 abi_ulong retcode[4];
107 struct sigframe_v2
109 struct target_ucontext_v2 uc;
110 abi_ulong retcode[4];
113 struct rt_sigframe_v1
115 abi_ulong pinfo;
116 abi_ulong puc;
117 struct target_siginfo info;
118 struct target_ucontext_v1 uc;
119 abi_ulong retcode[4];
122 struct rt_sigframe_v2
124 struct target_siginfo info;
125 struct target_ucontext_v2 uc;
126 abi_ulong retcode[4];
129 #define TARGET_CONFIG_CPU_32 1
132 * For ARM syscalls, we encode the syscall number into the instruction.
134 #define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
135 #define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
138 * For Thumb syscalls, we pass the syscall number via r7. We therefore
139 * need two 16-bit instructions.
141 #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
142 #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
144 static const abi_ulong retcodes[4] = {
145 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
146 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
150 * Stub needed to make sure the FD register (r9) contains the right
151 * value.
153 static const unsigned long sigreturn_fdpic_codes[3] = {
154 0xe59fc004, /* ldr r12, [pc, #4] to read function descriptor */
155 0xe59c9004, /* ldr r9, [r12, #4] to setup GOT */
156 0xe59cf000 /* ldr pc, [r12] to jump into restorer */
159 static const unsigned long sigreturn_fdpic_thumb_codes[3] = {
160 0xc008f8df, /* ldr r12, [pc, #8] to read function descriptor */
161 0x9004f8dc, /* ldr r9, [r12, #4] to setup GOT */
162 0xf000f8dc /* ldr pc, [r12] to jump into restorer */
165 static inline int valid_user_regs(CPUARMState *regs)
167 return 1;
170 static void
171 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
172 CPUARMState *env, abi_ulong mask)
174 __put_user(env->regs[0], &sc->arm_r0);
175 __put_user(env->regs[1], &sc->arm_r1);
176 __put_user(env->regs[2], &sc->arm_r2);
177 __put_user(env->regs[3], &sc->arm_r3);
178 __put_user(env->regs[4], &sc->arm_r4);
179 __put_user(env->regs[5], &sc->arm_r5);
180 __put_user(env->regs[6], &sc->arm_r6);
181 __put_user(env->regs[7], &sc->arm_r7);
182 __put_user(env->regs[8], &sc->arm_r8);
183 __put_user(env->regs[9], &sc->arm_r9);
184 __put_user(env->regs[10], &sc->arm_r10);
185 __put_user(env->regs[11], &sc->arm_fp);
186 __put_user(env->regs[12], &sc->arm_ip);
187 __put_user(env->regs[13], &sc->arm_sp);
188 __put_user(env->regs[14], &sc->arm_lr);
189 __put_user(env->regs[15], &sc->arm_pc);
190 #ifdef TARGET_CONFIG_CPU_32
191 __put_user(cpsr_read(env), &sc->arm_cpsr);
192 #endif
194 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
195 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
196 __put_user(/* current->thread.address */ 0, &sc->fault_address);
197 __put_user(mask, &sc->oldmask);
200 static inline abi_ulong
201 get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
203 unsigned long sp;
205 sp = target_sigsp(get_sp_from_cpustate(regs), ka);
207 * ATPCS B01 mandates 8-byte alignment
209 return (sp - framesize) & ~7;
212 static int
213 setup_return(CPUARMState *env, struct target_sigaction *ka,
214 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
216 abi_ulong handler = 0;
217 abi_ulong handler_fdpic_GOT = 0;
218 abi_ulong retcode;
220 int thumb;
221 int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
223 if (is_fdpic) {
224 /* In FDPIC mode, ka->_sa_handler points to a function
225 * descriptor (FD). The first word contains the address of the
226 * handler. The second word contains the value of the PIC
227 * register (r9). */
228 abi_ulong funcdesc_ptr = ka->_sa_handler;
229 if (get_user_ual(handler, funcdesc_ptr)
230 || get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) {
231 return 1;
233 } else {
234 handler = ka->_sa_handler;
237 thumb = handler & 1;
239 uint32_t cpsr = cpsr_read(env);
241 cpsr &= ~CPSR_IT;
242 if (thumb) {
243 cpsr |= CPSR_T;
244 } else {
245 cpsr &= ~CPSR_T;
248 if (ka->sa_flags & TARGET_SA_RESTORER) {
249 if (is_fdpic) {
250 /* For FDPIC we ensure that the restorer is called with a
251 * correct r9 value. For that we need to write code on
252 * the stack that sets r9 and jumps back to restorer
253 * value.
255 if (thumb) {
256 __put_user(sigreturn_fdpic_thumb_codes[0], rc);
257 __put_user(sigreturn_fdpic_thumb_codes[1], rc + 1);
258 __put_user(sigreturn_fdpic_thumb_codes[2], rc + 2);
259 __put_user((abi_ulong)ka->sa_restorer, rc + 3);
260 } else {
261 __put_user(sigreturn_fdpic_codes[0], rc);
262 __put_user(sigreturn_fdpic_codes[1], rc + 1);
263 __put_user(sigreturn_fdpic_codes[2], rc + 2);
264 __put_user((abi_ulong)ka->sa_restorer, rc + 3);
267 retcode = rc_addr + thumb;
268 } else {
269 retcode = ka->sa_restorer;
271 } else {
272 unsigned int idx = thumb;
274 if (ka->sa_flags & TARGET_SA_SIGINFO) {
275 idx += 2;
278 __put_user(retcodes[idx], rc);
280 retcode = rc_addr + thumb;
283 env->regs[0] = usig;
284 if (is_fdpic) {
285 env->regs[9] = handler_fdpic_GOT;
287 env->regs[13] = frame_addr;
288 env->regs[14] = retcode;
289 env->regs[15] = handler & (thumb ? ~1 : ~3);
290 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
292 return 0;
295 static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
297 int i;
298 struct target_vfp_sigframe *vfpframe;
299 vfpframe = (struct target_vfp_sigframe *)regspace;
300 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
301 __put_user(sizeof(*vfpframe), &vfpframe->size);
302 for (i = 0; i < 32; i++) {
303 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
305 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
306 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
307 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
308 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
309 return (abi_ulong*)(vfpframe+1);
312 static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
313 CPUARMState *env)
315 int i;
316 struct target_iwmmxt_sigframe *iwmmxtframe;
317 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
318 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
319 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
320 for (i = 0; i < 16; i++) {
321 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
323 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
324 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
325 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
326 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
327 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
328 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
329 return (abi_ulong*)(iwmmxtframe+1);
332 static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
333 target_sigset_t *set, CPUARMState *env)
335 struct target_sigaltstack stack;
336 int i;
337 abi_ulong *regspace;
339 /* Clear all the bits of the ucontext we don't use. */
340 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
342 memset(&stack, 0, sizeof(stack));
343 target_save_altstack(&stack, env);
344 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
346 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
347 /* Save coprocessor signal frame. */
348 regspace = uc->tuc_regspace;
349 if (arm_feature(env, ARM_FEATURE_VFP)) {
350 regspace = setup_sigframe_v2_vfp(regspace, env);
352 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
353 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
356 /* Write terminating magic word */
357 __put_user(0, regspace);
359 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
360 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
364 /* compare linux/arch/arm/kernel/signal.c:setup_frame() */
365 static void setup_frame_v1(int usig, struct target_sigaction *ka,
366 target_sigset_t *set, CPUARMState *regs)
368 struct sigframe_v1 *frame;
369 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
370 int i;
372 trace_user_setup_frame(regs, frame_addr);
373 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
374 goto sigsegv;
377 setup_sigcontext(&frame->sc, regs, set->sig[0]);
379 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
380 __put_user(set->sig[i], &frame->extramask[i - 1]);
383 if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
384 frame_addr + offsetof(struct sigframe_v1, retcode))) {
385 goto sigsegv;
388 unlock_user_struct(frame, frame_addr, 1);
389 return;
390 sigsegv:
391 unlock_user_struct(frame, frame_addr, 1);
392 force_sigsegv(usig);
395 static void setup_frame_v2(int usig, struct target_sigaction *ka,
396 target_sigset_t *set, CPUARMState *regs)
398 struct sigframe_v2 *frame;
399 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
401 trace_user_setup_frame(regs, frame_addr);
402 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
403 goto sigsegv;
406 setup_sigframe_v2(&frame->uc, set, regs);
408 if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
409 frame_addr + offsetof(struct sigframe_v2, retcode))) {
410 goto sigsegv;
413 unlock_user_struct(frame, frame_addr, 1);
414 return;
415 sigsegv:
416 unlock_user_struct(frame, frame_addr, 1);
417 force_sigsegv(usig);
420 void setup_frame(int usig, struct target_sigaction *ka,
421 target_sigset_t *set, CPUARMState *regs)
423 if (get_osversion() >= 0x020612) {
424 setup_frame_v2(usig, ka, set, regs);
425 } else {
426 setup_frame_v1(usig, ka, set, regs);
430 /* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
431 static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
432 target_siginfo_t *info,
433 target_sigset_t *set, CPUARMState *env)
435 struct rt_sigframe_v1 *frame;
436 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
437 struct target_sigaltstack stack;
438 int i;
439 abi_ulong info_addr, uc_addr;
441 trace_user_setup_rt_frame(env, frame_addr);
442 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
443 goto sigsegv;
446 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
447 __put_user(info_addr, &frame->pinfo);
448 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
449 __put_user(uc_addr, &frame->puc);
450 tswap_siginfo(&frame->info, info);
452 /* Clear all the bits of the ucontext we don't use. */
453 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
455 memset(&stack, 0, sizeof(stack));
456 target_save_altstack(&stack, env);
457 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
459 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
460 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
461 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
464 if (setup_return(env, ka, frame->retcode, frame_addr, usig,
465 frame_addr + offsetof(struct rt_sigframe_v1, retcode))) {
466 goto sigsegv;
469 env->regs[1] = info_addr;
470 env->regs[2] = uc_addr;
472 unlock_user_struct(frame, frame_addr, 1);
473 return;
474 sigsegv:
475 unlock_user_struct(frame, frame_addr, 1);
476 force_sigsegv(usig);
479 static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
480 target_siginfo_t *info,
481 target_sigset_t *set, CPUARMState *env)
483 struct rt_sigframe_v2 *frame;
484 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
485 abi_ulong info_addr, uc_addr;
487 trace_user_setup_rt_frame(env, frame_addr);
488 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
489 goto sigsegv;
492 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
493 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
494 tswap_siginfo(&frame->info, info);
496 setup_sigframe_v2(&frame->uc, set, env);
498 if (setup_return(env, ka, frame->retcode, frame_addr, usig,
499 frame_addr + offsetof(struct rt_sigframe_v2, retcode))) {
500 goto sigsegv;
503 env->regs[1] = info_addr;
504 env->regs[2] = uc_addr;
506 unlock_user_struct(frame, frame_addr, 1);
507 return;
508 sigsegv:
509 unlock_user_struct(frame, frame_addr, 1);
510 force_sigsegv(usig);
513 void setup_rt_frame(int usig, struct target_sigaction *ka,
514 target_siginfo_t *info,
515 target_sigset_t *set, CPUARMState *env)
517 if (get_osversion() >= 0x020612) {
518 setup_rt_frame_v2(usig, ka, info, set, env);
519 } else {
520 setup_rt_frame_v1(usig, ka, info, set, env);
524 static int
525 restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
527 int err = 0;
528 uint32_t cpsr;
530 __get_user(env->regs[0], &sc->arm_r0);
531 __get_user(env->regs[1], &sc->arm_r1);
532 __get_user(env->regs[2], &sc->arm_r2);
533 __get_user(env->regs[3], &sc->arm_r3);
534 __get_user(env->regs[4], &sc->arm_r4);
535 __get_user(env->regs[5], &sc->arm_r5);
536 __get_user(env->regs[6], &sc->arm_r6);
537 __get_user(env->regs[7], &sc->arm_r7);
538 __get_user(env->regs[8], &sc->arm_r8);
539 __get_user(env->regs[9], &sc->arm_r9);
540 __get_user(env->regs[10], &sc->arm_r10);
541 __get_user(env->regs[11], &sc->arm_fp);
542 __get_user(env->regs[12], &sc->arm_ip);
543 __get_user(env->regs[13], &sc->arm_sp);
544 __get_user(env->regs[14], &sc->arm_lr);
545 __get_user(env->regs[15], &sc->arm_pc);
546 #ifdef TARGET_CONFIG_CPU_32
547 __get_user(cpsr, &sc->arm_cpsr);
548 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
549 #endif
551 err |= !valid_user_regs(env);
553 return err;
556 static long do_sigreturn_v1(CPUARMState *env)
558 abi_ulong frame_addr;
559 struct sigframe_v1 *frame = NULL;
560 target_sigset_t set;
561 sigset_t host_set;
562 int i;
565 * Since we stacked the signal on a 64-bit boundary,
566 * then 'sp' should be word aligned here. If it's
567 * not, then the user is trying to mess with us.
569 frame_addr = env->regs[13];
570 trace_user_do_sigreturn(env, frame_addr);
571 if (frame_addr & 7) {
572 goto badframe;
575 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
576 goto badframe;
579 __get_user(set.sig[0], &frame->sc.oldmask);
580 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
581 __get_user(set.sig[i], &frame->extramask[i - 1]);
584 target_to_host_sigset_internal(&host_set, &set);
585 set_sigmask(&host_set);
587 if (restore_sigcontext(env, &frame->sc)) {
588 goto badframe;
591 #if 0
592 /* Send SIGTRAP if we're single-stepping */
593 if (ptrace_cancel_bpt(current))
594 send_sig(SIGTRAP, current, 1);
595 #endif
596 unlock_user_struct(frame, frame_addr, 0);
597 return -TARGET_QEMU_ESIGRETURN;
599 badframe:
600 force_sig(TARGET_SIGSEGV);
601 return -TARGET_QEMU_ESIGRETURN;
604 static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
606 int i;
607 abi_ulong magic, sz;
608 uint32_t fpscr, fpexc;
609 struct target_vfp_sigframe *vfpframe;
610 vfpframe = (struct target_vfp_sigframe *)regspace;
612 __get_user(magic, &vfpframe->magic);
613 __get_user(sz, &vfpframe->size);
614 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
615 return 0;
617 for (i = 0; i < 32; i++) {
618 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
620 __get_user(fpscr, &vfpframe->ufp.fpscr);
621 vfp_set_fpscr(env, fpscr);
622 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
623 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
624 * and the exception flag is cleared
626 fpexc |= (1 << 30);
627 fpexc &= ~((1 << 31) | (1 << 28));
628 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
629 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
630 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
631 return (abi_ulong*)(vfpframe + 1);
634 static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
635 abi_ulong *regspace)
637 int i;
638 abi_ulong magic, sz;
639 struct target_iwmmxt_sigframe *iwmmxtframe;
640 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
642 __get_user(magic, &iwmmxtframe->magic);
643 __get_user(sz, &iwmmxtframe->size);
644 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
645 return 0;
647 for (i = 0; i < 16; i++) {
648 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
650 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
651 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
652 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
653 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
654 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
655 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
656 return (abi_ulong*)(iwmmxtframe + 1);
659 static int do_sigframe_return_v2(CPUARMState *env,
660 target_ulong context_addr,
661 struct target_ucontext_v2 *uc)
663 sigset_t host_set;
664 abi_ulong *regspace;
666 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
667 set_sigmask(&host_set);
669 if (restore_sigcontext(env, &uc->tuc_mcontext))
670 return 1;
672 /* Restore coprocessor signal frame */
673 regspace = uc->tuc_regspace;
674 if (arm_feature(env, ARM_FEATURE_VFP)) {
675 regspace = restore_sigframe_v2_vfp(env, regspace);
676 if (!regspace) {
677 return 1;
680 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
681 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
682 if (!regspace) {
683 return 1;
687 if (do_sigaltstack(context_addr
688 + offsetof(struct target_ucontext_v2, tuc_stack),
689 0, get_sp_from_cpustate(env)) == -EFAULT) {
690 return 1;
693 #if 0
694 /* Send SIGTRAP if we're single-stepping */
695 if (ptrace_cancel_bpt(current))
696 send_sig(SIGTRAP, current, 1);
697 #endif
699 return 0;
702 static long do_sigreturn_v2(CPUARMState *env)
704 abi_ulong frame_addr;
705 struct sigframe_v2 *frame = NULL;
708 * Since we stacked the signal on a 64-bit boundary,
709 * then 'sp' should be word aligned here. If it's
710 * not, then the user is trying to mess with us.
712 frame_addr = env->regs[13];
713 trace_user_do_sigreturn(env, frame_addr);
714 if (frame_addr & 7) {
715 goto badframe;
718 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
719 goto badframe;
722 if (do_sigframe_return_v2(env,
723 frame_addr
724 + offsetof(struct sigframe_v2, uc),
725 &frame->uc)) {
726 goto badframe;
729 unlock_user_struct(frame, frame_addr, 0);
730 return -TARGET_QEMU_ESIGRETURN;
732 badframe:
733 unlock_user_struct(frame, frame_addr, 0);
734 force_sig(TARGET_SIGSEGV);
735 return -TARGET_QEMU_ESIGRETURN;
738 long do_sigreturn(CPUARMState *env)
740 if (get_osversion() >= 0x020612) {
741 return do_sigreturn_v2(env);
742 } else {
743 return do_sigreturn_v1(env);
747 static long do_rt_sigreturn_v1(CPUARMState *env)
749 abi_ulong frame_addr;
750 struct rt_sigframe_v1 *frame = NULL;
751 sigset_t host_set;
754 * Since we stacked the signal on a 64-bit boundary,
755 * then 'sp' should be word aligned here. If it's
756 * not, then the user is trying to mess with us.
758 frame_addr = env->regs[13];
759 trace_user_do_rt_sigreturn(env, frame_addr);
760 if (frame_addr & 7) {
761 goto badframe;
764 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
765 goto badframe;
768 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
769 set_sigmask(&host_set);
771 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
772 goto badframe;
775 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
776 goto badframe;
778 #if 0
779 /* Send SIGTRAP if we're single-stepping */
780 if (ptrace_cancel_bpt(current))
781 send_sig(SIGTRAP, current, 1);
782 #endif
783 unlock_user_struct(frame, frame_addr, 0);
784 return -TARGET_QEMU_ESIGRETURN;
786 badframe:
787 unlock_user_struct(frame, frame_addr, 0);
788 force_sig(TARGET_SIGSEGV);
789 return -TARGET_QEMU_ESIGRETURN;
792 static long do_rt_sigreturn_v2(CPUARMState *env)
794 abi_ulong frame_addr;
795 struct rt_sigframe_v2 *frame = NULL;
798 * Since we stacked the signal on a 64-bit boundary,
799 * then 'sp' should be word aligned here. If it's
800 * not, then the user is trying to mess with us.
802 frame_addr = env->regs[13];
803 trace_user_do_rt_sigreturn(env, frame_addr);
804 if (frame_addr & 7) {
805 goto badframe;
808 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
809 goto badframe;
812 if (do_sigframe_return_v2(env,
813 frame_addr
814 + offsetof(struct rt_sigframe_v2, uc),
815 &frame->uc)) {
816 goto badframe;
819 unlock_user_struct(frame, frame_addr, 0);
820 return -TARGET_QEMU_ESIGRETURN;
822 badframe:
823 unlock_user_struct(frame, frame_addr, 0);
824 force_sig(TARGET_SIGSEGV);
825 return -TARGET_QEMU_ESIGRETURN;
828 long do_rt_sigreturn(CPUARMState *env)
830 if (get_osversion() >= 0x020612) {
831 return do_rt_sigreturn_v2(env);
832 } else {
833 return do_rt_sigreturn_v1(env);