]> git.proxmox.com Git - mirror_qemu.git/blob - linux-user/arm/signal.c
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-next-280519-2' into...
[mirror_qemu.git] / linux-user / arm / signal.c
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 }