diff options
Diffstat (limited to 'arch/mips/kernel/signal.c')
-rw-r--r-- | arch/mips/kernel/signal.c | 72 |
1 files changed, 27 insertions, 45 deletions
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 9e60d117e41e..1d57605e4615 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -280,7 +280,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
280 | return err; | 280 | return err; |
281 | } | 281 | } |
282 | 282 | ||
283 | void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 283 | void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, |
284 | size_t frame_size) | 284 | size_t frame_size) |
285 | { | 285 | { |
286 | unsigned long sp; | 286 | unsigned long sp; |
@@ -295,9 +295,7 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
295 | */ | 295 | */ |
296 | sp -= 32; | 296 | sp -= 32; |
297 | 297 | ||
298 | /* This is the X/Open sanctioned signal stack switching. */ | 298 | sp = sigsp(sp, ksig); |
299 | if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) | ||
300 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
301 | 299 | ||
302 | return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); | 300 | return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); |
303 | } | 301 | } |
@@ -428,20 +426,20 @@ badframe: | |||
428 | } | 426 | } |
429 | 427 | ||
430 | #ifdef CONFIG_TRAD_SIGNALS | 428 | #ifdef CONFIG_TRAD_SIGNALS |
431 | static int setup_frame(void *sig_return, struct k_sigaction *ka, | 429 | static int setup_frame(void *sig_return, struct ksignal *ksig, |
432 | struct pt_regs *regs, int signr, sigset_t *set) | 430 | struct pt_regs *regs, sigset_t *set) |
433 | { | 431 | { |
434 | struct sigframe __user *frame; | 432 | struct sigframe __user *frame; |
435 | int err = 0; | 433 | int err = 0; |
436 | 434 | ||
437 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 435 | frame = get_sigframe(ksig, regs, sizeof(*frame)); |
438 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | 436 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
439 | goto give_sigsegv; | 437 | return -EFAULT; |
440 | 438 | ||
441 | err |= setup_sigcontext(regs, &frame->sf_sc); | 439 | err |= setup_sigcontext(regs, &frame->sf_sc); |
442 | err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); | 440 | err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); |
443 | if (err) | 441 | if (err) |
444 | goto give_sigsegv; | 442 | return -EFAULT; |
445 | 443 | ||
446 | /* | 444 | /* |
447 | * Arguments to signal handler: | 445 | * Arguments to signal handler: |
@@ -453,37 +451,32 @@ static int setup_frame(void *sig_return, struct k_sigaction *ka, | |||
453 | * $25 and c0_epc point to the signal handler, $29 points to the | 451 | * $25 and c0_epc point to the signal handler, $29 points to the |
454 | * struct sigframe. | 452 | * struct sigframe. |
455 | */ | 453 | */ |
456 | regs->regs[ 4] = signr; | 454 | regs->regs[ 4] = ksig->sig; |
457 | regs->regs[ 5] = 0; | 455 | regs->regs[ 5] = 0; |
458 | regs->regs[ 6] = (unsigned long) &frame->sf_sc; | 456 | regs->regs[ 6] = (unsigned long) &frame->sf_sc; |
459 | regs->regs[29] = (unsigned long) frame; | 457 | regs->regs[29] = (unsigned long) frame; |
460 | regs->regs[31] = (unsigned long) sig_return; | 458 | regs->regs[31] = (unsigned long) sig_return; |
461 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; | 459 | regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; |
462 | 460 | ||
463 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | 461 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", |
464 | current->comm, current->pid, | 462 | current->comm, current->pid, |
465 | frame, regs->cp0_epc, regs->regs[31]); | 463 | frame, regs->cp0_epc, regs->regs[31]); |
466 | return 0; | 464 | return 0; |
467 | |||
468 | give_sigsegv: | ||
469 | force_sigsegv(signr, current); | ||
470 | return -EFAULT; | ||
471 | } | 465 | } |
472 | #endif | 466 | #endif |
473 | 467 | ||
474 | static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, | 468 | static int setup_rt_frame(void *sig_return, struct ksignal *ksig, |
475 | struct pt_regs *regs, int signr, sigset_t *set, | 469 | struct pt_regs *regs, sigset_t *set) |
476 | siginfo_t *info) | ||
477 | { | 470 | { |
478 | struct rt_sigframe __user *frame; | 471 | struct rt_sigframe __user *frame; |
479 | int err = 0; | 472 | int err = 0; |
480 | 473 | ||
481 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 474 | frame = get_sigframe(ksig, regs, sizeof(*frame)); |
482 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | 475 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
483 | goto give_sigsegv; | 476 | return -EFAULT; |
484 | 477 | ||
485 | /* Create siginfo. */ | 478 | /* Create siginfo. */ |
486 | err |= copy_siginfo_to_user(&frame->rs_info, info); | 479 | err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info); |
487 | 480 | ||
488 | /* Create the ucontext. */ | 481 | /* Create the ucontext. */ |
489 | err |= __put_user(0, &frame->rs_uc.uc_flags); | 482 | err |= __put_user(0, &frame->rs_uc.uc_flags); |
@@ -493,7 +486,7 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, | |||
493 | err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); | 486 | err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); |
494 | 487 | ||
495 | if (err) | 488 | if (err) |
496 | goto give_sigsegv; | 489 | return -EFAULT; |
497 | 490 | ||
498 | /* | 491 | /* |
499 | * Arguments to signal handler: | 492 | * Arguments to signal handler: |
@@ -505,22 +498,18 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, | |||
505 | * $25 and c0_epc point to the signal handler, $29 points to | 498 | * $25 and c0_epc point to the signal handler, $29 points to |
506 | * the struct rt_sigframe. | 499 | * the struct rt_sigframe. |
507 | */ | 500 | */ |
508 | regs->regs[ 4] = signr; | 501 | regs->regs[ 4] = ksig->sig; |
509 | regs->regs[ 5] = (unsigned long) &frame->rs_info; | 502 | regs->regs[ 5] = (unsigned long) &frame->rs_info; |
510 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; | 503 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; |
511 | regs->regs[29] = (unsigned long) frame; | 504 | regs->regs[29] = (unsigned long) frame; |
512 | regs->regs[31] = (unsigned long) sig_return; | 505 | regs->regs[31] = (unsigned long) sig_return; |
513 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; | 506 | regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; |
514 | 507 | ||
515 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | 508 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", |
516 | current->comm, current->pid, | 509 | current->comm, current->pid, |
517 | frame, regs->cp0_epc, regs->regs[31]); | 510 | frame, regs->cp0_epc, regs->regs[31]); |
518 | 511 | ||
519 | return 0; | 512 | return 0; |
520 | |||
521 | give_sigsegv: | ||
522 | force_sigsegv(signr, current); | ||
523 | return -EFAULT; | ||
524 | } | 513 | } |
525 | 514 | ||
526 | struct mips_abi mips_abi = { | 515 | struct mips_abi mips_abi = { |
@@ -534,8 +523,7 @@ struct mips_abi mips_abi = { | |||
534 | .restart = __NR_restart_syscall | 523 | .restart = __NR_restart_syscall |
535 | }; | 524 | }; |
536 | 525 | ||
537 | static void handle_signal(unsigned long sig, siginfo_t *info, | 526 | static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
538 | struct k_sigaction *ka, struct pt_regs *regs) | ||
539 | { | 527 | { |
540 | sigset_t *oldset = sigmask_to_save(); | 528 | sigset_t *oldset = sigmask_to_save(); |
541 | int ret; | 529 | int ret; |
@@ -557,7 +545,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, | |||
557 | regs->regs[2] = EINTR; | 545 | regs->regs[2] = EINTR; |
558 | break; | 546 | break; |
559 | case ERESTARTSYS: | 547 | case ERESTARTSYS: |
560 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 548 | if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { |
561 | regs->regs[2] = EINTR; | 549 | regs->regs[2] = EINTR; |
562 | break; | 550 | break; |
563 | } | 551 | } |
@@ -571,29 +559,23 @@ static void handle_signal(unsigned long sig, siginfo_t *info, | |||
571 | regs->regs[0] = 0; /* Don't deal with this again. */ | 559 | regs->regs[0] = 0; /* Don't deal with this again. */ |
572 | } | 560 | } |
573 | 561 | ||
574 | if (sig_uses_siginfo(ka)) | 562 | if (sig_uses_siginfo(&ksig->ka)) |
575 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, | 563 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, |
576 | ka, regs, sig, oldset, info); | 564 | ksig, regs, oldset); |
577 | else | 565 | else |
578 | ret = abi->setup_frame(vdso + abi->signal_return_offset, | 566 | ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig, |
579 | ka, regs, sig, oldset); | 567 | regs, oldset); |
580 | |||
581 | if (ret) | ||
582 | return; | ||
583 | 568 | ||
584 | signal_delivered(sig, info, ka, regs, 0); | 569 | signal_setup_done(ret, ksig, 0); |
585 | } | 570 | } |
586 | 571 | ||
587 | static void do_signal(struct pt_regs *regs) | 572 | static void do_signal(struct pt_regs *regs) |
588 | { | 573 | { |
589 | struct k_sigaction ka; | 574 | struct ksignal ksig; |
590 | siginfo_t info; | ||
591 | int signr; | ||
592 | 575 | ||
593 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 576 | if (get_signal(&ksig)) { |
594 | if (signr > 0) { | ||
595 | /* Whee! Actually deliver the signal. */ | 577 | /* Whee! Actually deliver the signal. */ |
596 | handle_signal(signr, &info, &ka, regs); | 578 | handle_signal(&ksig, regs); |
597 | return; | 579 | return; |
598 | } | 580 | } |
599 | 581 | ||