File: /usr/src/linux/arch/ia64/ia32/ia32_signal.c

1     /*
2      * IA32 Architecture-specific signal handling support.
3      *
4      * Copyright (C) 1999 Hewlett-Packard Co
5      * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
6      * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
7      * Copyright (C) 2000 VA Linux Co
8      * Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
9      *
10      * Derived from i386 and Alpha versions.
11      */
12     
13     #include <linux/errno.h>
14     #include <linux/kernel.h>
15     #include <linux/mm.h>
16     #include <linux/ptrace.h>
17     #include <linux/sched.h>
18     #include <linux/signal.h>
19     #include <linux/smp.h>
20     #include <linux/smp_lock.h>
21     #include <linux/stddef.h>
22     #include <linux/unistd.h>
23     #include <linux/wait.h>
24     
25     #include <asm/uaccess.h>
26     #include <asm/rse.h>
27     #include <asm/sigcontext.h>
28     #include <asm/segment.h>
29     #include <asm/ia32.h>
30     
31     #define DEBUG_SIG	0
32     #define _BLOCKABLE	(~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
33     
34     
35     struct sigframe_ia32
36     {
37            int pretcode;
38            int sig;
39            struct sigcontext_ia32 sc;
40            struct _fpstate_ia32 fpstate;
41            unsigned int extramask[_IA32_NSIG_WORDS-1];
42            char retcode[8];
43     };
44     
45     struct rt_sigframe_ia32
46     {
47            int pretcode;
48            int sig;
49            int pinfo;
50            int puc;
51            siginfo_t32 info;
52            struct ucontext_ia32 uc;
53            struct _fpstate_ia32 fpstate;
54            char retcode[8];
55     };
56     
57     static int
58     copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from)
59     {
60     	int err;
61     
62     	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
63     		return -EFAULT;
64     
65     	/* If you change siginfo_t structure, please be sure
66     	   this code is fixed accordingly.
67     	   It should never copy any pad contained in the structure
68     	   to avoid security leaks, but must copy the generic
69     	   3 ints plus the relevant union member.
70     	   This routine must convert siginfo from 64bit to 32bit as well
71     	   at the same time.  */
72     	err = __put_user(from->si_signo, &to->si_signo);
73     	err |= __put_user(from->si_errno, &to->si_errno);
74     	err |= __put_user((short)from->si_code, &to->si_code);
75     	if (from->si_code < 0)
76     		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
77     	else {
78     		switch (from->si_code >> 16) {
79     		case __SI_CHLD >> 16:
80     			err |= __put_user(from->si_utime, &to->si_utime);
81     			err |= __put_user(from->si_stime, &to->si_stime);
82     			err |= __put_user(from->si_status, &to->si_status);
83     		default:
84     			err |= __put_user(from->si_pid, &to->si_pid);
85     			err |= __put_user(from->si_uid, &to->si_uid);
86     			break;
87     		case __SI_FAULT >> 16:
88     			err |= __put_user((long)from->si_addr, &to->si_addr);
89     			break;
90     		case __SI_POLL >> 16:
91     			err |= __put_user(from->si_band, &to->si_band);
92     			err |= __put_user(from->si_fd, &to->si_fd);
93     			break;
94     		/* case __SI_RT: This is not generated by the kernel as of now.  */
95     		}
96     	}
97     	return err;
98     }
99     
100     
101     
102     static int
103     setup_sigcontext_ia32(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
104                     struct pt_regs *regs, unsigned long mask)
105     {
106            int  err = 0;
107            unsigned long flag;
108     
109            err |= __put_user((regs->r16 >> 32) & 0xffff , (unsigned int *)&sc->fs);
110            err |= __put_user((regs->r16 >> 48) & 0xffff , (unsigned int *)&sc->gs);
111     
112            err |= __put_user((regs->r16 >> 56) & 0xffff, (unsigned int *)&sc->es);
113            err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&sc->ds);
114            err |= __put_user(regs->r15, &sc->edi);
115            err |= __put_user(regs->r14, &sc->esi);
116            err |= __put_user(regs->r13, &sc->ebp);
117            err |= __put_user(regs->r12, &sc->esp);
118            err |= __put_user(regs->r11, &sc->ebx);
119            err |= __put_user(regs->r10, &sc->edx);
120            err |= __put_user(regs->r9, &sc->ecx);
121            err |= __put_user(regs->r8, &sc->eax);
122     #if 0
123            err |= __put_user(current->tss.trap_no, &sc->trapno);
124            err |= __put_user(current->tss.error_code, &sc->err);
125     #endif
126            err |= __put_user(regs->cr_iip, &sc->eip);
127            err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs);
128            /*
129     	*  `eflags' is in an ar register for this context
130     	*/
131            asm volatile ("mov %0=ar.eflag ;;" : "=r"(flag));
132            err |= __put_user((unsigned int)flag, &sc->eflags);
133            
134            err |= __put_user(regs->r12, &sc->esp_at_signal);
135            err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss);
136     
137     #if 0
138            tmp = save_i387(fpstate);
139            if (tmp < 0)
140              err = 1;
141            else
142              err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
143     
144            /* non-iBCS2 extensions.. */
145     #endif
146            err |= __put_user(mask, &sc->oldmask);
147     #if 0
148            err |= __put_user(current->tss.cr2, &sc->cr2);
149     #endif
150            
151            return err;
152     }
153     
154     static int
155     restore_sigcontext_ia32(struct pt_regs *regs, struct sigcontext_ia32 *sc, int *peax)
156     {
157            unsigned int err = 0;
158     
159     #define COPY(ia64x, ia32x)             err |= __get_user(regs->ia64x, &sc->ia32x)
160     
161     #define copyseg_gs(tmp)        (regs->r16 |= (unsigned long) tmp << 48)
162     #define copyseg_fs(tmp)        (regs->r16 |= (unsigned long) tmp << 32)
163     #define copyseg_cs(tmp)        (regs->r17 |= tmp)
164     #define copyseg_ss(tmp)        (regs->r17 |= (unsigned long) tmp << 16)
165     #define copyseg_es(tmp)        (regs->r16 |= (unsigned long) tmp << 16)
166     #define copyseg_ds(tmp)        (regs->r16 |= tmp)
167     
168     #define COPY_SEG(seg)                                          \
169            { unsigned short tmp;                                   \
170              err |= __get_user(tmp, &sc->seg);                             \
171              copyseg_##seg(tmp); }
172     
173     #define COPY_SEG_STRICT(seg)                                   \
174            { unsigned short tmp;                                   \
175              err |= __get_user(tmp, &sc->seg);                             \
176              copyseg_##seg(tmp|3); }
177     
178            /* To make COPY_SEGs easier, we zero r16, r17 */
179            regs->r16 = 0;
180            regs->r17 = 0;
181     
182            COPY_SEG(gs);
183            COPY_SEG(fs);
184            COPY_SEG(es);
185            COPY_SEG(ds);
186            COPY(r15, edi);
187            COPY(r14, esi);
188            COPY(r13, ebp);
189            COPY(r12, esp);
190            COPY(r11, ebx);
191            COPY(r10, edx);
192            COPY(r9, ecx);
193            COPY(cr_iip, eip);
194            COPY_SEG_STRICT(cs);
195            COPY_SEG_STRICT(ss);
196            {
197     		unsigned int tmpflags;
198     		unsigned long flag;
199     
200     		/*
201     		 *  IA32 `eflags' is not part of `pt_regs', it's
202     		 *  in an ar register which is part of the thread
203     		 *  context.  Fortunately, we are executing in the
204     		 *  IA32 process's context.
205     		 */
206     		err |= __get_user(tmpflags, &sc->eflags);
207     		asm volatile ("mov %0=ar.eflag ;;" : "=r"(flag));
208     		flag &= ~0x40DD5;
209     		flag |= (tmpflags & 0x40DD5);
210     		asm volatile ("mov ar.eflag=%0 ;;" :: "r"(flag));
211     
212     		regs->r1 = -1;	/* disable syscall checks, r1 is orig_eax */
213            }
214     
215     #if 0
216            {
217                    struct _fpstate * buf;
218                    err |= __get_user(buf, &sc->fpstate);
219                    if (buf) {
220                            if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
221                                    goto badframe;
222                            err |= restore_i387(buf);
223                    }
224            }
225     #endif
226     
227            err |= __get_user(*peax, &sc->eax);
228            return err;
229     
230     #if 0       
231     badframe:
232            return 1;
233     #endif
234     
235     }
236     
237     /*
238      * Determine which stack to use..
239      */
240     static inline void *
241     get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
242     {
243            unsigned long esp;
244            unsigned int xss;
245     
246            /* Default to using normal stack */
247            esp = regs->r12;
248            xss = regs->r16 >> 16;
249     
250            /* This is the X/Open sanctioned signal stack switching.  */
251            if (ka->sa.sa_flags & SA_ONSTACK) {
252                    if (! on_sig_stack(esp))
253                            esp = current->sas_ss_sp + current->sas_ss_size;
254            }
255            /* Legacy stack switching not supported */
256            
257            return (void *)((esp - frame_size) & -8ul);
258     }
259     
260     static int
261     setup_frame_ia32(int sig, struct k_sigaction *ka, sigset_t *set,
262                struct pt_regs * regs) 
263     {      
264            struct sigframe_ia32 *frame;
265            int err = 0;
266     
267            frame = get_sigframe(ka, regs, sizeof(*frame));
268     
269            if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
270                    goto give_sigsegv;
271     
272            err |= __put_user((current->exec_domain
273                               && current->exec_domain->signal_invmap
274                               && sig < 32
275                               ? (int)(current->exec_domain->signal_invmap[sig])
276                               : sig),
277                              &frame->sig);
278     
279            err |= setup_sigcontext_ia32(&frame->sc, &frame->fpstate, regs, set->sig[0]);
280     
281            if (_IA32_NSIG_WORDS > 1) {
282                    err |= __copy_to_user(frame->extramask, &set->sig[1],
283                                          sizeof(frame->extramask));
284            }
285     
286            /* Set up to return from userspace.  If provided, use a stub
287               already in userspace.  */
288            err |= __put_user((long)frame->retcode, &frame->pretcode);
289            /* This is popl %eax ; movl $,%eax ; int $0x80 */
290            err |= __put_user(0xb858, (short *)(frame->retcode+0));
291     #define __IA32_NR_sigreturn            119
292            err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
293            err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
294            err |= __put_user(0x80cd, (short *)(frame->retcode+6));
295     
296            if (err)
297                    goto give_sigsegv;
298     
299            /* Set up registers for signal handler */
300            regs->r12 = (unsigned long) frame;
301            regs->cr_iip = (unsigned long) ka->sa.sa_handler;
302     
303            set_fs(USER_DS);
304            regs->r16 = (__USER_DS << 16) |  (__USER_DS); /* ES == DS, GS, FS are zero */
305            regs->r17 = (__USER_DS << 16) | __USER_CS;
306     
307     #if 0
308            regs->eflags &= ~TF_MASK;
309     #endif
310     
311     #if 0
312            printk("SIG deliver (%s:%d): sig=%d sp=%p pc=%lx ra=%x\n",
313                    current->comm, current->pid, sig, (void *) frame, regs->cr_iip, frame->pretcode);
314     #endif
315     
316            return 1;
317     
318     give_sigsegv:
319            if (sig == SIGSEGV)
320                    ka->sa.sa_handler = SIG_DFL;
321            force_sig(SIGSEGV, current);
322            return 0;
323     }
324     
325     static int
326     setup_rt_frame_ia32(int sig, struct k_sigaction *ka, siginfo_t *info,
327                   sigset_t *set, struct pt_regs * regs)
328     {
329            struct rt_sigframe_ia32 *frame;
330            int err = 0;
331     
332            frame = get_sigframe(ka, regs, sizeof(*frame));
333     
334            if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
335                    goto give_sigsegv;
336     
337            err |= __put_user((current->exec_domain
338                               && current->exec_domain->signal_invmap
339                               && sig < 32
340                               ? current->exec_domain->signal_invmap[sig]
341                               : sig),
342                              &frame->sig);
343            err |= __put_user((long)&frame->info, &frame->pinfo);
344            err |= __put_user((long)&frame->uc, &frame->puc);
345            err |= copy_siginfo_to_user32(&frame->info, info);
346     
347            /* Create the ucontext.  */
348            err |= __put_user(0, &frame->uc.uc_flags);
349            err |= __put_user(0, &frame->uc.uc_link);
350            err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
351            err |= __put_user(sas_ss_flags(regs->r12),
352                              &frame->uc.uc_stack.ss_flags);
353            err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
354            err |= setup_sigcontext_ia32(&frame->uc.uc_mcontext, &frame->fpstate,
355                                    regs, set->sig[0]);
356            err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
357            
358            err |= __put_user((long)frame->retcode, &frame->pretcode);
359            /* This is movl $,%eax ; int $0x80 */
360            err |= __put_user(0xb8, (char *)(frame->retcode+0));
361     #define __IA32_NR_rt_sigreturn         173
362            err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
363            err |= __put_user(0x80cd, (short *)(frame->retcode+5));
364     
365            if (err)
366                    goto give_sigsegv;
367     
368            /* Set up registers for signal handler */
369            regs->r12 = (unsigned long) frame;
370            regs->cr_iip = (unsigned long) ka->sa.sa_handler;
371     
372            set_fs(USER_DS);
373     
374            regs->r16 = (__USER_DS << 16) |  (__USER_DS); /* ES == DS, GS, FS are zero */
375            regs->r17 = (__USER_DS << 16) | __USER_CS;
376     
377     #if 0
378            regs->eflags &= ~TF_MASK;
379     #endif
380     
381     #if 0
382            printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n",
383                    current->comm, current->pid, (void *) frame, regs->cr_iip, frame->pretcode);
384     #endif
385     
386            return 1;
387     
388     give_sigsegv:
389            if (sig == SIGSEGV)
390                    ka->sa.sa_handler = SIG_DFL;
391            force_sig(SIGSEGV, current);
392            return 0;
393     }
394     
395     int
396     ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
397     		   sigset_t *set, struct pt_regs *regs)
398     {
399            /* Set up the stack frame */
400            if (ka->sa.sa_flags & SA_SIGINFO)
401                    return(setup_rt_frame_ia32(sig, ka, info, set, regs));
402            else
403                    return(setup_frame_ia32(sig, ka, set, regs));
404     }
405     
406     asmlinkage int
407     sys32_sigreturn(
408     int arg0,
409     int arg1,
410     int arg2,
411     int arg3,
412     int arg4,
413     int arg5,
414     int arg6,
415     int arg7,
416     unsigned long stack)
417     {
418            struct pt_regs *regs = (struct pt_regs *) &stack;
419            struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(regs->r12- 8);
420            sigset_t set;
421            int eax;
422     
423            if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
424                    goto badframe;
425     
426            if (__get_user(set.sig[0], &frame->sc.oldmask)
427                || (_IA32_NSIG_WORDS > 1
428                    && __copy_from_user((((char *) &set.sig) + 4),
429                                        &frame->extramask,
430                                        sizeof(frame->extramask))))
431                    goto badframe;
432     
433            sigdelsetmask(&set, ~_BLOCKABLE);
434            spin_lock_irq(&current->sigmask_lock);
435            current->blocked = (sigset_t) set;
436            recalc_sigpending(current);
437            spin_unlock_irq(&current->sigmask_lock);
438            
439            if (restore_sigcontext_ia32(regs, &frame->sc, &eax))
440                    goto badframe;
441            return eax;
442     
443     badframe:
444            force_sig(SIGSEGV, current);
445            return 0;
446     }      
447     
448     asmlinkage int
449     sys32_rt_sigreturn(
450     int arg0,
451     int arg1,
452     int arg2,
453     int arg3,
454     int arg4,
455     int arg5,
456     int arg6,
457     int arg7,
458     unsigned long stack)
459     {
460            struct pt_regs *regs = (struct pt_regs *) &stack;
461            struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(regs->r12 - 4);
462            sigset_t set;
463            stack_t st;
464            int eax;
465     
466            if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
467                    goto badframe;
468            if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
469                    goto badframe;
470     
471            sigdelsetmask(&set, ~_BLOCKABLE);
472            spin_lock_irq(&current->sigmask_lock);
473            current->blocked =  set;
474            recalc_sigpending(current);
475            spin_unlock_irq(&current->sigmask_lock);
476            
477            if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax))
478                    goto badframe;
479     
480            if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
481                    goto badframe;
482            /* It is more difficult to avoid calling this function than to
483               call it and ignore errors.  */
484            do_sigaltstack(&st, NULL, regs->r12);
485     
486            return eax;
487     
488     badframe:
489            force_sig(SIGSEGV, current);
490            return 0;
491     }      
492     
493