Hello TFM owners,
I would like to report an issue for ARMv8-MAIN in TFM.
From GCC9, it may use FPU registers (S16~S31) to backup general purpose registers for better performance. However, TFM’s library mode is not backup and restore FPU registers (S16~S31) base on EXC_RETURN.FType bit in tfm_core_sfn_request. (Reference for LR.FType https://developer.arm.com/documentation/100235/0004/the-cortex-m33-processor... )
This may causes FPU registers (S16~S31) to be corrupted in tfm_core_sfn_request, if interrupt happens between two SVC call.
Here is an example to reproduce the issue:
1. Task A uses FPU S16 register to backup GPR R0 2. Task A calls psa_import_key() API 3. After the instruction “SVC %[SVC_REQ]” in tfm_core_sfn_request, the CONTROL.FPCA become “NOT active” 4. Enter FreeRTOS PendSV_Handler and schedule to others task.
* Originally, this should backup S16 due to CONTROL.FPCA is active and EXC_RETURN.FType should be 0. * But, the EXC_RETURN.FType become 1 due to step3. So the S16 is not backup in stack and changed by others task.
1. Another task uses FPU S16 register (overwrite the value of S16 from Task A) 2. Enter FreeRTOS PendSV_Handler and schedule back to Task A 3. psa_import_key is finished and exit from TFM 4. Task A restore GPR R0 from FPU R16 5. Memory access violation in Task A due to incorrect value of GPR R0.
Stacking FPU s16-s31 in tfm_core_sfn_request can fix this problem. Please check the blue instructions. Thank you.
__attribute__((section("SFN"), naked)) int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr) { __ASM volatile( "PUSH {r4-r12, lr} \n" "MRS r4, control \n" /* Check FPCA in control register */ "TST r4, #0x04 \n" "IT NE \n" /* Stacking S16-S31, if CONTROL.FPCA = 1 */ "VSTMDBNE sp!, {s16-s31} \n" "PUSH {r4} \n" /* Backup CONTROL register */ "PUSH {r4} \n" /* For 8-bytes alignment to prevent xPSR.BIT9 = 1 */ "SVC %[SVC_REQ] \n" /* To remove upon instruction, xPSR.BIT9 should be masked to 0 in prepare_partition_iovec_ctx(…) */ "MOV r4, #0 \n" "MOV r5, r4 \n" "MOV r6, r4 \n" "MOV r7, r4 \n" "MOV r8, r4 \n" "MOV r9, r4 \n" "MOV r10, r4 \n" "MOV r11, r4 \n" "BLX lr \n" "SVC %[SVC_RET] \n" "POP {r4} \n" /* Restore CONTROL register */ "POP {r4} \n" "TST r4, #0x04 \n" /* Check FPCA in control register */ "IT NE \n" "VLDMIANE sp!, {s16-s31} \n" /* Restore S16-S31, if CONTROL.FPCA = 1 */ "POP {r4-r12, pc} \n" : : [SVC_REQ] "I" (TFM_SVC_SFN_REQUEST), [SVC_RET] "I" (TFM_SVC_SFN_RETURN) ); }
Best regards!