aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-01-19 05:42:49 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-19 05:42:49 -0500
commit2d7d5f05111a9d913131a2764d8b20157f8f758d (patch)
tree792deb7a3b9f72894d16affff1569a15b35e428b /arch/sparc/kernel
parentf7111ceb5266750db2a1d193b98fb6a3d9b5a56a (diff)
[SPARC]: Add support for *at(), ppoll, and pselect syscalls.
This also includes by necessity _TIF_RESTORE_SIGMASK support, which actually resulted in a lot of cleanups. The sparc signal handling code is quite a mess and I should clean it up some day. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r--arch/sparc/kernel/entry.S56
-rw-r--r--arch/sparc/kernel/rtrap.S9
-rw-r--r--arch/sparc/kernel/signal.c117
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c2
-rw-r--r--arch/sparc/kernel/systbls.S10
5 files changed, 44 insertions, 150 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 03ecb4e4614e..c51d08d218ef 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1277,62 +1277,6 @@ sys_sigstack:
1277 mov %l5, %o7 1277 mov %l5, %o7
1278 1278
1279 .align 4 1279 .align 4
1280 .globl sys_sigpause
1281sys_sigpause:
1282 /* Note: %o0 already has correct value... */
1283 call do_sigpause
1284 add %sp, STACKFRAME_SZ, %o1
1285
1286 ld [%curptr + TI_FLAGS], %l5
1287 andcc %l5, _TIF_SYSCALL_TRACE, %g0
1288 be 1f
1289 nop
1290
1291 call syscall_trace
1292 nop
1293
12941:
1295 /* We are returning to a signal handler. */
1296 RESTORE_ALL
1297
1298 .align 4
1299 .globl sys_sigsuspend
1300sys_sigsuspend:
1301 call do_sigsuspend
1302 add %sp, STACKFRAME_SZ, %o0
1303
1304 ld [%curptr + TI_FLAGS], %l5
1305 andcc %l5, _TIF_SYSCALL_TRACE, %g0
1306 be 1f
1307 nop
1308
1309 call syscall_trace
1310 nop
1311
13121:
1313 /* We are returning to a signal handler. */
1314 RESTORE_ALL
1315
1316 .align 4
1317 .globl sys_rt_sigsuspend
1318sys_rt_sigsuspend:
1319 /* Note: %o0, %o1 already have correct value... */
1320 call do_rt_sigsuspend
1321 add %sp, STACKFRAME_SZ, %o2
1322
1323 ld [%curptr + TI_FLAGS], %l5
1324 andcc %l5, _TIF_SYSCALL_TRACE, %g0
1325 be 1f
1326 nop
1327
1328 call syscall_trace
1329 nop
1330
13311:
1332 /* We are returning to a signal handler. */
1333 RESTORE_ALL
1334
1335 .align 4
1336 .globl sys_sigreturn 1280 .globl sys_sigreturn
1337sys_sigreturn: 1281sys_sigreturn:
1338 call do_sigreturn 1282 call do_sigreturn
diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S
index f7460d897e79..77ca6fd81253 100644
--- a/arch/sparc/kernel/rtrap.S
+++ b/arch/sparc/kernel/rtrap.S
@@ -68,15 +68,14 @@ ret_trap_lockless_ipi:
68 68
69 ld [%curptr + TI_FLAGS], %g2 69 ld [%curptr + TI_FLAGS], %g2
70signal_p: 70signal_p:
71 andcc %g2, (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING), %g0 71 andcc %g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0
72 bz,a ret_trap_continue 72 bz,a ret_trap_continue
73 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr 73 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
74 74
75 clr %o0 75 mov %l5, %o1
76 mov %l5, %o2 76 mov %l6, %o2
77 mov %l6, %o3
78 call do_signal 77 call do_signal
79 add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr 78 add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr
80 79
81 /* Fall through. */ 80 /* Fall through. */
82 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr 81 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 5f34d7dc2b89..0748d8147bbf 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -35,9 +35,6 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
35 void *fpqueue, unsigned long *fpqdepth); 35 void *fpqueue, unsigned long *fpqdepth);
36extern void fpload(unsigned long *fpregs, unsigned long *fsr); 36extern void fpload(unsigned long *fpregs, unsigned long *fsr);
37 37
38asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
39 unsigned long orig_o0, int restart_syscall);
40
41/* Signal frames: the original one (compatible with SunOS): 38/* Signal frames: the original one (compatible with SunOS):
42 * 39 *
43 * Set up a signal frame... Make the stack look the way SunOS 40 * Set up a signal frame... Make the stack look the way SunOS
@@ -95,98 +92,30 @@ struct rt_signal_frame {
95#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7))) 92#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7)))
96#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) 93#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
97 94
98/* 95static int _sigpause_common(old_sigset_t set)
99 * atomically swap in the new signal mask, and wait for a signal.
100 * This is really tricky on the Sparc, watch out...
101 */
102asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
103{ 96{
104 sigset_t saveset;
105
106 set &= _BLOCKABLE; 97 set &= _BLOCKABLE;
107 spin_lock_irq(&current->sighand->siglock); 98 spin_lock_irq(&current->sighand->siglock);
108 saveset = current->blocked; 99 current->saved_sigmask = current->blocked;
109 siginitset(&current->blocked, set); 100 siginitset(&current->blocked, set);
110 recalc_sigpending(); 101 recalc_sigpending();
111 spin_unlock_irq(&current->sighand->siglock); 102 spin_unlock_irq(&current->sighand->siglock);
112 103
113 regs->pc = regs->npc; 104 current->state = TASK_INTERRUPTIBLE;
114 regs->npc += 4; 105 schedule();
115 106 set_thread_flag(TIF_RESTORE_SIGMASK);
116 /* Condition codes and return value where set here for sigpause,
117 * and so got used by setup_frame, which again causes sigreturn()
118 * to return -EINTR.
119 */
120 while (1) {
121 current->state = TASK_INTERRUPTIBLE;
122 schedule();
123 /*
124 * Return -EINTR and set condition code here,
125 * so the interrupted system call actually returns
126 * these.
127 */
128 regs->psr |= PSR_C;
129 regs->u_regs[UREG_I0] = EINTR;
130 if (do_signal(&saveset, regs, 0, 0))
131 return;
132 }
133}
134 107
135asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs) 108 return -ERESTARTNOHAND;
136{
137 _sigpause_common(set, regs);
138} 109}
139 110
140asmlinkage void do_sigsuspend (struct pt_regs *regs) 111asmlinkage int sys_sigpause(unsigned int set)
141{ 112{
142 _sigpause_common(regs->u_regs[UREG_I0], regs); 113 return _sigpause_common(set);
143} 114}
144 115
145asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, 116asmlinkage int sys_sigsuspend(old_sigset_t set)
146 struct pt_regs *regs)
147{ 117{
148 sigset_t oldset, set; 118 return _sigpause_common(set);
149
150 /* XXX: Don't preclude handling different sized sigset_t's. */
151 if (sigsetsize != sizeof(sigset_t)) {
152 regs->psr |= PSR_C;
153 regs->u_regs[UREG_I0] = EINVAL;
154 return;
155 }
156
157 if (copy_from_user(&set, uset, sizeof(set))) {
158 regs->psr |= PSR_C;
159 regs->u_regs[UREG_I0] = EFAULT;
160 return;
161 }
162
163 sigdelsetmask(&set, ~_BLOCKABLE);
164 spin_lock_irq(&current->sighand->siglock);
165 oldset = current->blocked;
166 current->blocked = set;
167 recalc_sigpending();
168 spin_unlock_irq(&current->sighand->siglock);
169
170 regs->pc = regs->npc;
171 regs->npc += 4;
172
173 /* Condition codes and return value where set here for sigpause,
174 * and so got used by setup_frame, which again causes sigreturn()
175 * to return -EINTR.
176 */
177 while (1) {
178 current->state = TASK_INTERRUPTIBLE;
179 schedule();
180 /*
181 * Return -EINTR and set condition code here,
182 * so the interrupted system call actually returns
183 * these.
184 */
185 regs->psr |= PSR_C;
186 regs->u_regs[UREG_I0] = EINTR;
187 if (do_signal(&oldset, regs, 0, 0))
188 return;
189 }
190} 119}
191 120
192static inline int 121static inline int
@@ -1067,13 +996,13 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
1067 * want to handle. Thus you cannot kill init even with a SIGKILL even by 996 * want to handle. Thus you cannot kill init even with a SIGKILL even by
1068 * mistake. 997 * mistake.
1069 */ 998 */
1070asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, 999asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall)
1071 unsigned long orig_i0, int restart_syscall)
1072{ 1000{
1073 siginfo_t info; 1001 siginfo_t info;
1074 struct sparc_deliver_cookie cookie; 1002 struct sparc_deliver_cookie cookie;
1075 struct k_sigaction ka; 1003 struct k_sigaction ka;
1076 int signr; 1004 int signr;
1005 sigset_t *oldset;
1077 1006
1078 /* 1007 /*
1079 * XXX Disable svr4 signal handling until solaris emulation works. 1008 * XXX Disable svr4 signal handling until solaris emulation works.
@@ -1089,7 +1018,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
1089 cookie.restart_syscall = restart_syscall; 1018 cookie.restart_syscall = restart_syscall;
1090 cookie.orig_i0 = orig_i0; 1019 cookie.orig_i0 = orig_i0;
1091 1020
1092 if (!oldset) 1021 if (test_thread_flag(TIF_RESTORE_SIGMASK))
1022 oldset = &current->saved_sigmask;
1023 else
1093 oldset = &current->blocked; 1024 oldset = &current->blocked;
1094 1025
1095 signr = get_signal_to_deliver(&info, &ka, regs, &cookie); 1026 signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
@@ -1098,7 +1029,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
1098 syscall_restart(cookie.orig_i0, regs, &ka.sa); 1029 syscall_restart(cookie.orig_i0, regs, &ka.sa);
1099 handle_signal(signr, &ka, &info, oldset, 1030 handle_signal(signr, &ka, &info, oldset,
1100 regs, svr4_signal); 1031 regs, svr4_signal);
1101 return 1; 1032 /* a signal was successfully delivered; the saved
1033 * sigmask will have been stored in the signal frame,
1034 * and will be restored by sigreturn, so we can simply
1035 * clear the TIF_RESTORE_SIGMASK flag.
1036 */
1037 if (test_thread_flag(TIF_RESTORE_SIGMASK))
1038 clear_thread_flag(TIF_RESTORE_SIGMASK);
1039 return;
1102 } 1040 }
1103 if (cookie.restart_syscall && 1041 if (cookie.restart_syscall &&
1104 (regs->u_regs[UREG_I0] == ERESTARTNOHAND || 1042 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -1115,7 +1053,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
1115 regs->pc -= 4; 1053 regs->pc -= 4;
1116 regs->npc -= 4; 1054 regs->npc -= 4;
1117 } 1055 }
1118 return 0; 1056
1057 /* if there's no signal to deliver, we just put the saved sigmask
1058 * back
1059 */
1060 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
1061 clear_thread_flag(TIF_RESTORE_SIGMASK);
1062 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
1063 }
1119} 1064}
1120 1065
1121asmlinkage int 1066asmlinkage int
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 0b0d492c953b..19b25399d7e4 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -66,7 +66,6 @@ struct poll {
66 66
67extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *); 67extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
68extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *); 68extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
69void _sigpause_common (unsigned int set, struct pt_regs *);
70extern void (*__copy_1page)(void *, const void *); 69extern void (*__copy_1page)(void *, const void *);
71extern void __memmove(void *, const void *, __kernel_size_t); 70extern void __memmove(void *, const void *, __kernel_size_t);
72extern void (*bzero_1page)(void *); 71extern void (*bzero_1page)(void *);
@@ -227,7 +226,6 @@ EXPORT_SYMBOL(kunmap_atomic);
227/* Solaris/SunOS binary compatibility */ 226/* Solaris/SunOS binary compatibility */
228EXPORT_SYMBOL(svr4_setcontext); 227EXPORT_SYMBOL(svr4_setcontext);
229EXPORT_SYMBOL(svr4_getcontext); 228EXPORT_SYMBOL(svr4_getcontext);
230EXPORT_SYMBOL(_sigpause_common);
231 229
232EXPORT_SYMBOL(dump_thread); 230EXPORT_SYMBOL(dump_thread);
233 231
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index e457a40838fc..6877ae4cd1d9 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -75,7 +75,10 @@ sys_call_table:
75/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy 75/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
76/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink 76/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
77/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid 77/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
78/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl 78/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
79/*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_newfstatat
80/*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
81/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll
79 82
80#ifdef CONFIG_SUNOS_EMUL 83#ifdef CONFIG_SUNOS_EMUL
81 /* Now the SunOS syscall table. */ 84 /* Now the SunOS syscall table. */
@@ -181,6 +184,11 @@ sunos_sys_table:
181 .long sunos_nosys, sunos_nosys, sunos_nosys 184 .long sunos_nosys, sunos_nosys, sunos_nosys
182 .long sunos_nosys 185 .long sunos_nosys
183/*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys 186/*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys
187 .long sunos_nosys, sunos_nosys, sunos_nosys
188 .long sunos_nosys, sunos_nosys, sunos_nosys
184 .long sunos_nosys 189 .long sunos_nosys
190/*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys
191 .long sunos_nosys, sunos_nosys, sunos_nosys
192 .long sunos_nosys, sunos_nosys, sunos_nosys
185 193
186#endif 194#endif