Build: Follow the 'source_structure.rst'

This is the first patch to follow the first commit of source structure
document. The items under the 'secure_fw' folder are re-organized:

- Create/Move some folders/files to follow document.
- Rename some folders to foll, for example, 'secure_fw/services' to
  'secure_fw/partitions'.
- Update affected files to make it work.

This is a big change, to make the structure meet the basic shape of
the structure document defined, and make it easier to be understood
for users. Staging changes are not applicable so they are combined
into one - and because it is not the final shape yet, so:

- Upcoming updates on the 'secure_fw' folder would follow up soon.
- Fine-tune about the 'source_structure.rst' would come, too.

Change-Id: I5c11175e0a4579cd9b42d3e3519dbffb87334d0b
Signed-off-by: Ken Liu <ken.liu@arm.com>
diff --git a/secure_fw/spm/model_ipc/tfm_thread.c b/secure_fw/spm/model_ipc/tfm_thread.c
new file mode 100644
index 0000000..1d66e25
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_thread.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include "tfm_arch.h"
+#include "tfm_thread.h"
+#include "tfm_utils.h"
+#include "tfm_memory_utils.h"
+#include "tfm/tfm_core_svc.h"
+#include "tfm/spm_api.h"
+#include "tfm_core_utils.h"
+
+/* Force ZERO in case ZI(bss) clear is missing */
+static struct tfm_core_thread_t *p_thrd_head = NULL;
+static struct tfm_core_thread_t *p_runn_head = NULL;
+static struct tfm_core_thread_t *p_curr_thrd = NULL;
+
+/* Define Macro to fetch global to support future expansion (PERCPU e.g.) */
+#define LIST_HEAD   p_thrd_head
+#define RUNN_HEAD   p_runn_head
+#define CURR_THRD   p_curr_thrd
+
+static struct tfm_core_thread_t *find_next_running_thread(
+                                                struct tfm_core_thread_t *pth)
+{
+    while (pth && pth->state != THRD_STATE_RUNNING) {
+        pth = pth->next;
+    }
+
+    return pth;
+}
+
+/* To get next running thread for scheduler */
+struct tfm_core_thread_t *tfm_core_thrd_get_next_thread(void)
+{
+    /*
+     * First RUNNING thread has highest priority since threads are sorted with
+     * priority.
+     */
+    return find_next_running_thread(RUNN_HEAD);
+}
+
+/* To get current thread for caller */
+struct tfm_core_thread_t *tfm_core_thrd_get_curr_thread(void)
+{
+    return CURR_THRD;
+}
+
+/* Insert a new thread into list by descending priority (Highest at head) */
+static void insert_by_prior(struct tfm_core_thread_t **head,
+                            struct tfm_core_thread_t *node)
+{
+    if (*head == NULL || (node->prior <= (*head)->prior)) {
+        node->next = *head;
+        *head = node;
+    } else {
+        struct tfm_core_thread_t *iter = *head;
+
+        while (iter->next && (node->prior > iter->next->prior)) {
+            iter = iter->next;
+        }
+        node->next = iter->next;
+        iter->next = node;
+    }
+}
+
+/*
+ * Set first running thread as head to reduce enumerate
+ * depth while searching for a first running thread.
+ */
+static void update_running_head(struct tfm_core_thread_t **runn,
+                                struct tfm_core_thread_t *node)
+{
+    if ((node->state == THRD_STATE_RUNNING) &&
+        (*runn == NULL || (node->prior < (*runn)->prior))) {
+        *runn = node;
+    } else {
+        *runn = LIST_HEAD;
+    }
+}
+
+/* Set context members only. No validation here */
+void tfm_core_thrd_init(struct tfm_core_thread_t *pth,
+                        tfm_core_thrd_entry_t pfn, void *param,
+                        uintptr_t stk_top, uintptr_t stk_btm)
+{
+    pth->prior = THRD_PRIOR_MEDIUM;
+    pth->state = THRD_STATE_CREATING;
+    pth->pfn = pfn;
+    pth->param = param;
+    pth->stk_btm = stk_btm;
+    pth->stk_top = stk_top;
+}
+
+uint32_t tfm_core_thrd_start(struct tfm_core_thread_t *pth)
+{
+    /* Validate parameters before really start */
+    if ((pth->state != THRD_STATE_CREATING) ||
+        (pth->pfn == NULL)                  ||
+        (pth->stk_btm == 0)                 ||
+        (pth->stk_top == 0)) {
+        return THRD_ERR_INVALID_PARAM;
+    }
+
+    /* Thread management runs in handler mode; set context for thread mode. */
+    tfm_arch_init_context(&pth->arch_ctx, pth->param, (uintptr_t)pth->pfn,
+                          pth->stk_btm, pth->stk_top);
+
+    /* Insert a new thread with priority */
+    insert_by_prior(&LIST_HEAD, pth);
+
+    /* Mark it as RUNNING after insertion */
+    tfm_core_thrd_set_state(pth, THRD_STATE_RUNNING);
+
+    return THRD_SUCCESS;
+}
+
+void tfm_core_thrd_set_state(struct tfm_core_thread_t *pth, uint32_t new_state)
+{
+    TFM_CORE_ASSERT(pth != NULL && new_state < THRD_STATE_INVALID);
+
+    pth->state = new_state;
+    update_running_head(&RUNN_HEAD, pth);
+}
+
+/* Scheduling won't happen immediately but after the exception returns */
+void tfm_core_thrd_activate_schedule(void)
+{
+    tfm_arch_trigger_pendsv();
+}
+
+void tfm_core_thrd_start_scheduler(struct tfm_core_thread_t *pth)
+{
+    /*
+     * There is no selected thread before scheduler start, assign the caller
+     * provided thread as the current thread. Update the hardware PSP/PSPLIM
+     * with the value in thread context to ensure they are identical.
+     * This function can be called only ONCE; further calling triggers assert.
+     */
+    TFM_CORE_ASSERT(CURR_THRD == NULL);
+    TFM_CORE_ASSERT(pth != NULL);
+    TFM_CORE_ASSERT(pth->arch_ctx.sp != 0);
+
+    tfm_arch_update_ctx(&pth->arch_ctx);
+
+    CURR_THRD = pth;
+
+    tfm_core_thrd_activate_schedule();
+}
+
+void tfm_core_thrd_switch_context(struct tfm_arch_ctx_t *p_actx,
+                                  struct tfm_core_thread_t *prev,
+                                  struct tfm_core_thread_t *next)
+{
+    TFM_CORE_ASSERT(prev != NULL);
+    TFM_CORE_ASSERT(next != NULL);
+
+    /*
+     * First, update latest context into the current thread context.
+     * Then, update background context with next thread's context.
+     */
+    tfm_core_util_memcpy(&prev->arch_ctx, p_actx, sizeof(*p_actx));
+    tfm_core_util_memcpy(p_actx, &next->arch_ctx, sizeof(next->arch_ctx));
+
+    /* Update current thread indicator */
+    CURR_THRD = next;
+}