]> git.proxmox.com Git - mirror_qemu.git/blob - linux-user/arm/signal.c
linux-user: introduce target_sigsp() and target_save_altstack()
[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 "target_signal.h"
22 #include "signal-common.h"
23 #include "linux-user/trace.h"
24
25 struct target_sigcontext {
26 abi_ulong trap_no;
27 abi_ulong error_code;
28 abi_ulong oldmask;
29 abi_ulong arm_r0;
30 abi_ulong arm_r1;
31 abi_ulong arm_r2;
32 abi_ulong arm_r3;
33 abi_ulong arm_r4;
34 abi_ulong arm_r5;
35 abi_ulong arm_r6;
36 abi_ulong arm_r7;
37 abi_ulong arm_r8;
38 abi_ulong arm_r9;
39 abi_ulong arm_r10;
40 abi_ulong arm_fp;
41 abi_ulong arm_ip;
42 abi_ulong arm_sp;
43 abi_ulong arm_lr;
44 abi_ulong arm_pc;
45 abi_ulong arm_cpsr;
46 abi_ulong fault_address;
47 };
48
49 struct target_ucontext_v1 {
50 abi_ulong tuc_flags;
51 abi_ulong tuc_link;
52 target_stack_t tuc_stack;
53 struct target_sigcontext tuc_mcontext;
54 target_sigset_t tuc_sigmask; /* mask last for extensibility */
55 };
56
57 struct target_ucontext_v2 {
58 abi_ulong tuc_flags;
59 abi_ulong tuc_link;
60 target_stack_t tuc_stack;
61 struct target_sigcontext tuc_mcontext;
62 target_sigset_t tuc_sigmask; /* mask last for extensibility */
63 char __unused[128 - sizeof(target_sigset_t)];
64 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
65 };
66
67 struct target_user_vfp {
68 uint64_t fpregs[32];
69 abi_ulong fpscr;
70 };
71
72 struct target_user_vfp_exc {
73 abi_ulong fpexc;
74 abi_ulong fpinst;
75 abi_ulong fpinst2;
76 };
77
78 struct target_vfp_sigframe {
79 abi_ulong magic;
80 abi_ulong size;
81 struct target_user_vfp ufp;
82 struct target_user_vfp_exc ufp_exc;
83 } __attribute__((__aligned__(8)));
84
85 struct target_iwmmxt_sigframe {
86 abi_ulong magic;
87 abi_ulong size;
88 uint64_t regs[16];
89 /* Note that not all the coprocessor control registers are stored here */
90 uint32_t wcssf;
91 uint32_t wcasf;
92 uint32_t wcgr0;
93 uint32_t wcgr1;
94 uint32_t wcgr2;
95 uint32_t wcgr3;
96 } __attribute__((__aligned__(8)));
97
98 #define TARGET_VFP_MAGIC 0x56465001
99 #define TARGET_IWMMXT_MAGIC 0x12ef842a
100
101 struct sigframe_v1
102 {
103 struct target_sigcontext sc;
104 abi_ulong extramask[TARGET_NSIG_WORDS-1];
105 abi_ulong retcode[4];
106 };
107
108 struct sigframe_v2
109 {
110 struct target_ucontext_v2 uc;
111 abi_ulong retcode[4];
112 };
113
114 struct rt_sigframe_v1
115 {
116 abi_ulong pinfo;
117 abi_ulong puc;
118 struct target_siginfo info;
119 struct target_ucontext_v1 uc;
120 abi_ulong retcode[4];
121 };
122
123 struct rt_sigframe_v2
124 {
125 struct target_siginfo info;
126 struct target_ucontext_v2 uc;
127 abi_ulong retcode[4];
128 };
129
130 #define TARGET_CONFIG_CPU_32 1
131
132 /*
133 * For ARM syscalls, we encode the syscall number into the instruction.
134 */
135 #define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
136 #define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
137
138 /*
139 * For Thumb syscalls, we pass the syscall number via r7. We therefore
140 * need two 16-bit instructions.
141 */
142 #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
143 #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
144
145 static const abi_ulong retcodes[4] = {
146 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
147 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
148 };
149
150 /*
151 * Stub needed to make sure the FD register (r9) contains the right
152 * value.
153 */
154 static const unsigned long sigreturn_fdpic_codes[3] = {
155 0xe59fc004, /* ldr r12, [pc, #4] to read function descriptor */
156 0xe59c9004, /* ldr r9, [r12, #4] to setup GOT */
157 0xe59cf000 /* ldr pc, [r12] to jump into restorer */
158 };
159
160 static const unsigned long sigreturn_fdpic_thumb_codes[3] = {
161 0xc008f8df, /* ldr r12, [pc, #8] to read function descriptor */
162 0x9004f8dc, /* ldr r9, [r12, #4] to setup GOT */
163 0xf000f8dc /* ldr pc, [r12] to jump into restorer */
164 };
165
166 static inline int valid_user_regs(CPUARMState *regs)
167 {
168 return 1;
169 }
170
171 static void
172 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
173 CPUARMState *env, abi_ulong mask)
174 {
175 __put_user(env->regs[0], &sc->arm_r0);
176 __put_user(env->regs[1], &sc->arm_r1);
177 __put_user(env->regs[2], &sc->arm_r2);
178 __put_user(env->regs[3], &sc->arm_r3);
179 __put_user(env->regs[4], &sc->arm_r4);
180 __put_user(env->regs[5], &sc->arm_r5);
181 __put_user(env->regs[6], &sc->arm_r6);
182 __put_user(env->regs[7], &sc->arm_r7);
183 __put_user(env->regs[8], &sc->arm_r8);
184 __put_user(env->regs[9], &sc->arm_r9);
185 __put_user(env->regs[10], &sc->arm_r10);
186 __put_user(env->regs[11], &sc->arm_fp);
187 __put_user(env->regs[12], &sc->arm_ip);
188 __put_user(env->regs[13], &sc->arm_sp);
189 __put_user(env->regs[14], &sc->arm_lr);
190 __put_user(env->regs[15], &sc->arm_pc);
191 #ifdef TARGET_CONFIG_CPU_32
192 __put_user(cpsr_read(env), &sc->arm_cpsr);
193 #endif
194
195 __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
196 __put_user(/* current->thread.error_code */ 0, &sc->error_code);
197 __put_user(/* current->thread.address */ 0, &sc->fault_address);
198 __put_user(mask, &sc->oldmask);
199 }
200
201 static inline abi_ulong
202 get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
203 {
204 unsigned long sp;
205
206 sp = target_sigsp(get_sp_from_cpustate(regs), ka);
207 /*
208 * ATPCS B01 mandates 8-byte alignment
209 */
210 return (sp - framesize) & ~7;
211 }
212
213 static int
214 setup_return(CPUARMState *env, struct target_sigaction *ka,
215 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
216 {
217 abi_ulong handler = 0;
218 abi_ulong handler_fdpic_GOT = 0;
219 abi_ulong retcode;
220
221 int thumb;
222 int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
223
224 if (is_fdpic) {
225 /* In FDPIC mode, ka->_sa_handler points to a function
226 * descriptor (FD). The first word contains the address of the
227 * handler. The second word contains the value of the PIC
228 * register (r9). */
229 abi_ulong funcdesc_ptr = ka->_sa_handler;
230 if (get_user_ual(handler, funcdesc_ptr)
231 || get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) {
232 return 1;
233 }
234 } else {
235 handler = ka->_sa_handler;
236 }
237
238 thumb = handler & 1;
239
240 uint32_t cpsr = cpsr_read(env);
241
242 cpsr &= ~CPSR_IT;
243 if (thumb) {
244 cpsr |= CPSR_T;
245 } else {
246 cpsr &= ~CPSR_T;
247 }
248
249 if (ka->sa_flags & TARGET_SA_RESTORER) {
250 if (is_fdpic) {
251 /* For FDPIC we ensure that the restorer is called with a
252 * correct r9 value. For that we need to write code on
253 * the stack that sets r9 and jumps back to restorer
254 * value.
255 */
256 if (thumb) {
257 __put_user(sigreturn_fdpic_thumb_codes[0], rc);
258 __put_user(sigreturn_fdpic_thumb_codes[1], rc + 1);
259 __put_user(sigreturn_fdpic_thumb_codes[2], rc + 2);
260 __put_user((abi_ulong)ka->sa_restorer, rc + 3);
261 } else {
262 __put_user(sigreturn_fdpic_codes[0], rc);
263 __put_user(sigreturn_fdpic_codes[1], rc + 1);
264 __put_user(sigreturn_fdpic_codes[2], rc + 2);
265 __put_user((abi_ulong)ka->sa_restorer, rc + 3);
266 }
267
268 retcode = rc_addr + thumb;
269 } else {
270 retcode = ka->sa_restorer;
271 }
272 } else {
273 unsigned int idx = thumb;
274
275 if (ka->sa_flags & TARGET_SA_SIGINFO) {
276 idx += 2;
277 }
278
279 __put_user(retcodes[idx], rc);
280
281 retcode = rc_addr + thumb;
282 }
283
284 env->regs[0] = usig;
285 if (is_fdpic) {
286 env->regs[9] = handler_fdpic_GOT;
287 }
288 env->regs[13] = frame_addr;
289 env->regs[14] = retcode;
290 env->regs[15] = handler & (thumb ? ~1 : ~3);
291 cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
292
293 return 0;
294 }
295
296 static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
297 {
298 int i;
299 struct target_vfp_sigframe *vfpframe;
300 vfpframe = (struct target_vfp_sigframe *)regspace;
301 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
302 __put_user(sizeof(*vfpframe), &vfpframe->size);
303 for (i = 0; i < 32; i++) {
304 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
305 }
306 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
307 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
308 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
309 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
310 return (abi_ulong*)(vfpframe+1);
311 }
312
313 static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
314 CPUARMState *env)
315 {
316 int i;
317 struct target_iwmmxt_sigframe *iwmmxtframe;
318 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
319 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
320 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
321 for (i = 0; i < 16; i++) {
322 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
323 }
324 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
325 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
326 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
327 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
328 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
329 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
330 return (abi_ulong*)(iwmmxtframe+1);
331 }
332
333 static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
334 target_sigset_t *set, CPUARMState *env)
335 {
336 struct target_sigaltstack stack;
337 int i;
338 abi_ulong *regspace;
339
340 /* Clear all the bits of the ucontext we don't use. */
341 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
342
343 memset(&stack, 0, sizeof(stack));
344 target_save_altstack(&stack, env);
345 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
346
347 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
348 /* Save coprocessor signal frame. */
349 regspace = uc->tuc_regspace;
350 if (arm_feature(env, ARM_FEATURE_VFP)) {
351 regspace = setup_sigframe_v2_vfp(regspace, env);
352 }
353 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
354 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
355 }
356
357 /* Write terminating magic word */
358 __put_user(0, regspace);
359
360 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
361 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
362 }
363 }
364
365 /* compare linux/arch/arm/kernel/signal.c:setup_frame() */
366 static void setup_frame_v1(int usig, struct target_sigaction *ka,
367 target_sigset_t *set, CPUARMState *regs)
368 {
369 struct sigframe_v1 *frame;
370 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
371 int i;
372
373 trace_user_setup_frame(regs, frame_addr);
374 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
375 goto sigsegv;
376 }
377
378 setup_sigcontext(&frame->sc, regs, set->sig[0]);
379
380 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
381 __put_user(set->sig[i], &frame->extramask[i - 1]);
382 }
383
384 if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
385 frame_addr + offsetof(struct sigframe_v1, retcode))) {
386 goto sigsegv;
387 }
388
389 unlock_user_struct(frame, frame_addr, 1);
390 return;
391 sigsegv:
392 unlock_user_struct(frame, frame_addr, 1);
393 force_sigsegv(usig);
394 }
395
396 static void setup_frame_v2(int usig, struct target_sigaction *ka,
397 target_sigset_t *set, CPUARMState *regs)
398 {
399 struct sigframe_v2 *frame;
400 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
401
402 trace_user_setup_frame(regs, frame_addr);
403 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
404 goto sigsegv;
405 }
406
407 setup_sigframe_v2(&frame->uc, set, regs);
408
409 if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
410 frame_addr + offsetof(struct sigframe_v2, retcode))) {
411 goto sigsegv;
412 }
413
414 unlock_user_struct(frame, frame_addr, 1);
415 return;
416 sigsegv:
417 unlock_user_struct(frame, frame_addr, 1);
418 force_sigsegv(usig);
419 }
420
421 void setup_frame(int usig, struct target_sigaction *ka,
422 target_sigset_t *set, CPUARMState *regs)
423 {
424 if (get_osversion() >= 0x020612) {
425 setup_frame_v2(usig, ka, set, regs);
426 } else {
427 setup_frame_v1(usig, ka, set, regs);
428 }
429 }
430
431 /* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
432 static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
433 target_siginfo_t *info,
434 target_sigset_t *set, CPUARMState *env)
435 {
436 struct rt_sigframe_v1 *frame;
437 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
438 struct target_sigaltstack stack;
439 int i;
440 abi_ulong info_addr, uc_addr;
441
442 trace_user_setup_rt_frame(env, frame_addr);
443 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
444 goto sigsegv;
445 }
446
447 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
448 __put_user(info_addr, &frame->pinfo);
449 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
450 __put_user(uc_addr, &frame->puc);
451 tswap_siginfo(&frame->info, info);
452
453 /* Clear all the bits of the ucontext we don't use. */
454 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
455
456 memset(&stack, 0, sizeof(stack));
457 target_save_altstack(&stack, env);
458 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
459
460 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
461 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
462 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
463 }
464
465 if (setup_return(env, ka, frame->retcode, frame_addr, usig,
466 frame_addr + offsetof(struct rt_sigframe_v1, retcode))) {
467 goto sigsegv;
468 }
469
470 env->regs[1] = info_addr;
471 env->regs[2] = uc_addr;
472
473 unlock_user_struct(frame, frame_addr, 1);
474 return;
475 sigsegv:
476 unlock_user_struct(frame, frame_addr, 1);
477 force_sigsegv(usig);
478 }
479
480 static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
481 target_siginfo_t *info,
482 target_sigset_t *set, CPUARMState *env)
483 {
484 struct rt_sigframe_v2 *frame;
485 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
486 abi_ulong info_addr, uc_addr;
487
488 trace_user_setup_rt_frame(env, frame_addr);
489 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
490 goto sigsegv;
491 }
492
493 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
494 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
495 tswap_siginfo(&frame->info, info);
496
497 setup_sigframe_v2(&frame->uc, set, env);
498
499 if (setup_return(env, ka, frame->retcode, frame_addr, usig,
500 frame_addr + offsetof(struct rt_sigframe_v2, retcode))) {
501 goto sigsegv;
502 }
503
504 env->regs[1] = info_addr;
505 env->regs[2] = uc_addr;
506
507 unlock_user_struct(frame, frame_addr, 1);
508 return;
509 sigsegv:
510 unlock_user_struct(frame, frame_addr, 1);
511 force_sigsegv(usig);
512 }
513
514 void setup_rt_frame(int usig, struct target_sigaction *ka,
515 target_siginfo_t *info,
516 target_sigset_t *set, CPUARMState *env)
517 {
518 if (get_osversion() >= 0x020612) {
519 setup_rt_frame_v2(usig, ka, info, set, env);
520 } else {
521 setup_rt_frame_v1(usig, ka, info, set, env);
522 }
523 }
524
525 static int
526 restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
527 {
528 int err = 0;
529 uint32_t cpsr;
530
531 __get_user(env->regs[0], &sc->arm_r0);
532 __get_user(env->regs[1], &sc->arm_r1);
533 __get_user(env->regs[2], &sc->arm_r2);
534 __get_user(env->regs[3], &sc->arm_r3);
535 __get_user(env->regs[4], &sc->arm_r4);
536 __get_user(env->regs[5], &sc->arm_r5);
537 __get_user(env->regs[6], &sc->arm_r6);
538 __get_user(env->regs[7], &sc->arm_r7);
539 __get_user(env->regs[8], &sc->arm_r8);
540 __get_user(env->regs[9], &sc->arm_r9);
541 __get_user(env->regs[10], &sc->arm_r10);
542 __get_user(env->regs[11], &sc->arm_fp);
543 __get_user(env->regs[12], &sc->arm_ip);
544 __get_user(env->regs[13], &sc->arm_sp);
545 __get_user(env->regs[14], &sc->arm_lr);
546 __get_user(env->regs[15], &sc->arm_pc);
547 #ifdef TARGET_CONFIG_CPU_32
548 __get_user(cpsr, &sc->arm_cpsr);
549 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
550 #endif
551
552 err |= !valid_user_regs(env);
553
554 return err;
555 }
556
557 static long do_sigreturn_v1(CPUARMState *env)
558 {
559 abi_ulong frame_addr;
560 struct sigframe_v1 *frame = NULL;
561 target_sigset_t set;
562 sigset_t host_set;
563 int i;
564
565 /*
566 * Since we stacked the signal on a 64-bit boundary,
567 * then 'sp' should be word aligned here. If it's
568 * not, then the user is trying to mess with us.
569 */
570 frame_addr = env->regs[13];
571 trace_user_do_sigreturn(env, frame_addr);
572 if (frame_addr & 7) {
573 goto badframe;
574 }
575
576 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
577 goto badframe;
578 }
579
580 __get_user(set.sig[0], &frame->sc.oldmask);
581 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
582 __get_user(set.sig[i], &frame->extramask[i - 1]);
583 }
584
585 target_to_host_sigset_internal(&host_set, &set);
586 set_sigmask(&host_set);
587
588 if (restore_sigcontext(env, &frame->sc)) {
589 goto badframe;
590 }
591
592 #if 0
593 /* Send SIGTRAP if we're single-stepping */
594 if (ptrace_cancel_bpt(current))
595 send_sig(SIGTRAP, current, 1);
596 #endif
597 unlock_user_struct(frame, frame_addr, 0);
598 return -TARGET_QEMU_ESIGRETURN;
599
600 badframe:
601 force_sig(TARGET_SIGSEGV);
602 return -TARGET_QEMU_ESIGRETURN;
603 }
604
605 static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
606 {
607 int i;
608 abi_ulong magic, sz;
609 uint32_t fpscr, fpexc;
610 struct target_vfp_sigframe *vfpframe;
611 vfpframe = (struct target_vfp_sigframe *)regspace;
612
613 __get_user(magic, &vfpframe->magic);
614 __get_user(sz, &vfpframe->size);
615 if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
616 return 0;
617 }
618 for (i = 0; i < 32; i++) {
619 __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
620 }
621 __get_user(fpscr, &vfpframe->ufp.fpscr);
622 vfp_set_fpscr(env, fpscr);
623 __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
624 /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
625 * and the exception flag is cleared
626 */
627 fpexc |= (1 << 30);
628 fpexc &= ~((1 << 31) | (1 << 28));
629 env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
630 __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
631 __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
632 return (abi_ulong*)(vfpframe + 1);
633 }
634
635 static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
636 abi_ulong *regspace)
637 {
638 int i;
639 abi_ulong magic, sz;
640 struct target_iwmmxt_sigframe *iwmmxtframe;
641 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
642
643 __get_user(magic, &iwmmxtframe->magic);
644 __get_user(sz, &iwmmxtframe->size);
645 if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
646 return 0;
647 }
648 for (i = 0; i < 16; i++) {
649 __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
650 }
651 __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
652 __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
653 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
654 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
655 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
656 __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
657 return (abi_ulong*)(iwmmxtframe + 1);
658 }
659
660 static int do_sigframe_return_v2(CPUARMState *env,
661 target_ulong context_addr,
662 struct target_ucontext_v2 *uc)
663 {
664 sigset_t host_set;
665 abi_ulong *regspace;
666
667 target_to_host_sigset(&host_set, &uc->tuc_sigmask);
668 set_sigmask(&host_set);
669
670 if (restore_sigcontext(env, &uc->tuc_mcontext))
671 return 1;
672
673 /* Restore coprocessor signal frame */
674 regspace = uc->tuc_regspace;
675 if (arm_feature(env, ARM_FEATURE_VFP)) {
676 regspace = restore_sigframe_v2_vfp(env, regspace);
677 if (!regspace) {
678 return 1;
679 }
680 }
681 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
682 regspace = restore_sigframe_v2_iwmmxt(env, regspace);
683 if (!regspace) {
684 return 1;
685 }
686 }
687
688 if (do_sigaltstack(context_addr
689 + offsetof(struct target_ucontext_v2, tuc_stack),
690 0, get_sp_from_cpustate(env)) == -EFAULT) {
691 return 1;
692 }
693
694 #if 0
695 /* Send SIGTRAP if we're single-stepping */
696 if (ptrace_cancel_bpt(current))
697 send_sig(SIGTRAP, current, 1);
698 #endif
699
700 return 0;
701 }
702
703 static long do_sigreturn_v2(CPUARMState *env)
704 {
705 abi_ulong frame_addr;
706 struct sigframe_v2 *frame = NULL;
707
708 /*
709 * Since we stacked the signal on a 64-bit boundary,
710 * then 'sp' should be word aligned here. If it's
711 * not, then the user is trying to mess with us.
712 */
713 frame_addr = env->regs[13];
714 trace_user_do_sigreturn(env, frame_addr);
715 if (frame_addr & 7) {
716 goto badframe;
717 }
718
719 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
720 goto badframe;
721 }
722
723 if (do_sigframe_return_v2(env,
724 frame_addr
725 + offsetof(struct sigframe_v2, uc),
726 &frame->uc)) {
727 goto badframe;
728 }
729
730 unlock_user_struct(frame, frame_addr, 0);
731 return -TARGET_QEMU_ESIGRETURN;
732
733 badframe:
734 unlock_user_struct(frame, frame_addr, 0);
735 force_sig(TARGET_SIGSEGV);
736 return -TARGET_QEMU_ESIGRETURN;
737 }
738
739 long do_sigreturn(CPUARMState *env)
740 {
741 if (get_osversion() >= 0x020612) {
742 return do_sigreturn_v2(env);
743 } else {
744 return do_sigreturn_v1(env);
745 }
746 }
747
748 static long do_rt_sigreturn_v1(CPUARMState *env)
749 {
750 abi_ulong frame_addr;
751 struct rt_sigframe_v1 *frame = NULL;
752 sigset_t host_set;
753
754 /*
755 * Since we stacked the signal on a 64-bit boundary,
756 * then 'sp' should be word aligned here. If it's
757 * not, then the user is trying to mess with us.
758 */
759 frame_addr = env->regs[13];
760 trace_user_do_rt_sigreturn(env, frame_addr);
761 if (frame_addr & 7) {
762 goto badframe;
763 }
764
765 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
766 goto badframe;
767 }
768
769 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
770 set_sigmask(&host_set);
771
772 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
773 goto badframe;
774 }
775
776 if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
777 goto badframe;
778
779 #if 0
780 /* Send SIGTRAP if we're single-stepping */
781 if (ptrace_cancel_bpt(current))
782 send_sig(SIGTRAP, current, 1);
783 #endif
784 unlock_user_struct(frame, frame_addr, 0);
785 return -TARGET_QEMU_ESIGRETURN;
786
787 badframe:
788 unlock_user_struct(frame, frame_addr, 0);
789 force_sig(TARGET_SIGSEGV);
790 return -TARGET_QEMU_ESIGRETURN;
791 }
792
793 static long do_rt_sigreturn_v2(CPUARMState *env)
794 {
795 abi_ulong frame_addr;
796 struct rt_sigframe_v2 *frame = NULL;
797
798 /*
799 * Since we stacked the signal on a 64-bit boundary,
800 * then 'sp' should be word aligned here. If it's
801 * not, then the user is trying to mess with us.
802 */
803 frame_addr = env->regs[13];
804 trace_user_do_rt_sigreturn(env, frame_addr);
805 if (frame_addr & 7) {
806 goto badframe;
807 }
808
809 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
810 goto badframe;
811 }
812
813 if (do_sigframe_return_v2(env,
814 frame_addr
815 + offsetof(struct rt_sigframe_v2, uc),
816 &frame->uc)) {
817 goto badframe;
818 }
819
820 unlock_user_struct(frame, frame_addr, 0);
821 return -TARGET_QEMU_ESIGRETURN;
822
823 badframe:
824 unlock_user_struct(frame, frame_addr, 0);
825 force_sig(TARGET_SIGSEGV);
826 return -TARGET_QEMU_ESIGRETURN;
827 }
828
829 long do_rt_sigreturn(CPUARMState *env)
830 {
831 if (get_osversion() >= 0x020612) {
832 return do_rt_sigreturn_v2(env);
833 } else {
834 return do_rt_sigreturn_v1(env);
835 }
836 }