diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-11 21:49:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-11 21:49:08 -0400 |
commit | 8213a2f3eeafdecf06dd718cb4130372263f6067 (patch) | |
tree | 0d02e3201dac64d1429f8552ee1163d4a1ef1646 /arch/parisc | |
parent | 40924754f2cabd5d9af4bcd4dcecc362b5e0baa1 (diff) | |
parent | 12f79be93d94698778ff2b3f921073fc5f6780d6 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull pile 2 of execve and kernel_thread unification work from Al Viro:
"Stuff in there: kernel_thread/kernel_execve/sys_execve conversions for
several more architectures plus assorted signal fixes and cleanups.
There'll be more (in particular, real fixes for the alpha
do_notify_resume() irq mess)..."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (43 commits)
alpha: don't open-code trace_report_syscall_{enter,exit}
Uninclude linux/freezer.h
m32r: trim masks
avr32: trim masks
tile: don't bother with SIGTRAP in setup_frame
microblaze: don't bother with SIGTRAP in setup_rt_frame()
mn10300: don't bother with SIGTRAP in setup_frame()
frv: no need to raise SIGTRAP in setup_frame()
x86: get rid of duplicate code in case of CONFIG_VM86
unicore32: remove pointless test
h8300: trim _TIF_WORK_MASK
parisc: decide whether to go to slow path (tracesys) based on thread flags
parisc: don't bother looping in do_signal()
parisc: fix double restarts
bury the rest of TIF_IRET
sanitize tsk_is_polling()
bury _TIF_RESTORE_SIGMASK
unicore32: unobfuscate _TIF_WORK_MASK
mips: NOTIFY_RESUME is not needed in TIF masks
mips: merge the identical "return from syscall" per-ABI code
...
Conflicts:
arch/arm/include/asm/thread_info.h
Diffstat (limited to 'arch/parisc')
-rw-r--r-- | arch/parisc/hpux/gate.S | 2 | ||||
-rw-r--r-- | arch/parisc/include/asm/thread_info.h | 5 | ||||
-rw-r--r-- | arch/parisc/kernel/signal.c | 45 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall.S | 9 |
4 files changed, 25 insertions, 36 deletions
diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S index 38a1c1b8d4e8..011468857e98 100644 --- a/arch/parisc/hpux/gate.S +++ b/arch/parisc/hpux/gate.S | |||
@@ -71,7 +71,7 @@ ENTRY(hpux_gateway_page) | |||
71 | STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ | 71 | STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ |
72 | STREG %r27, TASK_PT_GR27(%r1) /* user dp */ | 72 | STREG %r27, TASK_PT_GR27(%r1) /* user dp */ |
73 | STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ | 73 | STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ |
74 | STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ | 74 | STREG %r0, TASK_PT_ORIG_R28(%r1) /* don't prohibit restarts */ |
75 | STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */ | 75 | STREG %r29, TASK_PT_GR29(%r1) /* 8th argument */ |
76 | STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ | 76 | STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ |
77 | 77 | ||
diff --git a/arch/parisc/include/asm/thread_info.h b/arch/parisc/include/asm/thread_info.h index 22b4726dee49..d1fb79a36f3d 100644 --- a/arch/parisc/include/asm/thread_info.h +++ b/arch/parisc/include/asm/thread_info.h | |||
@@ -68,13 +68,16 @@ struct thread_info { | |||
68 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | 68 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) |
69 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) | 69 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) |
70 | #define _TIF_32BIT (1 << TIF_32BIT) | 70 | #define _TIF_32BIT (1 << TIF_32BIT) |
71 | #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) | ||
72 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | 71 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) |
73 | #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) | 72 | #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) |
74 | #define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) | 73 | #define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) |
75 | 74 | ||
76 | #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \ | 75 | #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \ |
77 | _TIF_NEED_RESCHED) | 76 | _TIF_NEED_RESCHED) |
77 | #define _TIF_SYSCALL_TRACE_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \ | ||
78 | _TIF_BLOCKSTEP) | ||
79 | |||
80 | #define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG) | ||
78 | 81 | ||
79 | #endif /* __KERNEL__ */ | 82 | #endif /* __KERNEL__ */ |
80 | 83 | ||
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 594459bde14e..537996955998 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
@@ -113,6 +113,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | |||
113 | (usp - sigframe_size); | 113 | (usp - sigframe_size); |
114 | DBG(2,"sys_rt_sigreturn: frame is %p\n", frame); | 114 | DBG(2,"sys_rt_sigreturn: frame is %p\n", frame); |
115 | 115 | ||
116 | regs->orig_r28 = 1; /* no restarts for sigreturn */ | ||
117 | |||
116 | #ifdef CONFIG_64BIT | 118 | #ifdef CONFIG_64BIT |
117 | compat_frame = (struct compat_rt_sigframe __user *)frame; | 119 | compat_frame = (struct compat_rt_sigframe __user *)frame; |
118 | 120 | ||
@@ -437,7 +439,7 @@ give_sigsegv: | |||
437 | * OK, we're invoking a handler. | 439 | * OK, we're invoking a handler. |
438 | */ | 440 | */ |
439 | 441 | ||
440 | static long | 442 | static void |
441 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 443 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
442 | struct pt_regs *regs, int in_syscall) | 444 | struct pt_regs *regs, int in_syscall) |
443 | { | 445 | { |
@@ -447,7 +449,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
447 | 449 | ||
448 | /* Set up the stack frame */ | 450 | /* Set up the stack frame */ |
449 | if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) | 451 | if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) |
450 | return 0; | 452 | return; |
451 | 453 | ||
452 | signal_delivered(sig, info, ka, regs, | 454 | signal_delivered(sig, info, ka, regs, |
453 | test_thread_flag(TIF_SINGLESTEP) || | 455 | test_thread_flag(TIF_SINGLESTEP) || |
@@ -455,13 +457,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
455 | 457 | ||
456 | DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", | 458 | DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", |
457 | regs->gr[28]); | 459 | regs->gr[28]); |
458 | |||
459 | return 1; | ||
460 | } | 460 | } |
461 | 461 | ||
462 | static inline void | 462 | static inline void |
463 | syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | 463 | syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) |
464 | { | 464 | { |
465 | if (regs->orig_r28) | ||
466 | return; | ||
467 | regs->orig_r28 = 1; /* no more restarts */ | ||
465 | /* Check the return code */ | 468 | /* Check the return code */ |
466 | switch (regs->gr[28]) { | 469 | switch (regs->gr[28]) { |
467 | case -ERESTART_RESTARTBLOCK: | 470 | case -ERESTART_RESTARTBLOCK: |
@@ -482,8 +485,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | |||
482 | * we have to do is fiddle the return pointer. | 485 | * we have to do is fiddle the return pointer. |
483 | */ | 486 | */ |
484 | regs->gr[31] -= 8; /* delayed branching */ | 487 | regs->gr[31] -= 8; /* delayed branching */ |
485 | /* Preserve original r28. */ | ||
486 | regs->gr[28] = regs->orig_r28; | ||
487 | break; | 488 | break; |
488 | } | 489 | } |
489 | } | 490 | } |
@@ -491,6 +492,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | |||
491 | static inline void | 492 | static inline void |
492 | insert_restart_trampoline(struct pt_regs *regs) | 493 | insert_restart_trampoline(struct pt_regs *regs) |
493 | { | 494 | { |
495 | if (regs->orig_r28) | ||
496 | return; | ||
497 | regs->orig_r28 = 1; /* no more restarts */ | ||
494 | switch(regs->gr[28]) { | 498 | switch(regs->gr[28]) { |
495 | case -ERESTART_RESTARTBLOCK: { | 499 | case -ERESTART_RESTARTBLOCK: { |
496 | /* Restart the system call - no handlers present */ | 500 | /* Restart the system call - no handlers present */ |
@@ -525,9 +529,6 @@ insert_restart_trampoline(struct pt_regs *regs) | |||
525 | flush_user_icache_range(regs->gr[30], regs->gr[30] + 4); | 529 | flush_user_icache_range(regs->gr[30], regs->gr[30] + 4); |
526 | 530 | ||
527 | regs->gr[31] = regs->gr[30] + 8; | 531 | regs->gr[31] = regs->gr[30] + 8; |
528 | /* Preserve original r28. */ | ||
529 | regs->gr[28] = regs->orig_r28; | ||
530 | |||
531 | return; | 532 | return; |
532 | } | 533 | } |
533 | case -ERESTARTNOHAND: | 534 | case -ERESTARTNOHAND: |
@@ -539,9 +540,6 @@ insert_restart_trampoline(struct pt_regs *regs) | |||
539 | * slot of the branch external instruction. | 540 | * slot of the branch external instruction. |
540 | */ | 541 | */ |
541 | regs->gr[31] -= 8; | 542 | regs->gr[31] -= 8; |
542 | /* Preserve original r28. */ | ||
543 | regs->gr[28] = regs->orig_r28; | ||
544 | |||
545 | return; | 543 | return; |
546 | } | 544 | } |
547 | default: | 545 | default: |
@@ -570,30 +568,17 @@ do_signal(struct pt_regs *regs, long in_syscall) | |||
570 | DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n", | 568 | DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n", |
571 | regs, regs->sr[7], in_syscall); | 569 | regs, regs->sr[7], in_syscall); |
572 | 570 | ||
573 | /* Everyone else checks to see if they are in kernel mode at | 571 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
574 | this point and exits if that's the case. I'm not sure why | 572 | DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); |
575 | we would be called in that case, but for some reason we | ||
576 | are. */ | ||
577 | |||
578 | /* May need to force signal if handle_signal failed to deliver */ | ||
579 | while (1) { | ||
580 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
581 | DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); | ||
582 | 573 | ||
583 | if (signr <= 0) | 574 | if (signr > 0) { |
584 | break; | ||
585 | |||
586 | /* Restart a system call if necessary. */ | 575 | /* Restart a system call if necessary. */ |
587 | if (in_syscall) | 576 | if (in_syscall) |
588 | syscall_restart(regs, &ka); | 577 | syscall_restart(regs, &ka); |
589 | 578 | ||
590 | /* Whee! Actually deliver the signal. If the | 579 | handle_signal(signr, &info, &ka, regs, in_syscall); |
591 | delivery failed, we need to continue to iterate in | 580 | return; |
592 | this loop so we can deliver the SIGSEGV... */ | ||
593 | if (handle_signal(signr, &info, &ka, regs, in_syscall)) | ||
594 | return; | ||
595 | } | 581 | } |
596 | /* end of while(1) looping forever if we can't force a signal */ | ||
597 | 582 | ||
598 | /* Did we come from a system call? */ | 583 | /* Did we come from a system call? */ |
599 | if (in_syscall) | 584 | if (in_syscall) |
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 82a52b2fb13f..86742df0b194 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S | |||
@@ -156,7 +156,7 @@ linux_gateway_entry: | |||
156 | STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ | 156 | STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ |
157 | STREG %r27, TASK_PT_GR27(%r1) /* user dp */ | 157 | STREG %r27, TASK_PT_GR27(%r1) /* user dp */ |
158 | STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ | 158 | STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */ |
159 | STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ | 159 | STREG %r0, TASK_PT_ORIG_R28(%r1) /* don't prohibit restarts */ |
160 | STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */ | 160 | STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */ |
161 | STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ | 161 | STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ |
162 | 162 | ||
@@ -180,9 +180,10 @@ linux_gateway_entry: | |||
180 | 180 | ||
181 | /* Are we being ptraced? */ | 181 | /* Are we being ptraced? */ |
182 | mfctl %cr30, %r1 | 182 | mfctl %cr30, %r1 |
183 | LDREG TI_TASK(%r1),%r1 | 183 | LDREG TI_FLAGS(%r1),%r1 |
184 | ldw TASK_PTRACE(%r1), %r1 | 184 | ldi _TIF_SYSCALL_TRACE_MASK, %r19 |
185 | bb,<,n %r1,31,.Ltracesys | 185 | and,COND(=) %r1, %r19, %r0 |
186 | b,n .Ltracesys | ||
186 | 187 | ||
187 | /* Note! We cannot use the syscall table that is mapped | 188 | /* Note! We cannot use the syscall table that is mapped |
188 | nearby since the gateway page is mapped execute-only. */ | 189 | nearby since the gateway page is mapped execute-only. */ |