diff options
| author | Patrick McHardy <kaber@trash.net> | 2010-05-10 12:39:28 -0400 |
|---|---|---|
| committer | Patrick McHardy <kaber@trash.net> | 2010-05-10 12:39:28 -0400 |
| commit | 1e4b1057121bc756b91758a434b504d2010f6088 (patch) | |
| tree | b016cf2c728289c7e36d9e4e488f30ab0bd0ae6e /arch/mips/kernel/signal.c | |
| parent | 3b254c54ec46eb022cb26ee6ab37fae23f5f7d6a (diff) | |
| parent | 3ee943728fff536edaf8f59faa58aaa1aa7366e3 (diff) | |
Merge branch 'master' of /repos/git/net-next-2.6
Conflicts:
net/bridge/br_device.c
net/bridge/br_forward.c
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'arch/mips/kernel/signal.c')
| -rw-r--r-- | arch/mips/kernel/signal.c | 86 |
1 files changed, 19 insertions, 67 deletions
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index d0c68b5d717b..2099d5a4c4b7 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <asm/ucontext.h> | 32 | #include <asm/ucontext.h> |
| 33 | #include <asm/cpu-features.h> | 33 | #include <asm/cpu-features.h> |
| 34 | #include <asm/war.h> | 34 | #include <asm/war.h> |
| 35 | #include <asm/vdso.h> | ||
| 35 | 36 | ||
| 36 | #include "signal-common.h" | 37 | #include "signal-common.h" |
| 37 | 38 | ||
| @@ -44,47 +45,20 @@ extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); | |||
| 44 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); | 45 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); |
| 45 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); | 46 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); |
| 46 | 47 | ||
| 47 | /* | ||
| 48 | * Horribly complicated - with the bloody RM9000 workarounds enabled | ||
| 49 | * the signal trampolines is moving to the end of the structure so we can | ||
| 50 | * increase the alignment without breaking software compatibility. | ||
| 51 | */ | ||
| 52 | #if ICACHE_REFILLS_WORKAROUND_WAR == 0 | ||
| 53 | |||
| 54 | struct sigframe { | 48 | struct sigframe { |
| 55 | u32 sf_ass[4]; /* argument save space for o32 */ | 49 | u32 sf_ass[4]; /* argument save space for o32 */ |
| 56 | u32 sf_code[2]; /* signal trampoline */ | 50 | u32 sf_pad[2]; /* Was: signal trampoline */ |
| 57 | struct sigcontext sf_sc; | 51 | struct sigcontext sf_sc; |
| 58 | sigset_t sf_mask; | 52 | sigset_t sf_mask; |
| 59 | }; | 53 | }; |
| 60 | 54 | ||
| 61 | struct rt_sigframe { | 55 | struct rt_sigframe { |
| 62 | u32 rs_ass[4]; /* argument save space for o32 */ | 56 | u32 rs_ass[4]; /* argument save space for o32 */ |
| 63 | u32 rs_code[2]; /* signal trampoline */ | 57 | u32 rs_pad[2]; /* Was: signal trampoline */ |
| 64 | struct siginfo rs_info; | 58 | struct siginfo rs_info; |
| 65 | struct ucontext rs_uc; | 59 | struct ucontext rs_uc; |
| 66 | }; | 60 | }; |
| 67 | 61 | ||
| 68 | #else | ||
| 69 | |||
| 70 | struct sigframe { | ||
| 71 | u32 sf_ass[4]; /* argument save space for o32 */ | ||
| 72 | u32 sf_pad[2]; | ||
| 73 | struct sigcontext sf_sc; /* hw context */ | ||
| 74 | sigset_t sf_mask; | ||
| 75 | u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */ | ||
| 76 | }; | ||
| 77 | |||
| 78 | struct rt_sigframe { | ||
| 79 | u32 rs_ass[4]; /* argument save space for o32 */ | ||
| 80 | u32 rs_pad[2]; | ||
| 81 | struct siginfo rs_info; | ||
| 82 | struct ucontext rs_uc; | ||
| 83 | u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */ | ||
| 84 | }; | ||
| 85 | |||
| 86 | #endif | ||
| 87 | |||
| 88 | /* | 62 | /* |
| 89 | * Helper routines | 63 | * Helper routines |
| 90 | */ | 64 | */ |
| @@ -266,32 +240,6 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 266 | return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); | 240 | return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); |
| 267 | } | 241 | } |
| 268 | 242 | ||
| 269 | int install_sigtramp(unsigned int __user *tramp, unsigned int syscall) | ||
| 270 | { | ||
| 271 | int err; | ||
| 272 | |||
| 273 | /* | ||
| 274 | * Set up the return code ... | ||
| 275 | * | ||
| 276 | * li v0, __NR__foo_sigreturn | ||
| 277 | * syscall | ||
| 278 | */ | ||
| 279 | |||
| 280 | err = __put_user(0x24020000 + syscall, tramp + 0); | ||
| 281 | err |= __put_user(0x0000000c , tramp + 1); | ||
| 282 | if (ICACHE_REFILLS_WORKAROUND_WAR) { | ||
| 283 | err |= __put_user(0, tramp + 2); | ||
| 284 | err |= __put_user(0, tramp + 3); | ||
| 285 | err |= __put_user(0, tramp + 4); | ||
| 286 | err |= __put_user(0, tramp + 5); | ||
| 287 | err |= __put_user(0, tramp + 6); | ||
| 288 | err |= __put_user(0, tramp + 7); | ||
| 289 | } | ||
| 290 | flush_cache_sigtramp((unsigned long) tramp); | ||
| 291 | |||
| 292 | return err; | ||
| 293 | } | ||
| 294 | |||
| 295 | /* | 243 | /* |
| 296 | * Atomically swap in the new signal mask, and wait for a signal. | 244 | * Atomically swap in the new signal mask, and wait for a signal. |
| 297 | */ | 245 | */ |
| @@ -484,8 +432,8 @@ badframe: | |||
| 484 | } | 432 | } |
| 485 | 433 | ||
| 486 | #ifdef CONFIG_TRAD_SIGNALS | 434 | #ifdef CONFIG_TRAD_SIGNALS |
| 487 | static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | 435 | static int setup_frame(void *sig_return, struct k_sigaction *ka, |
| 488 | int signr, sigset_t *set) | 436 | struct pt_regs *regs, int signr, sigset_t *set) |
| 489 | { | 437 | { |
| 490 | struct sigframe __user *frame; | 438 | struct sigframe __user *frame; |
| 491 | int err = 0; | 439 | int err = 0; |
| @@ -494,8 +442,6 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
| 494 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | 442 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
| 495 | goto give_sigsegv; | 443 | goto give_sigsegv; |
| 496 | 444 | ||
| 497 | err |= install_sigtramp(frame->sf_code, __NR_sigreturn); | ||
| 498 | |||
| 499 | err |= setup_sigcontext(regs, &frame->sf_sc); | 445 | err |= setup_sigcontext(regs, &frame->sf_sc); |
| 500 | err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); | 446 | err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); |
| 501 | if (err) | 447 | if (err) |
| @@ -515,7 +461,7 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
| 515 | regs->regs[ 5] = 0; | 461 | regs->regs[ 5] = 0; |
| 516 | regs->regs[ 6] = (unsigned long) &frame->sf_sc; | 462 | regs->regs[ 6] = (unsigned long) &frame->sf_sc; |
| 517 | regs->regs[29] = (unsigned long) frame; | 463 | regs->regs[29] = (unsigned long) frame; |
| 518 | regs->regs[31] = (unsigned long) frame->sf_code; | 464 | regs->regs[31] = (unsigned long) sig_return; |
| 519 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; | 465 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; |
| 520 | 466 | ||
| 521 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | 467 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", |
| @@ -529,8 +475,9 @@ give_sigsegv: | |||
| 529 | } | 475 | } |
| 530 | #endif | 476 | #endif |
| 531 | 477 | ||
| 532 | static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | 478 | static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, |
| 533 | int signr, sigset_t *set, siginfo_t *info) | 479 | struct pt_regs *regs, int signr, sigset_t *set, |
| 480 | siginfo_t *info) | ||
| 534 | { | 481 | { |
| 535 | struct rt_sigframe __user *frame; | 482 | struct rt_sigframe __user *frame; |
| 536 | int err = 0; | 483 | int err = 0; |
| @@ -539,8 +486,6 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
| 539 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | 486 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
| 540 | goto give_sigsegv; | 487 | goto give_sigsegv; |
| 541 | 488 | ||
| 542 | err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn); | ||
| 543 | |||
| 544 | /* Create siginfo. */ | 489 | /* Create siginfo. */ |
| 545 | err |= copy_siginfo_to_user(&frame->rs_info, info); | 490 | err |= copy_siginfo_to_user(&frame->rs_info, info); |
| 546 | 491 | ||
| @@ -573,7 +518,7 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
| 573 | regs->regs[ 5] = (unsigned long) &frame->rs_info; | 518 | regs->regs[ 5] = (unsigned long) &frame->rs_info; |
| 574 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; | 519 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; |
| 575 | regs->regs[29] = (unsigned long) frame; | 520 | regs->regs[29] = (unsigned long) frame; |
| 576 | regs->regs[31] = (unsigned long) frame->rs_code; | 521 | regs->regs[31] = (unsigned long) sig_return; |
| 577 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; | 522 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; |
| 578 | 523 | ||
| 579 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | 524 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", |
| @@ -590,8 +535,11 @@ give_sigsegv: | |||
| 590 | struct mips_abi mips_abi = { | 535 | struct mips_abi mips_abi = { |
| 591 | #ifdef CONFIG_TRAD_SIGNALS | 536 | #ifdef CONFIG_TRAD_SIGNALS |
| 592 | .setup_frame = setup_frame, | 537 | .setup_frame = setup_frame, |
| 538 | .signal_return_offset = offsetof(struct mips_vdso, signal_trampoline), | ||
| 593 | #endif | 539 | #endif |
| 594 | .setup_rt_frame = setup_rt_frame, | 540 | .setup_rt_frame = setup_rt_frame, |
| 541 | .rt_signal_return_offset = | ||
| 542 | offsetof(struct mips_vdso, rt_signal_trampoline), | ||
| 595 | .restart = __NR_restart_syscall | 543 | .restart = __NR_restart_syscall |
| 596 | }; | 544 | }; |
| 597 | 545 | ||
| @@ -599,6 +547,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
| 599 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) | 547 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) |
| 600 | { | 548 | { |
| 601 | int ret; | 549 | int ret; |
| 550 | struct mips_abi *abi = current->thread.abi; | ||
| 551 | void *vdso = current->mm->context.vdso; | ||
| 602 | 552 | ||
| 603 | switch(regs->regs[0]) { | 553 | switch(regs->regs[0]) { |
| 604 | case ERESTART_RESTARTBLOCK: | 554 | case ERESTART_RESTARTBLOCK: |
| @@ -619,9 +569,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
| 619 | regs->regs[0] = 0; /* Don't deal with this again. */ | 569 | regs->regs[0] = 0; /* Don't deal with this again. */ |
| 620 | 570 | ||
| 621 | if (sig_uses_siginfo(ka)) | 571 | if (sig_uses_siginfo(ka)) |
| 622 | ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info); | 572 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, |
| 573 | ka, regs, sig, oldset, info); | ||
| 623 | else | 574 | else |
| 624 | ret = current->thread.abi->setup_frame(ka, regs, sig, oldset); | 575 | ret = abi->setup_frame(vdso + abi->signal_return_offset, |
| 576 | ka, regs, sig, oldset); | ||
| 625 | 577 | ||
| 626 | spin_lock_irq(¤t->sighand->siglock); | 578 | spin_lock_irq(¤t->sighand->siglock); |
| 627 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | 579 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
