diff options
-rw-r--r-- | arch/frv/kernel/entry.S | 2 | ||||
-rw-r--r-- | arch/frv/kernel/signal.c | 73 |
2 files changed, 46 insertions, 29 deletions
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index ad10ea595459..5f6548388b74 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S | |||
@@ -1076,7 +1076,7 @@ __entry_work_notifysig: | |||
1076 | LEDS 0x6410 | 1076 | LEDS 0x6410 |
1077 | ori.p gr4,#0,gr8 | 1077 | ori.p gr4,#0,gr8 |
1078 | call do_notify_resume | 1078 | call do_notify_resume |
1079 | bra __entry_return_direct | 1079 | bra __entry_resume_userspace |
1080 | 1080 | ||
1081 | # perform syscall entry tracing | 1081 | # perform syscall entry tracing |
1082 | __syscall_trace_entry: | 1082 | __syscall_trace_entry: |
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index d4ccc0728dfe..89a1cf5c076a 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c | |||
@@ -297,7 +297,8 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, | |||
297 | /* | 297 | /* |
298 | * | 298 | * |
299 | */ | 299 | */ |
300 | static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) | 300 | static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, |
301 | struct pt_regs *regs) | ||
301 | { | 302 | { |
302 | struct sigframe __user *frame; | 303 | struct sigframe __user *frame; |
303 | int rsig; | 304 | int rsig; |
@@ -362,26 +363,30 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct p | |||
362 | 363 | ||
363 | set_fs(USER_DS); | 364 | set_fs(USER_DS); |
364 | 365 | ||
366 | /* the tracer may want to single-step inside the handler */ | ||
367 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
368 | ptrace_notify(SIGTRAP); | ||
369 | |||
365 | #if DEBUG_SIG | 370 | #if DEBUG_SIG |
366 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", | 371 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", |
367 | sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); | 372 | sig, current->comm, current->pid, frame, regs->pc, |
373 | frame->pretcode); | ||
368 | #endif | 374 | #endif |
369 | 375 | ||
370 | return; | 376 | return 1; |
371 | 377 | ||
372 | give_sigsegv: | 378 | give_sigsegv: |
373 | if (sig == SIGSEGV) | ||
374 | ka->sa.sa_handler = SIG_DFL; | ||
375 | |||
376 | force_sig(SIGSEGV, current); | 379 | force_sig(SIGSEGV, current); |
380 | return 0; | ||
381 | |||
377 | } /* end setup_frame() */ | 382 | } /* end setup_frame() */ |
378 | 383 | ||
379 | /*****************************************************************************/ | 384 | /*****************************************************************************/ |
380 | /* | 385 | /* |
381 | * | 386 | * |
382 | */ | 387 | */ |
383 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 388 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
384 | sigset_t *set, struct pt_regs * regs) | 389 | sigset_t *set, struct pt_regs * regs) |
385 | { | 390 | { |
386 | struct rt_sigframe __user *frame; | 391 | struct rt_sigframe __user *frame; |
387 | int rsig; | 392 | int rsig; |
@@ -457,17 +462,21 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
457 | 462 | ||
458 | set_fs(USER_DS); | 463 | set_fs(USER_DS); |
459 | 464 | ||
465 | /* the tracer may want to single-step inside the handler */ | ||
466 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
467 | ptrace_notify(SIGTRAP); | ||
468 | |||
460 | #if DEBUG_SIG | 469 | #if DEBUG_SIG |
461 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", | 470 | printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", |
462 | sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); | 471 | sig, current->comm, current->pid, frame, regs->pc, |
472 | frame->pretcode); | ||
463 | #endif | 473 | #endif |
464 | 474 | ||
465 | return; | 475 | return 1; |
466 | 476 | ||
467 | give_sigsegv: | 477 | give_sigsegv: |
468 | if (sig == SIGSEGV) | ||
469 | ka->sa.sa_handler = SIG_DFL; | ||
470 | force_sig(SIGSEGV, current); | 478 | force_sig(SIGSEGV, current); |
479 | return 0; | ||
471 | 480 | ||
472 | } /* end setup_rt_frame() */ | 481 | } /* end setup_rt_frame() */ |
473 | 482 | ||
@@ -475,10 +484,12 @@ give_sigsegv: | |||
475 | /* | 484 | /* |
476 | * OK, we're invoking a handler | 485 | * OK, we're invoking a handler |
477 | */ | 486 | */ |
478 | static void handle_signal(unsigned long sig, siginfo_t *info, | 487 | static int handle_signal(unsigned long sig, siginfo_t *info, |
479 | struct k_sigaction *ka, sigset_t *oldset, | 488 | struct k_sigaction *ka, sigset_t *oldset, |
480 | struct pt_regs *regs) | 489 | struct pt_regs *regs) |
481 | { | 490 | { |
491 | int ret; | ||
492 | |||
482 | /* Are we from a system call? */ | 493 | /* Are we from a system call? */ |
483 | if (in_syscall(regs)) { | 494 | if (in_syscall(regs)) { |
484 | /* If so, check system call restarting.. */ | 495 | /* If so, check system call restarting.. */ |
@@ -493,6 +504,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, | |||
493 | regs->gr8 = -EINTR; | 504 | regs->gr8 = -EINTR; |
494 | break; | 505 | break; |
495 | } | 506 | } |
507 | |||
496 | /* fallthrough */ | 508 | /* fallthrough */ |
497 | case -ERESTARTNOINTR: | 509 | case -ERESTARTNOINTR: |
498 | regs->gr8 = regs->orig_gr8; | 510 | regs->gr8 = regs->orig_gr8; |
@@ -502,16 +514,22 @@ static void handle_signal(unsigned long sig, siginfo_t *info, | |||
502 | 514 | ||
503 | /* Set up the stack frame */ | 515 | /* Set up the stack frame */ |
504 | if (ka->sa.sa_flags & SA_SIGINFO) | 516 | if (ka->sa.sa_flags & SA_SIGINFO) |
505 | setup_rt_frame(sig, ka, info, oldset, regs); | 517 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
506 | else | 518 | else |
507 | setup_frame(sig, ka, oldset, regs); | 519 | ret = setup_frame(sig, ka, oldset, regs); |
520 | |||
521 | if (ret) { | ||
522 | spin_lock_irq(¤t->sighand->siglock); | ||
523 | sigorsets(¤t->blocked, ¤t->blocked, | ||
524 | &ka->sa.sa_mask); | ||
525 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
526 | sigaddset(¤t->blocked, sig); | ||
527 | recalc_sigpending(); | ||
528 | spin_unlock_irq(¤t->sighand->siglock); | ||
529 | } | ||
530 | |||
531 | return ret; | ||
508 | 532 | ||
509 | spin_lock_irq(¤t->sighand->siglock); | ||
510 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
511 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
512 | sigaddset(¤t->blocked, sig); | ||
513 | recalc_sigpending(); | ||
514 | spin_unlock_irq(¤t->sighand->siglock); | ||
515 | } /* end handle_signal() */ | 533 | } /* end handle_signal() */ |
516 | 534 | ||
517 | /*****************************************************************************/ | 535 | /*****************************************************************************/ |
@@ -542,12 +560,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
542 | oldset = ¤t->blocked; | 560 | oldset = ¤t->blocked; |
543 | 561 | ||
544 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 562 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
545 | if (signr > 0) { | 563 | if (signr > 0) |
546 | handle_signal(signr, &info, &ka, oldset, regs); | 564 | return handle_signal(signr, &info, &ka, oldset, regs); |
547 | return 1; | ||
548 | } | ||
549 | 565 | ||
550 | no_signal: | 566 | no_signal: |
551 | /* Did we come from a system call? */ | 567 | /* Did we come from a system call? */ |
552 | if (regs->syscallno >= 0) { | 568 | if (regs->syscallno >= 0) { |
553 | /* Restart the system call - no handlers present */ | 569 | /* Restart the system call - no handlers present */ |
@@ -565,6 +581,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
565 | } | 581 | } |
566 | 582 | ||
567 | return 0; | 583 | return 0; |
584 | |||
568 | } /* end do_signal() */ | 585 | } /* end do_signal() */ |
569 | 586 | ||
570 | /*****************************************************************************/ | 587 | /*****************************************************************************/ |