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

Commit 14203e19 authored by Al Viro's avatar Al Viro
Browse files

microblaze: fix the horror with restarts of sigreturn()



solution a-la arm one - pick a callee-saved register (r30), set it
non-zero when entering a syscall, have sigreturn wrapper zero it out
and pass the value in it to do_notify_resume() as "in_syscall" (actually,
"restarts allowed") argument.

Note that we don't give a damn about ret_from_fork() - return value
is not restart-worthy anyway.

Possible remaining bug: on !MMU we still have _debug_exception()
restartable.  If it hits with -ERESTART_... accidentally in r3, fun happens.
MMU does _not_ have _debug_exception() restartable.  If that's decided to
be a bug (as I strongly suspect it to be), we'll just need to replace
setting r30 to 1 with setting r30 to 0 in !MMU _debug_exception().
Up to microblaze maintainers...

[folded a fix from Michal]

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c886a9fc
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -280,6 +280,7 @@ ENTRY(_user_exception)
	/* Figure out which function to use for this system call. */
	/* Note Microblaze barrel shift is optional, so don't rely on it */
	add	r12, r12, r12			/* convert num -> ptr */
	addik	r30, r0, 1			/* restarts allowed */
	add	r12, r12, r12
	lwi	r12, r12, sys_call_table	/* Get function pointer */
	addik	r15, r0, ret_to_user-8		/* set return address */
@@ -369,6 +370,7 @@ ENTRY(_debug_exception)
	bralid	r15, send_sig
	add	r7, r0, r0			/* 3rd param zero */

	addik	r30, r0, 1			/* restarts allowed ??? */
	/* Restore r3/r4 to work around how ret_to_user works */
	lwi	r3, r1, PT_R3
	lwi	r4, r1, PT_R4
@@ -492,7 +494,7 @@ work_pending:
	nop
1:	andi	r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
	beqi	r11, no_work_pending
	addk	r5, r1, r0
	addk	r5, r30, r0
	bralid	r15, do_notify_resume
	addik	r6, r0, 1
	bri	no_work_pending
@@ -562,6 +564,7 @@ no_work_pending:
	nop

sys_rt_sigreturn_wrapper:
	addk	r30, r0, r0		/* no restarts for this one */
	brid	sys_rt_sigreturn
	addk	r5, r1, r0

+3 −1
Original line number Diff line number Diff line
@@ -353,6 +353,7 @@ C_ENTRY(_user_exception):
	/* Figure out which function to use for this system call.  */
	/* Note Microblaze barrel shift is optional, so don't rely on it */
	add	r12, r12, r12;			/* convert num -> ptr */
	addi	r30, r0, 1			/* restarts allowed */
	add	r12, r12, r12;

#ifdef DEBUG
@@ -417,7 +418,7 @@ C_ENTRY(ret_from_trap):

	addik	r5, r1, 0;		/* Arg 1: struct pt_regs *regs */
	bralid	r15, do_notify_resume;	/* Handle any signals */
	addi	r6, r0, 1;		/* Arg 2: int in_syscall */
	add	r6, r30, r0;		/* Arg 2: int in_syscall */

/* Finally, return to user state.  */
1:	set_bip;			/*  Ints masked for state restore */
@@ -464,6 +465,7 @@ C_ENTRY(ret_from_kernel_thread):
	add	r3, r0, r0

C_ENTRY(sys_rt_sigreturn_wrapper):
	addik	r30, r0, 0		/* no restarts */
	brid	sys_rt_sigreturn	/* Do real work */
	addik	r5, r1, 0;		/* add user context as 1st arg */