aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/ia32
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2012-09-21 15:43:15 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2012-09-21 15:45:27 -0400
commit5e88353d8b5f483bc1c873ad24ac2b59a6b66c73 (patch)
treef5651873e535e4feabea0da5d253d0326b4bd029 /arch/x86/ia32
parent40d3cd6695014bf3c44e2ca66b610b18acaf923d (diff)
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.c12
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,
250 250
251 get_user_ex(tmp, &sc->fpstate); 251 get_user_ex(tmp, &sc->fpstate);
252 buf = compat_ptr(tmp); 252 buf = compat_ptr(tmp);
253 err |= restore_i387_xstate_ia32(buf);
254 253
255 get_user_ex(*pax, &sc->ax); 254 get_user_ex(*pax, &sc->ax);
256 } get_user_catch(err); 255 } get_user_catch(err);
257 256
257 err |= restore_i387_xstate_ia32(buf);
258
258 return err; 259 return err;
259} 260}
260 261
@@ -502,7 +503,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
502 put_user_ex(sig, &frame->sig); 503 put_user_ex(sig, &frame->sig);
503 put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo); 504 put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
504 put_user_ex(ptr_to_compat(&frame->uc), &frame->puc); 505 put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
505 err |= copy_siginfo_to_user32(&frame->info, info);
506 506
507 /* Create the ucontext. */ 507 /* Create the ucontext. */
508 if (cpu_has_xsave) 508 if (cpu_has_xsave)
@@ -514,9 +514,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
514 put_user_ex(sas_ss_flags(regs->sp), 514 put_user_ex(sas_ss_flags(regs->sp),
515 &frame->uc.uc_stack.ss_flags); 515 &frame->uc.uc_stack.ss_flags);
516 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); 516 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
517 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
518 regs, set->sig[0]);
519 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
520 517
521 if (ka->sa.sa_flags & SA_RESTORER) 518 if (ka->sa.sa_flags & SA_RESTORER)
522 restorer = ka->sa.sa_restorer; 519 restorer = ka->sa.sa_restorer;
@@ -532,6 +529,11 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
532 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); 529 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
533 } put_user_catch(err); 530 } put_user_catch(err);
534 531
532 err |= copy_siginfo_to_user32(&frame->info, info);
533 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
534 regs, set->sig[0]);
535 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
536
535 if (err) 537 if (err)
536 return -EFAULT; 538 return -EFAULT;
537 539