aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2009-05-12 06:10:52 -0400
committerMichal Simek <monstr@monstr.eu>2009-05-21 09:56:07 -0400
commita6029d1c8cfc9ac2609195f31c2e70b584d3496e (patch)
tree739930b605c3aae68fe669054cb01dfad1025ffa /arch
parent732703af9c3478c3f935dd5ae80140b9b12bda09 (diff)
microblaze: prepare signal handling for generic unistd.h
We need to define set_restore_sigmask() in order to get pselect and ppoll. Also, the setup_frame function can not be used when __NR_sigreturn is not defined. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch')
-rw-r--r--arch/microblaze/include/asm/syscalls.h3
-rw-r--r--arch/microblaze/include/asm/thread_info.h11
-rw-r--r--arch/microblaze/kernel/signal.c79
3 files changed, 17 insertions, 76 deletions
diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h
index 9cb4ff0edeb2..ddea9eb31f8d 100644
--- a/arch/microblaze/include/asm/syscalls.h
+++ b/arch/microblaze/include/asm/syscalls.h
@@ -34,6 +34,9 @@ asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
34asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act, 34asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act,
35 struct old_sigaction *oact); 35 struct old_sigaction *oact);
36 36
37asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act,
38 struct sigaction __user *oact, size_t sigsetsize);
39
37asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 40asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
38 struct pt_regs *regs); 41 struct pt_regs *regs);
39 42
diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h
index 4c3943e3f403..a0401d2ef8d5 100644
--- a/arch/microblaze/include/asm/thread_info.h
+++ b/arch/microblaze/include/asm/thread_info.h
@@ -154,6 +154,17 @@ static inline struct thread_info *current_thread_info(void)
154 */ 154 */
155/* FPU was used by this task this quantum (SMP) */ 155/* FPU was used by this task this quantum (SMP) */
156#define TS_USEDFPU 0x0001 156#define TS_USEDFPU 0x0001
157#define TS_RESTORE_SIGMASK 0x0002
158
159#ifndef __ASSEMBLY__
160#define HAVE_SET_RESTORE_SIGMASK 1
161static inline void set_restore_sigmask(void)
162{
163 struct thread_info *ti = current_thread_info();
164 ti->status |= TS_RESTORE_SIGMASK;
165 set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags);
166}
167#endif
157 168
158#endif /* __KERNEL__ */ 169#endif /* __KERNEL__ */
159#endif /* _ASM_MICROBLAZE_THREAD_INFO_H */ 170#endif /* _ASM_MICROBLAZE_THREAD_INFO_H */
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 804a074a94a8..3cdcbfe41295 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -288,80 +288,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
288 return (void __user *)((sp - frame_size) & -8UL); 288 return (void __user *)((sp - frame_size) & -8UL);
289} 289}
290 290
291static void setup_frame(int sig, struct k_sigaction *ka,
292 sigset_t *set, struct pt_regs *regs)
293{
294 struct sigframe *frame;
295 int err = 0;
296 int signal;
297
298 frame = get_sigframe(ka, regs, sizeof(*frame));
299
300 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
301 goto give_sigsegv;
302
303 signal = current_thread_info()->exec_domain
304 && current_thread_info()->exec_domain->signal_invmap
305 && sig < 32
306 ? current_thread_info()->exec_domain->signal_invmap[sig]
307 : sig;
308
309 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
310
311 if (_NSIG_WORDS > 1) {
312 err |= __copy_to_user(frame->extramask, &set->sig[1],
313 sizeof(frame->extramask));
314 }
315
316 /* Set up to return from userspace. If provided, use a stub
317 already in userspace. */
318 /* minus 8 is offset to cater for "rtsd r15,8" offset */
319 if (ka->sa.sa_flags & SA_RESTORER) {
320 regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
321 } else {
322 /* Note, these encodings are _big endian_! */
323
324 /* addi r12, r0, __NR_sigreturn */
325 err |= __put_user(0x31800000 | __NR_sigreturn ,
326 frame->tramp + 0);
327 /* brki r14, 0x8 */
328 err |= __put_user(0xb9cc0008, frame->tramp + 1);
329
330 /* Return from sighandler will jump to the tramp.
331 Negative 8 offset because return is rtsd r15, 8 */
332 regs->r15 = ((unsigned long)frame->tramp)-8;
333
334 __invalidate_cache_sigtramp((unsigned long)frame->tramp);
335 }
336
337 if (err)
338 goto give_sigsegv;
339
340 /* Set up registers for signal handler */
341 regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE;
342
343 /* Signal handler args: */
344 regs->r5 = signal; /* Arg 0: signum */
345 regs->r6 = (unsigned long) &frame->sc; /* arg 1: sigcontext */
346
347 /* Offset of 4 to handle microblaze rtid r14, 0 */
348 regs->pc = (unsigned long)ka->sa.sa_handler;
349
350 set_fs(USER_DS);
351
352#ifdef DEBUG_SIG
353 printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
354 current->comm, current->pid, frame, regs->pc);
355#endif
356
357 return;
358
359give_sigsegv:
360 if (sig == SIGSEGV)
361 ka->sa.sa_handler = SIG_DFL;
362 force_sig(SIGSEGV, current);
363}
364
365static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 291static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
366 sigset_t *set, struct pt_regs *regs) 292 sigset_t *set, struct pt_regs *regs)
367{ 293{
@@ -380,7 +306,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
380 ? current_thread_info()->exec_domain->signal_invmap[sig] 306 ? current_thread_info()->exec_domain->signal_invmap[sig]
381 : sig; 307 : sig;
382 308
383 err |= copy_siginfo_to_user(&frame->info, info); 309 if (info)
310 err |= copy_siginfo_to_user(&frame->info, info);
384 311
385 /* Create the ucontext. */ 312 /* Create the ucontext. */
386 err |= __put_user(0, &frame->uc.uc_flags); 313 err |= __put_user(0, &frame->uc.uc_flags);
@@ -478,7 +405,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
478 if (ka->sa.sa_flags & SA_SIGINFO) 405 if (ka->sa.sa_flags & SA_SIGINFO)
479 setup_rt_frame(sig, ka, info, oldset, regs); 406 setup_rt_frame(sig, ka, info, oldset, regs);
480 else 407 else
481 setup_frame(sig, ka, oldset, regs); 408 setup_rt_frame(sig, ka, NULL, oldset, regs);
482 409
483 if (ka->sa.sa_flags & SA_ONESHOT) 410 if (ka->sa.sa_flags & SA_ONESHOT)
484 ka->sa.sa_handler = SIG_DFL; 411 ka->sa.sa_handler = SIG_DFL;