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

Commit 00df111e authored by Al Viro's avatar Al Viro
Browse files

parisc: fix double restarts



Don't bother restoring r28 on syscall restarts; it's clobbered by
syscall anyway.  Reuse (now unused) ->orig_r28 as "no restarts allowed"
flag.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 8ca8230b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ ENTRY(hpux_gateway_page)
	STREG	%r26, TASK_PT_GR26(%r1)	 	/* 1st argument */
	STREG	%r27, TASK_PT_GR27(%r1)		/* user dp */
	STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
	STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
	STREG   %r0, TASK_PT_ORIG_R28(%r1)     /* don't prohibit restarts */
	STREG   %r29, TASK_PT_GR29(%r1)         /* 8th argument */
	STREG	%r31, TASK_PT_GR31(%r1)		/* preserve syscall return ptr */
	
+8 −8
Original line number Diff line number Diff line
@@ -113,6 +113,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
		(usp - sigframe_size);
	DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);

	regs->orig_r28 = 1; /* no restarts for sigreturn */

#ifdef CONFIG_64BIT
	compat_frame = (struct compat_rt_sigframe __user *)frame;
	
@@ -462,6 +464,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
static inline void
syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
{
	if (regs->orig_r28)
		return;
	regs->orig_r28 = 1; /* no more restarts */
	/* Check the return code */
	switch (regs->gr[28]) {
	case -ERESTART_RESTARTBLOCK:
@@ -482,8 +487,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
		 * we have to do is fiddle the return pointer.
		 */
		regs->gr[31] -= 8; /* delayed branching */
		/* Preserve original r28. */
		regs->gr[28] = regs->orig_r28;
		break;
	}
}
@@ -491,6 +494,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
static inline void
insert_restart_trampoline(struct pt_regs *regs)
{
	if (regs->orig_r28)
		return;
	regs->orig_r28 = 1; /* no more restarts */
	switch(regs->gr[28]) {
	case -ERESTART_RESTARTBLOCK: {
		/* Restart the system call - no handlers present */
@@ -525,9 +531,6 @@ insert_restart_trampoline(struct pt_regs *regs)
		flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);

		regs->gr[31] = regs->gr[30] + 8;
		/* Preserve original r28. */
		regs->gr[28] = regs->orig_r28;

		return;
	}
	case -ERESTARTNOHAND:
@@ -539,9 +542,6 @@ insert_restart_trampoline(struct pt_regs *regs)
		 * slot of the branch external instruction.
		 */
		regs->gr[31] -= 8;
		/* Preserve original r28. */
		regs->gr[28] = regs->orig_r28;

		return;
	}
	default:
+1 −1
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ linux_gateway_entry:
	STREG	%r26, TASK_PT_GR26(%r1)	 	/* 1st argument */
	STREG	%r27, TASK_PT_GR27(%r1)		/* user dp */
	STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
	STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
	STREG   %r0, TASK_PT_ORIG_R28(%r1)      /* don't prohibit restarts */
	STREG	%r29, TASK_PT_GR29(%r1)		/* return value 1 */
	STREG	%r31, TASK_PT_GR31(%r1)		/* preserve syscall return ptr */