Files
rtems/cpukit
Sebastian Huber e74cea4172 arm: Fix Armv7-M floating-point support
The _ARMV7M_Pendable_service_call() and _ARMV7M_Supervisor_call() work
as a team. The --ef and ++ef is there to preserve the original exception
frame across the jump to and from _ARMV7M_Thread_dispatch().

void _ARMV7M_Pendable_service_call( void )
{
   Per_CPU_Control *cpu_self = _Per_CPU_Get();

   /*
    * We must check here if a thread dispatch is allowed.  Right after a
    * "msr basepri_max, %[basepri]" instruction an interrupt service may
still
    * take place.  However, pendable service calls that are activated during
    * this interrupt service may be delayed until interrupts are enable
again.
    */
   if (
     ( cpu_self->isr_nest_level |
cpu_self->thread_dispatch_disable_level ) == 0
   ) {
     ARMV7M_Exception_frame *ef;

     cpu_self->isr_nest_level = 1;

     _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVCLR;
     _ARMV7M_Trigger_lazy_floating_point_context_save();

At this point, the floating point context should be saved on the
exception frame.  The FPCCR.LSPACT bit should be 0, to indicate that lazy
state preservation is no longer active.

     ef = (ARMV7M_Exception_frame *) _ARMV7M_Get_PSP();
     --ef;
     _ARMV7M_Set_PSP( (uint32_t) ef );

This new exception frame is just there to jump to
_ARMV7M_Thread_dispatch(). Here was the problem, that FPCCR.LSPACT was
not set to 1.  This resulted in a floating-point context from
uninitialized memory which could corrupt the floating-point state.  See
also:

https://developer.arm.com/documentation/ddi0403/d/System-Level-Architecture/System-Level-Programmers--Model/ARMv7-M-exception-model/Exception-return-behavior?lang=en

     /*
      * According to "ARMv7-M Architecture Reference Manual" section B1.5.6
      * "Exception entry behavior" the return address is half-word aligned.
      */
     ef->register_pc = (void *)
       ((uintptr_t) _ARMV7M_Thread_dispatch & ~((uintptr_t) 1));

     ef->register_xpsr = 0x01000000U;
   }
}

Close #4923.
2024-05-22 01:46:00 +00:00
..
2024-02-16 09:32:04 +01:00
2024-02-16 09:32:04 +01:00
2024-02-16 09:32:04 +01:00
2023-12-19 08:03:42 +01:00
2023-10-13 19:02:15 -05:00