aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/signal.c
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/kernel/signal.c
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/kernel/signal.c')
-rw-r--r--arch/x86/kernel/signal.c24
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