arch: arm: aarch32: initialize FPSCR to reset value for ARMv8.1

With GCC 11 now supporting low overhead branching in ARMv8.1, ASM "LE"
(loop-end) instructions would trigger an INVSTATE hard-fault after
FPSCR was set to 0. This was due to the FPSCR getting a new field in
ARMv8.1. LTPSIZE is now set to it's reset value of Tail predication not
applied.

Signed-off-by: Ryan McClelland <ryanmcclelland@fb.com>
This commit is contained in:
Ryan McClelland 2022-04-12 00:35:41 -07:00 committed by Marti Bolivar
commit f7ddcd2713
3 changed files with 24 additions and 0 deletions

View file

@ -144,7 +144,15 @@ static inline void z_arm_floating_point_init(void)
__ISB();
/* Initialize the Floating Point Status and Control Register. */
#if defined(CONFIG_ARMV8_1_M_MAINLINE)
/*
* For ARMv8.1-M with FPU, the FPSCR[18:16] LTPSIZE field must be set
* to 0b100 for "Tail predication not applied" as it's reset value
*/
__set_FPSCR(4 << FPU_FPDSCR_LTPSIZE_Pos);
#else
__set_FPSCR(0);
#endif
/*
* Note:

View file

@ -499,7 +499,15 @@ static void z_arm_prepare_switch_to_main(void)
* Unshared FP Registers mode (In Shared FP Registers mode, FPSCR is
* initialized at thread creation for threads that make use of the FP).
*/
#if defined(CONFIG_ARMV8_1_M_MAINLINE)
/*
* For ARMv8.1-M with FPU, the FPSCR[18:16] LTPSIZE field must be set
* to 0b100 for "Tail predication not applied" as it's reset value
*/
__set_FPSCR(4 << FPU_FPDSCR_LTPSIZE_Pos);
#else
__set_FPSCR(0);
#endif
#if defined(CONFIG_FPU_SHARING)
/* In Sharing mode clearing FPSCR may set the CONTROL.FPCA flag. */
__set_CONTROL(__get_CONTROL() & (~(CONTROL_FPCA_Msk)));

View file

@ -197,7 +197,15 @@ void arm_isr_handler(const void *args)
* to prevent from having the interrupt line set to pending again,
* in case FPU IRQ is selected by the test as "Available IRQ line"
*/
#if defined(CONFIG_ARMV8_1_M_MAINLINE)
/*
* For ARMv8.1-M with FPU, the FPSCR[18:16] LTPSIZE field must be set
* to 0b100 for "Tail predication not applied" as it's reset value
*/
__set_FPSCR(4 << FPU_FPDSCR_LTPSIZE_Pos);
#else
__set_FPSCR(0);
#endif
#endif
test_flag++;