FPU: Change interrupt test cases
Using timer interrupt to test FPU registers protection is not efficient
and direct. This patch refine test cases about FPU interrupt protection.
1. In secure, case 3 triggers a secure interrupt in secure client to
test both caller and callee registers protection.
2. In non-secure, case 3 triggers a non-secure interrupt in non-secure
client to test caller registers protection.
3. In non-secure, case 4 calls psa_call to enter secure world and then
secure service triggers a non-secure interrupt to test caller
and callee registers protection.
Signed-off-by: Jianliang Shen <jianliang.shen@arm.com>
Change-Id: I17d4f5d63c282d78db58ed57cea5b0d1f3b0da65
diff --git a/test/secure_fw/common_test_services/tfm_secure_client_service/tfm_secure_client_service.yaml b/test/secure_fw/common_test_services/tfm_secure_client_service/tfm_secure_client_service.yaml
index 0dacb05..350d1f7 100644
--- a/test/secure_fw/common_test_services/tfm_secure_client_service/tfm_secure_client_service.yaml
+++ b/test/secure_fw/common_test_services/tfm_secure_client_service/tfm_secure_client_service.yaml
@@ -54,7 +54,8 @@
"TFM_FIRMWARE_UPDATE_SERVICE",
"IPC_SERVICE_TEST_BASIC",
"IPC_SERVICE_TEST_STATELESS_ROT",
- "TFM_FPU_SERVICE_CHECK_FP_CALLEE_REGISTER",
+ "TFM_FPU_CHECK_FP_CALLEE_REGISTER",
+ "TFM_FPU_TEST_NS_PREEMPT_S",
"IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM",
"IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM",
"IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM",
diff --git a/test/secure_fw/suites/fpu/fpu_tests_common.c b/test/secure_fw/suites/fpu/fpu_tests_common.c
index 3c1821d..7627c6c 100644
--- a/test/secure_fw/suites/fpu/fpu_tests_common.c
+++ b/test/secure_fw/suites/fpu/fpu_tests_common.c
@@ -8,7 +8,6 @@
#include <string.h>
#include "fpu_tests_common.h"
-
__attribute__((naked))
void fp_func_jump_template(uintptr_t *func_table, uintptr_t *func_return,
uint32_t func_num)
@@ -105,3 +104,14 @@
TEST_FAIL("FP callee registers are not correctly cleared!");
}
}
+
+__attribute__((naked)) uint32_t fpu_interrupt_trigger(uint32_t IRQ_NUM){
+ __asm volatile(
+ "push {r7, lr} \n"
+ /* Software Trigger Interrupt Register address is 0xE000EF00. */
+ "ldr r7, =0xE000EF00 \n"
+ "str r0, [r7] \n"
+ "dsb 0xF \n"
+ "pop {r7, pc} \n"
+ );
+}
diff --git a/test/secure_fw/suites/fpu/fpu_tests_common.h b/test/secure_fw/suites/fpu/fpu_tests_common.h
index 105678d..c9428f9 100644
--- a/test/secure_fw/suites/fpu/fpu_tests_common.h
+++ b/test/secure_fw/suites/fpu/fpu_tests_common.h
@@ -14,6 +14,7 @@
#endif
#include "psa/client.h"
+#include "tfm_peripherals_def.h"
#include "test_framework_helpers.h"
#ifdef TFM_PSA_API
#include "psa_manifest/sid.h"
@@ -24,9 +25,6 @@
#endif
#define LOOP_ITERATIONS (300U)
-#define LOOPS_S_INT_TEST (50U)
-#define LOOPS_NS_INT_TEST (5000000U)
-#define WAIT_S_INT (2000U)
#define NR_FP_REG (32U)
#define NR_FP_CALLER_REG (NR_FP_REG / 2)
@@ -35,11 +33,6 @@
#define FP_CALLER_BUF_SIZE (NR_FP_CALLER_REG * sizeof(uint32_t))
#define FP_CALLEE_BUF_SIZE (NR_FP_CALLEE_REG * sizeof(uint32_t))
-#define REL_VALUE_FP_REGS_INVALIDATED (0xDEADBEEF)
-
-#define S_TIMER_TRIGGERED (0x19)
-#define S_TIMER_NOT_TRIGGERED (0x91)
-
#define PSA_CALL_PARAM_LEN (4U)
/*
@@ -78,6 +71,9 @@
/* Change FP callee registers. */
void populate_callee_fp_regs(const uint32_t *expecting_callee_content);
+/* Trigger FPU test interrupt. */
+uint32_t fpu_interrupt_trigger(uint32_t IRQ_NUM);
+
#ifdef __cplusplus
}
#endif
diff --git a/test/secure_fw/suites/fpu/non_secure/fpu_ns_interface_testsuite.c b/test/secure_fw/suites/fpu/non_secure/fpu_ns_interface_testsuite.c
index 0f9afca..fa314ad 100644
--- a/test/secure_fw/suites/fpu/non_secure/fpu_ns_interface_testsuite.c
+++ b/test/secure_fw/suites/fpu/non_secure/fpu_ns_interface_testsuite.c
@@ -8,13 +8,8 @@
#include <string.h>
#include "fpu_ns_tests.h"
#include "../fpu_tests_common.h"
-#include "os_wrapper/delay.h"
#include "tfm_psa_call_pack.h"
-static void tfm_fpu_test_fp_protection_secure_interrupt(
- struct test_result_t *ret);
-static void tfm_fpu_test_fp_protection_non_secure_interrupt(
- struct test_result_t *ret);
/* Test FP context protection after psa calls. */
static void tfm_fpu_test_fp_protection_ns_psa_call(struct test_result_t *ret);
@@ -22,6 +17,12 @@
static void tfm_fpu_test_fp_protection_ns_psa_call_loop(
struct test_result_t *ret);
+static void tfm_fpu_test_fp_protection_ns_after_ns_interrupt(
+ struct test_result_t *ret);
+
+static void tfm_fpu_test_fp_protection_s_after_ns_interrupt(
+ struct test_result_t *ret);
+
static struct test_t fpu_ns_tests[] = {
{
&tfm_fpu_test_clear_client_fp_data, "TFM_NS_FPU_TEST_1001",
@@ -32,14 +33,15 @@
"Test reliability of FP context protection after psa calls"
},
{
- &tfm_fpu_test_fp_protection_secure_interrupt, "TFM_NS_FPU_TEST_1003",
- "Test FP context protection in S interrupt after interrupt return"
+ &tfm_fpu_test_fp_protection_ns_after_ns_interrupt,
+ "TFM_NS_FPU_TEST_1003",
+ "Test FP context protection in NS thread after NS interrupt"
},
{
- &tfm_fpu_test_fp_protection_non_secure_interrupt,
+ &tfm_fpu_test_fp_protection_s_after_ns_interrupt,
"TFM_NS_FPU_TEST_1004",
"Test FP context protection in S thread after NS interrupt"
- }
+ },
};
void register_testsuite_ns_fpu_interface(struct test_suite_t *p_test_suite)
@@ -52,130 +54,6 @@
fpu_ns_tests, list_size, p_test_suite);
}
-/**
- * \brief Test FP context protection in S interrupt. Change FP registers in
- * non-secure thread first, then change them in S interrupt. After interrupt
- * return, check FP context protection in non-secure thread.
- * Expectation: FP registers in S interrupt should not be view in non-secure
- * thread.
- */
-static void tfm_fpu_test_fp_protection_secure_interrupt(
- struct test_result_t *ret)
-{
- psa_handle_t handle;
- psa_status_t status;
- uint8_t outvec_data[1] = {0};
- struct psa_outvec outvecs[1] = {{outvec_data, sizeof(outvec_data[0])}};
- static uint8_t i;
-
- uint32_t fp_caller_buffer[NR_FP_CALLER_REG] = {0};
- uint32_t fp_callee_buffer[NR_FP_CALLEE_REG] = {0};
- const uint32_t expecting_caller_content[NR_FP_CALLER_REG] = {
- 0xC0000000, 0xC1000000, 0xC2000000, 0xC3000000,
- 0xC4000000, 0xC5000000, 0xC6000000, 0xC7000000,
- 0xC8000000, 0xC9000000, 0xCA000000, 0xCB000000,
- 0xCC000000, 0xCD000000, 0xCE000000, 0xCF000000
- };
- const uint32_t expecting_callee_content[NR_FP_CALLEE_REG] = {
- 0xD0000000, 0xD1000000, 0xD2000000, 0xD3000000,
- 0xD4000000, 0xD5000000, 0xD6000000, 0xD7000000,
- 0xD8000000, 0xD9000000, 0xDA000000, 0xDB000000,
- 0xDC000000, 0xDD000000, 0xDE000000, 0xDF000000
- };
-
- ret->val = TEST_FAILED;
-
- /* Change FP regs */
- populate_caller_fp_regs(expecting_caller_content);
- populate_callee_fp_regs(expecting_callee_content);
-
- /* Start the timer */
- handle = psa_connect(TFM_FPU_SERVICE_START_S_TIMER_SID,
- TFM_FPU_SERVICE_START_S_TIMER_VERSION);
- if (!PSA_HANDLE_IS_VALID(handle)) {
- return;
- }
- status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
- if (status != PSA_SUCCESS) {
- return;
- }
- psa_close(handle);
-
- handle = psa_connect(TFM_FPU_SERVICE_CHECK_S_TIMER_TRIGGERED_SID,
- TFM_FPU_SERVICE_CHECK_S_TIMER_TRIGGERED_VERSION);
- if (!PSA_HANDLE_IS_VALID(handle)) {
- return;
- }
- /* Spin here */
- while (1) {
- /* Wait S interrupt triggered */
- os_wrapper_delay(WAIT_S_INT);
-
- status = psa_call(handle, PSA_IPC_CALL, NULL, 0, outvecs, 1);
- if (status == PSA_SUCCESS) {
- /* S interrupt triggered */
- if (outvec_data[0] == S_TIMER_TRIGGERED) {
- break;
- } else {
- i++;
- if (i > LOOPS_S_INT_TEST) {
- TEST_FAIL("Time out: NS thread not interrupted!\r\n");
- psa_close(handle);
- return;
- }
- }
- } else {
- TEST_FAIL("Check S interrupt triggered failed!\r\n");
- return;
- }
- }
-
- psa_close(handle);
-
- /* FP registers should be restored correctly after S interrupt */
- dump_fp_caller(fp_caller_buffer);
- dump_fp_callee(fp_callee_buffer);
-
- if ((!memcmp(fp_caller_buffer, expecting_caller_content,
- FP_CALLER_BUF_SIZE)) &&
- (!memcmp(fp_callee_buffer, expecting_callee_content,
- FP_CALLEE_BUF_SIZE))) {
- ret->val = TEST_PASSED;
- } else {
- ret->val = TEST_FAILED;
- }
-}
-
-/**
- * \brief In secure thread, trigger non-secure timer interrupt, check FP
- * context protection after NS interrupt.
- * Expectation: FP register in secure thread should be restored after NS
- * interrupt.
- */
-static void tfm_fpu_test_fp_protection_non_secure_interrupt(
- struct test_result_t *ret)
-{
- psa_handle_t handle;
- psa_status_t status;
- uint8_t *outvec_data[1] = {0};
- struct psa_outvec outvecs[1] = {{outvec_data, sizeof(outvec_data[0])}};
-
- ret->val = TEST_FAILED;
-
- handle = psa_connect(TFM_FPU_SERVICE_CHECK_NS_INTERRUPT_S_TEST_SID,
- TFM_FPU_SERVICE_CHECK_NS_INTERRUPT_S_TEST_VERSION);
- if (!PSA_HANDLE_IS_VALID(handle)) {
- return;
- }
-
- status = psa_call(handle, PSA_IPC_CALL, NULL, 0, outvecs, 1);
- if (status == PSA_SUCCESS) {
- ret->val = TEST_PASSED;
- }
-
- psa_close(handle);
-}
-
/*
* Description: Directly jump to tfm_psa_call_veneer from NS side.
* Expectation: Return psa_status_t status code.
@@ -225,8 +103,8 @@
ret->val = TEST_PASSED;
- handle = psa_connect(TFM_FPU_SERVICE_CHECK_FP_CALLEE_REGISTER_SID,
- TFM_FPU_SERVICE_CHECK_FP_CALLEE_REGISTER_VERSION);
+ handle = psa_connect(TFM_FPU_CHECK_FP_CALLEE_REGISTER_SID,
+ TFM_FPU_CHECK_FP_CALLEE_REGISTER_VERSION);
if (!PSA_HANDLE_IS_VALID(handle)) {
TEST_FAIL("PSA Connect fail!");
return;
@@ -268,3 +146,80 @@
tfm_fpu_test_fp_protection_ns_psa_call(ret);
}
}
+
+/*
+ * Description: Non-secure client trigger a non-secure interrupt and check
+ * caller and callee registers.
+ * Expectation: FP caller register in non-secure client should be restored after
+ * NS interrupt. Callee register should be same with values set in
+ * TFM_FPU_NS_TEST_Handler.
+ */
+static void tfm_fpu_test_fp_protection_ns_after_ns_interrupt(
+ struct test_result_t *ret)
+{
+ uint32_t fp_caller_buffer[NR_FP_CALLER_REG] = {0};
+ uint32_t fp_callee_buffer[NR_FP_CALLEE_REG] = {0};
+ const uint32_t expecting_caller_content[NR_FP_CALLER_REG] = {
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
+ };
+
+ /* Callee registers are changed in TFM_FPU_NS_TEST_Handler. */
+ const uint32_t expecting_callee_content[NR_FP_CALLEE_REG] = {
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
+ };
+
+ uintptr_t func_table[] = {
+ (uintptr_t)populate_caller_fp_regs, (uintptr_t)expecting_caller_content,
+ (uintptr_t)fpu_interrupt_trigger, (uintptr_t)TFM_FPU_NS_TEST_IRQ,
+ (uintptr_t)dump_fp_caller, (uintptr_t)fp_caller_buffer,
+ (uintptr_t)dump_fp_callee, (uintptr_t)fp_callee_buffer
+ };
+ uintptr_t func_return[ARRAY_SIZE(func_table)/2] = {0};
+
+ ret->val = TEST_PASSED;
+
+ fp_func_jump_template(func_table, func_return, ARRAY_SIZE(func_table)/2);
+
+ if (memcmp(fp_caller_buffer, expecting_caller_content,
+ FP_CALLER_BUF_SIZE)) {
+ TEST_FAIL("FP caller registers are not correctly retored in client!");
+ }
+
+ if (memcmp(fp_callee_buffer, expecting_callee_content,
+ FP_CALLEE_BUF_SIZE)) {
+ TEST_FAIL("FP callee registers are not same with NS interrupt change!");
+ }
+}
+
+/*
+ * Description: Secure client trigger a non-secure interrupt and check caller
+ * and callee registers in secure service.
+ * Expectation: FP register in secure client should be restored after NS
+ * interrupt.
+ */
+static void tfm_fpu_test_fp_protection_s_after_ns_interrupt(
+ struct test_result_t *ret)
+{
+ psa_handle_t handle;
+ psa_status_t status;
+
+ ret->val = TEST_PASSED;
+
+ handle = psa_connect(TFM_FPU_TEST_NS_PREEMPT_S_SID,
+ TFM_FPU_TEST_NS_PREEMPT_S_VERSION);
+ if (!PSA_HANDLE_IS_VALID(handle)) {
+ ret->val = TEST_FAILED;
+ TEST_FAIL("PSA Connect fail!");
+ return;
+ }
+
+ status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
+
+ if (status != PSA_SUCCESS) {
+ TEST_FAIL("Secure client trigger NS interrupt FP protection failed!");
+ }
+
+ psa_close(handle);
+}
diff --git a/test/secure_fw/suites/fpu/secure/fpu_s_interface_testsuite.c b/test/secure_fw/suites/fpu/secure/fpu_s_interface_testsuite.c
index 748d450..e8405ef 100755
--- a/test/secure_fw/suites/fpu/secure/fpu_s_interface_testsuite.c
+++ b/test/secure_fw/suites/fpu/secure/fpu_s_interface_testsuite.c
@@ -17,6 +17,10 @@
static void tfm_fpu_test_fp_protection_s_psa_call_loop(
struct test_result_t *ret);
+/* Test FP caller and callee protection after secure interrupt. */
+static void tfm_fpu_test_fp_protection_s_after_s_interrupt(
+ struct test_result_t *ret);
+
static struct test_t fpu_s_tests[] = {
{
&tfm_fpu_test_clear_client_fp_data, "TFM_S_FPU_TEST_1001",
@@ -25,7 +29,11 @@
{
&tfm_fpu_test_fp_protection_s_psa_call_loop, "TFM_S_FPU_TEST_1002",
"Test reliability of FP context protection after psa calls"
- }
+ },
+ {
+ &tfm_fpu_test_fp_protection_s_after_s_interrupt, "TFM_S_FPU_TEST_1003",
+ "Test FP context protection in S thread after S interrupt"
+ },
};
void register_testsuite_s_fpu_interface(struct test_suite_t *p_test_suite)
@@ -87,8 +95,8 @@
ret->val = TEST_PASSED;
- handle = psa_connect(TFM_FPU_SERVICE_CHECK_FP_CALLEE_REGISTER_SID,
- TFM_FPU_SERVICE_CHECK_FP_CALLEE_REGISTER_VERSION);
+ handle = psa_connect(TFM_FPU_CHECK_FP_CALLEE_REGISTER_SID,
+ TFM_FPU_CHECK_FP_CALLEE_REGISTER_VERSION);
if (!PSA_HANDLE_IS_VALID(handle)) {
TEST_FAIL("PSA Connect fail!");
return;
@@ -130,3 +138,47 @@
tfm_fpu_test_fp_protection_s_psa_call(ret);
}
}
+
+/*
+ * Description: Secure client trigger a secure interrupt and check caller and
+ * callee registers.
+ * Expectation: FP register in secure client should be restored after S
+ * interrupt.
+ */
+static void tfm_fpu_test_fp_protection_s_after_s_interrupt(
+ struct test_result_t *ret)
+{
+ uint32_t fp_caller_buffer[NR_FP_CALLER_REG] = {0};
+ uint32_t fp_callee_buffer[NR_FP_CALLEE_REG] = {0};
+ const uint32_t expecting_caller_content[NR_FP_CALLER_REG] = {
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
+ };
+ const uint32_t expecting_callee_content[NR_FP_CALLEE_REG] = {
+ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF
+ };
+
+ ret->val = TEST_PASSED;
+
+ uintptr_t func_table[] = {
+ (uintptr_t)populate_caller_fp_regs, (uintptr_t)expecting_caller_content,
+ (uintptr_t)populate_callee_fp_regs, (uintptr_t)expecting_callee_content,
+ (uintptr_t)fpu_interrupt_trigger, (uintptr_t)TFM_FPU_S_TEST_IRQ,
+ (uintptr_t)dump_fp_caller, (uintptr_t)fp_caller_buffer,
+ (uintptr_t)dump_fp_callee, (uintptr_t)fp_callee_buffer
+ };
+ uintptr_t func_return[ARRAY_SIZE(func_table)/2] = {0};
+
+ fp_func_jump_template(func_table, func_return, ARRAY_SIZE(func_table)/2);
+
+ if (memcmp(fp_caller_buffer, expecting_caller_content,
+ FP_CALLER_BUF_SIZE)) {
+ TEST_FAIL("FP caller registers are not correctly retored in client!");
+ }
+
+ if (memcmp(fp_callee_buffer, expecting_callee_content,
+ FP_CALLEE_BUF_SIZE)) {
+ TEST_FAIL("FP callee registers are not correctly retored in client!");
+ }
+}
diff --git a/test/secure_fw/suites/fpu/service/tfm_fpu_service_test.c b/test/secure_fw/suites/fpu/service/tfm_fpu_service_test.c
index 2f17a36..a764b77 100644
--- a/test/secure_fw/suites/fpu/service/tfm_fpu_service_test.c
+++ b/test/secure_fw/suites/fpu/service/tfm_fpu_service_test.c
@@ -13,7 +13,6 @@
#include "tfm_secure_api.h"
#include "tfm_sp_log.h"
#include "tfm_plat_test.h"
-#include "device_definition.h"
#include "fpu_tests_common.h"
/*
@@ -30,7 +29,7 @@
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
- psa_get(TFM_FPU_SERVICE_CHECK_FP_CALLEE_REGISTER_SIGNAL, &msg);
+ psa_get(TFM_FPU_CHECK_FP_CALLEE_REGISTER_SIGNAL, &msg);
switch (msg.type) {
case PSA_IPC_CONNECT:
psa_reply(msg.handle, PSA_SUCCESS);
@@ -59,142 +58,56 @@
}
}
-/**
- * Start S timer interrupt.
- * Expectation: S timer should be started.
- */
-static void fpu_client_start_secure_timer(void)
+/* Service handler for trigger NS interrupt. */
+static void fpu_service_check_fp_register_after_ns_inturrept(void)
{
psa_msg_t msg;
- psa_status_t r;
-
- r = psa_get(TFM_FPU_SERVICE_START_S_TIMER_SIGNAL, &msg);
- switch (msg.type) {
- case PSA_IPC_CONNECT:
- case PSA_IPC_DISCONNECT:
- psa_reply(msg.handle, PSA_SUCCESS);
- break;
- case PSA_IPC_CALL:
- /* Start the timer */
- tfm_plat_test_secure_timer_start();
- psa_reply(msg.handle, PSA_SUCCESS);
- break;
- default:
- psa_panic();
- break;
- }
-}
-
-/**
- * Read S timer reload value.
- * Expectation: S timer reload value should be read.
- */
-static void fpu_client_check_secure_timer_triggered(void)
-{
- psa_msg_t msg;
- psa_status_t r;
- int val;
-
- r = psa_get(TFM_FPU_SERVICE_CHECK_S_TIMER_TRIGGERED_SIGNAL, &msg);
- switch (msg.type) {
- case PSA_IPC_CONNECT:
- case PSA_IPC_DISCONNECT:
- psa_reply(msg.handle, PSA_SUCCESS);
- break;
- case PSA_IPC_CALL:
- if (msg.out_size[0] != 0) {
- /* Read the timer reload value */
- if (tfm_plat_test_secure_timer_get_reload_value()
- == REL_VALUE_FP_REGS_INVALIDATED) {
- val = S_TIMER_TRIGGERED;
- } else {
- val = S_TIMER_NOT_TRIGGERED;
- }
- psa_write(msg.handle, 0, &val, 1);
- r = PSA_SUCCESS;
- } else {
- r = PSA_ERROR_PROGRAMMER_ERROR;
- }
- psa_reply(msg.handle, r);
- break;
- default:
- psa_panic();
- break;
- }
-}
-
-/**
- * Test FP context protection after NS interrupt.
- * Expectation: FP register in secure thread should be restored after NS
- * interrupt.
- */
-int fpu_client_non_secure_interrupt_secure_test(void)
-{
- psa_msg_t msg;
- psa_status_t r;
- static uint32_t i;
uint32_t fp_caller_buffer[NR_FP_CALLER_REG] = {0};
- const uint32_t expecting_caller_content[NR_FP_CALLER_REG] = {
- 0xB0000000, 0xB1000000, 0xB2000000, 0xB3000000,
- 0xB4000000, 0xB5000000, 0xB6000000, 0xB7000000,
- 0xB8000000, 0xB9000000, 0xBA000000, 0xBB000000,
- 0xBC000000, 0xBD000000, 0xBE000000, 0xBF000000
- };
uint32_t fp_callee_buffer[NR_FP_CALLEE_REG] = {0};
+ const uint32_t expecting_caller_content[NR_FP_CALLER_REG] = {
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+ 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF
+ };
const uint32_t expecting_callee_content[NR_FP_CALLEE_REG] = {
- 0xC0000000, 0xC1000000, 0xC2000000, 0xC3000000,
- 0xC4000000, 0xC5000000, 0xC6000000, 0xC7000000,
- 0xC8000000, 0xC9000000, 0xCA000000, 0xCB000000,
- 0xCC000000, 0xCD000000, 0xCE000000, 0xCF000000
+ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+ 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF
};
- r = psa_get(TFM_FPU_SERVICE_CHECK_NS_INTERRUPT_S_TEST_SIGNAL, &msg);
+ uintptr_t func_table[] = {
+ (uintptr_t)populate_caller_fp_regs, (uintptr_t)expecting_caller_content,
+ (uintptr_t)populate_callee_fp_regs, (uintptr_t)expecting_callee_content,
+ (uintptr_t)fpu_interrupt_trigger, (uintptr_t)TFM_FPU_NS_TEST_IRQ,
+ (uintptr_t)dump_fp_caller, (uintptr_t)fp_caller_buffer,
+ (uintptr_t)dump_fp_callee, (uintptr_t)fp_callee_buffer
+ };
+ uintptr_t func_return[ARRAY_SIZE(func_table)/2] = {0};
+
+ psa_get(TFM_FPU_TEST_NS_PREEMPT_S_SIGNAL, &msg);
+
switch (msg.type) {
case PSA_IPC_CONNECT:
- case PSA_IPC_DISCONNECT:
psa_reply(msg.handle, PSA_SUCCESS);
break;
case PSA_IPC_CALL:
- /* Change FP regs */
- populate_caller_fp_regs(expecting_caller_content);
- populate_callee_fp_regs(expecting_callee_content);
- /* Start the timer */
- tfm_plat_test_non_secure_timer_start();
- LOG_DBGFMT("Wait for NS timer interrupt!\r\n");
- /* Spin here */
- while (1) {
- /* NS interrupt triggered */
- if (tfm_plat_test_non_secure_timer_get_reload_value()
- == REL_VALUE_FP_REGS_INVALIDATED) {
- LOG_DBGFMT("S thread interrupted by NS timer interrupt!\r\n");
- break;
- } else {
- i++;
- if (i > LOOPS_NS_INT_TEST) {
- LOG_DBGFMT("Time out: S thread is not interrupted!\r\n");
- break;
- }
- }
- }
- if (i > LOOPS_NS_INT_TEST) {
- /* Error for time out */
- r = PSA_ERROR_GENERIC_ERROR;
+ fp_func_jump_template(func_table, func_return, ARRAY_SIZE(func_table)/2);
+
+ if (memcmp(fp_caller_buffer, expecting_caller_content,
+ FP_CALLER_BUF_SIZE)) {
+ TEST_LOG("FP caller registers are not correctly retored!");
+ psa_reply(msg.handle, PSA_ERROR_GENERIC_ERROR);
} else {
- /* FP register should be restored after NS interrupt. */
- dump_fp_caller(fp_caller_buffer);
- dump_fp_callee(fp_callee_buffer);
- if ((!memcmp(fp_caller_buffer, expecting_caller_content,
- FP_CALLER_BUF_SIZE)) &&
- (!memcmp(fp_callee_buffer, expecting_callee_content,
- FP_CALLEE_BUF_SIZE))) {
- r = PSA_SUCCESS;
+ if (memcmp(fp_callee_buffer, expecting_callee_content,
+ FP_CALLEE_BUF_SIZE)) {
+ TEST_LOG("FP callee registers are not correctly retored!");
+ psa_reply(msg.handle, PSA_ERROR_GENERIC_ERROR);
} else {
- r = PSA_ERROR_GENERIC_ERROR;
+ psa_reply(msg.handle, PSA_SUCCESS);
}
}
- /* Reply with status */
- psa_reply(msg.handle, r);
+ break;
+ case PSA_IPC_DISCONNECT:
+ psa_reply(msg.handle, PSA_SUCCESS);
break;
default:
psa_panic();
@@ -209,14 +122,10 @@
while (1) {
signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
- if (signals & TFM_FPU_SERVICE_CHECK_FP_CALLEE_REGISTER_SIGNAL) {
+ if (signals & TFM_FPU_CHECK_FP_CALLEE_REGISTER_SIGNAL) {
fpu_service_check_fp_register();
- } else if (signals & TFM_FPU_SERVICE_START_S_TIMER_SIGNAL) {
- fpu_client_start_secure_timer();
- } else if (signals & TFM_FPU_SERVICE_CHECK_S_TIMER_TRIGGERED_SIGNAL) {
- fpu_client_check_secure_timer_triggered();
- } else if (signals & TFM_FPU_SERVICE_CHECK_NS_INTERRUPT_S_TEST_SIGNAL) {
- fpu_client_non_secure_interrupt_secure_test();
+ } else if (signals & TFM_FPU_TEST_NS_PREEMPT_S_SIGNAL) {
+ fpu_service_check_fp_register_after_ns_inturrept();
} else {
psa_panic();
}
diff --git a/test/secure_fw/suites/fpu/service/tfm_fpu_service_test.yaml b/test/secure_fw/suites/fpu/service/tfm_fpu_service_test.yaml
index 1adc9f8..a9b8c72 100644
--- a/test/secure_fw/suites/fpu/service/tfm_fpu_service_test.yaml
+++ b/test/secure_fw/suites/fpu/service/tfm_fpu_service_test.yaml
@@ -17,7 +17,7 @@
],
"services" : [
{
- "name": "TFM_FPU_SERVICE_CHECK_FP_CALLEE_REGISTER",
+ "name": "TFM_FPU_CHECK_FP_CALLEE_REGISTER",
"sid": "0x0000F091",
"connection_based": true,
"non_secure_clients": true,
@@ -25,38 +25,12 @@
"version_policy": "STRICT"
},
{
- "name": "TFM_FPU_SERVICE_START_S_TIMER",
+ "name": "TFM_FPU_TEST_NS_PREEMPT_S",
"sid": "0x0000F092",
"connection_based": true,
"non_secure_clients": true,
"version": 1,
"version_policy": "STRICT"
- },
- {
- "name": "TFM_FPU_SERVICE_CHECK_S_TIMER_TRIGGERED",
- "sid": "0x0000F093",
- "connection_based": true,
- "non_secure_clients": true,
- "version": 1,
- "version_policy": "STRICT"
- },
- {
- "name": "TFM_FPU_SERVICE_CHECK_NS_INTERRUPT_S_TEST",
- "sid": "0x0000F094",
- "connection_based": true,
- "non_secure_clients": true,
- "version": 1,
- "version_policy": "STRICT"
}
],
- "mmio_regions": [
- {
- "name": "TFM_PERIPHERAL_TIMER0",
- "permission": "READ-WRITE"
- },
- {
- "name": "TFM_PERIPHERAL_TIMER1",
- "permission": "READ-WRITE"
- }
- ]
}