diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-11-11 11:49:45 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-11-17 07:47:31 +0100 |
commit | 0c9bf40b89cd6763f9ec5d913d440c8b0074a092 (patch) | |
tree | 04cba2fa026fd198cfa00a172b7c7357293d2d11 /c | |
parent | libblock: Avoid NULL pointer access (diff) | |
download | rtems-0c9bf40b89cd6763f9ec5d913d440c8b0074a092.tar.bz2 |
Fix interrupt epilogue for ARMv7-AR and PowerPC
Close #2470.
Diffstat (limited to 'c')
-rw-r--r-- | c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S | 51 |
1 files changed, 38 insertions, 13 deletions
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 59e621f64f..0e71dad93c 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 @@ -29,29 +29,29 @@ #define SCRATCH_5_REGISTER r12 #define FRAME_REGISTER r14 -#define VECTOR_OFFSET(reg) GPR4_OFFSET(reg) -#define SELF_CPU_OFFSET(reg) GPR5_OFFSET(reg) -#define ISR_NEST_OFFSET(reg) GPR6_OFFSET(reg) -#define DISPATCH_LEVEL_OFFSET(reg) GPR7_OFFSET(reg) -#define HANDLER_OFFSET(reg) GPR8_OFFSET(reg) -#define SCRATCH_0_OFFSET(reg) GPR0_OFFSET(reg) -#define SCRATCH_1_OFFSET(reg) GPR3_OFFSET(reg) -#define SCRATCH_2_OFFSET(reg) GPR9_OFFSET(reg) -#define SCRATCH_3_OFFSET(reg) GPR10_OFFSET(reg) -#define SCRATCH_4_OFFSET(reg) GPR11_OFFSET(reg) -#define SCRATCH_5_OFFSET(reg) GPR12_OFFSET(reg) +#define VECTOR_OFFSET GPR4_OFFSET +#define SELF_CPU_OFFSET GPR5_OFFSET +#define ISR_NEST_OFFSET GPR6_OFFSET +#define DISPATCH_LEVEL_OFFSET GPR7_OFFSET +#define HANDLER_OFFSET GPR8_OFFSET +#define SCRATCH_0_OFFSET GPR0_OFFSET +#define SCRATCH_1_OFFSET GPR3_OFFSET +#define SCRATCH_2_OFFSET GPR9_OFFSET +#define SCRATCH_3_OFFSET GPR10_OFFSET +#define SCRATCH_4_OFFSET GPR11_OFFSET +#define SCRATCH_5_OFFSET GPR12_OFFSET /* * The register 2 slot is free, since this is the read-only small data anchor. */ -#define FRAME_OFFSET(reg) GPR2_OFFSET(reg) +#define FRAME_OFFSET GPR2_OFFSET #ifdef RTEMS_PROFILING /* * The PPC_EXC_MINIMAL_FRAME_SIZE is enough to store this additional register. */ #define ENTRY_INSTANT_REGISTER r15 -#define ENTRY_INSTANT_OFFSET(reg) GPR13_OFFSET(reg) +#define ENTRY_INSTANT_OFFSET GPR13_OFFSET .macro GET_TIME_BASE REG #ifdef ppc8540 @@ -399,6 +399,31 @@ thread_dispatching_done: evldd HANDLER_REGISTER, PPC_EXC_ACC_OFFSET(r1) #endif + /* + * 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, FRAME_OFFSET + stwcx. SCRATCH_0_REGISTER, r1, SCRATCH_0_REGISTER + /* Load SRR0, SRR1, CR, CTR, XER, and LR */ lwz SCRATCH_0_REGISTER, SRR0_FRAME_OFFSET(r1) lwz SCRATCH_1_REGISTER, SRR1_FRAME_OFFSET(r1) |