diff options
| author | Nicolas Pitre <nico@cam.org> | 2006-01-18 17:38:47 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-01-18 17:38:47 -0500 |
| commit | fcca538b83f2984095f15f0f90f6c7686e3a32d4 (patch) | |
| tree | bf113e29cb4cc4b13900814a3c7ada4884c94a18 /arch/arm/kernel | |
| parent | 1230b4046b9da77ccb83ef2eaffc54dc4a96093a (diff) | |
[ARM] 3270/1: ARM EABI: fix sigreturn and rt_sigreturn
Patch from Nicolas Pitre
The signal return path consists of user code provided by the kernel.
Since a syscall is used, it has to be updated to work with EABI.
Noticed by Daniel Jacobowitz.
Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
| -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]; |
