diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-04-29 04:11:34 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-03 18:16:02 -0500 |
commit | 14203e19cbc562a79f49117c45c80639a1e65bdd (patch) | |
tree | 758937f82d73a963b9ed0f5979f303c1522195fa /arch/microblaze/kernel/entry.S | |
parent | c886a9fc1f69c0e53788a9c4a780b6b8825bd4ab (diff) |
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: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/microblaze/kernel/entry.S')
-rw-r--r-- | arch/microblaze/kernel/entry.S | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index c217367dfc7..18908d29248 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -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 */ |