Skip to content

Commit a0fc143

Browse files
committed
xtensa: add missing exclusive access state management
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: [email protected] Fixes: f7c3487 ("xtensa: add exclusive atomics support") Signed-off-by: Max Filippov <[email protected]>
1 parent 6d65d37 commit a0fc143

File tree

3 files changed

+18
-0
lines changed

3 files changed

+18
-0
lines changed

arch/xtensa/include/asm/thread_info.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ struct thread_info {
5555
mm_segment_t addr_limit; /* thread address space */
5656

5757
unsigned long cpenable;
58+
#if XCHAL_HAVE_EXCLUSIVE
59+
/* result of the most recent exclusive store */
60+
unsigned long atomctl8;
61+
#endif
5862

5963
/* Allocate storage for extra user states and coprocessor states. */
6064
#if XTENSA_HAVE_COPROCESSORS

arch/xtensa/kernel/asm-offsets.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ int main(void)
9393
DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
9494
DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp));
9595
DEFINE(THREAD_CPENABLE, offsetof (struct thread_info, cpenable));
96+
#if XCHAL_HAVE_EXCLUSIVE
97+
DEFINE(THREAD_ATOMCTL8, offsetof (struct thread_info, atomctl8));
98+
#endif
9699
#if XTENSA_HAVE_COPROCESSORS
97100
DEFINE(THREAD_XTREGS_CP0, offsetof(struct thread_info, xtregs_cp.cp0));
98101
DEFINE(THREAD_XTREGS_CP1, offsetof(struct thread_info, xtregs_cp.cp1));

arch/xtensa/kernel/entry.S

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,11 @@ common_exception:
374374
s32i a2, a1, PT_LCOUNT
375375
#endif
376376

377+
#if XCHAL_HAVE_EXCLUSIVE
378+
/* Clear exclusive access monitor set by interrupted code */
379+
clrex
380+
#endif
381+
377382
/* It is now save to restore the EXC_TABLE_FIXUP variable. */
378383

379384
rsr a2, exccause
@@ -2020,6 +2025,12 @@ ENTRY(_switch_to)
20202025
s32i a3, a4, THREAD_CPENABLE
20212026
#endif
20222027

2028+
#if XCHAL_HAVE_EXCLUSIVE
2029+
l32i a3, a5, THREAD_ATOMCTL8
2030+
getex a3
2031+
s32i a3, a4, THREAD_ATOMCTL8
2032+
#endif
2033+
20232034
/* Flush register file. */
20242035

20252036
spill_registers_kernel

0 commit comments

Comments
 (0)