freertos(SMP): Fix SMP FreeRTOS Xtensa port FPU/Coproccessor bugs

This commit fixes the following FPU/Coprocessor bugs in the Xtensa port of
Amazon SMP FreeRTOS:

- vPortCleanUpCoprocArea() does not calculate the correct pointer to the
task's CPSA (located on the task's stack). This can result in
    - _xt_coproc_release() not releasing the task's CP ownership
    - The next coprocessor exception will write the current CP owner (i.e., the
      deleted task's CPSA) leading to memory corruption
- _xt_coproc_release() writes xCoreID instead of 0 when clearing a CP owner.
  This results in the next CP exception trying to load the CP owner's CPSA at
  the address of "xCoreID", leading to a double exception.
This commit is contained in:
Darian Leung 2022-12-03 00:14:17 +08:00
parent 4934487be4
commit fd48daf278
2 changed files with 9 additions and 9 deletions

View File

@ -721,21 +721,21 @@ void _xt_coproc_release(volatile void *coproc_sa_base, BaseType_t xCoreID);
void vPortCleanUpCoprocArea( void *pxTCB )
{
StackType_t *coproc_area;
UBaseType_t uxCoprocArea;
BaseType_t xCoreID;
/* Calculate the coproc save area in the stack from the TCB base */
coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxTCB + offset_pxEndOfStack ));
coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
coproc_area = ( StackType_t * ) ( ( ( uint32_t ) coproc_area - XT_CP_SIZE ) & ~0xf );
/* Get pointer to the task's coprocessor save area from TCB->pxEndOfStack. See uxInitialiseStackCPSA() */
uxCoprocArea = ( UBaseType_t ) ( ( ( StaticTask_t * ) pxTCB )->pxDummy8 ); /* Get TCB_t.pxEndOfStack */
uxCoprocArea = STACKPTR_ALIGN_DOWN(16, uxCoprocArea - XT_CP_SIZE);
/* Extract core ID from the affinity mask */
xCoreID = __builtin_ffs( * ( UBaseType_t * ) ( pxTCB + offset_uxCoreAffinityMask ) );
assert( xCoreID >= 1 );
xCoreID = ( ( StaticTask_t * ) pxTCB )->uxDummy25 ;
xCoreID = ( BaseType_t ) __builtin_ffs( ( int ) xCoreID );
assert( xCoreID >= 1 ); // __builtin_ffs always returns first set index + 1
xCoreID -= 1;
/* If task has live floating point registers somewhere, release them */
_xt_coproc_release( coproc_area, xCoreID );
_xt_coproc_release( (void *)uxCoprocArea, xCoreID );
}
#endif // ( XCHAL_CP_NUM > 0 && configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )

View File

@ -449,7 +449,7 @@ _xt_coproc_release:
1: l32i a8, a4, 0 /* a8 = owner at a4 */
bne a2, a8, 2f /* if (coproc_sa_base == owner) */
s32i a3, a4, 0 /* owner = unowned */
s32i a6, a4, 0 /* owner = unowned */
2: addi a4, a4, 1<<2 /* a4 = next entry in owner array */
bltu a4, a5, 1b /* repeat until end of array */