]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xtensa: add missing exclusive access state management
authorMax Filippov <jcmvbkbc@gmail.com>
Fri, 31 Jul 2020 19:38:05 +0000 (12:38 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 21 Aug 2020 11:07:23 +0000 (13:07 +0200)
commit a0fc1436f1f4f84e93144480bf30e0c958d135b6 upstream.

The result of the s32ex opcode is recorded in the ATOMCTL special
register and must be retrieved with the getex opcode. Context switch
between s32ex and getex may trash the ATOMCTL register and result in
duplicate update or missing update of the atomic variable.
Add atomctl8 field to the struct thread_info and use getex to swap
ATOMCTL bit 8 as a part of context switch.
Clear exclusive access monitor on kernel entry.

Cc: stable@vger.kernel.org
Fixes: f7c34874f04a ("xtensa: add exclusive atomics support")
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/xtensa/include/asm/thread_info.h
arch/xtensa/kernel/asm-offsets.c
arch/xtensa/kernel/entry.S

index f092cc3f4e66d34f938cfa13a7e497106d0f97bf..956d4d47c6cd1f473fa54f57db2b6fd1e397cf43 100644 (file)
@@ -55,6 +55,10 @@ struct thread_info {
        mm_segment_t            addr_limit;     /* thread address space */
 
        unsigned long           cpenable;
+#if XCHAL_HAVE_EXCLUSIVE
+       /* result of the most recent exclusive store */
+       unsigned long           atomctl8;
+#endif
 
        /* Allocate storage for extra user states and coprocessor states. */
 #if XTENSA_HAVE_COPROCESSORS
index 33a257b33723aadcc19176f2d22b6d9391d8d30e..dc5c83cad9be85608f7730b1dfb9dde7b5b0f07e 100644 (file)
@@ -93,6 +93,9 @@ int main(void)
        DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
        DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp));
        DEFINE(THREAD_CPENABLE, offsetof (struct thread_info, cpenable));
+#if XCHAL_HAVE_EXCLUSIVE
+       DEFINE(THREAD_ATOMCTL8, offsetof (struct thread_info, atomctl8));
+#endif
 #if XTENSA_HAVE_COPROCESSORS
        DEFINE(THREAD_XTREGS_CP0, offsetof(struct thread_info, xtregs_cp.cp0));
        DEFINE(THREAD_XTREGS_CP1, offsetof(struct thread_info, xtregs_cp.cp1));
index 06fbb0a171f1e8c67b7f70e9637426b5bc97e108..26e2869d255b0237ea4ef3dc10551bbef53f2eea 100644 (file)
@@ -374,6 +374,11 @@ common_exception:
        s32i    a2, a1, PT_LCOUNT
 #endif
 
+#if XCHAL_HAVE_EXCLUSIVE
+       /* Clear exclusive access monitor set by interrupted code */
+       clrex
+#endif
+
        /* It is now save to restore the EXC_TABLE_FIXUP variable. */
 
        rsr     a2, exccause
@@ -2020,6 +2025,12 @@ ENTRY(_switch_to)
        s32i    a3, a4, THREAD_CPENABLE
 #endif
 
+#if XCHAL_HAVE_EXCLUSIVE
+       l32i    a3, a5, THREAD_ATOMCTL8
+       getex   a3
+       s32i    a3, a4, THREAD_ATOMCTL8
+#endif
+
        /* Flush register file. */
 
        spill_registers_kernel