diff options
author | Till Straumann <strauman@slac.stanford.edu> | 2008-07-16 21:44:14 +0000 |
---|---|---|
committer | Till Straumann <strauman@slac.stanford.edu> | 2008-07-16 21:44:14 +0000 |
commit | 5166513cf5de6eaf65601b8c6540fedacf379488 (patch) | |
tree | 8ddd17ba3c6781334a160355182ba5cc51fafd68 /c/src | |
parent | 2008-07-16 Till Straumann <strauman@slac.stanford.edu> (diff) | |
download | rtems-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')
-rw-r--r-- | c/src/lib/libcpu/powerpc/ChangeLog | 9 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h | 36 |
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 |