SPM: New IRQ init and handler integration approach

The IRQ initialization is done by two HAL APIs.
This patch changes to use one API per IRQ.

The IRQ handler matches the handler name in VTOR in template.
This patch changes to let platform integrate.

Change-Id: I004fa4715d3210341f205634aebf509e6f8010e9
Signed-off-by: Kevin Peng <kevin.peng@arm.com>
Co-authored-by: Ken Liu <ken.liu@arm.com>
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.c b/secure_fw/spm/cmsis_psa/spm_ipc.c
index 33c8a33..729374d 100644
--- a/secure_fw/spm/cmsis_psa/spm_ipc.c
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.c
@@ -46,8 +46,6 @@
 TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
                  TFM_CONN_HANDLE_MAX_NUM);
 
-#include "tfm_secure_irq_handlers_ipc.inc"
-
 /*********************** Connection handle conversion APIs *******************/
 
 #define CONVERSION_FACTOR_BITOFFSET    3
@@ -798,7 +796,7 @@
 
 __attribute__((naked))
 static psa_flih_result_t tfm_flih_deprivileged_handling(void *p_pt,
-                                                        psa_flih_func fn_flih,
+                                                        uintptr_t fn_flih,
                                                         void *p_context_ctrl)
 {
     __ASM volatile("SVC %0           \n"
@@ -806,38 +804,41 @@
                    : : "I" (TFM_SVC_PREPARE_DEPRIV_FLIH));
 }
 
-void spm_interrupt_handler(struct partition_load_info_t *p_ldinf,
-                           psa_signal_t signal,
-                           uint32_t irq_line,
-                           psa_flih_func flih_func)
+void spm_handle_interrupt(void *p_pt, struct irq_load_info_t *p_ildi)
 {
     psa_flih_result_t flih_result;
-    struct partition_t *p_pt;
+    struct partition_t *p_part;
 
-    p_pt = tfm_spm_get_partition_by_id(p_ldinf->pid);
-    if (!p_pt) {
+    if (!p_pt || !p_ildi) {
         tfm_core_panic();
     }
 
-    if (flih_func == NULL) {
+    p_part = (struct partition_t *)p_pt;
+
+    if (p_ildi->pid != p_part->p_ldinf->pid) {
+        tfm_core_panic();
+    }
+
+    if (p_ildi->flih_func == NULL) {
         /* SLIH Model Handling */
-        tfm_hal_irq_disable(irq_line);
+        tfm_hal_irq_disable(p_ildi->source);
         flih_result = PSA_FLIH_SIGNAL;
     } else {
         /* FLIH Model Handling */
-        if (tfm_spm_partition_get_privileged_mode(p_ldinf->flags) ==
+        if (tfm_spm_partition_get_privileged_mode(p_part->p_ldinf->flags) ==
                                                 TFM_PARTITION_PRIVILEGED_MODE) {
-            flih_result = flih_func();
+            flih_result = p_ildi->flih_func();
         } else {
             flih_result = tfm_flih_deprivileged_handling(
-                                                      p_pt, flih_func,
-                                                      pth_curr->p_context_ctrl);
+                                                   p_part,
+                                                   (uintptr_t)p_ildi->flih_func,
+                                                   pth_curr->p_context_ctrl);
         }
     }
 
     if (flih_result == PSA_FLIH_SIGNAL) {
         __disable_irq();
-        spm_assert_signal(p_pt, signal);
+        spm_assert_signal(p_pt, p_ildi->signal);
         __enable_irq();
     }
 }
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.h b/secure_fw/spm/cmsis_psa/spm_ipc.h
index b0456c7..7cc0553 100644
--- a/secure_fw/spm/cmsis_psa/spm_ipc.h
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.h
@@ -55,8 +55,6 @@
 
 #define TFM_MSG_MAGIC                   0x15154343
 
-typedef psa_flih_result_t (*psa_flih_func)(void);
-
 /* Message struct to collect parameter from client */
 struct tfm_msg_body_t {
     int32_t magic;
@@ -455,9 +453,17 @@
                                     const struct partition_load_info_t *p_ldinf,
                                     psa_signal_t signal);
 
-void spm_interrupt_handler(struct partition_load_info_t *p_pldi,
-                           psa_signal_t signal,
-                           uint32_t irq_line,
-                           psa_flih_func flih_func);
+/**
+ * \brief Entry of Secure interrupt handler. Platforms can call this function to
+ *        handle individual interrupts.
+ *
+ * \param[in] p_pt         The owner Partition of the interrupt to handle
+ * \param[in] p_ildi       The irq_load_info_t struct of the interrupt to handle
+ *
+ * Note:
+ *  The input parameters are maintained by platforms and they must be init-ed
+ *  in the interrupt init functions.
+ */
+void spm_handle_interrupt(void *p_pt, struct irq_load_info_t *p_ildi);
 
 #endif /* __SPM_IPC_H__ */
diff --git a/secure_fw/spm/cmsis_psa/static_load.c b/secure_fw/spm/cmsis_psa/static_load.c
index 3d0ca60..873d90b 100644
--- a/secure_fw/spm/cmsis_psa/static_load.c
+++ b/secure_fw/spm/cmsis_psa/static_load.c
@@ -186,14 +186,7 @@
     for (i = 0; i < p_ldinf->nirqs; i++) {
         p_partition->signals_allowed |= p_irq_info[i].signal;
 
-        if (tfm_spm_hal_set_secure_irq_priority(p_irq_info[i].source)
-                                                      != TFM_PLAT_ERR_SUCCESS) {
-            tfm_core_panic();
-        }
-
-        if (tfm_spm_hal_set_irq_target_state(p_irq_info[i].source,
-                                             TFM_IRQ_TARGET_STATE_SECURE)
-                                               != TFM_IRQ_TARGET_STATE_SECURE) {
+        if (p_irq_info[i].init(p_partition, p_irq_info) != TFM_HAL_SUCCESS) {
             tfm_core_panic();
         }
 
diff --git a/secure_fw/spm/cmsis_psa/tfm_secure_irq_handlers_ipc.inc.template b/secure_fw/spm/cmsis_psa/tfm_secure_irq_handlers_ipc.inc.template
deleted file mode 100644
index d7b9fde..0000000
--- a/secure_fw/spm/cmsis_psa/tfm_secure_irq_handlers_ipc.inc.template
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-{{utilities.donotedit_warning}}
-
-/* Definitions of privileged IRQ handlers (if any) */
-{% for partition in partitions %}
-    {% if partition.manifest.irqs %}
-        {% if partition.attr.conditional %}
-#ifdef {{partition.attr.conditional}}
-        {% endif %}
-#include "{{partition.header_file}}"
-extern struct partition_{{partition.manifest.name|lower}}_load_info_t {{partition.manifest.name|lower}}_load;
-        {% for irq in partition.manifest.irqs %}
-            {% set irq_data = namespace() %}
-            {% if partition.manifest.psa_framework_version == 1.0 %}
-                {% set irq_data.signal = irq.signal %}
-            {% else %}
-                {% set irq_data.signal = irq.name + "_SIGNAL" %}
-            {% endif %}
-            {% if irq.source is number %}
-void irq_{{irq.source}}_Handler(void)
-            {% elif irq.source %}
-void {{irq.source}}_Handler(void)
-            {% else %}
-#error "Interrupt source isn't provided for 'irqs' in partition {{partition.manifest.name}}"
-            {% endif %}
-{
-            {% if irq.source %}
-                {% if partition.manifest.psa_framework_version == 1.1 and irq.handling == "FLIH" %}
-                    {% set irq_data.flih =  irq.name|lower + "_flih" %}
-                {% else %}
-                    {% set irq_data.flih =  "NULL" %}
-                {% endif %}
-    spm_interrupt_handler((struct partition_load_info_t *)&{{partition.manifest.name|lower}}_load, {{irq_data.signal}}, {{irq.source}}, {{irq_data.flih}});
-            {% else %}
-#error "Interrupt source isn't provided for 'irqs' in partition {{partition.manifest.name}}"
-            {% endif %}
-}
-        {% endfor %}
-        {% if partition.attr.conditional %}
-#endif /* {{partition.attr.conditional}} */
-        {% endif %}
-
-    {% endif %}
-{% endfor %}
diff --git a/secure_fw/spm/include/load/interrupt_defs.h b/secure_fw/spm/include/load/interrupt_defs.h
index 84d3b40..0c7d24c 100644
--- a/secure_fw/spm/include/load/interrupt_defs.h
+++ b/secure_fw/spm/include/load/interrupt_defs.h
@@ -8,12 +8,27 @@
 #ifndef __INTERRUPT_DEFS_H__
 #define __INTERRUPT_DEFS_H__
 
+#include <stdint.h>
+#include "tfm_hal_defs.h"
 #include "psa/service.h"
 
+/* IRQ static load info */
 struct irq_load_info_t {
-    uint32_t source;                       /* IRQ source (number/index)      */
-    uint32_t flih_func;                    /* FLIH function - 0 if SLIH      */
-    psa_signal_t signal;                   /* The signal assigned for IRQ    */
+    /*
+     * Initialization function per interrupt.
+     * args:  owner Partition, irq_load_info
+     */
+    enum tfm_hal_status_t (*init)(void *pt, struct irq_load_info_t *pildi);
+    psa_flih_result_t (*flih_func)(void);     /* FLIH function, NULL for SLIH */
+    int32_t      pid;                         /* Owner Partition ID           */
+    uint32_t     source;                      /* IRQ source (number/index)    */
+    psa_signal_t signal;                      /* The signal assigned for IRQ  */
+};
+
+/* IRQ runtime data */
+struct irq_t {
+    void                   *p_pt;   /* The owner Partition struct partition_t */
+    struct irq_load_info_t *p_ildi; /* The interrupt load info                */
 };
 
 #endif /* __INTERRUPT_DEFS_H__ */