aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/kernel/signal.c111
1 files changed, 45 insertions, 66 deletions
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index b5f385055244..6cec2881acbf 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -272,12 +272,9 @@ give_sigsegv:
272 */ 272 */
273 273
274static inline void __user * 274static inline void __user *
275get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) 275get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
276{ 276{
277 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) 277 return (void __user *)((sigsp(sp, ksig) - frame_size) & -32ul);
278 sp = current->sas_ss_sp + current->sas_ss_size;
279
280 return (void __user *)((sp - frame_size) & -32ul);
281} 278}
282 279
283static long 280static long
@@ -338,14 +335,13 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
338} 335}
339 336
340static int 337static int
341setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, 338setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
342 struct pt_regs *regs)
343{ 339{
344 unsigned long oldsp, r26, err = 0; 340 unsigned long oldsp, r26, err = 0;
345 struct sigframe __user *frame; 341 struct sigframe __user *frame;
346 342
347 oldsp = rdusp(); 343 oldsp = rdusp();
348 frame = get_sigframe(ka, oldsp, sizeof(*frame)); 344 frame = get_sigframe(ksig, oldsp, sizeof(*frame));
349 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 345 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
350 return -EFAULT; 346 return -EFAULT;
351 347
@@ -355,9 +351,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
355 351
356 /* Set up to return from userspace. If provided, use a stub 352 /* Set up to return from userspace. If provided, use a stub
357 already in userspace. */ 353 already in userspace. */
358 if (ka->ka_restorer) { 354 r26 = (unsigned long) ksig->ka.ka_restorer;
359 r26 = (unsigned long) ka->ka_restorer; 355 if (!r26) {
360 } else {
361 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); 356 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
362 err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1); 357 err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
363 err |= __put_user(INSN_CALLSYS, frame->retcode+2); 358 err |= __put_user(INSN_CALLSYS, frame->retcode+2);
@@ -371,8 +366,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
371 366
372 /* "Return" to the handler */ 367 /* "Return" to the handler */
373 regs->r26 = r26; 368 regs->r26 = r26;
374 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; 369 regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
375 regs->r16 = sig; /* a0: signal number */ 370 regs->r16 = ksig->sig; /* a0: signal number */
376 regs->r17 = 0; /* a1: exception code */ 371 regs->r17 = 0; /* a1: exception code */
377 regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */ 372 regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
378 wrusp((unsigned long) frame); 373 wrusp((unsigned long) frame);
@@ -385,18 +380,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
385} 380}
386 381
387static int 382static int
388setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 383setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
389 sigset_t *set, struct pt_regs *regs)
390{ 384{
391 unsigned long oldsp, r26, err = 0; 385 unsigned long oldsp, r26, err = 0;
392 struct rt_sigframe __user *frame; 386 struct rt_sigframe __user *frame;
393 387
394 oldsp = rdusp(); 388 oldsp = rdusp();
395 frame = get_sigframe(ka, oldsp, sizeof(*frame)); 389 frame = get_sigframe(ksig, oldsp, sizeof(*frame));
396 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 390 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
397 return -EFAULT; 391 return -EFAULT;
398 392
399 err |= copy_siginfo_to_user(&frame->info, info); 393 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
400 394
401 /* Create the ucontext. */ 395 /* Create the ucontext. */
402 err |= __put_user(0, &frame->uc.uc_flags); 396 err |= __put_user(0, &frame->uc.uc_flags);
@@ -411,9 +405,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
411 405
412 /* Set up to return from userspace. If provided, use a stub 406 /* Set up to return from userspace. If provided, use a stub
413 already in userspace. */ 407 already in userspace. */
414 if (ka->ka_restorer) { 408 r26 = (unsigned long) ksig->ka.ka_restorer;
415 r26 = (unsigned long) ka->ka_restorer; 409 if (!r26) {
416 } else {
417 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); 410 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
418 err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn, 411 err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
419 frame->retcode+1); 412 frame->retcode+1);
@@ -427,8 +420,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
427 420
428 /* "Return" to the handler */ 421 /* "Return" to the handler */
429 regs->r26 = r26; 422 regs->r26 = r26;
430 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; 423 regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
431 regs->r16 = sig; /* a0: signal number */ 424 regs->r16 = ksig->sig; /* a0: signal number */
432 regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */ 425 regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
433 regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */ 426 regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */
434 wrusp((unsigned long) frame); 427 wrusp((unsigned long) frame);
@@ -446,22 +439,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
446 * OK, we're invoking a handler. 439 * OK, we're invoking a handler.
447 */ 440 */
448static inline void 441static inline void
449handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, 442handle_signal(struct ksignal *ksig, struct pt_regs *regs)
450 struct pt_regs * regs)
451{ 443{
452 sigset_t *oldset = sigmask_to_save(); 444 sigset_t *oldset = sigmask_to_save();
453 int ret; 445 int ret;
454 446
455 if (ka->sa.sa_flags & SA_SIGINFO) 447 if (ksig->ka.sa.sa_flags & SA_SIGINFO)
456 ret = setup_rt_frame(sig, ka, info, oldset, regs); 448 ret = setup_rt_frame(ksig, oldset, regs);
457 else 449 else
458 ret = setup_frame(sig, ka, oldset, regs); 450 ret = setup_frame(ksig, oldset, regs);
459 451
460 if (ret) { 452 signal_setup_done(ret, ksig, 0);
461 force_sigsegv(sig, current);
462 return;
463 }
464 signal_delivered(sig, info, ka, regs, 0);
465} 453}
466 454
467static inline void 455static inline void
@@ -504,47 +492,38 @@ syscall_restart(unsigned long r0, unsigned long r19,
504static void 492static void
505do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19) 493do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
506{ 494{
507 siginfo_t info;
508 int signr;
509 unsigned long single_stepping = ptrace_cancel_bpt(current); 495 unsigned long single_stepping = ptrace_cancel_bpt(current);
510 struct k_sigaction ka; 496 struct ksignal ksig;
511 497
512 /* This lets the debugger run, ... */ 498 /* This lets the debugger run, ... */
513 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 499 if (get_signal(&ksig)) {
514 500 /* ... so re-check the single stepping. */
515 /* ... so re-check the single stepping. */ 501 single_stepping |= ptrace_cancel_bpt(current);
516 single_stepping |= ptrace_cancel_bpt(current);
517
518 if (signr > 0) {
519 /* Whee! Actually deliver the signal. */ 502 /* Whee! Actually deliver the signal. */
520 if (r0) 503 if (r0)
521 syscall_restart(r0, r19, regs, &ka); 504 syscall_restart(r0, r19, regs, &ksig.ka);
522 handle_signal(signr, &ka, &info, regs); 505 handle_signal(&ksig, regs);
523 if (single_stepping) 506 } else {
524 ptrace_set_bpt(current); /* re-set bpt */ 507 single_stepping |= ptrace_cancel_bpt(current);
525 return; 508 if (r0) {
526 } 509 switch (regs->r0) {
527 510 case ERESTARTNOHAND:
528 if (r0) { 511 case ERESTARTSYS:
529 switch (regs->r0) { 512 case ERESTARTNOINTR:
530 case ERESTARTNOHAND: 513 /* Reset v0 and a3 and replay syscall. */
531 case ERESTARTSYS: 514 regs->r0 = r0;
532 case ERESTARTNOINTR: 515 regs->r19 = r19;
533 /* Reset v0 and a3 and replay syscall. */ 516 regs->pc -= 4;
534 regs->r0 = r0; 517 break;
535 regs->r19 = r19; 518 case ERESTART_RESTARTBLOCK:
536 regs->pc -= 4; 519 /* Set v0 to the restart_syscall and replay */
537 break; 520 regs->r0 = __NR_restart_syscall;
538 case ERESTART_RESTARTBLOCK: 521 regs->pc -= 4;
539 /* Force v0 to the restart syscall and reply. */ 522 break;
540 regs->r0 = __NR_restart_syscall; 523 }
541 regs->pc -= 4;
542 break;
543 } 524 }
525 restore_saved_sigmask();
544 } 526 }
545
546 /* If there's no signal to deliver, we just restore the saved mask. */
547 restore_saved_sigmask();
548 if (single_stepping) 527 if (single_stepping)
549 ptrace_set_bpt(current); /* re-set breakpoint */ 528 ptrace_set_bpt(current); /* re-set breakpoint */
550} 529}