Commit 697a9d65 authored by Bernd Schmidt's avatar Bernd Schmidt Committed by Bryan Wu

[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: default avatarBernd Schmidt <bernds_cb1@t-online.de>
Signed-off-by: default avatarBryan Wu <cooloney@kernel.org>
parent 5af29f59
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/fixed_code.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
...@@ -50,6 +51,8 @@ struct rt_sigframe { ...@@ -50,6 +51,8 @@ struct rt_sigframe {
int sig; int sig;
struct siginfo *pinfo; struct siginfo *pinfo;
void *puc; void *puc;
/* This is no longer needed by the kernel, but unfortunately userspace
* code expects it to be there. */
char retcode[8]; char retcode[8];
struct siginfo info; struct siginfo info;
struct ucontext uc; struct ucontext uc;
...@@ -159,11 +162,6 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg ...@@ -159,11 +162,6 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg
return err; return err;
} }
static inline void push_cache(unsigned long vaddr, unsigned int len)
{
flush_icache_range(vaddr, vaddr + len);
}
static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size) size_t frame_size)
{ {
...@@ -209,19 +207,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, ...@@ -209,19 +207,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs);
err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
/* Set up to return from userspace. */
err |= __put_user(0x28, &(frame->retcode[0]));
err |= __put_user(0xe1, &(frame->retcode[1]));
err |= __put_user(0xad, &(frame->retcode[2]));
err |= __put_user(0x00, &(frame->retcode[3]));
err |= __put_user(0xa0, &(frame->retcode[4]));
err |= __put_user(0x00, &(frame->retcode[5]));
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
push_cache((unsigned long)&frame->retcode, sizeof(frame->retcode));
/* Set up registers for signal handler */ /* Set up registers for signal handler */
wrusp((unsigned long)frame); wrusp((unsigned long)frame);
if (get_personality & FDPIC_FUNCPTRS) { if (get_personality & FDPIC_FUNCPTRS) {
...@@ -231,7 +219,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, ...@@ -231,7 +219,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
__get_user(regs->p3, &funcptr->GOT); __get_user(regs->p3, &funcptr->GOT);
} else } else
regs->pc = (unsigned long)ka->sa.sa_handler; regs->pc = (unsigned long)ka->sa.sa_handler;
regs->rets = (unsigned long)(frame->retcode); regs->rets = SIGRETURN_STUB;
regs->r0 = frame->sig; regs->r0 = frame->sig;
regs->r1 = (unsigned long)(&frame->info); regs->r1 = (unsigned long)(&frame->info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment