]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
microblaze: fix the horror with restarts of sigreturn()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 29 Apr 2012 08:11:34 +0000 (04:11 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 3 Feb 2013 23:16:02 +0000 (18:16 -0500)
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>
arch/microblaze/kernel/entry-nommu.S
arch/microblaze/kernel/entry.S

index 29a05d62ec1a4f7e31a810cb506bf81cda92063d..96f97f845495adb8a83a5a09c73288b89fa993e8 100644 (file)
@@ -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
 
index c217367dfc7b31d14ecf138f2cee3371e8aa0251..18908d29248b540bff039a2bc708d6f36ccd2c41 100644 (file)
@@ -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 */