diff options
Diffstat (limited to 'arch/sh/kernel/signal_64.c')
-rw-r--r-- | arch/sh/kernel/signal_64.c | 82 |
1 files changed, 32 insertions, 50 deletions
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 23d4c71c91af..897abe7b871e 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c | |||
@@ -41,8 +41,7 @@ | |||
41 | #define DEBUG_SIG 0 | 41 | #define DEBUG_SIG 0 |
42 | 42 | ||
43 | static void | 43 | static void |
44 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 44 | handle_signal(struct ksignal *ksig, struct pt_regs *regs); |
45 | struct pt_regs * regs); | ||
46 | 45 | ||
47 | static inline void | 46 | static inline void |
48 | handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) | 47 | handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) |
@@ -82,9 +81,7 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) | |||
82 | */ | 81 | */ |
83 | static void do_signal(struct pt_regs *regs) | 82 | static void do_signal(struct pt_regs *regs) |
84 | { | 83 | { |
85 | siginfo_t info; | 84 | struct ksignal ksig; |
86 | int signr; | ||
87 | struct k_sigaction ka; | ||
88 | 85 | ||
89 | /* | 86 | /* |
90 | * We want the common case to go fast, which | 87 | * We want the common case to go fast, which |
@@ -95,12 +92,11 @@ static void do_signal(struct pt_regs *regs) | |||
95 | if (!user_mode(regs)) | 92 | if (!user_mode(regs)) |
96 | return; | 93 | return; |
97 | 94 | ||
98 | signr = get_signal_to_deliver(&info, &ka, regs, 0); | 95 | if (get_signal(&ksig)) { |
99 | if (signr > 0) { | 96 | handle_syscall_restart(regs, &ksig.ka.sa); |
100 | handle_syscall_restart(regs, &ka.sa); | ||
101 | 97 | ||
102 | /* Whee! Actually deliver the signal. */ | 98 | /* Whee! Actually deliver the signal. */ |
103 | handle_signal(signr, &info, &ka, regs); | 99 | handle_signal(&ksig, regs); |
104 | return; | 100 | return; |
105 | } | 101 | } |
106 | 102 | ||
@@ -378,17 +374,16 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) | |||
378 | void sa_default_restorer(void); /* See comments below */ | 374 | void sa_default_restorer(void); /* See comments below */ |
379 | void sa_default_rt_restorer(void); /* See comments below */ | 375 | void sa_default_rt_restorer(void); /* See comments below */ |
380 | 376 | ||
381 | static int setup_frame(int sig, struct k_sigaction *ka, | 377 | static int setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) |
382 | sigset_t *set, struct pt_regs *regs) | ||
383 | { | 378 | { |
384 | struct sigframe __user *frame; | 379 | struct sigframe __user *frame; |
385 | int err = 0; | 380 | int err = 0, sig = ksig->sig; |
386 | int signal; | 381 | int signal; |
387 | 382 | ||
388 | frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); | 383 | frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame)); |
389 | 384 | ||
390 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 385 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
391 | goto give_sigsegv; | 386 | return -EFAULT; |
392 | 387 | ||
393 | signal = current_thread_info()->exec_domain | 388 | signal = current_thread_info()->exec_domain |
394 | && current_thread_info()->exec_domain->signal_invmap | 389 | && current_thread_info()->exec_domain->signal_invmap |
@@ -400,7 +395,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
400 | 395 | ||
401 | /* Give up earlier as i386, in case */ | 396 | /* Give up earlier as i386, in case */ |
402 | if (err) | 397 | if (err) |
403 | goto give_sigsegv; | 398 | return -EFAULT; |
404 | 399 | ||
405 | if (_NSIG_WORDS > 1) { | 400 | if (_NSIG_WORDS > 1) { |
406 | err |= __copy_to_user(frame->extramask, &set->sig[1], | 401 | err |= __copy_to_user(frame->extramask, &set->sig[1], |
@@ -408,16 +403,16 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
408 | 403 | ||
409 | /* Give up earlier as i386, in case */ | 404 | /* Give up earlier as i386, in case */ |
410 | if (err) | 405 | if (err) |
411 | goto give_sigsegv; | 406 | return -EFAULT; |
412 | 407 | ||
413 | /* Set up to return from userspace. If provided, use a stub | 408 | /* Set up to return from userspace. If provided, use a stub |
414 | already in userspace. */ | 409 | already in userspace. */ |
415 | if (ka->sa.sa_flags & SA_RESTORER) { | 410 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
416 | /* | 411 | /* |
417 | * On SH5 all edited pointers are subject to NEFF | 412 | * On SH5 all edited pointers are subject to NEFF |
418 | */ | 413 | */ |
419 | DEREF_REG_PR = neff_sign_extend((unsigned long) | 414 | DEREF_REG_PR = neff_sign_extend((unsigned long) |
420 | ka->sa.sa_restorer | 0x1); | 415 | ksig->ka->sa.sa_restorer | 0x1); |
421 | } else { | 416 | } else { |
422 | /* | 417 | /* |
423 | * Different approach on SH5. | 418 | * Different approach on SH5. |
@@ -435,7 +430,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
435 | 430 | ||
436 | if (__copy_to_user(frame->retcode, | 431 | if (__copy_to_user(frame->retcode, |
437 | (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0) | 432 | (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0) |
438 | goto give_sigsegv; | 433 | return -EFAULT; |
439 | 434 | ||
440 | /* Cohere the trampoline with the I-cache. */ | 435 | /* Cohere the trampoline with the I-cache. */ |
441 | flush_cache_sigtramp(DEREF_REG_PR-1); | 436 | flush_cache_sigtramp(DEREF_REG_PR-1); |
@@ -460,7 +455,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
460 | regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc; | 455 | regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc; |
461 | regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc; | 456 | regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc; |
462 | 457 | ||
463 | regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler); | 458 | regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler); |
464 | 459 | ||
465 | set_fs(USER_DS); | 460 | set_fs(USER_DS); |
466 | 461 | ||
@@ -471,23 +466,19 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
471 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); | 466 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); |
472 | 467 | ||
473 | return 0; | 468 | return 0; |
474 | |||
475 | give_sigsegv: | ||
476 | force_sigsegv(sig, current); | ||
477 | return -EFAULT; | ||
478 | } | 469 | } |
479 | 470 | ||
480 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 471 | static int setup_rt_frame(struct ksignal *kig, sigset_t *set, |
481 | sigset_t *set, struct pt_regs *regs) | 472 | struct pt_regs *regs) |
482 | { | 473 | { |
483 | struct rt_sigframe __user *frame; | 474 | struct rt_sigframe __user *frame; |
484 | int err = 0; | 475 | int err = 0, sig = ksig->sig; |
485 | int signal; | 476 | int signal; |
486 | 477 | ||
487 | frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); | 478 | frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame)); |
488 | 479 | ||
489 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 480 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
490 | goto give_sigsegv; | 481 | return -EFAULT; |
491 | 482 | ||
492 | signal = current_thread_info()->exec_domain | 483 | signal = current_thread_info()->exec_domain |
493 | && current_thread_info()->exec_domain->signal_invmap | 484 | && current_thread_info()->exec_domain->signal_invmap |
@@ -497,11 +488,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
497 | 488 | ||
498 | err |= __put_user(&frame->info, &frame->pinfo); | 489 | err |= __put_user(&frame->info, &frame->pinfo); |
499 | err |= __put_user(&frame->uc, &frame->puc); | 490 | err |= __put_user(&frame->uc, &frame->puc); |
500 | err |= copy_siginfo_to_user(&frame->info, info); | 491 | err |= copy_siginfo_to_user(&frame->info, &ksig->info); |
501 | 492 | ||
502 | /* Give up earlier as i386, in case */ | 493 | /* Give up earlier as i386, in case */ |
503 | if (err) | 494 | if (err) |
504 | goto give_sigsegv; | 495 | return -EFAULT; |
505 | 496 | ||
506 | /* Create the ucontext. */ | 497 | /* Create the ucontext. */ |
507 | err |= __put_user(0, &frame->uc.uc_flags); | 498 | err |= __put_user(0, &frame->uc.uc_flags); |
@@ -513,16 +504,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
513 | 504 | ||
514 | /* Give up earlier as i386, in case */ | 505 | /* Give up earlier as i386, in case */ |
515 | if (err) | 506 | if (err) |
516 | goto give_sigsegv; | 507 | return -EFAULT; |
517 | 508 | ||
518 | /* Set up to return from userspace. If provided, use a stub | 509 | /* Set up to return from userspace. If provided, use a stub |
519 | already in userspace. */ | 510 | already in userspace. */ |
520 | if (ka->sa.sa_flags & SA_RESTORER) { | 511 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
521 | /* | 512 | /* |
522 | * On SH5 all edited pointers are subject to NEFF | 513 | * On SH5 all edited pointers are subject to NEFF |
523 | */ | 514 | */ |
524 | DEREF_REG_PR = neff_sign_extend((unsigned long) | 515 | DEREF_REG_PR = neff_sign_extend((unsigned long) |
525 | ka->sa.sa_restorer | 0x1); | 516 | ksig->ka.sa.sa_restorer | 0x1); |
526 | } else { | 517 | } else { |
527 | /* | 518 | /* |
528 | * Different approach on SH5. | 519 | * Different approach on SH5. |
@@ -540,7 +531,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
540 | 531 | ||
541 | if (__copy_to_user(frame->retcode, | 532 | if (__copy_to_user(frame->retcode, |
542 | (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0) | 533 | (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0) |
543 | goto give_sigsegv; | 534 | return -EFAULT; |
544 | 535 | ||
545 | /* Cohere the trampoline with the I-cache. */ | 536 | /* Cohere the trampoline with the I-cache. */ |
546 | flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15); | 537 | flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15); |
@@ -554,7 +545,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
554 | regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ | 545 | regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ |
555 | regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info; | 546 | regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info; |
556 | regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext; | 547 | regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext; |
557 | regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler); | 548 | regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler); |
558 | 549 | ||
559 | set_fs(USER_DS); | 550 | set_fs(USER_DS); |
560 | 551 | ||
@@ -564,33 +555,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
564 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); | 555 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); |
565 | 556 | ||
566 | return 0; | 557 | return 0; |
567 | |||
568 | give_sigsegv: | ||
569 | force_sigsegv(sig, current); | ||
570 | return -EFAULT; | ||
571 | } | 558 | } |
572 | 559 | ||
573 | /* | 560 | /* |
574 | * OK, we're invoking a handler | 561 | * OK, we're invoking a handler |
575 | */ | 562 | */ |
576 | static void | 563 | static void |
577 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 564 | handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
578 | struct pt_regs * regs) | ||
579 | { | 565 | { |
580 | sigset_t *oldset = sigmask_to_save(); | 566 | sigset_t *oldset = sigmask_to_save(); |
581 | int ret; | 567 | int ret; |
582 | 568 | ||
583 | /* Set up the stack frame */ | 569 | /* Set up the stack frame */ |
584 | if (ka->sa.sa_flags & SA_SIGINFO) | 570 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
585 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 571 | ret = setup_rt_frame(ksig, oldset, regs); |
586 | else | 572 | else |
587 | ret = setup_frame(sig, ka, oldset, regs); | 573 | ret = setup_frame(ksig, oldset, regs); |
588 | |||
589 | if (ret) | ||
590 | return; | ||
591 | 574 | ||
592 | signal_delivered(sig, info, ka, regs, | 575 | signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); |
593 | test_thread_flag(TIF_SINGLESTEP)); | ||
594 | } | 576 | } |
595 | 577 | ||
596 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | 578 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) |