diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2012-09-21 15:43:15 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2012-09-21 15:45:27 -0400 |
commit | 5e88353d8b5f483bc1c873ad24ac2b59a6b66c73 (patch) | |
tree | f5651873e535e4feabea0da5d253d0326b4bd029 /arch/x86/kernel/signal.c | |
parent | 40d3cd6695014bf3c44e2ca66b610b18acaf923d (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/kernel/signal.c')
-rw-r--r-- | arch/x86/kernel/signal.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index b280908a376e..932612887e92 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -114,11 +114,12 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
114 | regs->orig_ax = -1; /* disable syscall checks */ | 114 | regs->orig_ax = -1; /* disable syscall checks */ |
115 | 115 | ||
116 | get_user_ex(buf, &sc->fpstate); | 116 | get_user_ex(buf, &sc->fpstate); |
117 | err |= restore_i387_xstate(buf); | ||
118 | 117 | ||
119 | get_user_ex(*pax, &sc->ax); | 118 | get_user_ex(*pax, &sc->ax); |
120 | } get_user_catch(err); | 119 | } get_user_catch(err); |
121 | 120 | ||
121 | err |= restore_i387_xstate(buf); | ||
122 | |||
122 | return err; | 123 | return err; |
123 | } | 124 | } |
124 | 125 | ||
@@ -357,7 +358,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
357 | put_user_ex(sig, &frame->sig); | 358 | put_user_ex(sig, &frame->sig); |
358 | put_user_ex(&frame->info, &frame->pinfo); | 359 | put_user_ex(&frame->info, &frame->pinfo); |
359 | put_user_ex(&frame->uc, &frame->puc); | 360 | put_user_ex(&frame->uc, &frame->puc); |
360 | err |= copy_siginfo_to_user(&frame->info, info); | ||
361 | 361 | ||
362 | /* Create the ucontext. */ | 362 | /* Create the ucontext. */ |
363 | if (cpu_has_xsave) | 363 | if (cpu_has_xsave) |
@@ -369,9 +369,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
369 | put_user_ex(sas_ss_flags(regs->sp), | 369 | put_user_ex(sas_ss_flags(regs->sp), |
370 | &frame->uc.uc_stack.ss_flags); | 370 | &frame->uc.uc_stack.ss_flags); |
371 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 371 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
372 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
373 | regs, set->sig[0]); | ||
374 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
375 | 372 | ||
376 | /* Set up to return from userspace. */ | 373 | /* Set up to return from userspace. */ |
377 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); | 374 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); |
@@ -389,6 +386,11 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
389 | put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); | 386 | put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); |
390 | } put_user_catch(err); | 387 | } put_user_catch(err); |
391 | 388 | ||
389 | err |= copy_siginfo_to_user(&frame->info, info); | ||
390 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
391 | regs, set->sig[0]); | ||
392 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
393 | |||
392 | if (err) | 394 | if (err) |
393 | return -EFAULT; | 395 | return -EFAULT; |
394 | 396 | ||
@@ -436,8 +438,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
436 | put_user_ex(sas_ss_flags(regs->sp), | 438 | put_user_ex(sas_ss_flags(regs->sp), |
437 | &frame->uc.uc_stack.ss_flags); | 439 | &frame->uc.uc_stack.ss_flags); |
438 | put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | 440 | put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size); |
439 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); | ||
440 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
441 | 441 | ||
442 | /* Set up to return from userspace. If provided, use a stub | 442 | /* Set up to return from userspace. If provided, use a stub |
443 | already in userspace. */ | 443 | already in userspace. */ |
@@ -450,6 +450,9 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
450 | } | 450 | } |
451 | } put_user_catch(err); | 451 | } put_user_catch(err); |
452 | 452 | ||
453 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); | ||
454 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
455 | |||
453 | if (err) | 456 | if (err) |
454 | return -EFAULT; | 457 | return -EFAULT; |
455 | 458 | ||
@@ -855,9 +858,6 @@ static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, | |||
855 | &frame->uc.uc_stack.ss_flags); | 858 | &frame->uc.uc_stack.ss_flags); |
856 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 859 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
857 | put_user_ex(0, &frame->uc.uc__pad0); | 860 | put_user_ex(0, &frame->uc.uc__pad0); |
858 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
859 | regs, set->sig[0]); | ||
860 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
861 | 861 | ||
862 | if (ka->sa.sa_flags & SA_RESTORER) { | 862 | if (ka->sa.sa_flags & SA_RESTORER) { |
863 | restorer = ka->sa.sa_restorer; | 863 | restorer = ka->sa.sa_restorer; |
@@ -869,6 +869,10 @@ static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, | |||
869 | put_user_ex(restorer, &frame->pretcode); | 869 | put_user_ex(restorer, &frame->pretcode); |
870 | } put_user_catch(err); | 870 | } put_user_catch(err); |
871 | 871 | ||
872 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
873 | regs, set->sig[0]); | ||
874 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
875 | |||
872 | if (err) | 876 | if (err) |
873 | return -EFAULT; | 877 | return -EFAULT; |
874 | 878 | ||