aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-04-27 05:26:36 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-27 05:26:36 -0400
commit5526b7e4513c66bc1c91f661dcd518d5199f8934 (patch)
tree658de7d323dc5aa5c13d7c9545820b5911d758dc /arch/sparc/kernel
parent7cf069955f2f0b95fed6a8b1a61ef598a3df0f4e (diff)
sparc: Remove old style signal frame support.
Back around the same time we were bootstrapping the first 32-bit sparc Linux kernel with a SunOS userland, we made the signal frame match that of SunOS. By the time we even started putting together a native Linux userland for 32-bit Sparc we realized this layout wasn't sufficient for Linux's needs. Therefore we changed the layout, yet kept support for the old style signal frame layout in there. The detection mechanism is that we had sys_sigaction() start passing in a negative signal number to indicate "new style signal frames please". Anyways, no binaries exist in the world that use the old stuff. In fact, I bet Jakub Jelinek and myself are the only two people who ever had such binaries to be honest. So let's get rid of this stuff. I added an assertion using WARN_ON_ONCE() that makes sure 32-bit applications are passing in that negative signal number still. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel')
-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)))