ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / parisc / kernel / signal32.c
1 /*    Signal support for 32-bit kernel builds
2  *
3  *    Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
4  *    Code was mostly borrowed from kernel/signal.c.
5  *    See kernel/signal.c for additional Copyrights.
6  *
7  *
8  *    This program is free software; you can redistribute it and/or modify
9  *    it under the terms of the GNU General Public License as published by
10  *    the Free Software Foundation; either version 2 of the License, or
11  *    (at your option) any later version.
12  *
13  *    This program is distributed in the hope that it will be useful,
14  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *    GNU General Public License for more details.
17  *
18  *    You should have received a copy of the GNU General Public License
19  *    along with this program; if not, write to the Free Software
20  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <linux/config.h>
24 #include <linux/compat.h>
25 #include <linux/slab.h>
26 #include <linux/module.h>
27 #include <linux/unistd.h>
28 #include <linux/smp_lock.h>
29 #include <linux/init.h>
30 #include <linux/sched.h>
31 #include <linux/syscalls.h>
32 #include <linux/types.h>
33 #include <linux/errno.h>
34
35 #include <asm/compat_signal.h>
36 #include <asm/uaccess.h>
37
38 #include "signal32.h"
39 #include "sys32.h"
40
41 #define DEBUG_COMPAT_SIG 0 
42 #define DEBUG_COMPAT_SIG_LEVEL 2
43
44 #if DEBUG_COMPAT_SIG
45 #define DBG(LEVEL, ...) \
46         ((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
47         ? printk(__VA_ARGS__) : (void) 0)
48 #else
49 #define DBG(LEVEL, ...)
50 #endif
51
52 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
53
54 inline void
55 sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
56 {
57         s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
58 }
59
60 inline void
61 sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
62 {
63         s32->sig[0] = s64->sig[0] & 0xffffffffUL;
64         s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
65 }
66
67 static int
68 put_sigset32(compat_sigset_t *up, sigset_t *set, size_t sz)
69 {
70         compat_sigset_t s;
71
72         if (sz != sizeof *set) panic("put_sigset32()");
73         sigset_64to32(&s, set);
74
75         return copy_to_user(up, &s, sizeof s);
76 }
77
78 static int
79 get_sigset32(compat_sigset_t *up, sigset_t *set, size_t sz)
80 {
81         compat_sigset_t s;
82         int r;
83
84         if (sz != sizeof *set) panic("put_sigset32()");
85
86         if ((r = copy_from_user(&s, up, sz)) == 0) {
87                 sigset_32to64(set, &s);
88         }
89
90         return r;
91 }
92
93 int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset,
94                                     unsigned int sigsetsize)
95 {
96         sigset_t old_set, new_set;
97         int ret;
98
99         if (set && get_sigset32(set, &new_set, sigsetsize))
100                 return -EFAULT;
101         
102         KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? &new_set : NULL,
103                                  oset ? &old_set : NULL, sigsetsize);
104
105         if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
106                 return -EFAULT;
107
108         return ret;
109 }
110
111
112 int sys32_rt_sigpending(compat_sigset_t *uset, unsigned int sigsetsize)
113 {
114         int ret;
115         sigset_t set;
116
117         KERNEL_SYSCALL(ret, sys_rt_sigpending, &set, sigsetsize);
118
119         if (!ret && put_sigset32(uset, &set, sigsetsize))
120                 return -EFAULT;
121
122         return ret;
123 }
124
125 long
126 sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact,
127                  size_t sigsetsize)
128 {
129         struct k_sigaction32 new_sa32, old_sa32;
130         struct k_sigaction new_sa, old_sa;
131         int ret = -EINVAL;
132
133         if (act) {
134                 if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
135                         return -EFAULT;
136                 new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
137                 new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
138                 sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
139         }
140
141         ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
142
143         if (!ret && oact) {
144                 sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
145                 old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
146                 old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
147                 if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
148                         return -EFAULT;
149         }
150         return ret;
151 }
152
153 int 
154 do_sigaltstack32 (const compat_stack_t *uss32, compat_stack_t *uoss32, unsigned long sp)
155 {
156         compat_stack_t ss32, oss32;
157         stack_t ss, oss;
158         stack_t *ssp = NULL, *ossp = NULL;
159         int ret;
160
161         if (uss32) {
162                 if (copy_from_user(&ss32, uss32, sizeof ss32))
163                         return -EFAULT;
164
165                 ss.ss_sp = (void *)(unsigned long)ss32.ss_sp;
166                 ss.ss_flags = ss32.ss_flags;
167                 ss.ss_size = ss32.ss_size;
168
169                 ssp = &ss;
170         }
171
172         if (uoss32)
173                 ossp = &oss;
174
175         KERNEL_SYSCALL(ret, do_sigaltstack, ssp, ossp, sp);
176
177         if (!ret && uoss32) {
178                 oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
179                 oss32.ss_flags = oss.ss_flags;
180                 oss32.ss_size = oss.ss_size;
181                 if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
182                         return -EFAULT;
183         }
184
185         return ret;
186 }
187
188 long
189 restore_sigcontext32(struct compat_sigcontext *sc, struct compat_regfile * rf,
190                 struct pt_regs *regs)
191 {
192         long err = 0;
193         compat_uint_t compat_reg;
194         compat_uint_t compat_regt;
195         int regn;
196         
197         /* When loading 32-bit values into 64-bit registers make
198            sure to clear the upper 32-bits */
199         DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
200         DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
201         DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
202         for(regn=0; regn < 32; regn++){
203                 err |= __get_user(compat_reg,&sc->sc_gr[regn]);
204                 regs->gr[regn] = compat_reg;
205                 /* Load upper half */
206                 err |= __get_user(compat_regt,&rf->rf_gr[regn]);
207                 regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
208                 DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n", 
209                                 regn, regs->gr[regn], compat_regt, compat_reg);
210         }
211         DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
212         /* XXX: BE WARNED FR's are 64-BIT! */
213         err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
214                 
215         /* Better safe than sorry, pass __get_user two things of
216            the same size and let gcc do the upward conversion to 
217            64-bits */           
218         err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
219         /* Load upper half */
220         err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
221         regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
222         DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
223         DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n", 
224                         &sc->sc_iaoq[0], compat_reg);
225
226         err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
227         /* Load upper half */
228         err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
229         regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
230         DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
231         DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n", 
232                         &sc->sc_iaoq[1],compat_reg);    
233         DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n", 
234                         regs->iaoq[0],regs->iaoq[1]);           
235                 
236         err |= __get_user(compat_reg, &sc->sc_iasq[0]);
237         /* Load the upper half for iasq */
238         err |= __get_user(compat_regt, &rf->rf_iasq[0]);
239         regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
240         DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
241         
242         err |= __get_user(compat_reg, &sc->sc_iasq[1]);
243         /* Load the upper half for iasq */
244         err |= __get_user(compat_regt, &rf->rf_iasq[1]);
245         regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
246         DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
247         DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n", 
248                 regs->iasq[0],regs->iasq[1]);           
249
250         err |= __get_user(compat_reg, &sc->sc_sar);
251         /* Load the upper half for sar */
252         err |= __get_user(compat_regt, &rf->rf_sar);
253         regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg; 
254         DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);  
255         DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);                
256         DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
257         
258         return err;
259 }
260
261 /*
262  * Set up the sigcontext structure for this process.
263  * This is not an easy task if the kernel is 64-bit, it will require
264  * that we examine the process personality to determine if we need to
265  * truncate for a 32-bit userspace.
266  */
267 long
268 setup_sigcontext32(struct compat_sigcontext *sc, struct compat_regfile * rf, 
269                 struct pt_regs *regs, int in_syscall)            
270 {
271         compat_int_t flags = 0;
272         long err = 0;
273         compat_uint_t compat_reg;
274         compat_uint_t compat_regb;
275         int regn;
276         
277         if (on_sig_stack((unsigned long) sc))
278                 flags |= PARISC_SC_FLAG_ONSTACK;
279         
280         if (in_syscall) {
281                 
282                 DBG(1,"setup_sigcontext32: in_syscall\n");
283                 
284                 flags |= PARISC_SC_FLAG_IN_SYSCALL;
285                 /* Truncate gr31 */
286                 compat_reg = (compat_uint_t)(regs->gr[31]);
287                 /* regs->iaoq is undefined in the syscall return path */
288                 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
289                 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
290                                 &sc->sc_iaoq[0], compat_reg);
291                 
292                 /* Store upper half */
293                 compat_reg = (compat_uint_t)(regs->gr[32] >> 32);
294                 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
295                 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
296                 
297                 
298                 compat_reg = (compat_uint_t)(regs->gr[31]+4);
299                 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
300                 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
301                                 &sc->sc_iaoq[1], compat_reg);
302                 /* Store upper half */
303                 compat_reg = (compat_uint_t)((regs->gr[32]+4) >> 32);
304                 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
305                 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
306                 
307                 /* Truncate sr3 */
308                 compat_reg = (compat_uint_t)(regs->sr[3]);
309                 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
310                 err |= __put_user(compat_reg, &sc->sc_iasq[1]);         
311                 
312                 /* Store upper half */
313                 compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
314                 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
315                 err |= __put_user(compat_reg, &rf->rf_iasq[1]);         
316                 
317                 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
318                 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);            
319                 DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",                         
320                         regs->gr[31], regs->gr[31]+4);
321                 
322         } else {
323                 
324                 compat_reg = (compat_uint_t)(regs->iaoq[0]);
325                 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
326                 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
327                                 &sc->sc_iaoq[0], compat_reg);
328                 /* Store upper half */
329                 compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
330                 err |= __put_user(compat_reg, &rf->rf_iaoq[0]); 
331                 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
332                 
333                 compat_reg = (compat_uint_t)(regs->iaoq[1]);
334                 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
335                 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
336                                 &sc->sc_iaoq[1], compat_reg);
337                 /* Store upper half */
338                 compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
339                 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
340                 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
341                 
342                 
343                 compat_reg = (compat_uint_t)(regs->iasq[0]);
344                 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
345                 DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
346                                 &sc->sc_iasq[0], compat_reg);
347                 /* Store upper half */
348                 compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
349                 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
350                 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
351                 
352                 
353                 compat_reg = (compat_uint_t)(regs->iasq[1]);
354                 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
355                 DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
356                                 &sc->sc_iasq[1], compat_reg);
357                 /* Store upper half */
358                 compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
359                 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
360                 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
361
362                 /* Print out the IAOQ for debugging */          
363                 DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n", 
364                         regs->iaoq[0], regs->iaoq[1]);
365         }
366
367         err |= __put_user(flags, &sc->sc_flags);
368         
369         DBG(1,"setup_sigcontext32: Truncating general registers.\n");
370         
371         for(regn=0; regn < 32; regn++){
372                 /* Truncate a general register */
373                 compat_reg = (compat_uint_t)(regs->gr[regn]);
374                 err |= __put_user(compat_reg, &sc->sc_gr[regn]);
375                 /* Store upper half */
376                 compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
377                 err |= __put_user(compat_regb, &rf->rf_gr[regn]);
378
379                 /* DEBUG: Write out the "upper / lower" register data */
380                 DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn, 
381                                 compat_regb, compat_reg);
382         }
383         
384         /* Copy the floating point registers (same size)
385            XXX: BE WARNED FR's are 64-BIT! */   
386         DBG(1,"setup_sigcontext32: Copying from regs to sc, "
387               "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
388                 sizeof(regs->fr), sizeof(sc->sc_fr));
389         err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
390
391         compat_reg = (compat_uint_t)(regs->sar);
392         err |= __put_user(compat_reg, &sc->sc_sar);
393         DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
394         /* Store upper half */
395         compat_reg = (compat_uint_t)(regs->sar >> 32);
396         err |= __put_user(compat_reg, &rf->rf_sar);     
397         DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
398         DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
399
400         return err;
401 }