Jeenu Viswambharan | e34bf58 | 2018-10-12 08:48:36 +0100 | [diff] [blame] | 1 | RAS support in Trusted Firmware-A |
| 2 | ================================= |
| 3 | |
| 4 | .. section-numbering:: |
| 5 | :suffix: . |
| 6 | |
| 7 | .. contents:: |
| 8 | :depth: 2 |
| 9 | |
| 10 | .. |EHF| replace:: Exception Handling Framework |
| 11 | .. |TF-A| replace:: Trusted Firmware-A |
| 12 | |
| 13 | This document describes |TF-A| support for Arm Reliability, Availability, and |
| 14 | Serviceability (RAS) extensions. RAS is a mandatory extension for Armv8.2 and |
| 15 | later CPUs, and also an optional extension to the base Armv8.0 architecture. |
| 16 | |
| 17 | In conjunction with the |EHF|, support for RAS extension enables firmware-first |
| 18 | paradigm for handling platform errors, in which exceptions resulting from |
| 19 | errors—viz. Synchronous External Abort (SEA), Asynchronous External Abort |
| 20 | (signalled as SErrors), Fault Handling and Error Recovery interrupts are routed |
| 21 | to and handled in EL3. The |EHF| document mentions various `error handling |
| 22 | use-cases`__. |
| 23 | |
| 24 | .. __: exception-handling.rst#delegation-use-cases |
| 25 | |
| 26 | For the description of Arm RAS extensions, Standard Error Records, and the |
| 27 | precise definition of RAS terminology, please refer to the Arm Architecture |
| 28 | Reference Manual. The rest of this document assumes familiarity with |
| 29 | architecture and terminology. |
| 30 | |
| 31 | Overview |
| 32 | -------- |
| 33 | |
| 34 | As mentioned above, the RAS support in |TF-A| enables routing to and handling of |
| 35 | exceptions resulting from platform errors in EL3. It allows the platform to |
| 36 | define an External Abort handler, and to register RAS nodes and interrupts. RAS |
| 37 | framework also provides `helpers`__ for accessing Standard Error Records as |
| 38 | introduced by the RAS extensions. |
| 39 | |
| 40 | .. __: `Standard Error Record helpers`_ |
| 41 | |
| 42 | The build option ``RAS_EXTENSION`` when set to ``1`` includes the RAS in run |
| 43 | time firmware; ``EL3_EXCEPTION_HANDLING`` and ``HANDLE_EA_EL3_FIRST`` must also |
| 44 | be set ``1``. |
| 45 | |
| 46 | .. _ras-figure: |
| 47 | |
| 48 | .. image:: draw.io/ras.svg |
| 49 | |
| 50 | See more on `Engaging the RAS framework`_. |
| 51 | |
| 52 | Platform APIs |
| 53 | ------------- |
| 54 | |
| 55 | The RAS framework allows the platform to define handlers for External Abort, |
| 56 | Uncontainable Errors, Double Fault, and errors rising from EL3 execution. Please |
| 57 | refer to the porting guide for the `RAS platform API descriptions`__. |
| 58 | |
| 59 | .. __: porting-guide.rst#external-abort-handling-and-ras-support |
| 60 | |
| 61 | Registering RAS error records |
| 62 | ----------------------------- |
| 63 | |
| 64 | RAS nodes are components in the system capable of signalling errors to PEs |
| 65 | through one one of the notification mechanisms—SEAs, SErrors, or interrupts. RAS |
| 66 | nodes contain one or more error records, which are registers through which the |
| 67 | nodes advertise various properties of the signalled error. Arm recommends that |
| 68 | error records are implemented in the Standard Error Record format. The RAS |
| 69 | architecture allows for error records to be accessible via. system or |
| 70 | memory-mapped registers. |
| 71 | |
| 72 | The platform should enumerate the error records providing for each of them: |
| 73 | |
| 74 | - A handler to probe error records for errors; |
| 75 | - When the probing identifies an error, a handler to handle it; |
| 76 | - For memory-mapped error record, its base address and size in KB; for a system |
| 77 | register-accessed record, the start index of the record and number of |
| 78 | continuous records from that index; |
| 79 | - Any node-specific auxiliary data. |
| 80 | |
| 81 | With this information supplied, when the run time firmware receives one of the |
| 82 | notification mechanisms, the RAS framework can iterate through and probe error |
| 83 | records for error, and invoke the appropriate handler to handle it. |
| 84 | |
| 85 | The RAS framework provides the macros to populate error record information. The |
| 86 | macros are versioned, and the latest version as of this writing is 1. These |
| 87 | macros create a structure of type ``struct err_record_info`` from its arguments, |
| 88 | which are later passed to probe and error handlers. |
| 89 | |
| 90 | For memory-mapped error records: |
| 91 | |
| 92 | .. code:: c |
| 93 | |
| 94 | ERR_RECORD_MEMMAP_V1(base_addr, size_num_k, probe, handler, aux) |
| 95 | |
| 96 | And, for system register ones: |
| 97 | |
| 98 | .. code:: c |
| 99 | |
| 100 | ERR_RECORD_SYSREG_V1(idx_start, num_idx, probe, handler, aux) |
| 101 | |
| 102 | The probe handler must have the following prototype: |
| 103 | |
| 104 | .. code:: c |
| 105 | |
| 106 | typedef int (*err_record_probe_t)(const struct err_record_info *info, |
| 107 | int *probe_data); |
| 108 | |
| 109 | The probe handler must return a non-zero value if an error was detected, or 0 |
| 110 | otherwise. The ``probe_data`` output parameter can be used to pass any useful |
| 111 | information resulting from probe to the error handler (see `below`__). For |
| 112 | example, it could return the index of the record. |
| 113 | |
| 114 | .. __: `Standard Error Record helpers`_ |
| 115 | |
| 116 | The error handler must have the following prototype: |
| 117 | |
| 118 | .. code:: c |
| 119 | |
| 120 | typedef int (*err_record_handler_t)(const struct err_record_info *info, |
| 121 | int probe_data, const struct err_handler_data *const data); |
| 122 | |
| 123 | The ``data`` constant parameter describes the various properties of the error, |
| 124 | viz. the reason for the error, exception syndrome, and also ``flags``, |
| 125 | ``cookie``, and ``handle`` parameters from the `top-level exception handler`__. |
| 126 | |
| 127 | .. __: interrupt-framework-design.rst#el3-interrupts |
| 128 | |
| 129 | The platform is expected populate an array using the macros above, and register |
| 130 | the it with the RAS framework using the macro ``REGISTER_ERR_RECORD_INFO()``, |
| 131 | passing it the name of the array describing the records. Note that the macro |
| 132 | must be used in the same file where the array is defined. |
| 133 | |
| 134 | Standard Error Record helpers |
| 135 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 136 | |
| 137 | The |TF-A| RAS framework provides probe handlers for Standard Error Records, for |
| 138 | both memory-mapped and System Register accesses: |
| 139 | |
| 140 | .. code:: c |
| 141 | |
| 142 | int ras_err_ser_probe_memmap(const struct err_record_info *info, |
| 143 | int *probe_data); |
| 144 | |
| 145 | int ras_err_ser_probe_sysreg(const struct err_record_info *info, |
| 146 | int *probe_data); |
| 147 | |
| 148 | When the platform enumerates error records, for those records in the Standard |
| 149 | Error Record format, these helpers maybe used instead of rolling out their own. |
| 150 | Both helpers above: |
| 151 | |
| 152 | - Return non-zero value when an error is detected in a Standard Error Record; |
| 153 | - Set ``probe_data`` to the index of the error record upon detecting an error. |
| 154 | |
| 155 | Registering RAS interrupts |
| 156 | -------------------------- |
| 157 | |
| 158 | RAS nodes can signal errors to the PE by raising Fault Handling and/or Error |
| 159 | Recovery interrupts. For the firmware-first handling paradigm for interrupts to |
| 160 | work, the platform must setup and register with |EHF|. See `Interaction with |
| 161 | Exception Handling Framework`_. |
| 162 | |
| 163 | For each RAS interrupt, the platform has to provide structure of type ``struct |
| 164 | ras_interrupt``: |
| 165 | |
| 166 | - Interrupt number; |
| 167 | - The associated error record information (pointer to the corresponding |
| 168 | ``struct err_record_info``); |
| 169 | - Optionally, a cookie. |
| 170 | |
| 171 | The platform is expected to define an array of ``struct ras_interrupt``, and |
| 172 | register it with the RAS framework using the macro |
| 173 | ``REGISTER_RAS_INTERRUPTS()``, passing it the name of the array. Note that the |
| 174 | macro must be used in the same file where the array is defined. |
| 175 | |
| 176 | The array of ``struct ras_interrupt`` must be sorted in the increasing order of |
| 177 | interrupt number. This allows for fast look of handlers in order to service RAS |
| 178 | interrupts. |
| 179 | |
| 180 | Double-fault handling |
| 181 | --------------------- |
| 182 | |
| 183 | A Double Fault condition arises when an error is signalled to the PE while |
| 184 | handling of a previously signalled error is still underway. When a Double Fault |
| 185 | condition arises, the Arm RAS extensions only require for handler to perform |
| 186 | orderly shutdown of the system, as recovery may be impossible. |
| 187 | |
| 188 | The RAS extensions part of Armv8.4 introduced new architectural features to deal |
| 189 | with Double Fault conditions, specifically, the introduction of ``NMEA`` and |
| 190 | ``EASE`` bits to ``SCR_EL3`` register. These were introduced to assist EL3 |
| 191 | software which runs part of its entry/exit routines with exceptions momentarily |
| 192 | masked—meaning, in such systems, External Aborts/SErrors are not immediately |
| 193 | handled when they occur, but only after the exceptions are unmasked again. |
| 194 | |
| 195 | |TF-A|, for legacy reasons, executes entire EL3 with all exceptions unmasked. |
| 196 | This means that all exceptions routed to EL3 are handled immediately. |TF-A| |
| 197 | thus is able to detect a Double Fault conditions in software, without needing |
| 198 | the intended advantages of Armv8.4 Double Fault architecture extensions. |
| 199 | |
| 200 | Double faults are fatal, and terminate at the platform double fault handler, and |
| 201 | doesn't return. |
| 202 | |
| 203 | Engaging the RAS framework |
| 204 | -------------------------- |
| 205 | |
Paul Beesley | 1fbc97b | 2019-01-11 18:26:51 +0000 | [diff] [blame] | 206 | Enabling RAS support is a platform choice constructed from three distinct, but |
| 207 | related, build options: |
Jeenu Viswambharan | e34bf58 | 2018-10-12 08:48:36 +0100 | [diff] [blame] | 208 | |
| 209 | - ``RAS_EXTENSION=1`` includes the RAS framework in the run time firmware; |
| 210 | |
| 211 | - ``EL3_EXCEPTION_HANDLING=1`` enables handling of exceptions at EL3. See |
| 212 | `Interaction with Exception Handling Framework`_; |
| 213 | |
| 214 | - ``HANDLE_EA_EL3_FIRST=1`` enables routing of External Aborts and SErrors to |
| 215 | EL3. |
| 216 | |
| 217 | The RAS support in |TF-A| introduces a default implementation of |
| 218 | ``plat_ea_handler``, the External Abort handler in EL3. When ``RAS_EXTENSION`` |
| 219 | is set to ``1``, it'll first call ``ras_ea_handler()`` function, which is the |
| 220 | top-level RAS exception handler. ``ras_ea_handler`` is responsible for iterating |
| 221 | to through platform-supplied error records, probe them, and when an error is |
| 222 | identified, look up and invoke the corresponding error handler. |
| 223 | |
| 224 | Note that, if the platform chooses to override the ``plat_ea_handler`` function |
| 225 | and intend to use the RAS framework, it must explicitly call |
| 226 | ``ras_ea_handler()`` from within. |
| 227 | |
| 228 | Similarly, for RAS interrupts, the framework defines |
| 229 | ``ras_interrupt_handler()``. The RAS framework arranges for it to be invoked |
| 230 | when a RAS interrupt taken at EL3. The function bisects the platform-supplied |
| 231 | sorted array of interrupts to look up the error record information associated |
| 232 | with the interrupt number. That error handler for that record is then invoked to |
| 233 | handle the error. |
| 234 | |
| 235 | Interaction with Exception Handling Framework |
| 236 | --------------------------------------------- |
| 237 | |
| 238 | As mentioned in earlier sections, RAS framework interacts with the |EHF| to |
| 239 | arbitrate handling of RAS exceptions with others that are routed to EL3. This |
| 240 | means that the platform must partition a `priority level`__ for handling RAS |
| 241 | exceptions. The platform must then define the macro ``PLAT_RAS_PRI`` to the |
| 242 | priority level used for RAS exceptions. Platforms would typically want to |
| 243 | allocate the highest secure priority for RAS handling. |
| 244 | |
| 245 | .. __: exception-handling.rst#partitioning-priority-levels |
| 246 | |
Paul Beesley | 1fbc97b | 2019-01-11 18:26:51 +0000 | [diff] [blame] | 247 | Handling of both `interrupt`__ and `non-interrupt`__ exceptions follow the |
Jeenu Viswambharan | e34bf58 | 2018-10-12 08:48:36 +0100 | [diff] [blame] | 248 | sequences outlined in the |EHF| documentation. I.e., for interrupts, the |
| 249 | priority management is implicit; but for non-interrupt exceptions, they're |
| 250 | explicit using `EHF APIs`__. |
| 251 | |
| 252 | .. __: exception-handling.rst#interrupt-flow |
| 253 | .. __: exception-handling.rst#non-interrupt-flow |
| 254 | .. __: exception-handling.rst#activating-and-deactivating-priorities |
| 255 | |
| 256 | ---- |
| 257 | |
| 258 | *Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.* |