1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "qemu/osdep.h"
20#include "qemu.h"
21#include "signal-common.h"
22#include "linux-user/trace.h"
23
24struct 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
48struct 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;
54};
55
56struct 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;
62 char __unused[128 - sizeof(target_sigset_t)];
63 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
64};
65
66struct target_user_vfp {
67 uint64_t fpregs[32];
68 abi_ulong fpscr;
69};
70
71struct target_user_vfp_exc {
72 abi_ulong fpexc;
73 abi_ulong fpinst;
74 abi_ulong fpinst2;
75};
76
77struct 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
84struct target_iwmmxt_sigframe {
85 abi_ulong magic;
86 abi_ulong size;
87 uint64_t regs[16];
88
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
100struct sigframe_v1
101{
102 struct target_sigcontext sc;
103 abi_ulong extramask[TARGET_NSIG_WORDS-1];
104 abi_ulong retcode[4];
105};
106
107struct sigframe_v2
108{
109 struct target_ucontext_v2 uc;
110 abi_ulong retcode[4];
111};
112
113struct 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
122struct rt_sigframe_v2
123{
124 struct target_siginfo info;
125 struct target_ucontext_v2 uc;
126 abi_ulong retcode[4];
127};
128
129
130
131
132#define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
133#define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
134
135
136
137
138
139#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
140#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
141
142static const abi_ulong retcodes[4] = {
143 SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
144 SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
145};
146
147
148
149
150
151static const unsigned long sigreturn_fdpic_codes[3] = {
152 0xe59fc004,
153 0xe59c9004,
154 0xe59cf000
155};
156
157static const unsigned long sigreturn_fdpic_thumb_codes[3] = {
158 0xc008f8df,
159 0x9004f8dc,
160 0xf000f8dc
161};
162
163static inline int valid_user_regs(CPUARMState *regs)
164{
165 return 1;
166}
167
168static void
169setup_sigcontext(struct target_sigcontext *sc,
170 CPUARMState *env, abi_ulong mask)
171{
172 __put_user(env->regs[0], &sc->arm_r0);
173 __put_user(env->regs[1], &sc->arm_r1);
174 __put_user(env->regs[2], &sc->arm_r2);
175 __put_user(env->regs[3], &sc->arm_r3);
176 __put_user(env->regs[4], &sc->arm_r4);
177 __put_user(env->regs[5], &sc->arm_r5);
178 __put_user(env->regs[6], &sc->arm_r6);
179 __put_user(env->regs[7], &sc->arm_r7);
180 __put_user(env->regs[8], &sc->arm_r8);
181 __put_user(env->regs[9], &sc->arm_r9);
182 __put_user(env->regs[10], &sc->arm_r10);
183 __put_user(env->regs[11], &sc->arm_fp);
184 __put_user(env->regs[12], &sc->arm_ip);
185 __put_user(env->regs[13], &sc->arm_sp);
186 __put_user(env->regs[14], &sc->arm_lr);
187 __put_user(env->regs[15], &sc->arm_pc);
188 __put_user(cpsr_read(env), &sc->arm_cpsr);
189
190 __put_user( 0, &sc->trap_no);
191 __put_user( 0, &sc->error_code);
192 __put_user( 0, &sc->fault_address);
193 __put_user(mask, &sc->oldmask);
194}
195
196static inline abi_ulong
197get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
198{
199 unsigned long sp;
200
201 sp = target_sigsp(get_sp_from_cpustate(regs), ka);
202
203
204
205 return (sp - framesize) & ~7;
206}
207
208static int
209setup_return(CPUARMState *env, struct target_sigaction *ka,
210 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
211{
212 abi_ulong handler = 0;
213 abi_ulong handler_fdpic_GOT = 0;
214 abi_ulong retcode;
215
216 int thumb;
217 int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
218
219 if (is_fdpic) {
220
221
222
223
224 abi_ulong funcdesc_ptr = ka->_sa_handler;
225 if (get_user_ual(handler, funcdesc_ptr)
226 || get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) {
227 return 1;
228 }
229 } else {
230 handler = ka->_sa_handler;
231 }
232
233 thumb = handler & 1;
234
235 uint32_t cpsr = cpsr_read(env);
236
237 cpsr &= ~CPSR_IT;
238 if (thumb) {
239 cpsr |= CPSR_T;
240 } else {
241 cpsr &= ~CPSR_T;
242 }
243 if (env->cp15.sctlr_el[1] & SCTLR_E0E) {
244 cpsr |= CPSR_E;
245 } else {
246 cpsr &= ~CPSR_E;
247 }
248
249 if (ka->sa_flags & TARGET_SA_RESTORER) {
250 if (is_fdpic) {
251
252
253
254
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 | CPSR_E, CPSRWriteByInstr);
292 arm_rebuild_hflags(env);
293
294 return 0;
295}
296
297static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
298{
299 int i;
300 struct target_vfp_sigframe *vfpframe;
301 vfpframe = (struct target_vfp_sigframe *)regspace;
302 __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
303 __put_user(sizeof(*vfpframe), &vfpframe->size);
304 for (i = 0; i < 32; i++) {
305 __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
306 }
307 __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
308 __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
309 __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
310 __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
311 return (abi_ulong*)(vfpframe+1);
312}
313
314static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
315 CPUARMState *env)
316{
317 int i;
318 struct target_iwmmxt_sigframe *iwmmxtframe;
319 iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
320 __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
321 __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
322 for (i = 0; i < 16; i++) {
323 __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
324 }
325 __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
326 __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
327 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
328 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
329 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
330 __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
331 return (abi_ulong*)(iwmmxtframe+1);
332}
333
334static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
335 target_sigset_t *set, CPUARMState *env)
336{
337 struct target_sigaltstack stack;
338 int i;
339 abi_ulong *regspace;
340
341
342 memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
343
344 memset(&stack, 0, sizeof(stack));
345 target_save_altstack(&stack, env);
346 memcpy(&uc->tuc_stack, &stack, sizeof(stack));
347
348 setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
349
350 regspace = uc->tuc_regspace;
351 if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
352 regspace = setup_sigframe_v2_vfp(regspace, env);
353 }
354 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
355 regspace = setup_sigframe_v2_iwmmxt(regspace, env);
356 }
357
358
359 __put_user(0, regspace);
360
361 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
362 __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
363 }
364}
365
366
367static void setup_frame_v1(int usig, struct target_sigaction *ka,
368 target_sigset_t *set, CPUARMState *regs)
369{
370 struct sigframe_v1 *frame;
371 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
372 int i;
373
374 trace_user_setup_frame(regs, frame_addr);
375 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
376 goto sigsegv;
377 }
378
379 setup_sigcontext(&frame->sc, regs, set->sig[0]);
380
381 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
382 __put_user(set->sig[i], &frame->extramask[i - 1]);
383 }
384
385 if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
386 frame_addr + offsetof(struct sigframe_v1, retcode))) {
387 goto sigsegv;
388 }
389
390 unlock_user_struct(frame, frame_addr, 1);
391 return;
392sigsegv:
393 unlock_user_struct(frame, frame_addr, 1);
394 force_sigsegv(usig);
395}
396
397static void setup_frame_v2(int usig, struct target_sigaction *ka,
398 target_sigset_t *set, CPUARMState *regs)
399{
400 struct sigframe_v2 *frame;
401 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
402
403 trace_user_setup_frame(regs, frame_addr);
404 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
405 goto sigsegv;
406 }
407
408 setup_sigframe_v2(&frame->uc, set, regs);
409
410 if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
411 frame_addr + offsetof(struct sigframe_v2, retcode))) {
412 goto sigsegv;
413 }
414
415 unlock_user_struct(frame, frame_addr, 1);
416 return;
417sigsegv:
418 unlock_user_struct(frame, frame_addr, 1);
419 force_sigsegv(usig);
420}
421
422void setup_frame(int usig, struct target_sigaction *ka,
423 target_sigset_t *set, CPUARMState *regs)
424{
425 if (get_osversion() >= 0x020612) {
426 setup_frame_v2(usig, ka, set, regs);
427 } else {
428 setup_frame_v1(usig, ka, set, regs);
429 }
430}
431
432
433static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
434 target_siginfo_t *info,
435 target_sigset_t *set, CPUARMState *env)
436{
437 struct rt_sigframe_v1 *frame;
438 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
439 struct target_sigaltstack stack;
440 int i;
441 abi_ulong info_addr, uc_addr;
442
443 trace_user_setup_rt_frame(env, frame_addr);
444 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
445 goto sigsegv;
446 }
447
448 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
449 __put_user(info_addr, &frame->pinfo);
450 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
451 __put_user(uc_addr, &frame->puc);
452 tswap_siginfo(&frame->info, info);
453
454
455 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
456
457 memset(&stack, 0, sizeof(stack));
458 target_save_altstack(&stack, env);
459 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
460
461 setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
462 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
463 __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
464 }
465
466 if (setup_return(env, ka, frame->retcode, frame_addr, usig,
467 frame_addr + offsetof(struct rt_sigframe_v1, retcode))) {
468 goto sigsegv;
469 }
470
471 env->regs[1] = info_addr;
472 env->regs[2] = uc_addr;
473
474 unlock_user_struct(frame, frame_addr, 1);
475 return;
476sigsegv:
477 unlock_user_struct(frame, frame_addr, 1);
478 force_sigsegv(usig);
479}
480
481static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
482 target_siginfo_t *info,
483 target_sigset_t *set, CPUARMState *env)
484{
485 struct rt_sigframe_v2 *frame;
486 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
487 abi_ulong info_addr, uc_addr;
488
489 trace_user_setup_rt_frame(env, frame_addr);
490 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
491 goto sigsegv;
492 }
493
494 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
495 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
496 tswap_siginfo(&frame->info, info);
497
498 setup_sigframe_v2(&frame->uc, set, env);
499
500 if (setup_return(env, ka, frame->retcode, frame_addr, usig,
501 frame_addr + offsetof(struct rt_sigframe_v2, retcode))) {
502 goto sigsegv;
503 }
504
505 env->regs[1] = info_addr;
506 env->regs[2] = uc_addr;
507
508 unlock_user_struct(frame, frame_addr, 1);
509 return;
510sigsegv:
511 unlock_user_struct(frame, frame_addr, 1);
512 force_sigsegv(usig);
513}
514
515void setup_rt_frame(int usig, struct target_sigaction *ka,
516 target_siginfo_t *info,
517 target_sigset_t *set, CPUARMState *env)
518{
519 if (get_osversion() >= 0x020612) {
520 setup_rt_frame_v2(usig, ka, info, set, env);
521 } else {
522 setup_rt_frame_v1(usig, ka, info, set, env);
523 }
524}
525
526static int
527restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
528{
529 int err = 0;
530 uint32_t cpsr;
531
532 __get_user(env->regs[0], &sc->arm_r0);
533 __get_user(env->regs[1], &sc->arm_r1);
534 __get_user(env->regs[2], &sc->arm_r2);
535 __get_user(env->regs[3], &sc->arm_r3);
536 __get_user(env->regs[4], &sc->arm_r4);
537 __get_user(env->regs[5], &sc->arm_r5);
538 __get_user(env->regs[6], &sc->arm_r6);
539 __get_user(env->regs[7], &sc->arm_r7);
540 __get_user(env->regs[8], &sc->arm_r8);
541 __get_user(env->regs[9], &sc->arm_r9);
542 __get_user(env->regs[10], &sc->arm_r10);
543 __get_user(env->regs[11], &sc->arm_fp);
544 __get_user(env->regs[12], &sc->arm_ip);
545 __get_user(env->regs[13], &sc->arm_sp);
546 __get_user(env->regs[14], &sc->arm_lr);
547 __get_user(env->regs[15], &sc->arm_pc);
548 __get_user(cpsr, &sc->arm_cpsr);
549 cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
550 arm_rebuild_hflags(env);
551
552 err |= !valid_user_regs(env);
553
554 return err;
555}
556
557static 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
567
568
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
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
600badframe:
601 force_sig(TARGET_SIGSEGV);
602 return -TARGET_QEMU_ESIGRETURN;
603}
604
605static 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
625
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
635static 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
660static 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
674 regspace = uc->tuc_regspace;
675 if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
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 target_restore_altstack(&uc->tuc_stack, env);
689
690#if 0
691
692 if (ptrace_cancel_bpt(current))
693 send_sig(SIGTRAP, current, 1);
694#endif
695
696 return 0;
697}
698
699static long do_sigreturn_v2(CPUARMState *env)
700{
701 abi_ulong frame_addr;
702 struct sigframe_v2 *frame = NULL;
703
704
705
706
707
708
709 frame_addr = env->regs[13];
710 trace_user_do_sigreturn(env, frame_addr);
711 if (frame_addr & 7) {
712 goto badframe;
713 }
714
715 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
716 goto badframe;
717 }
718
719 if (do_sigframe_return_v2(env,
720 frame_addr
721 + offsetof(struct sigframe_v2, uc),
722 &frame->uc)) {
723 goto badframe;
724 }
725
726 unlock_user_struct(frame, frame_addr, 0);
727 return -TARGET_QEMU_ESIGRETURN;
728
729badframe:
730 unlock_user_struct(frame, frame_addr, 0);
731 force_sig(TARGET_SIGSEGV);
732 return -TARGET_QEMU_ESIGRETURN;
733}
734
735long do_sigreturn(CPUARMState *env)
736{
737 if (get_osversion() >= 0x020612) {
738 return do_sigreturn_v2(env);
739 } else {
740 return do_sigreturn_v1(env);
741 }
742}
743
744static long do_rt_sigreturn_v1(CPUARMState *env)
745{
746 abi_ulong frame_addr;
747 struct rt_sigframe_v1 *frame = NULL;
748 sigset_t host_set;
749
750
751
752
753
754
755 frame_addr = env->regs[13];
756 trace_user_do_rt_sigreturn(env, frame_addr);
757 if (frame_addr & 7) {
758 goto badframe;
759 }
760
761 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
762 goto badframe;
763 }
764
765 target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
766 set_sigmask(&host_set);
767
768 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
769 goto badframe;
770 }
771
772 target_restore_altstack(&frame->uc.tuc_stack, env);
773
774#if 0
775
776 if (ptrace_cancel_bpt(current))
777 send_sig(SIGTRAP, current, 1);
778#endif
779 unlock_user_struct(frame, frame_addr, 0);
780 return -TARGET_QEMU_ESIGRETURN;
781
782badframe:
783 unlock_user_struct(frame, frame_addr, 0);
784 force_sig(TARGET_SIGSEGV);
785 return -TARGET_QEMU_ESIGRETURN;
786}
787
788static long do_rt_sigreturn_v2(CPUARMState *env)
789{
790 abi_ulong frame_addr;
791 struct rt_sigframe_v2 *frame = NULL;
792
793
794
795
796
797
798 frame_addr = env->regs[13];
799 trace_user_do_rt_sigreturn(env, frame_addr);
800 if (frame_addr & 7) {
801 goto badframe;
802 }
803
804 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
805 goto badframe;
806 }
807
808 if (do_sigframe_return_v2(env,
809 frame_addr
810 + offsetof(struct rt_sigframe_v2, uc),
811 &frame->uc)) {
812 goto badframe;
813 }
814
815 unlock_user_struct(frame, frame_addr, 0);
816 return -TARGET_QEMU_ESIGRETURN;
817
818badframe:
819 unlock_user_struct(frame, frame_addr, 0);
820 force_sig(TARGET_SIGSEGV);
821 return -TARGET_QEMU_ESIGRETURN;
822}
823
824long do_rt_sigreturn(CPUARMState *env)
825{
826 if (get_osversion() >= 0x020612) {
827 return do_rt_sigreturn_v2(env);
828 } else {
829 return do_rt_sigreturn_v1(env);
830 }
831}
832