]> 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>
Fri, 1 Jun 2012 22:03:12 +0000 (18:03 -0400)
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...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/microblaze/kernel/entry-nommu.S
arch/microblaze/kernel/entry.S

index ea2d6cd41d8ead7e01f168239e5badc06606ac73..583a4d0b64163aedbcaeec390f3dac06a47c1328 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
@@ -485,7 +487,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
@@ -567,6 +569,7 @@ sys_execve:
        addk    r8, r1, r0
 
 sys_rt_sigreturn_wrapper:
+       addk    r30, r0, r0             /* no restarts for this one */
        brid    sys_rt_sigreturn
        addk    r5, r1, r0
 
index 03f7b8ce6b6bcc6968816b1ef09d50401a35ee21..436208e3783827beaa158a55483242e1040e66c8 100644 (file)
@@ -371,6 +371,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
@@ -435,7 +436,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 */
@@ -503,6 +504,7 @@ C_ENTRY(sys_execve):
        addik   r8, r1, 0;              /* add user context as 4th arg */
 
 C_ENTRY(sys_rt_sigreturn_wrapper):
+       addik   r30, r0, r0             /* no restarts */
        brid    sys_rt_sigreturn        /* Do real work */
        addik   r5, r1, 0;              /* add user context as 1st arg */