diff options
author | Michal Simek <monstr@monstr.eu> | 2009-05-12 06:10:52 -0400 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2009-05-21 09:56:07 -0400 |
commit | a6029d1c8cfc9ac2609195f31c2e70b584d3496e (patch) | |
tree | 739930b605c3aae68fe669054cb01dfad1025ffa /arch/microblaze/kernel | |
parent | 732703af9c3478c3f935dd5ae80140b9b12bda09 (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/microblaze/kernel')
-rw-r--r-- | arch/microblaze/kernel/signal.c | 79 |
1 files changed, 3 insertions, 76 deletions
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 | ||
291 | static 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 | |||
359 | give_sigsegv: | ||
360 | if (sig == SIGSEGV) | ||
361 | ka->sa.sa_handler = SIG_DFL; | ||
362 | force_sig(SIGSEGV, current); | ||
363 | } | ||
364 | |||
365 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 291 | static 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; |