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

Commit 4650f0a5 authored by Kyle McMartin's avatar Kyle McMartin Committed by Kyle McMartin
Browse files

[PARISC] Add TIF_RESTORE_SIGMASK support



And unmask the pselect6/ppoll system calls.

Signed-off-by: default avatarKyle McMartin <kyle@parisc-linux.org>
parent 0bbdac08
Loading
Loading
Loading
Loading
+58 −83
Original line number Diff line number Diff line
@@ -978,11 +978,39 @@ intr_check_resched:
	LDREG   TI_FLAGS(%r1),%r19	/* sched.h: TIF_NEED_RESCHED */
	bb,<,n	%r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */

	.import do_notify_resume,code
intr_check_sig:
	/* As above */
	mfctl   %cr30,%r1
	LDREG	TI_FLAGS(%r1),%r19	/* sched.h: TIF_SIGPENDING */
	bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
	LDREG	TI_FLAGS(%r1),%r19
	load32	(_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r20
	and,COND(<>)	%r19, %r20, %r0
	b,n	intr_restore	/* skip past if we've nothing to do */

	/* This check is critical to having LWS
	 * working. The IASQ is zero on the gateway
	 * page and we cannot deliver any signals until
	 * we get off the gateway page.
	 *
	 * Only do signals if we are returning to user space
	 */
	LDREG	PT_IASQ0(%r16), %r20
	CMPIB= 0,%r20,intr_restore /* backward */
	nop
	LDREG	PT_IASQ1(%r16), %r20
	CMPIB= 0,%r20,intr_restore /* backward */
	nop

	copy	%r0, %r25			/* long in_syscall = 0 */
#ifdef CONFIG_64BIT
	ldo	-16(%r30),%r29			/* Reference param save area */
#endif

	BL	do_notify_resume,%r2
	copy	%r16, %r26			/* struct pt_regs *regs */

	b	intr_check_sig
	nop

intr_restore:
	copy            %r16,%r29
@@ -1072,35 +1100,6 @@ intr_do_preempt:
	b,n	intr_restore		/* ssm PSW_SM_I done by intr_restore */
#endif /* CONFIG_PREEMPT */

	.import do_signal,code
intr_do_signal:
	/* 
		This check is critical to having LWS
		working. The IASQ is zero on the gateway
		page and we cannot deliver any signals until
		we get off the gateway page.

		Only do signals if we are returning to user space 
	*/
	LDREG	PT_IASQ0(%r16), %r20
	CMPIB= 0,%r20,intr_restore /* backward */
	nop
	LDREG	PT_IASQ1(%r16), %r20
	CMPIB= 0,%r20,intr_restore /* backward */
	nop

	copy	%r0, %r24			/* unsigned long in_syscall */
	copy	%r16, %r25			/* struct pt_regs *regs */
#ifdef CONFIG_64BIT
	ldo	-16(%r30),%r29			/* Reference param save area */
#endif

	BL	do_signal,%r2
	copy	%r0, %r26			/* sigset_t *oldset = NULL */

	b	intr_check_sig
	nop

	/*
	 * External interrupts.
	 */
@@ -2024,32 +2023,6 @@ sys32_sigaltstack_wrapper:
	nop
#endif

	.export sys_rt_sigsuspend_wrapper
sys_rt_sigsuspend_wrapper:
	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
	ldo	TASK_REGS(%r1),%r24
	reg_save %r24

	STREG	%r2, -RP_OFFSET(%r30)
#ifdef CONFIG_64BIT
	ldo	FRAME_SIZE(%r30), %r30
	BL	sys_rt_sigsuspend,%r2
	ldo	-16(%r30),%r29		/* Reference param save area */
#else
	BL	sys_rt_sigsuspend,%r2
	ldo	FRAME_SIZE(%r30), %r30
#endif

	ldo	-FRAME_SIZE(%r30), %r30
	LDREG	-RP_OFFSET(%r30), %r2

	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
	ldo	TASK_REGS(%r1),%r1
	reg_restore %r1

	bv	%r0(%r2)
	nop

	.export syscall_exit
syscall_exit:

@@ -2115,9 +2088,35 @@ syscall_check_resched:
	LDREG	TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19	/* long */
	bb,<,n	%r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */

	.import do_signal,code
syscall_check_sig:
	LDREG	TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19    /* get ti flags */
	bb,<,n	%r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
	LDREG	TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
	load32	(_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r26
	and,COND(<>)	%r19, %r26, %r0
	b,n	syscall_restore	/* skip past if we've nothing to do */

syscall_do_signal:
	/* Save callee-save registers (for sigcontext).
	 * FIXME: After this point the process structure should be
	 * consistent with all the relevant state of the process
	 * before the syscall.  We need to verify this.
	 */
	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
	ldo	TASK_REGS(%r1), %r26		/* struct pt_regs *regs */
	reg_save %r26

#ifdef CONFIG_64BIT
	ldo	-16(%r30),%r29			/* Reference param save area */
#endif

	BL	do_notify_resume,%r2
	ldi	1, %r25				/* long in_syscall = 1 */

	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
	ldo	TASK_REGS(%r1), %r20		/* reload pt_regs */
	reg_restore %r20

	b,n     syscall_check_sig

syscall_restore:
	/* Are we being ptraced? */
@@ -2256,30 +2255,6 @@ syscall_do_resched:
	b       syscall_check_bh  /* if resched, we start over again */
	nop

	.import do_signal,code
syscall_do_signal:
	/* Save callee-save registers (for sigcontext).
	   FIXME: After this point the process structure should be
	   consistent with all the relevant state of the process
	   before the syscall.  We need to verify this. */
	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 
	ldo	TASK_REGS(%r1), %r25		/* struct pt_regs *regs */
	reg_save %r25

	ldi	1, %r24				/* unsigned long in_syscall */

#ifdef CONFIG_64BIT
	ldo	-16(%r30),%r29			/* Reference param save area */
#endif
	BL	do_signal,%r2
	copy	%r0, %r26			/* sigset_t *oldset = NULL */

	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
	ldo	TASK_REGS(%r1), %r20		/* reload pt_regs */
	reg_restore %r20

	b,n     syscall_check_sig

	/*
	 * get_register is used by the non access tlb miss handlers to
	 * copy the value of the general register specified in r8 into
+22 −50
Original line number Diff line number Diff line
@@ -59,8 +59,6 @@
 * this. */
#define A(__x)	((unsigned long)(__x))

int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);

/*
 * Atomically swap in the new signal mask, and wait for a signal.
 */
@@ -68,49 +66,6 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
#include "sys32.h"
#endif

asmlinkage int
sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
{
	sigset_t saveset, newset;
#ifdef __LP64__
	compat_sigset_t newset32;

	if (is_compat_task()) {
		/* XXX: Don't preclude handling different sized sigset_t's.  */
		if (sigsetsize != sizeof(compat_sigset_t))
			return -EINVAL;
		if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
			return -EFAULT;
		sigset_32to64(&newset,&newset32);
		
	} else 
#endif
	{
		/* XXX: Don't preclude handling different sized sigset_t's.  */
		if (sigsetsize != sizeof(sigset_t))
			return -EINVAL;
	
		if (copy_from_user(&newset, unewset, sizeof(newset)))
			return -EFAULT;
	}

	sigdelsetmask(&newset, ~_BLOCKABLE);

	spin_lock_irq(&current->sighand->siglock);
	saveset = current->blocked;
	current->blocked = newset;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

	regs->gr[28] = -EINTR;
	while (1) {
		current->state = TASK_INTERRUPTIBLE;
		schedule();
		if (do_signal(&saveset, regs, 1))
			return -EINTR;
	}
}

/*
 * Do a signal return - restore sigcontext.
 */
@@ -528,12 +483,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 * us due to the magic of delayed branching.
 */

asmlinkage int
do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
asmlinkage void
do_signal(struct pt_regs *regs, long in_syscall)
{
	siginfo_t info;
	struct k_sigaction ka;
	int signr;
	sigset_t *oldset;

	DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
	       oldset, regs, regs->sr[7], in_syscall);
@@ -543,7 +499,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
	   we would be called in that case, but for some reason we
	   are. */

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

	DBG(1,"do_signal: oldset %08lx / %08lx\n", 
@@ -592,7 +550,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
		if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) {
			DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
				regs->gr[28]);
			return 1;
			if (test_thread_flag(TIF_RESTORE_SIGMASK))
				clear_thread_flag(TIF_RESTORE_SIGMASK);
			return;
		}
	}
	/* end of while(1) looping forever if we can't force a signal */
@@ -653,5 +613,17 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
	DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 
		regs->gr[28]);

	return 0;
	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
		clear_thread_flag(TIF_RESTORE_SIGMASK);
		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
	}

	return;
}

void do_notify_resume(struct pt_regs *regs, long in_syscall)
{
	if (test_thread_flag(TIF_SIGPENDING) ||
	    test_thread_flag(TIF_RESTORE_SIGMASK))
		do_signal(regs, in_syscall);
}
+3 −3
Original line number Diff line number Diff line
@@ -283,7 +283,7 @@
	 * struct from a 32-bit user-space app.
	 */
	ENTRY_SAME(rt_sigqueueinfo)
	ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
	ENTRY_COMP(rt_sigsuspend)
	ENTRY_SAME(chown)		/* 180 */
	/* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
	ENTRY_COMP(setsockopt)
@@ -377,8 +377,8 @@
	ENTRY_SAME(inotify_init)
	ENTRY_SAME(inotify_add_watch)	/* 270 */
	ENTRY_SAME(inotify_rm_watch)
	ENTRY_SAME(ni_syscall)		/* 271 ENTRY_COMP(pselect6) */
	ENTRY_SAME(ni_syscall)		/* 272 ENTRY_COMP(ppoll) */
	ENTRY_COMP(pselect6)
	ENTRY_COMP(ppoll)
	ENTRY_SAME(migrate_pages)
	ENTRY_COMP(openat)		/* 275 */
	ENTRY_SAME(mkdirat)
+3 −1
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct thread_info {
#define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_32BIT               5       /* 32 bit binary */
#define TIF_MEMDIE		6
#define TIF_RESTORE_SIGMASK	7	/* restore saved signal mask */

#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
@@ -69,9 +70,10 @@ struct thread_info {
#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
#define _TIF_32BIT		(1 << TIF_32BIT)
#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)

#define _TIF_USER_WORK_MASK     (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
                                 _TIF_NEED_RESCHED)
                                 _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)

#endif /* __KERNEL__ */

+2 −0
Original line number Diff line number Diff line
@@ -955,6 +955,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND

#endif /* __ASSEMBLY__ */