aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/process.c6
-rw-r--r--arch/sparc64/kernel/signal32.c272
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c11
3 files changed, 21 insertions, 268 deletions
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index acf8c5250aa9..500ac6d483a0 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -1,5 +1,4 @@
1/* $Id: process.c,v 1.131 2002/02/09 19:49:30 davem Exp $ 1/* arch/sparc64/kernel/process.c
2 * arch/sparc64/kernel/process.c
3 * 2 *
4 * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) 3 * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) 4 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
@@ -368,9 +367,6 @@ void flush_thread(void)
368 367
369 if (get_thread_current_ds() != ASI_AIUS) 368 if (get_thread_current_ds() != ASI_AIUS)
370 set_fs(USER_DS); 369 set_fs(USER_DS);
371
372 /* Init new signal delivery disposition. */
373 clear_thread_flag(TIF_NEWSIGNALS);
374} 370}
375 371
376/* It's a bit more tricky when 64-bit tasks are involved... */ 372/* It's a bit more tricky when 64-bit tasks are involved... */
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 43cdec64d9c9..91f8d0826db1 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -1,5 +1,4 @@
1/* $Id: signal32.c,v 1.74 2002/02/09 19:49:30 davem Exp $ 1/* arch/sparc64/kernel/signal32.c
2 * arch/sparc64/kernel/signal32.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)
@@ -31,30 +30,6 @@
31 30
32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 31#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
33 32
34/* Signal frames: the original one (compatible with SunOS):
35 *
36 * Set up a signal frame... Make the stack look the way SunOS
37 * expects it to look which is basically:
38 *
39 * ---------------------------------- <-- %sp at signal time
40 * Struct sigcontext
41 * Signal address
42 * Ptr to sigcontext area above
43 * Signal code
44 * The signal number itself
45 * One register window
46 * ---------------------------------- <-- New %sp
47 */
48struct signal_sframe32 {
49 struct reg_window32 sig_window;
50 int sig_num;
51 int sig_code;
52 /* struct sigcontext32 * */ u32 sig_scptr;
53 int sig_address;
54 struct sigcontext32 sig_context;
55 unsigned int extramask[_COMPAT_NSIG_WORDS - 1];
56};
57
58/* This magic should be in g_upper[0] for all upper parts 33/* This magic should be in g_upper[0] for all upper parts
59 * to be valid. 34 * to be valid.
60 */ 35 */
@@ -65,12 +40,7 @@ typedef struct {
65 unsigned int asi; 40 unsigned int asi;
66} siginfo_extra_v8plus_t; 41} siginfo_extra_v8plus_t;
67 42
68/* 43struct signal_frame32 {
69 * And the new one, intended to be used for Linux applications only
70 * (we have enough in there to work with clone).
71 * All the interesting bits are in the info field.
72 */
73struct new_signal_frame32 {
74 struct sparc_stackf32 ss; 44 struct sparc_stackf32 ss;
75 __siginfo32_t info; 45 __siginfo32_t info;
76 /* __siginfo_fpu32_t * */ u32 fpu_save; 46 /* __siginfo_fpu32_t * */ u32 fpu_save;
@@ -149,8 +119,7 @@ struct rt_signal_frame32 {
149}; 119};
150 120
151/* Align macros */ 121/* Align macros */
152#define SF_ALIGNEDSZ (((sizeof(struct signal_sframe32) + 7) & (~7))) 122#define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 7) & (~7)))
153#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7)))
154#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7))) 123#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
155 124
156int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) 125int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
@@ -241,17 +210,22 @@ static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu
241 return err; 210 return err;
242} 211}
243 212
244void do_new_sigreturn32(struct pt_regs *regs) 213void do_sigreturn32(struct pt_regs *regs)
245{ 214{
246 struct new_signal_frame32 __user *sf; 215 struct signal_frame32 __user *sf;
247 unsigned int psr; 216 unsigned int psr;
248 unsigned pc, npc, fpu_save; 217 unsigned pc, npc, fpu_save;
249 sigset_t set; 218 sigset_t set;
250 unsigned seta[_COMPAT_NSIG_WORDS]; 219 unsigned seta[_COMPAT_NSIG_WORDS];
251 int err, i; 220 int err, i;
252 221
222 /* Always make any pending restarted system calls return -EINTR */
223 current_thread_info()->restart_block.fn = do_no_restart_syscall;
224
225 synchronize_user_stack();
226
253 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; 227 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
254 sf = (struct new_signal_frame32 __user *) regs->u_regs[UREG_FP]; 228 sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
255 229
256 /* 1. Make sure we are not getting garbage from the user */ 230 /* 1. Make sure we are not getting garbage from the user */
257 if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || 231 if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
@@ -319,76 +293,6 @@ segv:
319 force_sig(SIGSEGV, current); 293 force_sig(SIGSEGV, current);
320} 294}
321 295
322asmlinkage void do_sigreturn32(struct pt_regs *regs)
323{
324 struct sigcontext32 __user *scptr;
325 unsigned int pc, npc, psr;
326 sigset_t set;
327 unsigned int seta[_COMPAT_NSIG_WORDS];
328 int err;
329
330 /* Always make any pending restarted system calls return -EINTR */
331 current_thread_info()->restart_block.fn = do_no_restart_syscall;
332
333 synchronize_user_stack();
334 if (test_thread_flag(TIF_NEWSIGNALS)) {
335 do_new_sigreturn32(regs);
336 return;
337 }
338
339 scptr = (struct sigcontext32 __user *)
340 (regs->u_regs[UREG_I0] & 0x00000000ffffffffUL);
341 /* Check sanity of the user arg. */
342 if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
343 (((unsigned long) scptr) & 3))
344 goto segv;
345
346 err = __get_user(pc, &scptr->sigc_pc);
347 err |= __get_user(npc, &scptr->sigc_npc);
348
349 if ((pc | npc) & 3)
350 goto segv; /* Nice try. */
351
352 err |= __get_user(seta[0], &scptr->sigc_mask);
353 /* Note that scptr + 1 points to extramask */
354 err |= copy_from_user(seta+1, scptr + 1,
355 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
356 if (err)
357 goto segv;
358 switch (_NSIG_WORDS) {
359 case 4: set.sig[3] = seta[6] + (((long)seta[7]) << 32);
360 case 3: set.sig[2] = seta[4] + (((long)seta[5]) << 32);
361 case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32);
362 case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
363 }
364 sigdelsetmask(&set, ~_BLOCKABLE);
365 spin_lock_irq(&current->sighand->siglock);
366 current->blocked = set;
367 recalc_sigpending();
368 spin_unlock_irq(&current->sighand->siglock);
369
370 if (test_thread_flag(TIF_32BIT)) {
371 pc &= 0xffffffff;
372 npc &= 0xffffffff;
373 }
374 regs->tpc = pc;
375 regs->tnpc = npc;
376 err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp);
377 err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0);
378 err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1);
379
380 /* User can only change condition codes in %tstate. */
381 err |= __get_user(psr, &scptr->sigc_psr);
382 if (err)
383 goto segv;
384 regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
385 regs->tstate |= psr_to_tstate_icc(psr);
386 return;
387
388segv:
389 force_sig(SIGSEGV, current);
390}
391
392asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) 296asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
393{ 297{
394 struct rt_signal_frame32 __user *sf; 298 struct rt_signal_frame32 __user *sf;
@@ -504,145 +408,6 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
504 return (void __user *)(sp - framesize); 408 return (void __user *)(sp - framesize);
505} 409}
506 410
507static void
508setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info)
509{
510 struct signal_sframe32 __user *sframep;
511 struct sigcontext32 __user *sc;
512 unsigned int seta[_COMPAT_NSIG_WORDS];
513 int err = 0;
514 void __user *sig_address;
515 int sig_code;
516 unsigned long pc = regs->tpc;
517 unsigned long npc = regs->tnpc;
518 unsigned int psr;
519
520 if (test_thread_flag(TIF_32BIT)) {
521 pc &= 0xffffffff;
522 npc &= 0xffffffff;
523 }
524
525 synchronize_user_stack();
526 save_and_clear_fpu();
527
528 sframep = (struct signal_sframe32 __user *)
529 get_sigframe(sa, regs, SF_ALIGNEDSZ);
530 if (invalid_frame_pointer(sframep, sizeof(*sframep))){
531 /* Don't change signal code and address, so that
532 * post mortem debuggers can have a look.
533 */
534 do_exit(SIGILL);
535 }
536
537 sc = &sframep->sig_context;
538
539 /* We've already made sure frame pointer isn't in kernel space... */
540 err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK),
541 &sc->sigc_onstack);
542
543 switch (_NSIG_WORDS) {
544 case 4: seta[7] = (oldset->sig[3] >> 32);
545 seta[6] = oldset->sig[3];
546 case 3: seta[5] = (oldset->sig[2] >> 32);
547 seta[4] = oldset->sig[2];
548 case 2: seta[3] = (oldset->sig[1] >> 32);
549 seta[2] = oldset->sig[1];
550 case 1: seta[1] = (oldset->sig[0] >> 32);
551 seta[0] = oldset->sig[0];
552 }
553 err |= __put_user(seta[0], &sc->sigc_mask);
554 err |= __copy_to_user(sframep->extramask, seta + 1,
555 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
556 err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp);
557 err |= __put_user(pc, &sc->sigc_pc);
558 err |= __put_user(npc, &sc->sigc_npc);
559 psr = tstate_to_psr(regs->tstate);
560 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
561 psr |= PSR_EF;
562 err |= __put_user(psr, &sc->sigc_psr);
563 err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
564 err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
565 err |= __put_user(get_thread_wsaved(), &sc->sigc_oswins);
566
567 err |= copy_in_user((u32 __user *)sframep,
568 (u32 __user *)(regs->u_regs[UREG_FP]),
569 sizeof(struct reg_window32));
570
571 set_thread_wsaved(0); /* So process is allowed to execute. */
572 err |= __put_user(signr, &sframep->sig_num);
573 sig_address = NULL;
574 sig_code = 0;
575 if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) {
576 sig_address = info->si_addr;
577 switch (signr) {
578 case SIGSEGV:
579 switch (info->si_code) {
580 case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break;
581 default: sig_code = SUBSIG_PROTECTION; break;
582 }
583 break;
584 case SIGILL:
585 switch (info->si_code) {
586 case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break;
587 case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break;
588 case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP(info->si_trapno); break;
589 default: sig_code = SUBSIG_STACK; break;
590 }
591 break;
592 case SIGFPE:
593 switch (info->si_code) {
594 case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break;
595 case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break;
596 case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break;
597 case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break;
598 case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break;
599 case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break;
600 case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break;
601 default: sig_code = SUBSIG_FPERROR; break;
602 }
603 break;
604 case SIGBUS:
605 switch (info->si_code) {
606 case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break;
607 case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break;
608 default: sig_code = SUBSIG_BUSTIMEOUT; break;
609 }
610 break;
611 case SIGEMT:
612 switch (info->si_code) {
613 case EMT_TAGOVF: sig_code = SUBSIG_TAG; break;
614 }
615 break;
616 case SIGSYS:
617 if (info->si_code == (__SI_FAULT|0x100)) {
618 /* See sys_sunos32.c */
619 sig_code = info->si_trapno;
620 break;
621 }
622 default:
623 sig_address = NULL;
624 }
625 }
626 err |= __put_user(ptr_to_compat(sig_address), &sframep->sig_address);
627 err |= __put_user(sig_code, &sframep->sig_code);
628 err |= __put_user(ptr_to_compat(sc), &sframep->sig_scptr);
629 if (err)
630 goto sigsegv;
631
632 regs->u_regs[UREG_FP] = (unsigned long) sframep;
633 regs->tpc = (unsigned long) sa->sa_handler;
634 regs->tnpc = (regs->tpc + 4);
635 if (test_thread_flag(TIF_32BIT)) {
636 regs->tpc &= 0xffffffff;
637 regs->tnpc &= 0xffffffff;
638 }
639 return;
640
641sigsegv:
642 force_sigsegv(signr, current);
643}
644
645
646static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) 411static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
647{ 412{
648 unsigned long *fpregs = current_thread_info()->fpregs; 413 unsigned long *fpregs = current_thread_info()->fpregs;
@@ -663,10 +428,10 @@ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
663 return err; 428 return err;
664} 429}
665 430
666static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, 431static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
667 int signo, sigset_t *oldset) 432 int signo, sigset_t *oldset)
668{ 433{
669 struct new_signal_frame32 __user *sf; 434 struct signal_frame32 __user *sf;
670 int sigframe_size; 435 int sigframe_size;
671 u32 psr; 436 u32 psr;
672 int i, err; 437 int i, err;
@@ -676,11 +441,11 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
676 synchronize_user_stack(); 441 synchronize_user_stack();
677 save_and_clear_fpu(); 442 save_and_clear_fpu();
678 443
679 sigframe_size = NF_ALIGNEDSZ; 444 sigframe_size = SF_ALIGNEDSZ;
680 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) 445 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
681 sigframe_size -= sizeof(__siginfo_fpu_t); 446 sigframe_size -= sizeof(__siginfo_fpu_t);
682 447
683 sf = (struct new_signal_frame32 __user *) 448 sf = (struct signal_frame32 __user *)
684 get_sigframe(&ka->sa, regs, sigframe_size); 449 get_sigframe(&ka->sa, regs, sigframe_size);
685 450
686 if (invalid_frame_pointer(sf, sigframe_size)) 451 if (invalid_frame_pointer(sf, sigframe_size))
@@ -944,10 +709,9 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
944{ 709{
945 if (ka->sa.sa_flags & SA_SIGINFO) 710 if (ka->sa.sa_flags & SA_SIGINFO)
946 setup_rt_frame32(ka, regs, signr, oldset, info); 711 setup_rt_frame32(ka, regs, signr, oldset, info);
947 else if (test_thread_flag(TIF_NEWSIGNALS))
948 new_setup_frame32(ka, regs, signr, oldset);
949 else 712 else
950 setup_frame32(&ka->sa, regs, signr, oldset, info); 713 setup_frame32(ka, regs, signr, oldset);
714
951 spin_lock_irq(&current->sighand->siglock); 715 spin_lock_irq(&current->sighand->siglock);
952 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 716 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
953 if (!(ka->sa.sa_flags & SA_NOMASK)) 717 if (!(ka->sa.sa_flags & SA_NOMASK))
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index c1a61e98899a..161ce4710fe7 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -554,10 +554,8 @@ asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act
554 struct k_sigaction new_ka, old_ka; 554 struct k_sigaction new_ka, old_ka;
555 int ret; 555 int ret;
556 556
557 if (sig < 0) { 557 WARN_ON_ONCE(sig >= 0);
558 set_thread_flag(TIF_NEWSIGNALS); 558 sig = -sig;
559 sig = -sig;
560 }
561 559
562 if (act) { 560 if (act) {
563 compat_old_sigset_t mask; 561 compat_old_sigset_t mask;
@@ -601,11 +599,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
601 if (sigsetsize != sizeof(compat_sigset_t)) 599 if (sigsetsize != sizeof(compat_sigset_t))
602 return -EINVAL; 600 return -EINVAL;
603 601
604 /* All tasks which use RT signals (effectively) use
605 * new style signals.
606 */
607 set_thread_flag(TIF_NEWSIGNALS);
608
609 if (act) { 602 if (act) {
610 u32 u_handler, u_restorer; 603 u32 u_handler, u_restorer;
611 604