xref: /openbmc/qemu/linux-user/arm/signal.c (revision 99d423e5)
1 /*
2  *  Emulation of Linux signals
3  *
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include "qemu/osdep.h"
20 #include "qemu.h"
21 #include "signal-common.h"
22 #include "linux-user/trace.h"
23 
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;
46 };
47 
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 */
54 };
55 
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)));
64 };
65 
66 struct target_user_vfp {
67     uint64_t fpregs[32];
68     abi_ulong fpscr;
69 };
70 
71 struct target_user_vfp_exc {
72     abi_ulong fpexc;
73     abi_ulong fpinst;
74     abi_ulong fpinst2;
75 };
76 
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)));
83 
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)));
96 
97 #define TARGET_VFP_MAGIC 0x56465001
98 #define TARGET_IWMMXT_MAGIC 0x12ef842a
99 
100 struct sigframe_v1
101 {
102     struct target_sigcontext sc;
103     abi_ulong extramask[TARGET_NSIG_WORDS-1];
104     abi_ulong retcode[4];
105 };
106 
107 struct sigframe_v2
108 {
109     struct target_ucontext_v2 uc;
110     abi_ulong retcode[4];
111 };
112 
113 struct rt_sigframe_v1
114 {
115     abi_ulong pinfo;
116     abi_ulong puc;
117     struct target_siginfo info;
118     struct target_ucontext_v1 uc;
119     abi_ulong retcode[4];
120 };
121 
122 struct rt_sigframe_v2
123 {
124     struct target_siginfo info;
125     struct target_ucontext_v2 uc;
126     abi_ulong retcode[4];
127 };
128 
129 #define TARGET_CONFIG_CPU_32 1
130 
131 /*
132  * For ARM syscalls, we encode the syscall number into the instruction.
133  */
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))
136 
137 /*
138  * For Thumb syscalls, we pass the syscall number via r7.  We therefore
139  * need two 16-bit instructions.
140  */
141 #define SWI_THUMB_SIGRETURN     (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
142 #define SWI_THUMB_RT_SIGRETURN  (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
143 
144 static const abi_ulong retcodes[4] = {
145         SWI_SYS_SIGRETURN,      SWI_THUMB_SIGRETURN,
146         SWI_SYS_RT_SIGRETURN,   SWI_THUMB_RT_SIGRETURN
147 };
148 
149 /*
150  * Stub needed to make sure the FD register (r9) contains the right
151  * value.
152  */
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 */
157 };
158 
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 */
163 };
164 
165 static inline int valid_user_regs(CPUARMState *regs)
166 {
167     return 1;
168 }
169 
170 static void
171 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
172                  CPUARMState *env, abi_ulong mask)
173 {
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
193 
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);
198 }
199 
200 static inline abi_ulong
201 get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
202 {
203     unsigned long sp;
204 
205     sp = target_sigsp(get_sp_from_cpustate(regs), ka);
206     /*
207      * ATPCS B01 mandates 8-byte alignment
208      */
209     return (sp - framesize) & ~7;
210 }
211 
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)
215 {
216     abi_ulong handler = 0;
217     abi_ulong handler_fdpic_GOT = 0;
218     abi_ulong retcode;
219 
220     int thumb;
221     int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
222 
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;
232         }
233     } else {
234         handler = ka->_sa_handler;
235     }
236 
237     thumb = handler & 1;
238 
239     uint32_t cpsr = cpsr_read(env);
240 
241     cpsr &= ~CPSR_IT;
242     if (thumb) {
243         cpsr |= CPSR_T;
244     } else {
245         cpsr &= ~CPSR_T;
246     }
247 
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.
254              */
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);
265             }
266 
267             retcode = rc_addr + thumb;
268         } else {
269             retcode = ka->sa_restorer;
270         }
271     } else {
272         unsigned int idx = thumb;
273 
274         if (ka->sa_flags & TARGET_SA_SIGINFO) {
275             idx += 2;
276         }
277 
278         __put_user(retcodes[idx], rc);
279 
280         retcode = rc_addr + thumb;
281     }
282 
283     env->regs[0] = usig;
284     if (is_fdpic) {
285         env->regs[9] = handler_fdpic_GOT;
286     }
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);
291 
292     return 0;
293 }
294 
295 static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
296 {
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]);
304     }
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);
310 }
311 
312 static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
313                                            CPUARMState *env)
314 {
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]);
322     }
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);
330 }
331 
332 static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
333                               target_sigset_t *set, CPUARMState *env)
334 {
335     struct target_sigaltstack stack;
336     int i;
337     abi_ulong *regspace;
338 
339     /* Clear all the bits of the ucontext we don't use.  */
340     memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
341 
342     memset(&stack, 0, sizeof(stack));
343     target_save_altstack(&stack, env);
344     memcpy(&uc->tuc_stack, &stack, sizeof(stack));
345 
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);
351     }
352     if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
353         regspace = setup_sigframe_v2_iwmmxt(regspace, env);
354     }
355 
356     /* Write terminating magic word */
357     __put_user(0, regspace);
358 
359     for(i = 0; i < TARGET_NSIG_WORDS; i++) {
360         __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
361     }
362 }
363 
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)
367 {
368     struct sigframe_v1 *frame;
369     abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
370     int i;
371 
372     trace_user_setup_frame(regs, frame_addr);
373     if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
374         goto sigsegv;
375     }
376 
377     setup_sigcontext(&frame->sc, regs, set->sig[0]);
378 
379     for(i = 1; i < TARGET_NSIG_WORDS; i++) {
380         __put_user(set->sig[i], &frame->extramask[i - 1]);
381     }
382 
383     if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
384                      frame_addr + offsetof(struct sigframe_v1, retcode))) {
385         goto sigsegv;
386     }
387 
388     unlock_user_struct(frame, frame_addr, 1);
389     return;
390 sigsegv:
391     unlock_user_struct(frame, frame_addr, 1);
392     force_sigsegv(usig);
393 }
394 
395 static void setup_frame_v2(int usig, struct target_sigaction *ka,
396                            target_sigset_t *set, CPUARMState *regs)
397 {
398     struct sigframe_v2 *frame;
399     abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
400 
401     trace_user_setup_frame(regs, frame_addr);
402     if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
403         goto sigsegv;
404     }
405 
406     setup_sigframe_v2(&frame->uc, set, regs);
407 
408     if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
409                      frame_addr + offsetof(struct sigframe_v2, retcode))) {
410         goto sigsegv;
411     }
412 
413     unlock_user_struct(frame, frame_addr, 1);
414     return;
415 sigsegv:
416     unlock_user_struct(frame, frame_addr, 1);
417     force_sigsegv(usig);
418 }
419 
420 void setup_frame(int usig, struct target_sigaction *ka,
421                  target_sigset_t *set, CPUARMState *regs)
422 {
423     if (get_osversion() >= 0x020612) {
424         setup_frame_v2(usig, ka, set, regs);
425     } else {
426         setup_frame_v1(usig, ka, set, regs);
427     }
428 }
429 
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)
434 {
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;
440 
441     trace_user_setup_rt_frame(env, frame_addr);
442     if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
443         goto sigsegv;
444     }
445 
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);
451 
452     /* Clear all the bits of the ucontext we don't use.  */
453     memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
454 
455     memset(&stack, 0, sizeof(stack));
456     target_save_altstack(&stack, env);
457     memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
458 
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]);
462     }
463 
464     if (setup_return(env, ka, frame->retcode, frame_addr, usig,
465                      frame_addr + offsetof(struct rt_sigframe_v1, retcode))) {
466         goto sigsegv;
467     }
468 
469     env->regs[1] = info_addr;
470     env->regs[2] = uc_addr;
471 
472     unlock_user_struct(frame, frame_addr, 1);
473     return;
474 sigsegv:
475     unlock_user_struct(frame, frame_addr, 1);
476     force_sigsegv(usig);
477 }
478 
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)
482 {
483     struct rt_sigframe_v2 *frame;
484     abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
485     abi_ulong info_addr, uc_addr;
486 
487     trace_user_setup_rt_frame(env, frame_addr);
488     if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
489         goto sigsegv;
490     }
491 
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);
495 
496     setup_sigframe_v2(&frame->uc, set, env);
497 
498     if (setup_return(env, ka, frame->retcode, frame_addr, usig,
499                      frame_addr + offsetof(struct rt_sigframe_v2, retcode))) {
500         goto sigsegv;
501     }
502 
503     env->regs[1] = info_addr;
504     env->regs[2] = uc_addr;
505 
506     unlock_user_struct(frame, frame_addr, 1);
507     return;
508 sigsegv:
509     unlock_user_struct(frame, frame_addr, 1);
510     force_sigsegv(usig);
511 }
512 
513 void setup_rt_frame(int usig, struct target_sigaction *ka,
514                     target_siginfo_t *info,
515                     target_sigset_t *set, CPUARMState *env)
516 {
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);
521     }
522 }
523 
524 static int
525 restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
526 {
527     int err = 0;
528     uint32_t cpsr;
529 
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
550 
551     err |= !valid_user_regs(env);
552 
553     return err;
554 }
555 
556 static long do_sigreturn_v1(CPUARMState *env)
557 {
558     abi_ulong frame_addr;
559     struct sigframe_v1 *frame = NULL;
560     target_sigset_t set;
561     sigset_t host_set;
562     int i;
563 
564     /*
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.
568      */
569     frame_addr = env->regs[13];
570     trace_user_do_sigreturn(env, frame_addr);
571     if (frame_addr & 7) {
572         goto badframe;
573     }
574 
575     if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
576         goto badframe;
577     }
578 
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]);
582     }
583 
584     target_to_host_sigset_internal(&host_set, &set);
585     set_sigmask(&host_set);
586 
587     if (restore_sigcontext(env, &frame->sc)) {
588         goto badframe;
589     }
590 
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;
598 
599 badframe:
600     force_sig(TARGET_SIGSEGV);
601     return -TARGET_QEMU_ESIGRETURN;
602 }
603 
604 static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
605 {
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;
611 
612     __get_user(magic, &vfpframe->magic);
613     __get_user(sz, &vfpframe->size);
614     if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
615         return 0;
616     }
617     for (i = 0; i < 32; i++) {
618         __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
619     }
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
625      */
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);
632 }
633 
634 static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
635                                              abi_ulong *regspace)
636 {
637     int i;
638     abi_ulong magic, sz;
639     struct target_iwmmxt_sigframe *iwmmxtframe;
640     iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
641 
642     __get_user(magic, &iwmmxtframe->magic);
643     __get_user(sz, &iwmmxtframe->size);
644     if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
645         return 0;
646     }
647     for (i = 0; i < 16; i++) {
648         __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
649     }
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);
657 }
658 
659 static int do_sigframe_return_v2(CPUARMState *env,
660                                  target_ulong context_addr,
661                                  struct target_ucontext_v2 *uc)
662 {
663     sigset_t host_set;
664     abi_ulong *regspace;
665 
666     target_to_host_sigset(&host_set, &uc->tuc_sigmask);
667     set_sigmask(&host_set);
668 
669     if (restore_sigcontext(env, &uc->tuc_mcontext))
670         return 1;
671 
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;
678         }
679     }
680     if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
681         regspace = restore_sigframe_v2_iwmmxt(env, regspace);
682         if (!regspace) {
683             return 1;
684         }
685     }
686 
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;
691     }
692 
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
698 
699     return 0;
700 }
701 
702 static long do_sigreturn_v2(CPUARMState *env)
703 {
704     abi_ulong frame_addr;
705     struct sigframe_v2 *frame = NULL;
706 
707     /*
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.
711      */
712     frame_addr = env->regs[13];
713     trace_user_do_sigreturn(env, frame_addr);
714     if (frame_addr & 7) {
715         goto badframe;
716     }
717 
718     if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
719         goto badframe;
720     }
721 
722     if (do_sigframe_return_v2(env,
723                               frame_addr
724                               + offsetof(struct sigframe_v2, uc),
725                               &frame->uc)) {
726         goto badframe;
727     }
728 
729     unlock_user_struct(frame, frame_addr, 0);
730     return -TARGET_QEMU_ESIGRETURN;
731 
732 badframe:
733     unlock_user_struct(frame, frame_addr, 0);
734     force_sig(TARGET_SIGSEGV);
735     return -TARGET_QEMU_ESIGRETURN;
736 }
737 
738 long do_sigreturn(CPUARMState *env)
739 {
740     if (get_osversion() >= 0x020612) {
741         return do_sigreturn_v2(env);
742     } else {
743         return do_sigreturn_v1(env);
744     }
745 }
746 
747 static long do_rt_sigreturn_v1(CPUARMState *env)
748 {
749     abi_ulong frame_addr;
750     struct rt_sigframe_v1 *frame = NULL;
751     sigset_t host_set;
752 
753     /*
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.
757      */
758     frame_addr = env->regs[13];
759     trace_user_do_rt_sigreturn(env, frame_addr);
760     if (frame_addr & 7) {
761         goto badframe;
762     }
763 
764     if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
765         goto badframe;
766     }
767 
768     target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
769     set_sigmask(&host_set);
770 
771     if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
772         goto badframe;
773     }
774 
775     if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
776         goto badframe;
777 
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;
785 
786 badframe:
787     unlock_user_struct(frame, frame_addr, 0);
788     force_sig(TARGET_SIGSEGV);
789     return -TARGET_QEMU_ESIGRETURN;
790 }
791 
792 static long do_rt_sigreturn_v2(CPUARMState *env)
793 {
794     abi_ulong frame_addr;
795     struct rt_sigframe_v2 *frame = NULL;
796 
797     /*
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.
801      */
802     frame_addr = env->regs[13];
803     trace_user_do_rt_sigreturn(env, frame_addr);
804     if (frame_addr & 7) {
805         goto badframe;
806     }
807 
808     if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
809         goto badframe;
810     }
811 
812     if (do_sigframe_return_v2(env,
813                               frame_addr
814                               + offsetof(struct rt_sigframe_v2, uc),
815                               &frame->uc)) {
816         goto badframe;
817     }
818 
819     unlock_user_struct(frame, frame_addr, 0);
820     return -TARGET_QEMU_ESIGRETURN;
821 
822 badframe:
823     unlock_user_struct(frame, frame_addr, 0);
824     force_sig(TARGET_SIGSEGV);
825     return -TARGET_QEMU_ESIGRETURN;
826 }
827 
828 long do_rt_sigreturn(CPUARMState *env)
829 {
830     if (get_osversion() >= 0x020612) {
831         return do_rt_sigreturn_v2(env);
832     } else {
833         return do_rt_sigreturn_v1(env);
834     }
835 }
836