[PATCH 2/2] Fix interrupt epilogue for ARMv7-AR and PowerPC
Sebastian Huber
sebastian.huber at embedded-brains.de
Wed Nov 11 11:01:26 UTC 2015
---
.../bspsupport/ppc_exc_async_normal.S | 25 ++++++++++++++++++++
cpukit/score/cpu/arm/arm_exc_interrupt.S | 27 ++++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S
index 59e621f..6a1ea34 100644
--- a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S
@@ -423,6 +423,31 @@ thread_dispatching_done:
#endif
PPC_GPR_LOAD HANDLER_REGISTER, HANDLER_OFFSET(r1)
+ /*
+ * We must clear reservations here, since otherwise compare-and-swap
+ * atomic operations with interrupts enabled may yield wrong results.
+ * A compare-and-swap atomic operation is generated by the compiler
+ * like this:
+ *
+ * .L1:
+ * lwarx r9, r0, r3
+ * cmpw r9, r4
+ * bne- .L2
+ * stwcx. r5, r0, r3
+ * bne- .L1
+ * .L2:
+ *
+ * Consider the following scenario. A thread is interrupted right
+ * before the stwcx. The interrupt updates the value using a
+ * compare-and-swap sequence. Everything is fine up to this point.
+ * The interrupt performs now a compare-and-swap sequence which fails
+ * with a branch to .L2. The current processor has now a reservation.
+ * The interrupt returns without further stwcx. The thread updates the
+ * value using the unrelated reservation of the interrupt.
+ */
+ li SCRATCH_0_REGISTER, HANDLER_OFFSET
+ stwcx. SCRATCH_0_REGISTER, r1, SCRATCH_0_REGISTER
+
/* Restore SRR0, SRR1, CR, CTR, XER, and LR */
mtsrr0 SCRATCH_0_REGISTER
PPC_GPR_LOAD SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
diff --git a/cpukit/score/cpu/arm/arm_exc_interrupt.S b/cpukit/score/cpu/arm/arm_exc_interrupt.S
index 7930c32..fcb1510 100644
--- a/cpukit/score/cpu/arm/arm_exc_interrupt.S
+++ b/cpukit/score/cpu/arm/arm_exc_interrupt.S
@@ -209,6 +209,33 @@ thread_dispatch_done:
/* Restore EXCHANGE_LR and EXCHANGE_SPSR registers from exchange area */
ldmia sp!, {EXCHANGE_LR, EXCHANGE_SPSR}
+#ifdef ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE
+ /*
+ * We must clear reservations here, since otherwise compare-and-swap
+ * atomic operations with interrupts enabled may yield wrong results.
+ * A compare-and-swap atomic operation is generated by the compiler
+ * like this:
+ *
+ * .L1:
+ * ldrex r1, [r0]
+ * cmp r1, r3
+ * bne .L2
+ * strex r3, r2, [r0]
+ * cmp r3, #0
+ * bne .L1
+ * .L2:
+ *
+ * Consider the following scenario. A thread is interrupted right
+ * before the strex. The interrupt updates the value using a
+ * compare-and-swap sequence. Everything is fine up to this point.
+ * The interrupt performs now a compare-and-swap sequence which fails
+ * with a branch to .L2. The current processor has now a reservation.
+ * The interrupt returns without further strex. The thread updates the
+ * value using the unrelated reservation of the interrupt.
+ */
+ clrex
+#endif
+
/* Return from interrupt */
subs pc, lr, #4
--
1.8.4.5
More information about the devel
mailing list