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"
-    }
-  ]
 }