10 #include <linux/errno.h>
11 #include <linux/signal.h>
12 #include <linux/personality.h>
17 #include <asm/cacheflush.h>
18 #include <asm/ucontext.h>
19 #include <asm/unistd.h>
27 #define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE))
28 #define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE))
33 #define MOV_R7_NR_SIGRETURN (0xe3a07000 | (__NR_sigreturn - __NR_SYSCALL_BASE))
34 #define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
40 #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
41 #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
54 siginitset(&blocked, mask);
73 siginitset(&new_ka.
sa.sa_mask, mask);
91 static int preserve_crunch_context(
struct crunch_sigframe __user *
frame)
93 char kbuf[
sizeof(*frame) + 8];
94 struct crunch_sigframe *kframe;
97 kframe = (
struct crunch_sigframe *)((
unsigned long)(kbuf + 8) & ~7);
98 kframe->magic = CRUNCH_MAGIC;
99 kframe->size = CRUNCH_STORAGE_SIZE;
104 static int restore_crunch_context(
struct crunch_sigframe __user *frame)
106 char kbuf[
sizeof(*frame) + 8];
107 struct crunch_sigframe *kframe;
110 kframe = (
struct crunch_sigframe *)((
unsigned long)(kbuf + 8) & ~7);
113 if (kframe->magic != CRUNCH_MAGIC ||
114 kframe->size != CRUNCH_STORAGE_SIZE)
123 static int preserve_iwmmxt_context(
struct iwmmxt_sigframe *frame)
125 char kbuf[
sizeof(*frame) + 8];
126 struct iwmmxt_sigframe *kframe;
129 kframe = (
struct iwmmxt_sigframe *)((
unsigned long)(kbuf + 8) & ~7);
130 kframe->magic = IWMMXT_MAGIC;
131 kframe->size = IWMMXT_STORAGE_SIZE;
136 static int restore_iwmmxt_context(
struct iwmmxt_sigframe *frame)
138 char kbuf[
sizeof(*frame) + 8];
139 struct iwmmxt_sigframe *kframe;
142 kframe = (
struct iwmmxt_sigframe *)((
unsigned long)(kbuf + 8) & ~7);
145 if (kframe->magic != IWMMXT_MAGIC ||
146 kframe->size != IWMMXT_STORAGE_SIZE)
156 static int preserve_vfp_context(
struct vfp_sigframe __user *frame)
171 static int restore_vfp_context(
struct vfp_sigframe __user *frame)
231 err |= !valid_user_regs(regs);
233 aux = (
struct aux_sigframe
__user *) sf->uc.uc_regspace;
236 err |= restore_crunch_context(&aux->crunch);
239 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
240 err |= restore_iwmmxt_context(&aux->iwmmxt);
244 err |= restore_vfp_context(&aux->vfp);
262 if (regs->ARM_sp & 7)
265 frame = (
struct sigframe __user *)regs->ARM_sp;
270 if (restore_sigframe(regs, frame))
292 if (regs->ARM_sp & 7)
300 if (restore_sigframe(regs, &frame->
sig))
344 aux = (
struct aux_sigframe
__user *) sf->uc.uc_regspace;
347 err |= preserve_crunch_context(&aux->crunch);
350 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
351 err |= preserve_iwmmxt_context(&aux->iwmmxt);
355 err |= preserve_vfp_context(&aux->vfp);
362 static inline void __user *
365 unsigned long sp = regs->ARM_sp;
371 if ((ka->
sa.sa_flags &
SA_ONSTACK) && !sas_ss_flags(sp))
377 frame = (
void __user *)((sp - framesize) & ~7);
390 unsigned long __user *
rc,
void __user *frame,
int usig)
405 #ifdef CONFIG_ARM_THUMB
415 #if __LINUX_ARM_ARCH__ >= 7
427 unsigned int idx = thumb << 1;
448 (
unsigned long)(rc + 2));
455 regs->ARM_sp = (
unsigned long)frame;
457 regs->ARM_pc = handler;
458 regs->ARM_cpsr = cpsr;
466 struct sigframe __user *frame = get_sigframe(ka, regs,
sizeof(*frame));
477 err |= setup_sigframe(frame, regs,
set);
479 err = setup_return(regs, ka, frame->
retcode, frame, usig);
500 memset(&stack, 0,
sizeof(stack));
502 stack.
ss_flags = sas_ss_flags(regs->ARM_sp);
506 err |= setup_sigframe(&frame->
sig, regs,
set);
508 err = setup_return(regs, ka, frame->
sig.retcode, frame, usig);
516 regs->ARM_r1 = (
unsigned long)&frame->
info;
517 regs->ARM_r2 = (
unsigned long)&frame->
sig.uc;
532 sigset_t *oldset = sigmask_to_save();
546 ret = setup_rt_frame(usig, ka, info, oldset, regs);
548 ret = setup_frame(usig, ka, oldset, regs);
553 ret |= !valid_user_regs(regs);
573 unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
583 continue_addr = regs->ARM_pc;
584 restart_addr = continue_addr - (
thumb_mode(regs) ? 2 : 4);
585 retval = regs->ARM_r0;
598 regs->ARM_r0 = regs->ARM_ORIG_r0;
599 regs->ARM_pc = restart_addr;
614 if (regs->ARM_pc != restart_addr)
622 regs->ARM_r0 = -
EINTR;
623 regs->ARM_pc = continue_addr;
627 handle_signal(signr, &ka, &info, regs);
631 restore_saved_sigmask();
633 regs->ARM_pc = continue_addr;
648 int restart = do_signal(regs, syscall);
660 tracehook_notify_resume(regs);