aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/kernel/process.c2
-rw-r--r--arch/sparc/kernel/signal.c260
-rw-r--r--arch/sparc/kernel/sys_sparc.c14
3 files changed, 23 insertions, 253 deletions
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 70c0dd22491d..e7f35198ae34 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -357,8 +357,6 @@ void flush_thread(void)
357{ 357{
358 current_thread_info()->w_saved = 0; 358 current_thread_info()->w_saved = 0;
359 359
360 /* No new signal delivery by default */
361 current->thread.new_signal = 0;
362#ifndef CONFIG_SMP 360#ifndef CONFIG_SMP
363 if(last_task_used_math == current) { 361 if(last_task_used_math == current) {
364#else 362#else
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 3e849e8e3480..3c312290c3c2 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -1,5 +1,4 @@
1/* $Id: signal.c,v 1.110 2002/02/08 03:57:14 davem Exp $ 1/* linux/arch/sparc/kernel/signal.c
2 * linux/arch/sparc/kernel/signal.c
3 * 2 *
4 * Copyright (C) 1991, 1992 Linus Torvalds 3 * Copyright (C) 1991, 1992 Linus Torvalds
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -32,37 +31,7 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
32 void *fpqueue, unsigned long *fpqdepth); 31 void *fpqueue, unsigned long *fpqdepth);
33extern void fpload(unsigned long *fpregs, unsigned long *fsr); 32extern void fpload(unsigned long *fpregs, unsigned long *fsr);
34 33
35/* Signal frames: the original one (compatible with SunOS): 34struct signal_frame {
36 *
37 * Set up a signal frame... Make the stack look the way SunOS
38 * expects it to look which is basically:
39 *
40 * ---------------------------------- <-- %sp at signal time
41 * Struct sigcontext
42 * Signal address
43 * Ptr to sigcontext area above
44 * Signal code
45 * The signal number itself
46 * One register window
47 * ---------------------------------- <-- New %sp
48 */
49struct signal_sframe {
50 struct reg_window sig_window;
51 int sig_num;
52 int sig_code;
53 struct sigcontext __user *sig_scptr;
54 int sig_address;
55 struct sigcontext sig_context;
56 unsigned int extramask[_NSIG_WORDS - 1];
57};
58
59/*
60 * And the new one, intended to be used for Linux applications only
61 * (we have enough in there to work with clone).
62 * All the interesting bits are in the info field.
63 */
64
65struct new_signal_frame {
66 struct sparc_stackf ss; 35 struct sparc_stackf ss;
67 __siginfo_t info; 36 __siginfo_t info;
68 __siginfo_fpu_t __user *fpu_save; 37 __siginfo_fpu_t __user *fpu_save;
@@ -85,8 +54,7 @@ struct rt_signal_frame {
85}; 54};
86 55
87/* Align macros */ 56/* Align macros */
88#define SF_ALIGNEDSZ (((sizeof(struct signal_sframe) + 7) & (~7))) 57#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
89#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7)))
90#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) 58#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
91 59
92static int _sigpause_common(old_sigset_t set) 60static int _sigpause_common(old_sigset_t set)
@@ -141,15 +109,20 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
141 return err; 109 return err;
142} 110}
143 111
144static inline void do_new_sigreturn (struct pt_regs *regs) 112asmlinkage void do_sigreturn(struct pt_regs *regs)
145{ 113{
146 struct new_signal_frame __user *sf; 114 struct signal_frame __user *sf;
147 unsigned long up_psr, pc, npc; 115 unsigned long up_psr, pc, npc;
148 sigset_t set; 116 sigset_t set;
149 __siginfo_fpu_t __user *fpu_save; 117 __siginfo_fpu_t __user *fpu_save;
150 int err; 118 int err;
151 119
152 sf = (struct new_signal_frame __user *) regs->u_regs[UREG_FP]; 120 /* Always make any pending restarted system calls return -EINTR */
121 current_thread_info()->restart_block.fn = do_no_restart_syscall;
122
123 synchronize_user_stack();
124
125 sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
153 126
154 /* 1. Make sure we are not getting garbage from the user */ 127 /* 1. Make sure we are not getting garbage from the user */
155 if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) 128 if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
@@ -198,73 +171,6 @@ segv_and_exit:
198 force_sig(SIGSEGV, current); 171 force_sig(SIGSEGV, current);
199} 172}
200 173
201asmlinkage void do_sigreturn(struct pt_regs *regs)
202{
203 struct sigcontext __user *scptr;
204 unsigned long pc, npc, psr;
205 sigset_t set;
206 int err;
207
208 /* Always make any pending restarted system calls return -EINTR */
209 current_thread_info()->restart_block.fn = do_no_restart_syscall;
210
211 synchronize_user_stack();
212
213 if (current->thread.new_signal) {
214 do_new_sigreturn(regs);
215 return;
216 }
217
218 scptr = (struct sigcontext __user *) regs->u_regs[UREG_I0];
219
220 /* Check sanity of the user arg. */
221 if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext)) ||
222 (((unsigned long) scptr) & 3))
223 goto segv_and_exit;
224
225 err = __get_user(pc, &scptr->sigc_pc);
226 err |= __get_user(npc, &scptr->sigc_npc);
227
228 if ((pc | npc) & 3)
229 goto segv_and_exit;
230
231 /* This is pretty much atomic, no amount locking would prevent
232 * the races which exist anyways.
233 */
234 err |= __get_user(set.sig[0], &scptr->sigc_mask);
235 /* Note that scptr + 1 points to extramask */
236 err |= __copy_from_user(&set.sig[1], scptr + 1,
237 (_NSIG_WORDS - 1) * sizeof(unsigned int));
238
239 if (err)
240 goto segv_and_exit;
241
242 sigdelsetmask(&set, ~_BLOCKABLE);
243 spin_lock_irq(&current->sighand->siglock);
244 current->blocked = set;
245 recalc_sigpending();
246 spin_unlock_irq(&current->sighand->siglock);
247
248 regs->pc = pc;
249 regs->npc = npc;
250
251 err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp);
252 err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0);
253 err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1);
254
255 /* User can only change condition codes in %psr. */
256 err |= __get_user(psr, &scptr->sigc_psr);
257 if (err)
258 goto segv_and_exit;
259
260 regs->psr &= ~(PSR_ICC);
261 regs->psr |= (psr & PSR_ICC);
262 return;
263
264segv_and_exit:
265 force_sig(SIGSEGV, current);
266}
267
268asmlinkage void do_rt_sigreturn(struct pt_regs *regs) 174asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
269{ 175{
270 struct rt_signal_frame __user *sf; 176 struct rt_signal_frame __user *sf;
@@ -351,128 +257,6 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re
351 return (void __user *)(sp - framesize); 257 return (void __user *)(sp - framesize);
352} 258}
353 259
354static inline void
355setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info)
356{
357 struct signal_sframe __user *sframep;
358 struct sigcontext __user *sc;
359 int window = 0, err;
360 unsigned long pc = regs->pc;
361 unsigned long npc = regs->npc;
362 struct thread_info *tp = current_thread_info();
363 void __user *sig_address;
364 int sig_code;
365
366 synchronize_user_stack();
367 sframep = (struct signal_sframe __user *)
368 get_sigframe(sa, regs, SF_ALIGNEDSZ);
369 if (invalid_frame_pointer(sframep, sizeof(*sframep))){
370 /* Don't change signal code and address, so that
371 * post mortem debuggers can have a look.
372 */
373 goto sigill_and_return;
374 }
375
376 sc = &sframep->sig_context;
377
378 /* We've already made sure frame pointer isn't in kernel space... */
379 err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK),
380 &sc->sigc_onstack);
381 err |= __put_user(oldset->sig[0], &sc->sigc_mask);
382 err |= __copy_to_user(sframep->extramask, &oldset->sig[1],
383 (_NSIG_WORDS - 1) * sizeof(unsigned int));
384 err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp);
385 err |= __put_user(pc, &sc->sigc_pc);
386 err |= __put_user(npc, &sc->sigc_npc);
387 err |= __put_user(regs->psr, &sc->sigc_psr);
388 err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
389 err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
390 err |= __put_user(tp->w_saved, &sc->sigc_oswins);
391 if (tp->w_saved)
392 for (window = 0; window < tp->w_saved; window++) {
393 put_user((char *)tp->rwbuf_stkptrs[window],
394 &sc->sigc_spbuf[window]);
395 err |= __copy_to_user(&sc->sigc_wbuf[window],
396 &tp->reg_window[window],
397 sizeof(struct reg_window));
398 }
399 else
400 err |= __copy_to_user(sframep, (char *) regs->u_regs[UREG_FP],
401 sizeof(struct reg_window));
402
403 tp->w_saved = 0; /* So process is allowed to execute. */
404
405 err |= __put_user(signr, &sframep->sig_num);
406 sig_address = NULL;
407 sig_code = 0;
408 if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) {
409 sig_address = info->si_addr;
410 switch (signr) {
411 case SIGSEGV:
412 switch (info->si_code) {
413 case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break;
414 default: sig_code = SUBSIG_PROTECTION; break;
415 }
416 break;
417 case SIGILL:
418 switch (info->si_code) {
419 case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break;
420 case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break;
421 case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP(info->si_trapno); break;
422 default: sig_code = SUBSIG_STACK; break;
423 }
424 break;
425 case SIGFPE:
426 switch (info->si_code) {
427 case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break;
428 case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break;
429 case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break;
430 case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break;
431 case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break;
432 case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break;
433 case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break;
434 default: sig_code = SUBSIG_FPERROR; break;
435 }
436 break;
437 case SIGBUS:
438 switch (info->si_code) {
439 case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break;
440 case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break;
441 default: sig_code = SUBSIG_BUSTIMEOUT; break;
442 }
443 break;
444 case SIGEMT:
445 switch (info->si_code) {
446 case EMT_TAGOVF: sig_code = SUBSIG_TAG; break;
447 }
448 break;
449 case SIGSYS:
450 if (info->si_code == (__SI_FAULT|0x100)) {
451 sig_code = info->si_trapno;
452 break;
453 }
454 default:
455 sig_address = NULL;
456 }
457 }
458 err |= __put_user((unsigned long)sig_address, &sframep->sig_address);
459 err |= __put_user(sig_code, &sframep->sig_code);
460 err |= __put_user(sc, &sframep->sig_scptr);
461 if (err)
462 goto sigsegv;
463
464 regs->u_regs[UREG_FP] = (unsigned long) sframep;
465 regs->pc = (unsigned long) sa->sa_handler;
466 regs->npc = (regs->pc + 4);
467 return;
468
469sigill_and_return:
470 do_exit(SIGILL);
471sigsegv:
472 force_sigsegv(signr, current);
473}
474
475
476static inline int 260static inline int
477save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) 261save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
478{ 262{
@@ -508,21 +292,20 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
508 return err; 292 return err;
509} 293}
510 294
511static inline void 295static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
512new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, 296 int signo, sigset_t *oldset)
513 int signo, sigset_t *oldset)
514{ 297{
515 struct new_signal_frame __user *sf; 298 struct signal_frame __user *sf;
516 int sigframe_size, err; 299 int sigframe_size, err;
517 300
518 /* 1. Make sure everything is clean */ 301 /* 1. Make sure everything is clean */
519 synchronize_user_stack(); 302 synchronize_user_stack();
520 303
521 sigframe_size = NF_ALIGNEDSZ; 304 sigframe_size = SF_ALIGNEDSZ;
522 if (!used_math()) 305 if (!used_math())
523 sigframe_size -= sizeof(__siginfo_fpu_t); 306 sigframe_size -= sizeof(__siginfo_fpu_t);
524 307
525 sf = (struct new_signal_frame __user *) 308 sf = (struct signal_frame __user *)
526 get_sigframe(&ka->sa, regs, sigframe_size); 309 get_sigframe(&ka->sa, regs, sigframe_size);
527 310
528 if (invalid_frame_pointer(sf, sigframe_size)) 311 if (invalid_frame_pointer(sf, sigframe_size))
@@ -586,9 +369,8 @@ sigsegv:
586 force_sigsegv(signo, current); 369 force_sigsegv(signo, current);
587} 370}
588 371
589static inline void 372static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
590new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, 373 int signo, sigset_t *oldset, siginfo_t *info)
591 int signo, sigset_t *oldset, siginfo_t *info)
592{ 374{
593 struct rt_signal_frame __user *sf; 375 struct rt_signal_frame __user *sf;
594 int sigframe_size; 376 int sigframe_size;
@@ -674,11 +456,9 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
674 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) 456 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
675{ 457{
676 if (ka->sa.sa_flags & SA_SIGINFO) 458 if (ka->sa.sa_flags & SA_SIGINFO)
677 new_setup_rt_frame(ka, regs, signr, oldset, info); 459 setup_rt_frame(ka, regs, signr, oldset, info);
678 else if (current->thread.new_signal)
679 new_setup_frame(ka, regs, signr, oldset);
680 else 460 else
681 setup_frame(&ka->sa, regs, signr, oldset, info); 461 setup_frame(ka, regs, signr, oldset);
682 462
683 spin_lock_irq(&current->sighand->siglock); 463 spin_lock_irq(&current->sighand->siglock);
684 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 464 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index 42bf09db9a81..f188b5dc9fd0 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -1,5 +1,4 @@
1/* $Id: sys_sparc.c,v 1.70 2001/04/14 01:12:02 davem Exp $ 1/* linux/arch/sparc/kernel/sys_sparc.c
2 * linux/arch/sparc/kernel/sys_sparc.c
3 * 2 *
4 * This file contains various random system calls that 3 * This file contains various random system calls that
5 * have a non-standard calling sequence on the Linux/sparc 4 * have a non-standard calling sequence on the Linux/sparc
@@ -395,10 +394,8 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act,
395 struct k_sigaction new_ka, old_ka; 394 struct k_sigaction new_ka, old_ka;
396 int ret; 395 int ret;
397 396
398 if (sig < 0) { 397 WARN_ON_ONCE(sig >= 0);
399 current->thread.new_signal = 1; 398 sig = -sig;
400 sig = -sig;
401 }
402 399
403 if (act) { 400 if (act) {
404 unsigned long mask; 401 unsigned long mask;
@@ -446,11 +443,6 @@ sys_rt_sigaction(int sig,
446 if (sigsetsize != sizeof(sigset_t)) 443 if (sigsetsize != sizeof(sigset_t))
447 return -EINVAL; 444 return -EINVAL;
448 445
449 /* All tasks which use RT signals (effectively) use
450 * new style signals.
451 */
452 current->thread.new_signal = 1;
453
454 if (act) { 446 if (act) {
455 new_ka.ka_restorer = restorer; 447 new_ka.ka_restorer = restorer;
456 if (copy_from_user(&new_ka.sa, act, sizeof(*act))) 448 if (copy_from_user(&new_ka.sa, act, sizeof(*act)))