Linux Audio

Check our new training course

Loading...
v4.6
 
  1/*    Signal support for 32-bit kernel builds
  2 *
  3 *    Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
  4 *    Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org>
  5 *
  6 *    Code was mostly borrowed from kernel/signal.c.
  7 *    See kernel/signal.c for additional Copyrights.
  8 *
  9 *
 10 *    This program is free software; you can redistribute it and/or modify
 11 *    it under the terms of the GNU General Public License as published by
 12 *    the Free Software Foundation; either version 2 of the License, or
 13 *    (at your option) any later version.
 14 *
 15 *    This program is distributed in the hope that it will be useful,
 16 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18 *    GNU General Public License for more details.
 19 *
 20 *    You should have received a copy of the GNU General Public License
 21 *    along with this program; if not, write to the Free Software
 22 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23 */
 24
 25#include <linux/compat.h>
 26#include <linux/module.h>
 27#include <linux/unistd.h>
 28#include <linux/init.h>
 29#include <linux/sched.h>
 30#include <linux/syscalls.h>
 31#include <linux/types.h>
 32#include <linux/errno.h>
 33
 34#include <asm/uaccess.h>
 35
 36#include "signal32.h"
 37
 38#define DEBUG_COMPAT_SIG 0 
 39#define DEBUG_COMPAT_SIG_LEVEL 2
 40
 41#if DEBUG_COMPAT_SIG
 42#define DBG(LEVEL, ...) \
 43	((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
 44	? printk(__VA_ARGS__) : (void) 0)
 45#else
 46#define DBG(LEVEL, ...)
 47#endif
 48
 49inline void
 50sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
 51{
 52	s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
 53}
 54
 55inline void
 56sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
 57{
 58	s32->sig[0] = s64->sig[0] & 0xffffffffUL;
 59	s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
 60}
 61
 62long
 63restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
 64		struct pt_regs *regs)
 65{
 66	long err = 0;
 67	compat_uint_t compat_reg;
 68	compat_uint_t compat_regt;
 69	int regn;
 70	
 71	/* When loading 32-bit values into 64-bit registers make
 72	   sure to clear the upper 32-bits */
 73	DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
 74	DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
 75	DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
 76	for(regn=0; regn < 32; regn++){
 77		err |= __get_user(compat_reg,&sc->sc_gr[regn]);
 78		regs->gr[regn] = compat_reg;
 79		/* Load upper half */
 80		err |= __get_user(compat_regt,&rf->rf_gr[regn]);
 81		regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
 82		DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n", 
 83				regn, regs->gr[regn], compat_regt, compat_reg);
 84	}
 85	DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
 86	/* XXX: BE WARNED FR's are 64-BIT! */
 87	err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
 88		
 89	/* Better safe than sorry, pass __get_user two things of
 90	   the same size and let gcc do the upward conversion to 
 91	   64-bits */		
 92	err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
 93	/* Load upper half */
 94	err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
 95	regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
 96	DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
 97	DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n", 
 98			&sc->sc_iaoq[0], compat_reg);
 99
100	err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
101	/* Load upper half */
102	err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
103	regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
104	DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
105	DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n", 
106			&sc->sc_iaoq[1],compat_reg);	
107	DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n", 
108			regs->iaoq[0],regs->iaoq[1]);		
109		
110	err |= __get_user(compat_reg, &sc->sc_iasq[0]);
111	/* Load the upper half for iasq */
112	err |= __get_user(compat_regt, &rf->rf_iasq[0]);
113	regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
114	DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
115	
116	err |= __get_user(compat_reg, &sc->sc_iasq[1]);
117	/* Load the upper half for iasq */
118	err |= __get_user(compat_regt, &rf->rf_iasq[1]);
119	regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
120	DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
121	DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n", 
122		regs->iasq[0],regs->iasq[1]);		
123
124	err |= __get_user(compat_reg, &sc->sc_sar);
125	/* Load the upper half for sar */
126	err |= __get_user(compat_regt, &rf->rf_sar);
127	regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;	
128	DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);	
129	DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);		
130	DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
131	
132	return err;
133}
134
135/*
136 * Set up the sigcontext structure for this process.
137 * This is not an easy task if the kernel is 64-bit, it will require
138 * that we examine the process personality to determine if we need to
139 * truncate for a 32-bit userspace.
140 */
141long
142setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf, 
143		struct pt_regs *regs, int in_syscall)		 
144{
145	compat_int_t flags = 0;
146	long err = 0;
147	compat_uint_t compat_reg;
148	compat_uint_t compat_regb;
149	int regn;
150	
151	if (on_sig_stack((unsigned long) sc))
152		flags |= PARISC_SC_FLAG_ONSTACK;
153	
154	if (in_syscall) {
155		
156		DBG(1,"setup_sigcontext32: in_syscall\n");
157		
158		flags |= PARISC_SC_FLAG_IN_SYSCALL;
159		/* Truncate gr31 */
160		compat_reg = (compat_uint_t)(regs->gr[31]);
161		/* regs->iaoq is undefined in the syscall return path */
162		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
163		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
164				&sc->sc_iaoq[0], compat_reg);
165		
166		/* Store upper half */
167		compat_reg = (compat_uint_t)(regs->gr[31] >> 32);
168		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
169		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
170		
171		
172		compat_reg = (compat_uint_t)(regs->gr[31]+4);
173		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
174		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
175				&sc->sc_iaoq[1], compat_reg);
176		/* Store upper half */
177		compat_reg = (compat_uint_t)((regs->gr[31]+4) >> 32);
178		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
179		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
180		
181		/* Truncate sr3 */
182		compat_reg = (compat_uint_t)(regs->sr[3]);
183		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
184		err |= __put_user(compat_reg, &sc->sc_iasq[1]);		
185		
186		/* Store upper half */
187		compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
188		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
189		err |= __put_user(compat_reg, &rf->rf_iasq[1]);		
190		
191		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
192		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);		
193		DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",				
194			regs->gr[31], regs->gr[31]+4);
195		
196	} else {
197		
198		compat_reg = (compat_uint_t)(regs->iaoq[0]);
199		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
200		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
201				&sc->sc_iaoq[0], compat_reg);
202		/* Store upper half */
203		compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
204		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);	
205		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
206		
207		compat_reg = (compat_uint_t)(regs->iaoq[1]);
208		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
209		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
210				&sc->sc_iaoq[1], compat_reg);
211		/* Store upper half */
212		compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
213		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
214		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
215		
216		
217		compat_reg = (compat_uint_t)(regs->iasq[0]);
218		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
219		DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
220				&sc->sc_iasq[0], compat_reg);
221		/* Store upper half */
222		compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
223		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
224		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
225		
226		
227		compat_reg = (compat_uint_t)(regs->iasq[1]);
228		err |= __put_user(compat_reg, &sc->sc_iasq[1]);
229		DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
230				&sc->sc_iasq[1], compat_reg);
231		/* Store upper half */
232		compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
233		err |= __put_user(compat_reg, &rf->rf_iasq[1]);
234		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
235
236		/* Print out the IAOQ for debugging */		
237		DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n", 
238			regs->iaoq[0], regs->iaoq[1]);
239	}
240
241	err |= __put_user(flags, &sc->sc_flags);
242	
243	DBG(1,"setup_sigcontext32: Truncating general registers.\n");
244	
245	for(regn=0; regn < 32; regn++){
246		/* Truncate a general register */
247		compat_reg = (compat_uint_t)(regs->gr[regn]);
248		err |= __put_user(compat_reg, &sc->sc_gr[regn]);
249		/* Store upper half */
250		compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
251		err |= __put_user(compat_regb, &rf->rf_gr[regn]);
252
253		/* DEBUG: Write out the "upper / lower" register data */
254		DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn, 
255				compat_regb, compat_reg);
256	}
257	
258	/* Copy the floating point registers (same size)
259	   XXX: BE WARNED FR's are 64-BIT! */	
260	DBG(1,"setup_sigcontext32: Copying from regs to sc, "
261	      "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
262		sizeof(regs->fr), sizeof(sc->sc_fr));
263	err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
264
265	compat_reg = (compat_uint_t)(regs->sar);
266	err |= __put_user(compat_reg, &sc->sc_sar);
267	DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
268	/* Store upper half */
269	compat_reg = (compat_uint_t)(regs->sar >> 32);
270	err |= __put_user(compat_reg, &rf->rf_sar);	
271	DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
272	DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
273
274	return err;
275}
276
277int
278copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
279{
280	compat_uptr_t addr;
281	int err;
282
283	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
284		return -EFAULT;
285
286	err = __get_user(to->si_signo, &from->si_signo);
287	err |= __get_user(to->si_errno, &from->si_errno);
288	err |= __get_user(to->si_code, &from->si_code);
289
290	if (to->si_code < 0)
291		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
292	else {
293		switch (to->si_code >> 16) {
294		      case __SI_CHLD >> 16:
295			err |= __get_user(to->si_utime, &from->si_utime);
296			err |= __get_user(to->si_stime, &from->si_stime);
297			err |= __get_user(to->si_status, &from->si_status);
298		      default:
299			err |= __get_user(to->si_pid, &from->si_pid);
300			err |= __get_user(to->si_uid, &from->si_uid);
301			break;
302		      case __SI_FAULT >> 16:
303			err |= __get_user(addr, &from->si_addr);
304			to->si_addr = compat_ptr(addr);
305			break;
306		      case __SI_POLL >> 16:
307			err |= __get_user(to->si_band, &from->si_band);
308			err |= __get_user(to->si_fd, &from->si_fd);
309			break;
310		      case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
311		      case __SI_MESGQ >> 16:
312			err |= __get_user(to->si_pid, &from->si_pid);
313			err |= __get_user(to->si_uid, &from->si_uid);
314			err |= __get_user(to->si_int, &from->si_int);
315			break;
316		}
317	}
318	return err;
319}
320
321int
322copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from)
323{
324	compat_uptr_t addr;
325	compat_int_t val;
326	int err;
327
328	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
329		return -EFAULT;
330
331	/* If you change siginfo_t structure, please be sure
332	   this code is fixed accordingly.
333	   It should never copy any pad contained in the structure
334	   to avoid security leaks, but must copy the generic
335	   3 ints plus the relevant union member.
336	   This routine must convert siginfo from 64bit to 32bit as well
337	   at the same time.  */
338	err = __put_user(from->si_signo, &to->si_signo);
339	err |= __put_user(from->si_errno, &to->si_errno);
340	err |= __put_user((short)from->si_code, &to->si_code);
341	if (from->si_code < 0)
342		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
343	else {
344		switch (from->si_code >> 16) {
345		case __SI_CHLD >> 16:
346			err |= __put_user(from->si_utime, &to->si_utime);
347			err |= __put_user(from->si_stime, &to->si_stime);
348			err |= __put_user(from->si_status, &to->si_status);
349		default:
350			err |= __put_user(from->si_pid, &to->si_pid);
351			err |= __put_user(from->si_uid, &to->si_uid);
352			break;
353		case __SI_FAULT >> 16:
354			addr = ptr_to_compat(from->si_addr);
355			err |= __put_user(addr, &to->si_addr);
356			break;
357		case __SI_POLL >> 16:
358			err |= __put_user(from->si_band, &to->si_band);
359			err |= __put_user(from->si_fd, &to->si_fd);
360			break;
361		case __SI_TIMER >> 16:
362			err |= __put_user(from->si_tid, &to->si_tid);
363			err |= __put_user(from->si_overrun, &to->si_overrun);
364			val = (compat_int_t)from->si_int;
365			err |= __put_user(val, &to->si_int);
366			break;
367		case __SI_RT >> 16:	/* Not generated by the kernel as of now.  */
368		case __SI_MESGQ >> 16:
369			err |= __put_user(from->si_uid, &to->si_uid);
370			err |= __put_user(from->si_pid, &to->si_pid);
371			val = (compat_int_t)from->si_int;
372			err |= __put_user(val, &to->si_int);
373			break;
374		case __SI_SYS >> 16:
375			err |= __put_user(ptr_to_compat(from->si_call_addr), &to->si_call_addr);
376			err |= __put_user(from->si_syscall, &to->si_syscall);
377			err |= __put_user(from->si_arch, &to->si_arch);
378			break;
379		}
380	}
381	return err;
382}
v6.2
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*    Signal support for 32-bit kernel builds
  3 *
  4 *    Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
  5 *    Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org>
  6 *
  7 *    Code was mostly borrowed from kernel/signal.c.
  8 *    See kernel/signal.c for additional Copyrights.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  9 */
 10
 11#include <linux/compat.h>
 12#include <linux/module.h>
 13#include <linux/unistd.h>
 14#include <linux/init.h>
 15#include <linux/sched.h>
 16#include <linux/syscalls.h>
 17#include <linux/types.h>
 18#include <linux/errno.h>
 19
 20#include <linux/uaccess.h>
 21
 22#include "signal32.h"
 23
 24#define DEBUG_COMPAT_SIG 0 
 25#define DEBUG_COMPAT_SIG_LEVEL 2
 26
 27#if DEBUG_COMPAT_SIG
 28#define DBG(LEVEL, ...) \
 29	((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
 30	? printk(__VA_ARGS__) : (void) 0)
 31#else
 32#define DBG(LEVEL, ...)
 33#endif
 34
 
 
 
 
 
 
 
 
 
 
 
 
 
 35long
 36restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
 37		struct pt_regs *regs)
 38{
 39	long err = 0;
 40	compat_uint_t compat_reg;
 41	compat_uint_t compat_regt;
 42	int regn;
 43	
 44	/* When loading 32-bit values into 64-bit registers make
 45	   sure to clear the upper 32-bits */
 46	DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
 47	DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
 48	DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
 49	for(regn=0; regn < 32; regn++){
 50		err |= __get_user(compat_reg,&sc->sc_gr[regn]);
 51		regs->gr[regn] = compat_reg;
 52		/* Load upper half */
 53		err |= __get_user(compat_regt,&rf->rf_gr[regn]);
 54		regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
 55		DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n", 
 56				regn, regs->gr[regn], compat_regt, compat_reg);
 57	}
 58	DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
 59	/* XXX: BE WARNED FR's are 64-BIT! */
 60	err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
 61		
 62	/* Better safe than sorry, pass __get_user two things of
 63	   the same size and let gcc do the upward conversion to 
 64	   64-bits */		
 65	err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
 66	/* Load upper half */
 67	err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
 68	regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
 69	DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
 70	DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n", 
 71			&sc->sc_iaoq[0], compat_reg);
 72
 73	err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
 74	/* Load upper half */
 75	err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
 76	regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
 77	DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
 78	DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n", 
 79			&sc->sc_iaoq[1],compat_reg);	
 80	DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n", 
 81			regs->iaoq[0],regs->iaoq[1]);		
 82		
 83	err |= __get_user(compat_reg, &sc->sc_iasq[0]);
 84	/* Load the upper half for iasq */
 85	err |= __get_user(compat_regt, &rf->rf_iasq[0]);
 86	regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
 87	DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
 88	
 89	err |= __get_user(compat_reg, &sc->sc_iasq[1]);
 90	/* Load the upper half for iasq */
 91	err |= __get_user(compat_regt, &rf->rf_iasq[1]);
 92	regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
 93	DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
 94	DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n", 
 95		regs->iasq[0],regs->iasq[1]);		
 96
 97	err |= __get_user(compat_reg, &sc->sc_sar);
 98	/* Load the upper half for sar */
 99	err |= __get_user(compat_regt, &rf->rf_sar);
100	regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;	
101	DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);	
102	DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);		
103	DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
104	
105	return err;
106}
107
108/*
109 * Set up the sigcontext structure for this process.
110 * This is not an easy task if the kernel is 64-bit, it will require
111 * that we examine the process personality to determine if we need to
112 * truncate for a 32-bit userspace.
113 */
114long
115setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf, 
116		struct pt_regs *regs, int in_syscall)		 
117{
118	compat_int_t flags = 0;
119	long err = 0;
120	compat_uint_t compat_reg;
121	compat_uint_t compat_regb;
122	int regn;
123	
124	if (on_sig_stack((unsigned long) sc))
125		flags |= PARISC_SC_FLAG_ONSTACK;
126	
127	if (in_syscall) {
128		
129		DBG(1,"setup_sigcontext32: in_syscall\n");
130		
131		flags |= PARISC_SC_FLAG_IN_SYSCALL;
132		/* Truncate gr31 */
133		compat_reg = (compat_uint_t)(regs->gr[31]);
134		/* regs->iaoq is undefined in the syscall return path */
135		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
136		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
137				&sc->sc_iaoq[0], compat_reg);
138		
139		/* Store upper half */
140		compat_reg = (compat_uint_t)(regs->gr[31] >> 32);
141		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
142		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
143		
144		
145		compat_reg = (compat_uint_t)(regs->gr[31]+4);
146		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
147		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
148				&sc->sc_iaoq[1], compat_reg);
149		/* Store upper half */
150		compat_reg = (compat_uint_t)((regs->gr[31]+4) >> 32);
151		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
152		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
153		
154		/* Truncate sr3 */
155		compat_reg = (compat_uint_t)(regs->sr[3]);
156		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
157		err |= __put_user(compat_reg, &sc->sc_iasq[1]);		
158		
159		/* Store upper half */
160		compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
161		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
162		err |= __put_user(compat_reg, &rf->rf_iasq[1]);		
163		
164		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
165		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);		
166		DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",				
167			regs->gr[31], regs->gr[31]+4);
168		
169	} else {
170		
171		compat_reg = (compat_uint_t)(regs->iaoq[0]);
172		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
173		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
174				&sc->sc_iaoq[0], compat_reg);
175		/* Store upper half */
176		compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
177		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);	
178		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
179		
180		compat_reg = (compat_uint_t)(regs->iaoq[1]);
181		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
182		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
183				&sc->sc_iaoq[1], compat_reg);
184		/* Store upper half */
185		compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
186		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
187		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
188		
189		
190		compat_reg = (compat_uint_t)(regs->iasq[0]);
191		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
192		DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
193				&sc->sc_iasq[0], compat_reg);
194		/* Store upper half */
195		compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
196		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
197		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
198		
199		
200		compat_reg = (compat_uint_t)(regs->iasq[1]);
201		err |= __put_user(compat_reg, &sc->sc_iasq[1]);
202		DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
203				&sc->sc_iasq[1], compat_reg);
204		/* Store upper half */
205		compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
206		err |= __put_user(compat_reg, &rf->rf_iasq[1]);
207		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
208
209		/* Print out the IAOQ for debugging */		
210		DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n", 
211			regs->iaoq[0], regs->iaoq[1]);
212	}
213
214	err |= __put_user(flags, &sc->sc_flags);
215	
216	DBG(1,"setup_sigcontext32: Truncating general registers.\n");
217	
218	for(regn=0; regn < 32; regn++){
219		/* Truncate a general register */
220		compat_reg = (compat_uint_t)(regs->gr[regn]);
221		err |= __put_user(compat_reg, &sc->sc_gr[regn]);
222		/* Store upper half */
223		compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
224		err |= __put_user(compat_regb, &rf->rf_gr[regn]);
225
226		/* DEBUG: Write out the "upper / lower" register data */
227		DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn, 
228				compat_regb, compat_reg);
229	}
230	
231	/* Copy the floating point registers (same size)
232	   XXX: BE WARNED FR's are 64-BIT! */	
233	DBG(1,"setup_sigcontext32: Copying from regs to sc, "
234	      "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
235		sizeof(regs->fr), sizeof(sc->sc_fr));
236	err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
237
238	compat_reg = (compat_uint_t)(regs->sar);
239	err |= __put_user(compat_reg, &sc->sc_sar);
240	DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
241	/* Store upper half */
242	compat_reg = (compat_uint_t)(regs->sar >> 32);
243	err |= __put_user(compat_reg, &rf->rf_sar);	
244	DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
245	DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247	return err;
248}