Test: Add testcases for IRQ handling

This patch contains a test cases exercising the secure IRQ handling
feature of TF-M.

Details of the change:
 * Add documentation on the tests
 * Create new service which handles timer0 interrupts
 * Link timer0 driver structures to IRQ test service
 * Implement the testcases in the positive test suite, the new IRQ test
   service and in TFM_SP_CORE_TEST_2

Change-Id: If7e3d1b57eac4de9ff6e01f0b04efd04bc443545
Signed-off-by: Mate Toth-Pal <mate.toth-pal@arm.com>
diff --git a/docs/user_guides/services/core_test_services_integration_guide.rst b/docs/user_guides/services/core_test_services_integration_guide.rst
index a8f6b8c..c3f213f 100644
--- a/docs/user_guides/services/core_test_services_integration_guide.rst
+++ b/docs/user_guides/services/core_test_services_integration_guide.rst
@@ -54,6 +54,44 @@
 or all of the functions, by returning the values expected by the test cases,
 without actually executing the action expected by the test.
 
+******************
+IRQ handling tests
+******************
+
+The IRQ handling test currently tests the following scenarios:
+
+- NS code execution is interrupted by a secure IRQ (``IRQ_TEST_SCENARIO_1``)
+- S code execution is interrupted by a secure IRQ, The handler is not the
+  interrupted service (``IRQ_TEST_SCENARIO_2``)
+- S code execution is interrupted by a secure IRQ, The handler is the
+  interrupted service (``IRQ_TEST_SCENARIO_3``)
+- S code waits for an interrupt (calling ``psa_wait()``), the handler is in
+  the service that is waiting, ``psa_eoi()`` is called after ``psa_wait()`` returns
+  (``IRQ_TEST_SCENARIO_4``)
+
+The following test services participate in the test execution:
+
+- ``TFM_IRQ_TEST_1`` has the role of the interrupted partition with the IRQ
+  handler
+- ``TFM_SP_CORE_TEST_2`` has the role of the interrupted partition without the
+  IRQ handler
+
+All the test executions are initiated from the NS positive test suite. For each
+scenario the non-secure testcase calls the following secure functions in order:
+
+1. prepare_test_scenario for ``TFM_IRQ_TEST_1``
+2. prepare_test_scenario for ``TFM_SP_CORE_TEST_2``
+3. execute_test_scenario for ``TFM_IRQ_TEST_1``
+4. execute_test_scenario for ``TFM_SP_CORE_TEST_2``
+
+During these steps, the ``TFM_IRQ_TEST_1`` sets up a timer with a convenient
+init value, and depending on the scenario, one of the services, or the NS code
+enters a busy wait waiting for the timer interrupt to be raised. In case of
+``IRQ_TEST_SCENARIO_3``, when ``PSA API`` is used, the execute_test_scenario
+request of the NS code is only replied when the IRQ is handled, so no explicit
+busy wait is required. In all the other cases, handling of the irq is signalled
+to the waiting party by setting a variable in a non-secure memory location.
+
 --------------
 
 *Copyright (c) 2019, Arm Limited. All rights reserved.*
\ No newline at end of file
diff --git a/interface/include/tfm_veneers.h b/interface/include/tfm_veneers.h
index 71bc9e8..92856b3 100644
--- a/interface/include/tfm_veneers.h
+++ b/interface/include/tfm_veneers.h
@@ -100,6 +100,8 @@
 psa_status_t tfm_spm_core_test_2_sfn_invert_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 psa_status_t tfm_spm_core_test_2_check_caller_client_id_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 psa_status_t tfm_spm_core_test_2_get_every_second_byte_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_spm_core_test_2_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_spm_core_test_2_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 #endif /* TFM_PARTITION_TEST_CORE */
 
 #ifdef TFM_PARTITION_TEST_SECURE_SERVICES
@@ -115,6 +117,12 @@
 /******** TFM_SP_IPC_CLIENT_TEST ********/
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_IRQ_TEST_1 ********/
+psa_status_t tfm_spm_irq_test_1_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_spm_irq_test_1_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+#endif /* TFM_PARTITION_TEST_CORE */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/platform/ext/common/armclang/tfm_common_s.sct b/platform/ext/common/armclang/tfm_common_s.sct
index 27f539b..24bdbae 100644
--- a/platform/ext/common/armclang/tfm_common_s.sct
+++ b/platform/ext/common/armclang/tfm_common_s.sct
@@ -136,6 +136,14 @@
     }
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
+#ifdef TFM_PARTITION_TEST_CORE
+    TFM_IRQ_TEST_1 +0 ALIGN 32 {
+        *tfm_irq_test_service_1.* (+RO)
+        *timer_cmsdk* (+RO)
+        *(TFM_IRQ_TEST_1_ATTR_FN)
+    }
+#endif /* TFM_PARTITION_TEST_CORE */
+
     /*
      * This empty, zero long execution region is here to mark the end address
      * of APP RoT code.
@@ -343,6 +351,20 @@
 #endif
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
+#ifdef TFM_PARTITION_TEST_CORE
+    TFM_IRQ_TEST_1_DATA +0 ALIGN 32 {
+        *tfm_irq_test_service_1.* (+RW +ZI)
+        *timer_cmsdk* (+RW +ZI)
+        *(TFM_IRQ_TEST_1_ATTR_RW)
+        *(TFM_IRQ_TEST_1_ATTR_ZI)
+    }
+
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
+    TFM_IRQ_TEST_1_STACK +0 ALIGN 128 EMPTY 0x0400 {
+    }
+#endif
+#endif /* TFM_PARTITION_TEST_CORE */
+
     /*
      * This empty, zero long execution region is here to mark the end address
      * of APP RoT RW and Stack.
diff --git a/platform/ext/common/gcc/tfm_common_s.ld b/platform/ext/common/gcc/tfm_common_s.ld
index b287726..c17135a 100644
--- a/platform/ext/common/gcc/tfm_common_s.ld
+++ b/platform/ext/common/gcc/tfm_common_s.ld
@@ -113,6 +113,11 @@
         LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA))
         LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_DATA))
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
+#ifdef TFM_PARTITION_TEST_CORE
+        LONG (LOADADDR(.TFM_IRQ_TEST_1_DATA))
+        LONG (ADDR(.TFM_IRQ_TEST_1_DATA))
+        LONG (SIZEOF(.TFM_IRQ_TEST_1_DATA))
+#endif /* TFM_PARTITION_TEST_CORE */
         __copy_table_end__ = .;
     } > FLASH
 
@@ -204,6 +209,14 @@
         LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK))
 #endif
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
+#ifdef TFM_PARTITION_TEST_CORE
+        LONG (ADDR(.TFM_IRQ_TEST_1_BSS))
+        LONG (SIZEOF(.TFM_IRQ_TEST_1_BSS))
+#if defined(TFM_PSA_API) || (TFM_LVL != 1)
+        LONG (ADDR(.TFM_IRQ_TEST_1_STACK))
+        LONG (SIZEOF(.TFM_IRQ_TEST_1_STACK))
+#endif
+#endif /* TFM_PARTITION_TEST_CORE */
 #if !defined(TFM_PSA_API)
         LONG (ADDR(.TFM_UNPRIV_SCRATCH))
         LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
@@ -398,6 +411,22 @@
     Image$$TFM_SP_IPC_CLIENT_TEST$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST);
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
+#ifdef TFM_PARTITION_TEST_CORE
+    .TFM_IRQ_TEST_1 : ALIGN(32)
+    {
+        *tfm_irq_test_service_1.*(.text*)
+        *tfm_irq_test_service_1.*(.rodata*)
+        *timer_cmsdk*(.text*)
+        *timer_cmsdk*(.rodata*)
+        *(TFM_IRQ_TEST_1_ATTR_FN)
+        . = ALIGN(32);
+    } > FLASH
+    Image$$TFM_IRQ_TEST_1$$RO$$Base = ADDR(.TFM_IRQ_TEST_1);
+    Image$$TFM_IRQ_TEST_1$$RO$$Limit = ADDR(.TFM_IRQ_TEST_1) + SIZEOF(.TFM_IRQ_TEST_1);
+    Image$$TFM_IRQ_TEST_1$$Base = ADDR(.TFM_IRQ_TEST_1);
+    Image$$TFM_IRQ_TEST_1$$Limit = ADDR(.TFM_IRQ_TEST_1) + SIZEOF(.TFM_IRQ_TEST_1);
+#endif /* TFM_PARTITION_TEST_CORE */
+
     /**** APPLICATION RoT RO part (CODE + RODATA) end here */
     Image$$TFM_APP_CODE_END$$Base = .;
 
@@ -893,6 +922,42 @@
 
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
+#ifdef TFM_PARTITION_TEST_CORE
+    .TFM_IRQ_TEST_1_DATA : ALIGN(32)
+    {
+        *tfm_irq_test_service_1.*(.data*)
+        *timer_cmsdk*(.data*)
+        *(TFM_IRQ_TEST_1_ATTR_RW)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_IRQ_TEST_1_DATA$$RW$$Base = ADDR(.TFM_IRQ_TEST_1_DATA);
+    Image$$TFM_IRQ_TEST_1_DATA$$RW$$Limit = ADDR(.TFM_IRQ_TEST_1_DATA) + SIZEOF(.TFM_IRQ_TEST_1_DATA);
+
+    .TFM_IRQ_TEST_1_BSS : ALIGN(32)
+    {
+        start_of_TFM_IRQ_TEST_1 = .;
+        *tfm_irq_test_service_1.*(.bss*)
+        *tfm_irq_test_service_1.*(COMMON)
+        *timer_cmsdk*(.bss*)
+        *timer_cmsdk*(COMMON)
+        *(TFM_IRQ_TEST_1_ATTR_ZI)
+        . += (. - start_of_TFM_IRQ_TEST_1) ? 0 : 4;
+        . = ALIGN(32);
+    } > RAM AT> RAM
+    Image$$TFM_IRQ_TEST_1_DATA$$ZI$$Base = ADDR(.TFM_IRQ_TEST_1_BSS);
+    Image$$TFM_IRQ_TEST_1_DATA$$ZI$$Limit = ADDR(.TFM_IRQ_TEST_1_BSS) + SIZEOF(.TFM_IRQ_TEST_1_BSS);
+
+#if defined (TFM_PSA_API) || (TFM_LVL != 1)
+    .TFM_IRQ_TEST_1_STACK : ALIGN(128)
+    {
+        . += 0x0400;
+    } > RAM
+    Image$$TFM_IRQ_TEST_1_STACK$$ZI$$Base = ADDR(.TFM_IRQ_TEST_1_STACK);
+    Image$$TFM_IRQ_TEST_1_STACK$$ZI$$Limit = ADDR(.TFM_IRQ_TEST_1_STACK) + SIZEOF(.TFM_IRQ_TEST_1_STACK);
+#endif
+
+#endif /* TFM_PARTITION_TEST_CORE */
+
     /**** APPLICATION RoT DATA end here */
     Image$$TFM_APP_RW_STACK_END$$Base = .;
 
diff --git a/platform/ext/target/mps2/an519/armclang/startup_cmsdk_mps2_an519_s.s b/platform/ext/target/mps2/an519/armclang/startup_cmsdk_mps2_an519_s.s
index 363d83e..2bcbb67 100644
--- a/platform/ext/target/mps2/an519/armclang/startup_cmsdk_mps2_an519_s.s
+++ b/platform/ext/target/mps2/an519/armclang/startup_cmsdk_mps2_an519_s.s
@@ -58,7 +58,7 @@
                 DCD     NONSEC_WATCHDOG_RESET_Handler  ; - 0 Non-Secure Watchdog Reset Handler
                 DCD     NONSEC_WATCHDOG_Handler        ; - 1 Non-Secure Watchdog Handler
                 DCD     S32K_TIMER_Handler             ; - 2 S32K Timer Handler
-                DCD     TIMER0_Handler                 ; - 3 TIMER 0 Handler
+                DCD     TFM_TIMER0_IRQ_Handler         ; - 3 TIMER 0 Handler
                 DCD     TIMER1_Handler                 ; - 4 TIMER 1 Handler
                 DCD     DUALTIMER_Handler              ; - 5 Dual Timer Handler
                 DCD     0                              ; Reserved - 6
@@ -219,7 +219,7 @@
                 EXPORT NONSEC_WATCHDOG_RESET_Handler   [WEAK] ; - 0 Non-Secure Watchdog Reset Handler
                 EXPORT NONSEC_WATCHDOG_Handler         [WEAK] ; - 1 Non-Secure Watchdog Handler
                 EXPORT S32K_TIMER_Handler              [WEAK] ; - 2 S32K Timer Handler
-                EXPORT TIMER0_Handler                  [WEAK] ; - 3 TIMER 0 Handler
+                EXPORT TFM_TIMER0_IRQ_Handler          [WEAK] ; - 3 TIMER 0 Handler
                 EXPORT TIMER1_Handler                  [WEAK] ; - 4 TIMER 1 Handler
                 EXPORT DUALTIMER_Handler               [WEAK] ; - 5 Dual Timer Handler
 ; External Interrupts
@@ -292,7 +292,7 @@
 NONSEC_WATCHDOG_RESET_Handler  ; - 0 Non-Secure Watchdog Reset Handler
 NONSEC_WATCHDOG_Handler        ; - 1 Non-Secure Watchdog Handler
 S32K_TIMER_Handler             ; - 2 S32K Timer Handler
-TIMER0_Handler                 ; - 3 TIMER 0 Handler
+TFM_TIMER0_IRQ_Handler         ; - 3 TIMER 0 Handler
 TIMER1_Handler                 ; - 4 TIMER 1 Handler
 DUALTIMER_Handler              ; - 5 Dual Timer Handler
 ; External Interrupts
diff --git a/platform/ext/target/mps2/an519/gcc/startup_cmsdk_mps2_an519_s.S b/platform/ext/target/mps2/an519/gcc/startup_cmsdk_mps2_an519_s.S
index fefc1cc..e7302b1 100644
--- a/platform/ext/target/mps2/an519/gcc/startup_cmsdk_mps2_an519_s.S
+++ b/platform/ext/target/mps2/an519/gcc/startup_cmsdk_mps2_an519_s.S
@@ -47,7 +47,7 @@
     .long    NONSEC_WATCHDOG_RESET_Handler  /* 0: Non-Secure Watchdog Reset Handler */
     .long    NONSEC_WATCHDOG_Handler        /* 1: Non-Secure Watchdog Handler */
     .long    S32K_TIMER_Handler             /* 2: S32K Timer Handler */
-    .long    TIMER0_Handler                 /* 3: TIMER 0 Handler */
+    .long    TFM_TIMER0_IRQ_Handler         /* 3: TIMER 0 Handler */
     .long    TIMER1_Handler                 /* 4: TIMER 1 Handler */
     .long    DUALTIMER_Handler              /* 5: Dual Timer Handler */
     .long    0                              /* 6: Reserved */
@@ -344,7 +344,7 @@
     def_irq_handler     NONSEC_WATCHDOG_RESET_Handler  /* 0: Non-Secure Watchdog Reset Handler */
     def_irq_handler     NONSEC_WATCHDOG_Handler        /* 1: Non-Secure Watchdog Handler */
     def_irq_handler     S32K_TIMER_Handler             /* 2: S32K Timer Handler */
-    def_irq_handler     TIMER0_Handler                 /* 3: TIMER 0 Handler */
+    def_irq_handler     TFM_TIMER0_IRQ_Handler         /* 3: TIMER 0 Handler */
     def_irq_handler     TIMER1_Handler                 /* 4: TIMER 1 Handler */
     def_irq_handler     DUALTIMER_Handler              /* 5: Dual Timer Handler */
     def_irq_handler     MPC_Handler                    /* 9 MPC Combined (Secure) Handler */
diff --git a/platform/ext/target/mps2/an519/retarget/platform_retarget_dev.c b/platform/ext/target/mps2/an519/retarget/platform_retarget_dev.c
index 1540586..2e48657 100644
--- a/platform/ext/target/mps2/an519/retarget/platform_retarget_dev.c
+++ b/platform/ext/target/mps2/an519/retarget/platform_retarget_dev.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018 ARM Limited
+ * Copyright (c) 2016-2019 Arm Limited
  *
  * Licensed under the Apache License Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
 #include "platform_retarget_dev.h"
 #include "platform_retarget.h"
 #include "system_cmsdk_mps2_an519.h"
+#include "platform/include/tfm_plat_defs.h"
 
 /* ARM UART driver structures */
 #ifdef ARM_UART0_S
@@ -300,12 +301,16 @@
 
 /* CMSDK Timer driver structures */
 #ifdef CMSDK_TIMER0_S
-static const struct cmsdk_timer_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S = {
-    .base = CMSDK_TIMER0_BASE_S};
-static struct cmsdk_timer_dev_data_t CMSDK_TIMER0_DEV_DATA_S = {
-    .is_initialized = 0};
-struct cmsdk_timer_dev_t CMSDK_TIMER0_DEV_S = {&(CMSDK_TIMER0_DEV_CFG_S),
-                                               &(CMSDK_TIMER0_DEV_DATA_S)};
+static const struct cmsdk_timer_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S
+    TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {.base = CMSDK_TIMER0_BASE_S};
+static struct cmsdk_timer_dev_data_t CMSDK_TIMER0_DEV_DATA_S
+    TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {.is_initialized = 0};
+
+struct cmsdk_timer_dev_t CMSDK_TIMER0_DEV_S
+       TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+       = {&(CMSDK_TIMER0_DEV_CFG_S), &(CMSDK_TIMER0_DEV_DATA_S)};
 #endif
 #ifdef CMSDK_TIMER0_NS
 static const struct cmsdk_timer_dev_cfg_t CMSDK_TIMER0_DEV_CFG_NS = {
diff --git a/platform/ext/target/mps2/an521/armclang/startup_cmsdk_mps2_an521_s.s b/platform/ext/target/mps2/an521/armclang/startup_cmsdk_mps2_an521_s.s
index 0ee9e00..f969533 100644
--- a/platform/ext/target/mps2/an521/armclang/startup_cmsdk_mps2_an521_s.s
+++ b/platform/ext/target/mps2/an521/armclang/startup_cmsdk_mps2_an521_s.s
@@ -55,7 +55,7 @@
                 DCD     NONSEC_WATCHDOG_RESET_Handler  ; - 0 Non-Secure Watchdog Reset Handler
                 DCD     NONSEC_WATCHDOG_Handler        ; - 1 Non-Secure Watchdog Handler
                 DCD     S32K_TIMER_Handler             ; - 2 S32K Timer Handler
-                DCD     TIMER0_Handler                 ; - 3 TIMER 0 Handler
+                DCD     TFM_TIMER0_IRQ_Handler         ; - 3 TIMER 0 Handler
                 DCD     TIMER1_Handler                 ; - 4 TIMER 1 Handler
                 DCD     DUALTIMER_Handler              ; - 5 Dual Timer Handler
                 DCD     0                              ; Reserved - 6
@@ -238,7 +238,7 @@
                 EXPORT NONSEC_WATCHDOG_RESET_Handler   [WEAK] ; - 0 Non-Secure Watchdog Reset Handler
                 EXPORT NONSEC_WATCHDOG_Handler         [WEAK] ; - 1 Non-Secure Watchdog Handler
                 EXPORT S32K_TIMER_Handler              [WEAK] ; - 2 S32K Timer Handler
-                EXPORT TIMER0_Handler                  [WEAK] ; - 3 TIMER 0 Handler
+                EXPORT TFM_TIMER0_IRQ_Handler          [WEAK] ; - 3 TIMER 0 Handler
                 EXPORT TIMER1_Handler                  [WEAK] ; - 4 TIMER 1 Handler
                 EXPORT DUALTIMER_Handler               [WEAK] ; - 5 Dual Timer Handler
 ; External Interrupts
@@ -311,7 +311,7 @@
 NONSEC_WATCHDOG_RESET_Handler  ; - 0 Non-Secure Watchdog Reset Handler
 NONSEC_WATCHDOG_Handler        ; - 1 Non-Secure Watchdog Handler
 S32K_TIMER_Handler             ; - 2 S32K Timer Handler
-TIMER0_Handler                 ; - 3 TIMER 0 Handler
+TFM_TIMER0_IRQ_Handler         ; - 3 TIMER 0 Handler
 TIMER1_Handler                 ; - 4 TIMER 1 Handler
 DUALTIMER_Handler              ; - 5 Dual Timer Handler
 ; External Interrupts
diff --git a/platform/ext/target/mps2/an521/gcc/startup_cmsdk_mps2_an521_s.S b/platform/ext/target/mps2/an521/gcc/startup_cmsdk_mps2_an521_s.S
index 07fd8f8..ccac392 100644
--- a/platform/ext/target/mps2/an521/gcc/startup_cmsdk_mps2_an521_s.S
+++ b/platform/ext/target/mps2/an521/gcc/startup_cmsdk_mps2_an521_s.S
@@ -47,7 +47,7 @@
     .long    NONSEC_WATCHDOG_RESET_Handler  /* 0: Non-Secure Watchdog Reset Handler */
     .long    NONSEC_WATCHDOG_Handler        /* 1: Non-Secure Watchdog Handler */
     .long    S32K_TIMER_Handler             /* 2: S32K Timer Handler */
-    .long    TIMER0_Handler                 /* 3: TIMER 0 Handler */
+    .long    TFM_TIMER0_IRQ_Handler         /* 3: TIMER 0 Handler */
     .long    TIMER1_Handler                 /* 4: TIMER 1 Handler */
     .long    DUALTIMER_Handler              /* 5: Dual Timer Handler */
     .long    MHU0_Handler                   /* 6: Message Handling Unit 0 */
@@ -310,7 +310,7 @@
     def_irq_handler     NONSEC_WATCHDOG_RESET_Handler  /* 0: Non-Secure Watchdog Reset Handler */
     def_irq_handler     NONSEC_WATCHDOG_Handler        /* 1: Non-Secure Watchdog Handler */
     def_irq_handler     S32K_TIMER_Handler             /* 2: S32K Timer Handler */
-    def_irq_handler     TIMER0_Handler                 /* 3: TIMER 0 Handler */
+    def_irq_handler     TFM_TIMER0_IRQ_Handler         /* 3: TIMER 0 Handler */
     def_irq_handler     TIMER1_Handler                 /* 4: TIMER 1 Handler */
     def_irq_handler     DUALTIMER_Handler              /* 5: Dual Timer Handler */
     def_irq_handler     MHU0_Handler                   /* 6: Message Handling Unit 0 */
diff --git a/platform/ext/target/mps2/an521/retarget/platform_retarget_dev.c b/platform/ext/target/mps2/an521/retarget/platform_retarget_dev.c
index a7c70da..a281960 100644
--- a/platform/ext/target/mps2/an521/retarget/platform_retarget_dev.c
+++ b/platform/ext/target/mps2/an521/retarget/platform_retarget_dev.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018 ARM Limited
+ * Copyright (c) 2016-2019 Arm Limited
  *
  * Licensed under the Apache License Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
 #include "platform_retarget_dev.h"
 #include "platform_retarget.h"
 #include "system_cmsdk_mps2_an521.h"
+#include "platform/include/tfm_plat_defs.h"
 
 /* ARM UART driver structures */
 #ifdef ARM_UART0_S
@@ -300,12 +301,16 @@
 
 /* CMSDK Timer driver structures */
 #ifdef CMSDK_TIMER0_S
-static const struct cmsdk_timer_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S = {
-    .base = CMSDK_TIMER0_BASE_S};
-static struct cmsdk_timer_dev_data_t CMSDK_TIMER0_DEV_DATA_S = {
-    .is_initialized = 0};
-struct cmsdk_timer_dev_t CMSDK_TIMER0_DEV_S = {&(CMSDK_TIMER0_DEV_CFG_S),
-                                               &(CMSDK_TIMER0_DEV_DATA_S)};
+static const struct cmsdk_timer_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S
+    TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {.base = CMSDK_TIMER0_BASE_S};
+static struct cmsdk_timer_dev_data_t CMSDK_TIMER0_DEV_DATA_S
+    TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {.is_initialized = 0};
+
+struct cmsdk_timer_dev_t CMSDK_TIMER0_DEV_S
+       TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+       = {&(CMSDK_TIMER0_DEV_CFG_S), &(CMSDK_TIMER0_DEV_DATA_S)};
 #endif
 #ifdef CMSDK_TIMER0_NS
 static const struct cmsdk_timer_dev_cfg_t CMSDK_TIMER0_DEV_CFG_NS = {
diff --git a/platform/ext/target/mps3/an524/device/source/armclang/startup_cmsdk_mps3_an524_s.s b/platform/ext/target/mps3/an524/device/source/armclang/startup_cmsdk_mps3_an524_s.s
index 84d4d9d..ff9a8d3 100644
--- a/platform/ext/target/mps3/an524/device/source/armclang/startup_cmsdk_mps3_an524_s.s
+++ b/platform/ext/target/mps3/an524/device/source/armclang/startup_cmsdk_mps3_an524_s.s
@@ -56,7 +56,7 @@
     DCD     NONSEC_WATCHDOG_RESET_Handler ; 0 Non-Secure Watchdog Reset Handler
     DCD     NONSEC_WATCHDOG_Handler       ; 1 Non-Secure Watchdog Handler
     DCD     S32K_TIMER_Handler            ; 2 S32K Timer Handler
-    DCD     TIMER0_Handler                ; 3 TIMER 0 Handler
+    DCD     TFM_TIMER0_IRQ_Handler        ; 3 TIMER 0 Handler
     DCD     TIMER1_Handler                ; 4 TIMER 1 Handler
     DCD     DUALTIMER_Handler             ; 5 Dual Timer Handler
     DCD     0                             ; 6 Reserved
@@ -289,7 +289,7 @@
                                                 ;   Reset Handler
     EXPORT NONSEC_WATCHDOG_Handler       [WEAK] ; 1 Non-Secure Watchdog Handler
     EXPORT S32K_TIMER_Handler            [WEAK] ; 2 S32K Timer Handler
-    EXPORT TIMER0_Handler                [WEAK] ; 3 TIMER 0 Handler
+    EXPORT TFM_TIMER0_IRQ_Handler        [WEAK] ; 3 TIMER 0 Handler
     EXPORT TIMER1_Handler                [WEAK] ; 4 TIMER 1 Handler
     EXPORT DUALTIMER_Handler             [WEAK] ; 5 Dual Timer Handler
     EXPORT MHU0_Handler                  [WEAK] ; 6 Message Handling Unit 0
@@ -405,7 +405,7 @@
 NONSEC_WATCHDOG_RESET_Handler  ; 0 Non-Secure Watchdog Reset Handler
 NONSEC_WATCHDOG_Handler        ; 1 Non-Secure Watchdog Handler
 S32K_TIMER_Handler             ; 2 S32K Timer Handler
-TIMER0_Handler                 ; 3 TIMER 0 Handler
+TFM_TIMER0_IRQ_Handler         ; 3 TIMER 0 Handler
 TIMER1_Handler                 ; 4 TIMER 1 Handler
 DUALTIMER_Handler              ; 5 Dual Timer Handler
 MHU0_Handler                   ; 6 Message Handling Unit 0
diff --git a/platform/ext/target/mps3/an524/device/source/device_definition.c b/platform/ext/target/mps3/an524/device/source/device_definition.c
index 3f1e81e..7c86c3a 100644
--- a/platform/ext/target/mps3/an524/device/source/device_definition.c
+++ b/platform/ext/target/mps3/an524/device/source/device_definition.c
@@ -25,6 +25,7 @@
 
 #include "device_definition.h"
 #include "platform_base_address.h"
+#include "platform/include/tfm_plat_defs.h"
 
 /* UART CMSDK driver structures */
 #ifdef UART0_CMSDK_S
@@ -342,16 +343,19 @@
 
 /* CMSDK Timer driver structures */
 #ifdef CMSDK_TIMER0_S
-static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S = {
-    .base = CMSDK_TIMER0_BASE_S
-};
-static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_S = {
-    .is_initialized = 0
-};
-struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S = {
-    &(CMSDK_TIMER0_DEV_CFG_S),
-    &(CMSDK_TIMER0_DEV_DATA_S)
-};
+static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S
+    TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_IRQ_TEST_1") = {
+        .base = CMSDK_TIMER0_BASE_S
+    };
+static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_S
+    TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1") = {
+        .is_initialized = 0
+    };
+struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S
+    TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1") = {
+        &(CMSDK_TIMER0_DEV_CFG_S),
+        &(CMSDK_TIMER0_DEV_DATA_S)
+    };
 #endif
 #ifdef CMSDK_TIMER0_NS
 static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_NS = {
diff --git a/platform/ext/target/mps3/an524/device/source/gcc/startup_cmsdk_mps3_an524_s.S b/platform/ext/target/mps3/an524/device/source/gcc/startup_cmsdk_mps3_an524_s.S
index d7be1ab..6e6c976 100644
--- a/platform/ext/target/mps3/an524/device/source/gcc/startup_cmsdk_mps3_an524_s.S
+++ b/platform/ext/target/mps3/an524/device/source/gcc/startup_cmsdk_mps3_an524_s.S
@@ -48,7 +48,7 @@
     .long    NONSEC_WATCHDOG_RESET_Handler  /* 0: Non-Secure Watchdog Reset Handler */
     .long    NONSEC_WATCHDOG_Handler        /* 1: Non-Secure Watchdog Handler */
     .long    S32K_TIMER_Handler             /* 2: S32K Timer Handler */
-    .long    TIMER0_Handler                 /* 3: TIMER 0 Handler */
+    .long    TFM_TIMER0_IRQ_Handler         /* 3: TIMER 0 Handler */
     .long    TIMER1_Handler                 /* 4: TIMER 1 Handler */
     .long    DUALTIMER_Handler              /* 5: Dual Timer Handler */
     .long    MHU0_Handler                   /* 6: Message Handling Unit 0 */
@@ -343,7 +343,7 @@
     def_irq_handler     NONSEC_WATCHDOG_RESET_Handler  /* 0: Non-Secure Watchdog Reset Handler */
     def_irq_handler     NONSEC_WATCHDOG_Handler        /* 1: Non-Secure Watchdog Handler */
     def_irq_handler     S32K_TIMER_Handler             /* 2: S32K Timer Handler */
-    def_irq_handler     TIMER0_Handler                 /* 3: TIMER 0 Handler */
+    def_irq_handler     TFM_TIMER0_IRQ_Handler         /* 3: TIMER 0 Handler */
     def_irq_handler     TIMER1_Handler                 /* 4: TIMER 1 Handler */
     def_irq_handler     DUALTIMER_Handler              /* 5: Dual Timer Handler */
     def_irq_handler     MHU0_Handler                   /* 6: Message Handling Unit 0 */
diff --git a/platform/ext/target/musca_a/Device/Source/armclang/startup_cmsdk_musca_s.s b/platform/ext/target/musca_a/Device/Source/armclang/startup_cmsdk_musca_s.s
index 263a0ae..547544a 100644
--- a/platform/ext/target/musca_a/Device/Source/armclang/startup_cmsdk_musca_s.s
+++ b/platform/ext/target/musca_a/Device/Source/armclang/startup_cmsdk_musca_s.s
@@ -56,8 +56,8 @@
                 DCD    NS_WATCHDOG_RESET_IRQHandler    ;  0: Non-Secure Watchdog Reset Request Interrupt
                 DCD    NS_WATCHDOG_IRQHandler          ;  1: Non-Secure Watchdog Interrupt
                 DCD    S32K_TIMER_IRQHandler           ;  2: S32K Timer Interrupt
-                DCD    TIMER0_Handler                  ;  3: CMSDK Timer 0 Interrupt
-                DCD    TIMER1_Handler                  ;  4: CMSDK Timer 1 Interrupt
+                DCD    TFM_TIMER0_IRQ_Handler          ;  3: CMSDK Timer 0 Interrupt
+                DCD    TIMER1_IRQHandler               ;  4: CMSDK Timer 1 Interrupt
                 DCD    DUALTIMER_IRQHandler            ;  5: CMSDK Dual Timer Interrupt
                 DCD    MHU0_IRQHandler                 ;  6: Message Handling Unit 0 Interrupt
                 DCD    MHU1_IRQHandler                 ;  7: Message Handling Unit 1 Interrupt
@@ -178,8 +178,8 @@
                 Default_Handler NS_WATCHDOG_RESET_IRQHandler
                 Default_Handler NS_WATCHDOG_IRQHandler
                 Default_Handler S32K_TIMER_IRQHandler
-                Default_Handler TIMER0_Handler
-                Default_Handler TIMER1_Handler
+                Default_Handler TFM_TIMER0_IRQ_Handler
+                Default_Handler TIMER1_IRQHandler
                 Default_Handler DUALTIMER_IRQHandler
                 Default_Handler MHU0_IRQHandler
                 Default_Handler MHU1_IRQHandler
diff --git a/platform/ext/target/musca_a/Device/Source/device_definition.c b/platform/ext/target/musca_a/Device/Source/device_definition.c
index 5b93b46..f65425b 100644
--- a/platform/ext/target/musca_a/Device/Source/device_definition.c
+++ b/platform/ext/target/musca_a/Device/Source/device_definition.c
@@ -395,12 +395,15 @@
 
 /* CMSDK Timers driver structures */
 #ifdef CMSDK_TIMER0_S
-static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S = {
-    .base = MUSCA_CMSDK_TIMER0_S_BASE};
-static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_S = {
-    .is_initialized = 0};
-struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S = {&(CMSDK_TIMER0_DEV_CFG_S),
-                                               &(CMSDK_TIMER0_DEV_DATA_S)};
+static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S
+    TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {.base = MUSCA_CMSDK_TIMER0_S_BASE};
+static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_S
+    TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {.is_initialized = 0};
+struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S
+    TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {&(CMSDK_TIMER0_DEV_CFG_S), &(CMSDK_TIMER0_DEV_DATA_S)};
 #endif
 #ifdef CMSDK_TIMER0_NS
 static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_NS = {
diff --git a/platform/ext/target/musca_a/Device/Source/gcc/startup_cmsdk_musca_s.S b/platform/ext/target/musca_a/Device/Source/gcc/startup_cmsdk_musca_s.S
index 37ed397..f3b5d91 100644
--- a/platform/ext/target/musca_a/Device/Source/gcc/startup_cmsdk_musca_s.S
+++ b/platform/ext/target/musca_a/Device/Source/gcc/startup_cmsdk_musca_s.S
@@ -45,8 +45,8 @@
     .long    NS_WATCHDOG_RESET_IRQHandler    /*  0: Non-Secure Watchdog Reset Request Interrupt */
     .long    NS_WATCHDOG_IRQHandler          /*  1: Non-Secure Watchdog Interrupt */
     .long    S32K_TIMER_IRQHandler           /*  2: S32K Timer Interrupt */
-    .long    TIMER0_Handler                  /*  3: CMSDK Timer 0 Interrupt */
-    .long    TIMER1_Handler                  /*  4: CMSDK Timer 1 Interrupt */
+    .long    TFM_TIMER0_IRQ_Handler          /*  3: CMSDK Timer 0 Interrupt */
+    .long    TIMER1_IRQHandler               /*  4: CMSDK Timer 1 Interrupt */
     .long    DUALTIMER_IRQHandler            /*  5: CMSDK Dual Timer Interrupt */
     .long    MHU0_IRQHandler                 /*  6: Message Handling Unit 0 Interrupt */
     .long    MHU1_IRQHandler                 /*  7: Message Handling Unit 1 Interrupt */
@@ -290,8 +290,8 @@
     def_irq_handler     NS_WATCHDOG_RESET_IRQHandler    /*  0: Non-Secure Watchdog Reset Request Interrupt */
     def_irq_handler     NS_WATCHDOG_IRQHandler          /*  1: Non-Secure Watchdog Interrupt */
     def_irq_handler     S32K_TIMER_IRQHandler           /*  2: S32K Timer Interrupt */
-    def_irq_handler     TIMER0_Handler                  /*  3: CMSDK Timer 0 Interrupt */
-    def_irq_handler     TIMER1_Handler                  /*  4: CMSDK Timer 1 Interrupt */
+    def_irq_handler     TFM_TIMER0_IRQ_Handler          /*  3: CMSDK Timer 0 Interrupt */
+    def_irq_handler     TIMER1_IRQHandler               /*  4: CMSDK Timer 1 Interrupt */
     def_irq_handler     DUALTIMER_IRQHandler            /*  5: CMSDK Dual Timer Interrupt */
     def_irq_handler     MHU0_IRQHandler                 /*  6: Message Handling Unit 0 Interrupt */
     def_irq_handler     MHU1_IRQHandler                 /*  7: Message Handling Unit 1 Interrupt */
diff --git a/platform/ext/target/musca_b1/Device/Source/armclang/startup_cmsdk_musca_s.s b/platform/ext/target/musca_b1/Device/Source/armclang/startup_cmsdk_musca_s.s
index f558489..fe00a7f 100644
--- a/platform/ext/target/musca_b1/Device/Source/armclang/startup_cmsdk_musca_s.s
+++ b/platform/ext/target/musca_b1/Device/Source/armclang/startup_cmsdk_musca_s.s
@@ -56,8 +56,8 @@
                 DCD    NS_WATCHDOG_RESET_IRQHandler    ;  0: Non-Secure Watchdog Reset Request Interrupt
                 DCD    NS_WATCHDOG_IRQHandler          ;  1: Non-Secure Watchdog Interrupt
                 DCD    S32K_TIMER_IRQHandler           ;  2: S32K Timer Interrupt
-                DCD    TIMER0_Handler                  ;  3: CMSDK Timer 0 Interrupt
-                DCD    TIMER1_Handler                  ;  4: CMSDK Timer 1 Interrupt
+                DCD    TFM_TIMER0_IRQ_Handler          ;  3: CMSDK Timer 0 Interrupt
+                DCD    TIMER1_IRQHandler               ;  4: CMSDK Timer 1 Interrupt
                 DCD    DUALTIMER_IRQHandler            ;  5: CMSDK Dual Timer Interrupt
                 DCD    MHU0_IRQHandler                 ;  6: Message Handling Unit 0 Interrupt
                 DCD    MHU1_IRQHandler                 ;  7: Message Handling Unit 1 Interrupt
@@ -178,8 +178,8 @@
                 Default_Handler NS_WATCHDOG_RESET_IRQHandler
                 Default_Handler NS_WATCHDOG_IRQHandler
                 Default_Handler S32K_TIMER_IRQHandler
-                Default_Handler TIMER0_Handler
-                Default_Handler TIMER1_Handler
+                Default_Handler TFM_TIMER0_IRQ_Handler
+                Default_Handler TIMER1_IRQHandler
                 Default_Handler DUALTIMER_IRQHandler
                 Default_Handler MHU0_IRQHandler
                 Default_Handler MHU1_IRQHandler
diff --git a/platform/ext/target/musca_b1/Device/Source/device_definition.c b/platform/ext/target/musca_b1/Device/Source/device_definition.c
index b942d29..c392f1c 100644
--- a/platform/ext/target/musca_b1/Device/Source/device_definition.c
+++ b/platform/ext/target/musca_b1/Device/Source/device_definition.c
@@ -369,12 +369,15 @@
 
 /** CMSDK Timers driver structures */
 #ifdef CMSDK_TIMER0_S
-static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S = {
-    .base = MUSCA_B1_CMSDK_TIMER0_S_BASE};
-static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_S = {
-    .is_initialized = 0};
-struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S = {&(CMSDK_TIMER0_DEV_CFG_S),
-                                               &(CMSDK_TIMER0_DEV_DATA_S)};
+static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S
+    TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {.base = MUSCA_B1_CMSDK_TIMER0_S_BASE};
+static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_S
+    TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {.is_initialized = 0};
+struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S
+    TFM_LINK_SET_RW_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
+    = {&(CMSDK_TIMER0_DEV_CFG_S), &(CMSDK_TIMER0_DEV_DATA_S)};
 #endif
 #ifdef CMSDK_TIMER0_NS
 static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_NS = {
diff --git a/platform/ext/target/musca_b1/Device/Source/gcc/startup_cmsdk_musca_s.S b/platform/ext/target/musca_b1/Device/Source/gcc/startup_cmsdk_musca_s.S
index 37ed397..f3b5d91 100644
--- a/platform/ext/target/musca_b1/Device/Source/gcc/startup_cmsdk_musca_s.S
+++ b/platform/ext/target/musca_b1/Device/Source/gcc/startup_cmsdk_musca_s.S
@@ -45,8 +45,8 @@
     .long    NS_WATCHDOG_RESET_IRQHandler    /*  0: Non-Secure Watchdog Reset Request Interrupt */
     .long    NS_WATCHDOG_IRQHandler          /*  1: Non-Secure Watchdog Interrupt */
     .long    S32K_TIMER_IRQHandler           /*  2: S32K Timer Interrupt */
-    .long    TIMER0_Handler                  /*  3: CMSDK Timer 0 Interrupt */
-    .long    TIMER1_Handler                  /*  4: CMSDK Timer 1 Interrupt */
+    .long    TFM_TIMER0_IRQ_Handler          /*  3: CMSDK Timer 0 Interrupt */
+    .long    TIMER1_IRQHandler               /*  4: CMSDK Timer 1 Interrupt */
     .long    DUALTIMER_IRQHandler            /*  5: CMSDK Dual Timer Interrupt */
     .long    MHU0_IRQHandler                 /*  6: Message Handling Unit 0 Interrupt */
     .long    MHU1_IRQHandler                 /*  7: Message Handling Unit 1 Interrupt */
@@ -290,8 +290,8 @@
     def_irq_handler     NS_WATCHDOG_RESET_IRQHandler    /*  0: Non-Secure Watchdog Reset Request Interrupt */
     def_irq_handler     NS_WATCHDOG_IRQHandler          /*  1: Non-Secure Watchdog Interrupt */
     def_irq_handler     S32K_TIMER_IRQHandler           /*  2: S32K Timer Interrupt */
-    def_irq_handler     TIMER0_Handler                  /*  3: CMSDK Timer 0 Interrupt */
-    def_irq_handler     TIMER1_Handler                  /*  4: CMSDK Timer 1 Interrupt */
+    def_irq_handler     TFM_TIMER0_IRQ_Handler          /*  3: CMSDK Timer 0 Interrupt */
+    def_irq_handler     TIMER1_IRQHandler               /*  4: CMSDK Timer 1 Interrupt */
     def_irq_handler     DUALTIMER_IRQHandler            /*  5: CMSDK Dual Timer Interrupt */
     def_irq_handler     MHU0_IRQHandler                 /*  6: Message Handling Unit 0 Interrupt */
     def_irq_handler     MHU1_IRQHandler                 /*  7: Message Handling Unit 1 Interrupt */
diff --git a/platform/include/tfm_plat_test.h b/platform/include/tfm_plat_test.h
index c3d7317..513134d 100644
--- a/platform/include/tfm_plat_test.h
+++ b/platform/include/tfm_plat_test.h
@@ -54,11 +54,13 @@
  * the timer should be long enough so that the test service can go to the state
  * where it starts waiting for the interrupt.
  */
+TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
 void tfm_plat_test_secure_timer_start(void);
 
 /**
  * \brief Stops the Secure timer and clears the timer interrupt.
  */
+TFM_LINK_SET_RO_IN_PARTITION_SECTION("TFM_IRQ_TEST_1")
 void tfm_plat_test_secure_timer_stop(void);
 
 /**
diff --git a/secure_fw/core/ipc/include/tfm_spm_signal_defs.h b/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
index 523b6b1..a508691 100644
--- a/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
+++ b/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
@@ -15,5 +15,6 @@
 #include "secure_fw/services/secure_storage/tfm_sst_signal.h"
 #include "secure_fw/services/initial_attestation/tfm_attest_signal.h"
 #include "test/test_services/tfm_ipc_client/tfm_ipc_client_partition.h"
+#include "test/test_services/tfm_irq_test_service_1/tfm_irq_test_service_1_signal.h"
 
 #endif /* __TFM_SPM_SIGNAL_DEFS_H__ */
diff --git a/secure_fw/core/ipc/tfm_secure_irq_handlers_ipc.inc b/secure_fw/core/ipc/tfm_secure_irq_handlers_ipc.inc
index 42a6086..7303a66 100644
--- a/secure_fw/core/ipc/tfm_secure_irq_handlers_ipc.inc
+++ b/secure_fw/core/ipc/tfm_secure_irq_handlers_ipc.inc
@@ -12,9 +12,25 @@
 
 /* Definitions of the signals of the IRQs (if any) */
 const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[] = {
+#ifdef TFM_PARTITION_TEST_CORE
+    { TFM_IRQ_TEST_1_ID, SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ, TFM_TIMER0_IRQ, 64 },
+#endif /* TFM_PARTITION_TEST_CORE */
 };
 
 const size_t tfm_core_irq_signals_count = sizeof(tfm_core_irq_signals) /
                                           sizeof(*tfm_core_irq_signals);
 
 /* Definitions of privileged IRQ handlers (if any) */
+#ifdef TFM_PARTITION_TEST_CORE
+void TFM_TIMER0_IRQ_Handler(void)
+{
+    __disable_irq();
+    /* It is OK to call tfm_irq_handler directly from here, as we are already
+     * in handler mode, and we will not be pre-empted as we disabled interrupts
+     */
+    tfm_irq_handler(TFM_IRQ_TEST_1_ID, SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ, TFM_TIMER0_IRQ);
+    __enable_irq();
+}
+
+#endif /* TFM_PARTITION_TEST_CORE */
+
diff --git a/secure_fw/core/tfm_irq_signal_defs.h b/secure_fw/core/tfm_irq_signal_defs.h
index e851776..2327a28 100644
--- a/secure_fw/core/tfm_irq_signal_defs.h
+++ b/secure_fw/core/tfm_irq_signal_defs.h
@@ -7,5 +7,6 @@
 #ifndef __TFM_IRQ_SIGNAL_DEFS_H__
 #define __TFM_IRQ_SIGNAL_DEFS_H__
 
+#define SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ              (1U << (27 + 4))
 
 #endif /* __TFM_IRQ_SIGNAL_DEFS_H__ */
diff --git a/secure_fw/core/tfm_secure_irq_handlers.inc b/secure_fw/core/tfm_secure_irq_handlers.inc
index 5ff583a..01e6e1e 100644
--- a/secure_fw/core/tfm_secure_irq_handlers.inc
+++ b/secure_fw/core/tfm_secure_irq_handlers.inc
@@ -11,6 +11,9 @@
 
 /* Definitions of the signals of the IRQs */
 const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[] = {
+#ifdef TFM_PARTITION_TEST_CORE
+    { TFM_IRQ_TEST_1_ID, SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ, TFM_TIMER0_IRQ, 64 },
+#endif /* TFM_PARTITION_TEST_CORE */
 };
 
 const size_t tfm_core_irq_signals_count = sizeof(tfm_core_irq_signals) /
@@ -22,5 +25,20 @@
                                   uint32_t irq_line);
 
 /* Forward declarations of unpriv IRQ handlers*/
+#ifdef TFM_PARTITION_TEST_CORE
+extern void SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ_isr(void);
+#endif /* TFM_PARTITION_TEST_CORE */
+
 
 /* Definitions of privileged IRQ handlers */
+#ifdef TFM_PARTITION_TEST_CORE
+void TFM_TIMER0_IRQ_Handler(void)
+{
+    priv_irq_handler_main(TFM_IRQ_TEST_1_ID,
+                          (uint32_t)SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ_isr,
+                          SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ,
+                          TFM_TIMER0_IRQ);
+}
+
+#endif /* TFM_PARTITION_TEST_CORE */
+
diff --git a/secure_fw/ns_callable/tfm_veneers.c b/secure_fw/ns_callable/tfm_veneers.c
index 2ba8a2c..023ce36 100644
--- a/secure_fw/ns_callable/tfm_veneers.c
+++ b/secure_fw/ns_callable/tfm_veneers.c
@@ -94,6 +94,8 @@
 psa_status_t spm_core_test_2_sfn_invert(psa_invec *, size_t, psa_outvec *, size_t);
 psa_status_t spm_core_test_2_check_caller_client_id(psa_invec *, size_t, psa_outvec *, size_t);
 psa_status_t spm_core_test_2_get_every_second_byte(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_prepare_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_execute_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
 #endif /* TFM_PARTITION_TEST_CORE */
 
 #ifdef TFM_PARTITION_TEST_SECURE_SERVICES
@@ -109,6 +111,12 @@
 /******** TFM_SP_IPC_CLIENT_TEST ********/
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_IRQ_TEST_1 ********/
+psa_status_t spm_irq_test_1_prepare_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_irq_test_1_execute_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_CORE */
+
 
 #define TFM_VENEER_FUNCTION(partition_name, sfn_name) \
     __tfm_secure_gateway_attributes__ \
@@ -206,6 +214,8 @@
 TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_sfn_invert)
 TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_check_caller_client_id)
 TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_get_every_second_byte)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_prepare_test_scenario)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_execute_test_scenario)
 #endif /* TFM_PARTITION_TEST_CORE */
 
 #ifdef TFM_PARTITION_TEST_SECURE_SERVICES
@@ -221,3 +231,9 @@
 /******** TFM_SP_IPC_CLIENT_TEST ********/
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_IRQ_TEST_1 ********/
+TFM_VENEER_FUNCTION(TFM_IRQ_TEST_1, spm_irq_test_1_prepare_test_scenario)
+TFM_VENEER_FUNCTION(TFM_IRQ_TEST_1, spm_irq_test_1_execute_test_scenario)
+#endif /* TFM_PARTITION_TEST_CORE */
+
diff --git a/secure_fw/services/tfm_partition_defs.inc b/secure_fw/services/tfm_partition_defs.inc
index 19e459d..bf195a3 100644
--- a/secure_fw/services/tfm_partition_defs.inc
+++ b/secure_fw/services/tfm_partition_defs.inc
@@ -44,6 +44,10 @@
 #define TFM_SP_IPC_CLIENT_TEST_ID (TFM_SP_BASE + 9)
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
-#define TFM_MAX_USER_PARTITIONS (10)
+#ifdef TFM_PARTITION_TEST_CORE
+#define TFM_IRQ_TEST_1_ID (TFM_SP_BASE + 10)
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#define TFM_MAX_USER_PARTITIONS (11)
 
 #endif /* __TFM_PARTITION_DEFS_INC__ */
diff --git a/secure_fw/services/tfm_partition_list.inc b/secure_fw/services/tfm_partition_list.inc
index 90344e2..41f50e1 100644
--- a/secure_fw/services/tfm_partition_list.inc
+++ b/secure_fw/services/tfm_partition_list.inc
@@ -99,4 +99,14 @@
 PARTITION_ADD_INIT_FUNC(TFM_SP_IPC_CLIENT_TEST, ipc_client_test_main);
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_IRQ_TEST_1 ********/
+#define TFM_PARTITION_TFM_IRQ_TEST_1_IRQ_COUNT 1
+PARTITION_DECLARE(TFM_IRQ_TEST_1, 0
+    | SPM_PART_FLAG_IPC
+    , "APPLICATION-ROT", TFM_IRQ_TEST_1_ID, NORMAL);
+PARTITION_ADD_INIT_FUNC(TFM_IRQ_TEST_1, tfm_irq_test_1_init);
+PARTITION_ADD_PERIPHERAL(TFM_IRQ_TEST_1, TFM_PERIPHERAL_TIMER0);
+#endif /* TFM_PARTITION_TEST_CORE */
+
 #endif /* __TFM_PARTITION_LIST_INC__ */
diff --git a/secure_fw/services/tfm_service_list.inc b/secure_fw/services/tfm_service_list.inc
index f3bf254..d408bf5 100644
--- a/secure_fw/services/tfm_service_list.inc
+++ b/secure_fw/services/tfm_service_list.inc
@@ -249,6 +249,24 @@
         1,
         TFM_VERSION_POLICY_STRICT
 },
+{
+        "SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO",
+        TFM_SP_CORE_TEST_2_ID,
+        SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SIGNAL,
+        0x00002204,
+        true,
+        1,
+        TFM_VERSION_POLICY_STRICT
+},
+{
+        "SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO",
+        TFM_SP_CORE_TEST_2_ID,
+        SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SIGNAL,
+        0x00002205,
+        true,
+        1,
+        TFM_VERSION_POLICY_STRICT
+},
 #endif /* TFM_PARTITION_TEST_CORE */
 
 #ifdef TFM_PARTITION_TEST_SECURE_SERVICES
@@ -353,4 +371,26 @@
 },
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_IRQ_TEST_1 ********/
+{
+        "SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO",
+        TFM_IRQ_TEST_1_ID,
+        SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SIGNAL,
+        0x00002300,
+        true,
+        1,
+        TFM_VERSION_POLICY_STRICT
+},
+{
+        "SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO",
+        TFM_IRQ_TEST_1_ID,
+        SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SIGNAL,
+        0x00002301,
+        true,
+        1,
+        TFM_VERSION_POLICY_STRICT
+},
+#endif /* TFM_PARTITION_TEST_CORE */
+
 #endif /* __TFM_SERVICE_LIST_INC__ */
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 9953613..945e925 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -46,9 +46,11 @@
 if (CORE_TEST_INTERACTIVE OR CORE_TEST_POSITIVE)
 	set(ENABLE_CORE_TESTS True)
 	set(ENABLE_CORE_TESTS_2 True)
+	set(ENABLE_IRQ_TEST_SERVICES True)
 else()
 	set(ENABLE_CORE_TESTS False)
 	set(ENABLE_CORE_TESTS_2 False)
+	set(ENABLE_IRQ_TEST_SERVICES False)
 endif()
 
 set(ENABLE_SECURE_STORAGE_SERVICE_TESTS TRUE)
diff --git a/test/suites/core/non_secure/core_ns_positive_testsuite.c b/test/suites/core/non_secure/core_ns_positive_testsuite.c
index 320b8fb..08f11a4 100644
--- a/test/suites/core/non_secure/core_ns_positive_testsuite.c
+++ b/test/suites/core/non_secure/core_ns_positive_testsuite.c
@@ -40,6 +40,7 @@
 static void tfm_core_test_spm_request(struct test_result_t *ret);
 static void tfm_core_test_iovec_sanitization(struct test_result_t *ret);
 static void tfm_core_test_outvec_write(struct test_result_t *ret);
+static void tfm_core_test_secure_irq(struct test_result_t *ret);
 
 static struct test_t core_tests[] = {
 CORE_TEST_DESCRIPTION(CORE_TEST_ID_NS_THREAD, tfm_core_test_ns_thread,
@@ -52,6 +53,11 @@
 CORE_TEST_DESCRIPTION(CORE_TEST_ID_MEMORY_PERMISSIONS,
     tfm_core_test_permissions,
     "Test secure service memory access permissions"),
+#endif /* TFM_PSA_API */
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_SECURE_IRQ,
+    tfm_core_test_secure_irq,
+    "Test secure irq"),
+#ifndef TFM_PSA_API
 CORE_TEST_DESCRIPTION(CORE_TEST_ID_MPU_ACCESS, tfm_core_test_mpu_access,
     "Test secure service MPU accesses"),
 #endif /* TFM_PSA_API */
@@ -420,6 +426,129 @@
     ret->val = TEST_PASSED;
 }
 
+static int32_t execute_test_scenario_ns(
+                               enum irq_test_scenario_t test_scenario,
+                               struct irq_test_execution_data_t *execution_data)
+{
+
+    switch (test_scenario) {
+    case IRQ_TEST_SCENARIO_NONE:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    case IRQ_TEST_SCENARIO_1:
+        if (execution_data->timer0_triggered) {
+            return CORE_TEST_ERRNO_TEST_FAULT;
+        }
+        while (!execution_data->timer0_triggered) {
+            ;
+        }
+        break;
+    case IRQ_TEST_SCENARIO_2:
+    case IRQ_TEST_SCENARIO_3:
+    case IRQ_TEST_SCENARIO_4:
+        /* nothing to be done here */
+        break;
+    default:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    return CORE_TEST_ERRNO_SUCCESS;
+}
+
+static int32_t tfm_core_test_secure_irq_scenario(
+                                         enum irq_test_scenario_t test_scenario)
+{
+    struct irq_test_execution_data_t execution_data = {0};
+    struct irq_test_execution_data_t *execution_data_address = &execution_data;
+    uint32_t scenario = test_scenario;
+
+    psa_invec in_vec[] = {
+                 {&scenario, sizeof(uint32_t)},
+                 {&execution_data_address,
+                                  sizeof(struct irq_test_execution_data_t *)} };
+    int32_t err;
+
+#ifdef TFM_PSA_API
+    err = psa_test_common(SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SID,
+                          SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_MIN_VER,
+                          in_vec, 2, NULL, 0);
+#else
+    err = tfm_spm_irq_test_1_prepare_test_scenario_veneer(in_vec, 2, NULL, 0);
+#endif
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        return err;
+    }
+
+#ifdef TFM_PSA_API
+    err = psa_test_common(SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SID,
+                          SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_MIN_VER,
+                          in_vec, 2, NULL, 0);
+#else
+    err = tfm_spm_core_test_2_prepare_test_scenario_veneer(in_vec, 2, NULL, 0);
+#endif
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        return err;
+    }
+
+#ifdef TFM_PSA_API
+    err = psa_test_common(SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SID,
+                          SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_MIN_VER,
+                          in_vec, 2, NULL, 0);
+#else
+    err = tfm_spm_irq_test_1_execute_test_scenario_veneer(in_vec, 1, NULL, 0);
+#endif
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        return err;
+    }
+
+#ifdef TFM_PSA_API
+    err = psa_test_common(SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SID,
+                          SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_MIN_VER,
+                          in_vec, 2, NULL, 0);
+#else
+    err = tfm_spm_core_test_2_execute_test_scenario_veneer(in_vec, 1, NULL, 0);
+#endif
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        return err;
+    }
+
+    err = execute_test_scenario_ns(test_scenario, &execution_data);
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        return err;
+    }
+
+    return CORE_TEST_ERRNO_SUCCESS;
+}
+
+static void tfm_core_test_secure_irq(struct test_result_t *ret)
+{
+    int32_t err;
+
+    err = tfm_core_test_secure_irq_scenario(IRQ_TEST_SCENARIO_1);
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        TEST_FAIL("Failed to execute IRQ test scenario 1.");
+        return;
+    }
+
+    err = tfm_core_test_secure_irq_scenario(IRQ_TEST_SCENARIO_2);
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        TEST_FAIL("Failed to execute IRQ test scenario 2.");
+        return;
+    }
+
+    err = tfm_core_test_secure_irq_scenario(IRQ_TEST_SCENARIO_3);
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        TEST_FAIL("Failed to execute IRQ test scenario 3.");
+        return;
+    }
+
+    err = tfm_core_test_secure_irq_scenario(IRQ_TEST_SCENARIO_4);
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        TEST_FAIL("Failed to execute IRQ test scenario 4.");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
 
 /*
  * \brief Tests whether the initialisation of the service was successful.
diff --git a/test/test_services/CMakeLists.inc b/test/test_services/CMakeLists.inc
index d591ce6..cbfc572 100644
--- a/test/test_services/CMakeLists.inc
+++ b/test/test_services/CMakeLists.inc
@@ -38,6 +38,13 @@
 	list(APPEND ALL_SRC_C_S "${CORE_TEST_DIR}/tfm_core_test_2/tfm_ss_core_test_2.c")
 endif()
 
+if (NOT DEFINED ENABLE_IRQ_TEST_SERVICES)
+	message(FATAL_ERROR "Incomplete build configuration: ENABLE_IRQ_TEST_SERVICES is undefined. ")
+elseif(ENABLE_IRQ_TEST_SERVICES)
+	list(APPEND ALL_SRC_C_S
+		"${CORE_TEST_DIR}/tfm_irq_test_service_1/tfm_irq_test_service_1.c")
+endif()
+
 if (NOT DEFINED TFM_PARTITION_TEST_SECURE_SERVICES)
 	message(FATAL_ERROR "Incomplete build configuration: TFM_PARTITION_TEST_SECURE_SERVICES is undefined. ")
 elseif (TFM_PARTITION_TEST_SECURE_SERVICES)
diff --git a/test/test_services/tfm_core_test/core_test_defs.h b/test/test_services/tfm_core_test/core_test_defs.h
index 3a36619..c7a3ae1 100644
--- a/test/test_services/tfm_core_test/core_test_defs.h
+++ b/test/test_services/tfm_core_test/core_test_defs.h
@@ -15,6 +15,7 @@
 #include <inttypes.h>
 #include <limits.h>
 #include "tfm_api.h"
+#include "secure_fw/core/tfm_core.h"
 
 /* These definitions are used in symbols, only digits are permitted */
 #define CORE_TEST_ID_NS_THREAD            1001
@@ -31,6 +32,7 @@
 #define CORE_TEST_ID_SPM_REQUEST          1014
 #define CORE_TEST_ID_IOVEC_SANITIZATION   1015
 #define CORE_TEST_ID_OUTVEC_WRITE         1016
+#define CORE_TEST_ID_SECURE_IRQ           1017
 #define CORE_TEST_ID_BLOCK                2001
 
 #define SPM_CORE_TEST_INIT_SUCCESS_SID                 0x00002100
@@ -64,10 +66,31 @@
 #define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SID     0x00002201
 #define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID      0x00002202
 #define SPM_CORE_TEST_2_INVERT_SID                     0x00002203
+#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SID      0x00002204
+#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SID      0x00002205
 #define SPM_CORE_TEST_2_SLAVE_SERVICE_MIN_VER              0x0001
 #define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_MIN_VER     0x0001
 #define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_MIN_VER      0x0001
 #define SPM_CORE_TEST_2_INVERT_MIN_VER                     0x0001
+#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_MIN_VER      0x0001
+#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_MIN_VER      0x0001
+
+#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SID  0x00002300
+#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SID  0x00002301
+#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_MIN_VER  0x0001
+#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_MIN_VER  0x0001
+
+enum irq_test_scenario_t {
+    IRQ_TEST_SCENARIO_NONE,
+    IRQ_TEST_SCENARIO_1,
+    IRQ_TEST_SCENARIO_2,
+    IRQ_TEST_SCENARIO_3,
+    IRQ_TEST_SCENARIO_4,
+};
+
+struct irq_test_execution_data_t {
+    volatile int32_t timer0_triggered;
+};
 
 /* Use lower 16 bits in return value for error code, upper 16 for line number
  * in test service
diff --git a/test/test_services/tfm_core_test_2/manifest.yaml b/test/test_services/tfm_core_test_2/manifest.yaml
index c388912..2bef0cc 100644
--- a/test/test_services/tfm_core_test_2/manifest.yaml
+++ b/test/test_services/tfm_core_test_2/manifest.yaml
@@ -41,6 +41,20 @@
       "non_secure_clients": true,
       "minor_version": 1,
       "minor_policy": "STRICT"
+    },
+    {
+      "name": "TFM_CORE_TEST_2_SFN_PREPARE_TEST_SCENARIO",
+      "signal": "SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "STRICT"
+    },
+    {
+      "name": "TFM_CORE_TEST_2_SFN_EXECUTE_TEST_SCENARIO",
+      "signal": "SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "STRICT"
     }
   ],
   "linker_pattern": {
@@ -81,5 +95,21 @@
       "minor_version": 1,
       "minor_policy": "STRICT"
     },
+    {
+    "name": "SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO",
+    "sid": "0x00002204",
+    "signal": "SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SIGNAL",
+    "non_secure_clients": "true",
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+    },
+    {
+    "name": "SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO",
+    "sid": "0x00002205",
+    "signal": "SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SIGNAL",
+    "non_secure_clients": "true",
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+    },
   ]
 }
diff --git a/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.c b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.c
index a6192a1..4f93fc8 100644
--- a/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.c
+++ b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.c
@@ -29,6 +29,10 @@
 
 static int32_t* invalid_addresses [] = {(int32_t*)0x0, (int32_t*)0xFFF12000};
 
+/* structures for secure IRQ testing */
+static enum irq_test_scenario_t current_scenario = IRQ_TEST_SCENARIO_NONE;
+static struct irq_test_execution_data_t *current_execution_data;
+
 psa_status_t spm_core_test_2_slave_service(struct psa_invec *in_vec,
                                            size_t in_len,
                                            struct psa_outvec *out_vec,
@@ -179,7 +183,7 @@
     uint32_t *out_ptr;
     int32_t *res_ptr;
 
-    if (in_len != 1 || out_len != 2) {
+    if ((in_len != 1) || (out_len != 2)) {
         return CORE_TEST_ERRNO_INVALID_PARAMETER;
     }
 
@@ -197,6 +201,88 @@
     return spm_core_test_2_sfn_invert_internal(in_ptr, out_ptr, res_ptr, len);
 }
 
+static psa_status_t spm_core_test_2_prepare_test_scenario_internal(
+                               enum irq_test_scenario_t irq_test_scenario,
+                               struct irq_test_execution_data_t *execution_data)
+{
+    current_scenario = irq_test_scenario;
+    current_execution_data = execution_data;
+
+    switch (irq_test_scenario) {
+    case IRQ_TEST_SCENARIO_NONE:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    case IRQ_TEST_SCENARIO_1:
+    case IRQ_TEST_SCENARIO_2:
+    case IRQ_TEST_SCENARIO_3:
+    case IRQ_TEST_SCENARIO_4:
+        /* No action is necessary*/
+        break;
+    default:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    return CORE_TEST_ERRNO_SUCCESS;
+}
+
+psa_status_t spm_core_test_2_prepare_test_scenario(
+                             struct psa_invec *in_vec, size_t in_len,
+                             struct psa_outvec *out_vec, size_t out_size)
+{
+    if ((in_len != 2) ||
+        (in_vec[0].len != sizeof(uint32_t)) ||
+        (in_vec[1].len != sizeof(struct irq_test_execution_data_t *))) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    enum irq_test_scenario_t irq_test_scenario =
+            (enum irq_test_scenario_t) *(uint32_t *)in_vec[0].base;
+
+    struct irq_test_execution_data_t *execution_data =
+            *(struct irq_test_execution_data_t **)in_vec[1].base;
+
+    return spm_core_test_2_prepare_test_scenario_internal(irq_test_scenario,
+                                                          execution_data);
+}
+
+static psa_status_t spm_core_test_2_execute_test_scenario_internal(
+                                     enum irq_test_scenario_t irq_test_scenario)
+{
+    switch (irq_test_scenario) {
+    case IRQ_TEST_SCENARIO_NONE:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    case IRQ_TEST_SCENARIO_1:
+        /* No action is necessary*/
+        break;
+    case IRQ_TEST_SCENARIO_2:
+        if (current_execution_data->timer0_triggered) {
+            return CORE_TEST_ERRNO_TEST_FAULT;
+        }
+        while (!current_execution_data->timer0_triggered) {
+            ;
+        }
+        break;
+    case IRQ_TEST_SCENARIO_3:
+    case IRQ_TEST_SCENARIO_4:
+        /* No action is necessary*/
+        break;
+    default:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    return CORE_TEST_ERRNO_SUCCESS;
+}
+
+psa_status_t spm_core_test_2_execute_test_scenario(
+                                    struct psa_invec *in_vec, size_t in_len,
+                                    struct psa_outvec *out_vec, size_t out_size)
+{
+    enum irq_test_scenario_t irq_test_scenario =
+            (enum irq_test_scenario_t) *(uint32_t *)in_vec[0].base;
+
+    return spm_core_test_2_execute_test_scenario_internal(irq_test_scenario);
+}
+
+
 #ifdef TFM_PSA_API
 
 typedef psa_status_t (*core_test_2_func_t)(psa_msg_t *msg);
@@ -307,6 +393,49 @@
     return ret;
 }
 
+psa_status_t spm_core_test_2_wrap_prepare_test_scenario(psa_msg_t *msg)
+{
+    uint32_t irq_test_scenario;
+    struct irq_test_execution_data_t *execution_data;
+    size_t num;
+
+    if ((msg->in_size[0] != sizeof(uint32_t)) ||
+        (msg->in_size[1] != sizeof(struct irq_test_execution_data_t*)))  {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    num = psa_read(msg->handle, 0, &irq_test_scenario, sizeof(uint32_t));
+    if (num != msg->in_size[0]) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    num = psa_read(msg->handle, 1, &execution_data, sizeof(
+                                            struct irq_test_execution_data_t*));
+    if (num != msg->in_size[1]) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    return spm_core_test_2_prepare_test_scenario_internal(irq_test_scenario,
+                                                          execution_data);
+}
+
+psa_status_t spm_core_test_2_wrap_execute_test_scenario(psa_msg_t *msg)
+{
+    uint32_t irq_test_scenario;
+    size_t num;
+
+    if (msg->in_size[0] != sizeof(uint32_t))  {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    num = psa_read(msg->handle, 0, &irq_test_scenario, sizeof(uint32_t));
+    if (num != msg->in_size[0]) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    return spm_core_test_2_execute_test_scenario_internal(irq_test_scenario);
+}
+
 #endif
 
 /* FIXME: Add a testcase to test that a failed init makes the secure partition
@@ -334,6 +463,14 @@
         } else if (signals & SPM_CORE_TEST_2_INVERT_SIGNAL) {
             core_test_2_signal_handle(SPM_CORE_TEST_2_INVERT_SIGNAL,
                                       spm_core_test_2_wrap_sfn_invert);
+        } else if (signals & SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SIGNAL) {
+            core_test_2_signal_handle(
+                                   SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SIGNAL,
+                                   spm_core_test_2_wrap_prepare_test_scenario);
+        } else if (signals & SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SIGNAL) {
+            core_test_2_signal_handle(
+                                   SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SIGNAL,
+                                   spm_core_test_2_wrap_execute_test_scenario);
         } else {
             ; /* do nothing */
         }
diff --git a/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_signal.h b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_signal.h
index ae9c1db..e95c72b 100644
--- a/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_signal.h
+++ b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_signal.h
@@ -15,6 +15,9 @@
 #define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SIGNAL   (1 << (1  + 4))
 #define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SIGNAL    (1 << (2  + 4))
 #define SPM_CORE_TEST_2_INVERT_SIGNAL                   (1 << (3  + 4))
+#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SIGNAL    (1 << (4  + 4))
+#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SIGNAL    (1 << (5  + 4))
+
 #endif /* TFM_PSA_API */
 
 #endif /* __TFM_CORE_TEST_2_SIGNAL_H__ */
diff --git a/test/test_services/tfm_irq_test_service_1/manifest.yaml b/test/test_services/tfm_irq_test_service_1/manifest.yaml
new file mode 100644
index 0000000..5c0d83d
--- /dev/null
+++ b/test/test_services/tfm_irq_test_service_1/manifest.yaml
@@ -0,0 +1,76 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+  "name": "TFM_IRQ_TEST_1",
+  "type": "APPLICATION-ROT",
+  "priority": "NORMAL",
+  "id": "0x0000010B",
+  "entry_point": "tfm_irq_test_1_init",
+  "tfm_partition_ipc": true,
+  "stack_size": "0x0400",
+  "heap_size": "0x0400",
+  "mmio_regions": [
+    {
+      "name": "TFM_PERIPHERAL_TIMER0",
+      "permission": "READ-WRITE"
+    }
+  ],
+  "tfm_init_symbol": "tfm_irq_test_1_init",
+  "secure_functions": [
+    {
+      "name": "SPM_IRQ_TEST_1_PREPARE_TEST_SCENARIO",
+      "signal": "SPM_IRQ_TEST_1_PREPARE_TEST_SCENARIO",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "STRICT"
+    },
+    {
+      "name": "SPM_IRQ_TEST_1_EXECUTE_TEST_SCENARIO",
+      "signal": "SPM_IRQ_TEST_1_EXECUTE_TEST_SCENARIO",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "STRICT"
+    }
+  ],
+  "irqs": [
+    {
+      "line_name": "TFM_TIMER0_IRQ",
+      "signal": "SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ",
+      "tfm_irq_priority": 64,
+    }
+  ],
+  "source_files": [
+    "./tfm_irq_test_service_1.c",
+    "*timer_cmsdk.c",
+    "*timer_cmsdk_drv.c",
+  ],
+  "linker_pattern": {
+    "object_list": [
+      "*tfm_irq_test_service_1.*",
+      "*timer_cmsdk*",
+    ]
+  },
+  "services": [
+    {
+    "name": "SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO",
+    "sid": "0x00002300",
+    "signal": "SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SIGNAL",
+    "non_secure_clients": "true",
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+    },
+    {
+    "name": "SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO",
+    "sid": "0x00002301",
+    "signal": "SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SIGNAL",
+    "non_secure_clients": "true",
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+    },
+  ]
+}
diff --git a/test/test_services/tfm_irq_test_service_1/tfm_irq_test_service_1.c b/test/test_services/tfm_irq_test_service_1/tfm_irq_test_service_1.c
new file mode 100644
index 0000000..334e4dc
--- /dev/null
+++ b/test/test_services/tfm_irq_test_service_1/tfm_irq_test_service_1.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include "tfm_api.h"
+#include "tfm_veneers.h"
+#include "secure_fw/core/secure_utilities.h"
+#include "secure_fw/core/tfm_secure_api.h"
+#include "secure_fw/include/tfm_spm_services_api.h"
+#include "spm_partition_defs.h"
+#include "test/test_services/tfm_core_test/core_test_defs.h"
+#include "psa_service.h"
+#include "tfm_irq_test_service_1_signal.h"
+#include "tfm_irq_signal_defs.h"
+#include "tfm_plat_test.h"
+
+static enum irq_test_scenario_t current_scenario = IRQ_TEST_SCENARIO_NONE;
+static struct irq_test_execution_data_t *current_execution_data;
+
+#ifdef TFM_PSA_API
+static psa_handle_t execute_msg_handle = -1;
+#endif
+
+/**
+ * \brief unrecoverable error during test execution.
+ *
+ * Called from places, where error code would be very difficult, or impossible
+ * to return.
+ */
+static void halt_test_execution(void)
+{
+    while (1) {
+        ; /* Test fail */
+    }
+}
+
+/**
+ * \brief Stop the timer, and disable and clear interrupts
+ */
+static void stop_timer(void)
+{
+    tfm_plat_test_secure_timer_stop();
+}
+
+uint32_t spm_irq_test_1_prepare_test_scenario_internal(
+                               enum irq_test_scenario_t irq_test_scenario,
+                               struct irq_test_execution_data_t *execution_data)
+{
+    current_scenario = irq_test_scenario;
+    current_execution_data = execution_data;
+
+    current_execution_data->timer0_triggered = 0;
+
+    switch (irq_test_scenario) {
+    case IRQ_TEST_SCENARIO_NONE:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    case IRQ_TEST_SCENARIO_1:
+    case IRQ_TEST_SCENARIO_2:
+    case IRQ_TEST_SCENARIO_3:
+    case IRQ_TEST_SCENARIO_4:
+        tfm_plat_test_secure_timer_start();
+        break;
+    default:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    return CORE_TEST_ERRNO_SUCCESS;
+}
+
+uint32_t spm_irq_test_1_execute_test_scenario(
+                                     struct psa_invec *in_vec, size_t in_len,
+                                     struct psa_outvec *out_vec, size_t out_len)
+{
+    enum irq_test_scenario_t irq_test_scenario =
+            (enum irq_test_scenario_t) *(uint32_t *)in_vec[0].base;
+    psa_signal_t signals = 0;
+
+    if (irq_test_scenario != current_scenario) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    switch (irq_test_scenario) {
+    case IRQ_TEST_SCENARIO_NONE:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    case IRQ_TEST_SCENARIO_1:
+    case IRQ_TEST_SCENARIO_2:
+        /* nothing to do*/
+        break;
+    case IRQ_TEST_SCENARIO_3:
+        if (current_execution_data->timer0_triggered) {
+            return CORE_TEST_ERRNO_TEST_FAULT;
+        }
+        while (!current_execution_data->timer0_triggered) {
+            /* Wait for the timer to be triggered */
+            ;
+        }
+        break;
+    case IRQ_TEST_SCENARIO_4:
+        if (current_execution_data->timer0_triggered) {
+            return CORE_TEST_ERRNO_TEST_FAULT;
+        }
+        while ((signals & SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ) == 0) {
+            signals = psa_wait(SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ,
+                               PSA_BLOCK);
+        }
+        if (!current_execution_data->timer0_triggered) {
+            return CORE_TEST_ERRNO_TEST_FAULT;
+        }
+        psa_eoi(SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ);
+        break;
+    default:
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    return CORE_TEST_ERRNO_SUCCESS;
+}
+
+uint32_t spm_irq_test_1_prepare_test_scenario(
+                                     struct psa_invec *in_vec, size_t in_len,
+                                     struct psa_outvec *out_vec, size_t out_len)
+{
+    enum irq_test_scenario_t irq_test_scenario;
+    struct irq_test_execution_data_t *execution_data;
+
+    if ((in_len != 2) || (out_len != 0)) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    if ((in_vec[0].len != sizeof(uint32_t)) ||
+        (in_vec[1].len != sizeof(struct irq_test_execution_data_t *))) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    irq_test_scenario =
+            (enum irq_test_scenario_t) *(uint32_t *)in_vec[0].base;
+
+    execution_data =
+            *(struct irq_test_execution_data_t **)in_vec[1].base;
+
+    return spm_irq_test_1_prepare_test_scenario_internal(irq_test_scenario,
+                                                         execution_data);
+}
+
+#ifndef TFM_PSA_API
+
+void SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ_isr(void)
+{
+    stop_timer();
+
+    if ((current_execution_data == NULL) ||
+        (current_execution_data->timer0_triggered != 0)) {
+            halt_test_execution();
+    }
+
+    current_execution_data->timer0_triggered = 1;
+
+    switch (current_scenario) {
+    case IRQ_TEST_SCENARIO_NONE:
+        halt_test_execution();
+        break;
+    case IRQ_TEST_SCENARIO_1:
+    case IRQ_TEST_SCENARIO_2:
+    case IRQ_TEST_SCENARIO_3:
+        psa_eoi(SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ);
+        break;
+    case IRQ_TEST_SCENARIO_4:
+        /* nothing to do*/
+        break;
+    default:
+        halt_test_execution();
+        break;
+    }
+
+    __asm("DSB");
+}
+
+#else /* TFM_PSA_API */
+
+typedef psa_status_t (*irq_test_1_func_t)(psa_msg_t *msg);
+
+static void spm_irq_test_1_signal_handle(psa_signal_t signal,
+                                         irq_test_1_func_t pfn)
+{
+    psa_msg_t msg;
+    psa_status_t status;
+
+    status = psa_get(signal, &msg);
+    if (status) {
+        return;
+    }
+
+    switch (msg.type) {
+    case PSA_IPC_CONNECT:
+        psa_reply(msg.handle, PSA_SUCCESS);
+        break;
+    case PSA_IPC_CALL:
+        status = pfn(&msg);
+        psa_reply(msg.handle, status);
+        break;
+    case PSA_IPC_DISCONNECT:
+        psa_reply(msg.handle, PSA_SUCCESS);
+        break;
+    default:
+        break;
+    }
+}
+
+void TIMER_0_isr_ipc(void)
+{
+    current_execution_data->timer0_triggered = 1;
+
+    tfm_plat_test_secure_timer_stop();
+
+    switch (current_scenario) {
+    case IRQ_TEST_SCENARIO_NONE:
+        halt_test_execution();
+        break;
+    case IRQ_TEST_SCENARIO_1:
+    case IRQ_TEST_SCENARIO_2:
+        psa_eoi(SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ);
+        break;
+    case IRQ_TEST_SCENARIO_3:
+        /* execute_msg_handle have to be valid at this point */
+        if (execute_msg_handle <= 0) {
+            halt_test_execution();
+        }
+        /* reply to the execute message, to unblock NS side */
+        psa_reply(execute_msg_handle, CORE_TEST_ERRNO_SUCCESS);
+        execute_msg_handle = -1;
+        psa_eoi(SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ);
+        break;
+    case IRQ_TEST_SCENARIO_4:
+        /* This case should never be executed as in this scenario the 'execute
+         * function does the psa wait, and calls psa_eoi immediately'. So when
+         * execution gets to the psa_wait in the main loop, the IRQ signal is
+         * unset.
+         */
+        halt_test_execution();
+        break;
+    default:
+        halt_test_execution();
+        break;
+    }
+}
+
+static psa_status_t spm_irq_test_1_wrap_prepare_test_scenario(psa_msg_t *msg)
+{
+    uint32_t irq_test_scenario;
+    struct irq_test_execution_data_t *execution_data;
+    size_t num;
+
+    if ((msg->in_size[0] != sizeof(uint32_t)) ||
+        (msg->in_size[1] != sizeof(struct irq_test_execution_data_t *))) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+
+    num = psa_read(msg->handle, 0, &irq_test_scenario, sizeof(uint32_t));
+    if (num != msg->in_size[0]) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    num = psa_read(msg->handle, 1, &execution_data,
+                   sizeof(struct irq_test_execution_data_t *));
+    if (num != msg->in_size[1]) {
+        return CORE_TEST_ERRNO_INVALID_PARAMETER;
+    }
+
+    return spm_irq_test_1_prepare_test_scenario_internal(irq_test_scenario,
+                                                         execution_data);
+}
+
+static void spm_irq_test_1_execute_test_scenario_ipc_call(psa_msg_t *msg)
+{
+    size_t num;
+    uint32_t irq_test_scenario;
+    psa_signal_t signals = 0;
+
+    num = psa_read(msg->handle, 0, &irq_test_scenario, sizeof(uint32_t));
+    if ((num != msg->in_size[0]) ||
+        (irq_test_scenario != current_scenario)) {
+        psa_reply(msg->handle, CORE_TEST_ERRNO_INVALID_PARAMETER);
+        return;
+    }
+
+    switch (irq_test_scenario) {
+    case IRQ_TEST_SCENARIO_NONE:
+        psa_reply(msg->handle, CORE_TEST_ERRNO_INVALID_PARAMETER);
+        return;
+    case IRQ_TEST_SCENARIO_1:
+    case IRQ_TEST_SCENARIO_2:
+        /* nothing to do, return success */
+        psa_reply(msg->handle, CORE_TEST_ERRNO_SUCCESS);
+        return;
+    case IRQ_TEST_SCENARIO_3:
+        if (current_execution_data->timer0_triggered) {
+            psa_reply(msg->handle, CORE_TEST_ERRNO_TEST_FAULT);
+            return;
+        }
+        /* We need the ISR to be able to run. So we do a wait to let
+         * it run and set timer0_triggered. This message will be replied
+         * from the ISR, so the NS side remains blocked for now. To be able
+         * to reply, we also save the handle of the message.
+         */
+        if (execute_msg_handle > 0) {
+            /* execute_msg_handle should be uninitialised at this point */
+            psa_reply(msg->handle, CORE_TEST_ERRNO_TEST_FAULT);
+            return;
+        }
+        execute_msg_handle = msg->handle;
+        while (!(signals & SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ)) {
+           signals = psa_wait(SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ,
+                              PSA_BLOCK);
+        }
+        return;
+    case IRQ_TEST_SCENARIO_4:
+        while (!(signals & SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ)) {
+            signals = psa_wait(SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ,
+                              PSA_BLOCK);
+        }
+        /* There is no need to call the ISR in this scenario, so we can
+         * clear the IRQ signal
+         */
+        stop_timer();
+        psa_eoi(SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ);
+        psa_reply(msg->handle, CORE_TEST_ERRNO_SUCCESS);
+        break;
+    default:
+        psa_reply(msg->handle, CORE_TEST_ERRNO_INVALID_PARAMETER);
+        return;
+    }
+}
+
+static void spm_irq_test_1_execute_test_scenario_ipc(psa_signal_t signal)
+{
+    psa_msg_t msg;
+    psa_status_t status;
+
+    status = psa_get(signal, &msg);
+    if (status) {
+        return;
+    }
+
+    if (signal != SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SIGNAL) {
+        psa_reply(msg.handle, CORE_TEST_ERRNO_INVALID_PARAMETER);
+    }
+
+    switch (msg.type) {
+    case PSA_IPC_CONNECT:
+        psa_reply(msg.handle, PSA_SUCCESS);
+        break;
+    case PSA_IPC_CALL:
+        spm_irq_test_1_execute_test_scenario_ipc_call(&msg);
+    break;
+    case PSA_IPC_DISCONNECT:
+        psa_reply(msg.handle, PSA_SUCCESS);
+        break;
+    default:
+        break;
+    }
+}
+#endif /* TFM_PSA_API */
+
+int32_t tfm_irq_test_1_init(void)
+{
+    tfm_enable_irq(SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ);
+#ifdef TFM_PSA_API
+    psa_signal_t signals = 0;
+
+    while (1) {
+        signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+        if (signals & SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ) {
+            TIMER_0_isr_ipc();
+        } else if (signals & SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SIGNAL) {
+            spm_irq_test_1_signal_handle(
+                               SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SIGNAL,
+                               spm_irq_test_1_wrap_prepare_test_scenario);
+        } else if (signals & SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SIGNAL) {
+            spm_irq_test_1_execute_test_scenario_ipc(
+                              SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SIGNAL);
+        } else {
+            ; /* do nothing */
+        }
+    }
+#endif /* TFM_PSA_API */
+
+    return TFM_SUCCESS;
+}
+
diff --git a/test/test_services/tfm_irq_test_service_1/tfm_irq_test_service_1_signal.h b/test/test_services/tfm_irq_test_service_1/tfm_irq_test_service_1_signal.h
new file mode 100644
index 0000000..c6b13ab
--- /dev/null
+++ b/test/test_services/tfm_irq_test_service_1/tfm_irq_test_service_1_signal.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_IRQ_TEST_1_SERVICE_SIGNAL_H__
+#define __TFM_IRQ_TEST_1_SERVICE_SIGNAL_H__
+
+/* FixMe: hardcode it for the tool cannot support now */
+#ifdef TFM_PSA_API
+
+#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SIGNAL    (1U << (4  + 4))
+#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SIGNAL    (1U << (5  + 4))
+
+#endif /* TFM_PSA_API */
+
+#endif /* __TFM_IRQ_TEST_1_SERVICE_SIGNAL_H__ */
diff --git a/tools/tfm_manifest_list.yaml b/tools/tfm_manifest_list.yaml
index b55a0e9..599810b 100644
--- a/tools/tfm_manifest_list.yaml
+++ b/tools/tfm_manifest_list.yaml
@@ -107,6 +107,16 @@
       "conditional": "TFM_PARTITION_TEST_CORE_IPC",
       "version_major": 0,
       "version_minor": 1
+    },
+    {
+      "name": "TFM IRQ Test Service 1",
+      "short_name": "TFM_IRQ_Test_1",
+      "manifest": "test/test_services/tfm_irq_test_service_1/manifest.yaml",
+      "tfm_extensions": true,
+      "tfm_partition_ipc": true,
+      "conditional": "TFM_PARTITION_TEST_CORE",
+      "version_major": 0,
+      "version_minor": 1
     }
   ]
 }