diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/kernel/signal.c | 29 | ||||
-rw-r--r-- | arch/arm/kernel/signal.h | 2 |
2 files changed, 19 insertions, 12 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 765922bcf9e7..a0cd0a90a10d 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -30,15 +30,21 @@ | |||
30 | #define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)) | 30 | #define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)) |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * With EABI, the syscall number has to be loaded into r7. | ||
34 | */ | ||
35 | #define MOV_R7_NR_SIGRETURN (0xe3a07000 | (__NR_sigreturn - __NR_SYSCALL_BASE)) | ||
36 | #define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) | ||
37 | |||
38 | /* | ||
33 | * For Thumb syscalls, we pass the syscall number via r7. We therefore | 39 | * For Thumb syscalls, we pass the syscall number via r7. We therefore |
34 | * need two 16-bit instructions. | 40 | * need two 16-bit instructions. |
35 | */ | 41 | */ |
36 | #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) | 42 | #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) |
37 | #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) | 43 | #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) |
38 | 44 | ||
39 | const unsigned long sigreturn_codes[4] = { | 45 | const unsigned long sigreturn_codes[7] = { |
40 | SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, | 46 | MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, |
41 | SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN | 47 | MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, |
42 | }; | 48 | }; |
43 | 49 | ||
44 | static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); | 50 | static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); |
@@ -189,7 +195,7 @@ struct aux_sigframe { | |||
189 | struct sigframe { | 195 | struct sigframe { |
190 | struct sigcontext sc; | 196 | struct sigcontext sc; |
191 | unsigned long extramask[_NSIG_WORDS-1]; | 197 | unsigned long extramask[_NSIG_WORDS-1]; |
192 | unsigned long retcode; | 198 | unsigned long retcode[2]; |
193 | struct aux_sigframe aux __attribute__((aligned(8))); | 199 | struct aux_sigframe aux __attribute__((aligned(8))); |
194 | }; | 200 | }; |
195 | 201 | ||
@@ -198,7 +204,7 @@ struct rt_sigframe { | |||
198 | void __user *puc; | 204 | void __user *puc; |
199 | struct siginfo info; | 205 | struct siginfo info; |
200 | struct ucontext uc; | 206 | struct ucontext uc; |
201 | unsigned long retcode; | 207 | unsigned long retcode[2]; |
202 | struct aux_sigframe aux __attribute__((aligned(8))); | 208 | struct aux_sigframe aux __attribute__((aligned(8))); |
203 | }; | 209 | }; |
204 | 210 | ||
@@ -436,12 +442,13 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, | |||
436 | if (ka->sa.sa_flags & SA_RESTORER) { | 442 | if (ka->sa.sa_flags & SA_RESTORER) { |
437 | retcode = (unsigned long)ka->sa.sa_restorer; | 443 | retcode = (unsigned long)ka->sa.sa_restorer; |
438 | } else { | 444 | } else { |
439 | unsigned int idx = thumb; | 445 | unsigned int idx = thumb << 1; |
440 | 446 | ||
441 | if (ka->sa.sa_flags & SA_SIGINFO) | 447 | if (ka->sa.sa_flags & SA_SIGINFO) |
442 | idx += 2; | 448 | idx += 3; |
443 | 449 | ||
444 | if (__put_user(sigreturn_codes[idx], rc)) | 450 | if (__put_user(sigreturn_codes[idx], rc) || |
451 | __put_user(sigreturn_codes[idx+1], rc+1)) | ||
445 | return 1; | 452 | return 1; |
446 | 453 | ||
447 | if (cpsr & MODE32_BIT) { | 454 | if (cpsr & MODE32_BIT) { |
@@ -456,7 +463,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, | |||
456 | * the return code written onto the stack. | 463 | * the return code written onto the stack. |
457 | */ | 464 | */ |
458 | flush_icache_range((unsigned long)rc, | 465 | flush_icache_range((unsigned long)rc, |
459 | (unsigned long)(rc + 1)); | 466 | (unsigned long)(rc + 2)); |
460 | 467 | ||
461 | retcode = ((unsigned long)rc) + thumb; | 468 | retcode = ((unsigned long)rc) + thumb; |
462 | } | 469 | } |
@@ -488,7 +495,7 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg | |||
488 | } | 495 | } |
489 | 496 | ||
490 | if (err == 0) | 497 | if (err == 0) |
491 | err = setup_return(regs, ka, &frame->retcode, frame, usig); | 498 | err = setup_return(regs, ka, frame->retcode, frame, usig); |
492 | 499 | ||
493 | return err; | 500 | return err; |
494 | } | 501 | } |
@@ -522,7 +529,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | |||
522 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 529 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
523 | 530 | ||
524 | if (err == 0) | 531 | if (err == 0) |
525 | err = setup_return(regs, ka, &frame->retcode, frame, usig); | 532 | err = setup_return(regs, ka, frame->retcode, frame, usig); |
526 | 533 | ||
527 | if (err == 0) { | 534 | if (err == 0) { |
528 | /* | 535 | /* |
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h index 91d26faca62b..9991049c522d 100644 --- a/arch/arm/kernel/signal.h +++ b/arch/arm/kernel/signal.h | |||
@@ -9,4 +9,4 @@ | |||
9 | */ | 9 | */ |
10 | #define KERN_SIGRETURN_CODE 0xffff0500 | 10 | #define KERN_SIGRETURN_CODE 0xffff0500 |
11 | 11 | ||
12 | extern const unsigned long sigreturn_codes[4]; | 12 | extern const unsigned long sigreturn_codes[7]; |