summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu
diff options
context:
space:
mode:
authorTill Straumann <strauman@slac.stanford.edu>2008-07-16 21:44:14 +0000
committerTill Straumann <strauman@slac.stanford.edu>2008-07-16 21:44:14 +0000
commit5166513cf5de6eaf65601b8c6540fedacf379488 (patch)
tree8ddd17ba3c6781334a160355182ba5cc51fafd68 /c/src/lib/libcpu
parent2008-07-16 Till Straumann <strauman@slac.stanford.edu> (diff)
downloadrtems-5166513cf5de6eaf65601b8c6540fedacf379488.tar.bz2
2008-07-16 Till Straumann <strauman@slac.stanford.edu>
* new-exceptions/bspsupport/ppc_exc_asm_macros.h: Added a test to TEST_LOCK_crit so that a context switch is always prevented if MSR_CE is not set in the interrupt mask. (Support mode where the user wants to leave MSR_CE always enabled but abstains from calling OS primitives from the exception handler.)
Diffstat (limited to 'c/src/lib/libcpu')
-rw-r--r--c/src/lib/libcpu/powerpc/ChangeLog9
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h36
2 files changed, 35 insertions, 10 deletions
diff --git a/c/src/lib/libcpu/powerpc/ChangeLog b/c/src/lib/libcpu/powerpc/ChangeLog
index 29803fec08..4967927206 100644
--- a/c/src/lib/libcpu/powerpc/ChangeLog
+++ b/c/src/lib/libcpu/powerpc/ChangeLog
@@ -1,5 +1,14 @@
2008-07-16 Till Straumann <strauman@slac.stanford.edu>
+ * new-exceptions/bspsupport/ppc_exc_asm_macros.h: Added
+ a test to TEST_LOCK_crit so that a context switch is
+ always prevented if MSR_CE is not set in the interrupt mask.
+ (Support mode where the user wants to leave MSR_CE always enabled
+ but abstains from calling OS primitives from the exception
+ handler.)
+
+2008-07-16 Till Straumann <strauman@slac.stanford.edu>
+
* shared/include/powerpc-utility.h: Added
GET_INTERRUPT_MASK macro.
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h
index 106e73bd6d..9739bf76df 100644
--- a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h
@@ -140,9 +140,9 @@ ppc_exc_min_prolog_sync_\_NAME:
* MACRO: TEST_1ST_OPCODE_crit
*****************************************************************************
*
- * USES: REG, CR_LOCK
+ * USES: REG, cr0
* ON EXIT: REG available (contains *pc - STW_R1_R13(0)),
- * return value in CR_LOCK.
+ * return value in cr0.
*
* test opcode interrupted by critical (asynchronous) exception; set CR_LOCK if
*
@@ -161,7 +161,7 @@ ppc_exc_min_prolog_sync_\_NAME:
* if what's left compares against the 'ppc_exc_lock_std@sdarel'
* address offset then we have a match...
*/
- cmpli CR_LOCK, \_REG, ppc_exc_lock_std@sdarel
+ cmplwi cr0, \_REG, ppc_exc_lock_std@sdarel
.endm
@@ -190,11 +190,19 @@ ppc_exc_min_prolog_sync_\_NAME:
*
* critical-exception wrapper has to check 'std' lock:
*
- * Return CR_LOCK = ( ppc_lock_std == 0
+ * Return CR_LOCK = ( (interrupt_mask & MSR_CE) != 0
+ && ppc_lock_std == 0
* && * SRR0 != <write std lock instruction> )
*
*/
.macro TEST_LOCK_crit _FLVR
+ /* If MSR_CE is not in the IRQ mask then we must never allow
+ * thread-dispatching!
+ */
+ GET_INTERRUPT_MASK mask=SCRATCH_REGISTER_1
+ /* EQ(cr0) = ((interrupt_mask & MSR_CE) == 0) */
+ andis. SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, MSR_CE@h
+ beq TEST_LOCK_crit_done_\_FLVR
/* STD interrupt could have been interrupted before executing the 1st
* instruction which sets the lock; check this case by looking at the
@@ -202,7 +210,7 @@ ppc_exc_min_prolog_sync_\_NAME:
*/
TEST_1ST_OPCODE_crit _REG=SCRATCH_REGISTER_0
/*
- * At this point CR_LOCK is set if
+ * At this point cr0 is set if
*
* *(PC) == 'stw r1, ppc_exc_lock_std@sdarel(r13)'
*
@@ -210,13 +218,21 @@ ppc_exc_min_prolog_sync_\_NAME:
/* check lock */
lwz SCRATCH_REGISTER_1, ppc_exc_lock_std@sdarel(r13)
- cmpli cr0, SCRATCH_REGISTER_1, 0
- /*
+ cmplwi CR_LOCK, SCRATCH_REGISTER_1, 0
+
+ /* set EQ(CR_LOCK) to result */
+TEST_LOCK_crit_done_\_FLVR:
+ /* If we end up here because the interrupt mask did not contain
+ * MSR_CE then cr0 is set and therefore the value of CR_LOCK
+ * does not matter since x && !1 == 0:
*
- * CR_LOCK = ( *pc != <write std lock instruction>
- * && ppc_exc_lock_std == 0 )
+ * if ( (interrupt_mask & MSR_CE) == 0 ) {
+ * EQ(CR_LOCK) = EQ(CR_LOCK) && ! ((interrupt_mask & MSR_CE) == 0)
+ * } else {
+ * EQ(CR_LOCK) = (ppc_exc_lock_std == 0) && ! (*pc == <write std lock instruction>)
+ * }
*/
- crandc EQ(CR_LOCK), EQ(cr0), EQ(CR_LOCK)
+ crandc EQ(CR_LOCK), EQ(CR_LOCK), EQ(cr0)
.endm