aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/signal.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2012-09-21 20:18:44 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2012-09-21 20:18:44 -0400
commit49b8c695e331c9685e6ffdbf34872509d77c8459 (patch)
treed4afdfae0115b2ab56687d23d6329d6ad934788f /arch/x86/kernel/signal.c
parente59d1b0a24199db01978e6c1e89859eda93ce683 (diff)
parentb1a74bf8212367be2b1d6685c11a84e056eaaaf1 (diff)
Merge branch 'x86/fpu' into x86/smap
Reason for merge: x86/fpu changed the structure of some of the code that x86/smap changes; mostly fpu-internal.h but also minor changes to the signal code. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Resolved Conflicts: arch/x86/ia32/ia32_signal.c arch/x86/include/asm/fpu-internal.h arch/x86/kernel/signal.c
Diffstat (limited to 'arch/x86/kernel/signal.c')
-rw-r--r--arch/x86/kernel/signal.c215
1 files changed, 91 insertions, 124 deletions
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 932612887e92..036bddb46236 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -118,7 +118,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
118 get_user_ex(*pax, &sc->ax); 118 get_user_ex(*pax, &sc->ax);
119 } get_user_catch(err); 119 } get_user_catch(err);
120 120
121 err |= restore_i387_xstate(buf); 121 err |= restore_xstate_sig(buf, config_enabled(CONFIG_X86_32));
122 122
123 return err; 123 return err;
124} 124}
@@ -207,35 +207,32 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
207 void __user **fpstate) 207 void __user **fpstate)
208{ 208{
209 /* Default to using normal stack */ 209 /* Default to using normal stack */
210 unsigned long math_size = 0;
210 unsigned long sp = regs->sp; 211 unsigned long sp = regs->sp;
212 unsigned long buf_fx = 0;
211 int onsigstack = on_sig_stack(sp); 213 int onsigstack = on_sig_stack(sp);
212 214
213#ifdef CONFIG_X86_64
214 /* redzone */ 215 /* redzone */
215 sp -= 128; 216 if (config_enabled(CONFIG_X86_64))
216#endif /* CONFIG_X86_64 */ 217 sp -= 128;
217 218
218 if (!onsigstack) { 219 if (!onsigstack) {
219 /* This is the X/Open sanctioned signal stack switching. */ 220 /* This is the X/Open sanctioned signal stack switching. */
220 if (ka->sa.sa_flags & SA_ONSTACK) { 221 if (ka->sa.sa_flags & SA_ONSTACK) {
221 if (current->sas_ss_size) 222 if (current->sas_ss_size)
222 sp = current->sas_ss_sp + current->sas_ss_size; 223 sp = current->sas_ss_sp + current->sas_ss_size;
223 } else { 224 } else if (config_enabled(CONFIG_X86_32) &&
224#ifdef CONFIG_X86_32 225 (regs->ss & 0xffff) != __USER_DS &&
225 /* This is the legacy signal stack switching. */ 226 !(ka->sa.sa_flags & SA_RESTORER) &&
226 if ((regs->ss & 0xffff) != __USER_DS && 227 ka->sa.sa_restorer) {
227 !(ka->sa.sa_flags & SA_RESTORER) && 228 /* This is the legacy signal stack switching. */
228 ka->sa.sa_restorer)
229 sp = (unsigned long) ka->sa.sa_restorer; 229 sp = (unsigned long) ka->sa.sa_restorer;
230#endif /* CONFIG_X86_32 */
231 } 230 }
232 } 231 }
233 232
234 if (used_math()) { 233 if (used_math()) {
235 sp -= sig_xstate_size; 234 sp = alloc_mathframe(sp, config_enabled(CONFIG_X86_32),
236#ifdef CONFIG_X86_64 235 &buf_fx, &math_size);
237 sp = round_down(sp, 64);
238#endif /* CONFIG_X86_64 */
239 *fpstate = (void __user *)sp; 236 *fpstate = (void __user *)sp;
240 } 237 }
241 238
@@ -248,8 +245,9 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
248 if (onsigstack && !likely(on_sig_stack(sp))) 245 if (onsigstack && !likely(on_sig_stack(sp)))
249 return (void __user *)-1L; 246 return (void __user *)-1L;
250 247
251 /* save i387 state */ 248 /* save i387 and extended state */
252 if (used_math() && save_i387_xstate(*fpstate) < 0) 249 if (used_math() &&
250 save_xstate_sig(*fpstate, (void __user *)buf_fx, math_size) < 0)
253 return (void __user *)-1L; 251 return (void __user *)-1L;
254 252
255 return (void __user *)sp; 253 return (void __user *)sp;
@@ -385,7 +383,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
385 */ 383 */
386 put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); 384 put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
387 } put_user_catch(err); 385 } put_user_catch(err);
388 386
389 err |= copy_siginfo_to_user(&frame->info, info); 387 err |= copy_siginfo_to_user(&frame->info, info);
390 err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, 388 err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
391 regs, set->sig[0]); 389 regs, set->sig[0]);
@@ -477,6 +475,75 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
477} 475}
478#endif /* CONFIG_X86_32 */ 476#endif /* CONFIG_X86_32 */
479 477
478static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
479 siginfo_t *info, compat_sigset_t *set,
480 struct pt_regs *regs)
481{
482#ifdef CONFIG_X86_X32_ABI
483 struct rt_sigframe_x32 __user *frame;
484 void __user *restorer;
485 int err = 0;
486 void __user *fpstate = NULL;
487
488 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
489
490 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
491 return -EFAULT;
492
493 if (ka->sa.sa_flags & SA_SIGINFO) {
494 if (copy_siginfo_to_user32(&frame->info, info))
495 return -EFAULT;
496 }
497
498 put_user_try {
499 /* Create the ucontext. */
500 if (cpu_has_xsave)
501 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
502 else
503 put_user_ex(0, &frame->uc.uc_flags);
504 put_user_ex(0, &frame->uc.uc_link);
505 put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
506 put_user_ex(sas_ss_flags(regs->sp),
507 &frame->uc.uc_stack.ss_flags);
508 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
509 put_user_ex(0, &frame->uc.uc__pad0);
510
511 if (ka->sa.sa_flags & SA_RESTORER) {
512 restorer = ka->sa.sa_restorer;
513 } else {
514 /* could use a vstub here */
515 restorer = NULL;
516 err |= -EFAULT;
517 }
518 put_user_ex(restorer, &frame->pretcode);
519 } put_user_catch(err);
520
521 err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
522 regs, set->sig[0]);
523 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
524
525 if (err)
526 return -EFAULT;
527
528 /* Set up registers for signal handler */
529 regs->sp = (unsigned long) frame;
530 regs->ip = (unsigned long) ka->sa.sa_handler;
531
532 /* We use the x32 calling convention here... */
533 regs->di = sig;
534 regs->si = (unsigned long) &frame->info;
535 regs->dx = (unsigned long) &frame->uc;
536
537 loadsegment(ds, __USER_DS);
538 loadsegment(es, __USER_DS);
539
540 regs->cs = __USER_CS;
541 regs->ss = __USER_DS;
542#endif /* CONFIG_X86_X32_ABI */
543
544 return 0;
545}
546
480#ifdef CONFIG_X86_32 547#ifdef CONFIG_X86_32
481/* 548/*
482 * Atomically swap in the new signal mask, and wait for a signal. 549 * Atomically swap in the new signal mask, and wait for a signal.
@@ -615,55 +682,22 @@ static int signr_convert(int sig)
615 return sig; 682 return sig;
616} 683}
617 684
618#ifdef CONFIG_X86_32
619
620#define is_ia32 1
621#define ia32_setup_frame __setup_frame
622#define ia32_setup_rt_frame __setup_rt_frame
623
624#else /* !CONFIG_X86_32 */
625
626#ifdef CONFIG_IA32_EMULATION
627#define is_ia32 test_thread_flag(TIF_IA32)
628#else /* !CONFIG_IA32_EMULATION */
629#define is_ia32 0
630#endif /* CONFIG_IA32_EMULATION */
631
632#ifdef CONFIG_X86_X32_ABI
633#define is_x32 test_thread_flag(TIF_X32)
634
635static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
636 siginfo_t *info, compat_sigset_t *set,
637 struct pt_regs *regs);
638#else /* !CONFIG_X86_X32_ABI */
639#define is_x32 0
640#endif /* CONFIG_X86_X32_ABI */
641
642int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
643 sigset_t *set, struct pt_regs *regs);
644int ia32_setup_frame(int sig, struct k_sigaction *ka,
645 sigset_t *set, struct pt_regs *regs);
646
647#endif /* CONFIG_X86_32 */
648
649static int 685static int
650setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 686setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
651 struct pt_regs *regs) 687 struct pt_regs *regs)
652{ 688{
653 int usig = signr_convert(sig); 689 int usig = signr_convert(sig);
654 sigset_t *set = sigmask_to_save(); 690 sigset_t *set = sigmask_to_save();
691 compat_sigset_t *cset = (compat_sigset_t *) set;
655 692
656 /* Set up the stack frame */ 693 /* Set up the stack frame */
657 if (is_ia32) { 694 if (is_ia32_frame()) {
658 if (ka->sa.sa_flags & SA_SIGINFO) 695 if (ka->sa.sa_flags & SA_SIGINFO)
659 return ia32_setup_rt_frame(usig, ka, info, set, regs); 696 return ia32_setup_rt_frame(usig, ka, info, cset, regs);
660 else 697 else
661 return ia32_setup_frame(usig, ka, set, regs); 698 return ia32_setup_frame(usig, ka, cset, regs);
662#ifdef CONFIG_X86_X32_ABI 699 } else if (is_x32_frame()) {
663 } else if (is_x32) { 700 return x32_setup_rt_frame(usig, ka, info, cset, regs);
664 return x32_setup_rt_frame(usig, ka, info,
665 (compat_sigset_t *)set, regs);
666#endif
667 } else { 701 } else {
668 return __setup_rt_frame(sig, ka, info, set, regs); 702 return __setup_rt_frame(sig, ka, info, set, regs);
669 } 703 }
@@ -827,73 +861,6 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
827} 861}
828 862
829#ifdef CONFIG_X86_X32_ABI 863#ifdef CONFIG_X86_X32_ABI
830static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
831 siginfo_t *info, compat_sigset_t *set,
832 struct pt_regs *regs)
833{
834 struct rt_sigframe_x32 __user *frame;
835 void __user *restorer;
836 int err = 0;
837 void __user *fpstate = NULL;
838
839 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
840
841 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
842 return -EFAULT;
843
844 if (ka->sa.sa_flags & SA_SIGINFO) {
845 if (copy_siginfo_to_user32(&frame->info, info))
846 return -EFAULT;
847 }
848
849 put_user_try {
850 /* Create the ucontext. */
851 if (cpu_has_xsave)
852 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
853 else
854 put_user_ex(0, &frame->uc.uc_flags);
855 put_user_ex(0, &frame->uc.uc_link);
856 put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
857 put_user_ex(sas_ss_flags(regs->sp),
858 &frame->uc.uc_stack.ss_flags);
859 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
860 put_user_ex(0, &frame->uc.uc__pad0);
861
862 if (ka->sa.sa_flags & SA_RESTORER) {
863 restorer = ka->sa.sa_restorer;
864 } else {
865 /* could use a vstub here */
866 restorer = NULL;
867 err |= -EFAULT;
868 }
869 put_user_ex(restorer, &frame->pretcode);
870 } put_user_catch(err);
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
876 if (err)
877 return -EFAULT;
878
879 /* Set up registers for signal handler */
880 regs->sp = (unsigned long) frame;
881 regs->ip = (unsigned long) ka->sa.sa_handler;
882
883 /* We use the x32 calling convention here... */
884 regs->di = sig;
885 regs->si = (unsigned long) &frame->info;
886 regs->dx = (unsigned long) &frame->uc;
887
888 loadsegment(ds, __USER_DS);
889 loadsegment(es, __USER_DS);
890
891 regs->cs = __USER_CS;
892 regs->ss = __USER_DS;
893
894 return 0;
895}
896
897asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs) 864asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
898{ 865{
899 struct rt_sigframe_x32 __user *frame; 866 struct rt_sigframe_x32 __user *frame;