MIPS: Save static registers before sysmips
authorJames Hogan <james.hogan@imgtec.com>
Wed, 31 May 2017 15:19:48 +0000 (16:19 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jul 2017 22:03:27 +0000 (15:03 -0700)
commit 49955d84cd9ccdca5a16a495e448e1a06fad9e49 upstream.

The MIPS sysmips system call handler may return directly from the
MIPS_ATOMIC_SET case (mips_atomic_set()) to syscall_exit. This path
restores the static (callee saved) registers, however they won't have
been saved on entry to the system call.

Use the save_static_function() macro to create a __sys_sysmips wrapper
function which saves the static registers before calling sys_sysmips, so
that the correct static register state is restored by syscall_exit.

Fixes: f1e39a4a616c ("MIPS: Rewrite sysmips(MIPS_ATOMIC_SET, ...) in C with inline assembler")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/16149/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/syscall.c

index 00cad1005a16d1fc1925166ec5746e5ac9890154..ffa43464da00259a0ba3825d9a48babfd9797e47 100644 (file)
@@ -361,7 +361,7 @@ EXPORT(sys_call_table)
        PTR     sys_writev
        PTR     sys_cacheflush
        PTR     sys_cachectl
-       PTR     sys_sysmips
+       PTR     __sys_sysmips
        PTR     sys_ni_syscall                  /* 4150 */
        PTR     sys_getsid
        PTR     sys_fdatasync
index a6576cf1e6d9f92457bf873edf3226c0e4edd94b..e72f53630552f94243bcfc0aba25906dc9f9e525 100644 (file)
@@ -318,7 +318,7 @@ EXPORT(sys_call_table)
        PTR     sys_sched_getaffinity
        PTR     sys_cacheflush
        PTR     sys_cachectl
-       PTR     sys_sysmips
+       PTR     __sys_sysmips
        PTR     sys_io_setup                    /* 5200 */
        PTR     sys_io_destroy
        PTR     sys_io_getevents
index 9a47c1233d2a3d1f4afd489c6c9371dbc15defcf..dc33ef055fa255f1202a82c852c097bc2ad36fa4 100644 (file)
@@ -307,7 +307,7 @@ EXPORT(sysn32_call_table)
        PTR     compat_sys_sched_getaffinity
        PTR     sys_cacheflush
        PTR     sys_cachectl
-       PTR     sys_sysmips
+       PTR     __sys_sysmips
        PTR     compat_sys_io_setup                     /* 6200 */
        PTR     sys_io_destroy
        PTR     compat_sys_io_getevents
index 8be0757e34cd98a7d868bc87e69d35f33dbe90cd..680f2cc13a6dbb07e579090d33778fa42f160cc2 100644 (file)
@@ -358,7 +358,7 @@ EXPORT(sys32_call_table)
        PTR     compat_sys_writev
        PTR     sys_cacheflush
        PTR     sys_cachectl
-       PTR     sys_sysmips
+       PTR     __sys_sysmips
        PTR     sys_ni_syscall                  /* 4150 */
        PTR     sys_getsid
        PTR     sys_fdatasync
index 720bc8ef26ba6f6b98b439493d9e2428eb4063e5..1c864e20156f7b45fbb65d8ec8f00115c963827d 100644 (file)
@@ -200,6 +200,12 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
        unreachable();
 }
 
+/*
+ * mips_atomic_set() normally returns directly via syscall_exit potentially
+ * clobbering static registers, so be sure to preserve them.
+ */
+save_static_function(sys_sysmips);
+
 SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
 {
        switch (cmd) {