blob: 970d6ba11221b43272615abc84a15a9a98e0359d [file] [log] [blame]
Mate Toth-Pal4341de02018-10-02 12:55:47 +02001###################
2Secure IRQ handling
3###################
4
5The Armv8-M Architecture makes it possible to configure interrupts to target
6secure state.
7
8TF-M makes it possible for secure partitions to get notified of secure
9interrupts.
10
11By default TF-M sets up interrupts to target NS state. To configure an interrupt
12to target secure state and assign a handler to it, the manifest of the partition
13must be edited.
14
15See the following example:
16
17
18.. code-block:: yaml
19
20 {
21 "name": "...",
22 "type": "...",
23 "priority": "...",
24
25 ...
26
27 "irqs": [
28 {
Jaykumar Pitambarbhai Patelb3799e12019-10-08 17:23:12 +053029 "source": "5",
Mate Toth-Pal4341de02018-10-02 12:55:47 +020030 "signal": "DUAL_TIMER"
31 },
32 {
Jaykumar Pitambarbhai Patelb3799e12019-10-08 17:23:12 +053033 "source": "TFM_IRQ_LINE_TIMER_1",
Mate Toth-Pal4341de02018-10-02 12:55:47 +020034 "signal": "TIMER_1"
35 "tfm_irq_priority": 64,
36 }
37 ],
38
39 ...
40
41 }
42
43To set up a handler in a partition, the ``irqs`` node must be added. A single
44secure partition can have handlers registered for multiple IRQs, in this case
45the list ``irqs`` has multiple elements in it.
46
47An IRQ handler is defined by the following nodes:
48
Jaykumar Pitambarbhai Patelb3799e12019-10-08 17:23:12 +053049- ``source``: The IRQ number or the name IRQ line. With the name of the IRQ
50 line, there must be defined a macro in ``tfm_peripherals_def.h`` which is
51 substituted to the IRQ line num.
Mate Toth-Pal4341de02018-10-02 12:55:47 +020052- ``signal`` The name of the signal for this IRQ
53- ``tfm_irq_priority``: The priority of the IRQ. This number must be in the
54 range [0-255] inclusive. Please note that some of the less significant bits of
55 this value might be dropped based on the number of priority bits implemented
56 in the platform.
57
58.. important::
59
60 The name of the privileged interrupt handler is derived from the node
61 specifying the IRQ line number.
62
Jaykumar Pitambarbhai Patelb3799e12019-10-08 17:23:12 +053063 - In case ``source`` is IRQ number, the name of the handler becomes
64 ``void irq_<number>_Handler(void)``.
65 - In case ``source`` is defined IRQ macro, the name of the handler becomes
66 ``void <macro>_Handler(void)``.
Mate Toth-Pal4341de02018-10-02 12:55:47 +020067
68 This is important, because the derived name have to be present in the vector
69 table as the handler of the IRQ.
70
71.. Note::
72
Jaykumar Pitambarbhai Patelb3799e12019-10-08 17:23:12 +053073 ``signal`` and ``source`` are mandatory.
Mate Toth-Pal4341de02018-10-02 12:55:47 +020074
75 ``tfm_irq_priority`` is optional. If ``tfm_irq_priority`` is not set for an
76 IRQ, the default is value is ``TFM_DEFAULT_SECURE_IRQ_PRIOTITY``.
77
78If an IRQ handler is registered, TF-M will:
79
Jaykumar Pitambarbhai Patelb3799e12019-10-08 17:23:12 +053080- Set the IRQ with number or macro to target secure state
81- Set the priority of IRQ with number or macro to ``tfm_irq_priority`` or to
82 the default.
Mate Toth-Pal4341de02018-10-02 12:55:47 +020083
84TF-M configures the interrupt lines to be disabled by default. Interrupts for a
85service can be enabled by the secure service by calling
86``void tfm_enable_irq(psa_signal_t irq_signal)``. The function can be called in
87the service init function.
88
89*************
90Library model
91*************
92
93In Library model a function with the name derived from the value of the
Jaykumar Pitambarbhai Patelb3799e12019-10-08 17:23:12 +053094``source`` property is generated. This function will be put in the vector table
95by the linker (as the handlers in the startup assembly are defined as weak
96symbols). The code generated for this function will forward the call to the
97function with the name of the value of the ``signal`` property post-fixed with
98``_isr``.
Mate Toth-Pal4341de02018-10-02 12:55:47 +020099
100.. hint::
101
102 for a signal ``"signal": "DUAL_TIMER"`` the name of the handler function is
103 ``DUAL_TIMER_isr``
104
105The signature of the IRQ handler in the partition must be the following:
106
107.. code-block:: c
108
109 void partition_irq_handler(void);
110
111The detailed description on how secure interrupt handling works in the Library
112model see
113`Secure Partition Interrupt Handling design document <https://developer.trustedfirmware.org/w/tf_m/design/secure_partition_interrupt_handling/>`_.
114
115*********
116IPC model
117*********
118
119The detailed description on how secure interrupt handling works in the IPC
120model, see the
121`PSA Firmware Framework and RoT Services specification <https://pages.arm.com/psa-resources-ff.html>`_.
122
123######################
124Implementation details
125######################
126
Galanakis, Minosf56baf62019-11-11 13:57:42 +0000127****************************
128Library model implementation
129****************************
Mate Toth-Pal4341de02018-10-02 12:55:47 +0200130
131As a result of the function call like behaviour of secure services in library
132model, some information that is critical for the SPM to keep track of partition
133states, is stored on the stack of the active partitions. When an interrupt
134happens, and a handler partition is set to running state, it has access to its
135whole stack, and could corrupt the data stacked by the SPM. To prevent this, a
136separate Context stack is introduced for each secure partition, that is used by
137the SPM to save this information before starting to execute secure partition
138code.
139
140A stack frame to this context stack is pushed when the execution in the
141partition is interrupted, and when a handler in the partition interrupts another
142service. So the maximal stack usage can happen in the following situation:
143
144Consider secure partition 'A'. 'A' is running, and then it is interrupted by
145an other partition. Then the lowest priority interrupt of 'A' is triggered.
146Then before the handler returns, the partition is interrupted by another
147partition's handler. Then before the running handler returns, the second
148lowest interrupt of 'A' is triggered. This can go until the highest priority
149interrupt of 'A' is triggered, and then this last handler is interrupted. At
150this point the context stack looks like this:
151
152.. code-block::
153
154 +------------+
155 | [intr_ctx] |
156 | [hndl_ctx] |
157 | . |
158 | . |
159 | . |
160 | [intr_ctx] |
161 | [hndl_ctx] |
162 | [intr_ctx] |
163 +------------+
164
165 Legend:
166 [intr_ctx]: Frame pushed when the partition is interrupted
167 [hndl_ctx]: Frame pushed when the partition is handling an interrupt
168
169So the max stack size can be calculated as a function of the IRQ count of 'A':
170
171.. code-block::
172
173
174 max_stack_size = intr_ctx_size + (IRQ_CNT * (intr_ctx_size + hndl_ctx_size))
175
176--------------
177
178*Copyright (c) 2018-2019, Arm Limited. All rights reserved.*