Test: Add FP test cases
1. Enable FP support for test framework.
2. Adding FP service partition for FPU test.
3. Adding test cases in TFM_SP_SECURE_TEST_PARTITION partition to
verify FP context protection.
4. Separate qcbor, t_cose for SPE and NSPE.
Note:
FPU is used by SPE only, NSPE is not allowed to use FPU at current
stage.
Change-Id: I703cac5b3fc8e8c0840babb7af16fa346b5d2c95
Signed-off-by: Feder Liang <Feder.Liang@arm.com>
diff --git a/test/config/check_config.cmake b/test/config/check_config.cmake
index 41f2c0b..171f6d2 100644
--- a/test/config/check_config.cmake
+++ b/test/config/check_config.cmake
@@ -34,6 +34,7 @@
message(STATUS "TEST_S_PLATFORM is set as ${TEST_S_PLATFORM}")
message(STATUS "TEST_S_FWU is set as ${TEST_S_FWU}")
message(STATUS "TEST_S_IPC is set as ${TEST_S_IPC}")
+message(STATUS "TEST_S_FPU is set as ${TEST_S_FPU}")
message(STATUS "---------- Display TEST Configuration - stop ---------------")
@@ -47,6 +48,8 @@
tfm_invalid_config(NOT TFM_PARTITION_FIRMWARE_UPDATE AND (TEST_NS_FWU OR TEST_S_FWU))
tfm_invalid_config(NOT TFM_PARTITION_AUDIT_LOG AND (TEST_NS_AUDIT OR TEST_S_AUDIT))
tfm_invalid_config((TFM_LIB_MODEL) AND (TEST_NS_IPC OR TEST_S_IPC OR TEST_NS_SLIH_IRQ OR TEST_NS_FLIH_IRQ))
+tfm_invalid_config(CONFIG_TFM_SPE_FP STREQUAL "0" AND TEST_S_FPU)
+tfm_invalid_config(TFM_LIB_MODEL AND TEST_S_FPU)
tfm_invalid_config((NOT TFM_MULTI_CORE_TOPOLOGY) AND TEST_NS_MULTI_CORE)
tfm_invalid_config(TEST_NS_T_COSE AND SYMMETRIC_INITIAL_ATTESTATION)
tfm_invalid_config((NOT TFM_NS_MANAGE_NSID) AND TEST_NS_MANAGE_NSID)
diff --git a/test/config/default_s_test_config.cmake b/test/config/default_s_test_config.cmake
index 4a38da7..b2a8575 100644
--- a/test/config/default_s_test_config.cmake
+++ b/test/config/default_s_test_config.cmake
@@ -19,3 +19,4 @@
set(TEST_S_PLATFORM ON CACHE BOOL "Whether to build S regression Platform tests")
set(TEST_S_FWU OFF CACHE BOOL "Whether to build S regression FWU tests")
set(TEST_S_IPC ON CACHE BOOL "Whether to build S regression IPC tests")
+set(TEST_S_FPU OFF CACHE BOOL "Whether to build S regression FPU tests")
diff --git a/test/config/default_test_config.cmake b/test/config/default_test_config.cmake
index 7f3deee..1bfacae 100644
--- a/test/config/default_test_config.cmake
+++ b/test/config/default_test_config.cmake
@@ -70,6 +70,10 @@
set(ATTEST_TEST_GET_PUBLIC_KEY OFF CACHE BOOL "Require to retrieve Initial Attestation public in runtime for test purpose")
+############################################ FPU Tests #########################
+
+set(TEST_S_FPU OFF CACHE BOOL "Whether to build S regression FPU tests")
+
################################## Extra test suites ###########################
set(EXTRA_NS_TEST_SUITES_PATHS "" CACHE PATH "List of extra non-secure test suites directories. An extra test suite folder contains source code, CMakeLists.txt and cmake configuration file")
diff --git a/test/config/set_config.cmake b/test/config/set_config.cmake
index 75f6477..57f2117 100644
--- a/test/config/set_config.cmake
+++ b/test/config/set_config.cmake
@@ -67,6 +67,10 @@
set(TEST_NS_MANAGE_NSID OFF CACHE BOOL "Whether to build NS regression NSID management tests")
endif()
+if (CONFIG_TFM_SPE_FP STREQUAL "0")
+ set(TEST_S_FPU OFF CACHE BOOL "Whether to build S regression FPU tests")
+endif()
+
########################## Test framework sync #################################
get_cmake_property(CACHE_VARS CACHE_VARIABLES)
diff --git a/test/framework/secure_suites.c b/test/framework/secure_suites.c
index bbe3676..674144e 100644
--- a/test/framework/secure_suites.c
+++ b/test/framework/secure_suites.c
@@ -35,6 +35,9 @@
#include "audit_s_tests.h"
#endif
#endif /* TFM_PSA_API */
+#if defined (TEST_S_FPU)
+#include "fpu_s_tests.h"
+#endif
#ifdef EXTRA_S_TEST_SUITE
#include "extra_s_tests.h"
#endif
@@ -85,6 +88,11 @@
{®ister_testsuite_s_ipc_interface, 0, 0, 0},
#endif
+#ifdef TEST_S_FPU
+ /* Secure FPU test cases */
+ {®ister_testsuite_s_fpu_interface, 0, 0, 0},
+#endif
+
#ifdef EXTRA_S_TEST_SUITE
/* Secure extra test cases */
{®ister_testsuite_extra_s_interface, 0, 0, 0},
diff --git a/test/secure_tests.cmake b/test/secure_tests.cmake
index e1111ab..9212b7f 100644
--- a/test/secure_tests.cmake
+++ b/test/secure_tests.cmake
@@ -74,6 +74,9 @@
if (TEST_S_FWU)
add_library(tfm_test_suite_fwu_s STATIC EXCLUDE_FROM_ALL)
endif()
+if (TEST_S_FPU)
+ add_library(tfm_test_suite_fpu_s STATIC EXCLUDE_FROM_ALL)
+endif()
if (EXTRA_S_TEST_SUITES_PATHS)
add_library(tfm_test_suite_extra_s STATIC EXCLUDE_FROM_ALL)
endif()
diff --git a/test/suites/CMakeLists.txt b/test/suites/CMakeLists.txt
index deafdd8..691f1fd 100644
--- a/test/suites/CMakeLists.txt
+++ b/test/suites/CMakeLists.txt
@@ -84,6 +84,7 @@
add_subdirectory(irq)
add_subdirectory(multi_core/non_secure)
add_subdirectory(nsid)
+add_subdirectory(fpu)
if (TFM_FUZZER_TOOL_TESTS AND TEST_FRAMEWORK_NS)
if (NOT DEFINED TFM_FUZZER_TOOL_TESTS_CMAKE_INC_PATH)
diff --git a/test/suites/attestation/CMakeLists.txt b/test/suites/attestation/CMakeLists.txt
index 08ae89b..d24bd9c 100644
--- a/test/suites/attestation/CMakeLists.txt
+++ b/test/suites/attestation/CMakeLists.txt
@@ -48,7 +48,7 @@
target_link_libraries(tfm_test_suite_attestation_ns
PRIVATE
- tfm_qcbor
+ tfm_qcbor_ns
tfm_t_cose_ns
tfm_test_framework_ns
#TODO I'm not sure this should _really_ be linked here
@@ -96,9 +96,14 @@
TEST_S_ATTESTATION
)
+ target_compile_options(tfm_test_suite_attestation_s
+ PUBLIC
+ ${COMPILER_CP_FLAG}
+ )
+
target_link_libraries(tfm_test_suite_attestation_s
PRIVATE
- tfm_qcbor
+ tfm_qcbor_s
tfm_t_cose_s
tfm_test_framework_s
tfm_attestation_defs
diff --git a/test/suites/fpu/CMakeLists.txt b/test/suites/fpu/CMakeLists.txt
new file mode 100644
index 0000000..f5ce54b
--- /dev/null
+++ b/test/suites/fpu/CMakeLists.txt
@@ -0,0 +1,42 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_policy(SET CMP0079 NEW)
+
+if (NOT TEST_S_FPU)
+ return()
+endif()
+
+####################### Secure #################################################
+
+target_sources(tfm_test_suite_fpu_s
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/fpu_tests_common.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/secure/fpu_s_interface_testsuite.c
+)
+
+target_include_directories(tfm_test_suite_fpu_s
+ PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/secure
+)
+
+target_compile_definitions(tfm_test_suite_fpu_s
+ INTERFACE
+ TEST_S_FPU
+)
+
+target_link_libraries(tfm_test_suite_fpu_s
+ PRIVATE
+ tfm_test_framework_s
+ PUBLIC
+ platform_s
+)
+
+target_link_libraries(tfm_s_tests
+ INTERFACE
+ tfm_test_suite_fpu_s
+)
diff --git a/test/suites/fpu/fpu_tests_common.c b/test/suites/fpu/fpu_tests_common.c
new file mode 100644
index 0000000..49d85eb
--- /dev/null
+++ b/test/suites/fpu/fpu_tests_common.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "fpu_tests_common.h"
+#include "psa_manifest/sid.h"
+#include "tfm_arch.h"
+
+/**
+ * Change FP registers.
+ */
+__attribute__((naked)) static void change_fp_in_client(void)
+{
+ __asm volatile(
+ "mov r0, #0x000000C0 \n"
+ "vmov s0, r0 \n"
+ "mov r0, #0x000000C1 \n"
+ "vmov s1, r0 \n"
+ "mov r0, #0x000000C2 \n"
+ "vmov s2, r0 \n"
+ "mov r0, #0x000000C3 \n"
+ "vmov s3, r0 \n"
+ "mov r0, #0x000000C4 \n"
+ "vmov s4, r0 \n"
+ "mov r0, #0x000000C5 \n"
+ "vmov s5, r0 \n"
+ "mov r0, #0x000000C6 \n"
+ "vmov s6, r0 \n"
+ "mov r0, #0x000000C7 \n"
+ "vmov s7, r0 \n"
+ "mov r0, #0x000000C8 \n"
+ "vmov s8, r0 \n"
+ "mov r0, #0x000000C9 \n"
+ "vmov s9, r0 \n"
+ "mov r0, #0x000000CA \n"
+ "vmov s10, r0 \n"
+ "mov r0, #0x000000CB \n"
+ "vmov s11, r0 \n"
+ "mov r0, #0x000000CC \n"
+ "vmov s12, r0 \n"
+ "mov r0, #0x000000CD \n"
+ "vmov s13, r0 \n"
+ "mov r0, #0x000000CE \n"
+ "vmov s14, r0 \n"
+ "mov r0, #0x000000CF \n"
+ "vmov s15, r0 \n"
+ "mov r0, #0x000000D0 \n"
+ "vmov s16, r0 \n"
+ "mov r0, #0x000000D1 \n"
+ "vmov s17, r0 \n"
+ "mov r0, #0x000000D2 \n"
+ "vmov s18, r0 \n"
+ "mov r0, #0x000000D3 \n"
+ "vmov s19, r0 \n"
+ "mov r0, #0x000000D4 \n"
+ "vmov s20, r0 \n"
+ "mov r0, #0x000000D5 \n"
+ "vmov s21, r0 \n"
+ "mov r0, #0x000000D6 \n"
+ "vmov s22, r0 \n"
+ "mov r0, #0x000000D7 \n"
+ "vmov s23, r0 \n"
+ "mov r0, #0x000000D8 \n"
+ "vmov s24, r0 \n"
+ "mov r0, #0x000000D9 \n"
+ "vmov s25, r0 \n"
+ "mov r0, #0x000000DA \n"
+ "vmov s26, r0 \n"
+ "mov r0, #0x000000DB \n"
+ "vmov s27, r0 \n"
+ "mov r0, #0x000000DC \n"
+ "vmov s28, r0 \n"
+ "mov r0, #0x000000DD \n"
+ "vmov s29, r0 \n"
+ "mov r0, #0x000000DE \n"
+ "vmov s30, r0 \n"
+ "mov r0, #0x000000DF \n"
+ "vmov s31, r0 \n"
+
+ "bx lr \n"
+ );
+}
+
+/**
+ * Check whether FP registers are restored correctly.
+ * Return:
+ * 1 - FP registers are restored correctly
+ * 0 - FP registers are not restored correctly
+ */
+__attribute__((naked)) static bool check_fp_restored_client(void)
+{
+ __asm volatile(
+ "mov r3, #0 \n"
+
+ "vmov r2, s0 \n"
+ "cmp r2, 0x000000C0 \n"
+ "bne exit \n"
+
+ "vmov r2, s1 \n"
+ "cmp r2, 0x000000C1 \n"
+ "bne exit \n"
+
+ "vmov r2, s2 \n"
+ "cmp r2, 0x000000C2 \n"
+ "bne exit \n"
+
+ "vmov r2, s3 \n"
+ "cmp r2, 0x000000C3 \n"
+ "bne exit \n"
+
+ "vmov r2, s4 \n"
+ "cmp r2, 0x000000C4 \n"
+ "bne exit \n"
+
+ "vmov r2, s5 \n"
+ "cmp r2, 0x000000C5 \n"
+ "bne exit \n"
+
+ "vmov r2, s6 \n"
+ "cmp r2, 0x000000C6 \n"
+ "bne exit \n"
+
+ "vmov r2, s7 \n"
+ "cmp r2, 0x000000C7 \n"
+ "bne exit \n"
+
+ "vmov r2, s8 \n"
+ "cmp r2, 0x000000C8 \n"
+ "bne exit \n"
+
+ "vmov r2, s9 \n"
+ "cmp r2, 0x000000C9 \n"
+ "bne exit \n"
+
+ "vmov r2, s10 \n"
+ "cmp r2, 0x000000CA \n"
+ "bne exit \n"
+
+ "vmov r2, s11 \n"
+ "cmp r2, 0x000000CB \n"
+ "bne exit \n"
+
+ "vmov r2, s12 \n"
+ "cmp r2, 0x000000CC \n"
+ "bne exit \n"
+
+ "vmov r2, s13 \n"
+ "cmp r2, 0x000000CD \n"
+ "bne exit \n"
+
+ "vmov r2, s14 \n"
+ "cmp r2, 0x000000CE \n"
+ "bne exit \n"
+
+ "vmov r2, s15 \n"
+ "cmp r2, 0x000000CF \n"
+ "bne exit \n"
+
+ "vmov r2, s16 \n"
+ "cmp r2, 0x000000D0 \n"
+ "bne exit \n"
+
+ "vmov r2, s17 \n"
+ "cmp r2, 0x000000D1 \n"
+ "bne exit \n"
+
+ "vmov r2, s18 \n"
+ "cmp r2, 0x000000D2 \n"
+ "bne exit \n"
+
+ "vmov r2, s19 \n"
+ "cmp r2, 0x000000D3 \n"
+ "bne exit \n"
+
+ "vmov r2, s20 \n"
+ "cmp r2, 0x000000D4 \n"
+ "bne exit \n"
+
+ "vmov r2, s21 \n"
+ "cmp r2, 0x000000D5 \n"
+ "bne exit \n"
+
+ "vmov r2, s22 \n"
+ "cmp r2, 0x000000D6 \n"
+ "bne exit \n"
+
+ "vmov r2, s23 \n"
+ "cmp r2, 0x000000D7 \n"
+ "bne exit \n"
+
+ "vmov r2, s24 \n"
+ "cmp r2, 0x000000D8 \n"
+ "bne exit \n"
+
+ "vmov r2, s25 \n"
+ "cmp r2, 0x000000D9 \n"
+ "bne exit \n"
+
+ "vmov r2, s26 \n"
+ "cmp r2, 0x000000DA \n"
+ "bne exit \n"
+
+ "vmov r2, s27 \n"
+ "cmp r2, 0x000000DB \n"
+ "bne exit \n"
+
+ "vmov r2, s28 \n"
+ "cmp r2, 0x000000DC \n"
+ "bne exit \n"
+
+ "vmov r2, s29 \n"
+ "cmp r2, 0x000000DD \n"
+ "bne exit \n"
+
+ "vmov r2, s30 \n"
+ "cmp r2, 0x000000DE \n"
+ "bne exit \n"
+
+ "vmov r2, s31 \n"
+ "cmp r2, 0x000000DF \n"
+ "bne exit \n"
+
+ "mov r3, #1 \n"
+ "exit: \n"
+ "mov r0, r3 \n"
+
+ "bx lr \n"
+ );
+}
+
+/**
+ * Description: Test FP context protection after psa calls. Change FP registers
+ * in FPU client/service partition separately, then check FP registers after
+ * psa calls.
+ * Expectation: FP registers in FPU client/service partition should be saved
+ * and restored correctly.
+ */
+void tfm_fpu_test_fp_protection_psa_call(struct test_result_t *ret)
+{
+ psa_handle_t handle;
+ psa_status_t status;
+
+ handle = psa_connect(TFM_FPU_SERVICE_CHECK_FP_REGISTER_SID,
+ TFM_FPU_SERVICE_CHECK_FP_REGISTER_VERSION);
+ if (!PSA_HANDLE_IS_VALID(handle)) {
+ ret->val = TEST_FAILED;
+ return;
+ }
+
+ /* Change FP registers in secure thread */
+ change_fp_in_client();
+
+ status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
+ if (status == PSA_SUCCESS) {
+ /* FP registers should be restored */
+ if (check_fp_restored_client()) {
+ ret->val = TEST_PASSED;
+ } else {
+ ret->val = TEST_FAILED;
+ }
+ }
+
+ psa_close(handle);
+}
+
+/**
+ * Description: Clear FP registers in FPU service partition for next test.
+ * Expectation: FP registers in FPU service partition should be cleared.
+ */
+void tfm_fpu_test_clear_service_fp_data(struct test_result_t *ret)
+{
+ psa_handle_t handle;
+ psa_status_t status;
+
+ handle = psa_connect(TFM_FPU_SERVICE_CLEAR_FP_REGISTER_SID,
+ TFM_FPU_SERVICE_CLEAR_FP_REGISTER_VERSION);
+ if (!PSA_HANDLE_IS_VALID(handle)) {
+ ret->val = TEST_FAILED;
+ return;
+ }
+
+ status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
+ if (status == PSA_SUCCESS) {
+ ret->val = TEST_PASSED;
+ } else {
+ ret->val = TEST_FAILED;
+ }
+
+ psa_close(handle);
+}
+
+/**
+ * Description: Test reliability of FP context protection after psa calls by
+ * loops. Change FP registers in FPU client/service partition separately, then
+ * check FP registers after psa calls.
+ * Expectation: FP registers in FPU client/service partition should be saved
+ * and restored correctly.
+ */
+void tfm_fpu_test_fp_protection_psa_call_loop(struct test_result_t *ret)
+{
+ psa_handle_t handle;
+ psa_status_t status;
+ uint32_t itr;
+
+ for (itr = 0; itr < LOOP_ITERATIONS; itr++) {
+ TEST_LOG(" > Iteration %d of %d\r", itr + 1, LOOP_ITERATIONS);
+
+ handle = psa_connect(TFM_FPU_SERVICE_CHECK_FP_REGISTER_SID,
+ TFM_FPU_SERVICE_CHECK_FP_REGISTER_VERSION);
+ if (handle <= 0) {
+ TEST_FAIL("The RoT Service has refused the connection!\r\n");
+ ret->val = TEST_FAILED;
+ return;
+ }
+
+ /* Change FP registers in secure thread */
+ change_fp_in_client();
+
+ status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
+ if (status == PSA_SUCCESS) {
+ /* FP registers should be restored */
+ if (check_fp_restored_client()) {
+ ret->val = TEST_PASSED;
+ } else {
+ ret->val = TEST_FAILED;
+ }
+ } else {
+ ret->val = TEST_FAILED;
+ }
+
+ psa_close(handle);
+
+ handle = psa_connect(TFM_FPU_SERVICE_CLEAR_FP_REGISTER_SID,
+ TFM_FPU_SERVICE_CLEAR_FP_REGISTER_VERSION);
+ if (handle <= 0) {
+ TEST_LOG("The RoT Service has refused the connection!\r\n");
+ ret->val = TEST_FAILED;
+ return;
+ }
+
+ status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
+ if (status == PSA_SUCCESS) {
+ ret->val = TEST_PASSED;
+ } else {
+ ret->val = TEST_FAILED;
+ }
+
+ psa_close(handle);
+ }
+
+ ret->val = TEST_PASSED;
+}
diff --git a/test/suites/fpu/fpu_tests_common.h b/test/suites/fpu/fpu_tests_common.h
new file mode 100644
index 0000000..bcbe19d
--- /dev/null
+++ b/test/suites/fpu/fpu_tests_common.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+
+#ifndef __FPU_TESTS_COMMON_H__
+#define __FPU_TESTS_COMMON_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "psa/client.h"
+#include "test_framework_helpers.h"
+#ifdef TFM_PSA_API
+#include "psa_manifest/sid.h"
+#endif
+
+
+#define LOOP_ITERATIONS (300U)
+
+/**
+ * Test FP context protection after psa calls.
+ */
+void tfm_fpu_test_fp_protection_psa_call(struct test_result_t *ret);
+
+/**
+ * Clear FP registers in FPU service partition.
+ */
+void tfm_fpu_test_clear_service_fp_data(struct test_result_t *ret);
+
+/**
+ * Test reliability of FP context protection after psa calls by loops.
+ */
+void tfm_fpu_test_fp_protection_psa_call_loop(struct test_result_t *ret);
+
+/**
+ * Clear FP registers in FPU client partition.
+ */
+void tfm_fpu_test_clear_client_fp_data(struct test_result_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FPU_TESTS_COMMON__ */
diff --git a/test/suites/fpu/secure/fpu_s_interface_testsuite.c b/test/suites/fpu/secure/fpu_s_interface_testsuite.c
new file mode 100755
index 0000000..f648283
--- /dev/null
+++ b/test/suites/fpu/secure/fpu_s_interface_testsuite.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "fpu_s_tests.h"
+#include "../fpu_tests_common.h"
+
+static struct test_t fpu_s_tests[] = {
+ {
+ &tfm_fpu_test_clear_client_fp_data, "TFM_S_FPU_TEST_1001",
+ "Clear FP registers in FPU client partition",
+ {TEST_PASSED}
+ },
+ {
+ &tfm_fpu_test_fp_protection_psa_call, "TFM_S_FPU_TEST_1002",
+ "Test FP context protection after psa calls",
+ {TEST_PASSED}
+ },
+ {
+ &tfm_fpu_test_clear_service_fp_data, "TFM_S_FPU_TEST_1003",
+ "Clear FP registers in FPU service partition for next test",
+ {TEST_PASSED}
+ },
+ {
+ &tfm_fpu_test_fp_protection_psa_call_loop, "TFM_S_FPU_TEST_1004",
+ "Test reliability of FP context protection after psa calls",
+ {TEST_PASSED}
+ }
+};
+
+/**
+ * Check invalidation of FP registers.
+ */
+__attribute__((naked)) static uint32_t check_fp_invalidated(void);
+
+void register_testsuite_s_fpu_interface(struct test_suite_t *p_test_suite)
+{
+ uint32_t list_size;
+
+ list_size = (sizeof(fpu_s_tests) / sizeof(fpu_s_tests[0]));
+
+ set_testsuite("FPU secure interface test (TFM_S_FPU_TEST_1XXX)",
+ fpu_s_tests, list_size, p_test_suite);
+}
+
+/**
+ * Clear FP registers.
+ */
+__attribute__((naked)) static int fpu_client_fp_clear_test(void)
+{
+ __asm volatile(
+ "eor r0, r0, r0 \n"
+ "vmov s1, r0 \n"
+ "vmov s2, r0 \n"
+ "vmov s3, r0 \n"
+ "vmov s4, r0 \n"
+ "vmov s5, r0 \n"
+ "vmov s6, r0 \n"
+ "vmov s7, r0 \n"
+ "vmov s8, r0 \n"
+ "vmov s9, r0 \n"
+ "vmov s10, r0 \n"
+ "vmov s11, r0 \n"
+ "vmov s12, r0 \n"
+ "vmov s13, r0 \n"
+ "vmov s14, r0 \n"
+ "vmov s15, r0 \n"
+ "vmov s16, r0 \n"
+ "vmov s17, r0 \n"
+ "vmov s18, r0 \n"
+ "vmov s19, r0 \n"
+ "vmov s20, r0 \n"
+ "vmov s21, r0 \n"
+ "vmov s22, r0 \n"
+ "vmov s23, r0 \n"
+ "vmov s24, r0 \n"
+ "vmov s25, r0 \n"
+ "vmov s26, r0 \n"
+ "vmov s27, r0 \n"
+ "vmov s28, r0 \n"
+ "vmov s29, r0 \n"
+ "vmov s30, r0 \n"
+ "vmov s31, r0 \n"
+
+ "bx lr \n"
+ );
+}
+
+/**
+ * Description: Clear FP registers in FPU client partition for next test.
+ * Expectation: FP registers in FPU client partition should be cleared.
+ */
+void tfm_fpu_test_clear_client_fp_data(struct test_result_t *ret)
+{
+ fpu_client_fp_clear_test();
+
+ if (check_fp_invalidated()) {
+ ret->val = TEST_PASSED;
+ } else {
+ ret->val = TEST_FAILED;
+ }
+}
+
+/**
+ * Check invalidation of FP registers.
+ * Return:
+ * 1 - FP registers are invalidated
+ * 0 - FP registers are not invalidated
+ */
+__attribute__((naked)) static uint32_t check_fp_invalidated(void)
+{
+ __asm volatile(
+ "mov r3, #1 \n"
+ "mov r2, #0 \n"
+
+ "vadd.f32 s2, s1, s0 \n"
+ "vadd.f32 s4, s3, s2 \n"
+ "vadd.f32 s6, s5, s4 \n"
+ "vadd.f32 s8, s7, s6 \n"
+ "vadd.f32 s10, s9, s8 \n"
+ "vadd.f32 s12, s11, s10 \n"
+ "vadd.f32 s14, s13, s12 \n"
+ "vadd.f32 s16, s15, s14 \n"
+ "vadd.f32 s18, s17, s16 \n"
+ "vadd.f32 s20, s19, s18 \n"
+ "vadd.f32 s22, s21, s20 \n"
+ "vadd.f32 s24, s23, s22 \n"
+ "vadd.f32 s26, s25, s24 \n"
+ "vadd.f32 s28, s27, s26 \n"
+ "vadd.f32 s30, s29, s28 \n"
+ "vadd.f32 s31, s29, s30 \n"
+ "vcmp.f32 s31, #0.0 \n"
+ "vmrs APSR_nzcv, fpscr \n"
+ "beq cleared \n"
+ "mov r3, r2 \n"
+ "cleared: \n"
+
+ "mov r0, r3 \n"
+ "bx lr \n"
+ );
+}
diff --git a/test/suites/fpu/secure/fpu_s_tests.h b/test/suites/fpu/secure/fpu_s_tests.h
new file mode 100644
index 0000000..bde86f4
--- /dev/null
+++ b/test/suites/fpu/secure/fpu_s_tests.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __FPU_S_TESTS_H__
+#define __FPU_S_TESTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test_framework.h"
+
+/**
+ * \brief Register testsuite for fpu secure interface.
+ *
+ * \param[in] p_test_suite The test suite to be executed.
+ */
+void register_testsuite_s_fpu_interface(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FPU_S_TESTS_H__ */
diff --git a/test/suites/qcbor/CMakeLists.txt b/test/suites/qcbor/CMakeLists.txt
index b7b95fd..b1ac7eb 100644
--- a/test/suites/qcbor/CMakeLists.txt
+++ b/test/suites/qcbor/CMakeLists.txt
@@ -6,11 +6,35 @@
#-------------------------------------------------------------------------------
cmake_policy(SET CMP0079 NEW)
-if (NOT TEST_NS_QCBOR)
+if (NOT TEST_NS_ATTESTATION AND NOT TEST_NS_QCBOR)
return()
endif()
-####################### Non Secure #############################################
+######################### qcbor ns ############################
+
+set(QCBOR_SRC_DIR ${CMAKE_SOURCE_DIR}/lib/ext/qcbor)
+
+add_library(tfm_qcbor_ns STATIC EXCLUDE_FROM_ALL)
+
+target_sources(tfm_qcbor_ns
+ PRIVATE
+ ${QCBOR_SRC_DIR}/src/ieee754.c
+ ${QCBOR_SRC_DIR}/src/qcbor_encode.c
+ ${QCBOR_SRC_DIR}/src/qcbor_decode.c
+ ${QCBOR_SRC_DIR}/src/UsefulBuf.c
+)
+
+target_include_directories(tfm_qcbor_ns
+ PUBLIC
+ $<BUILD_INTERFACE:${QCBOR_SRC_DIR}/inc>
+)
+
+target_link_libraries(tfm_qcbor_ns
+ PRIVATE
+ tfm_t_cose_defs
+)
+
+####################### Non Secure Test #############################################
add_library(tfm_test_suite_qcbor_ns STATIC EXCLUDE_FROM_ALL)
@@ -22,6 +46,7 @@
target_include_directories(tfm_test_suite_qcbor_ns
PUBLIC
non_secure
+ ${QCBOR_SRC_DIR}/test/
)
target_compile_definitions(tfm_test_suite_qcbor_ns
@@ -41,3 +66,33 @@
INTERFACE
tfm_test_suite_qcbor_ns
)
+
+if (NOT TEST_NS_QCBOR)
+ return()
+endif()
+
+############################ qcbor test ########################################
+
+add_library(tfm_qcbor_test STATIC EXCLUDE_FROM_ALL)
+
+target_sources(tfm_qcbor_test
+ PRIVATE
+ ${QCBOR_SRC_DIR}/test/float_tests.c
+ ${QCBOR_SRC_DIR}/test/half_to_double_from_rfc7049.c
+ ${QCBOR_SRC_DIR}/test/qcbor_decode_tests.c
+ ${QCBOR_SRC_DIR}/test/qcbor_encode_tests.c
+ ${QCBOR_SRC_DIR}/test/run_tests.c
+ ${QCBOR_SRC_DIR}/test/UsefulBuf_Tests.c
+)
+
+target_include_directories(tfm_qcbor_test
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/test>
+ PRIVATE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
+)
+
+target_link_libraries(tfm_qcbor_test
+ PRIVATE
+ tfm_qcbor_ns
+)
diff --git a/test/suites/t_cose/CMakeLists.txt b/test/suites/t_cose/CMakeLists.txt
index 54dc2d9..1553517 100644
--- a/test/suites/t_cose/CMakeLists.txt
+++ b/test/suites/t_cose/CMakeLists.txt
@@ -7,10 +7,47 @@
cmake_policy(SET CMP0079 NEW)
+if (NOT TEST_NS_ATTESTATION AND NOT TEST_NS_T_COSE)
+ return()
+endif()
+
+set(T_COSE_SRC_DIR ${CMAKE_SOURCE_DIR}/lib/ext/t_cose)
+
+############################ t_cose non secure #################################
+
+add_library(tfm_t_cose_ns STATIC EXCLUDE_FROM_ALL)
+
+target_link_libraries(tfm_t_cose_ns
+ PUBLIC
+ tfm_t_cose_common
+ tfm_t_cose_defs
+ tfm_qcbor_ns
+ tfm_ns_interface
+)
+
if (NOT TEST_NS_T_COSE)
return()
endif()
+############################ t_cose test #######################################
+
+add_library(tfm_t_cose_test STATIC EXCLUDE_FROM_ALL)
+
+target_sources(tfm_t_cose_test
+ PRIVATE
+ ${T_COSE_SRC_DIR}/test/run_tests.c
+ ${T_COSE_SRC_DIR}/test/t_cose_make_psa_test_key.c
+ ${T_COSE_SRC_DIR}/test/t_cose_make_test_messages.c
+ ${T_COSE_SRC_DIR}/test/t_cose_sign_verify_test.c
+ ${T_COSE_SRC_DIR}/test/t_cose_test.c
+)
+
+target_include_directories(tfm_t_cose_test
+ PUBLIC
+ $<BUILD_INTERFACE:${T_COSE_SRC_DIR}/inc>
+ $<BUILD_INTERFACE:${T_COSE_SRC_DIR}/test>
+)
+
####################### Non Secure #############################################
add_library(tfm_test_suite_t_cose_ns STATIC EXCLUDE_FROM_ALL)
@@ -42,3 +79,8 @@
INTERFACE
tfm_test_suite_t_cose_ns
)
+
+target_link_libraries(tfm_t_cose_test
+ PRIVATE
+ tfm_t_cose_ns
+)
diff --git a/test/test_services/CMakeLists.txt b/test/test_services/CMakeLists.txt
index b894765..6c179c7 100644
--- a/test/test_services/CMakeLists.txt
+++ b/test/test_services/CMakeLists.txt
@@ -40,3 +40,7 @@
if (TEST_NS_FLIH_IRQ)
add_subdirectory(tfm_flih_test_service)
endif()
+
+if (TEST_S_FPU)
+ add_subdirectory(tfm_fpu_service)
+endif()
diff --git a/test/test_services/tfm_fpu_service/CMakeLists.txt b/test/test_services/tfm_fpu_service/CMakeLists.txt
new file mode 100644
index 0000000..2de27e7
--- /dev/null
+++ b/test/test_services/tfm_fpu_service/CMakeLists.txt
@@ -0,0 +1,65 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_policy(SET CMP0079 NEW)
+
+add_library(tfm_app_rot_partition_fpu_service STATIC)
+
+target_sources(tfm_app_rot_partition_fpu_service
+ PRIVATE
+ ./tfm_fpu_service_test.c
+)
+
+# The generated sources
+target_sources(tfm_app_rot_partition_fpu_service
+ PRIVATE
+ $<$<BOOL:${TFM_PSA_API}>:
+ ${CMAKE_BINARY_DIR}/generated/test_services/tfm_fpu_service/auto_generated/intermedia_tfm_fpu_service_test.c>
+)
+
+target_sources(tfm_partitions
+ INTERFACE
+ $<$<BOOL:${TFM_PSA_API}>:
+ ${CMAKE_BINARY_DIR}/generated/test_services/tfm_fpu_service/auto_generated/load_info_tfm_fpu_service_test.c>
+)
+
+target_include_directories(tfm_app_rot_partition_fpu_service
+ PUBLIC
+ .
+ PRIVATE
+ ${CMAKE_BINARY_DIR}/generated/test_services/tfm_fpu_service
+)
+
+target_include_directories(tfm_partitions
+ INTERFACE
+ ${CMAKE_BINARY_DIR}/generated/test_services/tfm_fpu_service
+)
+
+target_link_libraries(tfm_app_rot_partition_fpu_service
+ PRIVATE
+ tfm_secure_api
+ platform_s
+ tfm_test_framework_s
+ tfm_arch
+)
+
+target_link_libraries(tfm_spm
+ PRIVATE
+ tfm_app_rot_partition_fpu_service
+)
+
+############################ Partition Defs ####################################
+
+target_link_libraries(tfm_partitions
+ INTERFACE
+ tfm_app_rot_partition_fpu_service
+)
+
+target_compile_definitions(tfm_partition_defs
+ INTERFACE
+ TEST_S_FPU
+)
diff --git a/test/test_services/tfm_fpu_service/tfm_fpu_service_test.c b/test/test_services/tfm_fpu_service/tfm_fpu_service_test.c
new file mode 100644
index 0000000..91bee8c
--- /dev/null
+++ b/test/test_services/tfm_fpu_service/tfm_fpu_service_test.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include "psa/client.h"
+#include "psa/service.h"
+#include "psa_manifest/tfm_fpu_service_test.h"
+#include "tfm_api.h"
+#include "tfm_hal_isolation.h"
+#include "tfm_secure_api.h"
+
+/* Define the return status */
+#define FPU_SP_TEST_SUCCESS (0)
+#define FPU_SP_TEST_FAILED (-1)
+
+/*
+ * Fixme: Temporarily implement abort as infinite loop,
+ * will replace it later.
+ */
+static void tfm_abort(void)
+{
+ while (1)
+ ;
+}
+
+/**
+ * Clear FP registers.
+ */
+__attribute__((naked)) static void clear_fp_regs(void)
+{
+ __asm volatile(
+ "eor r0, r0, r0 \n"
+ "vmov s0, r0 \n"
+ "vmov s1, r0 \n"
+ "vmov s2, r0 \n"
+ "vmov s3, r0 \n"
+ "vmov s4, r0 \n"
+ "vmov s5, r0 \n"
+ "vmov s6, r0 \n"
+ "vmov s7, r0 \n"
+ "vmov s8, r0 \n"
+ "vmov s9, r0 \n"
+ "vmov s10, r0 \n"
+ "vmov s11, r0 \n"
+ "vmov s12, r0 \n"
+ "vmov s13, r0 \n"
+ "vmov s14, r0 \n"
+ "vmov s15, r0 \n"
+ "vmov s16, r0 \n"
+ "vmov s17, r0 \n"
+ "vmov s18, r0 \n"
+ "vmov s19, r0 \n"
+ "vmov s20, r0 \n"
+ "vmov s21, r0 \n"
+ "vmov s22, r0 \n"
+ "vmov s23, r0 \n"
+ "vmov s24, r0 \n"
+ "vmov s25, r0 \n"
+ "vmov s26, r0 \n"
+ "vmov s27, r0 \n"
+ "vmov s28, r0 \n"
+ "vmov s29, r0 \n"
+ "vmov s30, r0 \n"
+ "vmov s31, r0 \n"
+ "bx lr \n"
+ );
+}
+
+/**
+ * Check whether FP registers are restored correctly.
+ * Return:
+ * 1 - FP registers are restored correctly
+ * 0 - FP registers are not restored correctly
+ */
+__attribute__((naked)) static bool check_fp_restored_service(void)
+{
+ __asm volatile(
+ "mov r3, #0 \n"
+
+ "vmov r2, s0 \n"
+ "cmp r2, 0x000000E0 \n"
+ "bne quit \n"
+
+ "vmov r2, s1 \n"
+ "cmp r2, 0x000000E1 \n"
+ "bne quit \n"
+
+ "vmov r2, s2 \n"
+ "cmp r2, 0x000000E2 \n"
+ "bne quit \n"
+
+ "vmov r2, s3 \n"
+ "cmp r2, 0x000000E3 \n"
+ "bne quit \n"
+
+ "vmov r2, s4 \n"
+ "cmp r2, 0x000000E4 \n"
+ "bne quit \n"
+
+ "vmov r2, s5 \n"
+ "cmp r2, 0x000000E5 \n"
+ "bne quit \n"
+
+ "vmov r2, s6 \n"
+ "cmp r2, 0x000000E6 \n"
+ "bne quit \n"
+
+ "vmov r2, s7 \n"
+ "cmp r2, 0x000000E7 \n"
+ "bne quit \n"
+
+ "vmov r2, s8 \n"
+ "cmp r2, 0x000000E8 \n"
+ "bne quit \n"
+
+ "vmov r2, s9 \n"
+ "cmp r2, 0x000000E9 \n"
+ "bne quit \n"
+
+ "vmov r2, s10 \n"
+ "cmp r2, 0x000000EA \n"
+ "bne quit \n"
+
+ "vmov r2, s11 \n"
+ "cmp r2, 0x000000EB \n"
+ "bne quit \n"
+
+ "vmov r2, s12 \n"
+ "cmp r2, 0x000000EC \n"
+ "bne quit \n"
+
+ "vmov r2, s13 \n"
+ "cmp r2, 0x000000ED \n"
+ "bne quit \n"
+
+ "vmov r2, s14 \n"
+ "cmp r2, 0x000000EE \n"
+ "bne quit \n"
+
+ "vmov r2, s15 \n"
+ "cmp r2, 0x000000EF \n"
+ "bne quit \n"
+
+ "vmov r2, s16 \n"
+ "cmp r2, 0x000000F0 \n"
+ "bne quit \n"
+
+ "vmov r2, s17 \n"
+ "cmp r2, 0x000000F1 \n"
+ "bne quit \n"
+
+ "vmov r2, s18 \n"
+ "cmp r2, 0x000000F2 \n"
+ "bne quit \n"
+
+ "vmov r2, s19 \n"
+ "cmp r2, 0x000000F3 \n"
+ "bne quit \n"
+
+ "vmov r2, s20 \n"
+ "cmp r2, 0x000000F4 \n"
+ "bne quit \n"
+
+ "vmov r2, s21 \n"
+ "cmp r2, 0x000000F5 \n"
+ "bne quit \n"
+
+ "vmov r2, s22 \n"
+ "cmp r2, 0x000000F6 \n"
+ "bne quit \n"
+
+ "vmov r2, s23 \n"
+ "cmp r2, 0x000000F7 \n"
+ "bne quit \n"
+
+ "vmov r2, s24 \n"
+ "cmp r2, 0x000000F8 \n"
+ "bne quit \n"
+
+ "vmov r2, s25 \n"
+ "cmp r2, 0x000000F9 \n"
+ "bne quit \n"
+
+ "vmov r2, s26 \n"
+ "cmp r2, 0x000000FA \n"
+ "bne quit \n"
+
+ "vmov r2, s27 \n"
+ "cmp r2, 0x000000FB \n"
+ "bne quit \n"
+
+ "vmov r2, s28 \n"
+ "cmp r2, 0x000000FC \n"
+ "bne quit \n"
+
+ "vmov r2, s29 \n"
+ "cmp r2, 0x000000FD \n"
+ "bne quit \n"
+
+ "vmov r2, s30 \n"
+ "cmp r2, 0x000000FE \n"
+ "bne quit \n"
+
+ "vmov r2, s31 \n"
+ "cmp r2, 0x000000FF \n"
+ "bne quit \n"
+
+ "mov r3, #1 \n"
+ "quit: \n"
+ "mov r0, r3 \n"
+
+ "bx lr \n"
+ );
+}
+
+/**
+ * Change FP registers in FP service partition.
+ */
+__attribute__((naked)) static void change_fp_in_service(void)
+{
+ __asm volatile(
+ "mov r0, #0x000000E0 \n"
+ "vmov s0, r0 \n"
+ "mov r0, #0x000000E1 \n"
+ "vmov s1, r0 \n"
+ "mov r0, #0x000000E2 \n"
+ "vmov s2, r0 \n"
+ "mov r0, #0x000000E3 \n"
+ "vmov s3, r0 \n"
+ "mov r0, #0x000000E4 \n"
+ "vmov s4, r0 \n"
+ "mov r0, #0x000000E5 \n"
+ "vmov s5, r0 \n"
+ "mov r0, #0x000000E6 \n"
+ "vmov s6, r0 \n"
+ "mov r0, #0x000000E7 \n"
+ "vmov s7, r0 \n"
+ "mov r0, #0x000000E8 \n"
+ "vmov s8, r0 \n"
+ "mov r0, #0x000000E9 \n"
+ "vmov s9, r0 \n"
+ "mov r0, #0x000000EA \n"
+ "vmov s10, r0 \n"
+ "mov r0, #0x000000EB \n"
+ "vmov s11, r0 \n"
+ "mov r0, #0x000000EC \n"
+ "vmov s12, r0 \n"
+ "mov r0, #0x000000ED \n"
+ "vmov s13, r0 \n"
+ "mov r0, #0x000000EE \n"
+ "vmov s14, r0 \n"
+ "mov r0, #0x000000EF \n"
+ "vmov s15, r0 \n"
+ "mov r0, #0x000000F0 \n"
+ "vmov s16, r0 \n"
+ "mov r0, #0x000000F1 \n"
+ "vmov s17, r0 \n"
+ "mov r0, #0x000000F2 \n"
+ "vmov s18, r0 \n"
+ "mov r0, #0x000000F3 \n"
+ "vmov s19, r0 \n"
+ "mov r0, #0x000000F4 \n"
+ "vmov s20, r0 \n"
+ "mov r0, #0x000000F5 \n"
+ "vmov s21, r0 \n"
+ "mov r0, #0x000000F6 \n"
+ "vmov s22, r0 \n"
+ "mov r0, #0x000000F7 \n"
+ "vmov s23, r0 \n"
+ "mov r0, #0x000000F8 \n"
+ "vmov s24, r0 \n"
+ "mov r0, #0x000000F9 \n"
+ "vmov s25, r0 \n"
+ "mov r0, #0x000000FA \n"
+ "vmov s26, r0 \n"
+ "mov r0, #0x000000FB \n"
+ "vmov s27, r0 \n"
+ "mov r0, #0x000000FC \n"
+ "vmov s28, r0 \n"
+ "mov r0, #0x000000FD \n"
+ "vmov s29, r0 \n"
+ "mov r0, #0x000000FE \n"
+ "vmov s30, r0 \n"
+ "mov r0, #0x000000FF \n"
+ "vmov s31, r0 \n"
+
+ "bx lr \n"
+ );
+}
+
+/**
+ * Check whether FP registers is invalidated.
+ */
+__attribute__((naked)) static bool is_fp_cleaned(void)
+{
+ __asm volatile(
+ "mov r3, #1 \n"
+ "mov r2, #0 \n"
+ "vadd.f32 s2, s1, s0 \n"
+ "vadd.f32 s4, s3, s2 \n"
+ "vadd.f32 s6, s5, s4 \n"
+ "vadd.f32 s8, s7, s6 \n"
+ "vadd.f32 s10, s9, s8 \n"
+ "vadd.f32 s12, s11, s10 \n"
+ "vadd.f32 s14, s13, s12 \n"
+ "vadd.f32 s16, s15, s14 \n"
+ "vadd.f32 s18, s17, s16 \n"
+ "vadd.f32 s20, s19, s18 \n"
+ "vadd.f32 s22, s21, s20 \n"
+ "vadd.f32 s24, s23, s22 \n"
+ "vadd.f32 s26, s25, s24 \n"
+ "vadd.f32 s28, s27, s26 \n"
+ "vadd.f32 s30, s29, s28 \n"
+ "vadd.f32 s31, s29, s30 \n"
+ "vcmp.f32 s31, #0.0 \n"
+ "vmrs APSR_nzcv, fpscr \n"
+ "beq cleaned \n"
+ "mov r3, r2 \n"
+ "cleaned: \n"
+ "mov r0, r3 \n"
+
+ "bx lr \n"
+ );
+}
+
+/**
+ * Service handler for clear FP register.
+ */
+static void fpu_service_clear_fp_register(void)
+{
+ psa_msg_t msg;
+ psa_status_t r;
+
+ psa_get(TFM_FPU_SERVICE_CLEAR_FP_REGISTER_SIGNAL, &msg);
+ switch (msg.type) {
+ case PSA_IPC_CONNECT:
+ psa_reply(msg.handle, PSA_SUCCESS);
+ break;
+ case PSA_IPC_CALL:
+ if (check_fp_restored_service()) {
+ clear_fp_regs();
+ r = PSA_SUCCESS;
+ } else {
+ r = PSA_ERROR_INVALID_ARGUMENT;
+ }
+ psa_reply(msg.handle, r);
+ break;
+ case PSA_IPC_DISCONNECT:
+ psa_reply(msg.handle, PSA_SUCCESS);
+ break;
+ default:
+ /* Should not come here */
+ tfm_abort();
+ break;
+ }
+}
+
+/**
+ * Service handler for checking FP register.
+ */
+static void fpu_service_check_fp_register(void)
+{
+ psa_msg_t msg;
+
+ psa_get(TFM_FPU_SERVICE_CHECK_FP_REGISTER_SIGNAL, &msg);
+ switch (msg.type) {
+ case PSA_IPC_CONNECT:
+ psa_reply(msg.handle, PSA_SUCCESS);
+ break;
+ case PSA_IPC_CALL:
+ if (is_fp_cleaned()) {
+ change_fp_in_service();
+ psa_reply(msg.handle, PSA_SUCCESS);
+ } else {
+ psa_reply(msg.handle, PSA_ERROR_GENERIC_ERROR);
+ }
+ break;
+ case PSA_IPC_DISCONNECT:
+ psa_reply(msg.handle, PSA_SUCCESS);
+ break;
+ default:
+ /* Should not come here */
+ tfm_abort();
+ break;
+ }
+}
+
+/**
+ * FP service partition main thread.
+ */
+void fpu_service_test_main(void *param)
+{
+ uint32_t signals = 0;
+
+ clear_fp_regs();
+ while (1) {
+ signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+ if (signals & TFM_FPU_SERVICE_CLEAR_FP_REGISTER_SIGNAL) {
+ fpu_service_clear_fp_register();
+ } else if (signals & TFM_FPU_SERVICE_CHECK_FP_REGISTER_SIGNAL) {
+ fpu_service_check_fp_register();
+ } else {
+ /* Should not come here */
+ tfm_abort();
+ }
+ }
+}
diff --git a/test/test_services/tfm_fpu_service/tfm_fpu_service_test.yaml b/test/test_services/tfm_fpu_service/tfm_fpu_service_test.yaml
new file mode 100644
index 0000000..96a05d9
--- /dev/null
+++ b/test/test_services/tfm_fpu_service/tfm_fpu_service_test.yaml
@@ -0,0 +1,33 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+ "psa_framework_version": 1.0,
+ "name": "TFM_SP_FPU_SERVICE_TEST",
+ "type": "APPLICATION-ROT",
+ "priority": "NORMAL",
+ "entry_point": "fpu_service_test_main",
+ "stack_size": "0x0220",
+ "secure_functions": [
+ ],
+ "services" : [
+ {
+ "name": "TFM_FPU_SERVICE_CLEAR_FP_REGISTER",
+ "sid": "0x0000F090",
+ "non_secure_clients": false,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_FPU_SERVICE_CHECK_FP_REGISTER",
+ "sid": "0x0000F091",
+ "non_secure_clients": false,
+ "version": 1,
+ "version_policy": "STRICT"
+ }
+ ]
+}
diff --git a/test/test_services/tfm_secure_client_service/tfm_secure_client_service.yaml b/test/test_services/tfm_secure_client_service/tfm_secure_client_service.yaml
index 8943133..b448017 100644
--- a/test/test_services/tfm_secure_client_service/tfm_secure_client_service.yaml
+++ b/test/test_services/tfm_secure_client_service/tfm_secure_client_service.yaml
@@ -56,6 +56,8 @@
"TFM_FWU_REQUEST_REBOOT",
"TFM_FWU_ACCEPT",
"IPC_SERVICE_TEST_STATELESS_ROT",
- "TFM_ATTEST_TEST_GET_PUBLIC_KEY"
+ "TFM_ATTEST_TEST_GET_PUBLIC_KEY",
+ "TFM_FPU_SERVICE_CLEAR_FP_REGISTER",
+ "TFM_FPU_SERVICE_CHECK_FP_REGISTER"
]
}
diff --git a/test/test_services/tfm_test_manifest_list.yaml b/test/test_services/tfm_test_manifest_list.yaml
index 791b64f..bd11cfd 100644
--- a/test/test_services/tfm_test_manifest_list.yaml
+++ b/test/test_services/tfm_test_manifest_list.yaml
@@ -158,6 +158,20 @@
"*tfm_*partition_flih_test.*"
]
}
+ },
+ {
+ "name": "TFM FPU Test Service",
+ "short_name": "TFM_SP_FPU_SERVICE_TEST",
+ "manifest": "tfm_fpu_service/tfm_fpu_service_test.yaml",
+ "output_path": "test_services/tfm_fpu_service",
+ "conditional": "@TEST_S_FPU@",
+ "version_major": 0,
+ "version_minor": 1,
+ "linker_pattern": {
+ "library_list": [
+ "*tfm_*partition_fpu_service.*"
+ ]
+ }
}
]
}