PowerPC FP handling weakness.
Duncan Smith
dds at flavors.com
Wed Oct 11 07:58:27 UTC 2000
At 12:30 PM +0400 10/2/00, Sergei Organov wrote:
>Duncan Smith <dds at flavors.com> writes:
>[...]
>> At Flavors we have been using RTEMS for 4 or 5 years on 604/604e MPC105/106,
>> VME boards. Although the version we use is an old one, the BSP requirement
>> is probably similar.
>>
>> In our own BSP we do lazy FPU context switching based on actual use of FP
>> through the FP fault.
>>
>
>As an exercise I also implemented similar FPU context switching for another
>RTOS, and have faced with one subtle problem. The FP enable and interrupts
>enable bits are in the same MSR register. When on-demand context switch is
>used, the FP bit in MSR can be cleared any time if scheduling is enabled. This
>fact makes it impossible to use _ISR_Disable/_ISR_Enable pair in the form they
>are now, because the value of FP bit could be lost: _ISR_Disable reads MSR
>with FP bit set, then interrupts/context switches occur that clear FP bit,
>then interrupts are disabled by writing MSR with old value with cleared
>interrupts bit but set FP bit (here the right value of FP bit is lost), then
>FP instruction is executed and clobbers FP context owned by different task.
>
>One solution to the problem is to always clear FP bit in _ISR_Disable. This
>can lead to unnecessary FP context switches though.
>
>How did you solve the problem?
>
>BR,
>Sergei.
Sorry for the delay. I am out of town most of the time, and don't
check this stuff very often...
Here is the part of our SC handler for Enable/Disable interrupts.
Actually this only used for Disable...
#
###############################################################################
#
# System Call (0xc00) Level 0
#
# Exactly 64 words (max.) -dds 96-02-15
#
# Because the FP bit can be modified at any time due to an enabled
# External Exception, it is necessary that MFMSR/MTMSR used to clear
# the EE bit be atomic. To satisfy this we use the System Call Exception
# The protocol is:
# Bit 31 of R3 is inserted into MSR( EE ), Bits 0-30 of
R3 must be zero.
# Previous MSR( EE ) is returned in Bit 31 of R3, Bits
0-30 of R3 are cleared.
# R4 and R5 are destroyed.
#
# 0,1 - Bit to EE
#
csect _SC_Handler{RW}
export _SC_Handler{RW}
# SC Handler
dc.l _L0_SC_Handler{PR}
dc.l (_L0_SC_Handler_End - _L0_SC_Handler{PR}) >> 2
dc.l 0x0c00
dc.l 2
dc.l (_L0_SC_Cell_Done_LISORI - _L0_SC_Handler{PR}) >> 1
dc.l _L1_CS_Done
dc.l (_L0_SC_Cell_Timeout_LISORI - _L0_SC_Handler{PR}) >> 1
dc.l _L1_CS_Timeout
csect _L0_SC_Handler{PR}
export _L0_SC_Handler{PR}
cmplwi r3,1
bgt- _L0_SC_Cell
mfsrr1 r4 #Get MSR
extrwi r5,r4,1,16 #Extract EE bit
insrwi r4,r3,1,16 #Insert new EE bit
mtsrr1 r4 #Put MSR
mr r3,r5 #Copy result
rfi #Get done
---------------------------------------
The junk at the top of the csect is a linkage table used to copy
level 0 interrupt handlers to their low memory addresses, and to set
up the crawlouts to the level 1 handlers:
FYI, e.g. this is a LISORI and crawlout...:
mfsrr0 r5
mfsrr1 r6
ori r7,r6,MSR_EE|MSR_FP
mtsrr1 r7 #Put MSR
_L0_SC_Cell_Timeout_LISORI:
lis r7,0
ori r7,r7,0
mtsrr0 r7
rfi
#Transfer to Level 1
_L0_SC_Handler_End:
---------------------------------------
/*
* rtems_interrupt_disable
*
* DESCRIPTION:
*
* This routine disables all maskable interrupts and returns the
* previous level in _isr_cookie.
*/
#define rtems_interrupt_disable( _isr_cookie ) \
_ISR_Disable(_isr_cookie)
/*
* rtems_interrupt_enable
*
* DESCRIPTION:
*
* This routine enables maskable interrupts to the level indicated
* _isr_cookie.
*/
#define rtems_interrupt_enable( _isr_cookie ) \
_ISR_Enable(_isr_cookie)
/*
* rtems_interrupt_flash
*
* DESCRIPTION:
*
* This routine temporarily enables maskable interrupts to the
* level in _isr_cookie before redisabling them.
*/
#define rtems_interrupt_flash( _isr_cookie ) \
_ISR_Flash(_isr_cookie)
-------------------------------------
/*
* _ISR_Disable
*
* DESCRIPTION:
*
* This routine disables all interrupts so that a critical section
* of code can be executing without being interrupted. Upon return,
* the argument _level will contain the previous interrupt mask level.
*/
#define _ISR_Disable( _level ) \
_CPU_ISR_Disable( _level )
/*
* _ISR_Enable
*
* DESCRIPTION:
*
* This routine enables interrupts to the previous interrupt mask
* LEVEL. It is used at the end of a critical section of code to
* enable interrupts so they can be processed again.
*/
#define _ISR_Enable( _level ) \
_CPU_ISR_Enable( _level )
/*
* _ISR_Flash
*
* DESCRIPTION:
*
* This routine temporarily enables interrupts to the previous
* interrupt mask level and then disables all interrupts so that
* the caller can continue into the second part of a critical
* section. This routine is used to temporarily enable interrupts
* during a long critical section. It is used in long sections of
* critical code when a point is reached at which interrupts can
* be temporarily enabled. Deciding where to flash interrupts
* in a long critical section is often difficult and the point
* must be selected with care to insure that the critical section
* properly protects itself.
*/
#define _ISR_Flash( _level ) \
_CPU_ISR_Flash( _level )
-------------------------------------
/*
* Disable all interrupts for an RTEMS critical section. The previous
* level is returned in _level.
*/
#define _CPU_ISR_Disable( _isr_cookie ) \
{ \
(_isr_cookie) = __sc( 0 ); \
}
/*
* Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
* This indicates the end of an RTEMS critical section. The parameter
* _level is not modified.
*/
#define _CPU_ISR_Enable( _isr_cookie ) \
{ \
__mtmsr_isr_cookie( __mfmsr(), (_isr_cookie) ); \
}
/*
* This temporarily restores the interrupt to _level before immediately
* disabling them again. This is used to divide long RTEMS critical
* sections into two or more parts. The parameter _level is not
* modified.
*/
#define _CPU_ISR_Flash( _isr_cookie ) \
{ \
__mtmsr_isr_cookie( __mfmsr(), (_isr_cookie) ); \
__sc( 0 ); \
}
---------------------------------------
These get inlined by our Builder(locator):
...
.__mfmsr:
mfmsr r3
blr
.__mtmsr:
mtmsr r3
blr
...
.__mtmsr_isr_cookie:
insrwi r3,r4,1,16 #Insert new EE bit
mtmsr r3
blr
...
# Other
.__sc: sc
blr
More information about the users
mailing list