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/docs/integration_guide/tfm_secure_irq_integration_guide.rst b/docs/integration_guide/tfm_secure_irq_integration_guide.rst
index 40f7fa9..e0f5fdd 100644
--- a/docs/integration_guide/tfm_secure_irq_integration_guide.rst
+++ b/docs/integration_guide/tfm_secure_irq_integration_guide.rst
@@ -58,7 +58,7 @@
- Binding the interrupt to a Secure Partition.
- Granting the Secure Partition access permissions to the device of the
interrupt.
-- Configurating the interrupt.
+- Initializing the interrupt.
- Integrating the interrupt handling function
TF-M has two Test Partitions as good examples for both FLIH [3]_ and SLIH [4]_.
@@ -86,7 +86,7 @@
{
"irqs": [
{
- "source": "5",
+ "source": 5,
"signal": "DUAL_TIMER_SIGNAL"
},
{
@@ -138,7 +138,7 @@
"handling": "FLIH"
},
{
- "source" : "5",
+ "source" : 5,
"name" : "DUAL_TIMER",
"handling": "SLIH"
}
@@ -238,68 +238,98 @@
some_driver_code.c
)
-Configurating the Interrupts
-============================
+Initializing the Interrupts
+===========================
-Setting up configurations for an interrupt mainly includes setting the priority
-and targetting the interrupt to Secure State.
+Platforms must define an interrupt initialization function for each Secure
+interrupt.
+
+The prototype of the function is:
+
+.. code-block:: c
+
+ enum tfm_hal_status_t {source_symbol}_init(void *p_pt,
+ struct irq_load_info_t *p_ildi)
+
+The ``{source_symbol}`` is:
+
+- ``irq_{source}``, if the ``source`` attribute of the IRQ in Partition manifest
+ is a number
+- Lowercase of ``source`` attribute, if ``source`` is a symbolic name
+
+For example if the manifest declares ``"source": 5``, then the function name
+is ``irq_5_init``.
+If the mannifest declares ``"source" : "TIMER_1_IRQ"`` then the function
+name is ``timer_1_irq_init``.
+
+The initialization of an interrupt must include:
+
+- setting the priority
+- ensuring that the interrupt targets the Secure State.
+- saving the interrupt information
Setting Priority
----------------
-TF-M provides a HAL API for platforms to set priorities for interrupts:
+The priority of external interrupts must be in the following range:
+``(0, N / 2)``, where ``N`` is the number of configurable priorities.
+Smaller values have higher priorities.
-.. code-block:: c
+For example if the number of configurable priority of your interrupt controller
+is 16, you must use the priorities in range ``(0, 8)`` only, boundaries
+excluded.
- enum tfm_plat_err_t tfm_spm_hal_set_secure_irq_priority(IRQn_Type irq_line);
+Note that these are not the values set into the interrupt controllers.
+Different platforms may have different values for those priorities.
+But if you use the ``NVIC_SetPriority`` function provided by CMSIS to set
+priorities, you can pass the values directly.
-The priority value must be less than the value of ``PendSV`` (0x80) and greater
-than the value of ``SVC`` (0x0).
-
-Platforms have the fexibilities on how to assign the priorities to interrupts
-and how to get the priority for the given ``irq_line`` in the HAL API.
-For example, platforms can define a static map between the ``irq_line`` and
-priorities for the API to search in.
+Platforms have the fexibilities on the assignment of priorities.
Targeting Interrupts to Secure
------------------------------
-TF-M provides another HAL API for platforms to target interrupts to Secure
-State.
+In single core systems, platform integrators must ensure that the Secure
+interrupts target to Secure State by setting the Interrupt Controller.
+
+In multi-core systems, this might be optional.
+
+Saving the Interrupt Information
+--------------------------------
+
+The initialization function is called during Partition loading with the
+following information:
+
+- ``p_pt`` - pointer to Partition runtime struct of the owner Partition
+- ``p_ildi`` - pointer to ``irq_load_info_t`` struct of the interrupt
+
+Platforms must save the information for the future use.
+See `Integrating the Interrupt Handling Function`_ for the usage.
+
+The easiest way is to save them in global variables for each interrupt.
+TF-M provides a struct for saving the information:
.. code-block:: c
- enum irq_target_state_t tfm_spm_hal_set_irq_target_state(
- IRQn_Type irq_line,
- enum irq_target_state_t target_state);
-
-The ``target_state`` is ``TFM_IRQ_TARGET_STATE_SECURE`` for Secure IRQs.
+ struct irq_t {
+ void *p_pt;
+ struct irq_load_info_t *p_ildi;
+ };
Integrating the Interrupt Handling Function
===========================================
-TF-M automatically generates interrupt handling functions for each interrupt
-assigned to Secure Partitions during building.
-The format of the handling functions is:
+TF-M provides an interrupt handling entry for Secure interrupts:
.. code-block:: c
- void irq_{{source}}_Handler(void)
+ void spm_handle_interrupt(void *p_pt, struct irq_load_info_t *p_ildi)
-if ``source`` of the IRQ in manifest is a number.
+The ``p_pt`` and ``p_ildi`` are the information passed to interrupt
+initialization functions and saved by platforms.
-.. code-block:: c
-
- void {{irq.source}}_Handler(void)
-
-if ``source`` of the IRQ in manifest is a symbolic name.
-
-Platforms should integrate the handling functions in their own manner.
-For example, they can put the functions to Vector Table directly or have a
-integration layer where the handlers in Vector Table calls the functions
-generated by TF-M.
-
-Please check ``startup_cmsdk_mps2_an521_s`` for example of the former approach.
+Platforms should call this entry function in the interrupt handlers defined in
+Vector Table with the saved information for each interrupt.
****************************
Enabling the Interrupt Tests
diff --git a/docs/technical_references/design_docs/hardware_abstraction_layer.rst b/docs/technical_references/design_docs/hardware_abstraction_layer.rst
index 3c53df9..cdff8cc 100644
--- a/docs/technical_references/design_docs/hardware_abstraction_layer.rst
+++ b/docs/technical_references/design_docs/hardware_abstraction_layer.rst
@@ -584,6 +584,46 @@
- ``TFM_HAL_ERROR_GENERIC`` - failed to clear the pending interrupt.
- ``TFM_HAL_SUCCESS`` - the pending interrupt has been cleared.
+Initializations
+^^^^^^^^^^^^^^^
+
+**Prototype**
+
+.. code-block:: c
+
+ enum tfm_hal_status_t {source_symbol}_init(void *p_pt,
+ struct irq_load_info_t *p_ildi)
+
+The ``{source_symbol}`` is:
+
+- ``irq_{source}``, if the ``source`` attribute of the IRQ in Partition manifest
+ is a number
+- Lowercase of ``source`` attribute, if ``source`` is a symbolic name
+
+**Description**
+
+Each interrupt has an initialization function individually.
+The :term:`SPM` calls the functions while loading the Partitions.
+
+The following initializations are required for each interrupt:
+
+- Setting the priority. The value must between 0 to 0x80 exclusively.
+- Ensuring that the interrupt targets the Secure State.
+- Saving the input parameters for future use.
+
+Platforms can have extra initializations as well.
+
+**Parameter**
+
+- ``p_pt`` - pointer to Partition runtime struct of the owner Partition
+- ``p_ildi`` - pointer to ``irq_load_info_t`` struct of the interrupt
+
+**Note**
+
+Please refer to the
+:doc: `IRQ intergration guide<tfm_secure_irq_integration_guide>`
+for more information.
+
************************************
API Definition for Secure Partitions
************************************
diff --git a/platform/ext/target/arm/mps2/an519/CMakeLists.txt b/platform/ext/target/arm/mps2/an519/CMakeLists.txt
index da80a23..f67f4ad 100644
--- a/platform/ext/target/arm/mps2/an519/CMakeLists.txt
+++ b/platform/ext/target/arm/mps2/an519/CMakeLists.txt
@@ -88,6 +88,7 @@
native_drivers/mpu_armv8m_drv.c
native_drivers/ppc_sse200_drv.c
spm_hal.c
+ tfm_interrupts.c
tfm_hal_isolation.c
target_cfg.c
native_drivers/ppc_sse200_drv.c
diff --git a/platform/ext/target/arm/mps2/an519/tfm_interrupts.c b/platform/ext/target/arm/mps2/an519/tfm_interrupts.c
new file mode 100644
index 0000000..4b7619d
--- /dev/null
+++ b/platform/ext/target/arm/mps2/an519/tfm_interrupts.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "cmsis.h"
+#include "spm_ipc.h"
+#include "tfm_hal_interrupt.h"
+#include "tfm_peripherals_def.h"
+#include "load/interrupt_defs.h"
+
+static struct irq_load_info_t *p_tfm_timer0_irq_ldinf = NULL;
+static void *p_timer0_pt = NULL;
+
+void TFM_TIMER0_IRQ_Handler(void)
+{
+ spm_handle_interrupt(p_timer0_pt, p_tfm_timer0_irq_ldinf);
+}
+
+enum tfm_hal_status_t tfm_timer0_irq_init(void *p_pt,
+ struct irq_load_info_t *p_ildi)
+{
+ p_tfm_timer0_irq_ldinf = p_ildi;
+ p_timer0_pt = p_pt;
+
+ NVIC_SetPriority(TFM_TIMER0_IRQ, DEFAULT_IRQ_PRIORITY);
+ NVIC_ClearTargetState(TFM_TIMER0_IRQ);
+ NVIC_DisableIRQ(TFM_TIMER0_IRQ);
+
+ return TFM_HAL_SUCCESS;
+}
diff --git a/platform/ext/target/arm/mps2/an519/tfm_peripherals_def.h b/platform/ext/target/arm/mps2/an519/tfm_peripherals_def.h
index 3dc7174..a0e1998 100644
--- a/platform/ext/target/arm/mps2/an519/tfm_peripherals_def.h
+++ b/platform/ext/target/arm/mps2/an519/tfm_peripherals_def.h
@@ -15,6 +15,12 @@
extern "C" {
#endif
+/*
+ * Quantized default IRQ priority, the value is:
+ * (Number of configurable priority) / 4: (1UL << __NVIC_PRIO_BITS) / 4
+ */
+#define DEFAULT_IRQ_PRIORITY (1UL << (__NVIC_PRIO_BITS - 2))
+
#define TFM_TIMER0_IRQ (TIMER0_IRQn)
#define TFM_TIMER1_IRQ (TIMER1_IRQn)
diff --git a/platform/ext/target/arm/mps2/an521/CMakeLists.txt b/platform/ext/target/arm/mps2/an521/CMakeLists.txt
index 8c1aa0d..977e8f0 100644
--- a/platform/ext/target/arm/mps2/an521/CMakeLists.txt
+++ b/platform/ext/target/arm/mps2/an521/CMakeLists.txt
@@ -94,6 +94,7 @@
native_drivers/mpu_armv8m_drv.c
native_drivers/ppc_sse200_drv.c
spm_hal.c
+ tfm_interrupts.c
tfm_hal_isolation.c
target_cfg.c
native_drivers/ppc_sse200_drv.c
diff --git a/platform/ext/target/arm/mps2/an521/tfm_interrupts.c b/platform/ext/target/arm/mps2/an521/tfm_interrupts.c
new file mode 100644
index 0000000..3ca0aac
--- /dev/null
+++ b/platform/ext/target/arm/mps2/an521/tfm_interrupts.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "cmsis.h"
+#include "spm_ipc.h"
+#include "tfm_hal_interrupt.h"
+#include "tfm_peripherals_def.h"
+#include "load/interrupt_defs.h"
+
+static struct irq_t timer0_irq = {0};
+
+void TFM_TIMER0_IRQ_Handler(void)
+{
+ spm_handle_interrupt(timer0_irq.p_pt, timer0_irq.p_ildi);
+}
+
+enum tfm_hal_status_t tfm_timer0_irq_init(void *p_pt,
+ struct irq_load_info_t *p_ildi)
+{
+ timer0_irq.p_ildi = p_ildi;
+ timer0_irq.p_pt = p_pt;
+
+ NVIC_SetPriority(TFM_TIMER0_IRQ, DEFAULT_IRQ_PRIORITY);
+ NVIC_ClearTargetState(TFM_TIMER0_IRQ);
+ NVIC_DisableIRQ(TFM_TIMER0_IRQ);
+
+ return TFM_HAL_SUCCESS;
+}
diff --git a/platform/ext/target/arm/mps2/an521/tfm_peripherals_def.h b/platform/ext/target/arm/mps2/an521/tfm_peripherals_def.h
index 215036a..00e9b36 100644
--- a/platform/ext/target/arm/mps2/an521/tfm_peripherals_def.h
+++ b/platform/ext/target/arm/mps2/an521/tfm_peripherals_def.h
@@ -15,6 +15,12 @@
extern "C" {
#endif
+/*
+ * Quantized default IRQ priority, the value is:
+ * (Number of configurable priority) / 4: (1UL << __NVIC_PRIO_BITS) / 4
+ */
+#define DEFAULT_IRQ_PRIORITY (1UL << (__NVIC_PRIO_BITS - 2))
+
#define TFM_TIMER0_IRQ (TIMER0_IRQn)
#define TFM_TIMER1_IRQ (TIMER1_IRQn)
#define FF_TEST_UART_IRQ (UARTTX2_IRQn)
diff --git a/platform/ext/target/arm/mps3/an524/CMakeLists.txt b/platform/ext/target/arm/mps3/an524/CMakeLists.txt
index c4a5501..c7fb74e 100644
--- a/platform/ext/target/arm/mps3/an524/CMakeLists.txt
+++ b/platform/ext/target/arm/mps3/an524/CMakeLists.txt
@@ -91,6 +91,7 @@
native_drivers/uart_cmsdk_drv.c
native_drivers/timer_cmsdk_drv.c
spm_hal.c
+ tfm_interrupts.c
tfm_hal_isolation.c
target_cfg.c
native_drivers/ppc_sse200_drv.c
diff --git a/platform/ext/target/arm/mps3/an524/tfm_interrupts.c b/platform/ext/target/arm/mps3/an524/tfm_interrupts.c
new file mode 100644
index 0000000..3ca0aac
--- /dev/null
+++ b/platform/ext/target/arm/mps3/an524/tfm_interrupts.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "cmsis.h"
+#include "spm_ipc.h"
+#include "tfm_hal_interrupt.h"
+#include "tfm_peripherals_def.h"
+#include "load/interrupt_defs.h"
+
+static struct irq_t timer0_irq = {0};
+
+void TFM_TIMER0_IRQ_Handler(void)
+{
+ spm_handle_interrupt(timer0_irq.p_pt, timer0_irq.p_ildi);
+}
+
+enum tfm_hal_status_t tfm_timer0_irq_init(void *p_pt,
+ struct irq_load_info_t *p_ildi)
+{
+ timer0_irq.p_ildi = p_ildi;
+ timer0_irq.p_pt = p_pt;
+
+ NVIC_SetPriority(TFM_TIMER0_IRQ, DEFAULT_IRQ_PRIORITY);
+ NVIC_ClearTargetState(TFM_TIMER0_IRQ);
+ NVIC_DisableIRQ(TFM_TIMER0_IRQ);
+
+ return TFM_HAL_SUCCESS;
+}
diff --git a/platform/ext/target/arm/mps3/an524/tfm_peripherals_def.h b/platform/ext/target/arm/mps3/an524/tfm_peripherals_def.h
index b487d28..a745036 100644
--- a/platform/ext/target/arm/mps3/an524/tfm_peripherals_def.h
+++ b/platform/ext/target/arm/mps3/an524/tfm_peripherals_def.h
@@ -15,6 +15,12 @@
extern "C" {
#endif
+/*
+ * Quantized default IRQ priority, the value is:
+ * (Number of configurable priority) / 4: (1UL << __NVIC_PRIO_BITS) / 4
+ */
+#define DEFAULT_IRQ_PRIORITY (1UL << (__NVIC_PRIO_BITS - 2))
+
#define TFM_TIMER0_IRQ (TIMER0_IRQn)
#define TFM_TIMER1_IRQ (TIMER1_IRQn)
diff --git a/platform/ext/target/arm/musca_b1/sse_200/CMakeLists.txt b/platform/ext/target/arm/musca_b1/sse_200/CMakeLists.txt
index ac9e0ee..2a38424 100644
--- a/platform/ext/target/arm/musca_b1/sse_200/CMakeLists.txt
+++ b/platform/ext/target/arm/musca_b1/sse_200/CMakeLists.txt
@@ -110,6 +110,7 @@
$<$<NOT:$<BOOL:${FORWARD_PROT_MSG}>>:${CMAKE_MUSCA_B1_COMMON_DIR}/Native_Driver/musca_b1_eflash_drv.c>
Native_Driver/musca_b1_scc_drv.c
spm_hal.c
+ tfm_interrupts.c
tfm_hal_isolation.c
attest_hal.c
target_cfg.c
diff --git a/platform/ext/target/arm/musca_b1/sse_200/tfm_interrupts.c b/platform/ext/target/arm/musca_b1/sse_200/tfm_interrupts.c
new file mode 100644
index 0000000..3ca0aac
--- /dev/null
+++ b/platform/ext/target/arm/musca_b1/sse_200/tfm_interrupts.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "cmsis.h"
+#include "spm_ipc.h"
+#include "tfm_hal_interrupt.h"
+#include "tfm_peripherals_def.h"
+#include "load/interrupt_defs.h"
+
+static struct irq_t timer0_irq = {0};
+
+void TFM_TIMER0_IRQ_Handler(void)
+{
+ spm_handle_interrupt(timer0_irq.p_pt, timer0_irq.p_ildi);
+}
+
+enum tfm_hal_status_t tfm_timer0_irq_init(void *p_pt,
+ struct irq_load_info_t *p_ildi)
+{
+ timer0_irq.p_ildi = p_ildi;
+ timer0_irq.p_pt = p_pt;
+
+ NVIC_SetPriority(TFM_TIMER0_IRQ, DEFAULT_IRQ_PRIORITY);
+ NVIC_ClearTargetState(TFM_TIMER0_IRQ);
+ NVIC_DisableIRQ(TFM_TIMER0_IRQ);
+
+ return TFM_HAL_SUCCESS;
+}
diff --git a/platform/ext/target/arm/musca_b1/sse_200/tfm_peripherals_def.h b/platform/ext/target/arm/musca_b1/sse_200/tfm_peripherals_def.h
index f445f01..92a96fb 100644
--- a/platform/ext/target/arm/musca_b1/sse_200/tfm_peripherals_def.h
+++ b/platform/ext/target/arm/musca_b1/sse_200/tfm_peripherals_def.h
@@ -15,6 +15,12 @@
extern "C" {
#endif
+/*
+ * Quantized default IRQ priority, the value is:
+ * (Number of configurable priority) / 4: (1UL << __NVIC_PRIO_BITS) / 4
+ */
+#define DEFAULT_IRQ_PRIORITY (1UL << (__NVIC_PRIO_BITS - 2))
+
#define TFM_TIMER0_IRQ (TIMER0_IRQn)
#define TFM_TIMER1_IRQ (TIMER1_IRQn)
#define FF_TEST_UART_IRQ (UART1_Tx_IRQn)
diff --git a/platform/ext/target/arm/musca_s1/CMakeLists.txt b/platform/ext/target/arm/musca_s1/CMakeLists.txt
index 6aa42b3..908785c 100644
--- a/platform/ext/target/arm/musca_s1/CMakeLists.txt
+++ b/platform/ext/target/arm/musca_s1/CMakeLists.txt
@@ -91,6 +91,7 @@
Native_Driver/qspi_ip6514e_drv.c
Native_Driver/cache_drv.c
spm_hal.c
+ tfm_interrupts.c
tfm_hal_isolation.c
target_cfg.c
Native_Driver/timer_cmsdk_drv.c
diff --git a/platform/ext/target/arm/musca_s1/tfm_interrupts.c b/platform/ext/target/arm/musca_s1/tfm_interrupts.c
new file mode 100644
index 0000000..3ca0aac
--- /dev/null
+++ b/platform/ext/target/arm/musca_s1/tfm_interrupts.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "cmsis.h"
+#include "spm_ipc.h"
+#include "tfm_hal_interrupt.h"
+#include "tfm_peripherals_def.h"
+#include "load/interrupt_defs.h"
+
+static struct irq_t timer0_irq = {0};
+
+void TFM_TIMER0_IRQ_Handler(void)
+{
+ spm_handle_interrupt(timer0_irq.p_pt, timer0_irq.p_ildi);
+}
+
+enum tfm_hal_status_t tfm_timer0_irq_init(void *p_pt,
+ struct irq_load_info_t *p_ildi)
+{
+ timer0_irq.p_ildi = p_ildi;
+ timer0_irq.p_pt = p_pt;
+
+ NVIC_SetPriority(TFM_TIMER0_IRQ, DEFAULT_IRQ_PRIORITY);
+ NVIC_ClearTargetState(TFM_TIMER0_IRQ);
+ NVIC_DisableIRQ(TFM_TIMER0_IRQ);
+
+ return TFM_HAL_SUCCESS;
+}
diff --git a/platform/ext/target/arm/musca_s1/tfm_peripherals_def.h b/platform/ext/target/arm/musca_s1/tfm_peripherals_def.h
index f445f01..92a96fb 100644
--- a/platform/ext/target/arm/musca_s1/tfm_peripherals_def.h
+++ b/platform/ext/target/arm/musca_s1/tfm_peripherals_def.h
@@ -15,6 +15,12 @@
extern "C" {
#endif
+/*
+ * Quantized default IRQ priority, the value is:
+ * (Number of configurable priority) / 4: (1UL << __NVIC_PRIO_BITS) / 4
+ */
+#define DEFAULT_IRQ_PRIORITY (1UL << (__NVIC_PRIO_BITS - 2))
+
#define TFM_TIMER0_IRQ (TIMER0_IRQn)
#define TFM_TIMER1_IRQ (TIMER1_IRQn)
#define FF_TEST_UART_IRQ (UART1_Tx_IRQn)
diff --git a/platform/ext/target/cypress/psoc64/CMakeLists.txt b/platform/ext/target/cypress/psoc64/CMakeLists.txt
index 11cb736..f6c925d 100644
--- a/platform/ext/target/cypress/psoc64/CMakeLists.txt
+++ b/platform/ext/target/cypress/psoc64/CMakeLists.txt
@@ -116,6 +116,7 @@
./Native_Driver/generated_source/cycfg_system.c
./Native_Driver/generated_source/cycfg_qspi_memslot.c
./spm_hal.c
+ ./tfm_interrupts.c
./tfm_hal_isolation.c
./CMSIS_Driver/Driver_Flash.c
./CMSIS_Driver/Driver_USART.c
diff --git a/platform/ext/target/cypress/psoc64/tfm_interrupts.c b/platform/ext/target/cypress/psoc64/tfm_interrupts.c
new file mode 100644
index 0000000..2925a80
--- /dev/null
+++ b/platform/ext/target/cypress/psoc64/tfm_interrupts.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "cmsis.h"
+#include "spm_ipc.h"
+#include "tfm_hal_interrupt.h"
+#include "tfm_peripherals_def.h"
+#include "load/interrupt_defs.h"
+
+static struct irq_t timer0_irq = {0};
+
+void TFM_TIMER0_IRQ_Handler(void)
+{
+ spm_handle_interrupt(timer0_irq.p_pt, timer0_irq.p_ildi);
+}
+
+enum tfm_hal_status_t tfm_timer0_irq_init(void *p_pt,
+ struct irq_load_info_t *p_ildi)
+{
+ timer0_irq.p_ildi = p_ildi;
+ timer0_irq.p_pt = p_pt;
+
+ NVIC_SetPriority(TFM_TIMER0_IRQ, DEFAULT_IRQ_PRIORITY);
+ NVIC_DisableIRQ(TFM_TIMER0_IRQ);
+
+ return TFM_HAL_SUCCESS;
+}
diff --git a/platform/ext/target/cypress/psoc64/tfm_peripherals_def.h b/platform/ext/target/cypress/psoc64/tfm_peripherals_def.h
index 7327f20..65c8ba0 100644
--- a/platform/ext/target/cypress/psoc64/tfm_peripherals_def.h
+++ b/platform/ext/target/cypress/psoc64/tfm_peripherals_def.h
@@ -15,6 +15,12 @@
extern "C" {
#endif
+/*
+ * Quantized default IRQ priority, the value is:
+ * (Number of configurable priority) / 4: (1UL << __NVIC_PRIO_BITS) / 4
+ */
+#define DEFAULT_IRQ_PRIORITY (1UL << (__NVIC_PRIO_BITS - 2))
+
#define TFM_TIMER0_IRQ (NvicMux3_IRQn)
#define TFM_TIMER1_IRQ (tcpwm_0_interrupts_1_IRQn)
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__ */
diff --git a/tools/templates/partition_load_info.template b/tools/templates/partition_load_info.template
index 07cd77e..77a18fe 100644
--- a/tools/templates/partition_load_info.template
+++ b/tools/templates/partition_load_info.template
@@ -55,6 +55,19 @@
extern psa_status_t {{manifest.entry_init}}(void);
{% endif %}
+/* Interrupt init functions */
+{% if counter.irq_counter > 0 %}
+ {% for irq in manifest.irqs %}
+ {% if irq.source is number %}}
+extern enum tfm_hal_status_t {{"irq_" + irq.source|string + "_init"}}(void *p_pt,
+ struct irq_load_info_t *p_ildi);
+ {% else %}
+extern enum tfm_hal_status_t {{irq.source|lower + "_init"}}(void *p_pt,
+ struct irq_load_info_t *p_ildi);
+ {% endif %}
+ {% endfor %}
+{% endif %}
+
/* partition load info type definition */
struct partition_{{manifest.name|lower}}_load_info_t {
/* common length load data */
@@ -230,8 +243,13 @@
{% for irq in manifest.irqs %}
{% set irq_info = namespace() %}
{% set irq_info.source = irq.source %}
+ {% if irq.source is number %}}
+ {% set irq_info.source_symbol = "irq_" + irq.source|string %}
+ {% else %}
+ {% set irq_info.source_symbol = irq.source|lower %}
+ {% endif %}
{% if manifest.psa_framework_version == 1.1 and irq.handling == "FLIH" %}
- {% set irq_info.flih_func = "(uint32_t)" + irq.name|lower + "_flih" %}
+ {% set irq_info.flih_func = irq.name|lower + "_flih" %}
{% else %}
{% set irq_info.flih_func = 0 %}
{% endif %}
@@ -241,9 +259,11 @@
{% set irq_info.signal = irq.name + "_SIGNAL" %}
{% endif %}
{
- .source = {{irq_info.source}},
+ .init = {{irq_info.source_symbol + "_init"}},
.flih_func = {{irq_info.flih_func}},
- .signal = {{irq_info.signal}},
+ .pid = {{manifest.name}},
+ .source = {{irq_info.source}},
+ .signal = {{irq_info.signal}},
},
{% endfor %}
},
diff --git a/tools/tfm_generated_file_list.yaml b/tools/tfm_generated_file_list.yaml
index 4fc2b74..95eae40 100644
--- a/tools/tfm_generated_file_list.yaml
+++ b/tools/tfm_generated_file_list.yaml
@@ -40,12 +40,6 @@
"output": "secure_fw/spm/cmsis_func/tfm_secure_irq_handlers.inc"
},
{
- "name": "Secure IRQ handlers for PSA API",
- "short_name": "tfm_secure_irq_handlers_ipc",
- "template": "secure_fw/spm/cmsis_psa/tfm_secure_irq_handlers_ipc.inc.template",
- "output": "secure_fw/spm/cmsis_psa/tfm_secure_irq_handlers_ipc.inc"
- },
- {
"name": "SID H file",
"short_name": "sid.h",
"template": "interface/include/psa_manifest/sid.h.template",