Test: Add test suite for NSID management

Add SVC handlers from NS side to directly call ns client ext APIs,
which need to be called from handler mode.
Add NSID test suite for non-secure client extension support.
Test cases could cover normal tests, corner case tests and error tests.

Signed-off-by: Xinyu Zhang <xinyu.zhang@arm.com>
Change-Id: I0c79d8d0f92e960dc26b3dee2ea647d394dc868e
diff --git a/ns_interface/ns_client_ext/tfm_nsid_manager.h b/ns_interface/ns_client_ext/tfm_nsid_manager.h
old mode 100644
new mode 100755
index 7704aa0..b42311a
--- a/ns_interface/ns_client_ext/tfm_nsid_manager.h
+++ b/ns_interface/ns_client_ext/tfm_nsid_manager.h
@@ -35,6 +35,14 @@
 #define NSID_MGR_ERR_NO_FREE_ENTRY    0x03
 
 /*
+ * Current active NSID token needs to be manually save and reload
+ * before and after calling NS client ext directly from SVC in NSID test suite.
+ */
+#ifdef TEST_NS_MANAGE_NSID
+extern uint32_t current_active_token;
+#endif
+
+/*
  * Initialize the table to map token and nsid.
  * This function should be called before any other NSID manager APIs.
  */
diff --git a/ns_interface/ns_client_ext/tz_shim_layer.c b/ns_interface/ns_client_ext/tz_shim_layer.c
index ed959ea..74a12ec 100755
--- a/ns_interface/ns_client_ext/tz_shim_layer.c
+++ b/ns_interface/ns_client_ext/tz_shim_layer.c
@@ -28,6 +28,10 @@
 static uint8_t nsid_mgr_thread_id = 1;
 #endif
 
+#ifdef TEST_NS_MANAGE_NSID
+uint32_t current_active_token;
+#endif
+
 /*
  * TF-M shim layer of the CMSIS TZ RTOS thread context management API
  */
@@ -46,6 +50,9 @@
 
     /* Initialize the nsid manager */
     if (nsid_mgr_init() == NSID_MGR_ERR_SUCCESS) {
+#ifdef TEST_NS_MANAGE_NSID
+        current_active_token = TFM_NS_CLIENT_INVALID_TOKEN;
+#endif
         return 1U;    /* Success */
     } else {
         return 0U;    /* Error */
@@ -105,6 +112,11 @@
     }
 
     if (tfm_nsce_release_ctx(token) == TFM_NS_CLIENT_ERR_SUCCESS) {
+#ifdef TEST_NS_MANAGE_NSID
+        if (current_active_token != TFM_NS_CLIENT_INVALID_TOKEN) {
+            current_active_token = TFM_NS_CLIENT_INVALID_TOKEN;
+        }
+#endif
         return 1U;    /* Success */
     } else {
         return 0U;    /* Error */
@@ -135,6 +147,9 @@
     }
 
     if (tfm_nsce_load_ctx(token, nsid) == TFM_NS_CLIENT_ERR_SUCCESS) {
+#ifdef TEST_NS_MANAGE_NSID
+        current_active_token = token;
+#endif
         return 1U;    /* Success */
     } else {
         return 0U;    /* Error */
@@ -158,6 +173,11 @@
     token = (uint32_t)id;
 
     if (tfm_nsce_save_ctx(token) == TFM_NS_CLIENT_ERR_SUCCESS) {
+#ifdef TEST_NS_MANAGE_NSID
+        if (current_active_token != TFM_NS_CLIENT_INVALID_TOKEN) {
+            current_active_token = TFM_NS_CLIENT_INVALID_TOKEN;
+        }
+#endif
         return 1U;    /* Success */
     } else {
         return 0U;    /* Error */
diff --git a/test/suites/nsid/CMakeLists.txt b/test/suites/nsid/CMakeLists.txt
new file mode 100644
index 0000000..b3b6262
--- /dev/null
+++ b/test/suites/nsid/CMakeLists.txt
@@ -0,0 +1,43 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_policy(SET CMP0079 NEW)
+
+if (NOT TEST_NS_MANAGE_NSID)
+    return()
+endif()
+
+####################### Non Secure #############################################
+
+add_library(tfm_test_suite_nsid STATIC EXCLUDE_FROM_ALL)
+
+target_sources(tfm_test_suite_nsid
+    PRIVATE
+        ./nsid_testsuite.c
+        ./nsid_svc_handler.c
+)
+
+target_include_directories(tfm_test_suite_nsid
+    PUBLIC
+        ./
+)
+
+target_compile_definitions(tfm_test_suite_nsid
+    PUBLIC
+        $<$<BOOL:${TEST_NS_MANAGE_NSID}>:TEST_NS_MANAGE_NSID>
+)
+
+target_link_libraries(tfm_test_suite_nsid
+    PRIVATE
+        tfm_test_framework_ns
+        platform_ns
+)
+
+target_link_libraries(tfm_ns_tests
+    INTERFACE
+        tfm_test_suite_nsid
+)
diff --git a/test/suites/nsid/nsid_svc_handler.c b/test/suites/nsid/nsid_svc_handler.c
new file mode 100755
index 0000000..0e74e55
--- /dev/null
+++ b/test/suites/nsid/nsid_svc_handler.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "cmsis_compiler.h"
+#include "tfm_ns_client_ext.h"
+#include "nsid_svc_handler.h"
+
+/**
+ * \brief Macro to encode an svc instruction
+ *
+ */
+#define SVC(code) __ASM volatile("svc %0" : : "I" (code))
+
+/**
+ * \brief Numbers associated to each SVC available
+ *
+ * \details Start from 1 as 0 is reserved by RTX
+ */
+enum tfm_svc_num {
+    SVC_INVALID = 0,
+    /* SVC API for Services */
+    SVC_NS_CLIENT_EXT_INIT,
+    SVC_NS_CLIENT_ACQUIRE_CTX,
+    SVC_NS_CLIENT_RELEASE_CTX,
+    SVC_NS_CLIENT_LOAD_CTX,
+    SVC_NS_CLIENT_SAVE_CTX,
+    /* add all the new entries above this line */
+    SVC_TFM_MAX,
+};
+
+/* number of user SVC functions */
+#define USER_SVC_COUNT ((uint32_t)SVC_TFM_MAX - 1)
+
+/**
+ * \brief Modified table template for user defined SVC functions
+ *
+ * \details RTX has a weak definition of osRtxUserSVC, which
+ *          is overridden here
+ */
+#if (defined(__ARMCC_VERSION) && (__ARMCC_VERSION == 6110004))
+/* Workaround needed for a bug in Armclang 6.11, more details at:
+ * http://www.keil.com/support/docs/4089.htm
+ */
+__attribute__((section(".gnu.linkonce")))
+#endif
+extern void * const osRtxUserSVC[1+USER_SVC_COUNT];
+       void * const osRtxUserSVC[1+USER_SVC_COUNT] = {
+    (void *)USER_SVC_COUNT,
+    /* SVC API for Services */
+    (void *)tfm_nsce_init,
+    (void *)tfm_nsce_acquire_ctx,
+    (void *)tfm_nsce_release_ctx,
+    (void *)tfm_nsce_load_ctx,
+    (void *)tfm_nsce_save_ctx,
+};
+
+__attribute__ ((naked))
+uint32_t nsid_ext_init_svc(uint32_t ctx_requested)
+{
+    SVC(SVC_NS_CLIENT_EXT_INIT);
+    __ASM volatile("BX LR");
+}
+
+__attribute__ ((naked))
+uint32_t nsid_acquire_ctx_svc(uint8_t group_id, uint8_t thread_id)
+{
+    SVC(SVC_NS_CLIENT_ACQUIRE_CTX);
+    __ASM volatile("BX LR");
+}
+
+__attribute__ ((naked))
+uint32_t nsid_release_ctx_svc(uint32_t token)
+{
+    SVC(SVC_NS_CLIENT_RELEASE_CTX);
+    __ASM volatile("BX LR");
+}
+
+__attribute__ ((naked))
+uint32_t nsid_load_ctx_svc(uint32_t token, int32_t nsid)
+{
+    SVC(SVC_NS_CLIENT_LOAD_CTX);
+    __ASM volatile("BX LR");
+}
+
+__attribute__ ((naked))
+uint32_t nsid_save_ctx_svc(uint32_t token)
+{
+    SVC(SVC_NS_CLIENT_SAVE_CTX);
+    __ASM volatile("BX LR");
+}
diff --git a/test/suites/nsid/nsid_svc_handler.h b/test/suites/nsid/nsid_svc_handler.h
new file mode 100755
index 0000000..65621fd
--- /dev/null
+++ b/test/suites/nsid/nsid_svc_handler.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __NSID_SVC_HANDLER_H__
+#define __NSID_SVC_HANDLER_H__
+
+#include <stdint.h>
+// #include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SVC func to initialize ns client extension.
+ *
+ * \param [in] ctx_requested  Number of ns context to be requested.
+ *
+ * \return Returns number of context actually allocated by ns client ext.
+ */
+uint32_t nsid_ext_init_svc(uint32_t ctx_requested);
+
+/**
+ * \brief SVC func to acquire context from Secure side.
+ *
+ * \param [in] group_id  Group ID of NS client.
+ * \param [in] thread_id Thread ID of NS client.
+ *
+ * \return Returns token gerenated by SPM.
+ */
+uint32_t nsid_acquire_ctx_svc(uint8_t group_id, uint8_t thread_id);
+
+/**
+ * \brief SVC func to release context from Secure side.
+ *
+ * \param [in] token  Token of NS client.
+ *
+ * \return Returns TF-M NSID Error code.
+ */
+uint32_t nsid_release_ctx_svc(uint32_t token);
+
+/**
+ * \brief SVC func to release context from Secure side.
+ *
+ * \param [in] token  Token of NS client.
+ * \param [in] nsid   NSID of NS client.
+ *
+ * \return Returns TF-M NSID Error code.
+ */
+uint32_t nsid_load_ctx_svc(uint32_t token, int32_t nsid);
+
+/**
+ * \brief SVC func to save context from Secure side.
+ *
+ * \param [in] token  Token of NS client.
+ *
+ * \return Returns TF-M NSID Error code.
+ */
+uint32_t nsid_save_ctx_svc(uint32_t token);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __NSID_SVC_HANDLER_H__ */
diff --git a/test/suites/nsid/nsid_testsuite.c b/test/suites/nsid/nsid_testsuite.c
new file mode 100755
index 0000000..30cbb93
--- /dev/null
+++ b/test/suites/nsid/nsid_testsuite.c
@@ -0,0 +1,1040 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "test_framework.h"
+#include "tfm_ns_client_ext.h"
+#include "nsid_svc_handler.h"
+#include "tfm_nsid_manager.h"
+
+/*
+ * The following macros are defined for white-box test only.
+ * Some of them are duplicated from secure side.
+ * It is unnecessary to export these definitions to NS side in actual scenarios.
+ */
+#define MAKE_NS_CLIENT_TOKEN(tid, gid, idx)                         \
+                             (uint32_t)((((uint32_t)tid & 0xff)     \
+                             | (((uint32_t)gid & 0xff) << 8)        \
+                             | (((uint32_t)idx & 0xff) << 16))      \
+                             & 0x00ffffff)
+
+#define VALID_INDEX                   0x00
+#define VALID_GROUP_ID                0x00
+#define VALID_THREAD_ID_MIN           0x00
+#define VALID_THREAD_ID_MAX           UINT8_MAX
+#define VALID_NSID_MAX                ((int32_t)-1)
+#define VALID_NSID_MIN                INT32_MIN
+#define INVALID_INDEX                 0x01
+#define INVALID_GROUP_ID              0x01
+#define INVALID_RESERVED_TOKEN_BIT    0x10000000
+#define TFM_NS_CONTEXT_MAX            1
+
+static uint8_t thread_id = 0x20;
+static int32_t nsid = -500;
+
+/*
+ * This func is to be called at the beginning of test cases.
+ * The current active token needs to be saved first
+ * before calling ns_client_ext APIs through NS SVC.
+ * Values of NSID and Thread ID are changed to make sure
+ * every test case could be assigned with different tokens.
+ */
+static void nsid_test_case_init(struct test_result_t *ret)
+{
+    if (nsid_save_ctx_svc(current_active_token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("SAVE fail when saving test thread ctx\r\n");
+    }
+
+    nsid--;
+    thread_id++;
+
+    return;
+}
+
+/*
+ * This func is to be called at the end of test cases
+ * to re-load the saved token at the beginning of the test case.
+ */
+static void nsid_test_case_finish(struct test_result_t *ret)
+{
+    if (nsid_load_ctx_svc(current_active_token,
+                          nsid_mgr_query_nsid(current_active_token))
+        != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD fail when re-loading test thread ctx\r\n");
+    }
+    return;
+}
+
+/* Initialize with valid params */
+static void tfm_nsid_test_case_1(struct test_result_t *ret)
+{
+    nsid_test_case_init(ret);
+
+    if (nsid_ext_init_svc(0) != TFM_NS_CONTEXT_MAX) {
+        TEST_FAIL("INITIALIZE shall return TFM_NS_CONTEXT_MAX\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_ext_init_svc(1) != 1) {
+        TEST_FAIL("INITIALIZE shall return 1\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_ext_init_svc(TFM_NS_CONTEXT_MAX + 1) != TFM_NS_CONTEXT_MAX) {
+        TEST_FAIL("INITIALIZE shall return TFM_NS_CONTEXT_MAX\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Normal full sequence */
+static void tfm_nsid_test_case_2(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("SAVE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Normal acquire-release sequence */
+static void tfm_nsid_test_case_3(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/*  Normal acquire-load-release sequence */
+static void tfm_nsid_test_case_4(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Switch contexts */
+static void tfm_nsid_test_case_5(struct test_result_t *ret)
+{
+    uint32_t token_a;
+    uint32_t token_b;
+
+    nsid_test_case_init(ret);
+
+    token_a = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+    token_b = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id + 1);
+
+    if (token_a != MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                        VALID_GROUP_ID, \
+                                        VALID_INDEX) || \
+        token_b != MAKE_NS_CLIENT_TOKEN(thread_id + 1, \
+                                        VALID_GROUP_ID, \
+                                        VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token_a, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token_a) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("SAVE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token_b, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token_b) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("SAVE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token_a) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token_b) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Release inactive context */
+static void tfm_nsid_test_case_6(struct test_result_t *ret)
+{
+    uint32_t token_a;
+    uint32_t token_b;
+
+    nsid_test_case_init(ret);
+
+    token_a = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+    token_b = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id + 1);
+
+    if (token_a != MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                        VALID_GROUP_ID,
+                                        VALID_INDEX) || \
+        token_b != MAKE_NS_CLIENT_TOKEN(thread_id + 1, \
+                                        VALID_GROUP_ID, \
+                                        VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token_a, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token_b) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token_a) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Max NSID */
+static void tfm_nsid_test_case_7(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, VALID_NSID_MAX)
+        != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("SAVE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Min NSID */
+static void tfm_nsid_test_case_8(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, VALID_NSID_MIN)
+        != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("SAVE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Min TID */
+static void tfm_nsid_test_case_9(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, VALID_THREAD_ID_MIN);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(0x00, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("SAVE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Max TID */
+static void tfm_nsid_test_case_10(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, VALID_THREAD_ID_MAX);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(0xFF, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("SAVE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Load Thread B without saving Thread A */
+static void tfm_nsid_test_case_11(struct test_result_t *ret)
+{
+    uint32_t token_a;
+    uint32_t token_b;
+
+    nsid_test_case_init(ret);
+
+    token_a = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+    token_b = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id + 1);
+
+    if (token_a != MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                        VALID_GROUP_ID, \
+                                        VALID_INDEX) || \
+        token_b != MAKE_NS_CLIENT_TOKEN(thread_id + 1, \
+                                        VALID_GROUP_ID, \
+                                        VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token_a, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token_b, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token_a) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token_b) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Load with non-negative NSID */
+static void tfm_nsid_test_case_12(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    thread_id++;
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, 0) != TFM_NS_CLIENT_ERR_INVALID_NSID) {
+        TEST_FAIL("LOAD shall fail with non-negative NSID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, 1) != TFM_NS_CLIENT_ERR_INVALID_NSID) {
+        TEST_FAIL("LOAD shall fail with non-negative NSID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, 50) != TFM_NS_CLIENT_ERR_INVALID_NSID) {
+        TEST_FAIL("LOAD shall fail with non-negative NSID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    nsid_test_case_finish(ret);
+
+    ret->val = TEST_PASSED;
+}
+
+/* Load with invalid token */
+static void tfm_nsid_test_case_13(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(TFM_NS_CLIENT_INVALID_TOKEN, nsid)
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("LOAD shall fail with invalid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Save with invalid token */
+static void tfm_nsid_test_case_14(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall pass with valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(TFM_NS_CLIENT_INVALID_TOKEN)
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("SAVE shall fail with invalid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Release with invalid token */
+static void tfm_nsid_test_case_15(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(TFM_NS_CLIENT_INVALID_TOKEN)
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("RELEASE shall fail with invalid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Acquire with undefault GID */
+static void tfm_nsid_test_case_16(struct test_result_t *ret)
+{
+    nsid_test_case_init(ret);
+
+    if (nsid_acquire_ctx_svc(0x01, INVALID_GROUP_ID) \
+        != TFM_NS_CLIENT_INVALID_TOKEN) {
+        TEST_FAIL("ACQUIRE shall fail with invalid GID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_acquire_ctx_svc(0x50, INVALID_GROUP_ID) \
+        != TFM_NS_CLIENT_INVALID_TOKEN) {
+        TEST_FAIL("ACQUIRE shall fail with invalid GID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_acquire_ctx_svc(0xFF, INVALID_GROUP_ID) \
+        != TFM_NS_CLIENT_INVALID_TOKEN) {
+        TEST_FAIL("ACQUIRE shall fail with invalid GID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Load, save and release with token containing wrong info */
+static void tfm_nsid_test_case_17(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                               INVALID_GROUP_ID, \
+                                               VALID_INDEX), nsid) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("LOAD shall fail with token with wrong GID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                               VALID_GROUP_ID, \
+                                               INVALID_INDEX), nsid) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("LOAD shall fail with token with wrong index\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                               VALID_GROUP_ID, \
+                                               VALID_INDEX) \
+                          | INVALID_RESERVED_TOKEN_BIT, nsid) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("LOAD shall fail with token with wrong reserved bits\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall pass with valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(MAKE_NS_CLIENT_TOKEN(0xF0, \
+                                               VALID_GROUP_ID, \
+                                               VALID_INDEX)) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("SAVE shall fail with token with wrong TID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                               INVALID_GROUP_ID, \
+                                               VALID_INDEX)) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("SAVE shall fail with token with wrong GID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                               VALID_GROUP_ID, \
+                                               INVALID_INDEX)) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("SAVE shall fail with token with wrong index\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                               VALID_GROUP_ID, \
+                                               VALID_INDEX) \
+                          | INVALID_RESERVED_TOKEN_BIT) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("SAVE shall fail with token with wrong reserved bits\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("SAVE shall pass with valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                                  INVALID_GROUP_ID, \
+                                                  VALID_INDEX)) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("RELEASE shall fail with token with wrong GID\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                                  VALID_GROUP_ID, \
+                                                  INVALID_INDEX)) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("RELEASE shall fail with token with wrong index\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                               VALID_GROUP_ID, \
+                                               VALID_INDEX) \
+                          | INVALID_RESERVED_TOKEN_BIT) \
+        != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("RELEASE shall fail with token with wrong reserved bits\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Save without loading */
+static void tfm_nsid_test_case_18(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token) != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("SAVE shall fail when not loaded\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Save released context */
+static void tfm_nsid_test_case_19(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    token = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+
+    if (token != MAKE_NS_CLIENT_TOKEN(thread_id, VALID_GROUP_ID, VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token) != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("SAVE shall fail with released token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Save inactive context */
+static void tfm_nsid_test_case_20(struct test_result_t *ret)
+{
+    uint32_t token_a;
+    uint32_t token_b;
+
+    nsid_test_case_init(ret);
+
+    token_a = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id);
+    token_b = nsid_acquire_ctx_svc(VALID_GROUP_ID, thread_id + 1);
+
+    if (token_a != MAKE_NS_CLIENT_TOKEN(thread_id, \
+                                        VALID_GROUP_ID, \
+                                        VALID_INDEX) || \
+        token_b != MAKE_NS_CLIENT_TOKEN(thread_id + 1, \
+                                        VALID_GROUP_ID, \
+                                        VALID_INDEX)) {
+        TEST_FAIL("ACQUIRE shall return a valid token\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_load_ctx_svc(token_a, nsid) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("LOAD shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_save_ctx_svc(token_b) != TFM_NS_CLIENT_ERR_INVALID_TOKEN) {
+        TEST_FAIL("SAVE shall fail with inactive token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token_a) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (nsid_release_ctx_svc(token_b) != TFM_NS_CLIENT_ERR_SUCCESS) {
+        TEST_FAIL("RELEASE shall success with valid token value\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+/* Call in thread mode */
+static void tfm_nsid_test_case_21(struct test_result_t *ret)
+{
+    uint32_t token;
+
+    nsid_test_case_init(ret);
+
+    if (tfm_nsce_init(0) != 0) {
+        TEST_FAIL("INITIALIZE shall not success in thread mode\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    token = tfm_nsce_acquire_ctx(VALID_GROUP_ID, thread_id);
+
+    if (token != TFM_NS_CLIENT_ERR_INVALID_ACCESS) {
+        TEST_FAIL("ACQUIRE shall not success in thread mode\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (tfm_nsce_load_ctx(token, nsid) != TFM_NS_CLIENT_ERR_INVALID_ACCESS) {
+        TEST_FAIL("LOAD shall not success in thread mode\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (tfm_nsce_save_ctx(token) != TFM_NS_CLIENT_ERR_INVALID_ACCESS) {
+        TEST_FAIL("SAVE shall not success in thread mode\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    if (tfm_nsce_release_ctx(token) != TFM_NS_CLIENT_ERR_INVALID_ACCESS) {
+        TEST_FAIL("RELEASE shall not success in thread mode\r\n");
+        nsid_test_case_finish(ret);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+
+    nsid_test_case_finish(ret);
+}
+
+static struct test_t nsid_test_cases[] = {
+    /* Normal test */
+    {&tfm_nsid_test_case_1, "TFM_NS_NSID_TEST_1001",
+     "NSID management initialize ctx pass", {TEST_PASSED}},
+    {&tfm_nsid_test_case_2, "TFM_NS_NSID_TEST_1002",
+     "NSID management normal full sequence pass", {TEST_PASSED}},
+    {&tfm_nsid_test_case_3, "TFM_NS_NSID_TEST_1003",
+     "NSID management acquire-release sequence pass", {TEST_PASSED}},
+    {&tfm_nsid_test_case_4, "TFM_NS_NSID_TEST_1004",
+     "NSID management acquire-load-release sequence pass", {TEST_PASSED}},
+    {&tfm_nsid_test_case_5, "TFM_NS_NSID_TEST_1005",
+     "NSID management switching contexts pass", {TEST_PASSED}},
+    {&tfm_nsid_test_case_6, "TFM_NS_NSID_TEST_1006",
+     "NSID management releasing inactive context pass", {TEST_PASSED}},
+    /* Corner case test */
+    {&tfm_nsid_test_case_7, "TFM_NS_NSID_TEST_1007",
+     "NSID management pass with max valid NSID", {TEST_PASSED}},
+    {&tfm_nsid_test_case_8, "TFM_NS_NSID_TEST_1008",
+     "NSID management pass with min valid NSID", {TEST_PASSED}},
+    {&tfm_nsid_test_case_9, "TFM_NS_NSID_TEST_1009",
+     "NSID management pass with min TID", {TEST_PASSED}},
+    {&tfm_nsid_test_case_10, "TFM_NS_NSID_TEST_1010",
+     "NSID management pass with max TID", {TEST_PASSED}},
+    {&tfm_nsid_test_case_11, "TFM_NS_NSID_TEST_1011",
+     "NSID management pass when loading B without saving A", {TEST_PASSED}},
+    /* Error test */
+    /* Wrong params */
+    {&tfm_nsid_test_case_12, "TFM_NS_NSID_TEST_1012",
+     "NSID management loading fail with non-negative NSID", {TEST_PASSED}},
+    {&tfm_nsid_test_case_13, "TFM_NS_NSID_TEST_1013",
+     "NSID management fail when loading with invalid token", {TEST_PASSED}},
+    {&tfm_nsid_test_case_14, "TFM_NS_NSID_TEST_1014",
+     "NSID management fail when saving with invalid token", {TEST_PASSED}},
+    {&tfm_nsid_test_case_15, "TFM_NS_NSID_TEST_1015",
+     "NSID management fail when releasing with invalid token", {TEST_PASSED}},
+    {&tfm_nsid_test_case_16, "TFM_NS_NSID_TEST_1016",
+     "NSID management fail when acquiring with undefault GID", {TEST_PASSED}},
+    {&tfm_nsid_test_case_17, "TFM_NS_NSID_TEST_1017",
+     "NSID management fail with token containing wrong info", {TEST_PASSED}},
+    /* Wrong sequence */
+    {&tfm_nsid_test_case_18, "TFM_NS_NSID_TEST_1018",
+     "NSID management fail when saving without loading", {TEST_PASSED}},
+    {&tfm_nsid_test_case_19, "TFM_NS_NSID_TEST_1019",
+     "NSID management fail when saving released token", {TEST_PASSED}},
+    {&tfm_nsid_test_case_20, "TFM_NS_NSID_TEST_1020",
+     "NSID management fail when saving inactive token", {TEST_PASSED}},
+    /* Other tests */
+    {&tfm_nsid_test_case_21, "TFM_NS_NSID_TEST_1021",
+     "NSID management fail when called in thread mode", {TEST_PASSED}},
+};
+
+void register_testsuite_nsid_test(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size;
+
+    list_size = (sizeof(nsid_test_cases) / sizeof(nsid_test_cases[0]));
+
+    set_testsuite("TFM NSID Test (TFM_NSID_TEST_1xxx)",
+                  nsid_test_cases, list_size, p_test_suite);
+}
diff --git a/test/suites/nsid/nsid_testsuite.h b/test/suites/nsid/nsid_testsuite.h
new file mode 100644
index 0000000..3839f4b
--- /dev/null
+++ b/test/suites/nsid/nsid_testsuite.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __NSID_TESTSUITE_H__
+#define __NSID_TESTSUITE_H__
+
+#include "test_framework.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void register_testsuite_nsid_test(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __NSID_TESTSUITE_H__ */