[ARM] Support register switch in nommu mode
[linux-2.6/verdex.git] / arch / x86_64 / ia32 / ia32_signal.c
blobe0a92439f6342a350d45feaca527ed5b9e9e3426
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 *
10 * $Id: ia32_signal.c,v 1.22 2002/07/29 10:34:03 ak Exp $
13 #include <linux/sched.h>
14 #include <linux/mm.h>
15 #include <linux/smp.h>
16 #include <linux/smp_lock.h>
17 #include <linux/kernel.h>
18 #include <linux/signal.h>
19 #include <linux/errno.h>
20 #include <linux/wait.h>
21 #include <linux/ptrace.h>
22 #include <linux/unistd.h>
23 #include <linux/stddef.h>
24 #include <linux/personality.h>
25 #include <linux/compat.h>
26 #include <asm/ucontext.h>
27 #include <asm/uaccess.h>
28 #include <asm/i387.h>
29 #include <asm/ia32.h>
30 #include <asm/ptrace.h>
31 #include <asm/ia32_unistd.h>
32 #include <asm/user32.h>
33 #include <asm/sigcontext32.h>
34 #include <asm/fpu32.h>
35 #include <asm/proto.h>
36 #include <asm/vsyscall32.h>
38 #define DEBUG_SIG 0
40 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
42 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
43 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
45 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
47 int err;
48 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
49 return -EFAULT;
51 /* If you change siginfo_t structure, please make sure that
52 this code is fixed accordingly.
53 It should never copy any pad contained in the structure
54 to avoid security leaks, but must copy the generic
55 3 ints plus the relevant union member. */
56 err = __put_user(from->si_signo, &to->si_signo);
57 err |= __put_user(from->si_errno, &to->si_errno);
58 err |= __put_user((short)from->si_code, &to->si_code);
60 if (from->si_code < 0) {
61 err |= __put_user(from->si_pid, &to->si_pid);
62 err |= __put_user(from->si_uid, &to->si_uid);
63 err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
64 } else {
65 /* First 32bits of unions are always present:
66 * si_pid === si_band === si_tid === si_addr(LS half) */
67 err |= __put_user(from->_sifields._pad[0], &to->_sifields._pad[0]);
68 switch (from->si_code >> 16) {
69 case __SI_FAULT >> 16:
70 break;
71 case __SI_CHLD >> 16:
72 err |= __put_user(from->si_utime, &to->si_utime);
73 err |= __put_user(from->si_stime, &to->si_stime);
74 err |= __put_user(from->si_status, &to->si_status);
75 /* FALL THROUGH */
76 default:
77 case __SI_KILL >> 16:
78 err |= __put_user(from->si_uid, &to->si_uid);
79 break;
80 case __SI_POLL >> 16:
81 err |= __put_user(from->si_fd, &to->si_fd);
82 break;
83 case __SI_TIMER >> 16:
84 err |= __put_user(from->si_overrun, &to->si_overrun);
85 err |= __put_user(ptr_to_compat(from->si_ptr),
86 &to->si_ptr);
87 break;
88 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
89 case __SI_MESGQ >> 16:
90 err |= __put_user(from->si_uid, &to->si_uid);
91 err |= __put_user(from->si_int, &to->si_int);
92 break;
95 return err;
98 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
100 int err;
101 u32 ptr32;
102 if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
103 return -EFAULT;
105 err = __get_user(to->si_signo, &from->si_signo);
106 err |= __get_user(to->si_errno, &from->si_errno);
107 err |= __get_user(to->si_code, &from->si_code);
109 err |= __get_user(to->si_pid, &from->si_pid);
110 err |= __get_user(to->si_uid, &from->si_uid);
111 err |= __get_user(ptr32, &from->si_ptr);
112 to->si_ptr = compat_ptr(ptr32);
114 return err;
117 asmlinkage long
118 sys32_sigsuspend(int history0, int history1, old_sigset_t mask,
119 struct pt_regs *regs)
121 sigset_t saveset;
123 mask &= _BLOCKABLE;
124 spin_lock_irq(&current->sighand->siglock);
125 saveset = current->blocked;
126 siginitset(&current->blocked, mask);
127 recalc_sigpending();
128 spin_unlock_irq(&current->sighand->siglock);
130 regs->rax = -EINTR;
131 while (1) {
132 current->state = TASK_INTERRUPTIBLE;
133 schedule();
134 if (do_signal(regs, &saveset))
135 return -EINTR;
139 asmlinkage long
140 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;
147 if (uss_ptr) {
148 u32 ptr;
149 memset(&uss,0,sizeof(stack_t));
150 if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) ||
151 __get_user(ptr, &uss_ptr->ss_sp) ||
152 __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
153 __get_user(uss.ss_size, &uss_ptr->ss_size))
154 return -EFAULT;
155 uss.ss_sp = compat_ptr(ptr);
157 seg = get_fs();
158 set_fs(KERNEL_DS);
159 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->rsp);
160 set_fs(seg);
161 if (ret >= 0 && uoss_ptr) {
162 if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) ||
163 __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
164 __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
165 __put_user(uoss.ss_size, &uoss_ptr->ss_size))
166 ret = -EFAULT;
168 return ret;
172 * Do a signal return; undo the signal stack.
175 struct sigframe
177 u32 pretcode;
178 int sig;
179 struct sigcontext_ia32 sc;
180 struct _fpstate_ia32 fpstate;
181 unsigned int extramask[_COMPAT_NSIG_WORDS-1];
182 char retcode[8];
185 struct rt_sigframe
187 u32 pretcode;
188 int sig;
189 u32 pinfo;
190 u32 puc;
191 compat_siginfo_t info;
192 struct ucontext_ia32 uc;
193 struct _fpstate_ia32 fpstate;
194 char retcode[8];
197 static int
198 ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc, unsigned int *peax)
200 unsigned int err = 0;
202 /* Always make any pending restarted system calls return -EINTR */
203 current_thread_info()->restart_block.fn = do_no_restart_syscall;
205 #if DEBUG_SIG
206 printk("SIG restore_sigcontext: sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
207 sc, sc->err, sc->eip, sc->cs, sc->eflags);
208 #endif
209 #define COPY(x) { \
210 unsigned int reg; \
211 err |= __get_user(reg, &sc->e ##x); \
212 regs->r ## x = reg; \
215 #define RELOAD_SEG(seg,mask) \
216 { unsigned int cur; \
217 unsigned short pre; \
218 err |= __get_user(pre, &sc->seg); \
219 asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \
220 pre |= mask; \
221 if (pre != cur) loadsegment(seg,pre); }
223 /* Reload fs and gs if they have changed in the signal handler.
224 This does not handle long fs/gs base changes in the handler, but
225 does not clobber them at least in the normal case. */
228 unsigned gs, oldgs;
229 err |= __get_user(gs, &sc->gs);
230 gs |= 3;
231 asm("movl %%gs,%0" : "=r" (oldgs));
232 if (gs != oldgs)
233 load_gs_index(gs);
235 RELOAD_SEG(fs,3);
236 RELOAD_SEG(ds,3);
237 RELOAD_SEG(es,3);
239 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
240 COPY(dx); COPY(cx); COPY(ip);
241 /* Don't touch extended registers */
243 err |= __get_user(regs->cs, &sc->cs);
244 regs->cs |= 3;
245 err |= __get_user(regs->ss, &sc->ss);
246 regs->ss |= 3;
249 unsigned int tmpflags;
250 err |= __get_user(tmpflags, &sc->eflags);
251 regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
252 regs->orig_rax = -1; /* disable syscall checks */
256 u32 tmp;
257 struct _fpstate_ia32 __user * buf;
258 err |= __get_user(tmp, &sc->fpstate);
259 buf = compat_ptr(tmp);
260 if (buf) {
261 if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
262 goto badframe;
263 err |= restore_i387_ia32(current, buf, 0);
264 } else {
265 struct task_struct *me = current;
266 if (used_math()) {
267 clear_fpu(me);
268 clear_used_math();
274 u32 tmp;
275 err |= __get_user(tmp, &sc->eax);
276 *peax = tmp;
278 return err;
280 badframe:
281 return 1;
284 asmlinkage long sys32_sigreturn(struct pt_regs *regs)
286 struct sigframe __user *frame = (struct sigframe __user *)(regs->rsp-8);
287 sigset_t set;
288 unsigned int eax;
290 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
291 goto badframe;
292 if (__get_user(set.sig[0], &frame->sc.oldmask)
293 || (_COMPAT_NSIG_WORDS > 1
294 && __copy_from_user((((char *) &set.sig) + 4), &frame->extramask,
295 sizeof(frame->extramask))))
296 goto badframe;
298 sigdelsetmask(&set, ~_BLOCKABLE);
299 spin_lock_irq(&current->sighand->siglock);
300 current->blocked = set;
301 recalc_sigpending();
302 spin_unlock_irq(&current->sighand->siglock);
304 if (ia32_restore_sigcontext(regs, &frame->sc, &eax))
305 goto badframe;
306 return eax;
308 badframe:
309 signal_fault(regs, frame, "32bit sigreturn");
310 return 0;
313 asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
315 struct rt_sigframe __user *frame;
316 sigset_t set;
317 unsigned int eax;
318 struct pt_regs tregs;
320 frame = (struct rt_sigframe __user *)(regs->rsp - 4);
322 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
323 goto badframe;
324 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
325 goto badframe;
327 sigdelsetmask(&set, ~_BLOCKABLE);
328 spin_lock_irq(&current->sighand->siglock);
329 current->blocked = set;
330 recalc_sigpending();
331 spin_unlock_irq(&current->sighand->siglock);
333 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax))
334 goto badframe;
336 tregs = *regs;
337 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
338 goto badframe;
340 return eax;
342 badframe:
343 signal_fault(regs,frame,"32bit rt sigreturn");
344 return 0;
348 * Set up a signal frame.
351 static int
352 ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __user *fpstate,
353 struct pt_regs *regs, unsigned int mask)
355 int tmp, err = 0;
357 tmp = 0;
358 __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
359 err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
360 __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
361 err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
362 __asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp));
363 err |= __put_user(tmp, (unsigned int __user *)&sc->ds);
364 __asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp));
365 err |= __put_user(tmp, (unsigned int __user *)&sc->es);
367 err |= __put_user((u32)regs->rdi, &sc->edi);
368 err |= __put_user((u32)regs->rsi, &sc->esi);
369 err |= __put_user((u32)regs->rbp, &sc->ebp);
370 err |= __put_user((u32)regs->rsp, &sc->esp);
371 err |= __put_user((u32)regs->rbx, &sc->ebx);
372 err |= __put_user((u32)regs->rdx, &sc->edx);
373 err |= __put_user((u32)regs->rcx, &sc->ecx);
374 err |= __put_user((u32)regs->rax, &sc->eax);
375 err |= __put_user((u32)regs->cs, &sc->cs);
376 err |= __put_user((u32)regs->ss, &sc->ss);
377 err |= __put_user(current->thread.trap_no, &sc->trapno);
378 err |= __put_user(current->thread.error_code, &sc->err);
379 err |= __put_user((u32)regs->rip, &sc->eip);
380 err |= __put_user((u32)regs->eflags, &sc->eflags);
381 err |= __put_user((u32)regs->rsp, &sc->esp_at_signal);
383 tmp = save_i387_ia32(current, fpstate, regs, 0);
384 if (tmp < 0)
385 err = -EFAULT;
386 else {
387 clear_used_math();
388 stts();
389 err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL),
390 &sc->fpstate);
393 /* non-iBCS2 extensions.. */
394 err |= __put_user(mask, &sc->oldmask);
395 err |= __put_user(current->thread.cr2, &sc->cr2);
397 return err;
401 * Determine which stack to use..
403 static void __user *
404 get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
406 unsigned long rsp;
408 /* Default to using normal stack */
409 rsp = regs->rsp;
411 /* This is the X/Open sanctioned signal stack switching. */
412 if (ka->sa.sa_flags & SA_ONSTACK) {
413 if (sas_ss_flags(rsp) == 0)
414 rsp = current->sas_ss_sp + current->sas_ss_size;
417 /* This is the legacy signal stack switching. */
418 else if ((regs->ss & 0xffff) != __USER_DS &&
419 !(ka->sa.sa_flags & SA_RESTORER) &&
420 ka->sa.sa_restorer) {
421 rsp = (unsigned long) ka->sa.sa_restorer;
424 rsp -= frame_size;
425 /* Align the stack pointer according to the i386 ABI,
426 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
427 rsp = ((rsp + 4) & -16ul) - 4;
428 return (void __user *) rsp;
431 int ia32_setup_frame(int sig, struct k_sigaction *ka,
432 compat_sigset_t *set, struct pt_regs * regs)
434 struct sigframe __user *frame;
435 int err = 0;
437 frame = get_sigframe(ka, regs, sizeof(*frame));
439 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
440 goto give_sigsegv;
443 struct exec_domain *ed = current_thread_info()->exec_domain;
444 err |= __put_user((ed
445 && ed->signal_invmap
446 && sig < 32
447 ? ed->signal_invmap[sig]
448 : sig),
449 &frame->sig);
451 if (err)
452 goto give_sigsegv;
454 err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs,
455 set->sig[0]);
456 if (err)
457 goto give_sigsegv;
459 if (_COMPAT_NSIG_WORDS > 1) {
460 err |= __copy_to_user(frame->extramask, &set->sig[1],
461 sizeof(frame->extramask));
463 if (err)
464 goto give_sigsegv;
466 /* Return stub is in 32bit vsyscall page */
468 void __user *restorer = VSYSCALL32_SIGRETURN;
469 if (ka->sa.sa_flags & SA_RESTORER)
470 restorer = ka->sa.sa_restorer;
471 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
473 /* These are actually not used anymore, but left because some
474 gdb versions depend on them as a marker. */
476 /* copy_to_user optimizes that into a single 8 byte store */
477 static const struct {
478 u16 poplmovl;
479 u32 val;
480 u16 int80;
481 u16 pad;
482 } __attribute__((packed)) code = {
483 0xb858, /* popl %eax ; movl $...,%eax */
484 __NR_ia32_sigreturn,
485 0x80cd, /* int $0x80 */
488 err |= __copy_to_user(frame->retcode, &code, 8);
490 if (err)
491 goto give_sigsegv;
493 /* Set up registers for signal handler */
494 regs->rsp = (unsigned long) frame;
495 regs->rip = (unsigned long) ka->sa.sa_handler;
497 asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
498 asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
500 regs->cs = __USER32_CS;
501 regs->ss = __USER32_DS;
503 set_fs(USER_DS);
504 regs->eflags &= ~TF_MASK;
505 if (test_thread_flag(TIF_SINGLESTEP))
506 ptrace_notify(SIGTRAP);
508 #if DEBUG_SIG
509 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
510 current->comm, current->pid, frame, regs->rip, frame->pretcode);
511 #endif
513 return 1;
515 give_sigsegv:
516 force_sigsegv(sig, current);
517 return 0;
520 int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
521 compat_sigset_t *set, struct pt_regs * regs)
523 struct rt_sigframe __user *frame;
524 int err = 0;
526 frame = get_sigframe(ka, regs, sizeof(*frame));
528 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
529 goto give_sigsegv;
532 struct exec_domain *ed = current_thread_info()->exec_domain;
533 err |= __put_user((ed
534 && ed->signal_invmap
535 && sig < 32
536 ? ed->signal_invmap[sig]
537 : sig),
538 &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 err |= __put_user(0, &frame->uc.uc_flags);
548 err |= __put_user(0, &frame->uc.uc_link);
549 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
550 err |= __put_user(sas_ss_flags(regs->rsp),
551 &frame->uc.uc_stack.ss_flags);
552 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
553 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
554 regs, set->sig[0]);
555 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
556 if (err)
557 goto give_sigsegv;
561 void __user *restorer = VSYSCALL32_RTSIGRETURN;
562 if (ka->sa.sa_flags & SA_RESTORER)
563 restorer = ka->sa.sa_restorer;
564 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
567 /* This is movl $,%eax ; int $0x80 */
568 /* Not actually used anymore, but left because some gdb versions
569 need it. */
571 /* __copy_to_user optimizes that into a single 8 byte store */
572 static const struct {
573 u8 movl;
574 u32 val;
575 u16 int80;
576 u16 pad;
577 u8 pad2;
578 } __attribute__((packed)) code = {
579 0xb8,
580 __NR_ia32_rt_sigreturn,
581 0x80cd,
584 err |= __copy_to_user(frame->retcode, &code, 8);
586 if (err)
587 goto give_sigsegv;
589 /* Set up registers for signal handler */
590 regs->rsp = (unsigned long) frame;
591 regs->rip = (unsigned long) ka->sa.sa_handler;
593 asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
594 asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
596 regs->cs = __USER32_CS;
597 regs->ss = __USER32_DS;
599 set_fs(USER_DS);
600 regs->eflags &= ~TF_MASK;
601 if (test_thread_flag(TIF_SINGLESTEP))
602 ptrace_notify(SIGTRAP);
604 #if DEBUG_SIG
605 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
606 current->comm, current->pid, frame, regs->rip, frame->pretcode);
607 #endif
609 return 1;
611 give_sigsegv:
612 force_sigsegv(sig, current);
613 return 0;