diff options
| author | H. Peter Anvin <hpa@linux.intel.com> | 2012-09-21 12:43:15 -0700 | 
|---|---|---|
| committer | H. Peter Anvin <hpa@linux.intel.com> | 2012-09-21 12:45:27 -0700 | 
| commit | 5e88353d8b5f483bc1c873ad24ac2b59a6b66c73 (patch) | |
| tree | f5651873e535e4feabea0da5d253d0326b4bd029 /arch/x86/ia32 | |
| parent | 40d3cd6695014bf3c44e2ca66b610b18acaf923d (diff) | |
| download | linux-5e88353d8b5f483bc1c873ad24ac2b59a6b66c73.tar.bz2 | |
x86, smap: Reduce the SMAP overhead for signal handling
Signal handling contains a bunch of accesses to individual user space
items, which causes an excessive number of STAC and CLAC
instructions.  Instead, let get/put_user_try ... get/put_user_catch()
contain the STAC and CLAC instructions.
This means that get/put_user_try no longer nests, and furthermore that
it is no longer legal to use user space access functions other than
__get/put_user_ex() inside those blocks.  However, these macros are
x86-specific anyway and are only used in the signal-handling paths; a
simple reordering of moving the larger subroutine calls out of the
try...catch blocks resolves that problem.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Link: http://lkml.kernel.org/r/1348256595-29119-12-git-send-email-hpa@linux.intel.com
Diffstat (limited to 'arch/x86/ia32')
| -rw-r--r-- | arch/x86/ia32/ia32_signal.c | 12 | 
1 files changed, 7 insertions, 5 deletions
| diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 673ac9b63d6b..05e62a312bd9 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -250,11 +250,12 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,  		get_user_ex(tmp, &sc->fpstate);  		buf = compat_ptr(tmp); -		err |= restore_i387_xstate_ia32(buf);  		get_user_ex(*pax, &sc->ax);  	} get_user_catch(err); +	err |= restore_i387_xstate_ia32(buf); +  	return err;  } @@ -502,7 +503,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  		put_user_ex(sig, &frame->sig);  		put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);  		put_user_ex(ptr_to_compat(&frame->uc), &frame->puc); -		err |= copy_siginfo_to_user32(&frame->info, info);  		/* Create the ucontext.  */  		if (cpu_has_xsave) @@ -514,9 +514,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  		put_user_ex(sas_ss_flags(regs->sp),  			    &frame->uc.uc_stack.ss_flags);  		put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); -		err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, -					     regs, set->sig[0]); -		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));  		if (ka->sa.sa_flags & SA_RESTORER)  			restorer = ka->sa.sa_restorer; @@ -532,6 +529,11 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  		put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);  	} put_user_catch(err); +	err |= copy_siginfo_to_user32(&frame->info, info); +	err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, +				     regs, set->sig[0]); +	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); +  	if (err)  		return -EFAULT; |