SPM: Use the saved EXC_RETURN payload When returning to the ISR

Save the EXC_RETURN payload into the stack when the deprivileged
FLIH SVC is called. When FLIH function returns, use the saved
EXC_RETURN payload to return to ISR.

Signed-off-by: Chendi Sun <chendi.sun@arm.com>
Change-Id: I1b3a1596903cae0920f9f64be1cdaf6d9a12df99
diff --git a/secure_fw/spm/core/arch/tfm_arch_v6m_v7m.c b/secure_fw/spm/core/arch/tfm_arch_v6m_v7m.c
index b21af9e..85fc224 100644
--- a/secure_fw/spm/core/arch/tfm_arch_v6m_v7m.c
+++ b/secure_fw/spm/core/arch/tfm_arch_v6m_v7m.c
@@ -140,17 +140,19 @@
     "PUSH    {r1, r2}                       \n" /* Orig_exc_return, dummy */
     "BL      spm_svc_handler                \n"
     "MOV     lr, r0                         \n"
-    "POP     {r1, r2}                       \n" /* Orig_exc_return, dummy */
+    "LDR     r1, [sp]                       \n" /* Get orig_exc_return value */
     "MOVS    r2, #8                         \n"
     "ANDS    r0, r2                         \n" /* Mode bit */
     "ANDS    r1, r2                         \n"
-    "POP     {r2, r3}                       \n" /* PSP dummy */
     "SUBS    r0, r1                         \n" /* Compare EXC_RETURN values */
     "BGT     to_flih_func                   \n"
     "BLT     from_flih_func                 \n"
+    "ADD     sp, #16                        \n" /*
+                                                 * "Unstack" unused orig_exc_return, dummy,
+                                                 * PSP, PSPLIM pushed by current handler
+                                                 */
     "BX      lr                             \n"
     "to_flih_func:                          \n"
-    "PUSH    {r2, r3}                       \n" /* PSP dummy */
     "PUSH    {r4-r7}                        \n"
     "MOV     r4, r8                         \n"
     "MOV     r5, r9                         \n"
@@ -172,6 +174,10 @@
     "PUSH    {r4, r5}                       \n" /* Seal stack before EXC_RET */
     "BX      lr                             \n"
     "from_flih_func:                        \n"
+    "ADD     sp, #16                        \n" /*
+                                                 * "Unstack" unused orig_exc_return, dummy,
+                                                 * PSP, PSPLIM pushed by current handler
+                                                 */
     "POP     {r4, r5}                       \n" /* Seal stack */
     "ADD     sp, sp, #8                     \n" /* Dummy data to align SP offset for
                                                  * reserved additional state context,
@@ -183,7 +189,11 @@
     "MOV     r10, r6                        \n"
     "MOV     r11, r7                        \n"
     "POP     {r4-r7}                        \n"
-    "POP     {r1, r2}                       \n" /* PSP dummy */
+    "ADD     sp, #16                        \n" /*
+                                                 * "Unstack" unused orig_exc_return, dummy,
+                                                 * PSP, PSPLIM pushed by the previous
+                                                 * TFM_SVC_PREPARE_DEPRIV_FLIH request
+                                                 */
     "BX      lr                             \n"
     );
 }
diff --git a/secure_fw/spm/core/arch/tfm_arch_v8m_base.c b/secure_fw/spm/core/arch/tfm_arch_v8m_base.c
index b7f9e96..e9127cf 100644
--- a/secure_fw/spm/core/arch/tfm_arch_v8m_base.c
+++ b/secure_fw/spm/core/arch/tfm_arch_v8m_base.c
@@ -173,18 +173,19 @@
     "PUSH    {r1, r2}                       \n" /* Orig_exc_return, dummy */
     "BL      spm_svc_handler                \n"
     "MOV     lr, r0                         \n"
-    "POP     {r1, r2}                       \n" /* Orig_exc_return, dummy */
+    "LDR     r1, [sp]                       \n" /* Get orig_exc_return value */
     "MOVS    r2, #8                         \n"
     "ANDS    r0, r2                         \n" /* Mode bit */
     "ANDS    r1, r2                         \n"
-    "POP     {r2, r3}                       \n" /* PSP PSPLIM */
     "SUBS    r0, r1                         \n" /* Compare EXC_RETURN values */
     "BGT     to_flih_func                   \n"
     "BLT     from_flih_func                 \n"
+    "ADD     sp, #16                        \n" /*
+                                                 * "Unstack" unused orig_exc_return, dummy,
+                                                 * PSP, PSPLIM pushed by current handler
+                                                 */
     "BX      lr                             \n"
     "to_flih_func:                          \n"
-    "PUSH    {r2, r3}                       \n" /* PSP PSPLIM */
-    "PUSH    {r0, r1}                       \n"
     "LDR     r0, ="M2S(EXC_RETURN_DCRS)"    \n" /* Check DCRS */
     "MOV     r1, lr                         \n"
     "ANDS    r0, r1                         \n"
@@ -200,7 +201,6 @@
                                                  * integrity signature
                                                  */
     "v8b_svc_callee_saved:                  \n"
-    "POP     {r0, r1}                       \n"
     "LDR     r4, ="M2S(STACK_SEAL_PATTERN)" \n" /* clear r4-r11 */
     "MOV     r5, r4                         \n"
     "MOV     r6, r4                         \n"
@@ -212,8 +212,11 @@
     "PUSH    {r4, r5}                       \n" /* Seal stack before EXC_RET */
     "BX      lr                             \n"
     "from_flih_func:                        \n"
+    "ADD     sp, #16                        \n" /*
+                                                 * "Unstack" unused orig_exc_return, dummy,
+                                                 * PSP, PSPLIM pushed by current handler
+                                                 */
     "POP     {r4, r5}                       \n" /* Seal stack */
-    "PUSH    {r0, r1}                       \n"
     "LDR     r0, ="M2S(EXC_RETURN_DCRS)"    \n" /* Check DCRS */
     "MOV     r1, lr                         \n"
     "ANDS    r0, r1                         \n"
@@ -229,8 +232,11 @@
     "MOV     r11, r7                        \n"
     "POP     {r4-r7}                        \n"
     "v8b_svc_callee_loaded:                 \n"
-    "POP     {r0, r1}                       \n"
-    "POP     {r1, r2}                       \n" /* PSP PSPLIM */
+    "ADD     sp, #16                        \n" /*
+                                                 * "Unstack" unused orig_exc_return, dummy,
+                                                 * PSP, PSPLIM pushed by the previous
+                                                 * TFM_SVC_PREPARE_DEPRIV_FLIH request
+                                                 */
     "BX      lr                             \n"
     );
 }
diff --git a/secure_fw/spm/core/arch/tfm_arch_v8m_main.c b/secure_fw/spm/core/arch/tfm_arch_v8m_main.c
index 639607d..0bec25f 100644
--- a/secure_fw/spm/core/arch/tfm_arch_v8m_main.c
+++ b/secure_fw/spm/core/arch/tfm_arch_v8m_main.c
@@ -150,16 +150,18 @@
     "PUSH    {r1, r2}                        \n" /* Orig_exc_return, dummy */
     "BL      spm_svc_handler                 \n"
     "MOV     lr, r0                          \n"
-    "POP     {r1, r2}                        \n" /* Orig_exc_return, dummy */
-    "POP     {r2, r3}                        \n" /* PSP PSPLIM */
+    "LDR     r1, [sp]                        \n" /* Get orig_exc_return value */
     "AND     r0, #8                          \n" /* Mode bit */
     "AND     r1, #8                          \n"
     "SUBS    r0, r1                          \n" /* Compare EXC_RETURN values */
     "BGT     to_flih_func                    \n"
     "BLT     from_flih_func                  \n"
+    "ADD     sp, #16                         \n" /*
+                                                  * "Unstack" unused orig_exc_return, dummy,
+                                                  * PSP, PSPLIM pushed by current handler
+                                                  */
     "BX      lr                              \n"
     "to_flih_func:                           \n"
-    "PUSH    {r2, r3}                        \n" /* PSP PSPLIM */
     "ANDS    r3, lr, #"M2S(EXC_RETURN_DCRS)" \n" /* Check DCRS */
     "ITT     ne                              \n" /* Skip saving callee */
     "PUSHNE  {r4-r11}                        \n" /* Save callee */
@@ -178,6 +180,10 @@
     "PUSH    {r4, r5}                        \n" /* Seal stack before EXC_RET */
     "BX      lr                              \n"
     "from_flih_func:                         \n"
+    "ADD     sp, #16                         \n" /*
+                                                  * "Unstack" unused orig_exc_return, dummy,
+                                                  * PSP, PSPLIM pushed by current handler
+                                                  */
     "POP     {r4, r5}                        \n" /* Seal stack */
     "ANDS    r3, lr, #"M2S(EXC_RETURN_DCRS)" \n" /* Check DCRS */
     "ITT     ne                              \n" /* Skip loading callee */
@@ -186,7 +192,11 @@
                                                   * integrity signature
                                                   */
     "POPNE   {r4-r11}                        \n" /* Load callee */
-    "POP     {r1, r2}                        \n" /* PSP PSPLIM */
+    "ADD     sp, #16                         \n" /*
+                                                  * "Unstack" unused orig_exc_return, dummy,
+                                                  * PSP, PSPLIM pushed by the previous
+                                                  * TFM_SVC_PREPARE_DEPRIV_FLIH request
+                                                  */
     "BX      lr                              \n"
     );
 }
diff --git a/secure_fw/spm/core/interrupt.c b/secure_fw/spm/core/interrupt.c
index 88b8f0b..c457ef2 100644
--- a/secure_fw/spm/core/interrupt.c
+++ b/secure_fw/spm/core/interrupt.c
@@ -113,7 +113,7 @@
     /* Set FLIH result to the ISR */
     p_ctx_flih_ret->state_ctx.r0 = (uint32_t)result;
 
-    return EXC_RETURN_HANDLER;
+    return p_ctx_flih_ret->exc_return;
 }
 #endif
 
diff --git a/secure_fw/spm/include/tfm_arch.h b/secure_fw/spm/include/tfm_arch.h
index d19177e..f78e7a3 100644
--- a/secure_fw/spm/include/tfm_arch.h
+++ b/secure_fw/spm/include/tfm_arch.h
@@ -130,11 +130,13 @@
  * It is the same when de-privileged FLIH Function is ready to run.
  */
 struct context_flih_ret_t {
-    uint64_t stack_seal;    /* Two words stack seal */
+    uint64_t stack_seal;                  /* Two words stack seal                              */
     struct tfm_additional_context_t addi_ctx;
-    uint32_t psp;       /* PSP when interrupt exception ocurrs              */
-    uint32_t psplim;    /* PSPLIM when interrupt exception ocurrs when      */
-    struct tfm_state_context_t state_ctx; /* ctx on SVC_PREPARE_DEPRIV_FLIH */
+    uint32_t exc_return;                  /* exception return value on SVC_PREPARE_DEPRIV_FLIH */
+    uint32_t dummy;                       /* dummy value for 8 bytes aligned                   */
+    uint32_t psp;                         /* PSP when interrupt exception ocurrs               */
+    uint32_t psplim;                      /* PSPLIM when interrupt exception ocurrs when       */
+    struct tfm_state_context_t state_ctx; /* ctx on SVC_PREPARE_DEPRIV_FLIH                    */
 };
 
 /* Assign stack and stack limit to the context control instance. */