mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
c886a9fc1f
commit
14203e19cb
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue