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/exception-model/exception-entry-and-return )

 

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.
  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!

 

 

************* MEDIATEK Confidentiality Notice
 ********************
The information contained in this e-mail message (including any 
attachments) may be confidential, proprietary, privileged, or otherwise
exempt from disclosure under applicable laws. It is intended to be 
conveyed only to the designated recipient(s). Any use, dissemination, 
distribution, printing, retaining or copying of this e-mail (including its 
attachments) by unintended recipient(s) is strictly prohibited and may 
be unlawful. If you are not an intended recipient of this e-mail, or believe
 
that you have received this e-mail in error, please notify the sender 
immediately (by replying to this e-mail), delete any and all copies of 
this e-mail (including any attachments) from your system, and do not
disclose the content of this e-mail to any other person. Thank you!