aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 21:05:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 21:05:52 -0400
commit4e21fc138bfd7fe625ff5dc81541399aaf9d429b (patch)
tree43bedf14d2eee7711b8241dcfd6bd7b8737d9bd5 /arch/alpha/kernel
parent8418263e3547ed3816475e4c55a77004f0426ee6 (diff)
parent5522be6a4624a5f505555569e4d9cee946630686 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull third pile of kernel_execve() patches from Al Viro: "The last bits of infrastructure for kernel_thread() et.al., with alpha/arm/x86 use of those. Plus sanitizing the asm glue and do_notify_resume() on alpha, fixing the "disabled irq while running task_work stuff" breakage there. At that point the rest of kernel_thread/kernel_execve/sys_execve work can be done independently for different architectures. The only pending bits that do depend on having all architectures converted are restrictred to fs/* and kernel/* - that'll obviously have to wait for the next cycle. I thought we'd have to wait for all of them done before we start eliminating the longjump-style insanity in kernel_execve(), but it turned out there's a very simple way to do that without flagday-style changes." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: alpha: switch to saner kernel_execve() semantics arm: switch to saner kernel_execve() semantics x86, um: convert to saner kernel_execve() semantics infrastructure for saner ret_from_kernel_thread semantics make sure that kernel_thread() callbacks call do_exit() themselves make sure that we always have a return path from kernel_execve() ppc: eeh_event should just use kthread_run() don't bother with kernel_thread/kernel_execve for launching linuxrc alpha: get rid of switch_stack argument of do_work_pending() alpha: don't bother passing switch_stack separately from regs alpha: take SIGPENDING/NOTIFY_RESUME loop into signal.c alpha: simplify TIF_NEED_RESCHED handling
Diffstat (limited to 'arch/alpha/kernel')
-rw-r--r--arch/alpha/kernel/entry.S87
-rw-r--r--arch/alpha/kernel/signal.c48
2 files changed, 56 insertions, 79 deletions
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index 2a359c9ee3cd..a7607832dd4f 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -311,7 +311,7 @@ entSys:
311 311
312 .align 4 312 .align 4
313ret_from_sys_call: 313ret_from_sys_call:
314 cmovne $26, 0, $19 /* $19 = 0 => non-restartable */ 314 cmovne $26, 0, $18 /* $18 = 0 => non-restartable */
315 ldq $0, SP_OFF($sp) 315 ldq $0, SP_OFF($sp)
316 and $0, 8, $0 316 and $0, 8, $0
317 beq $0, ret_to_kernel 317 beq $0, ret_to_kernel
@@ -320,8 +320,8 @@ ret_to_user:
320 sampling and the rti. */ 320 sampling and the rti. */
321 lda $16, 7 321 lda $16, 7
322 call_pal PAL_swpipl 322 call_pal PAL_swpipl
323 ldl $5, TI_FLAGS($8) 323 ldl $17, TI_FLAGS($8)
324 and $5, _TIF_WORK_MASK, $2 324 and $17, _TIF_WORK_MASK, $2
325 bne $2, work_pending 325 bne $2, work_pending
326restore_all: 326restore_all:
327 RESTORE_ALL 327 RESTORE_ALL
@@ -341,10 +341,10 @@ $syscall_error:
341 * frame to indicate that a negative return value wasn't an 341 * frame to indicate that a negative return value wasn't an
342 * error number.. 342 * error number..
343 */ 343 */
344 ldq $19, 0($sp) /* old syscall nr (zero if success) */ 344 ldq $18, 0($sp) /* old syscall nr (zero if success) */
345 beq $19, $ret_success 345 beq $18, $ret_success
346 346
347 ldq $20, 72($sp) /* .. and this a3 */ 347 ldq $19, 72($sp) /* .. and this a3 */
348 subq $31, $0, $0 /* with error in v0 */ 348 subq $31, $0, $0 /* with error in v0 */
349 addq $31, 1, $1 /* set a3 for errno return */ 349 addq $31, 1, $1 /* set a3 for errno return */
350 stq $0, 0($sp) 350 stq $0, 0($sp)
@@ -362,51 +362,35 @@ $ret_success:
362 * Do all cleanup when returning from all interrupts and system calls. 362 * Do all cleanup when returning from all interrupts and system calls.
363 * 363 *
364 * Arguments: 364 * Arguments:
365 * $5: TI_FLAGS.
366 * $8: current. 365 * $8: current.
367 * $19: The old syscall number, or zero if this is not a return 366 * $17: TI_FLAGS.
367 * $18: The old syscall number, or zero if this is not a return
368 * from a syscall that errored and is possibly restartable. 368 * from a syscall that errored and is possibly restartable.
369 * $20: The old a3 value 369 * $19: The old a3 value
370 */ 370 */
371 371
372 .align 4 372 .align 4
373 .ent work_pending 373 .ent work_pending
374work_pending: 374work_pending:
375 and $5, _TIF_NEED_RESCHED, $2 375 and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING, $2
376 beq $2, $work_notifysig 376 bne $2, $work_notifysig
377 377
378$work_resched: 378$work_resched:
379 subq $sp, 16, $sp 379 /*
380 stq $19, 0($sp) /* save syscall nr */ 380 * We can get here only if we returned from syscall without SIGPENDING
381 stq $20, 8($sp) /* and error indication (a3) */ 381 * or got through work_notifysig already. Either case means no syscall
382 * restarts for us, so let $18 and $19 burn.
383 */
382 jsr $26, schedule 384 jsr $26, schedule
383 ldq $19, 0($sp) 385 mov 0, $18
384 ldq $20, 8($sp) 386 br ret_to_user
385 addq $sp, 16, $sp
386 /* Make sure need_resched and sigpending don't change between
387 sampling and the rti. */
388 lda $16, 7
389 call_pal PAL_swpipl
390 ldl $5, TI_FLAGS($8)
391 and $5, _TIF_WORK_MASK, $2
392 beq $2, restore_all
393 and $5, _TIF_NEED_RESCHED, $2
394 bne $2, $work_resched
395 387
396$work_notifysig: 388$work_notifysig:
397 mov $sp, $16 389 mov $sp, $16
398 bsr $1, do_switch_stack 390 bsr $1, do_switch_stack
399 mov $sp, $17 391 jsr $26, do_work_pending
400 mov $5, $18
401 mov $19, $9 /* save old syscall number */
402 mov $20, $10 /* save old a3 */
403 and $5, _TIF_SIGPENDING, $2
404 cmovne $2, 0, $9 /* we don't want double syscall restarts */
405 jsr $26, do_notify_resume
406 mov $9, $19
407 mov $10, $20
408 bsr $1, undo_switch_stack 392 bsr $1, undo_switch_stack
409 br ret_to_user 393 br restore_all
410.end work_pending 394.end work_pending
411 395
412/* 396/*
@@ -454,9 +438,9 @@ $strace_success:
454 438
455 .align 3 439 .align 3
456$strace_error: 440$strace_error:
457 ldq $19, 0($sp) /* old syscall nr (zero if success) */ 441 ldq $18, 0($sp) /* old syscall nr (zero if success) */
458 beq $19, $strace_success 442 beq $18, $strace_success
459 ldq $20, 72($sp) /* .. and this a3 */ 443 ldq $19, 72($sp) /* .. and this a3 */
460 444
461 subq $31, $0, $0 /* with error in v0 */ 445 subq $31, $0, $0 /* with error in v0 */
462 addq $31, 1, $1 /* set a3 for errno return */ 446 addq $31, 1, $1 /* set a3 for errno return */
@@ -464,11 +448,11 @@ $strace_error:
464 stq $1, 72($sp) /* a3 for return */ 448 stq $1, 72($sp) /* a3 for return */
465 449
466 bsr $1, do_switch_stack 450 bsr $1, do_switch_stack
467 mov $19, $9 /* save old syscall number */ 451 mov $18, $9 /* save old syscall number */
468 mov $20, $10 /* save old a3 */ 452 mov $19, $10 /* save old a3 */
469 jsr $26, syscall_trace_leave 453 jsr $26, syscall_trace_leave
470 mov $9, $19 454 mov $9, $18
471 mov $10, $20 455 mov $10, $19
472 bsr $1, undo_switch_stack 456 bsr $1, undo_switch_stack
473 457
474 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ 458 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
@@ -619,24 +603,9 @@ ret_from_kernel_thread:
619 mov $9, $27 603 mov $9, $27
620 mov $10, $16 604 mov $10, $16
621 jsr $26, ($9) 605 jsr $26, ($9)
622 ldgp $gp, 0($26)
623 mov $0, $16
624 mov $31, $26
625 jmp $31, sys_exit
626.end ret_from_kernel_thread
627
628 .globl ret_from_kernel_execve
629 .align 4
630 .ent ret_from_kernel_execve
631ret_from_kernel_execve:
632 mov $16, $sp
633 /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */
634 ldq $2, alpha_mv+HAE_CACHE
635 stq $2, 152($sp) /* HAE */
636 mov $31, $19 /* to disable syscall restarts */ 606 mov $31, $19 /* to disable syscall restarts */
637 br $31, ret_to_user 607 br $31, ret_to_user
638 608.end ret_from_kernel_thread
639.end ret_from_kernel_execve
640 609
641 610
642/* 611/*
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index a8c97d42ec8e..32575f85507d 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -298,8 +298,9 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
298 298
299static long 299static long
300setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, 300setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
301 struct switch_stack *sw, unsigned long mask, unsigned long sp) 301 unsigned long mask, unsigned long sp)
302{ 302{
303 struct switch_stack *sw = (struct switch_stack *)regs - 1;
303 long i, err = 0; 304 long i, err = 0;
304 305
305 err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack); 306 err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
@@ -354,7 +355,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
354 355
355static int 356static int
356setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, 357setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
357 struct pt_regs *regs, struct switch_stack * sw) 358 struct pt_regs *regs)
358{ 359{
359 unsigned long oldsp, r26, err = 0; 360 unsigned long oldsp, r26, err = 0;
360 struct sigframe __user *frame; 361 struct sigframe __user *frame;
@@ -364,7 +365,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
364 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 365 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
365 return -EFAULT; 366 return -EFAULT;
366 367
367 err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); 368 err |= setup_sigcontext(&frame->sc, regs, set->sig[0], oldsp);
368 if (err) 369 if (err)
369 return -EFAULT; 370 return -EFAULT;
370 371
@@ -401,7 +402,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
401 402
402static int 403static int
403setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 404setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
404 sigset_t *set, struct pt_regs *regs, struct switch_stack * sw) 405 sigset_t *set, struct pt_regs *regs)
405{ 406{
406 unsigned long oldsp, r26, err = 0; 407 unsigned long oldsp, r26, err = 0;
407 struct rt_sigframe __user *frame; 408 struct rt_sigframe __user *frame;
@@ -420,7 +421,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
420 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 421 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
421 err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags); 422 err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
422 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); 423 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
423 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw, 424 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs,
424 set->sig[0], oldsp); 425 set->sig[0], oldsp);
425 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 426 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
426 if (err) 427 if (err)
@@ -464,15 +465,15 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
464 */ 465 */
465static inline void 466static inline void
466handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, 467handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
467 struct pt_regs * regs, struct switch_stack *sw) 468 struct pt_regs * regs)
468{ 469{
469 sigset_t *oldset = sigmask_to_save(); 470 sigset_t *oldset = sigmask_to_save();
470 int ret; 471 int ret;
471 472
472 if (ka->sa.sa_flags & SA_SIGINFO) 473 if (ka->sa.sa_flags & SA_SIGINFO)
473 ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); 474 ret = setup_rt_frame(sig, ka, info, oldset, regs);
474 else 475 else
475 ret = setup_frame(sig, ka, oldset, regs, sw); 476 ret = setup_frame(sig, ka, oldset, regs);
476 477
477 if (ret) { 478 if (ret) {
478 force_sigsegv(sig, current); 479 force_sigsegv(sig, current);
@@ -519,8 +520,7 @@ syscall_restart(unsigned long r0, unsigned long r19,
519 * all (if we get here from anything but a syscall return, it will be 0) 520 * all (if we get here from anything but a syscall return, it will be 0)
520 */ 521 */
521static void 522static void
522do_signal(struct pt_regs * regs, struct switch_stack * sw, 523do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
523 unsigned long r0, unsigned long r19)
524{ 524{
525 siginfo_t info; 525 siginfo_t info;
526 int signr; 526 int signr;
@@ -537,7 +537,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
537 /* Whee! Actually deliver the signal. */ 537 /* Whee! Actually deliver the signal. */
538 if (r0) 538 if (r0)
539 syscall_restart(r0, r19, regs, &ka); 539 syscall_restart(r0, r19, regs, &ka);
540 handle_signal(signr, &ka, &info, regs, sw); 540 handle_signal(signr, &ka, &info, regs);
541 if (single_stepping) 541 if (single_stepping)
542 ptrace_set_bpt(current); /* re-set bpt */ 542 ptrace_set_bpt(current); /* re-set bpt */
543 return; 543 return;
@@ -568,15 +568,23 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
568} 568}
569 569
570void 570void
571do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, 571do_work_pending(struct pt_regs *regs, unsigned long thread_flags,
572 unsigned long thread_info_flags,
573 unsigned long r0, unsigned long r19) 572 unsigned long r0, unsigned long r19)
574{ 573{
575 if (thread_info_flags & _TIF_SIGPENDING) 574 do {
576 do_signal(regs, sw, r0, r19); 575 if (thread_flags & _TIF_NEED_RESCHED) {
577 576 schedule();
578 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 577 } else {
579 clear_thread_flag(TIF_NOTIFY_RESUME); 578 local_irq_enable();
580 tracehook_notify_resume(regs); 579 if (thread_flags & _TIF_SIGPENDING) {
581 } 580 do_signal(regs, r0, r19);
581 r0 = 0;
582 } else {
583 clear_thread_flag(TIF_NOTIFY_RESUME);
584 tracehook_notify_resume(regs);
585 }
586 }
587 local_irq_disable();
588 thread_flags = current_thread_info()->flags;
589 } while (thread_flags & _TIF_WORK_MASK);
582} 590}