x86, xsave: save/restore the extended state context in sigframe
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / x86 / ia32 / ia32_signal.c
blobf25a10124005c5a4911ba563a87ee94320ddd811
1 /*
2 * linux/arch/x86_64/ia32/ia32_signal.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
6 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
7 * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
8 * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen
9 */
11 #include <linux/sched.h>
12 #include <linux/mm.h>
13 #include <linux/smp.h>
14 #include <linux/kernel.h>
15 #include <linux/signal.h>
16 #include <linux/errno.h>
17 #include <linux/wait.h>
18 #include <linux/ptrace.h>
19 #include <linux/unistd.h>
20 #include <linux/stddef.h>
21 #include <linux/personality.h>
22 #include <linux/compat.h>
23 #include <linux/binfmts.h>
24 #include <asm/ucontext.h>
25 #include <asm/uaccess.h>
26 #include <asm/i387.h>
27 #include <asm/ia32.h>
28 #include <asm/ptrace.h>
29 #include <asm/ia32_unistd.h>
30 #include <asm/user32.h>
31 #include <asm/sigcontext32.h>
32 #include <asm/proto.h>
33 #include <asm/vdso.h>
35 #define DEBUG_SIG 0
37 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
39 #define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
40 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
41 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
42 X86_EFLAGS_CF)
44 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
45 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
47 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
49 int err;
51 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
52 return -EFAULT;
54 /* If you change siginfo_t structure, please make sure that
55 this code is fixed accordingly.
56 It should never copy any pad contained in the structure
57 to avoid security leaks, but must copy the generic
58 3 ints plus the relevant union member. */
59 err = __put_user(from->si_signo, &to->si_signo);
60 err |= __put_user(from->si_errno, &to->si_errno);
61 err |= __put_user((short)from->si_code, &to->si_code);
63 if (from->si_code < 0) {
64 err |= __put_user(from->si_pid, &to->si_pid);
65 err |= __put_user(from->si_uid, &to->si_uid);
66 err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
67 } else {
69 * First 32bits of unions are always present:
70 * si_pid === si_band === si_tid === si_addr(LS half)
72 err |= __put_user(from->_sifields._pad[0],
73 &to->_sifields._pad[0]);
74 switch (from->si_code >> 16) {
75 case __SI_FAULT >> 16:
76 break;
77 case __SI_CHLD >> 16:
78 err |= __put_user(from->si_utime, &to->si_utime);
79 err |= __put_user(from->si_stime, &to->si_stime);
80 err |= __put_user(from->si_status, &to->si_status);
81 /* FALL THROUGH */
82 default:
83 case __SI_KILL >> 16:
84 err |= __put_user(from->si_uid, &to->si_uid);
85 break;
86 case __SI_POLL >> 16:
87 err |= __put_user(from->si_fd, &to->si_fd);
88 break;
89 case __SI_TIMER >> 16:
90 err |= __put_user(from->si_overrun, &to->si_overrun);
91 err |= __put_user(ptr_to_compat(from->si_ptr),
92 &to->si_ptr);
93 break;
94 /* This is not generated by the kernel as of now. */
95 case __SI_RT >> 16:
96 case __SI_MESGQ >> 16:
97 err |= __put_user(from->si_uid, &to->si_uid);
98 err |= __put_user(from->si_int, &to->si_int);
99 break;
102 return err;
105 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
107 int err;
108 u32 ptr32;
110 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
111 return -EFAULT;
113 err = __get_user(to->si_signo, &from->si_signo);
114 err |= __get_user(to->si_errno, &from->si_errno);
115 err |= __get_user(to->si_code, &from->si_code);
117 err |= __get_user(to->si_pid, &from->si_pid);
118 err |= __get_user(to->si_uid, &from->si_uid);
119 err |= __get_user(ptr32, &from->si_ptr);
120 to->si_ptr = compat_ptr(ptr32);
122 return err;
125 asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
127 mask &= _BLOCKABLE;
128 spin_lock_irq(&current->sighand->siglock);
129 current->saved_sigmask = current->blocked;
130 siginitset(&current->blocked, mask);
131 recalc_sigpending();
132 spin_unlock_irq(&current->sighand->siglock);
134 current->state = TASK_INTERRUPTIBLE;
135 schedule();
136 set_restore_sigmask();
137 return -ERESTARTNOHAND;
140 asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
141 stack_ia32_t __user *uoss_ptr,
142 struct pt_regs *regs)
144 stack_t uss, uoss;
145 int ret;
146 mm_segment_t seg;
148 if (uss_ptr) {
149 u32 ptr;
151 memset(&uss, 0, sizeof(stack_t));
152 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) ||
153 __get_user(ptr, &uss_ptr->ss_sp) ||
154 __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
155 __get_user(uss.ss_size, &uss_ptr->ss_size))
156 return -EFAULT;
157 uss.ss_sp = compat_ptr(ptr);
159 seg = get_fs();
160 set_fs(KERNEL_DS);
161 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
162 set_fs(seg);
163 if (ret >= 0 && uoss_ptr) {
164 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) ||
165 __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
166 __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
167 __put_user(uoss.ss_size, &uoss_ptr->ss_size))
168 ret = -EFAULT;
170 return ret;
174 * Do a signal return; undo the signal stack.
177 struct sigframe
179 u32 pretcode;
180 int sig;
181 struct sigcontext_ia32 sc;
182 struct _fpstate_ia32 fpstate_unused; /* look at kernel/sigframe.h */
183 unsigned int extramask[_COMPAT_NSIG_WORDS-1];
184 char retcode[8];
185 /* fp state follows here */
188 struct rt_sigframe
190 u32 pretcode;
191 int sig;
192 u32 pinfo;
193 u32 puc;
194 compat_siginfo_t info;
195 struct ucontext_ia32 uc;
196 char retcode[8];
197 /* fp state follows here */
200 #define COPY(x) { \
201 unsigned int reg; \
202 err |= __get_user(reg, &sc->x); \
203 regs->x = reg; \
206 #define RELOAD_SEG(seg,mask) \
207 { unsigned int cur; \
208 unsigned short pre; \
209 err |= __get_user(pre, &sc->seg); \
210 asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \
211 pre |= mask; \
212 if (pre != cur) loadsegment(seg, pre); }
214 static int ia32_restore_sigcontext(struct pt_regs *regs,
215 struct sigcontext_ia32 __user *sc,
216 unsigned int *peax)
218 unsigned int tmpflags, gs, oldgs, err = 0;
219 void __user *buf;
220 u32 tmp;
222 /* Always make any pending restarted system calls return -EINTR */
223 current_thread_info()->restart_block.fn = do_no_restart_syscall;
225 #if DEBUG_SIG
226 printk(KERN_DEBUG "SIG restore_sigcontext: "
227 "sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
228 sc, sc->err, sc->ip, sc->cs, sc->flags);
229 #endif
232 * Reload fs and gs if they have changed in the signal
233 * handler. This does not handle long fs/gs base changes in
234 * the handler, but does not clobber them at least in the
235 * normal case.
237 err |= __get_user(gs, &sc->gs);
238 gs |= 3;
239 asm("movl %%gs,%0" : "=r" (oldgs));
240 if (gs != oldgs)
241 load_gs_index(gs);
243 RELOAD_SEG(fs, 3);
244 RELOAD_SEG(ds, 3);
245 RELOAD_SEG(es, 3);
247 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
248 COPY(dx); COPY(cx); COPY(ip);
249 /* Don't touch extended registers */
251 err |= __get_user(regs->cs, &sc->cs);
252 regs->cs |= 3;
253 err |= __get_user(regs->ss, &sc->ss);
254 regs->ss |= 3;
256 err |= __get_user(tmpflags, &sc->flags);
257 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
258 /* disable syscall checks */
259 regs->orig_ax = -1;
261 err |= __get_user(tmp, &sc->fpstate);
262 buf = compat_ptr(tmp);
263 err |= restore_i387_xstate_ia32(buf);
265 err |= __get_user(tmp, &sc->ax);
266 *peax = tmp;
268 return err;
271 asmlinkage long sys32_sigreturn(struct pt_regs *regs)
273 struct sigframe __user *frame = (struct sigframe __user *)(regs->sp-8);
274 sigset_t set;
275 unsigned int ax;
277 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
278 goto badframe;
279 if (__get_user(set.sig[0], &frame->sc.oldmask)
280 || (_COMPAT_NSIG_WORDS > 1
281 && __copy_from_user((((char *) &set.sig) + 4),
282 &frame->extramask,
283 sizeof(frame->extramask))))
284 goto badframe;
286 sigdelsetmask(&set, ~_BLOCKABLE);
287 spin_lock_irq(&current->sighand->siglock);
288 current->blocked = set;
289 recalc_sigpending();
290 spin_unlock_irq(&current->sighand->siglock);
292 if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
293 goto badframe;
294 return ax;
296 badframe:
297 signal_fault(regs, frame, "32bit sigreturn");
298 return 0;
301 asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
303 struct rt_sigframe __user *frame;
304 sigset_t set;
305 unsigned int ax;
306 struct pt_regs tregs;
308 frame = (struct rt_sigframe __user *)(regs->sp - 4);
310 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
311 goto badframe;
312 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
313 goto badframe;
315 sigdelsetmask(&set, ~_BLOCKABLE);
316 spin_lock_irq(&current->sighand->siglock);
317 current->blocked = set;
318 recalc_sigpending();
319 spin_unlock_irq(&current->sighand->siglock);
321 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
322 goto badframe;
324 tregs = *regs;
325 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
326 goto badframe;
328 return ax;
330 badframe:
331 signal_fault(regs, frame, "32bit rt sigreturn");
332 return 0;
336 * Set up a signal frame.
339 static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
340 void __user *fpstate,
341 struct pt_regs *regs, unsigned int mask)
343 int tmp, err = 0;
345 tmp = 0;
346 __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
347 err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
348 __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
349 err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
350 __asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp));
351 err |= __put_user(tmp, (unsigned int __user *)&sc->ds);
352 __asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp));
353 err |= __put_user(tmp, (unsigned int __user *)&sc->es);
355 err |= __put_user((u32)regs->di, &sc->di);
356 err |= __put_user((u32)regs->si, &sc->si);
357 err |= __put_user((u32)regs->bp, &sc->bp);
358 err |= __put_user((u32)regs->sp, &sc->sp);
359 err |= __put_user((u32)regs->bx, &sc->bx);
360 err |= __put_user((u32)regs->dx, &sc->dx);
361 err |= __put_user((u32)regs->cx, &sc->cx);
362 err |= __put_user((u32)regs->ax, &sc->ax);
363 err |= __put_user((u32)regs->cs, &sc->cs);
364 err |= __put_user((u32)regs->ss, &sc->ss);
365 err |= __put_user(current->thread.trap_no, &sc->trapno);
366 err |= __put_user(current->thread.error_code, &sc->err);
367 err |= __put_user((u32)regs->ip, &sc->ip);
368 err |= __put_user((u32)regs->flags, &sc->flags);
369 err |= __put_user((u32)regs->sp, &sc->sp_at_signal);
371 tmp = save_i387_xstate_ia32(fpstate);
372 if (tmp < 0)
373 err = -EFAULT;
374 else {
375 clear_used_math();
376 stts();
377 err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL),
378 &sc->fpstate);
381 /* non-iBCS2 extensions.. */
382 err |= __put_user(mask, &sc->oldmask);
383 err |= __put_user(current->thread.cr2, &sc->cr2);
385 return err;
389 * Determine which stack to use..
391 static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
392 size_t frame_size,
393 void **fpstate)
395 unsigned long sp;
397 /* Default to using normal stack */
398 sp = regs->sp;
400 /* This is the X/Open sanctioned signal stack switching. */
401 if (ka->sa.sa_flags & SA_ONSTACK) {
402 if (sas_ss_flags(sp) == 0)
403 sp = current->sas_ss_sp + current->sas_ss_size;
406 /* This is the legacy signal stack switching. */
407 else if ((regs->ss & 0xffff) != __USER_DS &&
408 !(ka->sa.sa_flags & SA_RESTORER) &&
409 ka->sa.sa_restorer)
410 sp = (unsigned long) ka->sa.sa_restorer;
412 if (used_math()) {
413 sp = sp - sig_xstate_ia32_size;
414 *fpstate = (struct _fpstate_ia32 *) sp;
417 sp -= frame_size;
418 /* Align the stack pointer according to the i386 ABI,
419 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
420 sp = ((sp + 4) & -16ul) - 4;
421 return (void __user *) sp;
424 int ia32_setup_frame(int sig, struct k_sigaction *ka,
425 compat_sigset_t *set, struct pt_regs *regs)
427 struct sigframe __user *frame;
428 void __user *restorer;
429 int err = 0;
430 void __user *fpstate = NULL;
432 /* copy_to_user optimizes that into a single 8 byte store */
433 static const struct {
434 u16 poplmovl;
435 u32 val;
436 u16 int80;
437 u16 pad;
438 } __attribute__((packed)) code = {
439 0xb858, /* popl %eax ; movl $...,%eax */
440 __NR_ia32_sigreturn,
441 0x80cd, /* int $0x80 */
445 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
447 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
448 goto give_sigsegv;
450 err |= __put_user(sig, &frame->sig);
451 if (err)
452 goto give_sigsegv;
454 err |= ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]);
455 if (err)
456 goto give_sigsegv;
458 if (_COMPAT_NSIG_WORDS > 1) {
459 err |= __copy_to_user(frame->extramask, &set->sig[1],
460 sizeof(frame->extramask));
461 if (err)
462 goto give_sigsegv;
465 if (ka->sa.sa_flags & SA_RESTORER) {
466 restorer = ka->sa.sa_restorer;
467 } else {
468 /* Return stub is in 32bit vsyscall page */
469 if (current->mm->context.vdso)
470 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
471 sigreturn);
472 else
473 restorer = &frame->retcode;
475 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
478 * These are actually not used anymore, but left because some
479 * gdb versions depend on them as a marker.
481 err |= __copy_to_user(frame->retcode, &code, 8);
482 if (err)
483 goto give_sigsegv;
485 /* Set up registers for signal handler */
486 regs->sp = (unsigned long) frame;
487 regs->ip = (unsigned long) ka->sa.sa_handler;
489 /* Make -mregparm=3 work */
490 regs->ax = sig;
491 regs->dx = 0;
492 regs->cx = 0;
494 asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
495 asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
497 regs->cs = __USER32_CS;
498 regs->ss = __USER32_DS;
500 #if DEBUG_SIG
501 printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
502 current->comm, current->pid, frame, regs->ip, frame->pretcode);
503 #endif
505 return 0;
507 give_sigsegv:
508 force_sigsegv(sig, current);
509 return -EFAULT;
512 int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
513 compat_sigset_t *set, struct pt_regs *regs)
515 struct rt_sigframe __user *frame;
516 void __user *restorer;
517 int err = 0;
518 void __user *fpstate = NULL;
520 /* __copy_to_user optimizes that into a single 8 byte store */
521 static const struct {
522 u8 movl;
523 u32 val;
524 u16 int80;
525 u16 pad;
526 u8 pad2;
527 } __attribute__((packed)) code = {
528 0xb8,
529 __NR_ia32_rt_sigreturn,
530 0x80cd,
534 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
536 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
537 goto give_sigsegv;
539 err |= __put_user(sig, &frame->sig);
540 err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo);
541 err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc);
542 err |= copy_siginfo_to_user32(&frame->info, info);
543 if (err)
544 goto give_sigsegv;
546 /* Create the ucontext. */
547 if (cpu_has_xsave)
548 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
549 else
550 err |= __put_user(0, &frame->uc.uc_flags);
551 err |= __put_user(0, &frame->uc.uc_link);
552 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
553 err |= __put_user(sas_ss_flags(regs->sp),
554 &frame->uc.uc_stack.ss_flags);
555 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
556 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
557 regs, set->sig[0]);
558 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
559 if (err)
560 goto give_sigsegv;
562 if (ka->sa.sa_flags & SA_RESTORER)
563 restorer = ka->sa.sa_restorer;
564 else
565 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
566 rt_sigreturn);
567 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
570 * Not actually used anymore, but left because some gdb
571 * versions need it.
573 err |= __copy_to_user(frame->retcode, &code, 8);
574 if (err)
575 goto give_sigsegv;
577 /* Set up registers for signal handler */
578 regs->sp = (unsigned long) frame;
579 regs->ip = (unsigned long) ka->sa.sa_handler;
581 /* Make -mregparm=3 work */
582 regs->ax = sig;
583 regs->dx = (unsigned long) &frame->info;
584 regs->cx = (unsigned long) &frame->uc;
586 /* Make -mregparm=3 work */
587 regs->ax = sig;
588 regs->dx = (unsigned long) &frame->info;
589 regs->cx = (unsigned long) &frame->uc;
591 asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
592 asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
594 regs->cs = __USER32_CS;
595 regs->ss = __USER32_DS;
597 #if DEBUG_SIG
598 printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
599 current->comm, current->pid, frame, regs->ip, frame->pretcode);
600 #endif
602 return 0;
604 give_sigsegv:
605 force_sigsegv(sig, current);
606 return -EFAULT;