blob: 77993a367b83f2a5867282710e653017c77aff3f [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 {
29 "line_num": "5",
30 "signal": "DUAL_TIMER"
31 },
32 {
33 "line_name": "TFM_IRQ_LINE_TIMER_1",
34 "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
49- ``line_num``: The number of the IRQ.
50- ``line_name``: The name of the IRQ line. With the name of the IRQ line there
51 must be defined a macro in ``tfm_peripherals_def.h`` which is substituted to
52 the IRQ line num.
53- ``signal`` The name of the signal for this IRQ
54- ``tfm_irq_priority``: The priority of the IRQ. This number must be in the
55 range [0-255] inclusive. Please note that some of the less significant bits of
56 this value might be dropped based on the number of priority bits implemented
57 in the platform.
58
59.. important::
60
61 The name of the privileged interrupt handler is derived from the node
62 specifying the IRQ line number.
63
64 - In case ``line_num`` is provided, the name of the handler becomes
65 ``void irq_<line_num>_Handler(void)``.
66 - In case ``line_name`` is provided, the name of the handler becomes
67 ``void <line_name>_Handler(void)``.
68
69 This is important, because the derived name have to be present in the vector
70 table as the handler of the IRQ.
71
72.. Note::
73
74 ``signal`` is mandatory. Specifying the IRQ line is also mandatory, so exactly
75 one of ``line_num`` and ``line_name`` must be defined.
76
77 ``tfm_irq_priority`` is optional. If ``tfm_irq_priority`` is not set for an
78 IRQ, the default is value is ``TFM_DEFAULT_SECURE_IRQ_PRIOTITY``.
79
80If an IRQ handler is registered, TF-M will:
81
82- Set the IRQ with number ``line_num`` or ``line_name`` to target secure state
83- Set the priority of IRQ with number ``line_num`` or ``line_name`` to
84 ``tfm_irq_priority`` or to the default.
85
86TF-M configures the interrupt lines to be disabled by default. Interrupts for a
87service can be enabled by the secure service by calling
88``void tfm_enable_irq(psa_signal_t irq_signal)``. The function can be called in
89the service init function.
90
91*************
92Library model
93*************
94
95In Library model a function with the name derived from the value of the
96``line_num`` or ``line_name`` property is generated. This function will be put
97in the vector table by the linker (as the handlers in the startup assembly are
98defined as weak symbols). The code generated for this function will forward the
99call to the function with the name of the value of the ``signal`` property
100post-fixed with ``_isr``.
101
102.. hint::
103
104 for a signal ``"signal": "DUAL_TIMER"`` the name of the handler function is
105 ``DUAL_TIMER_isr``
106
107The signature of the IRQ handler in the partition must be the following:
108
109.. code-block:: c
110
111 void partition_irq_handler(void);
112
113The detailed description on how secure interrupt handling works in the Library
114model see
115`Secure Partition Interrupt Handling design document <https://developer.trustedfirmware.org/w/tf_m/design/secure_partition_interrupt_handling/>`_.
116
117*********
118IPC model
119*********
120
121The detailed description on how secure interrupt handling works in the IPC
122model, see the
123`PSA Firmware Framework and RoT Services specification <https://pages.arm.com/psa-resources-ff.html>`_.
124
125######################
126Implementation details
127######################
128
129*************
130Library model
131*************
132
133As a result of the function call like behaviour of secure services in library
134model, some information that is critical for the SPM to keep track of partition
135states, is stored on the stack of the active partitions. When an interrupt
136happens, and a handler partition is set to running state, it has access to its
137whole stack, and could corrupt the data stacked by the SPM. To prevent this, a
138separate Context stack is introduced for each secure partition, that is used by
139the SPM to save this information before starting to execute secure partition
140code.
141
142A stack frame to this context stack is pushed when the execution in the
143partition is interrupted, and when a handler in the partition interrupts another
144service. So the maximal stack usage can happen in the following situation:
145
146Consider secure partition 'A'. 'A' is running, and then it is interrupted by
147an other partition. Then the lowest priority interrupt of 'A' is triggered.
148Then before the handler returns, the partition is interrupted by another
149partition's handler. Then before the running handler returns, the second
150lowest interrupt of 'A' is triggered. This can go until the highest priority
151interrupt of 'A' is triggered, and then this last handler is interrupted. At
152this point the context stack looks like this:
153
154.. code-block::
155
156 +------------+
157 | [intr_ctx] |
158 | [hndl_ctx] |
159 | . |
160 | . |
161 | . |
162 | [intr_ctx] |
163 | [hndl_ctx] |
164 | [intr_ctx] |
165 +------------+
166
167 Legend:
168 [intr_ctx]: Frame pushed when the partition is interrupted
169 [hndl_ctx]: Frame pushed when the partition is handling an interrupt
170
171So the max stack size can be calculated as a function of the IRQ count of 'A':
172
173.. code-block::
174
175
176 max_stack_size = intr_ctx_size + (IRQ_CNT * (intr_ctx_size + hndl_ctx_size))
177
178--------------
179
180*Copyright (c) 2018-2019, Arm Limited. All rights reserved.*