Paul Beesley | fc9ee36 | 2019-03-07 15:47:15 +0000 | [diff] [blame] | 1 | EL3 Runtime Service Writer's Guide |
Dan Handley | 610e7e1 | 2018-03-01 18:44:00 +0000 | [diff] [blame] | 2 | ===================================================== |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 3 | |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 4 | Introduction |
| 5 | ------------ |
| 6 | |
| 7 | This document describes how to add a runtime service to the EL3 Runtime |
Dan Handley | 610e7e1 | 2018-03-01 18:44:00 +0000 | [diff] [blame] | 8 | Firmware component of Trusted Firmware-A (TF-A), BL31. |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 9 | |
| 10 | Software executing in the normal world and in the trusted world at exception |
| 11 | levels lower than EL3 will request runtime services using the Secure Monitor |
| 12 | Call (SMC) instruction. These requests will follow the convention described in |
| 13 | the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function |
| 14 | identifiers to each SMC request and describes how arguments are passed and |
| 15 | results are returned. |
| 16 | |
| 17 | SMC Functions are grouped together based on the implementor of the service, for |
| 18 | example a subset of the Function IDs are designated as "OEM Calls" (see `SMCCC`_ |
| 19 | for full details). The EL3 runtime services framework in BL31 enables the |
| 20 | independent implementation of services for each group, which are then compiled |
| 21 | into the BL31 image. This simplifies the integration of common software from |
Dan Handley | 610e7e1 | 2018-03-01 18:44:00 +0000 | [diff] [blame] | 22 | Arm to support `PSCI`_, Secure Monitor for a Trusted OS and SoC specific |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 23 | software. The common runtime services framework ensures that SMC Functions are |
Paul Beesley | f864067 | 2019-04-12 14:19:42 +0100 | [diff] [blame] | 24 | dispatched to their respective service implementation - the |
| 25 | :ref:`Firmware Design` document provides details of how this is achieved. |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 26 | |
| 27 | The interface and operation of the runtime services depends heavily on the |
| 28 | concepts and definitions described in the `SMCCC`_, in particular SMC Function |
| 29 | IDs, Owning Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and |
| 30 | SMC64 calling conventions. Please refer to that document for a full explanation |
| 31 | of these terms. |
| 32 | |
| 33 | Owning Entities, Call Types and Function IDs |
| 34 | -------------------------------------------- |
| 35 | |
| 36 | The SMC Function Identifier includes a OEN field. These values and their |
| 37 | meaning are described in `SMCCC`_ and summarized in table 1 below. Some entities |
| 38 | are allocated a range of of OENs. The OEN must be interpreted in conjunction |
| 39 | with the SMC call type, which is either *Fast* or *Yielding*. Fast calls are |
| 40 | uninterruptible whereas Yielding calls can be pre-empted. The majority of |
| 41 | Owning Entities only have allocated ranges for Fast calls: Yielding calls are |
| 42 | reserved exclusively for Trusted OS providers or for interoperability with |
| 43 | legacy 32-bit software that predates the `SMCCC`_. |
| 44 | |
| 45 | :: |
| 46 | |
| 47 | Type OEN Service |
Dan Handley | 610e7e1 | 2018-03-01 18:44:00 +0000 | [diff] [blame] | 48 | Fast 0 Arm Architecture calls |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 49 | Fast 1 CPU Service calls |
| 50 | Fast 2 SiP Service calls |
| 51 | Fast 3 OEM Service calls |
| 52 | Fast 4 Standard Service calls |
| 53 | Fast 5-47 Reserved for future use |
| 54 | Fast 48-49 Trusted Application calls |
| 55 | Fast 50-63 Trusted OS calls |
| 56 | |
Dan Handley | 610e7e1 | 2018-03-01 18:44:00 +0000 | [diff] [blame] | 57 | Yielding 0- 1 Reserved for existing Armv7-A calls |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 58 | Yielding 2-63 Trusted OS Standard Calls |
| 59 | |
| 60 | *Table 1: Service types and their corresponding Owning Entity Numbers* |
| 61 | |
| 62 | Each individual entity can allocate the valid identifiers within the entity |
| 63 | range as they need - it is not necessary to coordinate with other entities of |
| 64 | the same type. For example, two SoC providers can use the same Function ID |
| 65 | within the SiP Service calls OEN range to mean different things - as these |
| 66 | calls should be specific to the SoC. The Standard Runtime Calls OEN is used for |
Dan Handley | 610e7e1 | 2018-03-01 18:44:00 +0000 | [diff] [blame] | 67 | services defined by Arm standards, such as `PSCI`_. |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 68 | |
| 69 | The SMC Function ID also indicates whether the call has followed the SMC32 |
| 70 | calling convention, where all parameters are 32-bit, or the SMC64 calling |
| 71 | convention, where the parameters are 64-bit. The framework identifies and |
| 72 | rejects invalid calls that use the SMC64 calling convention but that originate |
| 73 | from an AArch32 caller. |
| 74 | |
| 75 | The EL3 runtime services framework uses the call type and OEN to identify a |
| 76 | specific handler for each SMC call, but it is expected that an individual |
| 77 | handler will be responsible for all SMC Functions within a given service type. |
| 78 | |
| 79 | Getting started |
| 80 | --------------- |
| 81 | |
Paul Beesley | f864067 | 2019-04-12 14:19:42 +0100 | [diff] [blame] | 82 | TF-A has a ``services`` directory in the source tree under which |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 83 | each owning entity can place the implementation of its runtime service. The |
Paul Beesley | f864067 | 2019-04-12 14:19:42 +0100 | [diff] [blame] | 84 | `PSCI`_ implementation is located here in the ``lib/psci`` directory. |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 85 | |
Paul Beesley | f864067 | 2019-04-12 14:19:42 +0100 | [diff] [blame] | 86 | Runtime service sources will need to include the ``runtime_svc.h`` header file. |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 87 | |
| 88 | Registering a runtime service |
| 89 | ----------------------------- |
| 90 | |
| 91 | A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying |
| 92 | the name of the service, the range of OENs covered, the type of service and |
| 93 | initialization and call handler functions. |
| 94 | |
Paul Beesley | 493e349 | 2019-03-13 15:11:04 +0000 | [diff] [blame] | 95 | .. code:: c |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 96 | |
| 97 | #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) |
| 98 | |
| 99 | - ``_name`` is used to identify the data structure declared by this macro, and |
| 100 | is also used for diagnostic purposes |
| 101 | |
| 102 | - ``_start`` and ``_end`` values must be based on the ``OEN_*`` values defined in |
Paul Beesley | f864067 | 2019-04-12 14:19:42 +0100 | [diff] [blame] | 103 | ``smccc.h`` |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 104 | |
| 105 | - ``_type`` must be one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` |
| 106 | |
| 107 | - ``_setup`` is the initialization function with the ``rt_svc_init`` signature: |
| 108 | |
| 109 | .. code:: c |
| 110 | |
| 111 | typedef int32_t (*rt_svc_init)(void); |
| 112 | |
| 113 | - ``_smch`` is the SMC handler function with the ``rt_svc_handle`` signature: |
| 114 | |
| 115 | .. code:: c |
| 116 | |
| 117 | typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, |
| 118 | u_register_t x1, u_register_t x2, |
| 119 | u_register_t x3, u_register_t x4, |
| 120 | void *cookie, |
| 121 | void *handle, |
| 122 | u_register_t flags); |
| 123 | |
| 124 | Details of the requirements and behavior of the two callbacks is provided in |
| 125 | the following sections. |
| 126 | |
| 127 | During initialization the services framework validates each declared service |
| 128 | to ensure that the following conditions are met: |
| 129 | |
| 130 | #. The ``_start`` OEN is not greater than the ``_end`` OEN |
| 131 | #. The ``_end`` OEN does not exceed the maximum OEN value (63) |
| 132 | #. The ``_type`` is one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` |
| 133 | #. ``_setup`` and ``_smch`` routines have been specified |
| 134 | |
Paul Beesley | f864067 | 2019-04-12 14:19:42 +0100 | [diff] [blame] | 135 | ``std_svc_setup.c`` provides an example of registering a runtime service: |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 136 | |
| 137 | .. code:: c |
| 138 | |
| 139 | /* Register Standard Service Calls as runtime service */ |
| 140 | DECLARE_RT_SVC( |
| 141 | std_svc, |
| 142 | OEN_STD_START, |
| 143 | OEN_STD_END, |
| 144 | SMC_TYPE_FAST, |
| 145 | std_svc_setup, |
| 146 | std_svc_smc_handler |
| 147 | ); |
| 148 | |
| 149 | Initializing a runtime service |
| 150 | ------------------------------ |
| 151 | |
| 152 | Runtime services are initialized once, during cold boot, by the primary CPU |
| 153 | after platform and architectural initialization is complete. The framework |
| 154 | performs basic validation of the declared service before calling |
| 155 | the service initialization function (``_setup`` in the declaration). This |
| 156 | function must carry out any essential EL3 initialization prior to receiving a |
| 157 | SMC Function call via the handler function. |
| 158 | |
| 159 | On success, the initialization function must return ``0``. Any other return value |
| 160 | will cause the framework to issue a diagnostic: |
| 161 | |
| 162 | :: |
| 163 | |
| 164 | Error initializing runtime service <name of the service> |
| 165 | |
| 166 | and then ignore the service - the system will continue to boot but SMC calls |
| 167 | will not be passed to the service handler and instead return the *Unknown SMC |
| 168 | Function ID* result ``0xFFFFFFFF``. |
| 169 | |
| 170 | If the system must not be allowed to proceed without the service, the |
| 171 | initialization function must itself cause the firmware boot to be halted. |
| 172 | |
| 173 | If the service uses per-CPU data this must either be initialized for all CPUs |
| 174 | during this call, or be done lazily when a CPU first issues an SMC call to that |
| 175 | service. |
| 176 | |
| 177 | Handling runtime service requests |
| 178 | --------------------------------- |
| 179 | |
| 180 | SMC calls for a service are forwarded by the framework to the service's SMC |
| 181 | handler function (``_smch`` in the service declaration). This function must have |
| 182 | the following signature: |
| 183 | |
| 184 | .. code:: c |
| 185 | |
| 186 | typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, |
| 187 | u_register_t x1, u_register_t x2, |
| 188 | u_register_t x3, u_register_t x4, |
| 189 | void *cookie, |
| 190 | void *handle, |
| 191 | u_register_t flags); |
| 192 | |
| 193 | The handler is responsible for: |
| 194 | |
| 195 | #. Determining that ``smc_fid`` is a valid and supported SMC Function ID, |
| 196 | otherwise completing the request with the *Unknown SMC Function ID*: |
| 197 | |
| 198 | .. code:: c |
| 199 | |
| 200 | SMC_RET1(handle, SMC_UNK); |
| 201 | |
| 202 | #. Determining if the requested function is valid for the calling security |
| 203 | state. SMC Calls can be made from both the normal and trusted worlds and |
| 204 | the framework will forward all calls to the service handler. |
| 205 | |
| 206 | The ``flags`` parameter to this function indicates the caller security state |
| 207 | in bit[0], where a value of ``1`` indicates a non-secure caller. The |
| 208 | ``is_caller_secure(flags)`` and ``is_caller_non_secure(flags)`` can be used to |
| 209 | test this condition. |
| 210 | |
| 211 | If invalid, the request should be completed with: |
| 212 | |
| 213 | .. code:: c |
| 214 | |
| 215 | SMC_RET1(handle, SMC_UNK); |
| 216 | |
| 217 | #. Truncating parameters for calls made using the SMC32 calling convention. |
| 218 | Such calls can be determined by checking the CC field in bit[30] of the |
| 219 | ``smc_fid`` parameter, for example by using: |
| 220 | |
| 221 | :: |
| 222 | |
| 223 | if (GET_SMC_CC(smc_fid) == SMC_32) ... |
| 224 | |
| 225 | For such calls, the upper bits of the parameters x1-x4 and the saved |
| 226 | parameters X5-X7 are UNDEFINED and must be explicitly ignored by the |
| 227 | handler. This can be done by truncating the values to a suitable 32-bit |
| 228 | integer type before use, for example by ensuring that functions defined |
| 229 | to handle individual SMC Functions use appropriate 32-bit parameters. |
| 230 | |
| 231 | #. Providing the service requested by the SMC Function, utilizing the |
| 232 | immediate parameters x1-x4 and/or the additional saved parameters X5-X7. |
| 233 | The latter can be retrieved using the ``SMC_GET_GP(handle, ref)`` function, |
| 234 | supplying the appropriate ``CTX_GPREG_Xn`` reference, e.g. |
| 235 | |
| 236 | .. code:: c |
| 237 | |
| 238 | uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6); |
| 239 | |
| 240 | #. Implementing the standard SMC32 Functions that provide information about |
| 241 | the implementation of the service. These are the Call Count, Implementor |
| 242 | UID and Revision Details for each service documented in section 6 of the |
| 243 | `SMCCC`_. |
| 244 | |
Dan Handley | 610e7e1 | 2018-03-01 18:44:00 +0000 | [diff] [blame] | 245 | TF-A expects owning entities to follow this recommendation. |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 246 | |
Madhukar Pappireddy | 20be077 | 2019-11-09 23:28:08 -0600 | [diff] [blame] | 247 | #. Returning the result to the caller. Based on `SMCCC`_ spec, results are |
| 248 | returned in W0-W7(X0-X7) registers for SMC32(SMC64) calls from AArch64 |
| 249 | state. Results are returned in R0-R7 registers for SMC32 calls from AArch32 |
| 250 | state. The framework provides a family of macros to set the multi-register |
| 251 | return value and complete the handler: |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 252 | |
| 253 | .. code:: c |
| 254 | |
Madhukar Pappireddy | 20be077 | 2019-11-09 23:28:08 -0600 | [diff] [blame] | 255 | AArch64 state: |
| 256 | |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 257 | SMC_RET1(handle, x0); |
| 258 | SMC_RET2(handle, x0, x1); |
| 259 | SMC_RET3(handle, x0, x1, x2); |
| 260 | SMC_RET4(handle, x0, x1, x2, x3); |
Madhukar Pappireddy | 20be077 | 2019-11-09 23:28:08 -0600 | [diff] [blame] | 261 | SMC_RET5(handle, x0, x1, x2, x3, x4); |
| 262 | SMC_RET6(handle, x0, x1, x2, x3, x4, x5); |
| 263 | SMC_RET7(handle, x0, x1, x2, x3, x4, x5, x6); |
| 264 | SMC_RET8(handle, x0, x1, x2, x3, x4, x5, x6, x7); |
| 265 | |
| 266 | AArch32 state: |
| 267 | |
| 268 | SMC_RET1(handle, r0); |
| 269 | SMC_RET2(handle, r0, r1); |
| 270 | SMC_RET3(handle, r0, r1, r2); |
| 271 | SMC_RET4(handle, r0, r1, r2, r3); |
| 272 | SMC_RET5(handle, r0, r1, r2, r3, r4); |
| 273 | SMC_RET6(handle, r0, r1, r2, r3, r4, r5); |
| 274 | SMC_RET7(handle, r0, r1, r2, r3, r4, r5, r6); |
| 275 | SMC_RET8(handle, r0, r1, r2, r3, r4, r5, r6, r7); |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 276 | |
| 277 | The ``cookie`` parameter to the handler is reserved for future use and can be |
| 278 | ignored. The ``handle`` is returned by the SMC handler - completion of the |
| 279 | handler function must always be via one of the ``SMC_RETn()`` macros. |
| 280 | |
Paul Beesley | ba3ed40 | 2019-03-13 16:20:44 +0000 | [diff] [blame] | 281 | .. note:: |
| 282 | The PSCI and Test Secure-EL1 Payload Dispatcher services do not follow |
| 283 | all of the above requirements yet. |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 284 | |
| 285 | Services that contain multiple sub-services |
| 286 | ------------------------------------------- |
| 287 | |
| 288 | It is possible that a single owning entity implements multiple sub-services. For |
| 289 | example, the Standard calls service handles ``0x84000000``-``0x8400FFFF`` and |
| 290 | ``0xC4000000``-``0xC400FFFF`` functions. Within that range, the `PSCI`_ service |
| 291 | handles the ``0x84000000``-``0x8400001F`` and ``0xC4000000``-``0xC400001F`` functions. |
| 292 | In that respect, `PSCI`_ is a 'sub-service' of the Standard calls service. In |
| 293 | future, there could be additional such sub-services in the Standard calls |
| 294 | service which perform independent functions. |
| 295 | |
| 296 | In this situation it may be valuable to introduce a second level framework to |
| 297 | enable independent implementation of sub-services. Such a framework might look |
| 298 | very similar to the current runtime services framework, but using a different |
Dan Handley | 610e7e1 | 2018-03-01 18:44:00 +0000 | [diff] [blame] | 299 | part of the SMC Function ID to identify the sub-service. TF-A does not provide |
| 300 | such a framework at present. |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 301 | |
| 302 | Secure-EL1 Payload Dispatcher service (SPD) |
| 303 | ------------------------------------------- |
| 304 | |
| 305 | Services that handle SMC Functions targeting a Trusted OS, Trusted Application, |
| 306 | or other Secure-EL1 Payload are special. These services need to manage the |
| 307 | Secure-EL1 context, provide the *Secure Monitor* functionality of switching |
| 308 | between the normal and secure worlds, deliver SMC Calls through to Secure-EL1 |
| 309 | and generally manage the Secure-EL1 Payload through CPU power-state transitions. |
| 310 | |
| 311 | TODO: Provide details of the additional work required to implement a SPD and |
| 312 | the BL31 support for these services. Or a reference to the document that will |
| 313 | provide this information.... |
| 314 | |
| 315 | -------------- |
| 316 | |
laurenw-arm | 03e7e61 | 2020-04-16 10:02:17 -0500 | [diff] [blame] | 317 | *Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.* |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 318 | |
laurenw-arm | 03e7e61 | 2020-04-16 10:02:17 -0500 | [diff] [blame] | 319 | .. _SMCCC: https://developer.arm.com/docs/den0028/latest |
Douglas Raillard | d7c21b7 | 2017-06-28 15:23:03 +0100 | [diff] [blame] | 320 | .. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf |