aboutsummaryrefslogtreecommitdiffstats
path: root/arch/frv/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/frv/kernel/signal.c')
-rw-r--r--arch/frv/kernel/signal.c155
1 files changed, 85 insertions, 70 deletions
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index d4ccc0728dfe..5b7146f54fd5 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -35,7 +35,7 @@ struct fdpic_func_descriptor {
35 unsigned long GOT; 35 unsigned long GOT;
36}; 36};
37 37
38asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); 38static int do_signal(sigset_t *oldset);
39 39
40/* 40/*
41 * Atomically swap in the new signal mask, and wait for a signal. 41 * Atomically swap in the new signal mask, and wait for a signal.
@@ -55,7 +55,7 @@ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
55 while (1) { 55 while (1) {
56 current->state = TASK_INTERRUPTIBLE; 56 current->state = TASK_INTERRUPTIBLE;
57 schedule(); 57 schedule();
58 if (do_signal(__frame, &saveset)) 58 if (do_signal(&saveset))
59 /* return the signal number as the return value of this function 59 /* return the signal number as the return value of this function
60 * - this is an utterly evil hack. syscalls should not invoke do_signal() 60 * - this is an utterly evil hack. syscalls should not invoke do_signal()
61 * as entry.S sets regs->gr8 to the return value of the system call 61 * as entry.S sets regs->gr8 to the return value of the system call
@@ -91,7 +91,7 @@ asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
91 while (1) { 91 while (1) {
92 current->state = TASK_INTERRUPTIBLE; 92 current->state = TASK_INTERRUPTIBLE;
93 schedule(); 93 schedule();
94 if (do_signal(__frame, &saveset)) 94 if (do_signal(&saveset))
95 /* return the signal number as the return value of this function 95 /* return the signal number as the return value of this function
96 * - this is an utterly evil hack. syscalls should not invoke do_signal() 96 * - this is an utterly evil hack. syscalls should not invoke do_signal()
97 * as entry.S sets regs->gr8 to the return value of the system call 97 * as entry.S sets regs->gr8 to the return value of the system call
@@ -276,13 +276,12 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
276 * Determine which stack to use.. 276 * Determine which stack to use..
277 */ 277 */
278static inline void __user *get_sigframe(struct k_sigaction *ka, 278static inline void __user *get_sigframe(struct k_sigaction *ka,
279 struct pt_regs *regs,
280 size_t frame_size) 279 size_t frame_size)
281{ 280{
282 unsigned long sp; 281 unsigned long sp;
283 282
284 /* Default to using normal stack */ 283 /* Default to using normal stack */
285 sp = regs->sp; 284 sp = __frame->sp;
286 285
287 /* This is the X/Open sanctioned signal stack switching. */ 286 /* This is the X/Open sanctioned signal stack switching. */
288 if (ka->sa.sa_flags & SA_ONSTACK) { 287 if (ka->sa.sa_flags & SA_ONSTACK) {
@@ -291,18 +290,19 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
291 } 290 }
292 291
293 return (void __user *) ((sp - frame_size) & ~7UL); 292 return (void __user *) ((sp - frame_size) & ~7UL);
293
294} /* end get_sigframe() */ 294} /* end get_sigframe() */
295 295
296/*****************************************************************************/ 296/*****************************************************************************/
297/* 297/*
298 * 298 *
299 */ 299 */
300static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) 300static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
301{ 301{
302 struct sigframe __user *frame; 302 struct sigframe __user *frame;
303 int rsig; 303 int rsig;
304 304
305 frame = get_sigframe(ka, regs, sizeof(*frame)); 305 frame = get_sigframe(ka, sizeof(*frame));
306 306
307 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 307 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
308 goto give_sigsegv; 308 goto give_sigsegv;
@@ -346,47 +346,51 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct p
346 } 346 }
347 347
348 /* set up registers for signal handler */ 348 /* set up registers for signal handler */
349 regs->sp = (unsigned long) frame; 349 __frame->sp = (unsigned long) frame;
350 regs->lr = (unsigned long) &frame->retcode; 350 __frame->lr = (unsigned long) &frame->retcode;
351 regs->gr8 = sig; 351 __frame->gr8 = sig;
352 352
353 if (get_personality & FDPIC_FUNCPTRS) { 353 if (get_personality & FDPIC_FUNCPTRS) {
354 struct fdpic_func_descriptor __user *funcptr = 354 struct fdpic_func_descriptor __user *funcptr =
355 (struct fdpic_func_descriptor *) ka->sa.sa_handler; 355 (struct fdpic_func_descriptor *) ka->sa.sa_handler;
356 __get_user(regs->pc, &funcptr->text); 356 __get_user(__frame->pc, &funcptr->text);
357 __get_user(regs->gr15, &funcptr->GOT); 357 __get_user(__frame->gr15, &funcptr->GOT);
358 } else { 358 } else {
359 regs->pc = (unsigned long) ka->sa.sa_handler; 359 __frame->pc = (unsigned long) ka->sa.sa_handler;
360 regs->gr15 = 0; 360 __frame->gr15 = 0;
361 } 361 }
362 362
363 set_fs(USER_DS); 363 set_fs(USER_DS);
364 364
365 /* the tracer may want to single-step inside the handler */
366 if (test_thread_flag(TIF_SINGLESTEP))
367 ptrace_notify(SIGTRAP);
368
365#if DEBUG_SIG 369#if DEBUG_SIG
366 printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", 370 printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
367 sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); 371 sig, current->comm, current->pid, frame, __frame->pc,
372 frame->pretcode);
368#endif 373#endif
369 374
370 return; 375 return 1;
371 376
372give_sigsegv: 377give_sigsegv:
373 if (sig == SIGSEGV)
374 ka->sa.sa_handler = SIG_DFL;
375
376 force_sig(SIGSEGV, current); 378 force_sig(SIGSEGV, current);
379 return 0;
380
377} /* end setup_frame() */ 381} /* end setup_frame() */
378 382
379/*****************************************************************************/ 383/*****************************************************************************/
380/* 384/*
381 * 385 *
382 */ 386 */
383static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 387static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
384 sigset_t *set, struct pt_regs * regs) 388 sigset_t *set)
385{ 389{
386 struct rt_sigframe __user *frame; 390 struct rt_sigframe __user *frame;
387 int rsig; 391 int rsig;
388 392
389 frame = get_sigframe(ka, regs, sizeof(*frame)); 393 frame = get_sigframe(ka, sizeof(*frame));
390 394
391 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 395 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
392 goto give_sigsegv; 396 goto give_sigsegv;
@@ -409,7 +413,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
409 if (__put_user(0, &frame->uc.uc_flags) || 413 if (__put_user(0, &frame->uc.uc_flags) ||
410 __put_user(0, &frame->uc.uc_link) || 414 __put_user(0, &frame->uc.uc_link) ||
411 __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || 415 __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
412 __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) || 416 __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) ||
413 __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) 417 __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
414 goto give_sigsegv; 418 goto give_sigsegv;
415 419
@@ -440,34 +444,38 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
440 } 444 }
441 445
442 /* Set up registers for signal handler */ 446 /* Set up registers for signal handler */
443 regs->sp = (unsigned long) frame; 447 __frame->sp = (unsigned long) frame;
444 regs->lr = (unsigned long) &frame->retcode; 448 __frame->lr = (unsigned long) &frame->retcode;
445 regs->gr8 = sig; 449 __frame->gr8 = sig;
446 regs->gr9 = (unsigned long) &frame->info; 450 __frame->gr9 = (unsigned long) &frame->info;
447 451
448 if (get_personality & FDPIC_FUNCPTRS) { 452 if (get_personality & FDPIC_FUNCPTRS) {
449 struct fdpic_func_descriptor *funcptr = 453 struct fdpic_func_descriptor *funcptr =
450 (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; 454 (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
451 __get_user(regs->pc, &funcptr->text); 455 __get_user(__frame->pc, &funcptr->text);
452 __get_user(regs->gr15, &funcptr->GOT); 456 __get_user(__frame->gr15, &funcptr->GOT);
453 } else { 457 } else {
454 regs->pc = (unsigned long) ka->sa.sa_handler; 458 __frame->pc = (unsigned long) ka->sa.sa_handler;
455 regs->gr15 = 0; 459 __frame->gr15 = 0;
456 } 460 }
457 461
458 set_fs(USER_DS); 462 set_fs(USER_DS);
459 463
464 /* the tracer may want to single-step inside the handler */
465 if (test_thread_flag(TIF_SINGLESTEP))
466 ptrace_notify(SIGTRAP);
467
460#if DEBUG_SIG 468#if DEBUG_SIG
461 printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", 469 printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
462 sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); 470 sig, current->comm, current->pid, frame, __frame->pc,
471 frame->pretcode);
463#endif 472#endif
464 473
465 return; 474 return 1;
466 475
467give_sigsegv: 476give_sigsegv:
468 if (sig == SIGSEGV)
469 ka->sa.sa_handler = SIG_DFL;
470 force_sig(SIGSEGV, current); 477 force_sig(SIGSEGV, current);
478 return 0;
471 479
472} /* end setup_rt_frame() */ 480} /* end setup_rt_frame() */
473 481
@@ -475,43 +483,51 @@ give_sigsegv:
475/* 483/*
476 * OK, we're invoking a handler 484 * OK, we're invoking a handler
477 */ 485 */
478static void handle_signal(unsigned long sig, siginfo_t *info, 486static int handle_signal(unsigned long sig, siginfo_t *info,
479 struct k_sigaction *ka, sigset_t *oldset, 487 struct k_sigaction *ka, sigset_t *oldset)
480 struct pt_regs *regs)
481{ 488{
489 int ret;
490
482 /* Are we from a system call? */ 491 /* Are we from a system call? */
483 if (in_syscall(regs)) { 492 if (in_syscall(__frame)) {
484 /* If so, check system call restarting.. */ 493 /* If so, check system call restarting.. */
485 switch (regs->gr8) { 494 switch (__frame->gr8) {
486 case -ERESTART_RESTARTBLOCK: 495 case -ERESTART_RESTARTBLOCK:
487 case -ERESTARTNOHAND: 496 case -ERESTARTNOHAND:
488 regs->gr8 = -EINTR; 497 __frame->gr8 = -EINTR;
489 break; 498 break;
490 499
491 case -ERESTARTSYS: 500 case -ERESTARTSYS:
492 if (!(ka->sa.sa_flags & SA_RESTART)) { 501 if (!(ka->sa.sa_flags & SA_RESTART)) {
493 regs->gr8 = -EINTR; 502 __frame->gr8 = -EINTR;
494 break; 503 break;
495 } 504 }
505
496 /* fallthrough */ 506 /* fallthrough */
497 case -ERESTARTNOINTR: 507 case -ERESTARTNOINTR:
498 regs->gr8 = regs->orig_gr8; 508 __frame->gr8 = __frame->orig_gr8;
499 regs->pc -= 4; 509 __frame->pc -= 4;
500 } 510 }
501 } 511 }
502 512
503 /* Set up the stack frame */ 513 /* Set up the stack frame */
504 if (ka->sa.sa_flags & SA_SIGINFO) 514 if (ka->sa.sa_flags & SA_SIGINFO)
505 setup_rt_frame(sig, ka, info, oldset, regs); 515 ret = setup_rt_frame(sig, ka, info, oldset);
506 else 516 else
507 setup_frame(sig, ka, oldset, regs); 517 ret = setup_frame(sig, ka, oldset);
518
519 if (ret) {
520 spin_lock_irq(&current->sighand->siglock);
521 sigorsets(&current->blocked, &current->blocked,
522 &ka->sa.sa_mask);
523 if (!(ka->sa.sa_flags & SA_NODEFER))
524 sigaddset(&current->blocked, sig);
525 recalc_sigpending();
526 spin_unlock_irq(&current->sighand->siglock);
527 }
528
529 return ret;
508 530
509 spin_lock_irq(&current->sighand->siglock);
510 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
511 if (!(ka->sa.sa_flags & SA_NODEFER))
512 sigaddset(&current->blocked, sig);
513 recalc_sigpending();
514 spin_unlock_irq(&current->sighand->siglock);
515} /* end handle_signal() */ 531} /* end handle_signal() */
516 532
517/*****************************************************************************/ 533/*****************************************************************************/
@@ -520,7 +536,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
520 * want to handle. Thus you cannot kill init even with a SIGKILL even by 536 * want to handle. Thus you cannot kill init even with a SIGKILL even by
521 * mistake. 537 * mistake.
522 */ 538 */
523int do_signal(struct pt_regs *regs, sigset_t *oldset) 539static int do_signal(sigset_t *oldset)
524{ 540{
525 struct k_sigaction ka; 541 struct k_sigaction ka;
526 siginfo_t info; 542 siginfo_t info;
@@ -532,7 +548,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
532 * kernel mode. Just return without doing anything 548 * kernel mode. Just return without doing anything
533 * if so. 549 * if so.
534 */ 550 */
535 if (!user_mode(regs)) 551 if (!user_mode(__frame))
536 return 1; 552 return 1;
537 553
538 if (try_to_freeze()) 554 if (try_to_freeze())
@@ -541,30 +557,29 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
541 if (!oldset) 557 if (!oldset)
542 oldset = &current->blocked; 558 oldset = &current->blocked;
543 559
544 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 560 signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
545 if (signr > 0) { 561 if (signr > 0)
546 handle_signal(signr, &info, &ka, oldset, regs); 562 return handle_signal(signr, &info, &ka, oldset);
547 return 1;
548 }
549 563
550 no_signal: 564no_signal:
551 /* Did we come from a system call? */ 565 /* Did we come from a system call? */
552 if (regs->syscallno >= 0) { 566 if (__frame->syscallno >= 0) {
553 /* Restart the system call - no handlers present */ 567 /* Restart the system call - no handlers present */
554 if (regs->gr8 == -ERESTARTNOHAND || 568 if (__frame->gr8 == -ERESTARTNOHAND ||
555 regs->gr8 == -ERESTARTSYS || 569 __frame->gr8 == -ERESTARTSYS ||
556 regs->gr8 == -ERESTARTNOINTR) { 570 __frame->gr8 == -ERESTARTNOINTR) {
557 regs->gr8 = regs->orig_gr8; 571 __frame->gr8 = __frame->orig_gr8;
558 regs->pc -= 4; 572 __frame->pc -= 4;
559 } 573 }
560 574
561 if (regs->gr8 == -ERESTART_RESTARTBLOCK){ 575 if (__frame->gr8 == -ERESTART_RESTARTBLOCK){
562 regs->gr8 = __NR_restart_syscall; 576 __frame->gr8 = __NR_restart_syscall;
563 regs->pc -= 4; 577 __frame->pc -= 4;
564 } 578 }
565 } 579 }
566 580
567 return 0; 581 return 0;
582
568} /* end do_signal() */ 583} /* end do_signal() */
569 584
570/*****************************************************************************/ 585/*****************************************************************************/
@@ -580,6 +595,6 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
580 595
581 /* deal with pending signal delivery */ 596 /* deal with pending signal delivery */
582 if (thread_info_flags & _TIF_SIGPENDING) 597 if (thread_info_flags & _TIF_SIGPENDING)
583 do_signal(__frame, NULL); 598 do_signal(NULL);
584 599
585} /* end do_notify_resume() */ 600} /* end do_notify_resume() */