Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f27201da authored by David Woodhouse's avatar David Woodhouse Committed by Linus Torvalds
Browse files

[PATCH] TIF_RESTORE_SIGMASK support for arch/powerpc



Implement the TIF_RESTORE_SIGMASK flag in the new arch/powerpc kernel, for
both 32-bit and 64-bit system call paths.

Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 283828f3
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -227,7 +227,7 @@ ret_from_syscall:
	MTMSRD(r10)
	MTMSRD(r10)
	lwz	r9,TI_FLAGS(r12)
	lwz	r9,TI_FLAGS(r12)
	li	r8,-_LAST_ERRNO
	li	r8,-_LAST_ERRNO
	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
	bne-	syscall_exit_work
	bne-	syscall_exit_work
	cmplw	0,r3,r8
	cmplw	0,r3,r8
	blt+	syscall_exit_cont
	blt+	syscall_exit_cont
@@ -357,7 +357,7 @@ save_user_nvgprs_cont:
	lwz	r5,_MSR(r1)
	lwz	r5,_MSR(r1)
	andi.	r5,r5,MSR_PR
	andi.	r5,r5,MSR_PR
	beq	ret_from_except
	beq	ret_from_except
	andi.	r0,r9,_TIF_SIGPENDING
	andi.	r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
	beq	ret_from_except
	beq	ret_from_except
	b	do_user_signal
	b	do_user_signal
8:
8:
@@ -683,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
	/* Check current_thread_info()->flags */
	/* Check current_thread_info()->flags */
	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
	lwz	r9,TI_FLAGS(r9)
	lwz	r9,TI_FLAGS(r9)
	andi.	r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
	andi.	r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
	bne	do_work
	bne	do_work


restore_user:
restore_user:
@@ -917,7 +917,7 @@ recheck:
	lwz	r9,TI_FLAGS(r9)
	lwz	r9,TI_FLAGS(r9)
	andi.	r0,r9,_TIF_NEED_RESCHED
	andi.	r0,r9,_TIF_NEED_RESCHED
	bne-	do_resched
	bne-	do_resched
	andi.	r0,r9,_TIF_SIGPENDING
	andi.	r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
	beq	restore_user
	beq	restore_user
do_user_signal:			/* r10 contains MSR_KERNEL here */
do_user_signal:			/* r10 contains MSR_KERNEL here */
	ori	r10,r10,MSR_EE
	ori	r10,r10,MSR_EE
+1 −1
Original line number Original line Diff line number Diff line
@@ -160,7 +160,7 @@ syscall_exit:
	mtmsrd	r10,1
	mtmsrd	r10,1
	ld	r9,TI_FLAGS(r12)
	ld	r9,TI_FLAGS(r12)
	li	r11,-_LAST_ERRNO
	li	r11,-_LAST_ERRNO
	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR)
	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK)
	bne-	syscall_exit_work
	bne-	syscall_exit_work
	cmpld	r3,r11
	cmpld	r3,r11
	ld	r5,_CCR(r1)
	ld	r5,_CCR(r1)
+15 −5
Original line number Original line Diff line number Diff line
@@ -1128,7 +1128,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
{
	siginfo_t info;
	siginfo_t info;
	struct k_sigaction ka;
	struct k_sigaction ka;
	unsigned int frame, newsp;
	unsigned int newsp;
	int signr, ret;
	int signr, ret;


#ifdef CONFIG_PPC32
#ifdef CONFIG_PPC32
@@ -1139,11 +1139,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
	}
	}
#endif
#endif


	if (!oldset)
	if (test_thread_flag(TIF_RESTORE_SIGMASK))
		oldset = &current->saved_sigmask;
	else if (!oldset)
		oldset = &current->blocked;
		oldset = &current->blocked;


	newsp = frame = 0;

	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
#ifdef CONFIG_PPC32
#ifdef CONFIG_PPC32
no_signal:
no_signal:
@@ -1173,8 +1173,14 @@ no_signal:
		}
		}
	}
	}


	if (signr == 0)
	if (signr == 0) {
		/* No signal to deliver -- put the saved sigmask back */
		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
			clear_thread_flag(TIF_RESTORE_SIGMASK);
			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
		}
		return 0;		/* no signals delivered */
		return 0;		/* no signals delivered */
	}


	if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
	if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
	    && !on_sig_stack(regs->gpr[1]))
	    && !on_sig_stack(regs->gpr[1]))
@@ -1207,6 +1213,10 @@ no_signal:
			sigaddset(&current->blocked, signr);
			sigaddset(&current->blocked, signr);
		recalc_sigpending();
		recalc_sigpending();
		spin_unlock_irq(&current->sighand->siglock);
		spin_unlock_irq(&current->sighand->siglock);
		/* A signal was successfully delivered; the saved sigmask is in
		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
		if (test_thread_flag(TIF_RESTORE_SIGMASK))
			clear_thread_flag(TIF_RESTORE_SIGMASK);
	}
	}


	return ret;
	return ret;
+18 −2
Original line number Original line Diff line number Diff line
@@ -520,11 +520,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
	if (test_thread_flag(TIF_32BIT))
	if (test_thread_flag(TIF_32BIT))
		return do_signal32(oldset, regs);
		return do_signal32(oldset, regs);


	if (!oldset)
	if (test_thread_flag(TIF_RESTORE_SIGMASK))
		oldset = &current->saved_sigmask;
	else if (!oldset)
		oldset = &current->blocked;
		oldset = &current->blocked;


	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
	if (signr > 0) {
	if (signr > 0) {
		int ret;

		/* Whee!  Actually deliver the signal.  */
		/* Whee!  Actually deliver the signal.  */
		if (TRAP(regs) == 0x0C00)
		if (TRAP(regs) == 0x0C00)
			syscall_restart(regs, &ka);
			syscall_restart(regs, &ka);
@@ -537,7 +541,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
		if (current->thread.dabr)
		if (current->thread.dabr)
			set_dabr(current->thread.dabr);
			set_dabr(current->thread.dabr);


		return handle_signal(signr, &ka, &info, oldset, regs);
		ret = handle_signal(signr, &ka, &info, oldset, regs);

		/* If a signal was successfully delivered, the saved sigmask is in
		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
		if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
			clear_thread_flag(TIF_RESTORE_SIGMASK);

		return ret;
	}
	}


	if (TRAP(regs) == 0x0C00) {	/* System Call! */
	if (TRAP(regs) == 0x0C00) {	/* System Call! */
@@ -553,6 +564,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
			regs->result = 0;
			regs->result = 0;
		}
		}
	}
	}
	/* No signal to deliver -- put the saved sigmask back */
	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
		clear_thread_flag(TIF_RESTORE_SIGMASK);
		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
	}


	return 0;
	return 0;
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -321,3 +321,5 @@ SYSCALL(inotify_add_watch)
SYSCALL(inotify_rm_watch)
SYSCALL(inotify_rm_watch)
SYSCALL(spu_run)
SYSCALL(spu_run)
SYSCALL(spu_create)
SYSCALL(spu_create)
COMPAT_SYS(pselect6)
COMPAT_SYS(ppoll)
Loading