Core: Clear FP status before SPM initialization

Float point (FP) is forbidden during SPM initialization, clear it
before handler mode SPM initialization. And return the generic
EXC_RETURN for subsequent thread scheduling.

The usage of FP is still valid before SPM initialization and
the subsequent thread execution, just do not happen during SPM
initialization.

Change-Id: I48d7bd0f140cb1c933cdd621d598446cb81eaee3
Signed-off-by: Ken Liu <ken.liu@arm.com>
diff --git a/secure_fw/core/arch/include/tfm_arch.h b/secure_fw/core/arch/include/tfm_arch.h
index eb5f387..c65eb21 100644
--- a/secure_fw/core/arch/include/tfm_arch.h
+++ b/secure_fw/core/arch/include/tfm_arch.h
@@ -97,4 +97,9 @@
  */
 void tfm_arch_prioritize_secure_exception(void);
 
+/*
+ * Clear float point status.
+ */
+void tfm_arch_clear_fp_status(void);
+
 #endif
diff --git a/secure_fw/core/arch/tfm_arch_v6m_v7m.c b/secure_fw/core/arch/tfm_arch_v6m_v7m.c
index 494c14f..5cb111d 100644
--- a/secure_fw/core/arch/tfm_arch_v6m_v7m.c
+++ b/secure_fw/core/arch/tfm_arch_v6m_v7m.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -137,3 +137,22 @@
 void tfm_arch_prioritize_secure_exception(void)
 {
 }
+
+/* There is no FPCA in v6m */
+#ifndef __ARM_ARCH_6M__
+__attribute__((naked, noinline)) void tfm_arch_clear_fp_status(void)
+{
+    __ASM volatile(
+                   ".syntax unified          \n"
+                   "mrs  r0, control         \n"
+                   "bics r0, r0, #4          \n"
+                   "msr  control, r0         \n"
+                   "isb                      \n"
+                   "bx   lr                  \n"
+                  );
+}
+#else
+void tfm_arch_clear_fp_status(void)
+{
+}
+#endif
diff --git a/secure_fw/core/arch/tfm_arch_v8m_base.c b/secure_fw/core/arch/tfm_arch_v8m_base.c
index 764955f..d04d498 100644
--- a/secure_fw/core/arch/tfm_arch_v8m_base.c
+++ b/secure_fw/core/arch/tfm_arch_v8m_base.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -234,3 +234,8 @@
                  VECTKEY |
                  (AIRCR & ~SCB_AIRCR_VECTKEY_Msk);
 }
+
+/* There is no FPCA in baseline. */
+void tfm_arch_clear_fp_status(void)
+{
+}
diff --git a/secure_fw/core/arch/tfm_arch_v8m_main.c b/secure_fw/core/arch/tfm_arch_v8m_main.c
index 3bd69bd..503e9c1 100644
--- a/secure_fw/core/arch/tfm_arch_v8m_main.c
+++ b/secure_fw/core/arch/tfm_arch_v8m_main.c
@@ -224,3 +224,15 @@
                  VECTKEY |
                  (AIRCR & ~SCB_AIRCR_VECTKEY_Msk);
 }
+
+__attribute__((naked, noinline)) void tfm_arch_clear_fp_status(void)
+{
+    __ASM volatile(
+                   ".syntax unified          \n"
+                   "mrs  r0, control         \n"
+                   "bics r0, r0, #4          \n"
+                   "msr  control, r0         \n"
+                   "isb                      \n"
+                   "bx   lr                  \n"
+                  );
+}
diff --git a/secure_fw/core/tfm_core_svcalls_ipc.c b/secure_fw/core/tfm_core_svcalls_ipc.c
index 0d66752..5d7e317 100644
--- a/secure_fw/core/tfm_core_svcalls_ipc.c
+++ b/secure_fw/core/tfm_core_svcalls_ipc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -7,6 +7,7 @@
 
 #include <string.h>
 #include "tfm_api.h"
+#include "tfm_arch.h"
 #include "tfm_internal.h"
 #include "core/tfm_core_svc.h"
 #include "tfm_utils.h"
@@ -35,7 +36,8 @@
     }
     switch (svc_number) {
     case TFM_SVC_HANDLER_MODE:
-        tfm_spm_init();
+        tfm_arch_clear_fp_status();
+        exc_return = tfm_spm_init();
         break;
     case TFM_SVC_GET_BOOT_DATA:
         tfm_core_get_boot_data_handler(svc_args);
diff --git a/secure_fw/spm/spm_api.h b/secure_fw/spm/spm_api.h
index d7d0e7d..fbcda09 100644
--- a/secure_fw/spm/spm_api.h
+++ b/secure_fw/spm/spm_api.h
@@ -681,8 +681,11 @@
  * \brief                      SPM initialization implementation
  *
  * \details                    This function must be called under handler mode.
+ * \retval                     This function returns an EXC_RETURN value. Other
+ *                             faults would panic the execution and never
+ *                             returned.
  */
-void tfm_spm_init(void);
+uint32_t tfm_spm_init(void);
 
 #endif /* ifdef(TFM_PSA_API) */
 
diff --git a/secure_fw/spm/spm_api_ipc.c b/secure_fw/spm/spm_api_ipc.c
index dc27023..38ab043 100644
--- a/secure_fw/spm/spm_api_ipc.c
+++ b/secure_fw/spm/spm_api_ipc.c
@@ -510,7 +510,7 @@
 
 /********************** SPM functions for thread mode ************************/
 
-void tfm_spm_init(void)
+uint32_t tfm_spm_init(void)
 {
     uint32_t i, j, num;
     struct spm_partition_desc_t *partition;
@@ -615,6 +615,8 @@
      * the scheduler that the current thread is non-secure entry thread.
      */
     tfm_thrd_start_scheduler(p_ns_entry_thread);
+
+    return p_ns_entry_thread->state_ctx.ctxb.lr;
 }
 
 void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb)