diff options
| author | Bernd Schmidt <bernds_cb1@t-online.de> | 2008-04-23 14:51:36 -0400 |
|---|---|---|
| committer | Bryan Wu <cooloney@kernel.org> | 2008-04-23 14:51:36 -0400 |
| commit | 697a9d65aa799940da1c9145944c6b9bd0f442c5 (patch) | |
| tree | c92b8e314e3bcc5ccaca4cfa26b00648230abe9e /arch/blackfin | |
| parent | 5af29f595813cce3c125d01d2500be483732ef4f (diff) | |
[Blackfin] arch: a rather old performance improvement for the signal handling code
This is a rather old performance improvement for the signal handling
code, which was originally only committed on the 2007R1 branch as a
workaround for what we suspected to be a hardware bug.
There's no point in constructing a sigreturn stub on the stack and
flushing caches; we can just make signal handlers return to a known
location in the fixed code area.
Signed-off-by: Bernd Schmidt <bernds_cb1@t-online.de>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin')
| -rw-r--r-- | arch/blackfin/kernel/signal.c | 20 |
1 files changed, 4 insertions, 16 deletions
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index 71cfcd28b39f..d1fa24401dc6 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | #include <asm/cacheflush.h> | 39 | #include <asm/cacheflush.h> |
| 40 | #include <asm/ucontext.h> | 40 | #include <asm/ucontext.h> |
| 41 | #include <asm/fixed_code.h> | ||
| 41 | 42 | ||
| 42 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 43 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
| 43 | 44 | ||
| @@ -50,6 +51,8 @@ struct rt_sigframe { | |||
| 50 | int sig; | 51 | int sig; |
| 51 | struct siginfo *pinfo; | 52 | struct siginfo *pinfo; |
| 52 | void *puc; | 53 | void *puc; |
| 54 | /* This is no longer needed by the kernel, but unfortunately userspace | ||
| 55 | * code expects it to be there. */ | ||
| 53 | char retcode[8]; | 56 | char retcode[8]; |
| 54 | struct siginfo info; | 57 | struct siginfo info; |
| 55 | struct ucontext uc; | 58 | struct ucontext uc; |
| @@ -159,11 +162,6 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg | |||
| 159 | return err; | 162 | return err; |
| 160 | } | 163 | } |
| 161 | 164 | ||
| 162 | static inline void push_cache(unsigned long vaddr, unsigned int len) | ||
| 163 | { | ||
| 164 | flush_icache_range(vaddr, vaddr + len); | ||
| 165 | } | ||
| 166 | |||
| 167 | static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 165 | static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, |
| 168 | size_t frame_size) | 166 | size_t frame_size) |
| 169 | { | 167 | { |
| @@ -209,19 +207,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, | |||
| 209 | err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs); | 207 | err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs); |
| 210 | err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 208 | err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
| 211 | 209 | ||
| 212 | /* Set up to return from userspace. */ | ||
| 213 | err |= __put_user(0x28, &(frame->retcode[0])); | ||
| 214 | err |= __put_user(0xe1, &(frame->retcode[1])); | ||
| 215 | err |= __put_user(0xad, &(frame->retcode[2])); | ||
| 216 | err |= __put_user(0x00, &(frame->retcode[3])); | ||
| 217 | err |= __put_user(0xa0, &(frame->retcode[4])); | ||
| 218 | err |= __put_user(0x00, &(frame->retcode[5])); | ||
| 219 | |||
| 220 | if (err) | 210 | if (err) |
| 221 | goto give_sigsegv; | 211 | goto give_sigsegv; |
| 222 | 212 | ||
| 223 | push_cache((unsigned long)&frame->retcode, sizeof(frame->retcode)); | ||
| 224 | |||
| 225 | /* Set up registers for signal handler */ | 213 | /* Set up registers for signal handler */ |
| 226 | wrusp((unsigned long)frame); | 214 | wrusp((unsigned long)frame); |
| 227 | if (get_personality & FDPIC_FUNCPTRS) { | 215 | if (get_personality & FDPIC_FUNCPTRS) { |
| @@ -231,7 +219,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, | |||
| 231 | __get_user(regs->p3, &funcptr->GOT); | 219 | __get_user(regs->p3, &funcptr->GOT); |
| 232 | } else | 220 | } else |
| 233 | regs->pc = (unsigned long)ka->sa.sa_handler; | 221 | regs->pc = (unsigned long)ka->sa.sa_handler; |
| 234 | regs->rets = (unsigned long)(frame->retcode); | 222 | regs->rets = SIGRETURN_STUB; |
| 235 | 223 | ||
| 236 | regs->r0 = frame->sig; | 224 | regs->r0 = frame->sig; |
| 237 | regs->r1 = (unsigned long)(&frame->info); | 225 | regs->r1 = (unsigned long)(&frame->info); |
