diff --git a/acknowledgements.rst b/acknowledgements.rst deleted file mode 100644 index 095b5ad..0000000 --- a/acknowledgements.rst +++ /dev/null @@ -1,28 +0,0 @@ -**Note: This file is only relevant for legacy contributions, to acknowledge the -specific contributors referred to in "Arm Limited and Contributors" copyright -notices. As contributors are now encouraged to put their name or company name -directly into the copyright notices, this file is not relevant for new -contributions.** - -Contributor Acknowledgements -============================ - -Companies ---------- - -Linaro Limited - -NVIDIA Corporation - -Socionext Inc. - -Xilinx, Inc. - -NXP Semiconductors - -Marvell International Ltd. - -STMicroelectronics - -Individuals ------------ diff --git a/contributing.rst b/contributing.rst deleted file mode 100644 index bd950e5..0000000 --- a/contributing.rst +++ /dev/null @@ -1,149 +0,0 @@ -Contributing to Trusted Firmware-A -================================== - -Getting Started ---------------- - -- Make sure you have a Github account and you are logged on - `developer.trustedfirmware.org`_. -- Create an `issue`_ for your work if one does not already exist. This gives - everyone visibility of whether others are working on something similar. - - - If you intend to include Third Party IP in your contribution, please - raise a separate `issue`_ for this and ensure that the changes that - include Third Party IP are made on a separate topic branch. - -- Clone `arm-trusted-firmware-a`_ on your own machine as suggested on the - `User Guide`_. -- Create a local topic branch based on the `arm-trusted-firmware-a`_ ``master`` - branch. - -Making Changes --------------- - -- Make commits of logical units. See these general `Git guidelines`_ for - contributing to a project. -- Follow the `Coding Guidelines`_. - - - Use the checkpatch.pl script provided with the Linux source tree. A - Makefile target is provided for convenience (see the "Checking source code - style" section in the `User Guide`_). - -- Keep the commits on topic. If you need to fix another bug or make another - enhancement, please create a separate `issue`_ and address it on a separate - topic branch. -- Avoid long commit series. If you do have a long series, consider whether - some commits should be squashed together or addressed in a separate topic. -- Make sure your commit messages are in the proper format. If a commit fixes - an `issue`_, include a reference. -- Where appropriate, please update the documentation. - - - Consider whether the `User Guide`_, `Porting Guide`_, `Firmware Design`_ - or other in-source documentation needs updating. - - Ensure that each changed file has the correct copyright and license - information. Files that entirely consist of contributions to this - project should have a copyright notice and BSD-3-Clause SPDX license - identifier of the form as shown in `license.rst`_. Files that contain - changes to imported Third Party IP files should retain their original - copyright and license notices. For significant contributions you may - add your own copyright notice in following format: - - :: - - Portions copyright (c) [XXXX-]YYYY, . All rights reserved. - - where XXXX is the year of first contribution (if different to YYYY) and - YYYY is the year of most recent contribution. is your name or - your company name. - - If you are submitting new files that you intend to be the technical - sub-maintainer for (for example, a new platform port), then also update - the `Maintainers`_ file. - - For topics with multiple commits, you should make all documentation - changes (and nothing else) in the last commit of the series. Otherwise, - include the documentation changes within the single commit. - -- Please test your changes. As a minimum, ensure that Linux boots on the - Foundation FVP. See `Running the software on FVP`_ for more information. For - more extensive testing, consider running the `TF-A Tests`_ against your - patches. - -Submitting Changes ------------------- - -- Ensure that each commit in the series has at least one ``Signed-off-by:`` - line, using your real name and email address. The names in the - ``Signed-off-by:`` and ``Author:`` lines must match. If anyone else - contributes to the commit, they must also add their own ``Signed-off-by:`` - line. By adding this line the contributor certifies the contribution is made - under the terms of the `Developer Certificate of Origin (DCO)`_. - - More details may be found in the `Gerrit Signed-off-by Lines guidelines`_. - -- Ensure that each commit also has a unique ``Change-Id:`` line. If you have - cloned the repository with the "`Clone with commit-msg hook`" clone method - (as advised on the `User Guide`_), this should already be the case. - - More details may be found in the `Gerrit Change-Ids documentation`_. - -- Submit your changes for review at https://review.trustedfirmware.org - targeting the ``integration`` branch. - - - The changes will then undergo further review and testing by the - `Maintainers`_. Any review comments will be made directly on your patch. - This may require you to do some rework. - - Refer to the `Gerrit Uploading Changes documentation`_ for more details. - -- When the changes are accepted, the `Maintainers`_ will integrate them. - - - Typically, the `Maintainers`_ will merge the changes into the - ``integration`` branch. - - If the changes are not based on a sufficiently-recent commit, or if they - cannot be automatically rebased, then the `Maintainers`_ may rebase it on - the ``master`` branch or ask you to do so. - - After final integration testing, the changes will make their way into the - ``master`` branch. If a problem is found during integration, the merge - commit will be removed from the ``integration`` branch and the - `Maintainers`_ will ask you to create a new patch set to resolve the - problem. - -Binary Components ------------------ - -- Platforms may depend on binary components submitted to the `Trusted Firmware - binary repository`_ if they require code that the contributor is unable or - unwilling to open-source. This should be used as a rare exception. -- All binary components must follow the contribution guidelines (in particular - licensing rules) outlined in the `readme.rst `_ file of - the binary repository. -- Binary components must be restricted to only the specific functionality that - cannot be open-sourced and must be linked into a larger open-source platform - port. The majority of the platform port must still be implemented in open - source. Platform ports that are merely a thin wrapper around a binary - component that contains all the actual code will not be accepted. -- Only platform port code (i.e. in the ``plat/`` directory) may rely on - binary components. Generic code must always be fully open-source. - --------------- - -*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* - -.. _developer.trustedfirmware.org: https://developer.trustedfirmware.org -.. _issue: https://developer.trustedfirmware.org/project/board/1/ -.. _arm-trusted-firmware-a: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git -.. _Git guidelines: http://git-scm.com/book/ch5-2.html -.. _Coding Guidelines: ./docs/coding-guidelines.rst -.. _User Guide: ./docs/user-guide.rst -.. _Porting Guide: ./docs/porting-guide.rst -.. _Firmware Design: ./docs/firmware-design.rst -.. _license.rst: ./license.rst -.. _Acknowledgements: ./acknowledgements.rst -.. _Maintainers: ./maintainers.rst -.. _Running the software on FVP: ./docs/user-guide.rst#user-content-running-the-software-on-fvp -.. _Developer Certificate of Origin (DCO): ./dco.txt -.. _Gerrit Uploading Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html -.. _Gerrit Signed-off-by Lines guidelines: https://review.trustedfirmware.org/Documentation/user-signedoffby.html -.. _Gerrit Change-Ids documentation: https://review.trustedfirmware.org/Documentation/user-changeid.html -.. _TF-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/ -.. _Trusted Firmware binary repository: https://review.trustedfirmware.org/admin/repos/tf-binaries -.. _tf-binaries-readme: https://git.trustedfirmware.org/tf-binaries.git/tree/readme.rst diff --git a/docs/acknowledgements.rst b/docs/acknowledgements.rst new file mode 100644 index 0000000..095b5ad --- /dev/null +++ b/docs/acknowledgements.rst @@ -0,0 +1,28 @@ +**Note: This file is only relevant for legacy contributions, to acknowledge the +specific contributors referred to in "Arm Limited and Contributors" copyright +notices. As contributors are now encouraged to put their name or company name +directly into the copyright notices, this file is not relevant for new +contributions.** + +Contributor Acknowledgements +============================ + +Companies +--------- + +Linaro Limited + +NVIDIA Corporation + +Socionext Inc. + +Xilinx, Inc. + +NXP Semiconductors + +Marvell International Ltd. + +STMicroelectronics + +Individuals +----------- diff --git a/docs/arm-sip-service.rst b/docs/arm-sip-service.rst deleted file mode 100644 index 6cdac83..0000000 --- a/docs/arm-sip-service.rst +++ /dev/null @@ -1,96 +0,0 @@ -Arm SiP Service -=============== - -This document enumerates and describes the Arm SiP (Silicon Provider) services. - -SiP services are non-standard, platform-specific services offered by the silicon -implementer or platform provider. They are accessed via ``SMC`` ("SMC calls") -instruction executed from Exception Levels below EL3. SMC calls for SiP -services: - -- Follow `SMC Calling Convention`_; -- Use SMC function IDs that fall in the SiP range, which are ``0xc2000000`` - - ``0xc200ffff`` for 64-bit calls, and ``0x82000000`` - ``0x8200ffff`` for 32-bit - calls. - -The Arm SiP implementation offers the following services: - -- Performance Measurement Framework (PMF) -- Execution State Switching service - -Source definitions for Arm SiP service are located in the ``arm_sip_svc.h`` header -file. - -Performance Measurement Framework (PMF) ---------------------------------------- - -The `Performance Measurement Framework`_ -allows callers to retrieve timestamps captured at various paths in TF-A -execution. It's described in detail in `Firmware Design document`_. - -Execution State Switching service ---------------------------------- - -Execution State Switching service provides a mechanism for a non-secure lower -Exception Level (either EL2, or NS EL1 if EL2 isn't implemented) to request to -switch its execution state (a.k.a. Register Width), either from AArch64 to -AArch32, or from AArch32 to AArch64, for the calling CPU. This service is only -available when Trusted Firmware-A (TF-A) is built for AArch64 (i.e. when build -option ``ARCH`` is set to ``aarch64``). - -``ARM_SIP_SVC_EXE_STATE_SWITCH`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t Function ID - uint32_t PC hi - uint32_t PC lo - uint32_t Cookie hi - uint32_t Cookie lo - - Return: - uint32_t - -The function ID parameter must be ``0x82000020``. It uniquely identifies the -Execution State Switching service being requested. - -The parameters *PC hi* and *PC lo* defines upper and lower words, respectively, -of the entry point (physical address) at which execution should start, after -Execution State has been switched. When calling from AArch64, *PC hi* must be 0. - -When execution starts at the supplied entry point after Execution State has been -switched, the parameters *Cookie hi* and *Cookie lo* are passed in CPU registers -0 and 1, respectively. When calling from AArch64, *Cookie hi* must be 0. - -This call can only be made on the primary CPU, before any secondaries were -brought up with ``CPU_ON`` PSCI call. Otherwise, the call will always fail. - -The effect of switching execution state is as if the Exception Level were -entered for the first time, following power on. This means CPU registers that -have a defined reset value by the Architecture will assume that value. Other -registers should not be expected to hold their values before the call was made. -CPU endianness, however, is preserved from the previous execution state. Note -that this switches the execution state of the calling CPU only. This is not a -substitute for PSCI ``SYSTEM_RESET``. - -The service may return the following error codes: - -- ``STATE_SW_E_PARAM``: If any of the parameters were deemed invalid for - a specific request. -- ``STATE_SW_E_DENIED``: If the call is not successful, or when TF-A is - built for AArch32. - -If the call is successful, the caller wouldn't observe the SMC returning. -Instead, execution starts at the supplied entry point, with the CPU registers 0 -and 1 populated with the supplied *Cookie hi* and *Cookie lo* values, -respectively. - --------------- - -*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* - -.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html -.. _Performance Measurement Framework: ./firmware-design.rst#user-content-performance-measurement-framework -.. _Firmware Design document: ./firmware-design.rst diff --git a/docs/auth-framework.rst b/docs/auth-framework.rst deleted file mode 100644 index 0142fbd..0000000 --- a/docs/auth-framework.rst +++ /dev/null @@ -1,972 +0,0 @@ -Abstracting a Chain of Trust -============================ - - -.. section-numbering:: - :suffix: . - -.. contents:: - -The aim of this document is to describe the authentication framework -implemented in Trusted Firmware-A (TF-A). This framework fulfills the -following requirements: - -#. It should be possible for a platform port to specify the Chain of Trust in - terms of certificate hierarchy and the mechanisms used to verify a - particular image/certificate. - -#. The framework should distinguish between: - - - The mechanism used to encode and transport information, e.g. DER encoded - X.509v3 certificates to ferry Subject Public Keys, hashes and non-volatile - counters. - - - The mechanism used to verify the transported information i.e. the - cryptographic libraries. - -The framework has been designed following a modular approach illustrated in the -next diagram: - -:: - - +---------------+---------------+------------+ - | Trusted | Trusted | Trusted | - | Firmware | Firmware | Firmware | - | Generic | IO Framework | Platform | - | Code i.e. | (IO) | Port | - | BL1/BL2 (GEN) | | (PP) | - +---------------+---------------+------------+ - ^ ^ ^ - | | | - v v v - +-----------+ +-----------+ +-----------+ - | | | | | Image | - | Crypto | | Auth | | Parser | - | Module |<->| Module |<->| Module | - | (CM) | | (AM) | | (IPM) | - | | | | | | - +-----------+ +-----------+ +-----------+ - ^ ^ - | | - v v - +----------------+ +-----------------+ - | Cryptographic | | Image Parser | - | Libraries (CL) | | Libraries (IPL) | - +----------------+ +-----------------+ - | | - | | - | | - v v - +-----------------+ - | Misc. Libs e.g. | - | ASN.1 decoder | - | | - +-----------------+ - - DIAGRAM 1. - -This document describes the inner details of the authentication framework and -the abstraction mechanisms available to specify a Chain of Trust. - -Framework design ----------------- - -This section describes some aspects of the framework design and the rationale -behind them. These aspects are key to verify a Chain of Trust. - -Chain of Trust -~~~~~~~~~~~~~~ - -A CoT is basically a sequence of authentication images which usually starts with -a root of trust and culminates in a single data image. The following diagram -illustrates how this maps to a CoT for the BL31 image described in the -`TBBR-Client specification`_. - -:: - - +------------------+ +-------------------+ - | ROTPK/ROTPK Hash |------>| Trusted Key | - +------------------+ | Certificate | - | (Auth Image) | - /+-------------------+ - / | - / | - / | - / | - L v - +------------------+ +-------------------+ - | Trusted World |------>| BL31 Key | - | Public Key | | Certificate | - +------------------+ | (Auth Image) | - +-------------------+ - / | - / | - / | - / | - / v - +------------------+ L +-------------------+ - | BL31 Content |------>| BL31 Content | - | Certificate PK | | Certificate | - +------------------+ | (Auth Image) | - +-------------------+ - / | - / | - / | - / | - / v - +------------------+ L +-------------------+ - | BL31 Hash |------>| BL31 Image | - | | | (Data Image) | - +------------------+ | | - +-------------------+ - - DIAGRAM 2. - -The root of trust is usually a public key (ROTPK) that has been burnt in the -platform and cannot be modified. - -Image types -~~~~~~~~~~~ - -Images in a CoT are categorised as authentication and data images. An -authentication image contains information to authenticate a data image or -another authentication image. A data image is usually a boot loader binary, but -it could be any other data that requires authentication. - -Component responsibilities -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For every image in a Chain of Trust, the following high level operations are -performed to verify it: - -#. Allocate memory for the image either statically or at runtime. - -#. Identify the image and load it in the allocated memory. - -#. Check the integrity of the image as per its type. - -#. Authenticate the image as per the cryptographic algorithms used. - -#. If the image is an authentication image, extract the information that will - be used to authenticate the next image in the CoT. - -In Diagram 1, each component is responsible for one or more of these operations. -The responsibilities are briefly described below. - -TF-A Generic code and IO framework (GEN/IO) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -These components are responsible for initiating the authentication process for a -particular image in BL1 or BL2. For each BL image that requires authentication, -the Generic code asks recursively the Authentication module what is the parent -image until either an authenticated image or the ROT is reached. Then the -Generic code calls the IO framework to load the image and calls the -Authentication module to authenticate it, following the CoT from ROT to Image. - -TF-A Platform Port (PP) -^^^^^^^^^^^^^^^^^^^^^^^ - -The platform is responsible for: - -#. Specifying the CoT for each image that needs to be authenticated. Details of - how a CoT can be specified by the platform are explained later. The platform - also specifies the authentication methods and the parsing method used for - each image. - -#. Statically allocating memory for each parameter in each image which is - used for verifying the CoT, e.g. memory for public keys, hashes etc. - -#. Providing the ROTPK or a hash of it. - -#. Providing additional information to the IPM to enable it to identify and - extract authentication parameters contained in an image, e.g. if the - parameters are stored as X509v3 extensions, the corresponding OID must be - provided. - -#. Fulfill any other memory requirements of the IPM and the CM (not currently - described in this document). - -#. Export functions to verify an image which uses an authentication method that - cannot be interpreted by the CM, e.g. if an image has to be verified using a - NV counter, then the value of the counter to compare with can only be - provided by the platform. - -#. Export a custom IPM if a proprietary image format is being used (described - later). - -Authentication Module (AM) -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It is responsible for: - -#. Providing the necessary abstraction mechanisms to describe a CoT. Amongst - other things, the authentication and image parsing methods must be specified - by the PP in the CoT. - -#. Verifying the CoT passed by GEN by utilising functionality exported by the - PP, IPM and CM. - -#. Tracking which images have been verified. In case an image is a part of - multiple CoTs then it should be verified only once e.g. the Trusted World - Key Certificate in the TBBR-Client spec. contains information to verify - SCP_BL2, BL31, BL32 each of which have a separate CoT. (This - responsibility has not been described in this document but should be - trivial to implement). - -#. Reusing memory meant for a data image to verify authentication images e.g. - in the CoT described in Diagram 2, each certificate can be loaded and - verified in the memory reserved by the platform for the BL31 image. By the - time BL31 (the data image) is loaded, all information to authenticate it - will have been extracted from the parent image i.e. BL31 content - certificate. It is assumed that the size of an authentication image will - never exceed the size of a data image. It should be possible to verify this - at build time using asserts. - -Cryptographic Module (CM) -^^^^^^^^^^^^^^^^^^^^^^^^^ - -The CM is responsible for providing an API to: - -#. Verify a digital signature. -#. Verify a hash. - -The CM does not include any cryptography related code, but it relies on an -external library to perform the cryptographic operations. A Crypto-Library (CL) -linking the CM and the external library must be implemented. The following -functions must be provided by the CL: - -.. code:: c - - void (*init)(void); - int (*verify_signature)(void *data_ptr, unsigned int data_len, - void *sig_ptr, unsigned int sig_len, - void *sig_alg, unsigned int sig_alg_len, - void *pk_ptr, unsigned int pk_len); - int (*verify_hash)(void *data_ptr, unsigned int data_len, - void *digest_info_ptr, unsigned int digest_info_len); - -These functions are registered in the CM using the macro: - -.. code:: c - - REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash); - -``_name`` must be a string containing the name of the CL. This name is used for -debugging purposes. - -Image Parser Module (IPM) -^^^^^^^^^^^^^^^^^^^^^^^^^ - -The IPM is responsible for: - -#. Checking the integrity of each image loaded by the IO framework. -#. Extracting parameters used for authenticating an image based upon a - description provided by the platform in the CoT descriptor. - -Images may have different formats (for example, authentication images could be -x509v3 certificates, signed ELF files or any other platform specific format). -The IPM allows to register an Image Parser Library (IPL) for every image format -used in the CoT. This library must implement the specific methods to parse the -image. The IPM obtains the image format from the CoT and calls the right IPL to -check the image integrity and extract the authentication parameters. - -See Section "Describing the image parsing methods" for more details about the -mechanism the IPM provides to define and register IPLs. - -Authentication methods -~~~~~~~~~~~~~~~~~~~~~~ - -The AM supports the following authentication methods: - -#. Hash -#. Digital signature - -The platform may specify these methods in the CoT in case it decides to define -a custom CoT instead of reusing a predefined one. - -If a data image uses multiple methods, then all the methods must be a part of -the same CoT. The number and type of parameters are method specific. These -parameters should be obtained from the parent image using the IPM. - -#. Hash - - Parameters: - - #. A pointer to data to hash - #. Length of the data - #. A pointer to the hash - #. Length of the hash - - The hash will be represented by the DER encoding of the following ASN.1 - type: - - :: - - DigestInfo ::= SEQUENCE { - digestAlgorithm DigestAlgorithmIdentifier, - digest Digest - } - - This ASN.1 structure makes it possible to remove any assumption about the - type of hash algorithm used as this information accompanies the hash. This - should allow the Cryptography Library (CL) to support multiple hash - algorithm implementations. - -#. Digital Signature - - Parameters: - - #. A pointer to data to sign - #. Length of the data - #. Public Key Algorithm - #. Public Key value - #. Digital Signature Algorithm - #. Digital Signature value - - The Public Key parameters will be represented by the DER encoding of the - following ASN.1 type: - - :: - - SubjectPublicKeyInfo ::= SEQUENCE { - algorithm AlgorithmIdentifier{PUBLIC-KEY,{PublicKeyAlgorithms}}, - subjectPublicKey BIT STRING } - - The Digital Signature Algorithm will be represented by the DER encoding of - the following ASN.1 types. - - :: - - AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE { - algorithm ALGORITHM.&id({IOSet}), - parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL - } - - The digital signature will be represented by: - - :: - - signature ::= BIT STRING - -The authentication framework will use the image descriptor to extract all the -information related to authentication. - -Specifying a Chain of Trust ---------------------------- - -A CoT can be described as a set of image descriptors linked together in a -particular order. The order dictates the sequence in which they must be -verified. Each image has a set of properties which allow the AM to verify it. -These properties are described below. - -The PP is responsible for defining a single or multiple CoTs for a data image. -Unless otherwise specified, the data structures described in the following -sections are populated by the PP statically. - -Describing the image parsing methods -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The parsing method refers to the format of a particular image. For example, an -authentication image that represents a certificate could be in the X.509v3 -format. A data image that represents a boot loader stage could be in raw binary -or ELF format. The IPM supports three parsing methods. An image has to use one -of the three methods described below. An IPL is responsible for interpreting a -single parsing method. There has to be one IPL for every method used by the -platform. - -#. Raw format: This format is effectively a nop as an image using this method - is treated as being in raw binary format e.g. boot loader images used by - TF-A. This method should only be used by data images. - -#. X509V3 method: This method uses industry standards like X.509 to represent - PKI certificates (authentication images). It is expected that open source - libraries will be available which can be used to parse an image represented - by this method. Such libraries can be used to write the corresponding IPL - e.g. the X.509 parsing library code in mbed TLS. - -#. Platform defined method: This method caters for platform specific - proprietary standards to represent authentication or data images. For - example, The signature of a data image could be appended to the data image - raw binary. A header could be prepended to the combined blob to specify the - extents of each component. The platform will have to implement the - corresponding IPL to interpret such a format. - -The following enum can be used to define these three methods. - -.. code:: c - - typedef enum img_type_enum { - IMG_RAW, /* Binary image */ - IMG_PLAT, /* Platform specific format */ - IMG_CERT, /* X509v3 certificate */ - IMG_MAX_TYPES, - } img_type_t; - -An IPL must provide functions with the following prototypes: - -.. code:: c - - void init(void); - int check_integrity(void *img, unsigned int img_len); - int get_auth_param(const auth_param_type_desc_t *type_desc, - void *img, unsigned int img_len, - void **param, unsigned int *param_len); - -An IPL for each type must be registered using the following macro: - -:: - - REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param) - -- ``_type``: one of the types described above. -- ``_name``: a string containing the IPL name for debugging purposes. -- ``_init``: initialization function pointer. -- ``_check_int``: check image integrity function pointer. -- ``_get_param``: extract authentication parameter function pointer. - -The ``init()`` function will be used to initialize the IPL. - -The ``check_integrity()`` function is passed a pointer to the memory where the -image has been loaded by the IO framework and the image length. It should ensure -that the image is in the format corresponding to the parsing method and has not -been tampered with. For example, RFC-2459 describes a validation sequence for an -X.509 certificate. - -The ``get_auth_param()`` function is passed a parameter descriptor containing -information about the parameter (``type_desc`` and ``cookie``) to identify and -extract the data corresponding to that parameter from an image. This data will -be used to verify either the current or the next image in the CoT sequence. - -Each image in the CoT will specify the parsing method it uses. This information -will be used by the IPM to find the right parser descriptor for the image. - -Describing the authentication method(s) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As part of the CoT, each image has to specify one or more authentication methods -which will be used to verify it. As described in the Section "Authentication -methods", there are three methods supported by the AM. - -.. code:: c - - typedef enum { - AUTH_METHOD_NONE, - AUTH_METHOD_HASH, - AUTH_METHOD_SIG, - AUTH_METHOD_NUM - } auth_method_type_t; - -The AM defines the type of each parameter used by an authentication method. It -uses this information to: - -#. Specify to the ``get_auth_param()`` function exported by the IPM, which - parameter should be extracted from an image. - -#. Correctly marshall the parameters while calling the verification function - exported by the CM and PP. - -#. Extract authentication parameters from a parent image in order to verify a - child image e.g. to verify the certificate image, the public key has to be - obtained from the parent image. - -.. code:: c - - typedef enum { - AUTH_PARAM_NONE, - AUTH_PARAM_RAW_DATA, /* Raw image data */ - AUTH_PARAM_SIG, /* The image signature */ - AUTH_PARAM_SIG_ALG, /* The image signature algorithm */ - AUTH_PARAM_HASH, /* A hash (including the algorithm) */ - AUTH_PARAM_PUB_KEY, /* A public key */ - } auth_param_type_t; - -The AM defines the following structure to identify an authentication parameter -required to verify an image. - -.. code:: c - - typedef struct auth_param_type_desc_s { - auth_param_type_t type; - void *cookie; - } auth_param_type_desc_t; - -``cookie`` is used by the platform to specify additional information to the IPM -which enables it to uniquely identify the parameter that should be extracted -from an image. For example, the hash of a BL3x image in its corresponding -content certificate is stored in an X509v3 custom extension field. An extension -field can only be identified using an OID. In this case, the ``cookie`` could -contain the pointer to the OID defined by the platform for the hash extension -field while the ``type`` field could be set to ``AUTH_PARAM_HASH``. A value of 0 for -the ``cookie`` field means that it is not used. - -For each method, the AM defines a structure with the parameters required to -verify the image. - -.. code:: c - - /* - * Parameters for authentication by hash matching - */ - typedef struct auth_method_param_hash_s { - auth_param_type_desc_t *data; /* Data to hash */ - auth_param_type_desc_t *hash; /* Hash to match with */ - } auth_method_param_hash_t; - - /* - * Parameters for authentication by signature - */ - typedef struct auth_method_param_sig_s { - auth_param_type_desc_t *pk; /* Public key */ - auth_param_type_desc_t *sig; /* Signature to check */ - auth_param_type_desc_t *alg; /* Signature algorithm */ - auth_param_type_desc_t *tbs; /* Data signed */ - } auth_method_param_sig_t; - -The AM defines the following structure to describe an authentication method for -verifying an image - -.. code:: c - - /* - * Authentication method descriptor - */ - typedef struct auth_method_desc_s { - auth_method_type_t type; - union { - auth_method_param_hash_t hash; - auth_method_param_sig_t sig; - } param; - } auth_method_desc_t; - -Using the method type specified in the ``type`` field, the AM finds out what field -needs to access within the ``param`` union. - -Storing Authentication parameters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A parameter described by ``auth_param_type_desc_t`` to verify an image could be -obtained from either the image itself or its parent image. The memory allocated -for loading the parent image will be reused for loading the child image. Hence -parameters which are obtained from the parent for verifying a child image need -to have memory allocated for them separately where they can be stored. This -memory must be statically allocated by the platform port. - -The AM defines the following structure to store the data corresponding to an -authentication parameter. - -.. code:: c - - typedef struct auth_param_data_desc_s { - void *auth_param_ptr; - unsigned int auth_param_len; - } auth_param_data_desc_t; - -The ``auth_param_ptr`` field is initialized by the platform. The ``auth_param_len`` -field is used to specify the length of the data in the memory. - -For parameters that can be obtained from the child image itself, the IPM is -responsible for populating the ``auth_param_ptr`` and ``auth_param_len`` fields -while executing the ``img_get_auth_param()`` function. - -The AM defines the following structure to enable an image to describe the -parameters that should be extracted from it and used to verify the next image -(child) in a CoT. - -.. code:: c - - typedef struct auth_param_desc_s { - auth_param_type_desc_t type_desc; - auth_param_data_desc_t data; - } auth_param_desc_t; - -Describing an image in a CoT -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -An image in a CoT is a consolidation of the following aspects of a CoT described -above. - -#. A unique identifier specified by the platform which allows the IO framework - to locate the image in a FIP and load it in the memory reserved for the data - image in the CoT. - -#. A parsing method which is used by the AM to find the appropriate IPM. - -#. Authentication methods and their parameters as described in the previous - section. These are used to verify the current image. - -#. Parameters which are used to verify the next image in the current CoT. These - parameters are specified only by authentication images and can be extracted - from the current image once it has been verified. - -The following data structure describes an image in a CoT. - -.. code:: c - - typedef struct auth_img_desc_s { - unsigned int img_id; - const struct auth_img_desc_s *parent; - img_type_t img_type; - const auth_method_desc_t *const img_auth_methods; - const auth_param_desc_t *const authenticated_data; - } auth_img_desc_t; - -A CoT is defined as an array of pointers to ``auth_image_desc_t`` structures -linked together by the ``parent`` field. Those nodes with no parent must be -authenticated using the ROTPK stored in the platform. - -Implementation example ----------------------- - -This section is a detailed guide explaining a trusted boot implementation using -the authentication framework. This example corresponds to the Applicative -Functional Mode (AFM) as specified in the TBBR-Client document. It is -recommended to read this guide along with the source code. - -The TBBR CoT -~~~~~~~~~~~~ - -The CoT can be found in ``drivers/auth/tbbr/tbbr_cot.c``. This CoT consists of -an array of pointers to image descriptors and it is registered in the framework -using the macro ``REGISTER_COT(cot_desc)``, where 'cot_desc' must be the name -of the array (passing a pointer or any other type of indirection will cause the -registration process to fail). - -The number of images participating in the boot process depends on the CoT. -There is, however, a minimum set of images that are mandatory in TF-A and thus -all CoTs must present: - -- ``BL2`` -- ``SCP_BL2`` (platform specific) -- ``BL31`` -- ``BL32`` (optional) -- ``BL33`` - -The TBBR specifies the additional certificates that must accompany these images -for a proper authentication. Details about the TBBR CoT may be found in the -`Trusted Board Boot`_ document. - -Following the `Platform Porting Guide`_, a platform must provide unique -identifiers for all the images and certificates that will be loaded during the -boot process. If a platform is using the TBBR as a reference for trusted boot, -these identifiers can be obtained from ``include/common/tbbr/tbbr_img_def.h``. -Arm platforms include this file in ``include/plat/arm/common/arm_def.h``. Other -platforms may also include this file or provide their own identifiers. - -**Important**: the authentication module uses these identifiers to index the -CoT array, so the descriptors location in the array must match the identifiers. - -Each image descriptor must specify: - -- ``img_id``: the corresponding image unique identifier defined by the platform. -- ``img_type``: the image parser module uses the image type to call the proper - parsing library to check the image integrity and extract the required - authentication parameters. Three types of images are currently supported: - - - ``IMG_RAW``: image is a raw binary. No parsing functions are available, - other than reading the whole image. - - ``IMG_PLAT``: image format is platform specific. The platform may use this - type for custom images not directly supported by the authentication - framework. - - ``IMG_CERT``: image is an x509v3 certificate. - -- ``parent``: pointer to the parent image descriptor. The parent will contain - the information required to authenticate the current image. If the parent - is NULL, the authentication parameters will be obtained from the platform - (i.e. the BL2 and Trusted Key certificates are signed with the ROT private - key, whose public part is stored in the platform). -- ``img_auth_methods``: this points to an array which defines the - authentication methods that must be checked to consider an image - authenticated. Each method consists of a type and a list of parameter - descriptors. A parameter descriptor consists of a type and a cookie which - will point to specific information required to extract that parameter from - the image (i.e. if the parameter is stored in an x509v3 extension, the - cookie will point to the extension OID). Depending on the method type, a - different number of parameters must be specified. This pointer should not be - NULL. - Supported methods are: - - - ``AUTH_METHOD_HASH``: the hash of the image must match the hash extracted - from the parent image. The following parameter descriptors must be - specified: - - - ``data``: data to be hashed (obtained from current image) - - ``hash``: reference hash (obtained from parent image) - - - ``AUTH_METHOD_SIG``: the image (usually a certificate) must be signed with - the private key whose public part is extracted from the parent image (or - the platform if the parent is NULL). The following parameter descriptors - must be specified: - - - ``pk``: the public key (obtained from parent image) - - ``sig``: the digital signature (obtained from current image) - - ``alg``: the signature algorithm used (obtained from current image) - - ``data``: the data to be signed (obtained from current image) - -- ``authenticated_data``: this array pointer indicates what authentication - parameters must be extracted from an image once it has been authenticated. - Each parameter consists of a parameter descriptor and the buffer - address/size to store the parameter. The CoT is responsible for allocating - the required memory to store the parameters. This pointer may be NULL. - -In the ``tbbr_cot.c`` file, a set of buffers are allocated to store the parameters -extracted from the certificates. In the case of the TBBR CoT, these parameters -are hashes and public keys. In DER format, an RSA-2048 public key requires 294 -bytes, and a hash requires 51 bytes. Depending on the CoT and the authentication -process, some of the buffers may be reused at different stages during the boot. - -Next in that file, the parameter descriptors are defined. These descriptors will -be used to extract the parameter data from the corresponding image. - -Example: the BL31 Chain of Trust -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Four image descriptors form the BL31 Chain of Trust: - -.. code:: c - - static const auth_img_desc_t trusted_key_cert = { - .img_id = TRUSTED_KEY_CERT_ID, - .img_type = IMG_CERT, - .parent = NULL, - .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { - [0] = { - .type = AUTH_METHOD_SIG, - .param.sig = { - .pk = &subject_pk, - .sig = &sig, - .alg = &sig_alg, - .data = &raw_data - } - }, - [1] = { - .type = AUTH_METHOD_NV_CTR, - .param.nv_ctr = { - .cert_nv_ctr = &trusted_nv_ctr, - .plat_nv_ctr = &trusted_nv_ctr - } - } - }, - .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { - [0] = { - .type_desc = &trusted_world_pk, - .data = { - .ptr = (void *)trusted_world_pk_buf, - .len = (unsigned int)PK_DER_LEN - } - }, - [1] = { - .type_desc = &non_trusted_world_pk, - .data = { - .ptr = (void *)non_trusted_world_pk_buf, - .len = (unsigned int)PK_DER_LEN - } - } - } - }; - static const auth_img_desc_t soc_fw_key_cert = { - .img_id = SOC_FW_KEY_CERT_ID, - .img_type = IMG_CERT, - .parent = &trusted_key_cert, - .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { - [0] = { - .type = AUTH_METHOD_SIG, - .param.sig = { - .pk = &trusted_world_pk, - .sig = &sig, - .alg = &sig_alg, - .data = &raw_data - } - }, - [1] = { - .type = AUTH_METHOD_NV_CTR, - .param.nv_ctr = { - .cert_nv_ctr = &trusted_nv_ctr, - .plat_nv_ctr = &trusted_nv_ctr - } - } - }, - .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { - [0] = { - .type_desc = &soc_fw_content_pk, - .data = { - .ptr = (void *)content_pk_buf, - .len = (unsigned int)PK_DER_LEN - } - } - } - }; - static const auth_img_desc_t soc_fw_content_cert = { - .img_id = SOC_FW_CONTENT_CERT_ID, - .img_type = IMG_CERT, - .parent = &soc_fw_key_cert, - .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { - [0] = { - .type = AUTH_METHOD_SIG, - .param.sig = { - .pk = &soc_fw_content_pk, - .sig = &sig, - .alg = &sig_alg, - .data = &raw_data - } - }, - [1] = { - .type = AUTH_METHOD_NV_CTR, - .param.nv_ctr = { - .cert_nv_ctr = &trusted_nv_ctr, - .plat_nv_ctr = &trusted_nv_ctr - } - } - }, - .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { - [0] = { - .type_desc = &soc_fw_hash, - .data = { - .ptr = (void *)soc_fw_hash_buf, - .len = (unsigned int)HASH_DER_LEN - } - }, - [1] = { - .type_desc = &soc_fw_config_hash, - .data = { - .ptr = (void *)soc_fw_config_hash_buf, - .len = (unsigned int)HASH_DER_LEN - } - } - } - }; - static const auth_img_desc_t bl31_image = { - .img_id = BL31_IMAGE_ID, - .img_type = IMG_RAW, - .parent = &soc_fw_content_cert, - .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { - [0] = { - .type = AUTH_METHOD_HASH, - .param.hash = { - .data = &raw_data, - .hash = &soc_fw_hash - } - } - } - }; - -The **Trusted Key certificate** is signed with the ROT private key and contains -the Trusted World public key and the Non-Trusted World public key as x509v3 -extensions. This must be specified in the image descriptor using the -``img_auth_methods`` and ``authenticated_data`` arrays, respectively. - -The Trusted Key certificate is authenticated by checking its digital signature -using the ROTPK. Four parameters are required to check a signature: the public -key, the algorithm, the signature and the data that has been signed. Therefore, -four parameter descriptors must be specified with the authentication method: - -- ``subject_pk``: parameter descriptor of type ``AUTH_PARAM_PUB_KEY``. This type - is used to extract a public key from the parent image. If the cookie is an - OID, the key is extracted from the corresponding x509v3 extension. If the - cookie is NULL, the subject public key is retrieved. In this case, because - the parent image is NULL, the public key is obtained from the platform - (this key will be the ROTPK). -- ``sig``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to extract - the signature from the certificate. -- ``sig_alg``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to - extract the signature algorithm from the certificate. -- ``raw_data``: parameter descriptor of type ``AUTH_PARAM_RAW_DATA``. It is used - to extract the data to be signed from the certificate. - -Once the signature has been checked and the certificate authenticated, the -Trusted World public key needs to be extracted from the certificate. A new entry -is created in the ``authenticated_data`` array for that purpose. In that entry, -the corresponding parameter descriptor must be specified along with the buffer -address to store the parameter value. In this case, the ``tz_world_pk`` descriptor -is used to extract the public key from an x509v3 extension with OID -``TRUSTED_WORLD_PK_OID``. The BL31 key certificate will use this descriptor as -parameter in the signature authentication method. The key is stored in the -``plat_tz_world_pk_buf`` buffer. - -The **BL31 Key certificate** is authenticated by checking its digital signature -using the Trusted World public key obtained previously from the Trusted Key -certificate. In the image descriptor, we specify a single authentication method -by signature whose public key is the ``tz_world_pk``. Once this certificate has -been authenticated, we have to extract the BL31 public key, stored in the -extension specified by ``bl31_content_pk``. This key will be copied to the -``plat_content_pk`` buffer. - -The **BL31 certificate** is authenticated by checking its digital signature -using the BL31 public key obtained previously from the BL31 Key certificate. -We specify the authentication method using ``bl31_content_pk`` as public key. -After authentication, we need to extract the BL31 hash, stored in the extension -specified by ``bl31_hash``. This hash will be copied to the ``plat_bl31_hash_buf`` -buffer. - -The **BL31 image** is authenticated by calculating its hash and matching it -with the hash obtained from the BL31 certificate. The image descriptor contains -a single authentication method by hash. The parameters to the hash method are -the reference hash, ``bl31_hash``, and the data to be hashed. In this case, it is -the whole image, so we specify ``raw_data``. - -The image parser library -~~~~~~~~~~~~~~~~~~~~~~~~ - -The image parser module relies on libraries to check the image integrity and -extract the authentication parameters. The number and type of parser libraries -depend on the images used in the CoT. Raw images do not need a library, so -only an x509v3 library is required for the TBBR CoT. - -Arm platforms will use an x509v3 library based on mbed TLS. This library may be -found in ``drivers/auth/mbedtls/mbedtls_x509_parser.c``. It exports three -functions: - -.. code:: c - - void init(void); - int check_integrity(void *img, unsigned int img_len); - int get_auth_param(const auth_param_type_desc_t *type_desc, - void *img, unsigned int img_len, - void **param, unsigned int *param_len); - -The library is registered in the framework using the macro -``REGISTER_IMG_PARSER_LIB()``. Each time the image parser module needs to access -an image of type ``IMG_CERT``, it will call the corresponding function exported -in this file. - -The build system must be updated to include the corresponding library and -mbed TLS sources. Arm platforms use the ``arm_common.mk`` file to pull the -sources. - -The cryptographic library -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The cryptographic module relies on a library to perform the required operations, -i.e. verify a hash or a digital signature. Arm platforms will use a library -based on mbed TLS, which can be found in -``drivers/auth/mbedtls/mbedtls_crypto.c``. This library is registered in the -authentication framework using the macro ``REGISTER_CRYPTO_LIB()`` and exports -three functions: - -.. code:: c - - void init(void); - int verify_signature(void *data_ptr, unsigned int data_len, - void *sig_ptr, unsigned int sig_len, - void *sig_alg, unsigned int sig_alg_len, - void *pk_ptr, unsigned int pk_len); - int verify_hash(void *data_ptr, unsigned int data_len, - void *digest_info_ptr, unsigned int digest_info_len); - -The mbedTLS library algorithm support is configured by the -``TF_MBEDTLS_KEY_ALG`` variable which can take in 3 values: `rsa`, `ecdsa` or -`rsa+ecdsa`. This variable allows the Makefile to include the corresponding -sources in the build for the various algorithms. Setting the variable to -`rsa+ecdsa` enables support for both rsa and ecdsa algorithms in the mbedTLS -library. - -Note: If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can -be defined in the platform Makefile. It will make mbed TLS use an implementation -of SHA-256 with smaller memory footprint (~1.5 KB less) but slower (~30%). - --------------- - -*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.* - -.. _Trusted Board Boot: ./trusted-board-boot.rst -.. _Platform Porting Guide: ./porting-guide.rst -.. _TBBR-Client specification: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a diff --git a/docs/change-log.rst b/docs/change-log.rst index 1aca22b..6893582 100644 --- a/docs/change-log.rst +++ b/docs/change-log.rst @@ -2417,15 +2417,15 @@ *Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.* .. _SDEI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf -.. _PSCI Integration Guide: psci-lib-integration-guide.rst +.. _PSCI Integration Guide: ./getting_started/psci-lib-integration-guide.rst .. _Developer Certificate of Origin: ../dco.txt -.. _Contribution Guide: ../contributing.rst -.. _Authentication framework: auth-framework.rst -.. _Firmware Update: firmware-update.rst -.. _TF-A Reset Design: reset-design.rst -.. _Power Domain Topology Design: psci-pd-tree.rst +.. _Contribution Guide: ./contributing.rst +.. _Authentication framework: ./design/auth-framework.rst +.. _Firmware Update: ./design/firmware-update.rst +.. _TF-A Reset Design: ./design/reset-design.rst +.. _Power Domain Topology Design: ./design/psci-pd-tree.rst .. _TF-A wiki on GitHub: https://github.com/ARM-software/arm-trusted-firmware/wiki/ARM-Trusted-Firmware-Image-Terminology -.. _Authentication Framework: auth-framework.rst -.. _OP-TEE Dispatcher: optee-dispatcher.rst +.. _Authentication Framework: ./design/auth-framework.rst +.. _OP-TEE Dispatcher: ./spd/optee-dispatcher.rst .. _tf-issue#501: https://github.com/ARM-software/tf-issues/issues/501 .. _PR#1002: https://github.com/ARM-software/arm-trusted-firmware/pull/1002#issuecomment-312650193 diff --git a/docs/coding-guidelines.rst b/docs/coding-guidelines.rst deleted file mode 100644 index e8f365b..0000000 --- a/docs/coding-guidelines.rst +++ /dev/null @@ -1,555 +0,0 @@ -Trusted Firmware-A Coding Guidelines -==================================== - -.. section-numbering:: - :suffix: . - -.. contents:: - -The following sections contain TF coding guidelines. They are continually -evolving and should not be considered "set in stone". Feel free to question them -and provide feedback. - -Some of the guidelines may also apply to other codebases. - -**Note:** the existing TF codebase does not necessarily comply with all the -below guidelines but the intent is for it to do so eventually. - -Checkpatch overrides --------------------- - -Some checkpatch warnings in the TF codebase are deliberately ignored. These -include: - -- ``**WARNING: line over 80 characters**``: Although the codebase should - generally conform to the 80 character limit this is overly restrictive in some - cases. - -- ``**WARNING: Use of volatile is usually wrong``: see - `Why the “volatile” type class should not be used`_ . Although this document - contains some very useful information, there are several legimate uses of the - volatile keyword within the TF codebase. - -Headers and inclusion ---------------------- - -Header guards -^^^^^^^^^^^^^ - -For a header file called "some_driver.h" the style used by the Trusted Firmware -is: - -.. code:: c - - #ifndef SOME_DRIVER_H - #define SOME_DRIVER_H - -
- - #endif /* SOME_DRIVER_H */ - -Include statement ordering -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -All header files that are included by a source file must use the following, -grouped ordering. This is to improve readability (by making it easier to quickly -read through the list of headers) and maintainability. - -#. *System* includes: Header files from the standard *C* library, such as - ``stddef.h`` and ``string.h``. - -#. *Project* includes: Header files under the ``include/`` directory within TF - are *project* includes. - -#. *Platform* includes: Header files relating to a single, specific platform, - and which are located under the ``plat/`` directory within TF, - are *platform* includes. - -Within each group, ``#include`` statements must be in alphabetical order, -taking both the file and directory names into account. - -Groups must be separated by a single blank line for clarity. - -The example below illustrates the ordering rules using some contrived header -file names; this type of name reuse should be otherwise avoided. - -.. code:: c - - #include - - #include - #include - #include - #include - - #include "./a_header.h" - -Include statement variants -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Two variants of the ``#include`` directive are acceptable in the TF codebase. -Correct use of the two styles improves readability by suggesting the location -of the included header and reducing ambiguity in cases where generic and -platform-specific headers share a name. - -For header files that are in the same directory as the source file that is -including them, use the ``"..."`` variant. - -For header files that are **not** in the same directory as the source file that -is including them, use the ``<...>`` variant. - -Example (bl1_fwu.c): - -.. code:: c - - #include - #include - #include - - #include "bl1_private.h" - -Platform include paths -^^^^^^^^^^^^^^^^^^^^^^ - -Platforms are allowed to add more include paths to be passed to the compiler. -The ``PLAT_INCLUDES`` variable is used for this purpose. This is needed in -particular for the file ``platform_def.h``. - -Example: - -.. code:: c - - PLAT_INCLUDES += -Iinclude/plat/myplat/include - -Types and typedefs ------------------- - -Use of built-in *C* and *libc* data types -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The TF codebase should be kept as portable as possible, especially since both -64-bit and 32-bit platforms are supported. To help with this, the following data -type usage guidelines should be followed: - -- Where possible, use the built-in *C* data types for variable storage (for - example, ``char``, ``int``, ``long long``, etc) instead of the standard *C99* - types. Most code is typically only concerned with the minimum size of the - data stored, which the built-in *C* types guarantee. - -- Avoid using the exact-size standard *C99* types in general (for example, - ``uint16_t``, ``uint32_t``, ``uint64_t``, etc) since they can prevent the - compiler from making optimizations. There are legitimate uses for them, - for example to represent data of a known structure. When using them in struct - definitions, consider how padding in the struct will work across architectures. - For example, extra padding may be introduced in AArch32 systems if a struct - member crosses a 32-bit boundary. - -- Use ``int`` as the default integer type - it's likely to be the fastest on all - systems. Also this can be assumed to be 32-bit as a consequence of the - `Procedure Call Standard for the Arm Architecture`_ and the `Procedure Call - Standard for the Arm 64-bit Architecture`_ . - -- Avoid use of ``short`` as this may end up being slower than ``int`` in some - systems. If a variable must be exactly 16-bit, use ``int16_t`` or - ``uint16_t``. - -- Avoid use of ``long``. This is guaranteed to be at least 32-bit but, given - that `int` is 32-bit on Arm platforms, there is no use for it. For integers of - at least 64-bit, use ``long long``. - -- Use ``char`` for storing text. Use ``uint8_t`` for storing other 8-bit data. - -- Use ``unsigned`` for integers that can never be negative (counts, - indices, sizes, etc). TF intends to comply with MISRA "essential type" coding - rules (10.X), where signed and unsigned types are considered different - essential types. Choosing the correct type will aid this. MISRA static - analysers will pick up any implicit signed/unsigned conversions that may lead - to unexpected behaviour. - -- For pointer types: - - - If an argument in a function declaration is pointing to a known type then - simply use a pointer to that type (for example: ``struct my_struct *``). - - - If a variable (including an argument in a function declaration) is pointing - to a general, memory-mapped address, an array of pointers or another - structure that is likely to require pointer arithmetic then use - ``uintptr_t``. This will reduce the amount of casting required in the code. - Avoid using ``unsigned long`` or ``unsigned long long`` for this purpose; it - may work but is less portable. - - - For other pointer arguments in a function declaration, use ``void *``. This - includes pointers to types that are abstracted away from the known API and - pointers to arbitrary data. This allows the calling function to pass a - pointer argument to the function without any explicit casting (the cast to - ``void *`` is implicit). The function implementation can then do the - appropriate casting to a specific type. - - - Use ``ptrdiff_t`` to compare the difference between 2 pointers. - -- Use ``size_t`` when storing the ``sizeof()`` something. - -- Use ``ssize_t`` when returning the ``sizeof()`` something from a function that - can also return an error code; the signed type allows for a negative return - code in case of error. This practice should be used sparingly. - -- Use ``u_register_t`` when it's important to store the contents of a register - in its native size (32-bit in AArch32 and 64-bit in AArch64). This is not a - standard *C99* type but is widely available in libc implementations, - including the FreeBSD version included with the TF codebase. Where possible, - cast the variable to a more appropriate type before interpreting the data. For - example, the following struct in ``ep_info.h`` could use this type to minimize - the storage required for the set of registers: - -.. code:: c - - typedef struct aapcs64_params { - u_register_t arg0; - u_register_t arg1; - u_register_t arg2; - u_register_t arg3; - u_register_t arg4; - u_register_t arg5; - u_register_t arg6; - u_register_t arg7; - } aapcs64_params_t; - -If some code wants to operate on ``arg0`` and knows that it represents a 32-bit -unsigned integer on all systems, cast it to ``unsigned int``. - -These guidelines should be updated if additional types are needed. - -Avoid anonymous typedefs of structs/enums in headers -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For example, the following definition: - -.. code:: c - - typedef struct { - int arg1; - int arg2; - } my_struct_t; - - -is better written as: - -.. code:: c - - struct my_struct { - int arg1; - int arg2; - }; - -This allows function declarations in other header files that depend on the -struct/enum to forward declare the struct/enum instead of including the -entire header: - -.. code:: c - - #include - void my_func(my_struct_t *arg); - -instead of: - -.. code:: c - - struct my_struct; - void my_func(struct my_struct *arg); - -Some TF definitions use both a struct/enum name **and** a typedef name. This -is discouraged for new definitions as it makes it difficult for TF to comply -with MISRA rule 8.3, which states that "All declarations of an object or -function shall use the same names and type qualifiers". - -The Linux coding standards also discourage new typedefs and checkpatch emits -a warning for this. - -Existing typedefs will be retained for compatibility. - -Error handling and robustness ------------------------------ - -Using CASSERT to check for compile time data errors -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Where possible, use the ``CASSERT`` macro to check the validity of data known at -compile time instead of checking validity at runtime, to avoid unnecessary -runtime code. - -For example, this can be used to check that the assembler's and compiler's views -of the size of an array is the same. - -.. code:: c - - #include - - define MY_STRUCT_SIZE 8 /* Used by assembler source files */ - - struct my_struct { - uint32_t arg1; - uint32_t arg2; - }; - - CASSERT(MY_STRUCT_SIZE == sizeof(struct my_struct), assert_my_struct_size_mismatch); - - -If ``MY_STRUCT_SIZE`` in the above example were wrong then the compiler would -emit an error like this: - -.. code:: c - - my_struct.h:10:1: error: size of array ‘assert_my_struct_size_mismatch’ is negative - - -Using assert() to check for programming errors -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In general, each secure world TF image (BL1, BL2, BL31 and BL32) should be -treated as a tightly integrated package; the image builder should be aware of -and responsible for all functionality within the image, even if code within that -image is provided by multiple entities. This allows us to be more aggressive in -interpreting invalid state or bad function arguments as programming errors using -``assert()``, including arguments passed across platform porting interfaces. -This is in contrast to code in a Linux environment, which is less tightly -integrated and may attempt to be more defensive by passing the error back up the -call stack. - -Where possible, badly written TF code should fail early using ``assert()``. This -helps reduce the amount of untested conditional code. By default these -statements are not compiled into release builds, although this can be overridden -using the ``ENABLE_ASSERTIONS`` build flag. - -Examples: - -- Bad argument supplied to library function -- Bad argument provided by platform porting function -- Internal secure world image state is inconsistent - - -Handling integration errors -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Each secure world image may be provided by a different entity (for example, a -Trusted Boot vendor may provide the BL2 image, a TEE vendor may provide the BL32 -image and the OEM/SoC vendor may provide the other images). - -An image may contain bugs that are only visible when the images are integrated. -The system integrator may not even have access to the debug variants of all the -images in order to check if asserts are firing. For example, the release variant -of BL1 may have already been burnt into the SoC. Therefore, TF code that detects -an integration error should _not_ consider this a programming error, and should -always take action, even in release builds. - -If an integration error is considered non-critical it should be treated as a -recoverable error. If the error is considered critical it should be treated as -an unexpected unrecoverable error. - -Handling recoverable errors -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The secure world **must not** crash when supplied with bad data from an external -source. For example, data from the normal world or a hardware device. Similarly, -the secure world **must not** crash if it detects a non-critical problem within -itself or the system. It must make every effort to recover from the problem by -emitting a ``WARN`` message, performing any necessary error handling and -continuing. - -Examples: - -- Secure world receives SMC from normal world with bad arguments. -- Secure world receives SMC from normal world at an unexpected time. -- BL31 receives SMC from BL32 with bad arguments. -- BL31 receives SMC from BL32 at unexpected time. -- Secure world receives recoverable error from hardware device. Retrying the - operation may help here. -- Non-critical secure world service is not functioning correctly. -- BL31 SPD discovers minor configuration problem with corresponding SP. - -Handling unrecoverable errors -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In some cases it may not be possible for the secure world to recover from an -error. This situation should be handled in one of the following ways: - -1. If the unrecoverable error is unexpected then emit an ``ERROR`` message and - call ``panic()``. This will end up calling the platform-specific function - ``plat_panic_handler()``. -2. If the unrecoverable error is expected to occur in certain circumstances, - then emit an ``ERROR`` message and call the platform-specific function - ``plat_error_handler()``. - -Cases 1 and 2 are subtly different. A platform may implement ``plat_panic_handler`` -and ``plat_error_handler`` in the same way (for example, by waiting for a secure -watchdog to time-out or by invoking an interface on the platform's power -controller to reset the platform). However, ``plat_error_handler`` may take -additional action for some errors (for example, it may set a flag so the -platform resets into a different mode). Also, ``plat_panic_handler()`` may -implement additional debug functionality (for example, invoking a hardware -breakpoint). - -Examples of unexpected unrecoverable errors: - -- BL32 receives an unexpected SMC response from BL31 that it is unable to - recover from. -- BL31 Trusted OS SPD code discovers that BL2 has not loaded the corresponding - Trusted OS, which is critical for platform operation. -- Secure world discovers that a critical hardware device is an unexpected and - unrecoverable state. -- Secure world receives an unexpected and unrecoverable error from a critical - hardware device. -- Secure world discovers that it is running on unsupported hardware. - -Examples of expected unrecoverable errors: - -- BL1/BL2 fails to load the next image due to missing/corrupt firmware on disk. -- BL1/BL2 fails to authenticate the next image due to an invalid certificate. -- Secure world continuously receives recoverable errors from a hardware device - but is unable to proceed without a valid response. - -Handling critical unresponsiveness -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If the secure world is waiting for a response from an external source (for -example, the normal world or a hardware device) which is critical for continued -operation, it must not wait indefinitely. It must have a mechanism (for example, -a secure watchdog) for resetting itself and/or the external source to prevent -the system from executing in this state indefinitely. - -Examples: - -- BL1 is waiting for the normal world to raise an SMC to proceed to the next - stage of the secure firmware update process. -- A Trusted OS is waiting for a response from a proxy in the normal world that - is critical for continued operation. -- Secure world is waiting for a hardware response that is critical for continued - operation. - -Security considerations ------------------------ - -Part of the security of a platform is handling errors correctly, as described in -the previous section. There are several other security considerations covered in -this section. - -Do not leak secrets to the normal world -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The secure world **must not** leak secrets to the normal world, for example in -response to an SMC. - -Handling Denial of Service attacks -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The secure world **should never** crash or become unusable due to receiving too -many normal world requests (a *Denial of Service* or *DoS* attack). It should -have a mechanism for throttling or ignoring normal world requests. - -Performance considerations --------------------------- - -Avoid printf and use logging macros -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``debug.h`` provides logging macros (for example, ``WARN`` and ``ERROR``) -which wrap ``tf_log`` and which allow the logging call to be compiled-out -depending on the ``make`` command. Use these macros to avoid print statements -being compiled unconditionally into the binary. - -Each logging macro has a numerical log level: - -.. code:: c - - #define LOG_LEVEL_NONE 0 - #define LOG_LEVEL_ERROR 10 - #define LOG_LEVEL_NOTICE 20 - #define LOG_LEVEL_WARNING 30 - #define LOG_LEVEL_INFO 40 - #define LOG_LEVEL_VERBOSE 50 - - -By default, all logging statements with a log level ``<= LOG_LEVEL_INFO`` will -be compiled into debug builds and all statements with a log level -``<= LOG_LEVEL_NOTICE`` will be compiled into release builds. This can be -overridden from the command line or by the platform makefile (although it may be -necessary to clean the build directory first). For example, to enable -``VERBOSE`` logging on FVP: - -``make PLAT=fvp LOG_LEVEL=50 all`` - -Use const data where possible -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For example, the following code: - -.. code:: c - - struct my_struct { - int arg1; - int arg2; - }; - - void init(struct my_struct *ptr); - - void main(void) - { - struct my_struct x; - x.arg1 = 1; - x.arg2 = 2; - init(&x); - } - -is better written as: - -.. code:: c - - struct my_struct { - int arg1; - int arg2; - }; - - void init(const struct my_struct *ptr); - - void main(void) - { - const struct my_struct x = { 1, 2 }; - init(&x); - } - -This allows the linker to put the data in a read-only data section instead of a -writeable data section, which may result in a smaller and faster binary. Note -that this may require dependent functions (``init()`` in the above example) to -have ``const`` arguments, assuming they don't need to modify the data. - -Library and driver code ------------------------ - -TF library code (under ``lib/`` and ``include/lib``) is any code that provides a -reusable interface to other code, potentially even to code outside of TF. - -In some systems drivers must conform to a specific driver framework to provide -services to the rest of the system. TF has no driver framework and the -distinction between a driver and library is somewhat subjective. - -A driver (under ``drivers/`` and ``include/drivers/``) is defined as code that -interfaces with hardware via a memory mapped interface. - -Some drivers (for example, the Arm CCI driver in ``include/drivers/arm/cci.h``) -provide a general purpose API to that specific hardware. Other drivers (for -example, the Arm PL011 console driver in ``drivers/arm/pl011/pl011_console.S``) -provide a specific hardware implementation of a more abstract library API. In -the latter case there may potentially be multiple drivers for the same hardware -device. - -Neither libraries nor drivers should depend on platform-specific code. If they -require platform-specific data (for example, a base address) to operate then -they should provide an initialization function that takes the platform-specific -data as arguments. - -TF common code (under ``common/`` and ``include/common/``) is code that is re-used -by other generic (non-platform-specific) TF code. It is effectively internal -library code. - -.. _`Why the “volatile” type class should not be used`: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html -.. _`Procedure Call Standard for the Arm Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf -.. _`Procedure Call Standard for the Arm 64-bit Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf diff --git a/docs/components/arm-sip-service.rst b/docs/components/arm-sip-service.rst new file mode 100644 index 0000000..6cdac83 --- /dev/null +++ b/docs/components/arm-sip-service.rst @@ -0,0 +1,96 @@ +Arm SiP Service +=============== + +This document enumerates and describes the Arm SiP (Silicon Provider) services. + +SiP services are non-standard, platform-specific services offered by the silicon +implementer or platform provider. They are accessed via ``SMC`` ("SMC calls") +instruction executed from Exception Levels below EL3. SMC calls for SiP +services: + +- Follow `SMC Calling Convention`_; +- Use SMC function IDs that fall in the SiP range, which are ``0xc2000000`` - + ``0xc200ffff`` for 64-bit calls, and ``0x82000000`` - ``0x8200ffff`` for 32-bit + calls. + +The Arm SiP implementation offers the following services: + +- Performance Measurement Framework (PMF) +- Execution State Switching service + +Source definitions for Arm SiP service are located in the ``arm_sip_svc.h`` header +file. + +Performance Measurement Framework (PMF) +--------------------------------------- + +The `Performance Measurement Framework`_ +allows callers to retrieve timestamps captured at various paths in TF-A +execution. It's described in detail in `Firmware Design document`_. + +Execution State Switching service +--------------------------------- + +Execution State Switching service provides a mechanism for a non-secure lower +Exception Level (either EL2, or NS EL1 if EL2 isn't implemented) to request to +switch its execution state (a.k.a. Register Width), either from AArch64 to +AArch32, or from AArch32 to AArch64, for the calling CPU. This service is only +available when Trusted Firmware-A (TF-A) is built for AArch64 (i.e. when build +option ``ARCH`` is set to ``aarch64``). + +``ARM_SIP_SVC_EXE_STATE_SWITCH`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t Function ID + uint32_t PC hi + uint32_t PC lo + uint32_t Cookie hi + uint32_t Cookie lo + + Return: + uint32_t + +The function ID parameter must be ``0x82000020``. It uniquely identifies the +Execution State Switching service being requested. + +The parameters *PC hi* and *PC lo* defines upper and lower words, respectively, +of the entry point (physical address) at which execution should start, after +Execution State has been switched. When calling from AArch64, *PC hi* must be 0. + +When execution starts at the supplied entry point after Execution State has been +switched, the parameters *Cookie hi* and *Cookie lo* are passed in CPU registers +0 and 1, respectively. When calling from AArch64, *Cookie hi* must be 0. + +This call can only be made on the primary CPU, before any secondaries were +brought up with ``CPU_ON`` PSCI call. Otherwise, the call will always fail. + +The effect of switching execution state is as if the Exception Level were +entered for the first time, following power on. This means CPU registers that +have a defined reset value by the Architecture will assume that value. Other +registers should not be expected to hold their values before the call was made. +CPU endianness, however, is preserved from the previous execution state. Note +that this switches the execution state of the calling CPU only. This is not a +substitute for PSCI ``SYSTEM_RESET``. + +The service may return the following error codes: + +- ``STATE_SW_E_PARAM``: If any of the parameters were deemed invalid for + a specific request. +- ``STATE_SW_E_DENIED``: If the call is not successful, or when TF-A is + built for AArch32. + +If the call is successful, the caller wouldn't observe the SMC returning. +Instead, execution starts at the supplied entry point, with the CPU registers 0 +and 1 populated with the supplied *Cookie hi* and *Cookie lo* values, +respectively. + +-------------- + +*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* + +.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html +.. _Performance Measurement Framework: ./firmware-design.rst#user-content-performance-measurement-framework +.. _Firmware Design document: ./firmware-design.rst diff --git a/docs/components/exception-handling.rst b/docs/components/exception-handling.rst new file mode 100644 index 0000000..e3684f1 --- /dev/null +++ b/docs/components/exception-handling.rst @@ -0,0 +1,635 @@ +Exception Handling Framework in Trusted Firmware-A +================================================== + + + + +.. contents:: + :depth: 2 + +.. |EHF| replace:: Exception Handling Framework +.. |TF-A| replace:: Trusted Firmware-A + +This document describes various aspects of handling exceptions by Runtime +Firmware (BL31) that are targeted at EL3, other than SMCs. The |EHF| takes care +of the following exceptions when targeted at EL3: + +- Interrupts +- Synchronous External Aborts +- Asynchronous External Aborts + +|TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is +described in the `Firmware Design document`__. However, the |EHF| changes the +semantics of `interrupt handling`__ and `synchronous exceptions`__ other than +SMCs. + +.. __: firmware-design.rst#handling-an-smc +.. __: `Interrupt handling`_ +.. __: `Effect on SMC calls`_ + +The |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to +``1``, and is only available for AArch64 systems. + +Introduction +------------ + +Through various control bits in the ``SCR_EL3`` register, the Arm architecture +allows for asynchronous exceptions to be routed to EL3. As described in the +`Interrupt Framework Design`_ document, depending on the chosen interrupt +routing model, TF-A appropriately sets the ``FIQ`` and ``IRQ`` bits of +``SCR_EL3`` register to effect this routing. For most use cases, other than for +the purpose of facilitating context switch between Normal and Secure worlds, +FIQs and IRQs routed to EL3 are not required to be handled in EL3. + +However, the evolving system and standards landscape demands that various +exceptions are targeted at and handled in EL3. For instance: + +- Starting with ARMv8.2 architecture extension, many RAS features have been + introduced to the Arm architecture. With RAS features implemented, various + components of the system may use one of the asynchronous exceptions to signal + error conditions to PEs. These error conditions are of critical nature, and + it's imperative that corrective or remedial actions are taken at the earliest + opportunity. Therefore, a *Firmware-first Handling* approach is generally + followed in response to RAS events in the system. + +- The Arm `SDEI specification`_ defines interfaces through which Normal world + interacts with the Runtime Firmware in order to request notification of + system events. The SDEI specification requires that these events are notified + even when the Normal world executes with the exceptions masked. This too + implies that firmware-first handling is required, where the events are first + received by the EL3 firmware, and then dispatched to Normal world through + purely software mechanism. + +For |TF-A|, firmware-first handling means that asynchronous exceptions are +suitably routed to EL3, and the Runtime Firmware (BL31) is extended to include +software components that are capable of handling those exceptions that target +EL3. These components—referred to as *dispatchers* [#spd]_ in general—may +choose to: + +.. _delegation-use-cases: + +- Receive and handle exceptions entirely in EL3, meaning the exceptions + handling terminates in EL3. + +- Receive exceptions, but handle part of the exception in EL3, and delegate the + rest of the handling to a dedicated software stack running at lower Secure + ELs. In this scheme, the handling spans various secure ELs. + +- Receive exceptions, but handle part of the exception in EL3, and delegate + processing of the error to dedicated software stack running at lower secure + ELs (as above); additionally, the Normal world may also be required to + participate in the handling, or be notified of such events (for example, as + an SDEI event). In this scheme, exception handling potentially and maximally + spans all ELs in both Secure and Normal worlds. + +On any given system, all of the above handling models may be employed +independently depending on platform choice and the nature of the exception +received. + +.. [#spd] Not to be confused with `Secure Payload Dispatcher`__, which is an + EL3 component that operates in EL3 on behalf of Secure OS. + +.. __: firmware-design.rst#secure-el1-payloads-and-dispatchers + +The role of Exception Handling Framework +---------------------------------------- + +Corollary to the use cases cited above, the primary role of the |EHF| is to +facilitate firmware-first handling of exceptions on Arm systems. The |EHF| thus +enables multiple exception dispatchers in runtime firmware to co-exist, register +for, and handle exceptions targeted at EL3. This section outlines the basics, +and the rest of this document expands the various aspects of the |EHF|. + +In order to arbitrate exception handling among dispatchers, the |EHF| operation +is based on a priority scheme. This priority scheme is closely tied to how the +Arm GIC architecture defines it, although it's applied to non-interrupt +exceptions too (SErrors, for example). + +The platform is required to `partition`__ the Secure priority space into +priority levels as applicable for the Secure software stack. It then assigns the +dispatchers to one or more priority levels. The dispatchers then register +handlers for the priority levels at runtime. A dispatcher can register handlers +for more than one priority level. + +.. __: `Partitioning priority levels`_ + + +.. _ehf-figure: + +.. image:: ../draw.io/ehf.svg + +A priority level is *active* when a handler at that priority level is currently +executing in EL3, or has delegated the execution to a lower EL. For interrupts, +this is implicit when an interrupt is targeted and acknowledged at EL3, and the +priority of the acknowledged interrupt is used to match its registered handler. +The priority level is likewise implicitly deactivated when the interrupt +handling concludes by EOIing the interrupt. + +Non-interrupt exceptions (SErrors, for example) don't have a notion of priority. +In order for the priority arbitration to work, the |EHF| provides APIs in order +for these non-interrupt exceptions to assume a priority, and to interwork with +interrupts. Dispatchers handling such exceptions must therefore explicitly +activate and deactivate the respective priority level as and when they're +handled or delegated. + +Because priority activation and deactivation for interrupt handling is implicit +and involves GIC priority masking, it's impossible for a lower priority +interrupt to preempt a higher priority one. By extension, this means that a +lower priority dispatcher cannot preempt a higher-priority one. Priority +activation and deactivation for non-interrupt exceptions, however, has to be +explicit. The |EHF| therefore disallows for lower priority level to be activated +whilst a higher priority level is active, and would result in a panic. +Likewise, a panic would result if it's attempted to deactivate a lower priority +level when a higher priority level is active. + +In essence, priority level activation and deactivation conceptually works like a +stack—priority levels stack up in strictly increasing fashion, and need to be +unstacked in strictly the reverse order. For interrupts, the GIC ensures this is +the case; for non-interrupts, the |EHF| monitors and asserts this. See +`Transition of priority levels`_. + +Interrupt handling +------------------ + +The |EHF| is a client of *Interrupt Management Framework*, and registers the +top-level handler for interrupts that target EL3, as described in the `Interrupt +Framework Design`_ document. This has the following implications. + +- On GICv3 systems, when executing in S-EL1, pending Non-secure interrupts of + sufficient priority are signalled as FIQs, and therefore will be routed to + EL3. As a result, S-EL1 software cannot expect to handle Non-secure + interrupts at S-EL1. Essentially, this deprecates the routing mode described + as `CSS=0, TEL3=0`__. + + .. __: interrupt-framework-design.rst#el3-interrupts + + In order for S-EL1 software to handle Non-secure interrupts while having + |EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts + are received at EL3, but are then `synchronously`__ handled over to S-EL1. + + .. __: interrupt-framework-design.rst#secure-payload + +- On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is + set to ``1`` so that *Group 0* interrupts target EL3. + +- While executing in Secure world, |EHF| sets GIC Priority Mask Register to the + lowest Secure priority. This means that no Non-secure interrupts can preempt + Secure execution. See `Effect on SMC calls`_ for more details. + +As mentioned above, with |EHF|, the platform is required to partition *Group 0* +interrupts into distinct priority levels. A dispatcher that chooses to receive +interrupts can then *own* one or more priority levels, and register interrupt +handlers for them. A given priority level can be assigned to only one handler. A +dispatcher may register more than one priority level. + +Dispatchers are assigned interrupt priority levels in two steps: + +Partitioning priority levels +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interrupts are associated to dispatchers by way of grouping and assigning +interrupts to a priority level. In other words, all interrupts that are to +target a particular dispatcher should fall in a particular priority level. For +priority assignment: + +- Of the 8 bits of priority that Arm GIC architecture permits, bit 7 must be 0 + (secure space). + +- Depending on the number of dispatchers to support, the platform must choose + to use the top *n* of the 7 remaining bits to identify and assign interrupts + to individual dispatchers. Choosing *n* bits supports up to 2\ :sup:`n` + distinct dispatchers. For example, by choosing 2 additional bits (i.e., bits + 6 and 5), the platform can partition into 4 secure priority ranges: ``0x0``, + ``0x20``, ``0x40``, and ``0x60``. See `Interrupt handling example`_. + +Note: + + The Arm GIC architecture requires that a GIC implementation that supports two + security states must implement at least 32 priority levels; i.e., at least 5 + upper bits of the 8 bits are writeable. In the scheme described above, when + choosing *n* bits for priority range assignment, the platform must ensure + that at least ``n+1`` top bits of GIC priority are writeable. + +The priority thus assigned to an interrupt is also used to determine the +priority of delegated execution in lower ELs. Delegated execution in lower EL is +associated with a priority level chosen with ``ehf_activate_priority()`` API +(described `later`__). The chosen priority level also determines the interrupts +masked while executing in a lower EL, therefore controls preemption of delegated +execution. + +.. __: `ehf-apis`_ + +The platform expresses the chosen priority levels by declaring an array of +priority level descriptors. Each entry in the array is of type +``ehf_pri_desc_t``, and declares a priority level, and shall be populated by the +``EHF_PRI_DESC()`` macro. + +Note: + + The macro ``EHF_PRI_DESC()`` installs the descriptors in the array at a + computed index, and not necessarily where the macro is placed in the array. + The size of the array might therefore be larger than what it appears to be. + The ``ARRAY_SIZE()`` macro therefore should be used to determine the size of + array. + +Finally, this array of descriptors is exposed to |EHF| via the +``EHF_REGISTER_PRIORITIES()`` macro. + +Refer to the `Interrupt handling example`_ for usage. See also: `Interrupt +Prioritisation Considerations`_. + +Programming priority +~~~~~~~~~~~~~~~~~~~~ + +The text in `Partitioning priority levels`_ only describes how the platform +expresses the required levels of priority. It however doesn't choose interrupts +nor program the required priority in GIC. + +The `Firmware Design guide`__ explains methods for configuring secure +interrupts. |EHF| requires the platform to enumerate interrupt properties (as +opposed to just numbers) of Secure interrupts. The priority of secure interrupts +must match that as determined in the `Partitioning priority levels`_ section above. + +.. __: firmware-design.rst#configuring-secure-interrupts + +See `Limitations`_, and also refer to `Interrupt handling example`_ for +illustration. + +Registering handler +------------------- + +Dispatchers register handlers for their priority levels through the following +API: + +.. code:: c + + int ehf_register_priority_handler(int pri, ehf_handler_t handler) + +The API takes two arguments: + +- The priority level for which the handler is being registered; + +- The handler to be registered. The handler must be aligned to 4 bytes. + +If a dispatcher owns more than one priority levels, it has to call the API for +each of them. + +The API will succeed, and return ``0``, only if: + +- There exists a descriptor with the priority level requested. + +- There are no handlers already registered by a previous call to the API. + +Otherwise, the API returns ``-1``. + +The interrupt handler should have the following signature: + +.. code:: c + + typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle, + void *cookie); + +The parameters are as obtained from the top-level `EL3 interrupt handler`__. + +.. __: interrupt-framework-design.rst#el3-runtime-firmware + +The `SDEI dispatcher`__, for example, expects the platform to allocate two +different priority levels—``PLAT_SDEI_CRITICAL_PRI``, and +``PLAT_SDEI_NORMAL_PRI``—and registers the same handler to handle both levels. + +.. __: sdei.rst + +Interrupt handling example +-------------------------- + +The following annotated snippet demonstrates how a platform might choose to +assign interrupts to fictitious dispatchers: + +.. code:: c + + #include + #include + #include + + ... + + /* + * This platform uses 2 bits for interrupt association. In total, 3 upper + * bits are in use. + * + * 7 6 5 3 0 + * .-.-.-.----------. + * |0|b|b| ..0.. | + * '-'-'-'----------' + */ + #define PLAT_PRI_BITS 2 + + /* Priorities for individual dispatchers */ + #define DISP0_PRIO 0x00 /* Not used */ + #define DISP1_PRIO 0x20 + #define DISP2_PRIO 0x40 + #define DISP3_PRIO 0x60 + + /* Install priority level descriptors for each dispatcher */ + ehf_pri_desc_t plat_exceptions[] = { + EHF_PRI_DESC(PLAT_PRI_BITS, DISP1_PRIO), + EHF_PRI_DESC(PLAT_PRI_BITS, DISP2_PRIO), + EHF_PRI_DESC(PLAT_PRI_BITS, DISP3_PRIO), + }; + + /* Expose priority descriptors to Exception Handling Framework */ + EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions), + PLAT_PRI_BITS); + + ... + + /* List interrupt properties for GIC driver. All interrupts target EL3 */ + const interrupt_prop_t plat_interrupts[] = { + /* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */ + INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + + /* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */ + INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + + /* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */ + INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + }; + + ... + + /* Dispatcher 1 registers its handler */ + ehf_register_priority_handler(DISP1_PRIO, disp1_handler); + + /* Dispatcher 2 registers its handler */ + ehf_register_priority_handler(DISP2_PRIO, disp2_handler); + + /* Dispatcher 3 registers its handler */ + ehf_register_priority_handler(DISP3_PRIO, disp3_handler); + + ... + +See also the `Build-time flow`_ and the `Run-time flow`_. + +Activating and Deactivating priorities +-------------------------------------- + +A priority level is said to be *active* when an exception of that priority is +being handled: for interrupts, this is implied when the interrupt is +acknowledged; for non-interrupt exceptions, such as SErrors or `SDEI explicit +dispatches`__, this has to be done via calling ``ehf_activate_priority()``. See +`Run-time flow`_. + +.. __: sdei.rst#explicit-dispatch-of-events + +Conversely, when the dispatcher has reached a logical resolution for the cause +of the exception, the corresponding priority level ought to be deactivated. As +above, for interrupts, this is implied when the interrupt is EOId in the GIC; +for other exceptions, this has to be done via calling +``ehf_deactivate_priority()``. + +Thanks to `different provisions`__ for exception delegation, there are +potentially more than one work flow for deactivation: + +.. __: `delegation-use-cases`_ + +.. _deactivation workflows: + +- The dispatcher has addressed the cause of the exception, and decided to take + no further action. In this case, the dispatcher's handler deactivates the + priority level before returning to the |EHF|. Runtime firmware, upon exit + through an ``ERET``, resumes execution before the interrupt occurred. + +- The dispatcher has to delegate the execution to lower ELs, and the cause of + the exception can be considered resolved only when the lower EL returns + signals complete (via an ``SMC``) at a future point in time. The following + sequence ensues: + + #. The dispatcher calls ``setjmp()`` to setup a jump point, and arranges to + enter a lower EL upon the next ``ERET``. + + #. Through the ensuing ``ERET`` from runtime firmware, execution is delegated + to a lower EL. + + #. The lower EL completes its execution, and signals completion via an + ``SMC``. + + #. The ``SMC`` is handled by the same dispatcher that handled the exception + previously. Noticing the conclusion of exception handling, the dispatcher + does ``longjmp()`` to resume beyond the previous jump point. + +As mentioned above, the |EHF| provides the following APIs for activating and +deactivating interrupt: + +.. _ehf-apis: + +- ``ehf_activate_priority()`` activates the supplied priority level, but only + if the current active priority is higher than the given one; otherwise + panics. Also, to prevent interruption by physical interrupts of lower + priority, the |EHF| programs the *Priority Mask Register* corresponding to + the PE to the priority being activated. Dispatchers typically only need to + call this when handling exceptions other than interrupts, and it needs to + delegate execution to a lower EL at a desired priority level. + +- ``ehf_deactivate_priority()`` deactivates a given priority, but only if the + current active priority is equal to the given one; otherwise panics. |EHF| + also restores the *Priority Mask Register* corresponding to the PE to the + priority before the call to ``ehf_activate_priority()``. Dispatchers + typically only need to call this after handling exceptions other than + interrupts. + +The calling of APIs are subject to allowed `transitions`__. See also the +`Run-time flow`_. + +.. __: `Transition of priority levels`_ + +Transition of priority levels +----------------------------- + +The |EHF| APIs ``ehf_activate_priority()`` and ``ehf_deactivate_priority()`` can +be called to transition the current priority level on a PE. A given sequence of +calls to these APIs are subject to the following conditions: + +- For activation, the |EHF| only allows for the priority to increase (i.e. + numeric value decreases); + +- For deactivation, the |EHF| only allows for the priority to decrease (i.e. + numeric value increases). Additionally, the priority being deactivated is + required to be the current priority. + +If these are violated, a panic will result. + +Effect on SMC calls +------------------- + +In general, Secure execution is regarded as more important than Non-secure +execution. As discussed elsewhere in this document, EL3 execution, and any +delegated execution thereafter, has the effect of raising GIC's priority +mask—either implicitly by acknowledging Secure interrupts, or when dispatchers +call ``ehf_activate_priority()``. As a result, Non-secure interrupts cannot +preempt any Secure execution. + +SMCs from Non-secure world are synchronous exceptions, and are mechanisms for +Non-secure world to request Secure services. They're broadly classified as +*Fast* or *Yielding* (see `SMCCC`__). + +.. __: `http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html` + +- *Fast* SMCs are atomic from the caller's point of view. I.e., they return + to the caller only when the Secure world has finished serving the request. + Any Non-secure interrupts that become pending meanwhile cannot preempt Secure + execution. + +- *Yielding* SMCs carry the semantics of a preemptible, lower-priority request. + A pending Non-secure interrupt can preempt Secure execution handling a + Yielding SMC. I.e., the caller might observe a Yielding SMC returning when + either: + + #. Secure world completes the request, and the caller would find ``SMC_OK`` + as the return code. + + #. A Non-secure interrupt preempts Secure execution. Non-secure interrupt is + handled, and Non-secure execution resumes after ``SMC`` instruction. + + The dispatcher handling a Yielding SMC must provide a different return code + to the Non-secure caller to distinguish the latter case. This return code, + however, is not standardised (unlike ``SMC_UNKNOWN`` or ``SMC_OK``, for + example), so will vary across dispatchers that handle the request. + +For the latter case above, dispatchers before |EHF| expect Non-secure interrupts +to be taken to S-EL1 [#irq]_, so would get a chance to populate the designated +preempted error code before yielding to Non-secure world. + +The introduction of |EHF| changes the behaviour as described in `Interrupt +handling`_. + +When |EHF| is enabled, in order to allow Non-secure interrupts to preempt +Yielding SMC handling, the dispatcher must call ``ehf_allow_ns_preemption()`` +API. The API takes one argument, the error code to be returned to the Non-secure +world upon getting preempted. + +.. [#irq] In case of GICv2, Non-secure interrupts while in S-EL1 were signalled + as IRQs, and in case of GICv3, FIQs. + +Build-time flow +--------------- + +Please refer to the `figure`__ above. + +.. __: `ehf-figure`_ + +The build-time flow involves the following steps: + +#. Platform assigns priorities by installing priority level descriptors for + individual dispatchers, as described in `Partitioning priority levels`_. + +#. Platform provides interrupt properties to GIC driver, as described in + `Programming priority`_. + +#. Dispatcher calling ``ehf_register_priority_handler()`` to register an + interrupt handler. + +Also refer to the `Interrupt handling example`_. + +Run-time flow +------------- + +.. _interrupt-flow: + +The following is an example flow for interrupts: + +#. The GIC driver, during initialization, iterates through the platform-supplied + interrupt properties (see `Programming priority`_), and configures the + interrupts. This programs the appropriate priority and group (Group 0) on + interrupts belonging to different dispatchers. + +#. The |EHF|, during its initialisation, registers a top-level interrupt handler + with the `Interrupt Management Framework`__ for EL3 interrupts. This also + results in setting the routing bits in ``SCR_EL3``. + + .. __: interrupt-framework-design.rst#el3-runtime-firmware + +#. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0 + interrupt, and is taken to EL3. + +#. The top-level EL3 interrupt handler executes. The handler acknowledges the + interrupt, reads its *Running Priority*, and from that, determines the + dispatcher handler. + +#. The |EHF| programs the *Priority Mask Register* of the PE to the priority of + the interrupt received. + +#. The |EHF| marks that priority level *active*, and jumps to the dispatcher + handler. + +#. Once the dispatcher handler finishes its job, it has to immediately + *deactivate* the priority level before returning to the |EHF|. See + `deactivation workflows`_. + +.. _non-interrupt-flow: + +The following is an example flow for exceptions that targets EL3 other than +interrupt: + +#. The platform provides handlers for the specific kind of exception. + +#. The exception arrives, and the corresponding handler is executed. + +#. The handler calls ``ehf_activate_priority()`` to activate the required + priority level. This also has the effect of raising GIC priority mask, thus + preventing interrupts of lower priority from preempting the handling. The + handler may choose to do the handling entirely in EL3 or delegate to a lower + EL. + +#. Once exception handling concludes, the handler calls + ``ehf_deactivate_priority()`` to deactivate the priority level activated + earlier. This also has the effect of lowering GIC priority mask to what it + was before. + +Interrupt Prioritisation Considerations +--------------------------------------- + +The GIC priority scheme, by design, prioritises Secure interrupts over Normal +world ones. The platform further assigns relative priorities amongst Secure +dispatchers through |EHF|. + +As mentioned in `Partitioning priority levels`_, interrupts targeting distinct +dispatchers fall in distinct priority levels. Because they're routed via the +GIC, interrupt delivery to the PE is subject to GIC prioritisation rules. In +particular, when an interrupt is being handled by the PE (i.e., the interrupt is +in *Active* state), only interrupts of higher priority are signalled to the PE, +even if interrupts of same or lower priority are pending. This has the side +effect of one dispatcher being starved of interrupts by virtue of another +dispatcher handling its (higher priority) interrupts. + +The |EHF| doesn't enforce a particular prioritisation policy, but the platform +should carefully consider the assignment of priorities to dispatchers integrated +into runtime firmware. The platform should sensibly delineate priority to +various dispatchers according to their nature. In particular, dispatchers of +critical nature (RAS, for example) should be assigned higher priority than +others (SDEI, for example); and within SDEI, Critical priority SDEI should be +assigned higher priority than Normal ones. + +Limitations +----------- + +The |EHF| has the following limitations: + +- Although there could be up to 128 Secure dispatchers supported by the GIC + priority scheme, the size of descriptor array exposed with + ``EHF_REGISTER_PRIORITIES()`` macro is currently limited to 32. This serves most + expected use cases. This may be expanded in the future, should use cases + demand so. + +- The platform must ensure that the priority assigned to the dispatcher in the + exception descriptor and the programmed priority of interrupts handled by the + dispatcher match. The |EHF| cannot verify that this has been followed. + +---- + +*Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.* + +.. _Interrupt Framework Design: interrupt-framework-design.rst +.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf diff --git a/docs/components/firmware-update.rst b/docs/components/firmware-update.rst new file mode 100644 index 0000000..f3ad6af --- /dev/null +++ b/docs/components/firmware-update.rst @@ -0,0 +1,411 @@ +Trusted Firmware-A - Firmware Update design guide +================================================= + + + + +.. contents:: + +-------------- + +Introduction +------------ + +This document describes the design of the Firmware Update (FWU) feature, which +enables authenticated firmware to update firmware images from external +interfaces such as USB, UART, SD-eMMC, NAND, NOR or Ethernet to SoC Non-Volatile +memories such as NAND Flash, LPPDR2-NVM or any memory determined by the +platform. This feature functions even when the current firmware in the system +is corrupt or missing; it therefore may be used as a recovery mode. It may also +be complemented by other, higher level firmware update software. + +FWU implements a specific part of the Trusted Board Boot Requirements (TBBR) +specification, Arm DEN0006C-1. It should be used in conjunction with the +`Trusted Board Boot`_ design document, which describes the image authentication +parts of the Trusted Firmware-A (TF-A) TBBR implementation. + +Scope +~~~~~ + +This document describes the secure world FWU design. It is beyond its scope to +describe how normal world FWU images should operate. To implement normal world +FWU images, please refer to the "Non-Trusted Firmware Updater" requirements in +the TBBR. + +FWU Overview +------------ + +The FWU boot flow is primarily mediated by BL1. Since BL1 executes in ROM, and +it is usually desirable to minimize the amount of ROM code, the design allows +some parts of FWU to be implemented in other secure and normal world images. +Platform code may choose which parts are implemented in which images but the +general expectation is: + +- BL1 handles: + + - Detection and initiation of the FWU boot flow. + - Copying images from non-secure to secure memory + - FWU image authentication + - Context switching between the normal and secure world during the FWU + process. + +- Other secure world FWU images handle platform initialization required by + the FWU process. +- Normal world FWU images handle loading of firmware images from external + interfaces to non-secure memory. + +The primary requirements of the FWU feature are: + +#. Export a BL1 SMC interface to interoperate with other FWU images executing + at other Exception Levels. +#. Export a platform interface to provide FWU common code with the information + it needs, and to enable platform specific FWU functionality. See the + `Porting Guide`_ for details of this interface. + +TF-A uses abbreviated image terminology for FWU images like for other TF-A +images. An overview of this terminology can be found `here`_. + +The following diagram shows the FWU boot flow for Arm development platforms. +Arm CSS platforms like Juno have a System Control Processor (SCP), and these +use all defined FWU images. Other platforms may use a subset of these. + +|Flow Diagram| + +Image Identification +-------------------- + +Each FWU image and certificate is identified by a unique ID, defined by the +platform, which BL1 uses to fetch an image descriptor (``image_desc_t``) via a +call to ``bl1_plat_get_image_desc()``. The same ID is also used to prepare the +Chain of Trust (Refer to the `Authentication Framework Design`_ +for more information). + +The image descriptor includes the following information: + +- Executable or non-executable image. This indicates whether the normal world + is permitted to request execution of a secure world FWU image (after + authentication). Secure world certificates and non-AP images are examples + of non-executable images. +- Secure or non-secure image. This indicates whether the image is + authenticated/executed in secure or non-secure memory. +- Image base address and size. +- Image entry point configuration (an ``entry_point_info_t``). +- FWU image state. + +BL1 uses the FWU image descriptors to: + +- Validate the arguments of FWU SMCs +- Manage the state of the FWU process +- Initialize the execution state of the next FWU image. + +FWU State Machine +----------------- + +BL1 maintains state for each FWU image during FWU execution. FWU images at lower +Exception Levels raise SMCs to invoke FWU functionality in BL1, which causes +BL1 to update its FWU image state. The BL1 image states and valid state +transitions are shown in the diagram below. Note that secure images have a more +complex state machine than non-secure images. + +|FWU state machine| + +The following is a brief description of the supported states: + +- RESET: This is the initial state of every image at the start of FWU. + Authentication failure also leads to this state. A secure + image may yield to this state if it has completed execution. + It can also be reached by using ``FWU_SMC_IMAGE_RESET``. + +- COPYING: This is the state of a secure image while BL1 is copying it + in blocks from non-secure to secure memory. + +- COPIED: This is the state of a secure image when BL1 has completed + copying it to secure memory. + +- AUTHENTICATED: This is the state of an image when BL1 has successfully + authenticated it. + +- EXECUTED: This is the state of a secure, executable image when BL1 has + passed execution control to it. + +- INTERRUPTED: This is the state of a secure, executable image after it has + requested BL1 to resume normal world execution. + +BL1 SMC Interface +----------------- + +BL1_SMC_CALL_COUNT +~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x0 + + Return: + uint32_t + +This SMC returns the number of SMCs supported by BL1. + +BL1_SMC_UID +~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x1 + + Return: + UUID : 32 bits in each of w0-w3 (or r0-r3 for AArch32 callers) + +This SMC returns the 128-bit `Universally Unique Identifier`_ for the +BL1 SMC service. + +BL1_SMC_VERSION +~~~~~~~~~~~~~~~ + +:: + + Argument: + uint32_t function ID : 0x3 + + Return: + uint32_t : Bits [31:16] Major Version + Bits [15:0] Minor Version + +This SMC returns the current version of the BL1 SMC service. + +BL1_SMC_RUN_IMAGE +~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x4 + entry_point_info_t *ep_info + + Return: + void + + Pre-conditions: + if (normal world caller) synchronous exception + if (ep_info not EL3) synchronous exception + +This SMC passes execution control to an EL3 image described by the provided +``entry_point_info_t`` structure. In the normal TF-A boot flow, BL2 invokes +this SMC for BL1 to pass execution control to BL31. + +FWU_SMC_IMAGE_COPY +~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x10 + unsigned int image_id + uintptr_t image_addr + unsigned int block_size + unsigned int image_size + + Return: + int : 0 (Success) + : -ENOMEM + : -EPERM + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (image_id is non-secure image) return -EPERM + if (image_id state is not (RESET or COPYING)) return -EPERM + if (secure world caller) return -EPERM + if (image_addr + block_size overflows) return -ENOMEM + if (image destination address + image_size overflows) return -ENOMEM + if (source block is in secure memory) return -ENOMEM + if (source block is not mapped into BL1) return -ENOMEM + if (image_size > free secure memory) return -ENOMEM + if (image overlaps another image) return -EPERM + +This SMC copies the secure image indicated by ``image_id`` from non-secure memory +to secure memory for later authentication. The image may be copied in a single +block or multiple blocks. In either case, the total size of the image must be +provided in ``image_size`` when invoking this SMC for the first time for each +image; it is ignored in subsequent calls (if any) for the same image. + +The ``image_addr`` and ``block_size`` specify the source memory block to copy from. +The destination address is provided by the platform code. + +If ``block_size`` is greater than the amount of remaining bytes to copy for this +image then the former is truncated to the latter. The copy operation is then +considered as complete and the FWU state machine transitions to the "COPIED" +state. If there is still more to copy, the FWU state machine stays in or +transitions to the COPYING state (depending on the previous state). + +When using multiple blocks, the source blocks do not necessarily need to be in +contiguous memory. + +Once the SMC is handled, BL1 returns from exception to the normal world caller. + +FWU_SMC_IMAGE_AUTH +~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x11 + unsigned int image_id + uintptr_t image_addr + unsigned int image_size + + Return: + int : 0 (Success) + : -ENOMEM + : -EPERM + : -EAUTH + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (secure world caller) + if (image_id state is not RESET) return -EPERM + if (image_addr/image_size is not mapped into BL1) return -ENOMEM + else // normal world caller + if (image_id is secure image) + if (image_id state is not COPIED) return -EPERM + else // image_id is non-secure image + if (image_id state is not RESET) return -EPERM + if (image_addr/image_size is in secure memory) return -ENOMEM + if (image_addr/image_size not mapped into BL1) return -ENOMEM + +This SMC authenticates the image specified by ``image_id``. If the image is in the +RESET state, BL1 authenticates the image in place using the provided +``image_addr`` and ``image_size``. If the image is a secure image in the COPIED +state, BL1 authenticates the image from the secure memory that BL1 previously +copied the image into. + +BL1 returns from exception to the caller. If authentication succeeds then BL1 +sets the image state to AUTHENTICATED. If authentication fails then BL1 returns +the -EAUTH error and sets the image state back to RESET. + +FWU_SMC_IMAGE_EXECUTE +~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x12 + unsigned int image_id + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (secure world caller) return -EPERM + if (image_id is non-secure image) return -EPERM + if (image_id is non-executable image) return -EPERM + if (image_id state is not AUTHENTICATED) return -EPERM + +This SMC initiates execution of a previously authenticated image specified by +``image_id``, in the other security world to the caller. The current +implementation only supports normal world callers initiating execution of a +secure world image. + +BL1 saves the normal world caller's context, sets the secure image state to +EXECUTED, and returns from exception to the secure image. + +FWU_SMC_IMAGE_RESUME +~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x13 + register_t image_param + + Return: + register_t : image_param (Success) + : -EPERM + + Pre-conditions: + if (normal world caller and no INTERRUPTED secure image) return -EPERM + +This SMC resumes execution in the other security world while there is a secure +image in the EXECUTED/INTERRUPTED state. + +For normal world callers, BL1 sets the previously interrupted secure image state +to EXECUTED. For secure world callers, BL1 sets the previously executing secure +image state to INTERRUPTED. In either case, BL1 saves the calling world's +context, restores the resuming world's context and returns from exception into +the resuming world. If the call is successful then the caller provided +``image_param`` is returned to the resumed world, otherwise an error code is +returned to the caller. + +FWU_SMC_SEC_IMAGE_DONE +~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x14 + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (normal world caller) return -EPERM + +This SMC indicates completion of a previously executing secure image. + +BL1 sets the previously executing secure image state to the RESET state, +restores the normal world context and returns from exception into the normal +world. + +FWU_SMC_UPDATE_DONE +~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x15 + register_t client_cookie + + Return: + N/A + +This SMC completes the firmware update process. BL1 calls the platform specific +function ``bl1_plat_fwu_done``, passing the optional argument ``client_cookie`` as +a ``void *``. The SMC does not return. + +FWU_SMC_IMAGE_RESET +~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x16 + unsigned int image_id + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (secure world caller) return -EPERM + if (image in EXECUTED) return -EPERM + +This SMC sets the state of an image to RESET and zeroes the memory used by it. + +This is only allowed if the image is not being executed. + +-------------- + +*Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.* + +.. _Trusted Board Boot: ./trusted-board-boot.rst +.. _Porting Guide: ../getting_started/porting-guide.rst +.. _here: https://github.com/ARM-software/arm-trusted-firmware/wiki/ARM-Trusted-Firmware-Image-Terminology +.. _Authentication Framework Design: ./auth-framework.rst +.. _Universally Unique Identifier: https://tools.ietf.org/rfc/rfc4122.txt + +.. |Flow Diagram| image:: diagrams/fwu_flow.png?raw=true +.. |FWU state machine| image:: diagrams/fwu_states.png?raw=true diff --git a/docs/components/index.rst b/docs/components/index.rst new file mode 100644 index 0000000..f1904c0 --- /dev/null +++ b/docs/components/index.rst @@ -0,0 +1,18 @@ +Components +========== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + spd/index + arm-sip-service + exception-handling + firmware-update + platform-interrupt-controller-API + ras + romlib-design + sdei + secure-partition-manager-design + xlat-tables-lib-v2-design diff --git a/docs/components/platform-interrupt-controller-API.rst b/docs/components/platform-interrupt-controller-API.rst new file mode 100644 index 0000000..42d92be --- /dev/null +++ b/docs/components/platform-interrupt-controller-API.rst @@ -0,0 +1,312 @@ +Platform Interrupt Controller API documentation +=============================================== + + + +.. contents:: + +This document lists the optional platform interrupt controller API that +abstracts the runtime configuration and control of interrupt controller from the +generic code. The mandatory APIs are described in the `porting guide`__. + +.. __: ../getting_started/porting-guide.rst#interrupt-management-framework-in-bl31 + +Function: unsigned int plat_ic_get_running_priority(void); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This API should return the priority of the interrupt the PE is currently +servicing. This must be be called only after an interrupt has already been +acknowledged via ``plat_ic_acknowledge_interrupt``. + +In the case of Arm standard platforms using GIC, the *Running Priority Register* +is read to determine the priority of the interrupt. + +Function: int plat_ic_is_spi(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +The API should return whether the interrupt ID (first parameter) is categorized +as a Shared Peripheral Interrupt. Shared Peripheral Interrupts are typically +associated to system-wide peripherals, and these interrupts can target any PE in +the system. + +Function: int plat_ic_is_ppi(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +The API should return whether the interrupt ID (first parameter) is categorized +as a Private Peripheral Interrupt. Private Peripheral Interrupts are typically +associated with peripherals that are private to each PE. Interrupts from private +peripherals target to that PE only. + +Function: int plat_ic_is_sgi(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +The API should return whether the interrupt ID (first parameter) is categorized +as a Software Generated Interrupt. Software Generated Interrupts are raised by +explicit programming by software, and are typically used in inter-PE +communication. Secure SGIs are reserved for use by Secure world software. + +Function: unsigned int plat_ic_get_interrupt_active(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This API should return the *active* status of the interrupt ID specified by the +first parameter, ``id``. + +In case of Arm standard platforms using GIC, the implementation of the API reads +the GIC *Set Active Register* to read and return the active status of the +interrupt. + +Function: void plat_ic_enable_interrupt(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should enable the interrupt ID specified by the first parameter, +``id``. PEs in the system are expected to receive only enabled interrupts. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts barrier to make memory updates visible before enabling interrupt, and +then writes to GIC *Set Enable Register* to enable the interrupt. + +Function: void plat_ic_disable_interrupt(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should disable the interrupt ID specified by the first parameter, +``id``. PEs in the system are not expected to receive disabled interrupts. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to GIC *Clear Enable Register* to disable the interrupt, and inserts +barrier to make memory updates visible afterwards. + +Function: void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Argument : unsigned int + Return : void + +This API should set the priority of the interrupt specified by first parameter +``id`` to the value set by the second parameter ``priority``. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to GIC *Priority Register* set interrupt priority. + +Function: int plat_ic_has_interrupt_type(unsigned int type); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This API should return whether the platform supports a given interrupt type. The +parameter ``type`` shall be one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1``, or +``INTR_TYPE_NS``. + +In case of Arm standard platforms using GICv3, the implementation of the API +returns ``1`` for all interrupt types. + +In case of Arm standard platforms using GICv2, the API always return ``1`` for +``INTR_TYPE_NS``. Return value for other types depends on the value of build +option ``GICV2_G0_FOR_EL3``: + +- For interrupt type ``INTR_TYPE_EL3``: + + - When ``GICV2_G0_FOR_EL3`` is ``0``, it returns ``0``, indicating no support + for EL3 interrupts. + + - When ``GICV2_G0_FOR_EL3`` is ``1``, it returns ``1``, indicating support for + EL3 interrupts. + +- For interrupt type ``INTR_TYPE_S_EL1``: + + - When ``GICV2_G0_FOR_EL3`` is ``0``, it returns ``1``, indicating support for + Secure EL1 interrupts. + + - When ``GICV2_G0_FOR_EL3`` is ``1``, it returns ``0``, indicating no support + for Secure EL1 interrupts. + +Function: void plat_ic_set_interrupt_type(unsigned int id, unsigned int type); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Argument : unsigned int + Return : void + +This API should set the interrupt specified by first parameter ``id`` to the +type specified by second parameter ``type``. The ``type`` parameter can be +one of: + +- ``INTR_TYPE_NS``: interrupt is meant to be consumed by the Non-secure world. + +- ``INTR_TYPE_S_EL1``: interrupt is meant to be consumed by Secure EL1. + +- ``INTR_TYPE_EL3``: interrupt is meant to be consumed by EL3. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to the GIC *Group Register* and *Group Modifier Register* (only GICv3) to +assign the interrupt to the right group. + +For GICv3: + +- ``INTR_TYPE_NS`` maps to Group 1 interrupt. + +- ``INTR_TYPE_S_EL1`` maps to Secure Group 1 interrupt. + +- ``INTR_TYPE_EL3`` maps to Secure Group 0 interrupt. + +For GICv2: + +- ``INTR_TYPE_NS`` maps to Group 1 interrupt. + +- When the build option ``GICV2_G0_FOR_EL3`` is set to ``0`` (the default), + ``INTR_TYPE_S_EL1`` maps to Group 0. Otherwise, ``INTR_TYPE_EL3`` maps to + Group 0 interrupt. + +Function: void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : u_register_t + Return : void + +This API should raise an EL3 SGI. The first parameter, ``sgi_num``, specifies +the ID of the SGI. The second parameter, ``target``, must be the MPIDR of the +target PE. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts barrier to make memory updates visible before raising SGI, then writes +to appropriate *SGI Register* in order to raise the EL3 SGI. + +Function: void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, u_register_t mpidr); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Argument : unsigned int + Argument : u_register_t + Return : void + +This API should set the routing mode of Share Peripheral Interrupt (SPI) +specified by first parameter ``id`` to that specified by the second parameter +``routing_mode``. + +The ``routing_mode`` parameter can be one of: + +- ``INTR_ROUTING_MODE_ANY`` means the interrupt can be routed to any PE in the + system. The ``mpidr`` parameter is ignored in this case. + +- ``INTR_ROUTING_MODE_PE`` means the interrupt is routed to the PE whose MPIDR + value is specified by the parameter ``mpidr``. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to the GIC *Target Register* (GICv2) or *Route Register* (GICv3) to set +the routing. + +Function: void plat_ic_set_interrupt_pending(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should set the interrupt specified by first parameter ``id`` to +*Pending*. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts barrier to make memory updates visible before setting interrupt pending, +and writes to the GIC *Set Pending Register* to set the interrupt pending +status. + +Function: void plat_ic_clear_interrupt_pending(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should clear the *Pending* status of the interrupt specified by first +parameter ``id``. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to the GIC *Clear Pending Register* to clear the interrupt pending +status, and inserts barrier to make memory updates visible afterwards. + +Function: unsigned int plat_ic_set_priority_mask(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This API should set the priority mask (first parameter) in the interrupt +controller such that only interrupts of higher priority than the supplied one +may be signalled to the PE. The API should return the current priority value +that it's overwriting. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts to order memory updates before updating mask, then writes to the GIC +*Priority Mask Register*, and make sure memory updates are visible before +potential trigger due to mask update. + +Function: unsigned int plat_ic_get_interrupt_id(unsigned int raw); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : unsigned int + +This API should extract and return the interrupt number from the raw value +obtained by the acknowledging the interrupt (read using +``plat_ic_acknowledge_interrupt()``). If the interrupt ID is invalid, this API +should return ``INTR_ID_UNAVAILABLE``. + +In case of Arm standard platforms using GIC, the implementation of the API +masks out the interrupt ID field from the acknowledged value from GIC. + +---- + +*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* diff --git a/docs/components/ras.rst b/docs/components/ras.rst new file mode 100644 index 0000000..f329fb0 --- /dev/null +++ b/docs/components/ras.rst @@ -0,0 +1,257 @@ +RAS support in Trusted Firmware-A +================================= + + + +.. contents:: + :depth: 2 + +.. |EHF| replace:: Exception Handling Framework +.. |TF-A| replace:: Trusted Firmware-A + +This document describes |TF-A| support for Arm Reliability, Availability, and +Serviceability (RAS) extensions. RAS is a mandatory extension for Armv8.2 and +later CPUs, and also an optional extension to the base Armv8.0 architecture. + +In conjunction with the |EHF|, support for RAS extension enables firmware-first +paradigm for handling platform errors: exceptions resulting from errors are +routed to and handled in EL3. Said errors are Synchronous External Abort (SEA), +Asynchronous External Abort (signalled as SErrors), Fault Handling and Error +Recovery interrupts. The |EHF| document mentions various `error handling +use-cases`__. + +.. __: exception-handling.rst#delegation-use-cases + +For the description of Arm RAS extensions, Standard Error Records, and the +precise definition of RAS terminology, please refer to the Arm Architecture +Reference Manual. The rest of this document assumes familiarity with +architecture and terminology. + +Overview +-------- + +As mentioned above, the RAS support in |TF-A| enables routing to and handling of +exceptions resulting from platform errors in EL3. It allows the platform to +define an External Abort handler, and to register RAS nodes and interrupts. RAS +framework also provides `helpers`__ for accessing Standard Error Records as +introduced by the RAS extensions. + +.. __: `Standard Error Record helpers`_ + +The build option ``RAS_EXTENSION`` when set to ``1`` includes the RAS in run +time firmware; ``EL3_EXCEPTION_HANDLING`` and ``HANDLE_EA_EL3_FIRST`` must also +be set ``1``. + +.. _ras-figure: + +.. image:: ../draw.io/ras.svg + +See more on `Engaging the RAS framework`_. + +Platform APIs +------------- + +The RAS framework allows the platform to define handlers for External Abort, +Uncontainable Errors, Double Fault, and errors rising from EL3 execution. Please +refer to the porting guide for the `RAS platform API descriptions`__. + +.. __: ../getting_started/porting-guide.rst#external-abort-handling-and-ras-support + +Registering RAS error records +----------------------------- + +RAS nodes are components in the system capable of signalling errors to PEs +through one one of the notification mechanisms—SEAs, SErrors, or interrupts. RAS +nodes contain one or more error records, which are registers through which the +nodes advertise various properties of the signalled error. Arm recommends that +error records are implemented in the Standard Error Record format. The RAS +architecture allows for error records to be accessible via system or +memory-mapped registers. + +The platform should enumerate the error records providing for each of them: + +- A handler to probe error records for errors; +- When the probing identifies an error, a handler to handle it; +- For memory-mapped error record, its base address and size in KB; for a system + register-accessed record, the start index of the record and number of + continuous records from that index; +- Any node-specific auxiliary data. + +With this information supplied, when the run time firmware receives one of the +notification mechanisms, the RAS framework can iterate through and probe error +records for error, and invoke the appropriate handler to handle it. + +The RAS framework provides the macros to populate error record information. The +macros are versioned, and the latest version as of this writing is 1. These +macros create a structure of type ``struct err_record_info`` from its arguments, +which are later passed to probe and error handlers. + +For memory-mapped error records: + +.. code:: c + + ERR_RECORD_MEMMAP_V1(base_addr, size_num_k, probe, handler, aux) + +And, for system register ones: + +.. code:: c + + ERR_RECORD_SYSREG_V1(idx_start, num_idx, probe, handler, aux) + +The probe handler must have the following prototype: + +.. code:: c + + typedef int (*err_record_probe_t)(const struct err_record_info *info, + int *probe_data); + +The probe handler must return a non-zero value if an error was detected, or 0 +otherwise. The ``probe_data`` output parameter can be used to pass any useful +information resulting from probe to the error handler (see `below`__). For +example, it could return the index of the record. + +.. __: `Standard Error Record helpers`_ + +The error handler must have the following prototype: + +.. code:: c + + typedef int (*err_record_handler_t)(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data); + +The ``data`` constant parameter describes the various properties of the error, +including the reason for the error, exception syndrome, and also ``flags``, +``cookie``, and ``handle`` parameters from the `top-level exception handler`__. + +.. __: interrupt-framework-design.rst#el3-interrupts + +The platform is expected populate an array using the macros above, and register +the it with the RAS framework using the macro ``REGISTER_ERR_RECORD_INFO()``, +passing it the name of the array describing the records. Note that the macro +must be used in the same file where the array is defined. + +Standard Error Record helpers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The |TF-A| RAS framework provides probe handlers for Standard Error Records, for +both memory-mapped and System Register accesses: + +.. code:: c + + int ras_err_ser_probe_memmap(const struct err_record_info *info, + int *probe_data); + + int ras_err_ser_probe_sysreg(const struct err_record_info *info, + int *probe_data); + +When the platform enumerates error records, for those records in the Standard +Error Record format, these helpers maybe used instead of rolling out their own. +Both helpers above: + +- Return non-zero value when an error is detected in a Standard Error Record; +- Set ``probe_data`` to the index of the error record upon detecting an error. + +Registering RAS interrupts +-------------------------- + +RAS nodes can signal errors to the PE by raising Fault Handling and/or Error +Recovery interrupts. For the firmware-first handling paradigm for interrupts to +work, the platform must setup and register with |EHF|. See `Interaction with +Exception Handling Framework`_. + +For each RAS interrupt, the platform has to provide structure of type ``struct +ras_interrupt``: + +- Interrupt number; +- The associated error record information (pointer to the corresponding + ``struct err_record_info``); +- Optionally, a cookie. + +The platform is expected to define an array of ``struct ras_interrupt``, and +register it with the RAS framework using the macro +``REGISTER_RAS_INTERRUPTS()``, passing it the name of the array. Note that the +macro must be used in the same file where the array is defined. + +The array of ``struct ras_interrupt`` must be sorted in the increasing order of +interrupt number. This allows for fast look of handlers in order to service RAS +interrupts. + +Double-fault handling +--------------------- + +A Double Fault condition arises when an error is signalled to the PE while +handling of a previously signalled error is still underway. When a Double Fault +condition arises, the Arm RAS extensions only require for handler to perform +orderly shutdown of the system, as recovery may be impossible. + +The RAS extensions part of Armv8.4 introduced new architectural features to deal +with Double Fault conditions, specifically, the introduction of ``NMEA`` and +``EASE`` bits to ``SCR_EL3`` register. These were introduced to assist EL3 +software which runs part of its entry/exit routines with exceptions momentarily +masked—meaning, in such systems, External Aborts/SErrors are not immediately +handled when they occur, but only after the exceptions are unmasked again. + +|TF-A|, for legacy reasons, executes entire EL3 with all exceptions unmasked. +This means that all exceptions routed to EL3 are handled immediately. |TF-A| +thus is able to detect a Double Fault conditions in software, without needing +the intended advantages of Armv8.4 Double Fault architecture extensions. + +Double faults are fatal, and terminate at the platform double fault handler, and +doesn't return. + +Engaging the RAS framework +-------------------------- + +Enabling RAS support is a platform choice constructed from three distinct, but +related, build options: + +- ``RAS_EXTENSION=1`` includes the RAS framework in the run time firmware; + +- ``EL3_EXCEPTION_HANDLING=1`` enables handling of exceptions at EL3. See + `Interaction with Exception Handling Framework`_; + +- ``HANDLE_EA_EL3_FIRST=1`` enables routing of External Aborts and SErrors to + EL3. + +The RAS support in |TF-A| introduces a default implementation of +``plat_ea_handler``, the External Abort handler in EL3. When ``RAS_EXTENSION`` +is set to ``1``, it'll first call ``ras_ea_handler()`` function, which is the +top-level RAS exception handler. ``ras_ea_handler`` is responsible for iterating +to through platform-supplied error records, probe them, and when an error is +identified, look up and invoke the corresponding error handler. + +Note that, if the platform chooses to override the ``plat_ea_handler`` function +and intend to use the RAS framework, it must explicitly call +``ras_ea_handler()`` from within. + +Similarly, for RAS interrupts, the framework defines +``ras_interrupt_handler()``. The RAS framework arranges for it to be invoked +when a RAS interrupt taken at EL3. The function bisects the platform-supplied +sorted array of interrupts to look up the error record information associated +with the interrupt number. That error handler for that record is then invoked to +handle the error. + +Interaction with Exception Handling Framework +--------------------------------------------- + +As mentioned in earlier sections, RAS framework interacts with the |EHF| to +arbitrate handling of RAS exceptions with others that are routed to EL3. This +means that the platform must partition a `priority level`__ for handling RAS +exceptions. The platform must then define the macro ``PLAT_RAS_PRI`` to the +priority level used for RAS exceptions. Platforms would typically want to +allocate the highest secure priority for RAS handling. + +.. __: exception-handling.rst#partitioning-priority-levels + +Handling of both `interrupt`__ and `non-interrupt`__ exceptions follow the +sequences outlined in the |EHF| documentation. I.e., for interrupts, the +priority management is implicit; but for non-interrupt exceptions, they're +explicit using `EHF APIs`__. + +.. __: exception-handling.rst#interrupt-flow +.. __: exception-handling.rst#non-interrupt-flow +.. __: exception-handling.rst#activating-and-deactivating-priorities + +---- + +*Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.* diff --git a/docs/components/romlib-design.rst b/docs/components/romlib-design.rst new file mode 100644 index 0000000..4195721 --- /dev/null +++ b/docs/components/romlib-design.rst @@ -0,0 +1,133 @@ +Library at ROM +============== + +.. section-numbering:: + :suffix: . + +.. contents:: + +This document provides an overview of the "library at ROM" implementation in +Trusted Firmware-A (TF-A). + +Introduction +~~~~~~~~~~~~ + +The "library at ROM" feature allows platforms to build a library of functions to +be placed in ROM. This reduces SRAM usage by utilising the available space in +ROM. The "library at ROM" contains a jump table with the list of functions that +are placed in ROM. The capabilities of the "library at ROM" are: + +1. Functions can be from one or several libraries. + +2. Functions can be patched after they have been programmed into ROM. + +3. Platform-specific libraries can be placed in ROM. + +4. Functions can be accessed by one or more BL images. + +Index file +~~~~~~~~~~ + +.. image:: diagrams/romlib_design.png + :width: 600 + +Library at ROM is described by an index file with the list of functions to be +placed in ROM. The index file is platform specific and its format is: + +:: + + lib function [patch] + + lib -- Name of the library the function belongs to + function -- Name of the function to be placed in library at ROM + [patch] -- Option to patch the function + +It is also possible to insert reserved spaces in the list by using the keyword +"reserved" rather than the "lib" and "function" names as shown below: + +:: + + reserved reserved + +The reserved spaces can be used to add more functions in the future without +affecting the order and location of functions already existing in the jump +table. Also, for additional flexibility and modularity, the index file can +include other index files. + +For an index file example, refer to ``lib/romlib/jmptbl.i``. + +Wrapper functions +~~~~~~~~~~~~~~~~~ + +.. image:: diagrams/romlib_wrapper.png + :width: 600 + +When invoking a function of the "library at ROM", the calling sequence is as +follows: + +BL image --> wrapper function --> jump table entry --> library at ROM + +The index file is used to create a jump table which is placed in ROM. Then, the +wrappers refer to the jump table to call the "library at ROM" functions. The +wrappers essentially contain a branch instruction to the jump table entry +corresponding to the original function. Finally, the original function in the BL +image(s) is replaced with the wrapper function. + +The "library at ROM" contains a necessary init function that initialises the +global variables defined by the functions inside "library at ROM". + +Scripts +~~~~~~~ + +There are several scripts that generate the necessary files for the "library at +ROM" to work: + +1. ``gentbl.sh`` - Generates the jump table by parsing the index file. + +2. ``genvar.sh`` - Generates the jump table global variable (**not** the jump + table itself) with the absolute address in ROM. This global variable is, + basically, a pointer to the jump table. + +3. ``genwrappers.sh`` - Generates a wrapper function for each entry in the index + file except for the ones that contain the keyword ``patch``. The generated + wrapper file is called ``_.S``. + +Patching of functions in library at ROM +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``genwrappers.sh`` script does not generate wrappers for the entries in the +index file that contain the keyword ``patch``. Thus, it allows calling the +function from the actual library by breaking the link to the "library at ROM" +version of this function. + +The calling sequence for a patched function is as follows: + +BL image --> function + +Build library at ROM +~~~~~~~~~~~~~~~~~~~~~ + +The environment variable ``CROSS_COMPILE`` must be set as per the user guide. +In the below example the usage of ROMLIB together with mbed TLS is demonstrated +to showcase the benefits of library at ROM - it's not mandatory. + +:: + + make PLAT=fvp \ + MBEDTLS_DIR= \ + TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33= \ + USE_ROMLIB=1 \ + all fip + +Known issue +----------- +When building library at ROM, a clean build is always required. This is +necessary when changes are made to the index files, e.g. adding new functions, +patching existing ones etc. + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/docs/components/sdei.rst b/docs/components/sdei.rst new file mode 100644 index 0000000..aca1ccb --- /dev/null +++ b/docs/components/sdei.rst @@ -0,0 +1,375 @@ +SDEI: Software Delegated Exception Interface +============================================ + +.. contents:: + :depth: 2 + +This document provides an overview of the SDEI dispatcher implementation in +Trusted Firmware-A (TF-A). + +Introduction +------------ + +`Software Delegated Exception Interface`_ (SDEI) is an Arm specification for +Non-secure world to register handlers with firmware to receive notifications +about system events. Firmware will first receive the system events by way of +asynchronous exceptions and, in response, arranges for the registered handler to +execute in the Non-secure EL. + +Normal world software that interacts with the SDEI dispatcher (makes SDEI +requests and receives notifications) is referred to as the *SDEI Client*. A +client receives the event notification at the registered handler even when it +was executing with exceptions masked. The list of SDEI events available to the +client are specific to the platform [#std-event]_. See also `Determining client +EL`_. + +.. _general SDEI dispatch: + +The following figure depicts a general sequence involving SDEI client executing +at EL2 and an event dispatch resulting from the triggering of a bound interrupt. +A commentary is provided below: + +.. image:: ../plantuml/sdei_general.svg + +As part of initialisation, the SDEI client binds a Non-secure interrupt [1], and +the SDEI dispatcher returns a platform dynamic event number [2]. The client then +registers a handler for that event [3], enables the event [5], and unmasks all +events on the current PE [7]. This sequence is typical of an SDEI client, but it +may involve additional SDEI calls. + +At a later point in time, when the bound interrupt triggers [9], it's trapped to +EL3. The interrupt is handed over to the SDEI dispatcher, which then arranges to +execute the registered handler [10]. The client terminates its execution with +``SDEI_EVENT_COMPLETE`` [11], following which the dispatcher resumes the +original EL2 execution [13]. Note that the SDEI interrupt remains active until +the client handler completes, at which point EL3 does EOI [12]. + +Other than events bound to interrupts (as depicted in the sequence above, SDEI +events can be explicitly dispatched in response to other exceptions, for +example, upon receiving an *SError* or *Synchronous External Abort*. See +`Explicit dispatch of events`_. + +The remainder of this document only discusses the design and implementation of +SDEI dispatcher in TF-A, and assumes that the reader is familiar with the SDEI +specification, the interfaces, and their requirements. + +.. [#std-event] Except event 0, which is defined by the SDEI specification as a + standard event. + +Defining events +--------------- + +A platform choosing to include the SDEI dispatcher must also define the events +available on the platform, along with their attributes. + +The platform is expected to provide two arrays of event descriptors: one for +private events, and another for shared events. The SDEI dispatcher provides +``SDEI_PRIVATE_EVENT()`` and ``SDEI_SHARED_EVENT()`` macros to populate the +event descriptors. Both macros take 3 arguments: + +- The event number: this must be a positive 32-bit integer. + +- For an event that has a backing interrupt, the interrupt number the event is + bound to: + + - If it's not applicable to an event, this shall be left as ``0``. + + - If the event is dynamic, this should be specified as ``SDEI_DYN_IRQ``. + +- A bit map of `Event flags`_. + +To define event 0, the macro ``SDEI_DEFINE_EVENT_0()`` should be used. This +macro takes only one parameter: an SGI number to signal other PEs. + +To define an event that's meant to be `explicitly dispatched`__ (i.e., not as a +result of receiving an SDEI interrupt), the macro ``SDEI_EXPLICIT_EVENT()`` +should be used. It accepts two parameters: + +.. __: `Explicit dispatch of events`_ + +- The event number (as above); + +- Event priority: ``SDEI_MAPF_CRITICAL`` or ``SDEI_MAPF_NORMAL``, as described + below. + +Once the event descriptor arrays are defined, they should be exported to the +SDEI dispatcher using the ``REGISTER_SDEI_MAP()`` macro, passing it the pointers +to the private and shared event descriptor arrays, respectively. Note that the +``REGISTER_SDEI_MAP()`` macro must be used in the same file where the arrays are +defined. + +Regarding event descriptors: + +- For Event 0: + + - There must be exactly one descriptor in the private array, and none in the + shared array. + + - The event should be defined using ``SDEI_DEFINE_EVENT_0()``. + + - Must be bound to a Secure SGI on the platform. + +- Explicit events should only be used in the private array. + +- Statically bound shared and private interrupts must be bound to shared and + private interrupts on the platform, respectively. See the section on + `interrupt configuration`__. + + .. __: `Configuration within Exception Handling Framework`_ + +- Both arrays should be one-dimensional. The ``REGISTER_SDEI_MAP()`` macro + takes care of replicating private events for each PE on the platform. + +- Both arrays must be sorted in the increasing order of event number. + +The SDEI specification doesn't have provisions for discovery of available events +on the platform. The list of events made available to the client, along with +their semantics, have to be communicated out of band; for example, through +Device Trees or firmware configuration tables. + +See also `Event definition example`_. + +Event flags +~~~~~~~~~~~ + +Event flags describe the properties of the event. They are bit maps that can be +``OR``\ ed to form parameters to macros that `define events`__. + +.. __: `Defining events`_ + +- ``SDEI_MAPF_DYNAMIC``: Marks the event as dynamic. Dynamic events can be + bound to (or released from) any Non-secure interrupt at runtime via the + ``SDEI_INTERRUPT_BIND`` and ``SDEI_INTERRUPT_RELEASE`` calls. + +- ``SDEI_MAPF_BOUND``: Marks the event as statically bound to an interrupt. + These events cannot be re-bound at runtime. + +- ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is + the default priority. + +- ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority. + +Event definition example +------------------------ + +.. code:: c + + static sdei_ev_map_t plat_private_sdei[] = { + /* Event 0 definition */ + SDEI_DEFINE_EVENT_0(8), + + /* PPI */ + SDEI_PRIVATE_EVENT(8, 23, SDEI_MAPF_BOUND), + + /* Dynamic private events */ + SDEI_PRIVATE_EVENT(100, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_PRIVATE_EVENT(101, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) + + /* Events for explicit dispatch */ + SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL); + SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL); + }; + + /* Shared event mappings */ + static sdei_ev_map_t plat_shared_sdei[] = { + SDEI_SHARED_EVENT(804, 0, SDEI_MAPF_DYNAMIC), + + /* Dynamic shared events */ + SDEI_SHARED_EVENT(3000, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_SHARED_EVENT(3001, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) + }; + + /* Export SDEI events */ + REGISTER_SDEI_MAP(plat_private_sdei, plat_shared_sdei); + +Configuration within Exception Handling Framework +------------------------------------------------- + +The SDEI dispatcher functions alongside the Exception Handling Framework. This +means that the platform must assign priorities to both Normal and Critical SDEI +interrupts for the platform: + +- Install priority descriptors for Normal and Critical SDEI interrupts. + +- For those interrupts that are statically bound (i.e. events defined as having + the ``SDEI_MAPF_BOUND`` property), enumerate their properties for the GIC + driver to configure interrupts accordingly. + + The interrupts must be configured to target EL3. This means that they should + be configured as *Group 0*. Additionally, on GICv2 systems, the build option + ``GICV2_G0_FOR_EL3`` must be set to ``1``. + +See also `SDEI porting requirements`_. + +Determining client EL +--------------------- + +The SDEI specification requires that the *physical* SDEI client executes in the +highest Non-secure EL implemented on the system. This means that the dispatcher +will only allow SDEI calls to be made from: + +- EL2, if EL2 is implemented. The Hypervisor is expected to implement a + *virtual* SDEI dispatcher to support SDEI clients in Guest Operating Systems + executing in Non-secure EL1. + +- Non-secure EL1, if EL2 is not implemented or disabled. + +See the function ``sdei_client_el()`` in ``sdei_private.h``. + +Explicit dispatch of events +--------------------------- + +Typically, an SDEI event dispatch is caused by the PE receiving interrupts that +are bound to an SDEI event. However, there are cases where the Secure world +requires dispatch of an SDEI event as a direct or indirect result of a past +activity, such as receiving a Secure interrupt or an exception. + +The SDEI dispatcher implementation provides ``sdei_dispatch_event()`` API for +this purpose. The API has the following signature: + +:: + + int sdei_dispatch_event(int ev_num); + +The parameter ``ev_num`` is the event number to dispatch. The API returns ``0`` +on success, or ``-1`` on failure. + +The following figure depicts a scenario involving explicit dispatch of SDEI +event. A commentary is provided below: + +.. image:: ../plantuml/sdei_explicit_dispatch.svg + +As part of initialisation, the SDEI client registers a handler for a platform +event [1], enables the event [3], and unmasks the current PE [5]. Note that, +unlike in `general SDEI dispatch`_, this doesn't involve interrupt binding, as +bound or dynamic events can't be explicitly dispatched (see the section below). + +At a later point in time, a critical event [#critical-event]_ is trapped into +EL3 [7]. EL3 performs a first-level triage of the event, and a RAS component +assumes further handling [8]. The dispatch completes, but intends to involve +Non-secure world in further handling, and therefore decides to explicitly +dispatch an event [10] (which the client had already registered for [1]). The +rest of the sequence is similar to that in the `general SDEI dispatch`_: the +requested event is dispatched to the client (assuming all the conditions are +met), and when the handler completes, the preempted execution resumes. + +.. [#critical-event] Examples of critical event are *SError*, *Synchronous + External Abort*, *Fault Handling interrupt*, or *Error + Recovery interrupt* from one of RAS nodes in the system. + +Conditions for event dispatch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All of the following requirements must be met for the API to return ``0`` and +event to be dispatched: + +- SDEI events must be unmasked on the PE. I.e. the client must have called + ``PE_UNMASK`` beforehand. + +- Event 0 can't be dispatched. + +- The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro + described above. + +- The event must be private to the PE. + +- The event must have been registered for and enabled. + +- A dispatch for the same event must not be outstanding. I.e. it hasn't already + been dispatched and is yet to be completed. + +- The priority of the event (either Critical or Normal, as configured by the + platform at build-time) shouldn't cause priority inversion. This means: + + - If it's of Normal priority, neither Normal nor Critical priority dispatch + must be outstanding on the PE. + + - If it's of a Critical priority, no Critical priority dispatch must be + outstanding on the PE. + +Further, the caller should be aware of the following assumptions made by the +dispatcher: + +- The caller of the API is a component running in EL3; for example, a RAS + driver. + +- The requested dispatch will be permitted by the Exception Handling Framework. + I.e. the caller must make sure that the requested dispatch has sufficient + priority so as not to cause priority level inversion within Exception + Handling Framework. + +- The caller must be prepared for the SDEI dispatcher to restore the Non-secure + context, and mark that the active context. + +- The call will block until the SDEI client completes the event (i.e. when the + client calls either ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``). + +- The caller must be prepared for this API to return failure and handle + accordingly. + +Porting requirements +-------------------- + +The porting requirements of the SDEI dispatcher are outlined in the `porting +guide`__. + +.. __: `SDEI porting requirements`_ + +Note on writing SDEI event handlers +----------------------------------- + +*This section pertains to SDEI event handlers in general, not just when using +the TF-A SDEI dispatcher.* + +The SDEI specification requires that event handlers preserve the contents of all +registers except ``x0`` to ``x17``. This has significance if event handler is +written in C: compilers typically adjust the stack frame at the beginning and +end of C functions. For example, AArch64 GCC typically produces the following +function prologue and epilogue: + +:: + + c_event_handler: + stp x29, x30, [sp,#-32]! + mov x29, sp + + ... + + bl ... + + ... + + ldp x29, x30, [sp],#32 + ret + +The register ``x29`` is used as frame pointer in the prologue. Because neither a +valid ``SDEI_EVENT_COMPLETE`` nor ``SDEI_EVENT_COMPLETE_AND_RESUME`` calls +return to the handler, the epilogue never gets executed, and registers ``x29`` +and ``x30`` (in the case above) are inadvertently corrupted. This violates the +SDEI specification, and the normal execution thereafter will result in +unexpected behaviour. + +To work this around, it's advised that the top-level event handlers are +implemented in assembly, following a similar pattern as below: + +:: + + asm_event_handler: + /* Save link register whilst maintaining stack alignment */ + stp xzr, x30, [sp, #-16]! + bl c_event_handler + + /* Restore link register */ + ldp xzr, x30, [sp], #16 + + /* Complete call */ + ldr x0, =SDEI_EVENT_COMPLETE + smc #0 + b . + +---- + +*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* + +.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _SDEI porting requirements: ../getting_started/porting-guide.rst#sdei-porting-requirements diff --git a/docs/components/secure-partition-manager-design.rst b/docs/components/secure-partition-manager-design.rst new file mode 100644 index 0000000..2c32eba --- /dev/null +++ b/docs/components/secure-partition-manager-design.rst @@ -0,0 +1,823 @@ +******************************* +Secure Partition Manager Design +******************************* + + + +.. contents:: + +Background +========== + +In some market segments that primarily deal with client-side devices like mobile +phones, tablets, STBs and embedded devices, a Trusted OS instantiates trusted +applications to provide security services like DRM, secure payment and +authentication. The Global Platform TEE Client API specification defines the API +used by Non-secure world applications to access these services. A Trusted OS +fulfils the requirements of a security service as described above. + +Management services are typically implemented at the highest level of privilege +in the system, i.e. EL3 in Trusted Firmware-A (TF-A). The service requirements are +fulfilled by the execution environment provided by TF-A. + +The following diagram illustrates the corresponding software stack: + +|Image 1| + +In other market segments that primarily deal with server-side devices (e.g. data +centres and enterprise servers) the secure software stack typically does not +include a Global Platform Trusted OS. Security functions are accessed through +other interfaces (e.g. ACPI TCG TPM interface, UEFI runtime variable service). + +Placement of management and security functions with diverse requirements in a +privileged Exception Level (i.e. EL3 or S-EL1) makes security auditing of +firmware more difficult and does not allow isolation of unrelated services from +each other either. + +Introduction +============ + +A **Secure Partition** is a software execution environment instantiated in +S-EL0 that can be used to implement simple management and security services. +Since S-EL0 is an unprivileged Exception Level, a Secure Partition relies on +privileged firmware (i.e. TF-A) to be granted access to system and processor +resources. Essentially, it is a software sandbox in the Secure world that runs +under the control of privileged software, provides one or more services and +accesses the following system resources: + +- Memory and device regions in the system address map. + +- PE system registers. + +- A range of synchronous exceptions (e.g. SMC function identifiers). + +Note that currently TF-A only supports handling one Secure Partition. + +A Secure Partition enables TF-A to implement only the essential secure +services in EL3 and instantiate the rest in a partition in S-EL0. +Furthermore, multiple Secure Partitions can be used to isolate unrelated +services from each other. + +The following diagram illustrates the place of a Secure Partition in a typical +Armv8-A software stack. A single or multiple Secure Partitions provide secure +services to software components in the Non-secure world and other Secure +Partitions. + +|Image 2| + +The TF-A build system is responsible for including the Secure Partition image +in the FIP. During boot, BL2 includes support to authenticate and load the +Secure Partition image. A BL31 component called **Secure Partition Manager +(SPM)** is responsible for managing the partition. This is semantically +similar to a hypervisor managing a virtual machine. + +The SPM is responsible for the following actions during boot: + +- Allocate resources requested by the Secure Partition. + +- Perform architectural and system setup required by the Secure Partition to + fulfil a service request. + +- Implement a standard interface that is used for initialising a Secure + Partition. + +The SPM is responsible for the following actions during runtime: + +- Implement a standard interface that is used by a Secure Partition to fulfil + service requests. + +- Implement a standard interface that is used by the Non-secure world for + accessing the services exported by a Secure Partition. A service can be + invoked through a SMC. + +Alternatively, a partition can be viewed as a thread of execution running under +the control of the SPM. Hence common programming concepts described below are +applicable to a partition. + +Description +=========== + +The previous section introduced some general aspects of the software +architecture of a Secure Partition. This section describes the specific choices +made in the current implementation of this software architecture. Subsequent +revisions of the implementation will include a richer set of features that +enable a more flexible architecture. + +Building TF-A with Secure Partition support +------------------------------------------- + +SPM is supported on the Arm FVP exclusively at the moment. The current +implementation supports inclusion of only a single Secure Partition in which a +service always runs to completion (e.g. the requested services cannot be +preempted to give control back to the Normal world). + +It is not currently possible for BL31 to integrate SPM support and a Secure +Payload Dispatcher (SPD) at the same time; they are mutually exclusive. In the +SPM bootflow, a Secure Partition image executing at S-EL0 replaces the Secure +Payload image executing at S-EL1 (e.g. a Trusted OS). Both are referred to as +BL32. + +A working prototype of a SP has been implemented by re-purposing the EDK2 code +and tools, leveraging the concept of the *Standalone Management Mode (MM)* in +the UEFI specification (see the PI v1.6 Volume 4: Management Mode Core +Interface). This will be referred to as the *Standalone MM Secure Partition* in +the rest of this document. + +To enable SPM support in TF-A, the source code must be compiled with the build +flag ``ENABLE_SPM=1``, along with ``EL3_EXCEPTION_HANDLING=1``. On Arm +platforms the build option ``ARM_BL31_IN_DRAM`` must be set to 1. Also, the +location of the binary that contains the BL32 image +(``BL32=path/to/image.bin``) must be specified. + +First, build the Standalone MM Secure Partition. To build it, refer to the +`instructions in the EDK2 repository`_. + +Then build TF-A with SPM support and include the Standalone MM Secure Partition +image in the FIP: + +:: + + BL32=path/to/standalone/mm/sp BL33=path/to/bl33.bin \ + make PLAT=fvp ENABLE_SPM=1 ARM_BL31_IN_DRAM=1 fip all + +Describing Secure Partition resources +------------------------------------- + +TF-A exports a porting interface that enables a platform to specify the system +resources required by the Secure Partition. Some instructions are given below. +However, this interface is under development and it may change as new features +are implemented. + +- A Secure Partition is considered a BL32 image, so the same defines that apply + to BL32 images apply to a Secure Partition: ``BL32_BASE`` and ``BL32_LIMIT``. + +- The following defines are needed to allocate space for the translation tables + used by the Secure Partition: ``PLAT_SP_IMAGE_MMAP_REGIONS`` and + ``PLAT_SP_IMAGE_MAX_XLAT_TABLES``. + +- The functions ``plat_get_secure_partition_mmap()`` and + ``plat_get_secure_partition_boot_info()`` have to be implemented. The file + ``plat/arm/board/fvp/fvp_common.c`` can be used as an example. It uses the + defines in ``include/plat/arm/common/arm_spm_def.h``. + + - ``plat_get_secure_partition_mmap()`` returns an array of mmap regions that + describe the memory regions that the SPM needs to allocate for a Secure + Partition. + + - ``plat_get_secure_partition_boot_info()`` returns a + ``secure_partition_boot_info_t`` struct that is populated by the platform + with information about the memory map of the Secure Partition. + +For an example of all the changes in context, you may refer to commit +``e29efeb1b4``, in which the port for FVP was introduced. + +Accessing Secure Partition services +----------------------------------- + +The `SMC Calling Convention`_ (*Arm DEN 0028B*) describes SMCs as a conduit for +accessing services implemented in the Secure world. The ``MM_COMMUNICATE`` +interface defined in the `Management Mode Interface Specification`_ (*Arm DEN +0060A*) is used to invoke a Secure Partition service as a Fast Call. + +The mechanism used to identify a service within the partition depends on the +service implementation. It is assumed that the caller of the service will be +able to discover this mechanism through standard platform discovery mechanisms +like ACPI and Device Trees. For example, *Volume 4: Platform Initialisation +Specification v1.6. Management Mode Core Interface* specifies that a GUID is +used to identify a management mode service. A client populates the GUID in the +``EFI_MM_COMMUNICATE_HEADER``. The header is populated in the communication +buffer shared with the Secure Partition. + +A Fast Call appears to be atomic from the perspective of the caller and returns +when the requested operation has completed. A service invoked through the +``MM_COMMUNICATE`` SMC will run to completion in the partition on a given CPU. +The SPM is responsible for guaranteeing this behaviour. This means that there +can only be a single outstanding Fast Call in a partition on a given CPU. + +Exchanging data with the Secure Partition +----------------------------------------- + +The exchange of data between the Non-secure world and the partition takes place +through a shared memory region. The location of data in the shared memory area +is passed as a parameter to the ``MM_COMMUNICATE`` SMC. The shared memory area +is statically allocated by the SPM and is expected to be either implicitly known +to the Non-secure world or discovered through a platform discovery mechanism +e.g. ACPI table or device tree. It is possible for the Non-secure world to +exchange data with a partition only if it has been populated in this shared +memory area. The shared memory area is implemented as per the guidelines +specified in Section 3.2.3 of the `Management Mode Interface Specification`_ +(*Arm DEN 0060A*). + +The format of data structures used to encapsulate data in the shared memory is +agreed between the Non-secure world and the Secure Partition. For example, in +the `Management Mode Interface specification`_ (*Arm DEN 0060A*), Section 4 +describes that the communication buffer shared between the Non-secure world and +the Management Mode (MM) in the Secure world must be of the type +``EFI_MM_COMMUNICATE_HEADER``. This data structure is defined in *Volume 4: +Platform Initialisation Specification v1.6. Management Mode Core Interface*. +Any caller of a MM service will have to use the ``EFI_MM_COMMUNICATE_HEADER`` +data structure. + +Runtime model of the Secure Partition +===================================== + +This section describes how the Secure Partition interfaces with the SPM. + +Interface with SPM +------------------ + +In order to instantiate one or more secure services in the Secure Partition in +S-EL0, the SPM should define the following types of interfaces: + +- Interfaces that enable access to privileged operations from S-EL0. These + operations typically require access to system resources that are either shared + amongst multiple software components in the Secure world or cannot be directly + accessed from an unprivileged Exception Level. + +- Interfaces that establish the control path between the SPM and the Secure + Partition. + +This section describes the APIs currently exported by the SPM that enable a +Secure Partition to initialise itself and export its services in S-EL0. These +interfaces are not accessible from the Non-secure world. + +Conduit +^^^^^^^ + +The `SMC Calling Convention`_ (*Arm DEN 0028B*) specification describes the SMC +and HVC conduits for accessing firmware services and their availability +depending on the implemented Exception levels. In S-EL0, the Supervisor Call +exception (SVC) is the only architectural mechanism available for unprivileged +software to make a request for an operation implemented in privileged software. +Hence, the SVC conduit must be used by the Secure Partition to access interfaces +implemented by the SPM. + +A SVC causes an exception to be taken to S-EL1. TF-A assumes ownership of S-EL1 +and installs a simple exception vector table in S-EL1 that relays a SVC request +from a Secure Partition as a SMC request to the SPM in EL3. Upon servicing the +SMC request, Arm Trusted Firmware returns control directly to S-EL0 through an +ERET instruction. + +Calling conventions +^^^^^^^^^^^^^^^^^^^ + +The `SMC Calling Convention`_ (*Arm DEN 0028B*) specification describes the +32-bit and 64-bit calling conventions for the SMC and HVC conduits. The SVC +conduit introduces the concept of SVC32 and SVC64 calling conventions. The SVC32 +and SVC64 calling conventions are equivalent to the 32-bit (SMC32) and the +64-bit (SMC64) calling conventions respectively. + +Communication initiated by SPM +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A service request is initiated from the SPM through an exception return +instruction (ERET) to S-EL0. Later, the Secure Partition issues an SVC +instruction to signal completion of the request. Some example use cases are +given below: + +- A request to initialise the Secure Partition during system boot. + +- A request to handle a runtime service request. + +Communication initiated by Secure Partition +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A request is initiated from the Secure Partition by executing a SVC instruction. +An ERET instruction is used by TF-A to return to S-EL0 with the result of the +request. + +For instance, a request to perform privileged operations on behalf of a +partition (e.g. management of memory attributes in the translation tables for +the Secure EL1&0 translation regime). + +Interfaces +^^^^^^^^^^ + +The current implementation reserves function IDs for Fast Calls in the Standard +Secure Service calls range (see `SMC Calling Convention`_ (*Arm DEN 0028B*) +specification) for each API exported by the SPM. This section defines the +function prototypes for each function ID. The function IDs specify whether one +or both of the SVC32 and SVC64 calling conventions can be used to invoke the +corresponding interface. + +Secure Partition Event Management +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Secure Partition provides an Event Management interface that is used by the +SPM to delegate service requests to the Secure Partition. The interface also +allows the Secure Partition to: + +- Register with the SPM a service that it provides. +- Indicate completion of a service request delegated by the SPM + +Miscellaneous interfaces +------------------------ + +``SPM_VERSION_AARCH32`` +^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Returns the version of the interface exported by SPM. + +- Parameters + + - **uint32** - Function ID + + - SVC32 Version: **0x84000060** + +- Return parameters + + - **int32** - Status + + On success, the format of the value is as follows: + + - Bit [31]: Must be 0 + - Bits [30:16]: Major Version. Must be 0 for this revision of the SPM + interface. + - Bits [15:0]: Minor Version. Must be 1 for this revision of the SPM + interface. + + On error, the format of the value is as follows: + + - ``NOT_SUPPORTED``: SPM interface is not supported or not available for the + client. + +- Usage + + This function returns the version of the Secure Partition Manager + implementation. The major version is 0 and the minor version is 1. The version + number is a 31-bit unsigned integer, with the upper 15 bits denoting the major + revision, and the lower 16 bits denoting the minor revision. The following + rules apply to the version numbering: + + - Different major revision values indicate possibly incompatible functions. + + - For two revisions, A and B, for which the major revision values are + identical, if the minor revision value of revision B is greater than the + minor revision value of revision A, then every function in revision A must + work in a compatible way with revision B. However, it is possible for + revision B to have a higher function count than revision A. + +- Implementation responsibilities + + If this function returns a valid version number, all the functions that are + described subsequently must be implemented, unless it is explicitly stated + that a function is optional. + +See `Error Codes`_ for integer values that are associated with each return +code. + +Secure Partition Initialisation +------------------------------- + +The SPM is responsible for initialising the architectural execution context to +enable initialisation of a service in S-EL0. The responsibilities of the SPM are +listed below. At the end of initialisation, the partition issues a +``SP_EVENT_COMPLETE_AARCH64`` call (described later) to signal readiness for +handling requests for services implemented by the Secure Partition. The +initialisation event is executed as a Fast Call. + +Entry point invocation +^^^^^^^^^^^^^^^^^^^^^^ + +The entry point for service requests that should be handled as Fast Calls is +used as the target of the ERET instruction to start initialisation of the Secure +Partition. + +Architectural Setup +^^^^^^^^^^^^^^^^^^^ + +At cold boot, system registers accessible from S-EL0 will be in their reset +state unless otherwise specified. The SPM will perform the following +architectural setup to enable execution in S-EL0 + +MMU setup +^^^^^^^^^ + +The platform port of a Secure Partition specifies to the SPM a list of regions +that it needs access to and their attributes. The SPM validates this resource +description and initialises the Secure EL1&0 translation regime as follows. + +1. Device regions are mapped with nGnRE attributes and Execute Never + instruction access permissions. + +2. Code memory regions are mapped with RO data and Executable instruction access + permissions. + +3. Read Only data memory regions are mapped with RO data and Execute Never + instruction access permissions. + +4. Read Write data memory regions are mapped with RW data and Execute Never + instruction access permissions. + +5. If the resource description does not explicitly describe the type of memory + regions then all memory regions will be marked with Code memory region + attributes. + +6. The ``UXN`` and ``PXN`` bits are set for regions that are not executable by + S-EL0 or S-EL1. + +System Register Setup +^^^^^^^^^^^^^^^^^^^^^ + +System registers that influence software execution in S-EL0 are setup by the SPM +as follows: + +1. ``SCTLR_EL1`` + + - ``UCI=1`` + - ``EOE=0`` + - ``WXN=1`` + - ``nTWE=1`` + - ``nTWI=1`` + - ``UCT=1`` + - ``DZE=1`` + - ``I=1`` + - ``UMA=0`` + - ``SA0=1`` + - ``C=1`` + - ``A=1`` + - ``M=1`` + +2. ``CPACR_EL1`` + + - ``FPEN=b'11`` + +3. ``PSTATE`` + + - ``D,A,I,F=1`` + - ``CurrentEL=0`` (EL0) + - ``SpSel=0`` (Thread mode) + - ``NRW=0`` (AArch64) + +General Purpose Register Setup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +SPM will invoke the entry point of a service by executing an ERET instruction. +This transition into S-EL0 is special since it is not in response to a previous +request through a SVC instruction. This is the first entry into S-EL0. The +general purpose register usage at the time of entry will be as specified in the +"Return State" column of Table 3-1 in Section 3.1 "Register use in AArch64 SMC +calls" of the `SMC Calling Convention`_ (*Arm DEN 0028B*) specification. In +addition, certain other restrictions will be applied as described below. + +1. ``SP_EL0`` + + A non-zero value will indicate that the SPM has initialised the stack pointer + for the current CPU. + + The value will be 0 otherwise. + +2. ``X4-X30`` + + The values of these registers will be 0. + +3. ``X0-X3`` + + Parameters passed by the SPM. + + - ``X0``: Virtual address of a buffer shared between EL3 and S-EL0. The + buffer will be mapped in the Secure EL1&0 translation regime with read-only + memory attributes described earlier. + + - ``X1``: Size of the buffer in bytes. + + - ``X2``: Cookie value (*IMPLEMENTATION DEFINED*). + + - ``X3``: Cookie value (*IMPLEMENTATION DEFINED*). + +Runtime Event Delegation +------------------------ + +The SPM receives requests for Secure Partition services through a synchronous +invocation (i.e. a SMC from the Non-secure world). These requests are delegated +to the partition by programming a return from the last +``SP_EVENT_COMPLETE_AARCH64`` call received from the partition. The last call +was made to signal either completion of Secure Partition initialisation or +completion of a partition service request. + +``SP_EVENT_COMPLETE_AARCH64`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Signal completion of the last SP service request. + +- Parameters + + - **uint32** - Function ID + + - SVC64 Version: **0xC4000061** + + - **int32** - Event Status Code + + Zero or a positive value indicates that the event was handled successfully. + The values depend upon the original event that was delegated to the Secure + partition. They are described as follows. + + - ``SUCCESS`` : Used to indicate that the Secure Partition was initialised + or a runtime request was handled successfully. + + - Any other value greater than 0 is used to pass a specific Event Status + code in response to a runtime event. + + A negative value indicates an error. The values of Event Status code depend + on the original event. + +- Return parameters + + - **int32** - Event ID/Return Code + + Zero or a positive value specifies the unique ID of the event being + delegated to the partition by the SPM. + + In the current implementation, this parameter contains the function ID of + the ``MM_COMMUNICATE`` SMC. This value indicates to the partition that an + event has been delegated to it in response to an ``MM_COMMUNICATE`` request + from the Non-secure world. + + A negative value indicates an error. The format of the value is as follows: + + - ``NOT_SUPPORTED``: Function was called from the Non-secure world. + + See `Error Codes`_ for integer values that are associated with each return + code. + + - **uint32** - Event Context Address + + Address of a buffer shared between the SPM and Secure Partition to pass + event specific information. The format of the data populated in the buffer + is implementation defined. + + The buffer is mapped in the Secure EL1&0 translation regime with read-only + memory attributes described earlier. + + For the SVC64 version, this parameter is a 64-bit Virtual Address (VA). + + For the SVC32 version, this parameter is a 32-bit Virtual Address (VA). + + - **uint32** - Event context size + + Size of the memory starting at Event Address. + + - **uint32/uint64** - Event Cookie + + This is an optional parameter. If unused its value is SBZ. + +- Usage + + This function signals to the SPM that the handling of the last event delegated + to a partition has completed. The partition is ready to handle its next event. + A return from this function is in response to the next event that will be + delegated to the partition. The return parameters describe the next event. + +- Caller responsibilities + + A Secure Partition must only call ``SP_EVENT_COMPLETE_AARCH64`` to signal + completion of a request that was delegated to it by the SPM. + +- Callee responsibilities + + When the SPM receives this call from a Secure Partition, the corresponding + syndrome information can be used to return control through an ERET + instruction, to the instruction immediately after the call in the Secure + Partition context. This syndrome information comprises of general purpose and + system register values when the call was made. + + The SPM must save this syndrome information and use it to delegate the next + event to the Secure Partition. The return parameters of this interface must + specify the properties of the event and be populated in ``X0-X3/W0-W3`` + registers. + +Secure Partition Memory Management +---------------------------------- + +A Secure Partition executes at S-EL0, which is an unprivileged Exception Level. +The SPM is responsible for enabling access to regions of memory in the system +address map from a Secure Partition. This is done by mapping these regions in +the Secure EL1&0 Translation regime with appropriate memory attributes. +Attributes refer to memory type, permission, cacheability and shareability +attributes used in the Translation tables. The definitions of these attributes +and their usage can be found in the `Armv8-A ARM`_ (*Arm DDI 0487*). + +All memory required by the Secure Partition is allocated upfront in the SPM, +even before handing over to the Secure Partition for the first time. The initial +access permissions of the memory regions are statically provided by the platform +port and should allow the Secure Partition to run its initialisation code. + +However, they might not suit the final needs of the Secure Partition because its +final memory layout might not be known until the Secure Partition initialises +itself. As the Secure Partition initialises its runtime environment it might, +for example, load dynamically some modules. For instance, a Secure Partition +could implement a loader for a standard executable file format (e.g. an PE-COFF +loader for loading executable files at runtime). These executable files will be +a part of the Secure Partition image. The location of various sections in an +executable file and their permission attributes (e.g. read-write data, read-only +data and code) will be known only when the file is loaded into memory. + +In this case, the Secure Partition needs a way to change the access permissions +of its memory regions. The SPM provides this feature through the +``SP_MEMORY_ATTRIBUTES_SET_AARCH64`` SVC interface. This interface is available +to the Secure Partition during a specific time window: from the first entry into +the Secure Partition up to the first ``SP_EVENT_COMPLETE`` call that signals the +Secure Partition has finished its initialisation. Once the initialisation is +complete, the SPM does not allow changes to the memory attributes. + +This section describes the standard SVC interface that is implemented by the SPM +to determine and change permission attributes of memory regions that belong to a +Secure Partition. + +``SP_MEMORY_ATTRIBUTES_GET_AARCH64`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Request the permission attributes of a memory region from S-EL0. + +- Parameters + + - **uint32** Function ID + + - SVC64 Version: **0xC4000064** + + - **uint64** Base Address + + This parameter is a 64-bit Virtual Address (VA). + + There are no alignment restrictions on the Base Address. The permission + attributes of the translation granule it lies in are returned. + +- Return parameters + + - **int32** - Memory Attributes/Return Code + + On success the format of the Return Code is as follows: + + - Bits[1:0] : Data access permission + + - b'00 : No access + - b'01 : Read-Write access + - b'10 : Reserved + - b'11 : Read-only access + + - Bit[2]: Instruction access permission + + - b'0 : Executable + - b'1 : Non-executable + + - Bit[30:3] : Reserved. SBZ. + + - Bit[31] : Must be 0 + + On failure the following error codes are returned: + + - ``INVALID_PARAMETERS``: The Secure Partition is not allowed to access the + memory region the Base Address lies in. + + - ``NOT_SUPPORTED`` : The SPM does not support retrieval of attributes of + any memory page that is accessible by the Secure Partition, or the + function was called from the Non-secure world. Also returned if it is + used after ``SP_EVENT_COMPLETE_AARCH64``. + + See `Error Codes`_ for integer values that are associated with each return + code. + +- Usage + + This function is used to request the permission attributes for S-EL0 on a + memory region accessible from a Secure Partition. The size of the memory + region is equal to the Translation Granule size used in the Secure EL1&0 + translation regime. Requests to retrieve other memory region attributes are + not currently supported. + +- Caller responsibilities + + The caller must obtain the Translation Granule Size of the Secure EL1&0 + translation regime from the SPM through an implementation defined method. + +- Callee responsibilities + + The SPM must not return the memory access controls for a page of memory that + is not accessible from a Secure Partition. + +``SP_MEMORY_ATTRIBUTES_SET_AARCH64`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Set the permission attributes of a memory region from S-EL0. + +- Parameters + + - **uint32** - Function ID + + - SVC64 Version: **0xC4000065** + + - **uint64** - Base Address + + This parameter is a 64-bit Virtual Address (VA). + + The alignment of the Base Address must be greater than or equal to the size + of the Translation Granule Size used in the Secure EL1&0 translation + regime. + + - **uint32** - Page count + + Number of pages starting from the Base Address whose memory attributes + should be changed. The page size is equal to the Translation Granule Size. + + - **uint32** - Memory Access Controls + + - Bits[1:0] : Data access permission + + - b'00 : No access + - b'01 : Read-Write access + - b'10 : Reserved + - b'11 : Read-only access + + - Bit[2] : Instruction access permission + + - b'0 : Executable + - b'1 : Non-executable + + - Bits[31:3] : Reserved. SBZ. + + A combination of attributes that mark the region with RW and Executable + permissions is prohibited. A request to mark a device memory region with + Executable permissions is prohibited. + +- Return parameters + + - **int32** - Return Code + + - ``SUCCESS``: The Memory Access Controls were changed successfully. + + - ``DENIED``: The SPM is servicing a request to change the attributes of a + memory region that overlaps with the region specified in this request. + + - ``INVALID_PARAMETER``: An invalid combination of Memory Access Controls + has been specified. The Base Address is not correctly aligned. The Secure + Partition is not allowed to access part or all of the memory region + specified in the call. + + - ``NO_MEMORY``: The SPM does not have memory resources to change the + attributes of the memory region in the translation tables. + + - ``NOT_SUPPORTED``: The SPM does not permit change of attributes of any + memory region that is accessible by the Secure Partition. Function was + called from the Non-secure world. Also returned if it is used after + ``SP_EVENT_COMPLETE_AARCH64``. + + See `Error Codes`_ for integer values that are associated with each return + code. + +- Usage + + This function is used to change the permission attributes for S-EL0 on a + memory region accessible from a Secure Partition. The size of the memory + region is equal to the Translation Granule size used in the Secure EL1&0 + translation regime. Requests to change other memory region attributes are not + currently supported. + + This function is only available at boot time. This interface is revoked after + the Secure Partition sends the first ``SP_EVENT_COMPLETE_AARCH64`` to signal + that it is initialised and ready to receive run-time requests. + +- Caller responsibilities + + The caller must obtain the Translation Granule Size of the Secure EL1&0 + translation regime from the SPM through an implementation defined method. + +- Callee responsibilities + + The SPM must preserve the original memory access controls of the region of + memory in case of an unsuccessful call.  The SPM must preserve the consistency + of the S-EL1 translation regime if this function is called on different PEs + concurrently and the memory regions specified overlap. + +Error Codes +----------- + +.. csv-table:: + :header: "Name", "Value" + + ``SUCCESS``,0 + ``NOT_SUPPORTED``,-1 + ``INVALID_PARAMETER``,-2 + ``DENIED``,-3 + ``NO_MEMORY``,-5 + ``NOT_PRESENT``,-7 + +-------------- + +*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* + +.. _Armv8-A ARM: https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile +.. _instructions in the EDK2 repository: https://github.com/tianocore/edk2-staging/blob/AArch64StandaloneMm/HowtoBuild.MD +.. _Management Mode Interface Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0060a/DEN0060A_ARM_MM_Interface_Specification.pdf +.. _SDEI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf + +.. |Image 1| image:: ../diagrams/secure_sw_stack_tos.png +.. |Image 2| image:: ../diagrams/secure_sw_stack_sp.png diff --git a/docs/components/spd/index.rst b/docs/components/spd/index.rst new file mode 100644 index 0000000..e03bfe3 --- /dev/null +++ b/docs/components/spd/index.rst @@ -0,0 +1,11 @@ +Secure Payload Dispatcher (SPD) +=============================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + optee-dispatcher + tlk-dispatcher + trusty-dispatcher diff --git a/docs/components/spd/optee-dispatcher.rst b/docs/components/spd/optee-dispatcher.rst new file mode 100644 index 0000000..63baccc --- /dev/null +++ b/docs/components/spd/optee-dispatcher.rst @@ -0,0 +1,14 @@ +OP-TEE Dispatcher +================= + +`OP-TEE OS`_ is a Trusted OS running as Secure EL1. + +To build and execute OP-TEE follow the instructions at +`OP-TEE build.git`_ + +-------------- + +*Copyright (c) 2014-2018, Arm Limited and Contributors. All rights reserved.* + +.. _OP-TEE OS: https://github.com/OP-TEE/build +.. _OP-TEE build.git: https://github.com/OP-TEE/build diff --git a/docs/components/spd/tlk-dispatcher.rst b/docs/components/spd/tlk-dispatcher.rst new file mode 100644 index 0000000..90af5fa --- /dev/null +++ b/docs/components/spd/tlk-dispatcher.rst @@ -0,0 +1,76 @@ +Trusted Little Kernel (TLK) Dispatcher +====================================== + +TLK dispatcher (TLK-D) adds support for NVIDIA's Trusted Little Kernel (TLK) +to work with Trusted Firmware-A (TF-A). TLK-D can be compiled by including it +in the platform's makefile. TLK is primarily meant to work with Tegra SoCs, +so while TF-A only supports TLK on Tegra, the dispatcher code can only be +compiled for other platforms. + +In order to compile TLK-D, we need a BL32 image to be present. Since, TLKD +just needs to compile, any BL32 image would do. To use TLK as the BL32, please +refer to the "Build TLK" section. + +Once a BL32 is ready, TLKD can be included in the image by adding "SPD=tlkd" +to the build command. + +Trusted Little Kernel (TLK) +=========================== + +TLK is a Trusted OS running as Secure EL1. It is a Free Open Source Software +(FOSS) release of the NVIDIA® Trusted Little Kernel (TLK) technology, which +extends technology made available with the development of the Little Kernel (LK). +You can download the LK modular embedded preemptive kernel for use on Arm, +x86, and AVR32 systems from https://github.com/travisg/lk + +NVIDIA implemented its Trusted Little Kernel (TLK) technology, designed as a +free and open-source trusted execution environment (OTE). + +TLK features include: + +• Small, pre-emptive kernel +• Supports multi-threading, IPCs, and thread scheduling +• Added TrustZone features +• Added Secure Storage +• Under MIT/FreeBSD license + +NVIDIA extensions to Little Kernel (LK) include: + +• User mode +• Address-space separation for TAs +• TLK Client Application (CA) library +• TLK TA library +• Crypto library (encrypt/decrypt, key handling) via OpenSSL +• Linux kernel driver +• Cortex A9/A15 support +• Power Management +• TrustZone memory carve-out (reconfigurable) +• Page table management +• Debugging support over UART (USB planned) + +TLK is hosted by NVIDIA on http://nv-tegra.nvidia.com under the +3rdparty/ote\_partner/tlk.git repository. Detailed information about +TLK and OTE can be found in the Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf +manual located under the "documentation" directory\_. + +Build TLK +========= + +To build and execute TLK, follow the instructions from "Building a TLK Device" +section from Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf manual. + +Input parameters to TLK +======================= + +TLK expects the TZDRAM size and a structure containing the boot arguments. BL2 +passes this information to the EL3 software as members of the bl32\_ep\_info +struct, where bl32\_ep\_info is part of bl31\_params\_t (passed by BL2 in X0) + +Example: +-------- + +:: + + bl32_ep_info->args.arg0 = TZDRAM size available for BL32 + bl32_ep_info->args.arg1 = unused (used only on Armv7-A) + bl32_ep_info->args.arg2 = pointer to boot args diff --git a/docs/components/spd/trusty-dispatcher.rst b/docs/components/spd/trusty-dispatcher.rst new file mode 100644 index 0000000..be08570 --- /dev/null +++ b/docs/components/spd/trusty-dispatcher.rst @@ -0,0 +1,32 @@ +Trusty Dispatcher +================= + +Trusty is a a set of software components, supporting a Trusted Execution +Environment (TEE) on mobile devices, published and maintained by Google. + +Detailed information and build instructions can be found on the Android +Open Source Project (AOSP) webpage for Trusty hosted at +https://source.android.com/security/trusty + +Boot parameters +=============== + +Custom boot parameters can be passed to Trusty by providing a platform +specific function: + +.. code:: c + + void plat_trusty_set_boot_args(aapcs64_params_t *args) + +If this function is provided ``args->arg0`` must be set to the memory +size allocated to trusty. If the platform does not provide this +function, but defines ``TSP_SEC_MEM_SIZE``, a default implementation +will pass the memory size from ``TSP_SEC_MEM_SIZE``. ``args->arg1`` +can be set to a platform specific parameter block, and ``args->arg2`` +should then be set to the size of that block. + +Supported platforms +=================== + +Out of all the platforms supported by Trusted Firmware-A, Trusty is only +verified and supported by NVIDIA's Tegra SoCs. diff --git a/docs/components/xlat-tables-lib-v2-design.rst b/docs/components/xlat-tables-lib-v2-design.rst new file mode 100644 index 0000000..d55f010 --- /dev/null +++ b/docs/components/xlat-tables-lib-v2-design.rst @@ -0,0 +1,427 @@ +Translation Tables Library Design +================================= + + + + +.. contents:: + + +This document describes the design of the translation tables library (version 2) +used by Trusted Firmware-A (TF-A). This library provides APIs to create page +tables based on a description of the memory layout, as well as setting up system +registers related to the Memory Management Unit (MMU) and performing the +required Translation Lookaside Buffer (TLB) maintenance operations. + +More specifically, some use cases that this library aims to support are: + +#. Statically allocate translation tables and populate them (at run-time) based + on a description of the memory layout. The memory layout is typically + provided by the platform port as a list of memory regions; + +#. Support for generating translation tables pertaining to a different + translation regime than the exception level the library code is executing at; + +#. Support for dynamic mapping and unmapping of regions, even while the MMU is + on. This can be used to temporarily map some memory regions and unmap them + later on when no longer needed; + +#. Support for non-identity virtual to physical mappings to compress the virtual + address space; + +#. Support for changing memory attributes of memory regions at run-time. + + +About version 1 and version 2 +----------------------------- + +This document focuses on version 2 of the library, whose sources are available +in the `lib/xlat_tables_v2`_ directory. Version 1 of the library can still be +found in `lib/xlat_tables`_ directory but it is less flexible and doesn't +support dynamic mapping. Although potential bug fixes will be applied to both +versions, future features enhancements will focus on version 2 and might not be +back-ported to version 1. Therefore, it is recommended to use version 2, +especially for new platform ports. + +However, please note that version 2 is still in active development and is not +considered stable yet. Hence, compatibility breaks might be introduced. + +From this point onwards, this document will implicitly refer to version 2 of the +library. + + +Design concepts and interfaces +------------------------------ + +This section presents some of the key concepts and data structures used in the +translation tables library. + +`mmap` regions +~~~~~~~~~~~~~~ + +An ``mmap_region`` is an abstract, concise way to represent a memory region to +map. It is one of the key interfaces to the library. It is identified by: + +- its physical base address; +- its virtual base address; +- its size; +- its attributes; +- its mapping granularity (optional). + +See the ``struct mmap_region`` type in `xlat_tables_v2.h`_. + +The user usually provides a list of such mmap regions to map and lets the +library transpose that in a set of translation tables. As a result, the library +might create new translation tables, update or split existing ones. + +The region attributes specify the type of memory (for example device or cached +normal memory) as well as the memory access permissions (read-only or +read-write, executable or not, secure or non-secure, and so on). In the case of +the EL1&0 translation regime, the attributes also specify whether the region is +a User region (EL0) or Privileged region (EL1). See the ``MT_xxx`` definitions +in `xlat_tables_v2.h`_. Note that for the EL1&0 translation regime the Execute +Never attribute is set simultaneously for both EL1 and EL0. + +The granularity controls the translation table level to go down to when mapping +the region. For example, assuming the MMU has been configured to use a 4KB +granule size, the library might map a 2MB memory region using either of the two +following options: + +- using a single level-2 translation table entry; +- using a level-2 intermediate entry to a level-3 translation table (which + contains 512 entries, each mapping 4KB). + +The first solution potentially requires less translation tables, hence +potentially less memory. However, if part of this 2MB region is later remapped +with different memory attributes, the library might need to split the existing +page tables to refine the mappings. If a single level-2 entry has been used +here, a level-3 table will need to be allocated on the fly and the level-2 +modified to point to this new level-3 table. This has a performance cost at +run-time. + +If the user knows upfront that such a remapping operation is likely to happen +then they might enforce a 4KB mapping granularity for this 2MB region from the +beginning; remapping some of these 4KB pages on the fly then becomes a +lightweight operation. + +The region's granularity is an optional field; if it is not specified the +library will choose the mapping granularity for this region as it sees fit (more +details can be found in `The memory mapping algorithm`_ section below). + +Translation Context +~~~~~~~~~~~~~~~~~~~ + +The library can create or modify translation tables pertaining to a different +translation regime than the exception level the library code is executing at. +For example, the library might be used by EL3 software (for instance BL31) to +create translation tables pertaining to the S-EL1&0 translation regime. + +This flexibility comes from the use of *translation contexts*. A *translation +context* constitutes the superset of information used by the library to track +the status of a set of translation tables for a given translation regime. + +The library internally allocates a default translation context, which pertains +to the translation regime of the current exception level. Additional contexts +may be explicitly allocated and initialized using the +``REGISTER_XLAT_CONTEXT()`` macro. Separate APIs are provided to act either on +the default translation context or on an alternative one. + +To register a translation context, the user must provide the library with the +following information: + +* A name. + + The resulting translation context variable will be called after this name, to + which ``_xlat_ctx`` is appended. For example, if the macro name parameter is + ``foo``, the context variable name will be ``foo_xlat_ctx``. + +* The maximum number of `mmap` regions to map. + + Should account for both static and dynamic regions, if applicable. + +* The number of sub-translation tables to allocate. + + Number of translation tables to statically allocate for this context, + excluding the initial lookup level translation table, which is always + allocated. For example, if the initial lookup level is 1, this parameter would + specify the number of level-2 and level-3 translation tables to pre-allocate + for this context. + +* The size of the virtual address space. + + Size in bytes of the virtual address space to map using this context. This + will incidentally determine the number of entries in the initial lookup level + translation table : the library will allocate as many entries as is required + to map the entire virtual address space. + +* The size of the physical address space. + + Size in bytes of the physical address space to map using this context. + +The default translation context is internally initialized using information +coming (for the most part) from platform-specific defines: + +- name: hard-coded to ``tf`` ; hence the name of the default context variable is + ``tf_xlat_ctx``; +- number of `mmap` regions: ``MAX_MMAP_REGIONS``; +- number of sub-translation tables: ``MAX_XLAT_TABLES``; +- size of the virtual address space: ``PLAT_VIRT_ADDR_SPACE_SIZE``; +- size of the physical address space: ``PLAT_PHY_ADDR_SPACE_SIZE``. + +Please refer to the `Porting Guide`_ for more details about these macros. + + +Static and dynamic memory regions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The library optionally supports dynamic memory mapping. This feature may be +enabled using the ``PLAT_XLAT_TABLES_DYNAMIC`` platform build flag. + +When dynamic memory mapping is enabled, the library categorises mmap regions as +*static* or *dynamic*. + +- *Static regions* are fixed for the lifetime of the system. They can only be + added early on, before the translation tables are created and populated. They + cannot be removed afterwards. + +- *Dynamic regions* can be added or removed any time. + +When the dynamic memory mapping feature is disabled, only static regions exist. + +The dynamic memory mapping feature may be used to map and unmap transient memory +areas. This is useful when the user needs to access some memory for a fixed +period of time, after which the memory may be discarded and reclaimed. For +example, a memory region that is only required at boot time while the system is +initializing, or to temporarily share a memory buffer between the normal world +and trusted world. Note that it is up to the caller to ensure that these regions +are not accessed concurrently while the regions are being added or removed. + +Although this feature provides some level of dynamic memory allocation, this +does not allow dynamically allocating an arbitrary amount of memory at an +arbitrary memory location. The user is still required to declare at compile-time +the limits of these allocations ; the library will deny any mapping request that +does not fit within this pre-allocated pool of memory. + + +Library APIs +------------ + +The external APIs exposed by this library are declared and documented in the +`xlat_tables_v2.h`_ header file. This should be the reference point for +getting information about the usage of the different APIs this library +provides. This section just provides some extra details and clarifications. + +Although the ``mmap_region`` structure is a publicly visible type, it is not +recommended to populate these structures by hand. Instead, wherever APIs expect +function arguments of type ``mmap_region_t``, these should be constructed using +the ``MAP_REGION*()`` family of helper macros. This is to limit the risk of +compatibility breaks, should the ``mmap_region`` structure type evolve in the +future. + +The ``MAP_REGION()`` and ``MAP_REGION_FLAT()`` macros do not allow specifying a +mapping granularity, which leaves the library implementation free to choose +it. However, in cases where a specific granularity is required, the +``MAP_REGION2()`` macro might be used instead. + +As explained earlier in this document, when the dynamic mapping feature is +disabled, there is no notion of dynamic regions. Conceptually, there are only +static regions. For this reason (and to retain backward compatibility with the +version 1 of the library), the APIs that map static regions do not embed the +word *static* in their functions names (for example ``mmap_add_region()``), in +contrast with the dynamic regions APIs (for example +``mmap_add_dynamic_region()``). + +Although the definition of static and dynamic regions is not based on the state +of the MMU, the two are still related in some way. Static regions can only be +added before ``init_xlat_tables()`` is called and ``init_xlat_tables()`` must be +called while the MMU is still off. As a result, static regions cannot be added +once the MMU has been enabled. Dynamic regions can be added with the MMU on or +off. In practice, the usual call flow would look like this: + +#. The MMU is initially off. + +#. Add some static regions, add some dynamic regions. + +#. Initialize translation tables based on the list of mmap regions (using one of + the ``init_xlat_tables*()`` APIs). + +#. At this point, it is no longer possible to add static regions. Dynamic + regions can still be added or removed. + +#. Enable the MMU. + +#. Dynamic regions can continue to be added or removed. + +Because static regions are added early on at boot time and are all in the +control of the platform initialization code, the ``mmap_add*()`` family of APIs +are not expected to fail. They do not return any error code. + +Nonetheless, these APIs will check upfront whether the region can be +successfully added before updating the translation context structure. If the +library detects that there is insufficient memory to meet the request, or that +the new region will overlap another one in an invalid way, or if any other +unexpected error is encountered, they will print an error message on the UART. +Additionally, when asserts are enabled (typically in debug builds), an assertion +will be triggered. Otherwise, the function call will just return straight away, +without adding the offending memory region. + + +Library limitations +------------------- + +Dynamic regions are not allowed to overlap each other. Static regions are +allowed to overlap as long as one of them is fully contained inside the other +one. This is allowed for backwards compatibility with the previous behaviour in +the version 1 of the library. + + +Implementation details +---------------------- + +Code structure +~~~~~~~~~~~~~~ + +The library is divided into 4 modules: + +- **Core module** + + Provides the main functionality of the library, such as the initialization of + translation tables contexts and mapping/unmapping memory regions. This module + provides functions such as ``mmap_add_region_ctx`` that let the caller specify + the translation tables context affected by them. + + See `xlat_tables_core.c`_. + +- **Active context module** + + Instantiates the context that is used by the current BL image and provides + helpers to manipulate it, abstracting it from the rest of the code. + This module provides functions such as ``mmap_add_region``, that directly + affect the BL image using them. + + See `xlat_tables_context.c`_. + +- **Utilities module** + + Provides additional functionality like debug print of the current state of the + translation tables and helpers to query memory attributes and to modify them. + + See `xlat_tables_utils.c`_. + +- **Architectural module** + + Provides functions that are dependent on the current execution state + (AArch32/AArch64), such as the functions used for TLB invalidation, setup the + MMU, or calculate the Physical Address Space size. They do not need a + translation context to work on. + + See `aarch32/xlat_tables_arch.c`_ and `aarch64/xlat_tables_arch.c`_. + +From mmap regions to translation tables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A translation context contains a list of ``mmap_region_t``, which holds the +information of all the regions that are mapped at any given time. Whenever there +is a request to map (resp. unmap) a memory region, it is added to (resp. removed +from) the ``mmap_region_t`` list. + +The mmap regions list is a conceptual way to represent the memory layout. At +some point, the library has to convert this information into actual translation +tables to program into the MMU. + +Before the ``init_xlat_tables()`` API is called, the library only acts on the +mmap regions list. Adding a static or dynamic region at this point through one +of the ``mmap_add*()`` APIs does not affect the translation tables in any way, +they only get registered in the internal mmap region list. It is only when the +user calls the ``init_xlat_tables()`` that the translation tables are populated +in memory based on the list of mmap regions registered so far. This is an +optimization that allows creation of the initial set of translation tables in +one go, rather than having to edit them every time while the MMU is disabled. + +After the ``init_xlat_tables()`` API has been called, only dynamic regions can +be added. Changes to the translation tables (as well as the mmap regions list) +will take effect immediately. + +The memory mapping algorithm +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The mapping function is implemented as a recursive algorithm. It is however +bound by the level of depth of the translation tables (the Armv8-A architecture +allows up to 4 lookup levels). + +By default [#granularity-ref]_, the algorithm will attempt to minimize the +number of translation tables created to satisfy the user's request. It will +favour mapping a region using the biggest possible blocks, only creating a +sub-table if it is strictly necessary. This is to reduce the memory footprint of +the firmware. + +The most common reason for needing a sub-table is when a specific mapping +requires a finer granularity. Misaligned regions also require a finer +granularity than what the user may had originally expected, using a lot more +memory than expected. The reason is that all levels of translation are +restricted to address translations of the same granularity as the size of the +blocks of that level. For example, for a 4 KiB page size, a level 2 block entry +can only translate up to a granularity of 2 MiB. If the Physical Address is not +aligned to 2 MiB then additional level 3 tables are also needed. + +Note that not every translation level allows any type of descriptor. Depending +on the page size, levels 0 and 1 of translation may only allow table +descriptors. If a block entry could be able to describe a translation, but that +level does not allow block descriptors, a table descriptor will have to be used +instead, as well as additional tables at the next level. + +|Alignment Example| + +The mmap regions are sorted in a way that simplifies the code that maps +them. Even though this ordering is only strictly needed for overlapping static +regions, it must also be applied for dynamic regions to maintain a consistent +order of all regions at all times. As each new region is mapped, existing +entries in the translation tables are checked to ensure consistency. Please +refer to the comments in the source code of the core module for more details +about the sorting algorithm in use. + +.. [#granularity-ref] That is, when mmap regions do not enforce their mapping + granularity. + +TLB maintenance operations +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The library takes care of performing TLB maintenance operations when required. +For example, when the user requests removing a dynamic region, the library +invalidates all TLB entries associated to that region to ensure that these +changes are visible to subsequent execution, including speculative execution, +that uses the changed translation table entries. + +A counter-example is the initialization of translation tables. In this case, +explicit TLB maintenance is not required. The Armv8-A architecture guarantees +that all TLBs are disabled from reset and their contents have no effect on +address translation at reset [#tlb-reset-ref]_. Therefore, the TLBs invalidation +is deferred to the ``enable_mmu*()`` family of functions, just before the MMU is +turned on. + +TLB invalidation is not required when adding dynamic regions either. Dynamic +regions are not allowed to overlap existing memory region. Therefore, if the +dynamic mapping request is deemed legitimate, it automatically concerns memory +that was not mapped in this translation regime and the library will have +initialized its corresponding translation table entry to an invalid +descriptor. Given that the TLBs are not architecturally permitted to hold any +invalid translation table entry [#tlb-no-invalid-entry]_, this means that this +mapping cannot be cached in the TLBs. + +.. [#tlb-reset-ref] See section D4.9 `Translation Lookaside Buffers (TLBs)`, subsection `TLB behavior at reset` in Armv8-A, rev C.a. +.. [#tlb-no-invalid-entry] See section D4.10.1 `General TLB maintenance requirements` in Armv8-A, rev C.a. + +-------------- + +*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* + +.. _lib/xlat_tables_v2: ../../lib/xlat_tables_v2 +.. _lib/xlat_tables: ../../lib/xlat_tables +.. _xlat_tables_v2.h: ../../include/lib/xlat_tables/xlat_tables_v2.h +.. _xlat_tables_context.c: ../../lib/xlat_tables_v2/xlat_tables_context.c +.. _xlat_tables_core.c: ../../lib/xlat_tables_v2/xlat_tables_core.c +.. _xlat_tables_utils.c: ../../lib/xlat_tables_v2/xlat_tables_utils.c +.. _aarch32/xlat_tables_arch.c: ../../lib/xlat_tables_v2/aarch32/xlat_tables_arch.c +.. _aarch64/xlat_tables_arch.c: ../../lib/xlat_tables_v2/aarch64/xlat_tables_arch.c +.. _Porting Guide: ../getting_started/porting-guide.rst +.. |Alignment Example| image:: ../diagrams/xlat_align.png?raw=true diff --git a/docs/contents.rst b/docs/contents.rst deleted file mode 100644 index 4b3f74f..0000000 --- a/docs/contents.rst +++ /dev/null @@ -1,165 +0,0 @@ -Trusted Firmware-A Documentation Contents -========================================= - -This document serves as a list of the documentation that is included with the -Trusted Firmware-A source. - -Introduction ------------- - -`About Trusted Firmware-A`_ - -Getting Started ---------------- - -`Frequently-Asked Questions (FAQ)`_ - -`Image Terminology`_ - -`Porting Guide`_ - -`User Guide`_ - -Contributing ------------- - -`Coding Style and Guidelines`_ - -`Contributor Acknowledgements`_ - -`Contributor's Guide`_ - -`License`_ - -`Maintainers`_ - -Processes and Policies ----------------------- - -`Platform Compatibility Policy`_ - -`Release Processes`_ - -Secure Payload Dispatch ------------------------ - -`OP-TEE Dispatcher`_ - -`Trusted Little Kernel (TLK) Dispatcher`_ - -`Trusty Dispatcher`_ - -System Design and Components ----------------------------- - -`Arm CPU Specific Build Macros`_ - -`Arm SiP Services`_ - -`Authentication Framework & Chain of Trust`_ - -`CPU Reset`_ - -`EL3 Runtime Service Writer’s Guide`_ - -`Exception Handling Framework`_ - -`Firmware Design Overview`_ - -`Firmware Update (FWU)`_ - -`Interrupt Management Framework`_ - -`Library at ROM`_ - -`Platform Interrupt Controller API`_ - -`PSCI Library Integration Guide for Armv8-A AArch32 systems`_ - -`PSCI Power Domain Tree design`_ - -`Reliability, Availability, and Serviceability (RAS) Extensions`_ - -`Secure Partition Manager`_ - -`Software Delegated Exception Interface`_ - -`Translation (XLAT) Tables Library`_ - -`Trusted Board Boot Design Guide`_ - -Performance and Testing ------------------------ - -`PSCI Performance Measurements on Arm Juno Development Platform`_ - -Security and Advisories ------------------------ - -`Security Processes`_ - -`TFV-1`_ - -`TFV-2`_ - -`TFV-3`_ - -`TFV-4`_ - -`TFV-5`_ - -`TFV-6`_ - -`TFV-7`_ - -`TFV-8`_ - -Other Documents ---------------- - -`Change Log`_ - -.. _About Trusted Firmware-A: ../readme.rst -.. _Frequently-Asked Questions (FAQ): ./frequently-asked-questions.rst -.. _Image Terminology: ./image-terminology.rst -.. _Porting Guide: ./porting-guide.rst -.. _User Guide: ./user-guide.rst -.. _Coding Style and Guidelines: ./coding-guidelines.rst -.. _Contributor Acknowledgements: ../acknowledgements.rst -.. _`Contributor's Guide`: ../contributing.rst -.. _License: ../license.rst -.. _Maintainers: ../maintainers.rst -.. _Platform Compatibility Policy: ./platform-compatibility-policy.rst -.. _Release Processes: ./release-information.rst -.. _Arm SiP Services: ./arm-sip-service.rst -.. _Exception Handling Framework: ./exception-handling.rst -.. _Firmware Update (FWU): ./firmware-update.rst -.. _Interrupt Management Framework: ./interrupt-framework-design.rst -.. _Library at ROM: ./romlib-design.rst -.. _Platform Interrupt Controller API: ./platform-interrupt-controller-API.rst -.. _`Reliability, Availability, and Serviceability (RAS) Extensions`: ./ras.rst -.. _Secure Partition Manager: ./secure-partition-manager-design.rst -.. _Software Delegated Exception Interface: ./sdei.rst -.. _Translation (XLAT) Tables Library: ./xlat-tables-lib-v2-design.rst -.. _OP-TEE Dispatcher: ./spd/optee-dispatcher.rst -.. _Trusted Little Kernel (TLK) Dispatcher: ./spd/tlk-dispatcher.rst -.. _Trusty Dispatcher: ./spd/trusty-dispatcher.rst -.. _Arm CPU Specific Build Macros: ./cpu-specific-build-macros.rst -.. _`Authentication Framework & Chain of Trust`: ./auth-framework.rst -.. _CPU Reset: ./reset-design.rst -.. _`EL3 Runtime Service Writer’s Guide`: ./rt-svc-writers-guide.rst -.. _Firmware Design Overview: ./firmware-design.rst -.. _PSCI Library Integration Guide for Armv8-A AArch32 systems: ./psci-lib-integration-guide.rst -.. _PSCI Power Domain Tree design: ./psci-pd-tree.rst -.. _Trusted Board Boot Design Guide: ./trusted-board-boot.rst -.. _PSCI Performance Measurements on Arm Juno Development Platform: ./psci-performance-juno.rst -.. _Security Processes: ./security-center.rst -.. _Change Log: ./change-log.rst -.. _TFV-1: ./security_advisories/security-advisory-tfv-1.rst -.. _TFV-2: ./security_advisories/security-advisory-tfv-2.rst -.. _TFV-3: ./security_advisories/security-advisory-tfv-3.rst -.. _TFV-4: ./security_advisories/security-advisory-tfv-4.rst -.. _TFV-5: ./security_advisories/security-advisory-tfv-5.rst -.. _TFV-6: ./security_advisories/security-advisory-tfv-6.rst -.. _TFV-7: ./security_advisories/security-advisory-tfv-7.rst -.. _TFV-8: ./security_advisories/security-advisory-tfv-8.rst diff --git a/docs/cpu-specific-build-macros.rst b/docs/cpu-specific-build-macros.rst deleted file mode 100644 index 493e07e..0000000 --- a/docs/cpu-specific-build-macros.rst +++ /dev/null @@ -1,299 +0,0 @@ -Arm CPU Specific Build Macros -============================= - - -.. section-numbering:: - :suffix: . - -.. contents:: - -This document describes the various build options present in the CPU specific -operations framework to enable errata workarounds and to enable optimizations -for a specific CPU on a platform. - -Security Vulnerability Workarounds ----------------------------------- - -TF-A exports a series of build flags which control which security -vulnerability workarounds should be applied at runtime. - -- ``WORKAROUND_CVE_2017_5715``: Enables the security workaround for - `CVE-2017-5715`_. This flag can be set to 0 by the platform if none - of the PEs in the system need the workaround. Setting this flag to 0 provides - no performance benefit for non-affected platforms, it just helps to comply - with the recommendation in the spec regarding workaround discovery. - Defaults to 1. - -- ``WORKAROUND_CVE_2018_3639``: Enables the security workaround for - `CVE-2018-3639`_. Defaults to 1. The TF-A project recommends to keep - the default value of 1 even on platforms that are unaffected by - CVE-2018-3639, in order to comply with the recommendation in the spec - regarding workaround discovery. - -- ``DYNAMIC_WORKAROUND_CVE_2018_3639``: Enables dynamic mitigation for - `CVE-2018-3639`_. This build option should be set to 1 if the target - platform contains at least 1 CPU that requires dynamic mitigation. - Defaults to 0. - -CPU Errata Workarounds ----------------------- - -TF-A exports a series of build flags which control the errata workarounds that -are applied to each CPU by the reset handler. The errata details can be found -in the CPU specific errata documents published by Arm: - -- `Cortex-A53 MPCore Software Developers Errata Notice`_ -- `Cortex-A57 MPCore Software Developers Errata Notice`_ -- `Cortex-A72 MPCore Software Developers Errata Notice`_ - -The errata workarounds are implemented for a particular revision or a set of -processor revisions. This is checked by the reset handler at runtime. Each -errata workaround is identified by its ``ID`` as specified in the processor's -errata notice document. The format of the define used to enable/disable the -errata workaround is ``ERRATA__``, where the ``Processor name`` -is for example ``A57`` for the ``Cortex_A57`` CPU. - -Refer to the section *CPU errata status reporting* in -`Firmware Design guide`_ for information on how to write errata workaround -functions. - -All workarounds are disabled by default. The platform is responsible for -enabling these workarounds according to its requirement by defining the -errata workaround build flags in the platform specific makefile. In case -these workarounds are enabled for the wrong CPU revision then the errata -workaround is not applied. In the DEBUG build, this is indicated by -printing a warning to the crash console. - -In the current implementation, a platform which has more than 1 variant -with different revisions of a processor has no runtime mechanism available -for it to specify which errata workarounds should be enabled or not. - -The value of the build flags is 0 by default, that is, disabled. A value of 1 -will enable it. - -For Cortex-A9, the following errata build flags are defined : - -- ``ERRATA_A9_794073``: This applies errata 794073 workaround to Cortex-A9 - CPU. This needs to be enabled for all revisions of the CPU. - -For Cortex-A15, the following errata build flags are defined : - -- ``ERRATA_A15_816470``: This applies errata 816470 workaround to Cortex-A15 - CPU. This needs to be enabled only for revision >= r3p0 of the CPU. - -- ``ERRATA_A15_827671``: This applies errata 827671 workaround to Cortex-A15 - CPU. This needs to be enabled only for revision >= r3p0 of the CPU. - -For Cortex-A17, the following errata build flags are defined : - -- ``ERRATA_A17_852421``: This applies errata 852421 workaround to Cortex-A17 - CPU. This needs to be enabled only for revision <= r1p2 of the CPU. - -- ``ERRATA_A17_852423``: This applies errata 852423 workaround to Cortex-A17 - CPU. This needs to be enabled only for revision <= r1p2 of the CPU. - -For Cortex-A35, the following errata build flags are defined : - -- ``ERRATA_A35_855472``: This applies errata 855472 workaround to Cortex-A35 - CPUs. This needs to be enabled only for revision r0p0 of Cortex-A35. - -For Cortex-A53, the following errata build flags are defined : - -- ``ERRATA_A53_819472``: This applies errata 819472 workaround to all - CPUs. This needs to be enabled only for revision <= r0p1 of Cortex-A53. - -- ``ERRATA_A53_824069``: This applies errata 824069 workaround to all - CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53. - -- ``ERRATA_A53_826319``: This applies errata 826319 workaround to Cortex-A53 - CPU. This needs to be enabled only for revision <= r0p2 of the CPU. - -- ``ERRATA_A53_827319``: This applies errata 827319 workaround to all - CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53. - -- ``ERRATA_A53_835769``: This applies erratum 835769 workaround at compile and - link time to Cortex-A53 CPU. This needs to be enabled for some variants of - revision <= r0p4. This workaround can lead the linker to create ``*.stub`` - sections. - -- ``ERRATA_A53_836870``: This applies errata 836870 workaround to Cortex-A53 - CPU. This needs to be enabled only for revision <= r0p3 of the CPU. From - r0p4 and onwards, this errata is enabled by default in hardware. - -- ``ERRATA_A53_843419``: This applies erratum 843419 workaround at link time - to Cortex-A53 CPU. This needs to be enabled for some variants of revision - <= r0p4. This workaround can lead the linker to emit ``*.stub`` sections - which are 4kB aligned. - -- ``ERRATA_A53_855873``: This applies errata 855873 workaround to Cortex-A53 - CPUs. Though the erratum is present in every revision of the CPU, - this workaround is only applied to CPUs from r0p3 onwards, which feature - a chicken bit in CPUACTLR_EL1 to enable a hardware workaround. - Earlier revisions of the CPU have other errata which require the same - workaround in software, so they should be covered anyway. - -For Cortex-A55, the following errata build flags are defined : - -- ``ERRATA_A55_768277``: This applies errata 768277 workaround to Cortex-A55 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -- ``ERRATA_A55_778703``: This applies errata 778703 workaround to Cortex-A55 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -- ``ERRATA_A55_798797``: This applies errata 798797 workaround to Cortex-A55 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -- ``ERRATA_A55_846532``: This applies errata 846532 workaround to Cortex-A55 - CPU. This needs to be enabled only for revision <= r0p1 of the CPU. - -- ``ERRATA_A55_903758``: This applies errata 903758 workaround to Cortex-A55 - CPU. This needs to be enabled only for revision <= r0p1 of the CPU. - -For Cortex-A57, the following errata build flags are defined : - -- ``ERRATA_A57_806969``: This applies errata 806969 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -- ``ERRATA_A57_813419``: This applies errata 813419 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -- ``ERRATA_A57_813420``: This applies errata 813420 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -- ``ERRATA_A57_814670``: This applies errata 814670 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -- ``ERRATA_A57_817169``: This applies errata 817169 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision <= r0p1 of the CPU. - -- ``ERRATA_A57_826974``: This applies errata 826974 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision <= r1p1 of the CPU. - -- ``ERRATA_A57_826977``: This applies errata 826977 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision <= r1p1 of the CPU. - -- ``ERRATA_A57_828024``: This applies errata 828024 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision <= r1p1 of the CPU. - -- ``ERRATA_A57_829520``: This applies errata 829520 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision <= r1p2 of the CPU. - -- ``ERRATA_A57_833471``: This applies errata 833471 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision <= r1p2 of the CPU. - -- ``ERRATA_A57_859972``: This applies errata 859972 workaround to Cortex-A57 - CPU. This needs to be enabled only for revision <= r1p3 of the CPU. - - -For Cortex-A72, the following errata build flags are defined : - -- ``ERRATA_A72_859971``: This applies errata 859971 workaround to Cortex-A72 - CPU. This needs to be enabled only for revision <= r0p3 of the CPU. - -For Cortex-A73, the following errata build flags are defined : - -- ``ERRATA_A73_852427``: This applies errata 852427 workaround to Cortex-A73 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -- ``ERRATA_A73_855423``: This applies errata 855423 workaround to Cortex-A73 - CPU. This needs to be enabled only for revision <= r0p1 of the CPU. - -For Cortex-A75, the following errata build flags are defined : - -- ``ERRATA_A75_764081``: This applies errata 764081 workaround to Cortex-A75 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -- ``ERRATA_A75_790748``: This applies errata 790748 workaround to Cortex-A75 - CPU. This needs to be enabled only for revision r0p0 of the CPU. - -For Cortex-A76, the following errata build flags are defined : - -- ``ERRATA_A76_1073348``: This applies errata 1073348 workaround to Cortex-A76 - CPU. This needs to be enabled only for revision <= r1p0 of the CPU. - -- ``ERRATA_A76_1130799``: This applies errata 1130799 workaround to Cortex-A76 - CPU. This needs to be enabled only for revision <= r2p0 of the CPU. - -- ``ERRATA_A76_1220197``: This applies errata 1220197 workaround to Cortex-A76 - CPU. This needs to be enabled only for revision <= r2p0 of the CPU. - -- ``ERRATA_A76_1257314``: This applies errata 1257314 workaround to Cortex-A76 - CPU. This needs to be enabled only for revision <= r3p0 of the CPU. - -- ``ERRATA_A76_1262606``: This applies errata 1262606 workaround to Cortex-A76 - CPU. This needs to be enabled only for revision <= r3p0 of the CPU. - -- ``ERRATA_A76_1262888``: This applies errata 1262888 workaround to Cortex-A76 - CPU. This needs to be enabled only for revision <= r3p0 of the CPU. - -- ``ERRATA_A76_1275112``: This applies errata 1275112 workaround to Cortex-A76 - CPU. This needs to be enabled only for revision <= r3p0 of the CPU. - -DSU Errata Workarounds ----------------------- - -Similar to CPU errata, TF-A also implements workarounds for DSU (DynamIQ -Shared Unit) errata. The DSU errata details can be found in the respective Arm -documentation: - -- `Arm DSU Software Developers Errata Notice`_. - -Each erratum is identified by an ``ID``, as defined in the DSU errata notice -document. Thus, the build flags which enable/disable the errata workarounds -have the format ``ERRATA_DSU_``. The implementation and application logic -of DSU errata workarounds are similar to `CPU errata workarounds`_. - -For DSU errata, the following build flags are defined: - -- ``ERRATA_DSU_798953``: This applies errata 798953 workaround for the - affected DSU configurations. This errata applies only for those DSUs that - revision is r0p0 (on r0p1 it is fixed). However, please note that this - workaround results in increased DSU power consumption on idle. - -- ``ERRATA_DSU_936184``: This applies errata 936184 workaround for the - affected DSU configurations. This errata applies only for those DSUs that - contain the ACP interface **and** the DSU revision is older than r2p0 (on - r2p0 it is fixed). However, please note that this workaround results in - increased DSU power consumption on idle. - -CPU Specific optimizations --------------------------- - -This section describes some of the optimizations allowed by the CPU micro -architecture that can be enabled by the platform as desired. - -- ``SKIP_A57_L1_FLUSH_PWR_DWN``: This flag enables an optimization in the - Cortex-A57 cluster power down sequence by not flushing the Level 1 data - cache. The L1 data cache and the L2 unified cache are inclusive. A flush - of the L2 by set/way flushes any dirty lines from the L1 as well. This - is a known safe deviation from the Cortex-A57 TRM defined power down - sequence. Each Cortex-A57 based platform must make its own decision on - whether to use the optimization. - -- ``A53_DISABLE_NON_TEMPORAL_HINT``: This flag disables the cache non-temporal - hint. The LDNP/STNP instructions as implemented on Cortex-A53 do not behave - in a way most programmers expect, and will most probably result in a - significant speed degradation to any code that employs them. The Armv8-A - architecture (see Arm DDI 0487A.h, section D3.4.3) allows cores to ignore - the non-temporal hint and treat LDNP/STNP as LDP/STP instead. Enabling this - flag enforces this behaviour. This needs to be enabled only for revisions - <= r0p3 of the CPU and is enabled by default. - -- ``A57_DISABLE_NON_TEMPORAL_HINT``: This flag has the same behaviour as - ``A53_DISABLE_NON_TEMPORAL_HINT`` but for Cortex-A57. This needs to be - enabled only for revisions <= r1p2 of the CPU and is enabled by default, - as recommended in section "4.7 Non-Temporal Loads/Stores" of the - `Cortex-A57 Software Optimization Guide`_. - --------------- - -*Copyright (c) 2014-2019, Arm Limited and Contributors. All rights reserved.* - -.. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715 -.. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639 -.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/index.html -.. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/index.html -.. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html -.. _Firmware Design guide: firmware-design.rst -.. _Cortex-A57 Software Optimization Guide: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf -.. _Arm DSU Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm138168/index.html diff --git a/docs/design/auth-framework.rst b/docs/design/auth-framework.rst new file mode 100644 index 0000000..1bc5015 --- /dev/null +++ b/docs/design/auth-framework.rst @@ -0,0 +1,971 @@ +Abstracting a Chain of Trust +============================ + + + + +.. contents:: + +The aim of this document is to describe the authentication framework +implemented in Trusted Firmware-A (TF-A). This framework fulfills the +following requirements: + +#. It should be possible for a platform port to specify the Chain of Trust in + terms of certificate hierarchy and the mechanisms used to verify a + particular image/certificate. + +#. The framework should distinguish between: + + - The mechanism used to encode and transport information, e.g. DER encoded + X.509v3 certificates to ferry Subject Public Keys, hashes and non-volatile + counters. + + - The mechanism used to verify the transported information i.e. the + cryptographic libraries. + +The framework has been designed following a modular approach illustrated in the +next diagram: + +:: + + +---------------+---------------+------------+ + | Trusted | Trusted | Trusted | + | Firmware | Firmware | Firmware | + | Generic | IO Framework | Platform | + | Code i.e. | (IO) | Port | + | BL1/BL2 (GEN) | | (PP) | + +---------------+---------------+------------+ + ^ ^ ^ + | | | + v v v + +-----------+ +-----------+ +-----------+ + | | | | | Image | + | Crypto | | Auth | | Parser | + | Module |<->| Module |<->| Module | + | (CM) | | (AM) | | (IPM) | + | | | | | | + +-----------+ +-----------+ +-----------+ + ^ ^ + | | + v v + +----------------+ +-----------------+ + | Cryptographic | | Image Parser | + | Libraries (CL) | | Libraries (IPL) | + +----------------+ +-----------------+ + | | + | | + | | + v v + +-----------------+ + | Misc. Libs e.g. | + | ASN.1 decoder | + | | + +-----------------+ + + DIAGRAM 1. + +This document describes the inner details of the authentication framework and +the abstraction mechanisms available to specify a Chain of Trust. + +Framework design +---------------- + +This section describes some aspects of the framework design and the rationale +behind them. These aspects are key to verify a Chain of Trust. + +Chain of Trust +~~~~~~~~~~~~~~ + +A CoT is basically a sequence of authentication images which usually starts with +a root of trust and culminates in a single data image. The following diagram +illustrates how this maps to a CoT for the BL31 image described in the +`TBBR-Client specification`_. + +:: + + +------------------+ +-------------------+ + | ROTPK/ROTPK Hash |------>| Trusted Key | + +------------------+ | Certificate | + | (Auth Image) | + /+-------------------+ + / | + / | + / | + / | + L v + +------------------+ +-------------------+ + | Trusted World |------>| BL31 Key | + | Public Key | | Certificate | + +------------------+ | (Auth Image) | + +-------------------+ + / | + / | + / | + / | + / v + +------------------+ L +-------------------+ + | BL31 Content |------>| BL31 Content | + | Certificate PK | | Certificate | + +------------------+ | (Auth Image) | + +-------------------+ + / | + / | + / | + / | + / v + +------------------+ L +-------------------+ + | BL31 Hash |------>| BL31 Image | + | | | (Data Image) | + +------------------+ | | + +-------------------+ + + DIAGRAM 2. + +The root of trust is usually a public key (ROTPK) that has been burnt in the +platform and cannot be modified. + +Image types +~~~~~~~~~~~ + +Images in a CoT are categorised as authentication and data images. An +authentication image contains information to authenticate a data image or +another authentication image. A data image is usually a boot loader binary, but +it could be any other data that requires authentication. + +Component responsibilities +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For every image in a Chain of Trust, the following high level operations are +performed to verify it: + +#. Allocate memory for the image either statically or at runtime. + +#. Identify the image and load it in the allocated memory. + +#. Check the integrity of the image as per its type. + +#. Authenticate the image as per the cryptographic algorithms used. + +#. If the image is an authentication image, extract the information that will + be used to authenticate the next image in the CoT. + +In Diagram 1, each component is responsible for one or more of these operations. +The responsibilities are briefly described below. + +TF-A Generic code and IO framework (GEN/IO) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These components are responsible for initiating the authentication process for a +particular image in BL1 or BL2. For each BL image that requires authentication, +the Generic code asks recursively the Authentication module what is the parent +image until either an authenticated image or the ROT is reached. Then the +Generic code calls the IO framework to load the image and calls the +Authentication module to authenticate it, following the CoT from ROT to Image. + +TF-A Platform Port (PP) +^^^^^^^^^^^^^^^^^^^^^^^ + +The platform is responsible for: + +#. Specifying the CoT for each image that needs to be authenticated. Details of + how a CoT can be specified by the platform are explained later. The platform + also specifies the authentication methods and the parsing method used for + each image. + +#. Statically allocating memory for each parameter in each image which is + used for verifying the CoT, e.g. memory for public keys, hashes etc. + +#. Providing the ROTPK or a hash of it. + +#. Providing additional information to the IPM to enable it to identify and + extract authentication parameters contained in an image, e.g. if the + parameters are stored as X509v3 extensions, the corresponding OID must be + provided. + +#. Fulfill any other memory requirements of the IPM and the CM (not currently + described in this document). + +#. Export functions to verify an image which uses an authentication method that + cannot be interpreted by the CM, e.g. if an image has to be verified using a + NV counter, then the value of the counter to compare with can only be + provided by the platform. + +#. Export a custom IPM if a proprietary image format is being used (described + later). + +Authentication Module (AM) +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is responsible for: + +#. Providing the necessary abstraction mechanisms to describe a CoT. Amongst + other things, the authentication and image parsing methods must be specified + by the PP in the CoT. + +#. Verifying the CoT passed by GEN by utilising functionality exported by the + PP, IPM and CM. + +#. Tracking which images have been verified. In case an image is a part of + multiple CoTs then it should be verified only once e.g. the Trusted World + Key Certificate in the TBBR-Client spec. contains information to verify + SCP_BL2, BL31, BL32 each of which have a separate CoT. (This + responsibility has not been described in this document but should be + trivial to implement). + +#. Reusing memory meant for a data image to verify authentication images e.g. + in the CoT described in Diagram 2, each certificate can be loaded and + verified in the memory reserved by the platform for the BL31 image. By the + time BL31 (the data image) is loaded, all information to authenticate it + will have been extracted from the parent image i.e. BL31 content + certificate. It is assumed that the size of an authentication image will + never exceed the size of a data image. It should be possible to verify this + at build time using asserts. + +Cryptographic Module (CM) +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The CM is responsible for providing an API to: + +#. Verify a digital signature. +#. Verify a hash. + +The CM does not include any cryptography related code, but it relies on an +external library to perform the cryptographic operations. A Crypto-Library (CL) +linking the CM and the external library must be implemented. The following +functions must be provided by the CL: + +.. code:: c + + void (*init)(void); + int (*verify_signature)(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len); + int (*verify_hash)(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); + +These functions are registered in the CM using the macro: + +.. code:: c + + REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash); + +``_name`` must be a string containing the name of the CL. This name is used for +debugging purposes. + +Image Parser Module (IPM) +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The IPM is responsible for: + +#. Checking the integrity of each image loaded by the IO framework. +#. Extracting parameters used for authenticating an image based upon a + description provided by the platform in the CoT descriptor. + +Images may have different formats (for example, authentication images could be +x509v3 certificates, signed ELF files or any other platform specific format). +The IPM allows to register an Image Parser Library (IPL) for every image format +used in the CoT. This library must implement the specific methods to parse the +image. The IPM obtains the image format from the CoT and calls the right IPL to +check the image integrity and extract the authentication parameters. + +See Section "Describing the image parsing methods" for more details about the +mechanism the IPM provides to define and register IPLs. + +Authentication methods +~~~~~~~~~~~~~~~~~~~~~~ + +The AM supports the following authentication methods: + +#. Hash +#. Digital signature + +The platform may specify these methods in the CoT in case it decides to define +a custom CoT instead of reusing a predefined one. + +If a data image uses multiple methods, then all the methods must be a part of +the same CoT. The number and type of parameters are method specific. These +parameters should be obtained from the parent image using the IPM. + +#. Hash + + Parameters: + + #. A pointer to data to hash + #. Length of the data + #. A pointer to the hash + #. Length of the hash + + The hash will be represented by the DER encoding of the following ASN.1 + type: + + :: + + DigestInfo ::= SEQUENCE { + digestAlgorithm DigestAlgorithmIdentifier, + digest Digest + } + + This ASN.1 structure makes it possible to remove any assumption about the + type of hash algorithm used as this information accompanies the hash. This + should allow the Cryptography Library (CL) to support multiple hash + algorithm implementations. + +#. Digital Signature + + Parameters: + + #. A pointer to data to sign + #. Length of the data + #. Public Key Algorithm + #. Public Key value + #. Digital Signature Algorithm + #. Digital Signature value + + The Public Key parameters will be represented by the DER encoding of the + following ASN.1 type: + + :: + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier{PUBLIC-KEY,{PublicKeyAlgorithms}}, + subjectPublicKey BIT STRING } + + The Digital Signature Algorithm will be represented by the DER encoding of + the following ASN.1 types. + + :: + + AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE { + algorithm ALGORITHM.&id({IOSet}), + parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL + } + + The digital signature will be represented by: + + :: + + signature ::= BIT STRING + +The authentication framework will use the image descriptor to extract all the +information related to authentication. + +Specifying a Chain of Trust +--------------------------- + +A CoT can be described as a set of image descriptors linked together in a +particular order. The order dictates the sequence in which they must be +verified. Each image has a set of properties which allow the AM to verify it. +These properties are described below. + +The PP is responsible for defining a single or multiple CoTs for a data image. +Unless otherwise specified, the data structures described in the following +sections are populated by the PP statically. + +Describing the image parsing methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The parsing method refers to the format of a particular image. For example, an +authentication image that represents a certificate could be in the X.509v3 +format. A data image that represents a boot loader stage could be in raw binary +or ELF format. The IPM supports three parsing methods. An image has to use one +of the three methods described below. An IPL is responsible for interpreting a +single parsing method. There has to be one IPL for every method used by the +platform. + +#. Raw format: This format is effectively a nop as an image using this method + is treated as being in raw binary format e.g. boot loader images used by + TF-A. This method should only be used by data images. + +#. X509V3 method: This method uses industry standards like X.509 to represent + PKI certificates (authentication images). It is expected that open source + libraries will be available which can be used to parse an image represented + by this method. Such libraries can be used to write the corresponding IPL + e.g. the X.509 parsing library code in mbed TLS. + +#. Platform defined method: This method caters for platform specific + proprietary standards to represent authentication or data images. For + example, The signature of a data image could be appended to the data image + raw binary. A header could be prepended to the combined blob to specify the + extents of each component. The platform will have to implement the + corresponding IPL to interpret such a format. + +The following enum can be used to define these three methods. + +.. code:: c + + typedef enum img_type_enum { + IMG_RAW, /* Binary image */ + IMG_PLAT, /* Platform specific format */ + IMG_CERT, /* X509v3 certificate */ + IMG_MAX_TYPES, + } img_type_t; + +An IPL must provide functions with the following prototypes: + +.. code:: c + + void init(void); + int check_integrity(void *img, unsigned int img_len); + int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len); + +An IPL for each type must be registered using the following macro: + +:: + + REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param) + +- ``_type``: one of the types described above. +- ``_name``: a string containing the IPL name for debugging purposes. +- ``_init``: initialization function pointer. +- ``_check_int``: check image integrity function pointer. +- ``_get_param``: extract authentication parameter function pointer. + +The ``init()`` function will be used to initialize the IPL. + +The ``check_integrity()`` function is passed a pointer to the memory where the +image has been loaded by the IO framework and the image length. It should ensure +that the image is in the format corresponding to the parsing method and has not +been tampered with. For example, RFC-2459 describes a validation sequence for an +X.509 certificate. + +The ``get_auth_param()`` function is passed a parameter descriptor containing +information about the parameter (``type_desc`` and ``cookie``) to identify and +extract the data corresponding to that parameter from an image. This data will +be used to verify either the current or the next image in the CoT sequence. + +Each image in the CoT will specify the parsing method it uses. This information +will be used by the IPM to find the right parser descriptor for the image. + +Describing the authentication method(s) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As part of the CoT, each image has to specify one or more authentication methods +which will be used to verify it. As described in the Section "Authentication +methods", there are three methods supported by the AM. + +.. code:: c + + typedef enum { + AUTH_METHOD_NONE, + AUTH_METHOD_HASH, + AUTH_METHOD_SIG, + AUTH_METHOD_NUM + } auth_method_type_t; + +The AM defines the type of each parameter used by an authentication method. It +uses this information to: + +#. Specify to the ``get_auth_param()`` function exported by the IPM, which + parameter should be extracted from an image. + +#. Correctly marshall the parameters while calling the verification function + exported by the CM and PP. + +#. Extract authentication parameters from a parent image in order to verify a + child image e.g. to verify the certificate image, the public key has to be + obtained from the parent image. + +.. code:: c + + typedef enum { + AUTH_PARAM_NONE, + AUTH_PARAM_RAW_DATA, /* Raw image data */ + AUTH_PARAM_SIG, /* The image signature */ + AUTH_PARAM_SIG_ALG, /* The image signature algorithm */ + AUTH_PARAM_HASH, /* A hash (including the algorithm) */ + AUTH_PARAM_PUB_KEY, /* A public key */ + } auth_param_type_t; + +The AM defines the following structure to identify an authentication parameter +required to verify an image. + +.. code:: c + + typedef struct auth_param_type_desc_s { + auth_param_type_t type; + void *cookie; + } auth_param_type_desc_t; + +``cookie`` is used by the platform to specify additional information to the IPM +which enables it to uniquely identify the parameter that should be extracted +from an image. For example, the hash of a BL3x image in its corresponding +content certificate is stored in an X509v3 custom extension field. An extension +field can only be identified using an OID. In this case, the ``cookie`` could +contain the pointer to the OID defined by the platform for the hash extension +field while the ``type`` field could be set to ``AUTH_PARAM_HASH``. A value of 0 for +the ``cookie`` field means that it is not used. + +For each method, the AM defines a structure with the parameters required to +verify the image. + +.. code:: c + + /* + * Parameters for authentication by hash matching + */ + typedef struct auth_method_param_hash_s { + auth_param_type_desc_t *data; /* Data to hash */ + auth_param_type_desc_t *hash; /* Hash to match with */ + } auth_method_param_hash_t; + + /* + * Parameters for authentication by signature + */ + typedef struct auth_method_param_sig_s { + auth_param_type_desc_t *pk; /* Public key */ + auth_param_type_desc_t *sig; /* Signature to check */ + auth_param_type_desc_t *alg; /* Signature algorithm */ + auth_param_type_desc_t *tbs; /* Data signed */ + } auth_method_param_sig_t; + +The AM defines the following structure to describe an authentication method for +verifying an image + +.. code:: c + + /* + * Authentication method descriptor + */ + typedef struct auth_method_desc_s { + auth_method_type_t type; + union { + auth_method_param_hash_t hash; + auth_method_param_sig_t sig; + } param; + } auth_method_desc_t; + +Using the method type specified in the ``type`` field, the AM finds out what field +needs to access within the ``param`` union. + +Storing Authentication parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A parameter described by ``auth_param_type_desc_t`` to verify an image could be +obtained from either the image itself or its parent image. The memory allocated +for loading the parent image will be reused for loading the child image. Hence +parameters which are obtained from the parent for verifying a child image need +to have memory allocated for them separately where they can be stored. This +memory must be statically allocated by the platform port. + +The AM defines the following structure to store the data corresponding to an +authentication parameter. + +.. code:: c + + typedef struct auth_param_data_desc_s { + void *auth_param_ptr; + unsigned int auth_param_len; + } auth_param_data_desc_t; + +The ``auth_param_ptr`` field is initialized by the platform. The ``auth_param_len`` +field is used to specify the length of the data in the memory. + +For parameters that can be obtained from the child image itself, the IPM is +responsible for populating the ``auth_param_ptr`` and ``auth_param_len`` fields +while executing the ``img_get_auth_param()`` function. + +The AM defines the following structure to enable an image to describe the +parameters that should be extracted from it and used to verify the next image +(child) in a CoT. + +.. code:: c + + typedef struct auth_param_desc_s { + auth_param_type_desc_t type_desc; + auth_param_data_desc_t data; + } auth_param_desc_t; + +Describing an image in a CoT +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An image in a CoT is a consolidation of the following aspects of a CoT described +above. + +#. A unique identifier specified by the platform which allows the IO framework + to locate the image in a FIP and load it in the memory reserved for the data + image in the CoT. + +#. A parsing method which is used by the AM to find the appropriate IPM. + +#. Authentication methods and their parameters as described in the previous + section. These are used to verify the current image. + +#. Parameters which are used to verify the next image in the current CoT. These + parameters are specified only by authentication images and can be extracted + from the current image once it has been verified. + +The following data structure describes an image in a CoT. + +.. code:: c + + typedef struct auth_img_desc_s { + unsigned int img_id; + const struct auth_img_desc_s *parent; + img_type_t img_type; + const auth_method_desc_t *const img_auth_methods; + const auth_param_desc_t *const authenticated_data; + } auth_img_desc_t; + +A CoT is defined as an array of pointers to ``auth_image_desc_t`` structures +linked together by the ``parent`` field. Those nodes with no parent must be +authenticated using the ROTPK stored in the platform. + +Implementation example +---------------------- + +This section is a detailed guide explaining a trusted boot implementation using +the authentication framework. This example corresponds to the Applicative +Functional Mode (AFM) as specified in the TBBR-Client document. It is +recommended to read this guide along with the source code. + +The TBBR CoT +~~~~~~~~~~~~ + +The CoT can be found in ``drivers/auth/tbbr/tbbr_cot.c``. This CoT consists of +an array of pointers to image descriptors and it is registered in the framework +using the macro ``REGISTER_COT(cot_desc)``, where 'cot_desc' must be the name +of the array (passing a pointer or any other type of indirection will cause the +registration process to fail). + +The number of images participating in the boot process depends on the CoT. +There is, however, a minimum set of images that are mandatory in TF-A and thus +all CoTs must present: + +- ``BL2`` +- ``SCP_BL2`` (platform specific) +- ``BL31`` +- ``BL32`` (optional) +- ``BL33`` + +The TBBR specifies the additional certificates that must accompany these images +for a proper authentication. Details about the TBBR CoT may be found in the +`Trusted Board Boot`_ document. + +Following the `Platform Porting Guide`_, a platform must provide unique +identifiers for all the images and certificates that will be loaded during the +boot process. If a platform is using the TBBR as a reference for trusted boot, +these identifiers can be obtained from ``include/common/tbbr/tbbr_img_def.h``. +Arm platforms include this file in ``include/plat/arm/common/arm_def.h``. Other +platforms may also include this file or provide their own identifiers. + +**Important**: the authentication module uses these identifiers to index the +CoT array, so the descriptors location in the array must match the identifiers. + +Each image descriptor must specify: + +- ``img_id``: the corresponding image unique identifier defined by the platform. +- ``img_type``: the image parser module uses the image type to call the proper + parsing library to check the image integrity and extract the required + authentication parameters. Three types of images are currently supported: + + - ``IMG_RAW``: image is a raw binary. No parsing functions are available, + other than reading the whole image. + - ``IMG_PLAT``: image format is platform specific. The platform may use this + type for custom images not directly supported by the authentication + framework. + - ``IMG_CERT``: image is an x509v3 certificate. + +- ``parent``: pointer to the parent image descriptor. The parent will contain + the information required to authenticate the current image. If the parent + is NULL, the authentication parameters will be obtained from the platform + (i.e. the BL2 and Trusted Key certificates are signed with the ROT private + key, whose public part is stored in the platform). +- ``img_auth_methods``: this points to an array which defines the + authentication methods that must be checked to consider an image + authenticated. Each method consists of a type and a list of parameter + descriptors. A parameter descriptor consists of a type and a cookie which + will point to specific information required to extract that parameter from + the image (i.e. if the parameter is stored in an x509v3 extension, the + cookie will point to the extension OID). Depending on the method type, a + different number of parameters must be specified. This pointer should not be + NULL. + Supported methods are: + + - ``AUTH_METHOD_HASH``: the hash of the image must match the hash extracted + from the parent image. The following parameter descriptors must be + specified: + + - ``data``: data to be hashed (obtained from current image) + - ``hash``: reference hash (obtained from parent image) + + - ``AUTH_METHOD_SIG``: the image (usually a certificate) must be signed with + the private key whose public part is extracted from the parent image (or + the platform if the parent is NULL). The following parameter descriptors + must be specified: + + - ``pk``: the public key (obtained from parent image) + - ``sig``: the digital signature (obtained from current image) + - ``alg``: the signature algorithm used (obtained from current image) + - ``data``: the data to be signed (obtained from current image) + +- ``authenticated_data``: this array pointer indicates what authentication + parameters must be extracted from an image once it has been authenticated. + Each parameter consists of a parameter descriptor and the buffer + address/size to store the parameter. The CoT is responsible for allocating + the required memory to store the parameters. This pointer may be NULL. + +In the ``tbbr_cot.c`` file, a set of buffers are allocated to store the parameters +extracted from the certificates. In the case of the TBBR CoT, these parameters +are hashes and public keys. In DER format, an RSA-2048 public key requires 294 +bytes, and a hash requires 51 bytes. Depending on the CoT and the authentication +process, some of the buffers may be reused at different stages during the boot. + +Next in that file, the parameter descriptors are defined. These descriptors will +be used to extract the parameter data from the corresponding image. + +Example: the BL31 Chain of Trust +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Four image descriptors form the BL31 Chain of Trust: + +.. code:: c + + static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } + }; + static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } + }; + static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &soc_fw_config_hash, + .data = { + .ptr = (void *)soc_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } + }; + static const auth_img_desc_t bl31_image = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &soc_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_hash + } + } + } + }; + +The **Trusted Key certificate** is signed with the ROT private key and contains +the Trusted World public key and the Non-Trusted World public key as x509v3 +extensions. This must be specified in the image descriptor using the +``img_auth_methods`` and ``authenticated_data`` arrays, respectively. + +The Trusted Key certificate is authenticated by checking its digital signature +using the ROTPK. Four parameters are required to check a signature: the public +key, the algorithm, the signature and the data that has been signed. Therefore, +four parameter descriptors must be specified with the authentication method: + +- ``subject_pk``: parameter descriptor of type ``AUTH_PARAM_PUB_KEY``. This type + is used to extract a public key from the parent image. If the cookie is an + OID, the key is extracted from the corresponding x509v3 extension. If the + cookie is NULL, the subject public key is retrieved. In this case, because + the parent image is NULL, the public key is obtained from the platform + (this key will be the ROTPK). +- ``sig``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to extract + the signature from the certificate. +- ``sig_alg``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to + extract the signature algorithm from the certificate. +- ``raw_data``: parameter descriptor of type ``AUTH_PARAM_RAW_DATA``. It is used + to extract the data to be signed from the certificate. + +Once the signature has been checked and the certificate authenticated, the +Trusted World public key needs to be extracted from the certificate. A new entry +is created in the ``authenticated_data`` array for that purpose. In that entry, +the corresponding parameter descriptor must be specified along with the buffer +address to store the parameter value. In this case, the ``tz_world_pk`` descriptor +is used to extract the public key from an x509v3 extension with OID +``TRUSTED_WORLD_PK_OID``. The BL31 key certificate will use this descriptor as +parameter in the signature authentication method. The key is stored in the +``plat_tz_world_pk_buf`` buffer. + +The **BL31 Key certificate** is authenticated by checking its digital signature +using the Trusted World public key obtained previously from the Trusted Key +certificate. In the image descriptor, we specify a single authentication method +by signature whose public key is the ``tz_world_pk``. Once this certificate has +been authenticated, we have to extract the BL31 public key, stored in the +extension specified by ``bl31_content_pk``. This key will be copied to the +``plat_content_pk`` buffer. + +The **BL31 certificate** is authenticated by checking its digital signature +using the BL31 public key obtained previously from the BL31 Key certificate. +We specify the authentication method using ``bl31_content_pk`` as public key. +After authentication, we need to extract the BL31 hash, stored in the extension +specified by ``bl31_hash``. This hash will be copied to the ``plat_bl31_hash_buf`` +buffer. + +The **BL31 image** is authenticated by calculating its hash and matching it +with the hash obtained from the BL31 certificate. The image descriptor contains +a single authentication method by hash. The parameters to the hash method are +the reference hash, ``bl31_hash``, and the data to be hashed. In this case, it is +the whole image, so we specify ``raw_data``. + +The image parser library +~~~~~~~~~~~~~~~~~~~~~~~~ + +The image parser module relies on libraries to check the image integrity and +extract the authentication parameters. The number and type of parser libraries +depend on the images used in the CoT. Raw images do not need a library, so +only an x509v3 library is required for the TBBR CoT. + +Arm platforms will use an x509v3 library based on mbed TLS. This library may be +found in ``drivers/auth/mbedtls/mbedtls_x509_parser.c``. It exports three +functions: + +.. code:: c + + void init(void); + int check_integrity(void *img, unsigned int img_len); + int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len); + +The library is registered in the framework using the macro +``REGISTER_IMG_PARSER_LIB()``. Each time the image parser module needs to access +an image of type ``IMG_CERT``, it will call the corresponding function exported +in this file. + +The build system must be updated to include the corresponding library and +mbed TLS sources. Arm platforms use the ``arm_common.mk`` file to pull the +sources. + +The cryptographic library +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The cryptographic module relies on a library to perform the required operations, +i.e. verify a hash or a digital signature. Arm platforms will use a library +based on mbed TLS, which can be found in +``drivers/auth/mbedtls/mbedtls_crypto.c``. This library is registered in the +authentication framework using the macro ``REGISTER_CRYPTO_LIB()`` and exports +three functions: + +.. code:: c + + void init(void); + int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len); + int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); + +The mbedTLS library algorithm support is configured by the +``TF_MBEDTLS_KEY_ALG`` variable which can take in 3 values: `rsa`, `ecdsa` or +`rsa+ecdsa`. This variable allows the Makefile to include the corresponding +sources in the build for the various algorithms. Setting the variable to +`rsa+ecdsa` enables support for both rsa and ecdsa algorithms in the mbedTLS +library. + +Note: If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can +be defined in the platform Makefile. It will make mbed TLS use an implementation +of SHA-256 with smaller memory footprint (~1.5 KB less) but slower (~30%). + +-------------- + +*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Trusted Board Boot: ./trusted-board-boot.rst +.. _Platform Porting Guide: ../getting_started/porting-guide.rst +.. _TBBR-Client specification: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst new file mode 100644 index 0000000..d099ebe --- /dev/null +++ b/docs/design/cpu-specific-build-macros.rst @@ -0,0 +1,298 @@ +Arm CPU Specific Build Macros +============================= + + + + +.. contents:: + +This document describes the various build options present in the CPU specific +operations framework to enable errata workarounds and to enable optimizations +for a specific CPU on a platform. + +Security Vulnerability Workarounds +---------------------------------- + +TF-A exports a series of build flags which control which security +vulnerability workarounds should be applied at runtime. + +- ``WORKAROUND_CVE_2017_5715``: Enables the security workaround for + `CVE-2017-5715`_. This flag can be set to 0 by the platform if none + of the PEs in the system need the workaround. Setting this flag to 0 provides + no performance benefit for non-affected platforms, it just helps to comply + with the recommendation in the spec regarding workaround discovery. + Defaults to 1. + +- ``WORKAROUND_CVE_2018_3639``: Enables the security workaround for + `CVE-2018-3639`_. Defaults to 1. The TF-A project recommends to keep + the default value of 1 even on platforms that are unaffected by + CVE-2018-3639, in order to comply with the recommendation in the spec + regarding workaround discovery. + +- ``DYNAMIC_WORKAROUND_CVE_2018_3639``: Enables dynamic mitigation for + `CVE-2018-3639`_. This build option should be set to 1 if the target + platform contains at least 1 CPU that requires dynamic mitigation. + Defaults to 0. + +CPU Errata Workarounds +---------------------- + +TF-A exports a series of build flags which control the errata workarounds that +are applied to each CPU by the reset handler. The errata details can be found +in the CPU specific errata documents published by Arm: + +- `Cortex-A53 MPCore Software Developers Errata Notice`_ +- `Cortex-A57 MPCore Software Developers Errata Notice`_ +- `Cortex-A72 MPCore Software Developers Errata Notice`_ + +The errata workarounds are implemented for a particular revision or a set of +processor revisions. This is checked by the reset handler at runtime. Each +errata workaround is identified by its ``ID`` as specified in the processor's +errata notice document. The format of the define used to enable/disable the +errata workaround is ``ERRATA__``, where the ``Processor name`` +is for example ``A57`` for the ``Cortex_A57`` CPU. + +Refer to the section *CPU errata status reporting* in +`Firmware Design guide`_ for information on how to write errata workaround +functions. + +All workarounds are disabled by default. The platform is responsible for +enabling these workarounds according to its requirement by defining the +errata workaround build flags in the platform specific makefile. In case +these workarounds are enabled for the wrong CPU revision then the errata +workaround is not applied. In the DEBUG build, this is indicated by +printing a warning to the crash console. + +In the current implementation, a platform which has more than 1 variant +with different revisions of a processor has no runtime mechanism available +for it to specify which errata workarounds should be enabled or not. + +The value of the build flags is 0 by default, that is, disabled. A value of 1 +will enable it. + +For Cortex-A9, the following errata build flags are defined : + +- ``ERRATA_A9_794073``: This applies errata 794073 workaround to Cortex-A9 + CPU. This needs to be enabled for all revisions of the CPU. + +For Cortex-A15, the following errata build flags are defined : + +- ``ERRATA_A15_816470``: This applies errata 816470 workaround to Cortex-A15 + CPU. This needs to be enabled only for revision >= r3p0 of the CPU. + +- ``ERRATA_A15_827671``: This applies errata 827671 workaround to Cortex-A15 + CPU. This needs to be enabled only for revision >= r3p0 of the CPU. + +For Cortex-A17, the following errata build flags are defined : + +- ``ERRATA_A17_852421``: This applies errata 852421 workaround to Cortex-A17 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +- ``ERRATA_A17_852423``: This applies errata 852423 workaround to Cortex-A17 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +For Cortex-A35, the following errata build flags are defined : + +- ``ERRATA_A35_855472``: This applies errata 855472 workaround to Cortex-A35 + CPUs. This needs to be enabled only for revision r0p0 of Cortex-A35. + +For Cortex-A53, the following errata build flags are defined : + +- ``ERRATA_A53_819472``: This applies errata 819472 workaround to all + CPUs. This needs to be enabled only for revision <= r0p1 of Cortex-A53. + +- ``ERRATA_A53_824069``: This applies errata 824069 workaround to all + CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53. + +- ``ERRATA_A53_826319``: This applies errata 826319 workaround to Cortex-A53 + CPU. This needs to be enabled only for revision <= r0p2 of the CPU. + +- ``ERRATA_A53_827319``: This applies errata 827319 workaround to all + CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53. + +- ``ERRATA_A53_835769``: This applies erratum 835769 workaround at compile and + link time to Cortex-A53 CPU. This needs to be enabled for some variants of + revision <= r0p4. This workaround can lead the linker to create ``*.stub`` + sections. + +- ``ERRATA_A53_836870``: This applies errata 836870 workaround to Cortex-A53 + CPU. This needs to be enabled only for revision <= r0p3 of the CPU. From + r0p4 and onwards, this errata is enabled by default in hardware. + +- ``ERRATA_A53_843419``: This applies erratum 843419 workaround at link time + to Cortex-A53 CPU. This needs to be enabled for some variants of revision + <= r0p4. This workaround can lead the linker to emit ``*.stub`` sections + which are 4kB aligned. + +- ``ERRATA_A53_855873``: This applies errata 855873 workaround to Cortex-A53 + CPUs. Though the erratum is present in every revision of the CPU, + this workaround is only applied to CPUs from r0p3 onwards, which feature + a chicken bit in CPUACTLR_EL1 to enable a hardware workaround. + Earlier revisions of the CPU have other errata which require the same + workaround in software, so they should be covered anyway. + +For Cortex-A55, the following errata build flags are defined : + +- ``ERRATA_A55_768277``: This applies errata 768277 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A55_778703``: This applies errata 778703 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A55_798797``: This applies errata 798797 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A55_846532``: This applies errata 846532 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +- ``ERRATA_A55_903758``: This applies errata 903758 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +For Cortex-A57, the following errata build flags are defined : + +- ``ERRATA_A57_806969``: This applies errata 806969 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_813419``: This applies errata 813419 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_813420``: This applies errata 813420 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_814670``: This applies errata 814670 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_817169``: This applies errata 817169 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +- ``ERRATA_A57_826974``: This applies errata 826974 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A57_826977``: This applies errata 826977 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A57_828024``: This applies errata 828024 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A57_829520``: This applies errata 829520 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +- ``ERRATA_A57_833471``: This applies errata 833471 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +- ``ERRATA_A57_859972``: This applies errata 859972 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p3 of the CPU. + + +For Cortex-A72, the following errata build flags are defined : + +- ``ERRATA_A72_859971``: This applies errata 859971 workaround to Cortex-A72 + CPU. This needs to be enabled only for revision <= r0p3 of the CPU. + +For Cortex-A73, the following errata build flags are defined : + +- ``ERRATA_A73_852427``: This applies errata 852427 workaround to Cortex-A73 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A73_855423``: This applies errata 855423 workaround to Cortex-A73 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +For Cortex-A75, the following errata build flags are defined : + +- ``ERRATA_A75_764081``: This applies errata 764081 workaround to Cortex-A75 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A75_790748``: This applies errata 790748 workaround to Cortex-A75 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +For Cortex-A76, the following errata build flags are defined : + +- ``ERRATA_A76_1073348``: This applies errata 1073348 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r1p0 of the CPU. + +- ``ERRATA_A76_1130799``: This applies errata 1130799 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_A76_1220197``: This applies errata 1220197 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_A76_1257314``: This applies errata 1257314 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1262606``: This applies errata 1262606 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1262888``: This applies errata 1262888 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1275112``: This applies errata 1275112 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +DSU Errata Workarounds +---------------------- + +Similar to CPU errata, TF-A also implements workarounds for DSU (DynamIQ +Shared Unit) errata. The DSU errata details can be found in the respective Arm +documentation: + +- `Arm DSU Software Developers Errata Notice`_. + +Each erratum is identified by an ``ID``, as defined in the DSU errata notice +document. Thus, the build flags which enable/disable the errata workarounds +have the format ``ERRATA_DSU_``. The implementation and application logic +of DSU errata workarounds are similar to `CPU errata workarounds`_. + +For DSU errata, the following build flags are defined: + +- ``ERRATA_DSU_798953``: This applies errata 798953 workaround for the + affected DSU configurations. This errata applies only for those DSUs that + revision is r0p0 (on r0p1 it is fixed). However, please note that this + workaround results in increased DSU power consumption on idle. + +- ``ERRATA_DSU_936184``: This applies errata 936184 workaround for the + affected DSU configurations. This errata applies only for those DSUs that + contain the ACP interface **and** the DSU revision is older than r2p0 (on + r2p0 it is fixed). However, please note that this workaround results in + increased DSU power consumption on idle. + +CPU Specific optimizations +-------------------------- + +This section describes some of the optimizations allowed by the CPU micro +architecture that can be enabled by the platform as desired. + +- ``SKIP_A57_L1_FLUSH_PWR_DWN``: This flag enables an optimization in the + Cortex-A57 cluster power down sequence by not flushing the Level 1 data + cache. The L1 data cache and the L2 unified cache are inclusive. A flush + of the L2 by set/way flushes any dirty lines from the L1 as well. This + is a known safe deviation from the Cortex-A57 TRM defined power down + sequence. Each Cortex-A57 based platform must make its own decision on + whether to use the optimization. + +- ``A53_DISABLE_NON_TEMPORAL_HINT``: This flag disables the cache non-temporal + hint. The LDNP/STNP instructions as implemented on Cortex-A53 do not behave + in a way most programmers expect, and will most probably result in a + significant speed degradation to any code that employs them. The Armv8-A + architecture (see Arm DDI 0487A.h, section D3.4.3) allows cores to ignore + the non-temporal hint and treat LDNP/STNP as LDP/STP instead. Enabling this + flag enforces this behaviour. This needs to be enabled only for revisions + <= r0p3 of the CPU and is enabled by default. + +- ``A57_DISABLE_NON_TEMPORAL_HINT``: This flag has the same behaviour as + ``A53_DISABLE_NON_TEMPORAL_HINT`` but for Cortex-A57. This needs to be + enabled only for revisions <= r1p2 of the CPU and is enabled by default, + as recommended in section "4.7 Non-Temporal Loads/Stores" of the + `Cortex-A57 Software Optimization Guide`_. + +-------------- + +*Copyright (c) 2014-2019, Arm Limited and Contributors. All rights reserved.* + +.. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715 +.. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639 +.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/index.html +.. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/index.html +.. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html +.. _Firmware Design guide: firmware-design.rst +.. _Cortex-A57 Software Optimization Guide: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf +.. _Arm DSU Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm138168/index.html diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst new file mode 100644 index 0000000..e7107ba --- /dev/null +++ b/docs/design/firmware-design.rst @@ -0,0 +1,2687 @@ +Trusted Firmware-A design +========================= + + + + +.. contents:: + +Trusted Firmware-A (TF-A) implements a subset of the Trusted Board Boot +Requirements (TBBR) Platform Design Document (PDD) [1]_ for Arm reference +platforms. The TBB sequence starts when the platform is powered on and runs up +to the stage where it hands-off control to firmware running in the normal +world in DRAM. This is the cold boot path. + +TF-A also implements the Power State Coordination Interface PDD [2]_ as a +runtime service. PSCI is the interface from normal world software to firmware +implementing power management use-cases (for example, secondary CPU boot, +hotplug and idle). Normal world software can access TF-A runtime services via +the Arm SMC (Secure Monitor Call) instruction. The SMC instruction must be +used as mandated by the SMC Calling Convention [3]_. + +TF-A implements a framework for configuring and managing interrupts generated +in either security state. The details of the interrupt management framework +and its design can be found in TF-A Interrupt Management Design guide [4]_. + +TF-A also implements a library for setting up and managing the translation +tables. The details of this library can be found in `Xlat_tables design`_. + +TF-A can be built to support either AArch64 or AArch32 execution state. + +Cold boot +--------- + +The cold boot path starts when the platform is physically turned on. If +``COLD_BOOT_SINGLE_CPU=0``, one of the CPUs released from reset is chosen as the +primary CPU, and the remaining CPUs are considered secondary CPUs. The primary +CPU is chosen through platform-specific means. The cold boot path is mainly +executed by the primary CPU, other than essential CPU initialization executed by +all CPUs. The secondary CPUs are kept in a safe platform-specific state until +the primary CPU has performed enough initialization to boot them. + +Refer to the `Reset Design`_ for more information on the effect of the +``COLD_BOOT_SINGLE_CPU`` platform build option. + +The cold boot path in this implementation of TF-A depends on the execution +state. For AArch64, it is divided into five steps (in order of execution): + +- Boot Loader stage 1 (BL1) *AP Trusted ROM* +- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* +- Boot Loader stage 3-1 (BL31) *EL3 Runtime Software* +- Boot Loader stage 3-2 (BL32) *Secure-EL1 Payload* (optional) +- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* + +For AArch32, it is divided into four steps (in order of execution): + +- Boot Loader stage 1 (BL1) *AP Trusted ROM* +- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* +- Boot Loader stage 3-2 (BL32) *EL3 Runtime Software* +- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* + +Arm development platforms (Fixed Virtual Platforms (FVPs) and Juno) implement a +combination of the following types of memory regions. Each bootloader stage uses +one or more of these memory regions. + +- Regions accessible from both non-secure and secure states. For example, + non-trusted SRAM, ROM and DRAM. +- Regions accessible from only the secure state. For example, trusted SRAM and + ROM. The FVPs also implement the trusted DRAM which is statically + configured. Additionally, the Base FVPs and Juno development platform + configure the TrustZone Controller (TZC) to create a region in the DRAM + which is accessible only from the secure state. + +The sections below provide the following details: + +- dynamic configuration of Boot Loader stages +- initialization and execution of the first three stages during cold boot +- specification of the EL3 Runtime Software (BL31 for AArch64 and BL32 for + AArch32) entrypoint requirements for use by alternative Trusted Boot + Firmware in place of the provided BL1 and BL2 + +Dynamic Configuration during cold boot +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each of the Boot Loader stages may be dynamically configured if required by the +platform. The Boot Loader stage may optionally specify a firmware +configuration file and/or hardware configuration file as listed below: + +- HW_CONFIG - The hardware configuration file. Can be shared by all Boot Loader + stages and also by the Normal World Rich OS. +- TB_FW_CONFIG - Trusted Boot Firmware configuration file. Shared between BL1 + and BL2. +- SOC_FW_CONFIG - SoC Firmware configuration file. Used by BL31. +- TOS_FW_CONFIG - Trusted OS Firmware configuration file. Used by Trusted OS + (BL32). +- NT_FW_CONFIG - Non Trusted Firmware configuration file. Used by Non-trusted + firmware (BL33). + +The Arm development platforms use the Flattened Device Tree format for the +dynamic configuration files. + +Each Boot Loader stage can pass up to 4 arguments via registers to the next +stage. BL2 passes the list of the next images to execute to the *EL3 Runtime +Software* (BL31 for AArch64 and BL32 for AArch32) via `arg0`. All the other +arguments are platform defined. The Arm development platforms use the following +convention: + +- BL1 passes the address of a meminfo_t structure to BL2 via ``arg1``. This + structure contains the memory layout available to BL2. +- When dynamic configuration files are present, the firmware configuration for + the next Boot Loader stage is populated in the first available argument and + the generic hardware configuration is passed the next available argument. + For example, + + - If TB_FW_CONFIG is loaded by BL1, then its address is passed in ``arg0`` + to BL2. + - If HW_CONFIG is loaded by BL1, then its address is passed in ``arg2`` to + BL2. Note, ``arg1`` is already used for meminfo_t. + - If SOC_FW_CONFIG is loaded by BL2, then its address is passed in ``arg1`` + to BL31. Note, ``arg0`` is used to pass the list of executable images. + - Similarly, if HW_CONFIG is loaded by BL1 or BL2, then its address is + passed in ``arg2`` to BL31. + - For other BL3x images, if the firmware configuration file is loaded by + BL2, then its address is passed in ``arg0`` and if HW_CONFIG is loaded + then its address is passed in ``arg1``. + +BL1 +~~~ + +This stage begins execution from the platform's reset vector at EL3. The reset +address is platform dependent but it is usually located in a Trusted ROM area. +The BL1 data section is copied to trusted SRAM at runtime. + +On the Arm development platforms, BL1 code starts execution from the reset +vector defined by the constant ``BL1_RO_BASE``. The BL1 data section is copied +to the top of trusted SRAM as defined by the constant ``BL1_RW_BASE``. + +The functionality implemented by this stage is as follows. + +Determination of boot path +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Whenever a CPU is released from reset, BL1 needs to distinguish between a warm +boot and a cold boot. This is done using platform-specific mechanisms (see the +``plat_get_my_entrypoint()`` function in the `Porting Guide`_). In the case of a +warm boot, a CPU is expected to continue execution from a separate +entrypoint. In the case of a cold boot, the secondary CPUs are placed in a safe +platform-specific state (see the ``plat_secondary_cold_boot_setup()`` function in +the `Porting Guide`_) while the primary CPU executes the remaining cold boot path +as described in the following sections. + +This step only applies when ``PROGRAMMABLE_RESET_ADDRESS=0``. Refer to the +`Reset Design`_ for more information on the effect of the +``PROGRAMMABLE_RESET_ADDRESS`` platform build option. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL1 performs minimal architectural initialization as follows. + +- Exception vectors + + BL1 sets up simple exception vectors for both synchronous and asynchronous + exceptions. The default behavior upon receiving an exception is to populate + a status code in the general purpose register ``X0/R0`` and call the + ``plat_report_exception()`` function (see the `Porting Guide`_). The status + code is one of: + + For AArch64: + + :: + + 0x0 : Synchronous exception from Current EL with SP_EL0 + 0x1 : IRQ exception from Current EL with SP_EL0 + 0x2 : FIQ exception from Current EL with SP_EL0 + 0x3 : System Error exception from Current EL with SP_EL0 + 0x4 : Synchronous exception from Current EL with SP_ELx + 0x5 : IRQ exception from Current EL with SP_ELx + 0x6 : FIQ exception from Current EL with SP_ELx + 0x7 : System Error exception from Current EL with SP_ELx + 0x8 : Synchronous exception from Lower EL using aarch64 + 0x9 : IRQ exception from Lower EL using aarch64 + 0xa : FIQ exception from Lower EL using aarch64 + 0xb : System Error exception from Lower EL using aarch64 + 0xc : Synchronous exception from Lower EL using aarch32 + 0xd : IRQ exception from Lower EL using aarch32 + 0xe : FIQ exception from Lower EL using aarch32 + 0xf : System Error exception from Lower EL using aarch32 + + For AArch32: + + :: + + 0x10 : User mode + 0x11 : FIQ mode + 0x12 : IRQ mode + 0x13 : SVC mode + 0x16 : Monitor mode + 0x17 : Abort mode + 0x1a : Hypervisor mode + 0x1b : Undefined mode + 0x1f : System mode + + The ``plat_report_exception()`` implementation on the Arm FVP port programs + the Versatile Express System LED register in the following format to + indicate the occurrence of an unexpected exception: + + :: + + SYS_LED[0] - Security state (Secure=0/Non-Secure=1) + SYS_LED[2:1] - Exception Level (EL3=0x3, EL2=0x2, EL1=0x1, EL0=0x0) + For AArch32 it is always 0x0 + SYS_LED[7:3] - Exception Class (Sync/Async & origin). This is the value + of the status code + + A write to the LED register reflects in the System LEDs (S6LED0..7) in the + CLCD window of the FVP. + + BL1 does not expect to receive any exceptions other than the SMC exception. + For the latter, BL1 installs a simple stub. The stub expects to receive a + limited set of SMC types (determined by their function IDs in the general + purpose register ``X0/R0``): + + - ``BL1_SMC_RUN_IMAGE``: This SMC is raised by BL2 to make BL1 pass control + to EL3 Runtime Software. + - All SMCs listed in section "BL1 SMC Interface" in the `Firmware Update`_ + Design Guide are supported for AArch64 only. These SMCs are currently + not supported when BL1 is built for AArch32. + + Any other SMC leads to an assertion failure. + +- CPU initialization + + BL1 calls the ``reset_handler()`` function which in turn calls the CPU + specific reset handler function (see the section: "CPU specific operations + framework"). + +- Control register setup (for AArch64) + + - ``SCTLR_EL3``. Instruction cache is enabled by setting the ``SCTLR_EL3.I`` + bit. Alignment and stack alignment checking is enabled by setting the + ``SCTLR_EL3.A`` and ``SCTLR_EL3.SA`` bits. Exception endianness is set to + little-endian by clearing the ``SCTLR_EL3.EE`` bit. + + - ``SCR_EL3``. The register width of the next lower exception level is set + to AArch64 by setting the ``SCR.RW`` bit. The ``SCR.EA`` bit is set to trap + both External Aborts and SError Interrupts in EL3. The ``SCR.SIF`` bit is + also set to disable instruction fetches from Non-secure memory when in + secure state. + + - ``CPTR_EL3``. Accesses to the ``CPACR_EL1`` register from EL1 or EL2, or the + ``CPTR_EL2`` register from EL2 are configured to not trap to EL3 by + clearing the ``CPTR_EL3.TCPAC`` bit. Access to the trace functionality is + configured not to trap to EL3 by clearing the ``CPTR_EL3.TTA`` bit. + Instructions that access the registers associated with Floating Point + and Advanced SIMD execution are configured to not trap to EL3 by + clearing the ``CPTR_EL3.TFP`` bit. + + - ``DAIF``. The SError interrupt is enabled by clearing the SError interrupt + mask bit. + + - ``MDCR_EL3``. The trap controls, ``MDCR_EL3.TDOSA``, ``MDCR_EL3.TDA`` and + ``MDCR_EL3.TPM``, are set so that accesses to the registers they control + do not trap to EL3. AArch64 Secure self-hosted debug is disabled by + setting the ``MDCR_EL3.SDD`` bit. Also ``MDCR_EL3.SPD32`` is set to + disable AArch32 Secure self-hosted privileged debug from S-EL1. + +- Control register setup (for AArch32) + + - ``SCTLR``. Instruction cache is enabled by setting the ``SCTLR.I`` bit. + Alignment checking is enabled by setting the ``SCTLR.A`` bit. + Exception endianness is set to little-endian by clearing the + ``SCTLR.EE`` bit. + + - ``SCR``. The ``SCR.SIF`` bit is set to disable instruction fetches from + Non-secure memory when in secure state. + + - ``CPACR``. Allow execution of Advanced SIMD instructions at PL0 and PL1, + by clearing the ``CPACR.ASEDIS`` bit. Access to the trace functionality + is configured not to trap to undefined mode by clearing the + ``CPACR.TRCDIS`` bit. + + - ``NSACR``. Enable non-secure access to Advanced SIMD functionality and + system register access to implemented trace registers. + + - ``FPEXC``. Enable access to the Advanced SIMD and floating-point + functionality from all Exception levels. + + - ``CPSR.A``. The Asynchronous data abort interrupt is enabled by clearing + the Asynchronous data abort interrupt mask bit. + + - ``SDCR``. The ``SDCR.SPD`` field is set to disable AArch32 Secure + self-hosted privileged debug. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +On Arm platforms, BL1 performs the following platform initializations: + +- Enable the Trusted Watchdog. +- Initialize the console. +- Configure the Interconnect to enable hardware coherency. +- Enable the MMU and map the memory it needs to access. +- Configure any required platform storage to load the next bootloader image + (BL2). +- If the BL1 dynamic configuration file, ``TB_FW_CONFIG``, is available, then + load it to the platform defined address and make it available to BL2 via + ``arg0``. +- Configure the system timer and program the `CNTFRQ_EL0` for use by NS-BL1U + and NS-BL2U firmware update images. + +Firmware Update detection and execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After performing platform setup, BL1 common code calls +``bl1_plat_get_next_image_id()`` to determine if `Firmware Update`_ is required or +to proceed with the normal boot process. If the platform code returns +``BL2_IMAGE_ID`` then the normal boot sequence is executed as described in the +next section, else BL1 assumes that `Firmware Update`_ is required and execution +passes to the first image in the `Firmware Update`_ process. In either case, BL1 +retrieves a descriptor of the next image by calling ``bl1_plat_get_image_desc()``. +The image descriptor contains an ``entry_point_info_t`` structure, which BL1 +uses to initialize the execution state of the next image. + +BL2 image load and execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the normal boot flow, BL1 execution continues as follows: + +#. BL1 prints the following string from the primary CPU to indicate successful + execution of the BL1 stage: + + :: + + "Booting Trusted Firmware" + +#. BL1 loads a BL2 raw binary image from platform storage, at a + platform-specific base address. Prior to the load, BL1 invokes + ``bl1_plat_handle_pre_image_load()`` which allows the platform to update or + use the image information. If the BL2 image file is not present or if + there is not enough free trusted SRAM the following error message is + printed: + + :: + + "Failed to load BL2 firmware." + +#. BL1 invokes ``bl1_plat_handle_post_image_load()`` which again is intended + for platforms to take further action after image load. This function must + populate the necessary arguments for BL2, which may also include the memory + layout. Further description of the memory layout can be found later + in this document. + +#. BL1 passes control to the BL2 image at Secure EL1 (for AArch64) or at + Secure SVC mode (for AArch32), starting from its load address. + +BL2 +~~~ + +BL1 loads and passes control to BL2 at Secure-EL1 (for AArch64) or at Secure +SVC mode (for AArch32) . BL2 is linked against and loaded at a platform-specific +base address (more information can be found later in this document). +The functionality implemented by BL2 is as follows. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For AArch64, BL2 performs the minimal architectural initialization required +for subsequent stages of TF-A and normal world software. EL1 and EL0 are given +access to Floating Point and Advanced SIMD registers by clearing the +``CPACR.FPEN`` bits. + +For AArch32, the minimal architectural initialization required for subsequent +stages of TF-A and normal world software is taken care of in BL1 as both BL1 +and BL2 execute at PL1. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +On Arm platforms, BL2 performs the following platform initializations: + +- Initialize the console. +- Configure any required platform storage to allow loading further bootloader + images. +- Enable the MMU and map the memory it needs to access. +- Perform platform security setup to allow access to controlled components. +- Reserve some memory for passing information to the next bootloader image + EL3 Runtime Software and populate it. +- Define the extents of memory available for loading each subsequent + bootloader image. +- If BL1 has passed TB_FW_CONFIG dynamic configuration file in ``arg0``, + then parse it. + +Image loading in BL2 +^^^^^^^^^^^^^^^^^^^^ + +BL2 generic code loads the images based on the list of loadable images +provided by the platform. BL2 passes the list of executable images +provided by the platform to the next handover BL image. + +The list of loadable images provided by the platform may also contain +dynamic configuration files. The files are loaded and can be parsed as +needed in the ``bl2_plat_handle_post_image_load()`` function. These +configuration files can be passed to next Boot Loader stages as arguments +by updating the corresponding entrypoint information in this function. + +SCP_BL2 (System Control Processor Firmware) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some systems have a separate System Control Processor (SCP) for power, clock, +reset and system control. BL2 loads the optional SCP_BL2 image from platform +storage into a platform-specific region of secure memory. The subsequent +handling of SCP_BL2 is platform specific. For example, on the Juno Arm +development platform port the image is transferred into SCP's internal memory +using the Boot Over MHU (BOM) protocol after being loaded in the trusted SRAM +memory. The SCP executes SCP_BL2 and signals to the Application Processor (AP) +for BL2 execution to continue. + +EL3 Runtime Software image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the EL3 Runtime Software image from platform storage into a platform- +specific address in trusted SRAM. If there is not enough memory to load the +image or image is missing it leads to an assertion failure. + +AArch64 BL32 (Secure-EL1 Payload) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the optional BL32 image from platform storage into a platform- +specific region of secure memory. The image executes in the secure world. BL2 +relies on BL31 to pass control to the BL32 image, if present. Hence, BL2 +populates a platform-specific area of memory with the entrypoint/load-address +of the BL32 image. The value of the Saved Processor Status Register (``SPSR``) +for entry into BL32 is not determined by BL2, it is initialized by the +Secure-EL1 Payload Dispatcher (see later) within BL31, which is responsible for +managing interaction with BL32. This information is passed to BL31. + +BL33 (Non-trusted Firmware) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the BL33 image (e.g. UEFI or other test or boot software) from +platform storage into non-secure memory as defined by the platform. + +BL2 relies on EL3 Runtime Software to pass control to BL33 once secure state +initialization is complete. Hence, BL2 populates a platform-specific area of +memory with the entrypoint and Saved Program Status Register (``SPSR``) of the +normal world software image. The entrypoint is the load address of the BL33 +image. The ``SPSR`` is determined as specified in Section 5.13 of the +`PSCI PDD`_. This information is passed to the EL3 Runtime Software. + +AArch64 BL31 (EL3 Runtime Software) execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 execution continues as follows: + +#. BL2 passes control back to BL1 by raising an SMC, providing BL1 with the + BL31 entrypoint. The exception is handled by the SMC exception handler + installed by BL1. + +#. BL1 turns off the MMU and flushes the caches. It clears the + ``SCTLR_EL3.M/I/C`` bits, flushes the data cache to the point of coherency + and invalidates the TLBs. + +#. BL1 passes control to BL31 at the specified entrypoint at EL3. + +Running BL2 at EL3 execution level +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some platforms have a non-TF-A Boot ROM that expects the next boot stage +to execute at EL3. On these platforms, TF-A BL1 is a waste of memory +as its only purpose is to ensure TF-A BL2 is entered at S-EL1. To avoid +this waste, a special mode enables BL2 to execute at EL3, which allows +a non-TF-A Boot ROM to load and jump directly to BL2. This mode is selected +when the build flag BL2_AT_EL3 is enabled. The main differences in this +mode are: + +#. BL2 includes the reset code and the mailbox mechanism to differentiate + cold boot and warm boot. It runs at EL3 doing the arch + initialization required for EL3. + +#. BL2 does not receive the meminfo information from BL1 anymore. This + information can be passed by the Boot ROM or be internal to the + BL2 image. + +#. Since BL2 executes at EL3, BL2 jumps directly to the next image, + instead of invoking the RUN_IMAGE SMC call. + + +We assume 3 different types of BootROM support on the platform: + +#. The Boot ROM always jumps to the same address, for both cold + and warm boot. In this case, we will need to keep a resident part + of BL2 whose memory cannot be reclaimed by any other image. The + linker script defines the symbols __TEXT_RESIDENT_START__ and + __TEXT_RESIDENT_END__ that allows the platform to configure + correctly the memory map. +#. The platform has some mechanism to indicate the jump address to the + Boot ROM. Platform code can then program the jump address with + psci_warmboot_entrypoint during cold boot. +#. The platform has some mechanism to program the reset address using + the PROGRAMMABLE_RESET_ADDRESS feature. Platform code can then + program the reset address with psci_warmboot_entrypoint during + cold boot, bypassing the boot ROM for warm boot. + +In the last 2 cases, no part of BL2 needs to remain resident at +runtime. In the first 2 cases, we expect the Boot ROM to be able to +differentiate between warm and cold boot, to avoid loading BL2 again +during warm boot. + +This functionality can be tested with FVP loading the image directly +in memory and changing the address where the system jumps at reset. +For example: + + -C cluster0.cpu0.RVBAR=0x4022000 + --data cluster0.cpu0=bl2.bin@0x4022000 + +With this configuration, FVP is like a platform of the first case, +where the Boot ROM jumps always to the same address. For simplification, +BL32 is loaded in DRAM in this case, to avoid other images reclaiming +BL2 memory. + + +AArch64 BL31 +~~~~~~~~~~~~ + +The image for this stage is loaded by BL2 and BL1 passes control to BL31 at +EL3. BL31 executes solely in trusted SRAM. BL31 is linked against and +loaded at a platform-specific base address (more information can be found later +in this document). The functionality implemented by BL31 is as follows. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Currently, BL31 performs a similar architectural initialization to BL1 as +far as system register settings are concerned. Since BL1 code resides in ROM, +architectural initialization in BL31 allows override of any previous +initialization done by BL1. + +BL31 initializes the per-CPU data framework, which provides a cache of +frequently accessed per-CPU data optimised for fast, concurrent manipulation +on different CPUs. This buffer includes pointers to per-CPU contexts, crash +buffer, CPU reset and power down operations, PSCI data, platform data and so on. + +It then replaces the exception vectors populated by BL1 with its own. BL31 +exception vectors implement more elaborate support for handling SMCs since this +is the only mechanism to access the runtime services implemented by BL31 (PSCI +for example). BL31 checks each SMC for validity as specified by the +`SMC calling convention PDD`_ before passing control to the required SMC +handler routine. + +BL31 programs the ``CNTFRQ_EL0`` register with the clock frequency of the system +counter, which is provided by the platform. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +BL31 performs detailed platform initialization, which enables normal world +software to function correctly. + +On Arm platforms, this consists of the following: + +- Initialize the console. +- Configure the Interconnect to enable hardware coherency. +- Enable the MMU and map the memory it needs to access. +- Initialize the generic interrupt controller. +- Initialize the power controller device. +- Detect the system topology. + +Runtime services initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL31 is responsible for initializing the runtime services. One of them is PSCI. + +As part of the PSCI initializations, BL31 detects the system topology. It also +initializes the data structures that implement the state machine used to track +the state of power domain nodes. The state can be one of ``OFF``, ``RUN`` or +``RETENTION``. All secondary CPUs are initially in the ``OFF`` state. The cluster +that the primary CPU belongs to is ``ON``; any other cluster is ``OFF``. It also +initializes the locks that protect them. BL31 accesses the state of a CPU or +cluster immediately after reset and before the data cache is enabled in the +warm boot path. It is not currently possible to use 'exclusive' based spinlocks, +therefore BL31 uses locks based on Lamport's Bakery algorithm instead. + +The runtime service framework and its initialization is described in more +detail in the "EL3 runtime services framework" section below. + +Details about the status of the PSCI implementation are provided in the +"Power State Coordination Interface" section below. + +AArch64 BL32 (Secure-EL1 Payload) image initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If a BL32 image is present then there must be a matching Secure-EL1 Payload +Dispatcher (SPD) service (see later for details). During initialization +that service must register a function to carry out initialization of BL32 +once the runtime services are fully initialized. BL31 invokes such a +registered function to initialize BL32 before running BL33. This initialization +is not necessary for AArch32 SPs. + +Details on BL32 initialization and the SPD's role are described in the +"Secure-EL1 Payloads and Dispatchers" section below. + +BL33 (Non-trusted Firmware) execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +EL3 Runtime Software initializes the EL2 or EL1 processor context for normal- +world cold boot, ensuring that no secure state information finds its way into +the non-secure execution state. EL3 Runtime Software uses the entrypoint +information provided by BL2 to jump to the Non-trusted firmware image (BL33) +at the highest available Exception Level (EL2 if available, otherwise EL1). + +Using alternative Trusted Boot Firmware in place of BL1 & BL2 (AArch64 only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some platforms have existing implementations of Trusted Boot Firmware that +would like to use TF-A BL31 for the EL3 Runtime Software. To enable this +firmware architecture it is important to provide a fully documented and stable +interface between the Trusted Boot Firmware and BL31. + +Future changes to the BL31 interface will be done in a backwards compatible +way, and this enables these firmware components to be independently enhanced/ +updated to develop and exploit new functionality. + +Required CPU state when calling ``bl31_entrypoint()`` during cold boot +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function must only be called by the primary CPU. + +On entry to this function the calling primary CPU must be executing in AArch64 +EL3, little-endian data access, and all interrupt sources masked: + +:: + + PSTATE.EL = 3 + PSTATE.RW = 1 + PSTATE.DAIF = 0xf + SCTLR_EL3.EE = 0 + +X0 and X1 can be used to pass information from the Trusted Boot Firmware to the +platform code in BL31: + +:: + + X0 : Reserved for common TF-A information + X1 : Platform specific information + +BL31 zero-init sections (e.g. ``.bss``) should not contain valid data on entry, +these will be zero filled prior to invoking platform setup code. + +Use of the X0 and X1 parameters +''''''''''''''''''''''''''''''' + +The parameters are platform specific and passed from ``bl31_entrypoint()`` to +``bl31_early_platform_setup()``. The value of these parameters is never directly +used by the common BL31 code. + +The convention is that ``X0`` conveys information regarding the BL31, BL32 and +BL33 images from the Trusted Boot firmware and ``X1`` can be used for other +platform specific purpose. This convention allows platforms which use TF-A's +BL1 and BL2 images to transfer additional platform specific information from +Secure Boot without conflicting with future evolution of TF-A using ``X0`` to +pass a ``bl31_params`` structure. + +BL31 common and SPD initialization code depends on image and entrypoint +information about BL33 and BL32, which is provided via BL31 platform APIs. +This information is required until the start of execution of BL33. This +information can be provided in a platform defined manner, e.g. compiled into +the platform code in BL31, or provided in a platform defined memory location +by the Trusted Boot firmware, or passed from the Trusted Boot Firmware via the +Cold boot Initialization parameters. This data may need to be cleaned out of +the CPU caches if it is provided by an earlier boot stage and then accessed by +BL31 platform code before the caches are enabled. + +TF-A's BL2 implementation passes a ``bl31_params`` structure in +``X0`` and the Arm development platforms interpret this in the BL31 platform +code. + +MMU, Data caches & Coherency +'''''''''''''''''''''''''''' + +BL31 does not depend on the enabled state of the MMU, data caches or +interconnect coherency on entry to ``bl31_entrypoint()``. If these are disabled +on entry, these should be enabled during ``bl31_plat_arch_setup()``. + +Data structures used in the BL31 cold boot interface +'''''''''''''''''''''''''''''''''''''''''''''''''''' + +These structures are designed to support compatibility and independent +evolution of the structures and the firmware images. For example, a version of +BL31 that can interpret the BL3x image information from different versions of +BL2, a platform that uses an extended entry_point_info structure to convey +additional register information to BL31, or a ELF image loader that can convey +more details about the firmware images. + +To support these scenarios the structures are versioned and sized, which enables +BL31 to detect which information is present and respond appropriately. The +``param_header`` is defined to capture this information: + +.. code:: c + + typedef struct param_header { + uint8_t type; /* type of the structure */ + uint8_t version; /* version of this structure */ + uint16_t size; /* size of this structure in bytes */ + uint32_t attr; /* attributes: unused bits SBZ */ + } param_header_t; + +The structures using this format are ``entry_point_info``, ``image_info`` and +``bl31_params``. The code that allocates and populates these structures must set +the header fields appropriately, and the ``SET_PARAM_HEAD()`` a macro is defined +to simplify this action. + +Required CPU state for BL31 Warm boot initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When requesting a CPU power-on, or suspending a running CPU, TF-A provides +the platform power management code with a Warm boot initialization +entry-point, to be invoked by the CPU immediately after the reset handler. +On entry to the Warm boot initialization function the calling CPU must be in +AArch64 EL3, little-endian data access and all interrupt sources masked: + +:: + + PSTATE.EL = 3 + PSTATE.RW = 1 + PSTATE.DAIF = 0xf + SCTLR_EL3.EE = 0 + +The PSCI implementation will initialize the processor state and ensure that the +platform power management code is then invoked as required to initialize all +necessary system, cluster and CPU resources. + +AArch32 EL3 Runtime Software entrypoint interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To enable this firmware architecture it is important to provide a fully +documented and stable interface between the Trusted Boot Firmware and the +AArch32 EL3 Runtime Software. + +Future changes to the entrypoint interface will be done in a backwards +compatible way, and this enables these firmware components to be independently +enhanced/updated to develop and exploit new functionality. + +Required CPU state when entering during cold boot +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function must only be called by the primary CPU. + +On entry to this function the calling primary CPU must be executing in AArch32 +EL3, little-endian data access, and all interrupt sources masked: + +:: + + PSTATE.AIF = 0x7 + SCTLR.EE = 0 + +R0 and R1 are used to pass information from the Trusted Boot Firmware to the +platform code in AArch32 EL3 Runtime Software: + +:: + + R0 : Reserved for common TF-A information + R1 : Platform specific information + +Use of the R0 and R1 parameters +''''''''''''''''''''''''''''''' + +The parameters are platform specific and the convention is that ``R0`` conveys +information regarding the BL3x images from the Trusted Boot firmware and ``R1`` +can be used for other platform specific purpose. This convention allows +platforms which use TF-A's BL1 and BL2 images to transfer additional platform +specific information from Secure Boot without conflicting with future +evolution of TF-A using ``R0`` to pass a ``bl_params`` structure. + +The AArch32 EL3 Runtime Software is responsible for entry into BL33. This +information can be obtained in a platform defined manner, e.g. compiled into +the AArch32 EL3 Runtime Software, or provided in a platform defined memory +location by the Trusted Boot firmware, or passed from the Trusted Boot Firmware +via the Cold boot Initialization parameters. This data may need to be cleaned +out of the CPU caches if it is provided by an earlier boot stage and then +accessed by AArch32 EL3 Runtime Software before the caches are enabled. + +When using AArch32 EL3 Runtime Software, the Arm development platforms pass a +``bl_params`` structure in ``R0`` from BL2 to be interpreted by AArch32 EL3 Runtime +Software platform code. + +MMU, Data caches & Coherency +'''''''''''''''''''''''''''' + +AArch32 EL3 Runtime Software must not depend on the enabled state of the MMU, +data caches or interconnect coherency in its entrypoint. They must be explicitly +enabled if required. + +Data structures used in cold boot interface +''''''''''''''''''''''''''''''''''''''''''' + +The AArch32 EL3 Runtime Software cold boot interface uses ``bl_params`` instead +of ``bl31_params``. The ``bl_params`` structure is based on the convention +described in AArch64 BL31 cold boot interface section. + +Required CPU state for warm boot initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When requesting a CPU power-on, or suspending a running CPU, AArch32 EL3 +Runtime Software must ensure execution of a warm boot initialization entrypoint. +If TF-A BL1 is used and the PROGRAMMABLE_RESET_ADDRESS build flag is false, +then AArch32 EL3 Runtime Software must ensure that BL1 branches to the warm +boot entrypoint by arranging for the BL1 platform function, +plat_get_my_entrypoint(), to return a non-zero value. + +In this case, the warm boot entrypoint must be in AArch32 EL3, little-endian +data access and all interrupt sources masked: + +:: + + PSTATE.AIF = 0x7 + SCTLR.EE = 0 + +The warm boot entrypoint may be implemented by using TF-A +``psci_warmboot_entrypoint()`` function. In that case, the platform must fulfil +the pre-requisites mentioned in the `PSCI Library integration guide`_. + +EL3 runtime services framework +------------------------------ + +Software executing in the non-secure state and in the secure state at exception +levels lower than EL3 will request runtime services using the Secure Monitor +Call (SMC) instruction. These requests will follow the convention described in +the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function +identifiers to each SMC request and describes how arguments are passed and +returned. + +The EL3 runtime services framework enables the development of services by +different providers that can be easily integrated into final product firmware. +The following sections describe the framework which facilitates the +registration, initialization and use of runtime services in EL3 Runtime +Software (BL31). + +The design of the runtime services depends heavily on the concepts and +definitions described in the `SMCCC`_, in particular SMC Function IDs, Owning +Entity Numbers (OEN), Fast and Yielding calls, and the SMC32 and SMC64 calling +conventions. Please refer to that document for more detailed explanation of +these terms. + +The following runtime services are expected to be implemented first. They have +not all been instantiated in the current implementation. + +#. Standard service calls + + This service is for management of the entire system. The Power State + Coordination Interface (`PSCI`_) is the first set of standard service calls + defined by Arm (see PSCI section later). + +#. Secure-EL1 Payload Dispatcher service + + If a system runs a Trusted OS or other Secure-EL1 Payload (SP) then + it also requires a *Secure Monitor* at EL3 to switch the EL1 processor + context between the normal world (EL1/EL2) and trusted world (Secure-EL1). + The Secure Monitor will make these world switches in response to SMCs. The + `SMCCC`_ provides for such SMCs with the Trusted OS Call and Trusted + Application Call OEN ranges. + + The interface between the EL3 Runtime Software and the Secure-EL1 Payload is + not defined by the `SMCCC`_ or any other standard. As a result, each + Secure-EL1 Payload requires a specific Secure Monitor that runs as a runtime + service - within TF-A this service is referred to as the Secure-EL1 Payload + Dispatcher (SPD). + + TF-A provides a Test Secure-EL1 Payload (TSP) and its associated Dispatcher + (TSPD). Details of SPD design and TSP/TSPD operation are described in the + "Secure-EL1 Payloads and Dispatchers" section below. + +#. CPU implementation service + + This service will provide an interface to CPU implementation specific + services for a given platform e.g. access to processor errata workarounds. + This service is currently unimplemented. + +Additional services for Arm Architecture, SiP and OEM calls can be implemented. +Each implemented service handles a range of SMC function identifiers as +described in the `SMCCC`_. + +Registration +~~~~~~~~~~~~ + +A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying +the name of the service, the range of OENs covered, the type of service and +initialization and call handler functions. This macro instantiates a ``const struct rt_svc_desc`` for the service with these details (see ``runtime_svc.h``). +This structure is allocated in a special ELF section ``rt_svc_descs``, enabling +the framework to find all service descriptors included into BL31. + +The specific service for a SMC Function is selected based on the OEN and call +type of the Function ID, and the framework uses that information in the service +descriptor to identify the handler for the SMC Call. + +The service descriptors do not include information to identify the precise set +of SMC function identifiers supported by this service implementation, the +security state from which such calls are valid nor the capability to support +64-bit and/or 32-bit callers (using SMC32 or SMC64). Responding appropriately +to these aspects of a SMC call is the responsibility of the service +implementation, the framework is focused on integration of services from +different providers and minimizing the time taken by the framework before the +service handler is invoked. + +Details of the parameters, requirements and behavior of the initialization and +call handling functions are provided in the following sections. + +Initialization +~~~~~~~~~~~~~~ + +``runtime_svc_init()`` in ``runtime_svc.c`` initializes the runtime services +framework running on the primary CPU during cold boot as part of the BL31 +initialization. This happens prior to initializing a Trusted OS and running +Normal world boot firmware that might in turn use these services. +Initialization involves validating each of the declared runtime service +descriptors, calling the service initialization function and populating the +index used for runtime lookup of the service. + +The BL31 linker script collects all of the declared service descriptors into a +single array and defines symbols that allow the framework to locate and traverse +the array, and determine its size. + +The framework does basic validation of each descriptor to halt firmware +initialization if service declaration errors are detected. The framework does +not check descriptors for the following error conditions, and may behave in an +unpredictable manner under such scenarios: + +#. Overlapping OEN ranges +#. Multiple descriptors for the same range of OENs and ``call_type`` +#. Incorrect range of owning entity numbers for a given ``call_type`` + +Once validated, the service ``init()`` callback is invoked. This function carries +out any essential EL3 initialization before servicing requests. The ``init()`` +function is only invoked on the primary CPU during cold boot. If the service +uses per-CPU data this must either be initialized for all CPUs during this call, +or be done lazily when a CPU first issues an SMC call to that service. If +``init()`` returns anything other than ``0``, this is treated as an initialization +error and the service is ignored: this does not cause the firmware to halt. + +The OEN and call type fields present in the SMC Function ID cover a total of +128 distinct services, but in practice a single descriptor can cover a range of +OENs, e.g. SMCs to call a Trusted OS function. To optimize the lookup of a +service handler, the framework uses an array of 128 indices that map every +distinct OEN/call-type combination either to one of the declared services or to +indicate the service is not handled. This ``rt_svc_descs_indices[]`` array is +populated for all of the OENs covered by a service after the service ``init()`` +function has reported success. So a service that fails to initialize will never +have it's ``handle()`` function invoked. + +The following figure shows how the ``rt_svc_descs_indices[]`` index maps the SMC +Function ID call type and OEN onto a specific service handler in the +``rt_svc_descs[]`` array. + +|Image 1| + +Handling an SMC +~~~~~~~~~~~~~~~ + +When the EL3 runtime services framework receives a Secure Monitor Call, the SMC +Function ID is passed in W0 from the lower exception level (as per the +`SMCCC`_). If the calling register width is AArch32, it is invalid to invoke an +SMC Function which indicates the SMC64 calling convention: such calls are +ignored and return the Unknown SMC Function Identifier result code ``0xFFFFFFFF`` +in R0/X0. + +Bit[31] (fast/yielding call) and bits[29:24] (owning entity number) of the SMC +Function ID are combined to index into the ``rt_svc_descs_indices[]`` array. The +resulting value might indicate a service that has no handler, in this case the +framework will also report an Unknown SMC Function ID. Otherwise, the value is +used as a further index into the ``rt_svc_descs[]`` array to locate the required +service and handler. + +The service's ``handle()`` callback is provided with five of the SMC parameters +directly, the others are saved into memory for retrieval (if needed) by the +handler. The handler is also provided with an opaque ``handle`` for use with the +supporting library for parameter retrieval, setting return values and context +manipulation; and with ``flags`` indicating the security state of the caller. The +framework finally sets up the execution stack for the handler, and invokes the +services ``handle()`` function. + +On return from the handler the result registers are populated in X0-X3 before +restoring the stack and CPU state and returning from the original SMC. + +Exception Handling Framework +---------------------------- + +Please refer to the `Exception Handling Framework`_ document. + +Power State Coordination Interface +---------------------------------- + +TODO: Provide design walkthrough of PSCI implementation. + +The PSCI v1.1 specification categorizes APIs as optional and mandatory. All the +mandatory APIs in PSCI v1.1, PSCI v1.0 and in PSCI v0.2 draft specification +`Power State Coordination Interface PDD`_ are implemented. The table lists +the PSCI v1.1 APIs and their support in generic code. + +An API implementation might have a dependency on platform code e.g. CPU_SUSPEND +requires the platform to export a part of the implementation. Hence the level +of support of the mandatory APIs depends upon the support exported by the +platform port as well. The Juno and FVP (all variants) platforms export all the +required support. + ++-----------------------------+-------------+-------------------------------+ +| PSCI v1.1 API | Supported | Comments | ++=============================+=============+===============================+ +| ``PSCI_VERSION`` | Yes | The version returned is 1.1 | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_SUSPEND`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_OFF`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_ON`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``AFFINITY_INFO`` | Yes | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE_INFO_TYPE`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE_INFO_CPU`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_OFF`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_RESET`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_FEATURES`` | Yes | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_FREEZE`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_DEFAULT_SUSPEND`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``NODE_HW_STATE`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_SUSPEND`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_SET_SUSPEND_MODE`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_STAT_RESIDENCY`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_STAT_COUNT`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_RESET2`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MEM_PROTECT`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MEM_PROTECT_CHECK_RANGE`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ + +\*Note : These PSCI APIs require platform power management hooks to be +registered with the generic PSCI code to be supported. + +\*\*Note : These PSCI APIs require appropriate Secure Payload Dispatcher +hooks to be registered with the generic PSCI code to be supported. + +The PSCI implementation in TF-A is a library which can be integrated with +AArch64 or AArch32 EL3 Runtime Software for Armv8-A systems. A guide to +integrating PSCI library with AArch32 EL3 Runtime Software can be found +`here`_. + +Secure-EL1 Payloads and Dispatchers +----------------------------------- + +On a production system that includes a Trusted OS running in Secure-EL1/EL0, +the Trusted OS is coupled with a companion runtime service in the BL31 +firmware. This service is responsible for the initialisation of the Trusted +OS and all communications with it. The Trusted OS is the BL32 stage of the +boot flow in TF-A. The firmware will attempt to locate, load and execute a +BL32 image. + +TF-A uses a more general term for the BL32 software that runs at Secure-EL1 - +the *Secure-EL1 Payload* - as it is not always a Trusted OS. + +TF-A provides a Test Secure-EL1 Payload (TSP) and a Test Secure-EL1 Payload +Dispatcher (TSPD) service as an example of how a Trusted OS is supported on a +production system using the Runtime Services Framework. On such a system, the +Test BL32 image and service are replaced by the Trusted OS and its dispatcher +service. The TF-A build system expects that the dispatcher will define the +build flag ``NEED_BL32`` to enable it to include the BL32 in the build either +as a binary or to compile from source depending on whether the ``BL32`` build +option is specified or not. + +The TSP runs in Secure-EL1. It is designed to demonstrate synchronous +communication with the normal-world software running in EL1/EL2. Communication +is initiated by the normal-world software + +- either directly through a Fast SMC (as defined in the `SMCCC`_) + +- or indirectly through a `PSCI`_ SMC. The `PSCI`_ implementation in turn + informs the TSPD about the requested power management operation. This allows + the TSP to prepare for or respond to the power state change + +The TSPD service is responsible for. + +- Initializing the TSP + +- Routing requests and responses between the secure and the non-secure + states during the two types of communications just described + +Initializing a BL32 Image +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Secure-EL1 Payload Dispatcher (SPD) service is responsible for initializing +the BL32 image. It needs access to the information passed by BL2 to BL31 to do +so. This is provided by: + +.. code:: c + + entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t); + +which returns a reference to the ``entry_point_info`` structure corresponding to +the image which will be run in the specified security state. The SPD uses this +API to get entry point information for the SECURE image, BL32. + +In the absence of a BL32 image, BL31 passes control to the normal world +bootloader image (BL33). When the BL32 image is present, it is typical +that the SPD wants control to be passed to BL32 first and then later to BL33. + +To do this the SPD has to register a BL32 initialization function during +initialization of the SPD service. The BL32 initialization function has this +prototype: + +.. code:: c + + int32_t init(void); + +and is registered using the ``bl31_register_bl32_init()`` function. + +TF-A supports two approaches for the SPD to pass control to BL32 before +returning through EL3 and running the non-trusted firmware (BL33): + +#. In the BL32 setup function, use ``bl31_set_next_image_type()`` to + request that the exit from ``bl31_main()`` is to the BL32 entrypoint in + Secure-EL1. BL31 will exit to BL32 using the asynchronous method by + calling ``bl31_prepare_next_image_entry()`` and ``el3_exit()``. + + When the BL32 has completed initialization at Secure-EL1, it returns to + BL31 by issuing an SMC, using a Function ID allocated to the SPD. On + receipt of this SMC, the SPD service handler should switch the CPU context + from trusted to normal world and use the ``bl31_set_next_image_type()`` and + ``bl31_prepare_next_image_entry()`` functions to set up the initial return to + the normal world firmware BL33. On return from the handler the framework + will exit to EL2 and run BL33. + +#. The BL32 setup function registers an initialization function using + ``bl31_register_bl32_init()`` which provides a SPD-defined mechanism to + invoke a 'world-switch synchronous call' to Secure-EL1 to run the BL32 + entrypoint. + NOTE: The Test SPD service included with TF-A provides one implementation + of such a mechanism. + + On completion BL32 returns control to BL31 via a SMC, and on receipt the + SPD service handler invokes the synchronous call return mechanism to return + to the BL32 initialization function. On return from this function, + ``bl31_main()`` will set up the return to the normal world firmware BL33 and + continue the boot process in the normal world. + +Crash Reporting in BL31 +----------------------- + +BL31 implements a scheme for reporting the processor state when an unhandled +exception is encountered. The reporting mechanism attempts to preserve all the +register contents and report it via a dedicated UART (PL011 console). BL31 +reports the general purpose, EL3, Secure EL1 and some EL2 state registers. + +A dedicated per-CPU crash stack is maintained by BL31 and this is retrieved via +the per-CPU pointer cache. The implementation attempts to minimise the memory +required for this feature. The file ``crash_reporting.S`` contains the +implementation for crash reporting. + +The sample crash output is shown below. + +:: + + x0 :0x000000004F00007C + x1 :0x0000000007FFFFFF + x2 :0x0000000004014D50 + x3 :0x0000000000000000 + x4 :0x0000000088007998 + x5 :0x00000000001343AC + x6 :0x0000000000000016 + x7 :0x00000000000B8A38 + x8 :0x00000000001343AC + x9 :0x00000000000101A8 + x10 :0x0000000000000002 + x11 :0x000000000000011C + x12 :0x00000000FEFDC644 + x13 :0x00000000FED93FFC + x14 :0x0000000000247950 + x15 :0x00000000000007A2 + x16 :0x00000000000007A4 + x17 :0x0000000000247950 + x18 :0x0000000000000000 + x19 :0x00000000FFFFFFFF + x20 :0x0000000004014D50 + x21 :0x000000000400A38C + x22 :0x0000000000247950 + x23 :0x0000000000000010 + x24 :0x0000000000000024 + x25 :0x00000000FEFDC868 + x26 :0x00000000FEFDC86A + x27 :0x00000000019EDEDC + x28 :0x000000000A7CFDAA + x29 :0x0000000004010780 + x30 :0x000000000400F004 + scr_el3 :0x0000000000000D3D + sctlr_el3 :0x0000000000C8181F + cptr_el3 :0x0000000000000000 + tcr_el3 :0x0000000080803520 + daif :0x00000000000003C0 + mair_el3 :0x00000000000004FF + spsr_el3 :0x00000000800003CC + elr_el3 :0x000000000400C0CC + ttbr0_el3 :0x00000000040172A0 + esr_el3 :0x0000000096000210 + sp_el3 :0x0000000004014D50 + far_el3 :0x000000004F00007C + spsr_el1 :0x0000000000000000 + elr_el1 :0x0000000000000000 + spsr_abt :0x0000000000000000 + spsr_und :0x0000000000000000 + spsr_irq :0x0000000000000000 + spsr_fiq :0x0000000000000000 + sctlr_el1 :0x0000000030C81807 + actlr_el1 :0x0000000000000000 + cpacr_el1 :0x0000000000300000 + csselr_el1 :0x0000000000000002 + sp_el1 :0x0000000004028800 + esr_el1 :0x0000000000000000 + ttbr0_el1 :0x000000000402C200 + ttbr1_el1 :0x0000000000000000 + mair_el1 :0x00000000000004FF + amair_el1 :0x0000000000000000 + tcr_el1 :0x0000000000003520 + tpidr_el1 :0x0000000000000000 + tpidr_el0 :0x0000000000000000 + tpidrro_el0 :0x0000000000000000 + dacr32_el2 :0x0000000000000000 + ifsr32_el2 :0x0000000000000000 + par_el1 :0x0000000000000000 + far_el1 :0x0000000000000000 + afsr0_el1 :0x0000000000000000 + afsr1_el1 :0x0000000000000000 + contextidr_el1 :0x0000000000000000 + vbar_el1 :0x0000000004027000 + cntp_ctl_el0 :0x0000000000000000 + cntp_cval_el0 :0x0000000000000000 + cntv_ctl_el0 :0x0000000000000000 + cntv_cval_el0 :0x0000000000000000 + cntkctl_el1 :0x0000000000000000 + sp_el0 :0x0000000004010780 + +Guidelines for Reset Handlers +----------------------------- + +TF-A implements a framework that allows CPU and platform ports to perform +actions very early after a CPU is released from reset in both the cold and warm +boot paths. This is done by calling the ``reset_handler()`` function in both +the BL1 and BL31 images. It in turn calls the platform and CPU specific reset +handling functions. + +Details for implementing a CPU specific reset handler can be found in +Section 8. Details for implementing a platform specific reset handler can be +found in the `Porting Guide`_ (see the ``plat_reset_handler()`` function). + +When adding functionality to a reset handler, keep in mind that if a different +reset handling behavior is required between the first and the subsequent +invocations of the reset handling code, this should be detected at runtime. +In other words, the reset handler should be able to detect whether an action has +already been performed and act as appropriate. Possible courses of actions are, +e.g. skip the action the second time, or undo/redo it. + +Configuring secure interrupts +----------------------------- + +The GIC driver is responsible for performing initial configuration of secure +interrupts on the platform. To this end, the platform is expected to provide the +GIC driver (either GICv2 or GICv3, as selected by the platform) with the +interrupt configuration during the driver initialisation. + +Secure interrupt configuration are specified in an array of secure interrupt +properties. In this scheme, in both GICv2 and GICv3 driver data structures, the +``interrupt_props`` member points to an array of interrupt properties. Each +element of the array specifies the interrupt number and its attributes +(priority, group, configuration). Each element of the array shall be populated +by the macro ``INTR_PROP_DESC()``. The macro takes the following arguments: + +- 10-bit interrupt number, + +- 8-bit interrupt priority, + +- Interrupt type (one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1``, + ``INTR_TYPE_NS``), + +- Interrupt configuration (either ``GIC_INTR_CFG_LEVEL`` or + ``GIC_INTR_CFG_EDGE``). + +CPU specific operations framework +--------------------------------- + +Certain aspects of the Armv8-A architecture are implementation defined, +that is, certain behaviours are not architecturally defined, but must be +defined and documented by individual processor implementations. TF-A +implements a framework which categorises the common implementation defined +behaviours and allows a processor to export its implementation of that +behaviour. The categories are: + +#. Processor specific reset sequence. + +#. Processor specific power down sequences. + +#. Processor specific register dumping as a part of crash reporting. + +#. Errata status reporting. + +Each of the above categories fulfils a different requirement. + +#. allows any processor specific initialization before the caches and MMU + are turned on, like implementation of errata workarounds, entry into + the intra-cluster coherency domain etc. + +#. allows each processor to implement the power down sequence mandated in + its Technical Reference Manual (TRM). + +#. allows a processor to provide additional information to the developer + in the event of a crash, for example Cortex-A53 has registers which + can expose the data cache contents. + +#. allows a processor to define a function that inspects and reports the status + of all errata workarounds on that processor. + +Please note that only 2. is mandated by the TRM. + +The CPU specific operations framework scales to accommodate a large number of +different CPUs during power down and reset handling. The platform can specify +any CPU optimization it wants to enable for each CPU. It can also specify +the CPU errata workarounds to be applied for each CPU type during reset +handling by defining CPU errata compile time macros. Details on these macros +can be found in the `cpu-specific-build-macros.rst`_ file. + +The CPU specific operations framework depends on the ``cpu_ops`` structure which +needs to be exported for each type of CPU in the platform. It is defined in +``include/lib/cpus/aarch64/cpu_macros.S`` and has the following fields : ``midr``, +``reset_func()``, ``cpu_pwr_down_ops`` (array of power down functions) and +``cpu_reg_dump()``. + +The CPU specific files in ``lib/cpus`` export a ``cpu_ops`` data structure with +suitable handlers for that CPU. For example, ``lib/cpus/aarch64/cortex_a53.S`` +exports the ``cpu_ops`` for Cortex-A53 CPU. According to the platform +configuration, these CPU specific files must be included in the build by +the platform makefile. The generic CPU specific operations framework code exists +in ``lib/cpus/aarch64/cpu_helpers.S``. + +CPU specific Reset Handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +After a reset, the state of the CPU when it calls generic reset handler is: +MMU turned off, both instruction and data caches turned off and not part +of any coherency domain. + +The BL entrypoint code first invokes the ``plat_reset_handler()`` to allow +the platform to perform any system initialization required and any system +errata workarounds that needs to be applied. The ``get_cpu_ops_ptr()`` reads +the current CPU midr, finds the matching ``cpu_ops`` entry in the ``cpu_ops`` +array and returns it. Note that only the part number and implementer fields +in midr are used to find the matching ``cpu_ops`` entry. The ``reset_func()`` in +the returned ``cpu_ops`` is then invoked which executes the required reset +handling for that CPU and also any errata workarounds enabled by the platform. +This function must preserve the values of general purpose registers x20 to x29. + +Refer to Section "Guidelines for Reset Handlers" for general guidelines +regarding placement of code in a reset handler. + +CPU specific power down sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +During the BL31 initialization sequence, the pointer to the matching ``cpu_ops`` +entry is stored in per-CPU data by ``init_cpu_ops()`` so that it can be quickly +retrieved during power down sequences. + +Various CPU drivers register handlers to perform power down at certain power +levels for that specific CPU. The PSCI service, upon receiving a power down +request, determines the highest power level at which to execute power down +sequence for a particular CPU. It uses the ``prepare_cpu_pwr_dwn()`` function to +pick the right power down handler for the requested level. The function +retrieves ``cpu_ops`` pointer member of per-CPU data, and from that, further +retrieves ``cpu_pwr_down_ops`` array, and indexes into the required level. If the +requested power level is higher than what a CPU driver supports, the handler +registered for highest level is invoked. + +At runtime the platform hooks for power down are invoked by the PSCI service to +perform platform specific operations during a power down sequence, for example +turning off CCI coherency during a cluster power down. + +CPU specific register reporting during crash +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the crash reporting is enabled in BL31, when a crash occurs, the crash +reporting framework calls ``do_cpu_reg_dump`` which retrieves the matching +``cpu_ops`` using ``get_cpu_ops_ptr()`` function. The ``cpu_reg_dump()`` in +``cpu_ops`` is invoked, which then returns the CPU specific register values to +be reported and a pointer to the ASCII list of register names in a format +expected by the crash reporting framework. + +CPU errata status reporting +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Errata workarounds for CPUs supported in TF-A are applied during both cold and +warm boots, shortly after reset. Individual Errata workarounds are enabled as +build options. Some errata workarounds have potential run-time implications; +therefore some are enabled by default, others not. Platform ports shall +override build options to enable or disable errata as appropriate. The CPU +drivers take care of applying errata workarounds that are enabled and applicable +to a given CPU. Refer to the section titled *CPU Errata Workarounds* in `CPUBM`_ +for more information. + +Functions in CPU drivers that apply errata workaround must follow the +conventions listed below. + +The errata workaround must be authored as two separate functions: + +- One that checks for errata. This function must determine whether that errata + applies to the current CPU. Typically this involves matching the current + CPUs revision and variant against a value that's known to be affected by the + errata. If the function determines that the errata applies to this CPU, it + must return ``ERRATA_APPLIES``; otherwise, it must return + ``ERRATA_NOT_APPLIES``. The utility functions ``cpu_get_rev_var`` and + ``cpu_rev_var_ls`` functions may come in handy for this purpose. + +For an errata identified as ``E``, the check function must be named +``check_errata_E``. + +This function will be invoked at different times, both from assembly and from +C run time. Therefore it must follow AAPCS, and must not use stack. + +- Another one that applies the errata workaround. This function would call the + check function described above, and applies errata workaround if required. + +CPU drivers that apply errata workaround can optionally implement an assembly +function that report the status of errata workarounds pertaining to that CPU. +For a driver that registers the CPU, for example, ``cpux`` via ``declare_cpu_ops`` +macro, the errata reporting function, if it exists, must be named +``cpux_errata_report``. This function will always be called with MMU enabled; it +must follow AAPCS and may use stack. + +In a debug build of TF-A, on a CPU that comes out of reset, both BL1 and the +runtime firmware (BL31 in AArch64, and BL32 in AArch32) will invoke errata +status reporting function, if one exists, for that type of CPU. + +To report the status of each errata workaround, the function shall use the +assembler macro ``report_errata``, passing it: + +- The build option that enables the errata; + +- The name of the CPU: this must be the same identifier that CPU driver + registered itself with, using ``declare_cpu_ops``; + +- And the errata identifier: the identifier must match what's used in the + errata's check function described above. + +The errata status reporting function will be called once per CPU type/errata +combination during the software's active life time. + +It's expected that whenever an errata workaround is submitted to TF-A, the +errata reporting function is appropriately extended to report its status as +well. + +Reporting the status of errata workaround is for informational purpose only; it +has no functional significance. + +Memory layout of BL images +-------------------------- + +Each bootloader image can be divided in 2 parts: + +- the static contents of the image. These are data actually stored in the + binary on the disk. In the ELF terminology, they are called ``PROGBITS`` + sections; + +- the run-time contents of the image. These are data that don't occupy any + space in the binary on the disk. The ELF binary just contains some + metadata indicating where these data will be stored at run-time and the + corresponding sections need to be allocated and initialized at run-time. + In the ELF terminology, they are called ``NOBITS`` sections. + +All PROGBITS sections are grouped together at the beginning of the image, +followed by all NOBITS sections. This is true for all TF-A images and it is +governed by the linker scripts. This ensures that the raw binary images are +as small as possible. If a NOBITS section was inserted in between PROGBITS +sections then the resulting binary file would contain zero bytes in place of +this NOBITS section, making the image unnecessarily bigger. Smaller images +allow faster loading from the FIP to the main memory. + +Linker scripts and symbols +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each bootloader stage image layout is described by its own linker script. The +linker scripts export some symbols into the program symbol table. Their values +correspond to particular addresses. TF-A code can refer to these symbols to +figure out the image memory layout. + +Linker symbols follow the following naming convention in TF-A. + +- ``__
_START__`` + + Start address of a given section named ``
``. + +- ``__
_END__`` + + End address of a given section named ``
``. If there is an alignment + constraint on the section's end address then ``__
_END__`` corresponds + to the end address of the section's actual contents, rounded up to the right + boundary. Refer to the value of ``__
_UNALIGNED_END__`` to know the + actual end address of the section's contents. + +- ``__
_UNALIGNED_END__`` + + End address of a given section named ``
`` without any padding or + rounding up due to some alignment constraint. + +- ``__
_SIZE__`` + + Size (in bytes) of a given section named ``
``. If there is an + alignment constraint on the section's end address then ``__
_SIZE__`` + corresponds to the size of the section's actual contents, rounded up to the + right boundary. In other words, ``__
_SIZE__ = __
_END__ - _
_START__``. Refer to the value of ``__
_UNALIGNED_SIZE__`` + to know the actual size of the section's contents. + +- ``__
_UNALIGNED_SIZE__`` + + Size (in bytes) of a given section named ``
`` without any padding or + rounding up due to some alignment constraint. In other words, + ``__
_UNALIGNED_SIZE__ = __
_UNALIGNED_END__ - __
_START__``. + +Some of the linker symbols are mandatory as TF-A code relies on them to be +defined. They are listed in the following subsections. Some of them must be +provided for each bootloader stage and some are specific to a given bootloader +stage. + +The linker scripts define some extra, optional symbols. They are not actually +used by any code but they help in understanding the bootloader images' memory +layout as they are easy to spot in the link map files. + +Common linker symbols +^^^^^^^^^^^^^^^^^^^^^ + +All BL images share the following requirements: + +- The BSS section must be zero-initialised before executing any C code. +- The coherent memory section (if enabled) must be zero-initialised as well. +- The MMU setup code needs to know the extents of the coherent and read-only + memory regions to set the right memory attributes. When + ``SEPARATE_CODE_AND_RODATA=1``, it needs to know more specifically how the + read-only memory region is divided between code and data. + +The following linker symbols are defined for this purpose: + +- ``__BSS_START__`` +- ``__BSS_SIZE__`` +- ``__COHERENT_RAM_START__`` Must be aligned on a page-size boundary. +- ``__COHERENT_RAM_END__`` Must be aligned on a page-size boundary. +- ``__COHERENT_RAM_UNALIGNED_SIZE__`` +- ``__RO_START__`` +- ``__RO_END__`` +- ``__TEXT_START__`` +- ``__TEXT_END__`` +- ``__RODATA_START__`` +- ``__RODATA_END__`` + +BL1's linker symbols +^^^^^^^^^^^^^^^^^^^^ + +BL1 being the ROM image, it has additional requirements. BL1 resides in ROM and +it is entirely executed in place but it needs some read-write memory for its +mutable data. Its ``.data`` section (i.e. its allocated read-write data) must be +relocated from ROM to RAM before executing any C code. + +The following additional linker symbols are defined for BL1: + +- ``__BL1_ROM_END__`` End address of BL1's ROM contents, covering its code + and ``.data`` section in ROM. +- ``__DATA_ROM_START__`` Start address of the ``.data`` section in ROM. Must be + aligned on a 16-byte boundary. +- ``__DATA_RAM_START__`` Address in RAM where the ``.data`` section should be + copied over. Must be aligned on a 16-byte boundary. +- ``__DATA_SIZE__`` Size of the ``.data`` section (in ROM or RAM). +- ``__BL1_RAM_START__`` Start address of BL1 read-write data. +- ``__BL1_RAM_END__`` End address of BL1 read-write data. + +How to choose the right base addresses for each bootloader stage image +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There is currently no support for dynamic image loading in TF-A. This means +that all bootloader images need to be linked against their ultimate runtime +locations and the base addresses of each image must be chosen carefully such +that images don't overlap each other in an undesired way. As the code grows, +the base addresses might need adjustments to cope with the new memory layout. + +The memory layout is completely specific to the platform and so there is no +general recipe for choosing the right base addresses for each bootloader image. +However, there are tools to aid in understanding the memory layout. These are +the link map files: ``build///bl/bl.map``, with ```` +being the stage bootloader. They provide a detailed view of the memory usage of +each image. Among other useful information, they provide the end address of +each image. + +- ``bl1.map`` link map file provides ``__BL1_RAM_END__`` address. +- ``bl2.map`` link map file provides ``__BL2_END__`` address. +- ``bl31.map`` link map file provides ``__BL31_END__`` address. +- ``bl32.map`` link map file provides ``__BL32_END__`` address. + +For each bootloader image, the platform code must provide its start address +as well as a limit address that it must not overstep. The latter is used in the +linker scripts to check that the image doesn't grow past that address. If that +happens, the linker will issue a message similar to the following: + +:: + + aarch64-none-elf-ld: BLx has exceeded its limit. + +Additionally, if the platform memory layout implies some image overlaying like +on FVP, BL31 and TSP need to know the limit address that their PROGBITS +sections must not overstep. The platform code must provide those. + +TF-A does not provide any mechanism to verify at boot time that the memory +to load a new image is free to prevent overwriting a previously loaded image. +The platform must specify the memory available in the system for all the +relevant BL images to be loaded. + +For example, in the case of BL1 loading BL2, ``bl1_plat_sec_mem_layout()`` will +return the region defined by the platform where BL1 intends to load BL2. The +``load_image()`` function performs bounds check for the image size based on the +base and maximum image size provided by the platforms. Platforms must take +this behaviour into account when defining the base/size for each of the images. + +Memory layout on Arm development platforms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following list describes the memory layout on the Arm development platforms: + +- A 4KB page of shared memory is used for communication between Trusted + Firmware and the platform's power controller. This is located at the base of + Trusted SRAM. The amount of Trusted SRAM available to load the bootloader + images is reduced by the size of the shared memory. + + The shared memory is used to store the CPUs' entrypoint mailbox. On Juno, + this is also used for the MHU payload when passing messages to and from the + SCP. + +- Another 4 KB page is reserved for passing memory layout between BL1 and BL2 + and also the dynamic firmware configurations. + +- On FVP, BL1 is originally sitting in the Trusted ROM at address ``0x0``. On + Juno, BL1 resides in flash memory at address ``0x0BEC0000``. BL1 read-write + data are relocated to the top of Trusted SRAM at runtime. + +- BL2 is loaded below BL1 RW + +- EL3 Runtime Software, BL31 for AArch64 and BL32 for AArch32 (e.g. SP_MIN), + is loaded at the top of the Trusted SRAM, such that its NOBITS sections will + overwrite BL1 R/W data and BL2. This implies that BL1 global variables + remain valid only until execution reaches the EL3 Runtime Software entry + point during a cold boot. + +- On Juno, SCP_BL2 is loaded temporarily into the EL3 Runtime Software memory + region and transfered to the SCP before being overwritten by EL3 Runtime + Software. + +- BL32 (for AArch64) can be loaded in one of the following locations: + + - Trusted SRAM + - Trusted DRAM (FVP only) + - Secure region of DRAM (top 16MB of DRAM configured by the TrustZone + controller) + + When BL32 (for AArch64) is loaded into Trusted SRAM, it is loaded below + BL31. + +The location of the BL32 image will result in different memory maps. This is +illustrated for both FVP and Juno in the following diagrams, using the TSP as +an example. + +Note: Loading the BL32 image in TZC secured DRAM doesn't change the memory +layout of the other images in Trusted SRAM. + +CONFIG section in memory layouts shown below contains: + +:: + + +--------------------+ + |bl2_mem_params_descs| + |--------------------| + | fw_configs | + +--------------------+ + +``bl2_mem_params_descs`` contains parameters passed from BL2 to next the +BL image during boot. + +``fw_configs`` includes soc_fw_config, tos_fw_config and tb_fw_config. + +**FVP with TSP in Trusted SRAM with firmware configs :** +(These diagrams only cover the AArch64 case) + +:: + + DRAM + 0xffffffff +----------+ + : : + |----------| + |HW_CONFIG | + 0x83000000 |----------| (non-secure) + | | + 0x80000000 +----------+ + + Trusted SRAM + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + | | <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL32 | + 0x04002000 +----------+ +----------------+ + | CONFIG | + 0x04001000 +----------+ + | Shared | + 0x04000000 +----------+ + + Trusted ROM + 0x04000000 +----------+ + | BL1 (ro) | + 0x00000000 +----------+ + +**FVP with TSP in Trusted DRAM with firmware configs (default option):** + +:: + + DRAM + 0xffffffff +--------------+ + : : + |--------------| + | HW_CONFIG | + 0x83000000 |--------------| (non-secure) + | | + 0x80000000 +--------------+ + + Trusted DRAM + 0x08000000 +--------------+ + | BL32 | + 0x06000000 +--------------+ + + Trusted SRAM + 0x04040000 +--------------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |--------------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |--------------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + | | +----------------+ + +--------------+ + | CONFIG | + 0x04001000 +--------------+ + | Shared | + 0x04000000 +--------------+ + + Trusted ROM + 0x04000000 +--------------+ + | BL1 (ro) | + 0x00000000 +--------------+ + +**FVP with TSP in TZC-Secured DRAM with firmware configs :** + +:: + + DRAM + 0xffffffff +----------+ + | BL32 | (secure) + 0xff000000 +----------+ + | | + |----------| + |HW_CONFIG | + 0x83000000 |----------| (non-secure) + | | + 0x80000000 +----------+ + + Trusted SRAM + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + | | +----------------+ + 0x04002000 +----------+ + | CONFIG | + 0x04001000 +----------+ + | Shared | + 0x04000000 +----------+ + + Trusted ROM + 0x04000000 +----------+ + | BL1 (ro) | + 0x00000000 +----------+ + +**Juno with BL32 in Trusted SRAM :** + +:: + + Flash0 + 0x0C000000 +----------+ + : : + 0x0BED0000 |----------| + | BL1 (ro) | + 0x0BEC0000 |----------| + : : + 0x08000000 +----------+ BL31 is loaded + after SCP_BL2 has + Trusted SRAM been sent to SCP + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL32 | + | | +----------------+ + | | + 0x04001000 +----------+ + | MHU | + 0x04000000 +----------+ + +**Juno with BL32 in TZC-secured DRAM :** + +:: + + DRAM + 0xFFE00000 +----------+ + | BL32 | (secure) + 0xFF000000 |----------| + | | + : : (non-secure) + | | + 0x80000000 +----------+ + + Flash0 + 0x0C000000 +----------+ + : : + 0x0BED0000 |----------| + | BL1 (ro) | + 0x0BEC0000 |----------| + : : + 0x08000000 +----------+ BL31 is loaded + after SCP_BL2 has + Trusted SRAM been sent to SCP + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | + |----------| +----------------+ + 0x04001000 +----------+ + | MHU | + 0x04000000 +----------+ + +Library at ROM +--------------- + +Please refer to the `ROMLIB Design`_ document. + +Firmware Image Package (FIP) +---------------------------- + +Using a Firmware Image Package (FIP) allows for packing bootloader images (and +potentially other payloads) into a single archive that can be loaded by TF-A +from non-volatile platform storage. A driver to load images from a FIP has +been added to the storage layer and allows a package to be read from supported +platform storage. A tool to create Firmware Image Packages is also provided +and described below. + +Firmware Image Package layout +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FIP layout consists of a table of contents (ToC) followed by payload data. +The ToC itself has a header followed by one or more table entries. The ToC is +terminated by an end marker entry, and since the size of the ToC is 0 bytes, +the offset equals the total size of the FIP file. All ToC entries describe some +payload data that has been appended to the end of the binary package. With the +information provided in the ToC entry the corresponding payload data can be +retrieved. + +:: + + ------------------ + | ToC Header | + |----------------| + | ToC Entry 0 | + |----------------| + | ToC Entry 1 | + |----------------| + | ToC End Marker | + |----------------| + | | + | Data 0 | + | | + |----------------| + | | + | Data 1 | + | | + ------------------ + +The ToC header and entry formats are described in the header file +``include/tools_share/firmware_image_package.h``. This file is used by both the +tool and TF-A. + +The ToC header has the following fields: + +:: + + `name`: The name of the ToC. This is currently used to validate the header. + `serial_number`: A non-zero number provided by the creation tool + `flags`: Flags associated with this data. + Bits 0-31: Reserved + Bits 32-47: Platform defined + Bits 48-63: Reserved + +A ToC entry has the following fields: + +:: + + `uuid`: All files are referred to by a pre-defined Universally Unique + IDentifier [UUID] . The UUIDs are defined in + `include/tools_share/firmware_image_package.h`. The platform translates + the requested image name into the corresponding UUID when accessing the + package. + `offset_address`: The offset address at which the corresponding payload data + can be found. The offset is calculated from the ToC base address. + `size`: The size of the corresponding payload data in bytes. + `flags`: Flags associated with this entry. None are yet defined. + +Firmware Image Package creation tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FIP creation tool can be used to pack specified images into a binary +package that can be loaded by TF-A from platform storage. The tool currently +only supports packing bootloader images. Additional image definitions can be +added to the tool as required. + +The tool can be found in ``tools/fiptool``. + +Loading from a Firmware Image Package (FIP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Firmware Image Package (FIP) driver can load images from a binary package on +non-volatile platform storage. For the Arm development platforms, this is +currently NOR FLASH. + +Bootloader images are loaded according to the platform policy as specified by +the function ``plat_get_image_source()``. For the Arm development platforms, this +means the platform will attempt to load images from a Firmware Image Package +located at the start of NOR FLASH0. + +The Arm development platforms' policy is to only allow loading of a known set of +images. The platform policy can be modified to allow additional images. + +Use of coherent memory in TF-A +------------------------------ + +There might be loss of coherency when physical memory with mismatched +shareability, cacheability and memory attributes is accessed by multiple CPUs +(refer to section B2.9 of `Arm ARM`_ for more details). This possibility occurs +in TF-A during power up/down sequences when coherency, MMU and caches are +turned on/off incrementally. + +TF-A defines coherent memory as a region of memory with Device nGnRE attributes +in the translation tables. The translation granule size in TF-A is 4KB. This +is the smallest possible size of the coherent memory region. + +By default, all data structures which are susceptible to accesses with +mismatched attributes from various CPUs are allocated in a coherent memory +region (refer to section 2.1 of `Porting Guide`_). The coherent memory region +accesses are Outer Shareable, non-cacheable and they can be accessed +with the Device nGnRE attributes when the MMU is turned on. Hence, at the +expense of at least an extra page of memory, TF-A is able to work around +coherency issues due to mismatched memory attributes. + +The alternative to the above approach is to allocate the susceptible data +structures in Normal WriteBack WriteAllocate Inner shareable memory. This +approach requires the data structures to be designed so that it is possible to +work around the issue of mismatched memory attributes by performing software +cache maintenance on them. + +Disabling the use of coherent memory in TF-A +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It might be desirable to avoid the cost of allocating coherent memory on +platforms which are memory constrained. TF-A enables inclusion of coherent +memory in firmware images through the build flag ``USE_COHERENT_MEM``. +This flag is enabled by default. It can be disabled to choose the second +approach described above. + +The below sections analyze the data structures allocated in the coherent memory +region and the changes required to allocate them in normal memory. + +Coherent memory usage in PSCI implementation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``psci_non_cpu_pd_nodes`` data structure stores the platform's power domain +tree information for state management of power domains. By default, this data +structure is allocated in the coherent memory region in TF-A because it can be +accessed by multiple CPUs, either with caches enabled or disabled. + +.. code:: c + + typedef struct non_cpu_pwr_domain_node { + /* + * Index of the first CPU power domain node level 0 which has this node + * as its parent. + */ + unsigned int cpu_start_idx; + + /* + * Number of CPU power domains which are siblings of the domain indexed + * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx + * -> cpu_start_idx + ncpus' have this node as their parent. + */ + unsigned int ncpus; + + /* + * Index of the parent power domain node. + */ + unsigned int parent_node; + + plat_local_state_t local_state; + + unsigned char level; + + /* For indexing the psci_lock array*/ + unsigned char lock_index; + } non_cpu_pd_node_t; + +In order to move this data structure to normal memory, the use of each of its +fields must be analyzed. Fields like ``cpu_start_idx``, ``ncpus``, ``parent_node`` +``level`` and ``lock_index`` are only written once during cold boot. Hence removing +them from coherent memory involves only doing a clean and invalidate of the +cache lines after these fields are written. + +The field ``local_state`` can be concurrently accessed by multiple CPUs in +different cache states. A Lamport's Bakery lock ``psci_locks`` is used to ensure +mutual exclusion to this field and a clean and invalidate is needed after it +is written. + +Bakery lock data +~~~~~~~~~~~~~~~~ + +The bakery lock data structure ``bakery_lock_t`` is allocated in coherent memory +and is accessed by multiple CPUs with mismatched attributes. ``bakery_lock_t`` is +defined as follows: + +.. code:: c + + typedef struct bakery_lock { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data[BAKERY_LOCK_MAX_CPUS]; + } bakery_lock_t; + +It is a characteristic of Lamport's Bakery algorithm that the volatile per-CPU +fields can be read by all CPUs but only written to by the owning CPU. + +Depending upon the data cache line size, the per-CPU fields of the +``bakery_lock_t`` structure for multiple CPUs may exist on a single cache line. +These per-CPU fields can be read and written during lock contention by multiple +CPUs with mismatched memory attributes. Since these fields are a part of the +lock implementation, they do not have access to any other locking primitive to +safeguard against the resulting coherency issues. As a result, simple software +cache maintenance is not enough to allocate them in coherent memory. Consider +the following example. + +CPU0 updates its per-CPU field with data cache enabled. This write updates a +local cache line which contains a copy of the fields for other CPUs as well. Now +CPU1 updates its per-CPU field of the ``bakery_lock_t`` structure with data cache +disabled. CPU1 then issues a DCIVAC operation to invalidate any stale copies of +its field in any other cache line in the system. This operation will invalidate +the update made by CPU0 as well. + +To use bakery locks when ``USE_COHERENT_MEM`` is disabled, the lock data structure +has been redesigned. The changes utilise the characteristic of Lamport's Bakery +algorithm mentioned earlier. The bakery_lock structure only allocates the memory +for a single CPU. The macro ``DEFINE_BAKERY_LOCK`` allocates all the bakery locks +needed for a CPU into a section ``bakery_lock``. The linker allocates the memory +for other cores by using the total size allocated for the bakery_lock section +and multiplying it with (PLATFORM_CORE_COUNT - 1). This enables software to +perform software cache maintenance on the lock data structure without running +into coherency issues associated with mismatched attributes. + +The bakery lock data structure ``bakery_info_t`` is defined for use when +``USE_COHERENT_MEM`` is disabled as follows: + +.. code:: c + + typedef struct bakery_info { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data; + } bakery_info_t; + +The ``bakery_info_t`` represents a single per-CPU field of one lock and +the combination of corresponding ``bakery_info_t`` structures for all CPUs in the +system represents the complete bakery lock. The view in memory for a system +with n bakery locks are: + +:: + + bakery_lock section start + |----------------| + | `bakery_info_t`| <-- Lock_0 per-CPU field + | Lock_0 | for CPU0 + |----------------| + | `bakery_info_t`| <-- Lock_1 per-CPU field + | Lock_1 | for CPU0 + |----------------| + | .... | + |----------------| + | `bakery_info_t`| <-- Lock_N per-CPU field + | Lock_N | for CPU0 + ------------------ + | XXXXX | + | Padding to | + | next Cache WB | <--- Calculate PERCPU_BAKERY_LOCK_SIZE, allocate + | Granule | continuous memory for remaining CPUs. + ------------------ + | `bakery_info_t`| <-- Lock_0 per-CPU field + | Lock_0 | for CPU1 + |----------------| + | `bakery_info_t`| <-- Lock_1 per-CPU field + | Lock_1 | for CPU1 + |----------------| + | .... | + |----------------| + | `bakery_info_t`| <-- Lock_N per-CPU field + | Lock_N | for CPU1 + ------------------ + | XXXXX | + | Padding to | + | next Cache WB | + | Granule | + ------------------ + +Consider a system of 2 CPUs with 'N' bakery locks as shown above. For an +operation on Lock_N, the corresponding ``bakery_info_t`` in both CPU0 and CPU1 +``bakery_lock`` section need to be fetched and appropriate cache operations need +to be performed for each access. + +On Arm Platforms, bakery locks are used in psci (``psci_locks``) and power controller +driver (``arm_lock``). + +Non Functional Impact of removing coherent memory +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Removal of the coherent memory region leads to the additional software overhead +of performing cache maintenance for the affected data structures. However, since +the memory where the data structures are allocated is cacheable, the overhead is +mostly mitigated by an increase in performance. + +There is however a performance impact for bakery locks, due to: + +- Additional cache maintenance operations, and +- Multiple cache line reads for each lock operation, since the bakery locks + for each CPU are distributed across different cache lines. + +The implementation has been optimized to minimize this additional overhead. +Measurements indicate that when bakery locks are allocated in Normal memory, the +minimum latency of acquiring a lock is on an average 3-4 micro seconds whereas +in Device memory the same is 2 micro seconds. The measurements were done on the +Juno Arm development platform. + +As mentioned earlier, almost a page of memory can be saved by disabling +``USE_COHERENT_MEM``. Each platform needs to consider these trade-offs to decide +whether coherent memory should be used. If a platform disables +``USE_COHERENT_MEM`` and needs to use bakery locks in the porting layer, it can +optionally define macro ``PLAT_PERCPU_BAKERY_LOCK_SIZE`` (see the +`Porting Guide`_). Refer to the reference platform code for examples. + +Isolating code and read-only data on separate memory pages +---------------------------------------------------------- + +In the Armv8-A VMSA, translation table entries include fields that define the +properties of the target memory region, such as its access permissions. The +smallest unit of memory that can be addressed by a translation table entry is +a memory page. Therefore, if software needs to set different permissions on two +memory regions then it needs to map them using different memory pages. + +The default memory layout for each BL image is as follows: + +:: + + | ... | + +-------------------+ + | Read-write data | + +-------------------+ Page boundary + | | + +-------------------+ + | Exception vectors | + +-------------------+ 2 KB boundary + | | + +-------------------+ + | Read-only data | + +-------------------+ + | Code | + +-------------------+ BLx_BASE + +Note: The 2KB alignment for the exception vectors is an architectural +requirement. + +The read-write data start on a new memory page so that they can be mapped with +read-write permissions, whereas the code and read-only data below are configured +as read-only. + +However, the read-only data are not aligned on a page boundary. They are +contiguous to the code. Therefore, the end of the code section and the beginning +of the read-only data one might share a memory page. This forces both to be +mapped with the same memory attributes. As the code needs to be executable, this +means that the read-only data stored on the same memory page as the code are +executable as well. This could potentially be exploited as part of a security +attack. + +TF provides the build flag ``SEPARATE_CODE_AND_RODATA`` to isolate the code and +read-only data on separate memory pages. This in turn allows independent control +of the access permissions for the code and read-only data. In this case, +platform code gets a finer-grained view of the image layout and can +appropriately map the code region as executable and the read-only data as +execute-never. + +This has an impact on memory footprint, as padding bytes need to be introduced +between the code and read-only data to ensure the segregation of the two. To +limit the memory cost, this flag also changes the memory layout such that the +code and exception vectors are now contiguous, like so: + +:: + + | ... | + +-------------------+ + | Read-write data | + +-------------------+ Page boundary + | | + +-------------------+ + | Read-only data | + +-------------------+ Page boundary + | | + +-------------------+ + | Exception vectors | + +-------------------+ 2 KB boundary + | | + +-------------------+ + | Code | + +-------------------+ BLx_BASE + +With this more condensed memory layout, the separation of read-only data will +add zero or one page to the memory footprint of each BL image. Each platform +should consider the trade-off between memory footprint and security. + +This build flag is disabled by default, minimising memory footprint. On Arm +platforms, it is enabled. + +Publish and Subscribe Framework +------------------------------- + +The Publish and Subscribe Framework allows EL3 components to define and publish +events, to which other EL3 components can subscribe. + +The following macros are provided by the framework: + +- ``REGISTER_PUBSUB_EVENT(event)``: Defines an event, and takes one argument, + the event name, which must be a valid C identifier. All calls to + ``REGISTER_PUBSUB_EVENT`` macro must be placed in the file + ``pubsub_events.h``. + +- ``PUBLISH_EVENT_ARG(event, arg)``: Publishes a defined event, by iterating + subscribed handlers and calling them in turn. The handlers will be passed the + parameter ``arg``. The expected use-case is to broadcast an event. + +- ``PUBLISH_EVENT(event)``: Like ``PUBLISH_EVENT_ARG``, except that the value + ``NULL`` is passed to subscribed handlers. + +- ``SUBSCRIBE_TO_EVENT(event, handler)``: Registers the ``handler`` to + subscribe to ``event``. The handler will be executed whenever the ``event`` + is published. + +- ``for_each_subscriber(event, subscriber)``: Iterates through all handlers + subscribed for ``event``. ``subscriber`` must be a local variable of type + ``pubsub_cb_t *``, and will point to each subscribed handler in turn during + iteration. This macro can be used for those patterns that none of the + ``PUBLISH_EVENT_*()`` macros cover. + +Publishing an event that wasn't defined using ``REGISTER_PUBSUB_EVENT`` will +result in build error. Subscribing to an undefined event however won't. + +Subscribed handlers must be of type ``pubsub_cb_t``, with following function +signature: + +:: + + typedef void* (*pubsub_cb_t)(const void *arg); + +There may be arbitrary number of handlers registered to the same event. The +order in which subscribed handlers are notified when that event is published is +not defined. Subscribed handlers may be executed in any order; handlers should +not assume any relative ordering amongst them. + +Publishing an event on a PE will result in subscribed handlers executing on that +PE only; it won't cause handlers to execute on a different PE. + +Note that publishing an event on a PE blocks until all the subscribed handlers +finish executing on the PE. + +TF-A generic code publishes and subscribes to some events within. Platform +ports are discouraged from subscribing to them. These events may be withdrawn, +renamed, or have their semantics altered in the future. Platforms may however +register, publish, and subscribe to platform-specific events. + +Publish and Subscribe Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A publisher that wants to publish event ``foo`` would: + +- Define the event ``foo`` in the ``pubsub_events.h``. + + :: + + REGISTER_PUBSUB_EVENT(foo); + +- Depending on the nature of event, use one of ``PUBLISH_EVENT_*()`` macros to + publish the event at the appropriate path and time of execution. + +A subscriber that wants to subscribe to event ``foo`` published above would +implement: + +.. code:: c + + void *foo_handler(const void *arg) + { + void *result; + + /* Do handling ... */ + + return result; + } + + SUBSCRIBE_TO_EVENT(foo, foo_handler); + + +Reclaiming the BL31 initialization code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A significant amount of the code used for the initialization of BL31 is never +needed again after boot time. In order to reduce the runtime memory +footprint, the memory used for this code can be reclaimed after initialization +has finished and be used for runtime data. + +The build option ``RECLAIM_INIT_CODE`` can be set to mark this boot time code +with a ``.text.init.*`` attribute which can be filtered and placed suitably +within the BL image for later reclamation by the platform. The platform can +specify the filter and the memory region for this init section in BL31 via the +plat.ld.S linker script. For example, on the FVP, this section is placed +overlapping the secondary CPU stacks so that after the cold boot is done, this +memory can be reclaimed for the stacks. The init memory section is initially +mapped with ``RO``, ``EXECUTE`` attributes. After BL31 initialization has +completed, the FVP changes the attributes of this section to ``RW``, +``EXECUTE_NEVER`` allowing it to be used for runtime data. The memory attributes +are changed within the ``bl31_plat_runtime_setup`` platform hook. The init +section section can be reclaimed for any data which is accessed after cold +boot initialization and it is upto the platform to make the decision. + +Performance Measurement Framework +--------------------------------- + +The Performance Measurement Framework (PMF) facilitates collection of +timestamps by registered services and provides interfaces to retrieve them +from within TF-A. A platform can choose to expose appropriate SMCs to +retrieve these collected timestamps. + +By default, the global physical counter is used for the timestamp +value and is read via ``CNTPCT_EL0``. The framework allows to retrieve +timestamps captured by other CPUs. + +Timestamp identifier format +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A PMF timestamp is uniquely identified across the system via the +timestamp ID or ``tid``. The ``tid`` is composed as follows: + +:: + + Bits 0-7: The local timestamp identifier. + Bits 8-9: Reserved. + Bits 10-15: The service identifier. + Bits 16-31: Reserved. + +#. The service identifier. Each PMF service is identified by a + service name and a service identifier. Both the service name and + identifier are unique within the system as a whole. + +#. The local timestamp identifier. This identifier is unique within a given + service. + +Registering a PMF service +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To register a PMF service, the ``PMF_REGISTER_SERVICE()`` macro from ``pmf.h`` +is used. The arguments required are the service name, the service ID, +the total number of local timestamps to be captured and a set of flags. + +The ``flags`` field can be specified as a bitwise-OR of the following values: + +:: + + PMF_STORE_ENABLE: The timestamp is stored in memory for later retrieval. + PMF_DUMP_ENABLE: The timestamp is dumped on the serial console. + +The ``PMF_REGISTER_SERVICE()`` reserves memory to store captured +timestamps in a PMF specific linker section at build time. +Additionally, it defines necessary functions to capture and +retrieve a particular timestamp for the given service at runtime. + +The macro ``PMF_REGISTER_SERVICE()`` only enables capturing PMF timestamps +from within TF-A. In order to retrieve timestamps from outside of TF-A, the +``PMF_REGISTER_SERVICE_SMC()`` macro must be used instead. This macro +accepts the same set of arguments as the ``PMF_REGISTER_SERVICE()`` +macro but additionally supports retrieving timestamps using SMCs. + +Capturing a timestamp +~~~~~~~~~~~~~~~~~~~~~ + +PMF timestamps are stored in a per-service timestamp region. On a +system with multiple CPUs, each timestamp is captured and stored +in a per-CPU cache line aligned memory region. + +Having registered the service, the ``PMF_CAPTURE_TIMESTAMP()`` macro can be +used to capture a timestamp at the location where it is used. The macro +takes the service name, a local timestamp identifier and a flag as arguments. + +The ``flags`` field argument can be zero, or ``PMF_CACHE_MAINT`` which +instructs PMF to do cache maintenance following the capture. Cache +maintenance is required if any of the service's timestamps are captured +with data cache disabled. + +To capture a timestamp in assembly code, the caller should use +``pmf_calc_timestamp_addr`` macro (defined in ``pmf_asm_macros.S``) to +calculate the address of where the timestamp would be stored. The +caller should then read ``CNTPCT_EL0`` register to obtain the timestamp +and store it at the determined address for later retrieval. + +Retrieving a timestamp +~~~~~~~~~~~~~~~~~~~~~~ + +From within TF-A, timestamps for individual CPUs can be retrieved using either +``PMF_GET_TIMESTAMP_BY_MPIDR()`` or ``PMF_GET_TIMESTAMP_BY_INDEX()`` macros. +These macros accept the CPU's MPIDR value, or its ordinal position +respectively. + +From outside TF-A, timestamps for individual CPUs can be retrieved by calling +into ``pmf_smc_handler()``. + +.. code:: c + + Interface : pmf_smc_handler() + Argument : unsigned int smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4, void *cookie, + void *handle, u_register_t flags + Return : uintptr_t + + smc_fid: Holds the SMC identifier which is either `PMF_SMC_GET_TIMESTAMP_32` + when the caller of the SMC is running in AArch32 mode + or `PMF_SMC_GET_TIMESTAMP_64` when the caller is running in AArch64 mode. + x1: Timestamp identifier. + x2: The `mpidr` of the CPU for which the timestamp has to be retrieved. + This can be the `mpidr` of a different core to the one initiating + the SMC. In that case, service specific cache maintenance may be + required to ensure the updated copy of the timestamp is returned. + x3: A flags value that is either 0 or `PMF_CACHE_MAINT`. If + `PMF_CACHE_MAINT` is passed, then the PMF code will perform a + cache invalidate before reading the timestamp. This ensures + an updated copy is returned. + +The remaining arguments, ``x4``, ``cookie``, ``handle`` and ``flags`` are unused +in this implementation. + +PMF code structure +~~~~~~~~~~~~~~~~~~ + +#. ``pmf_main.c`` consists of core functions that implement service registration, + initialization, storing, dumping and retrieving timestamps. + +#. ``pmf_smc.c`` contains the SMC handling for registered PMF services. + +#. ``pmf.h`` contains the public interface to Performance Measurement Framework. + +#. ``pmf_asm_macros.S`` consists of macros to facilitate capturing timestamps in + assembly code. + +#. ``pmf_helpers.h`` is an internal header used by ``pmf.h``. + +Armv8-A Architecture Extensions +------------------------------- + +TF-A makes use of Armv8-A Architecture Extensions where applicable. This +section lists the usage of Architecture Extensions, and build flags +controlling them. + +In general, and unless individually mentioned, the build options +``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` select the Architecture Extension to +target when building TF-A. Subsequent Arm Architecture Extensions are backward +compatible with previous versions. + +The build system only requires that ``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` have a +valid numeric value. These build options only control whether or not +Architecture Extension-specific code is included in the build. Otherwise, TF-A +targets the base Armv8.0-A architecture; i.e. as if ``ARM_ARCH_MAJOR`` == 8 +and ``ARM_ARCH_MINOR`` == 0, which are also their respective default values. + +See also the *Summary of build options* in `User Guide`_. + +For details on the Architecture Extension and available features, please refer +to the respective Architecture Extension Supplement. + +Armv8.1-A +~~~~~~~~~ + +This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` >= 8, or when +``ARM_ARCH_MAJOR`` == 8 and ``ARM_ARCH_MINOR`` >= 1. + +- The Compare and Swap instruction is used to implement spinlocks. Otherwise, + the load-/store-exclusive instruction pair is used. + +Armv8.2-A +~~~~~~~~~ + +- The presence of ARMv8.2-TTCNP is detected at runtime. When it is present, the + Common not Private (TTBRn_ELx.CnP) bit is enabled to indicate that multiple + Processing Elements in the same Inner Shareable domain use the same + translation table entries for a given stage of translation for a particular + translation regime. + +Armv8.3-A +~~~~~~~~~ + +- Pointer authentication features of Armv8.3-A are unconditionally enabled in + the Non-secure world so that lower ELs are allowed to use them without + causing a trap to EL3. + + In order to enable the Secure world to use it, ``CTX_INCLUDE_PAUTH_REGS`` + must be set to 1. This will add all pointer authentication system registers + to the context that is saved when doing a world switch. + + The TF-A itself has support for pointer authentication at runtime + that can be enabled by setting both options ``ENABLE_PAUTH`` and + ``CTX_INCLUDE_PAUTH_REGS`` to 1. This enables pointer authentication in BL1, + BL2, BL31, and the TSP if it is used. + + These options are experimental features. + + Note that Pointer Authentication is enabled for Non-secure world irrespective + of the value of these build flags if the CPU supports it. + + If ``ARM_ARCH_MAJOR == 8`` and ``ARM_ARCH_MINOR >= 3`` the code footprint of + enabling PAuth is lower because the compiler will use the optimized + PAuth instructions rather than the backwards-compatible ones. + +Armv7-A +~~~~~~~ + +This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 7. + +There are several Armv7-A extensions available. Obviously the TrustZone +extension is mandatory to support the TF-A bootloader and runtime services. + +Platform implementing an Armv7-A system can to define from its target +Cortex-A architecture through ``ARM_CORTEX_A = yes`` in their +``platform.mk`` script. For example ``ARM_CORTEX_A15=yes`` for a +Cortex-A15 target. + +Platform can also set ``ARM_WITH_NEON=yes`` to enable neon support. +Note that using neon at runtime has constraints on non secure wolrd context. +TF-A does not yet provide VFP context management. + +Directive ``ARM_CORTEX_A`` and ``ARM_WITH_NEON`` are used to set +the toolchain target architecture directive. + +Platform may choose to not define straight the toolchain target architecture +directive by defining ``MARCH32_DIRECTIVE``. +I.e: + +:: + + MARCH32_DIRECTIVE := -mach=armv7-a + +Code Structure +-------------- + +TF-A code is logically divided between the three boot loader stages mentioned +in the previous sections. The code is also divided into the following +categories (present as directories in the source code): + +- **Platform specific.** Choice of architecture specific code depends upon + the platform. +- **Common code.** This is platform and architecture agnostic code. +- **Library code.** This code comprises of functionality commonly used by all + other code. The PSCI implementation and other EL3 runtime frameworks reside + as Library components. +- **Stage specific.** Code specific to a boot stage. +- **Drivers.** +- **Services.** EL3 runtime services (eg: SPD). Specific SPD services + reside in the ``services/spd`` directory (e.g. ``services/spd/tspd``). + +Each boot loader stage uses code from one or more of the above mentioned +categories. Based upon the above, the code layout looks like this: + +:: + + Directory Used by BL1? Used by BL2? Used by BL31? + bl1 Yes No No + bl2 No Yes No + bl31 No No Yes + plat Yes Yes Yes + drivers Yes No Yes + common Yes Yes Yes + lib Yes Yes Yes + services No No Yes + +The build system provides a non configurable build option IMAGE_BLx for each +boot loader stage (where x = BL stage). e.g. for BL1 , IMAGE_BL1 will be +defined by the build system. This enables TF-A to compile certain code only +for specific boot loader stages + +All assembler files have the ``.S`` extension. The linker source files for each +boot stage have the extension ``.ld.S``. These are processed by GCC to create the +linker scripts which have the extension ``.ld``. + +FDTs provide a description of the hardware platform and are used by the Linux +kernel at boot time. These can be found in the ``fdts`` directory. + +References +---------- + +.. [#] `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D)`_ +.. [#] `Power State Coordination Interface PDD`_ +.. [#] `SMC Calling Convention PDD`_ +.. [#] `TF-A Interrupt Management Design guide`_. + +-------------- + +*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Reset Design: ./reset-design.rst +.. _Porting Guide: ../getting_started/porting-guide.rst +.. _Firmware Update: ./firmware-update.rst +.. _PSCI PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _SMC calling convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf +.. _PSCI Library integration guide: ../getting_started/psci-lib-integration-guide.rst +.. _SMCCC: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _here: ../getting_started/psci-lib-integration-guide.rst +.. _cpu-specific-build-macros.rst: ./cpu-specific-build-macros.rst +.. _CPUBM: ./cpu-specific-build-macros.rst +.. _Arm ARM: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a.e/index.html +.. _User Guide: ../getting_started/user-guide.rst +.. _SMC Calling Convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf +.. _TF-A Interrupt Management Design guide: ./interrupt-framework-design.rst +.. _Xlat_tables design: xlat-tables-lib-v2-design.rst +.. _Exception Handling Framework: exception-handling.rst +.. _ROMLIB Design: romlib-design.rst +.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a + +.. |Image 1| image:: diagrams/rt-svc-descs-layout.png?raw=true diff --git a/docs/design/index.rst b/docs/design/index.rst new file mode 100644 index 0000000..a51a4eb --- /dev/null +++ b/docs/design/index.rst @@ -0,0 +1,15 @@ +System Design +============= + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + auth-framework + cpu-specific-build-macros + firmware-design + interrupt-framework-design + psci-pd-tree + reset-design + trusted-board-boot diff --git a/docs/design/interrupt-framework-design.rst b/docs/design/interrupt-framework-design.rst new file mode 100644 index 0000000..e4ec65a --- /dev/null +++ b/docs/design/interrupt-framework-design.rst @@ -0,0 +1,1024 @@ +Trusted Firmware-A interrupt management design guide +==================================================== + + + + +.. contents:: + +This framework is responsible for managing interrupts routed to EL3. It also +allows EL3 software to configure the interrupt routing behavior. Its main +objective is to implement the following two requirements. + +#. It should be possible to route interrupts meant to be handled by secure + software (Secure interrupts) to EL3, when execution is in non-secure state + (normal world). The framework should then take care of handing control of + the interrupt to either software in EL3 or Secure-EL1 depending upon the + software configuration and the GIC implementation. This requirement ensures + that secure interrupts are under the control of the secure software with + respect to their delivery and handling without the possibility of + intervention from non-secure software. + +#. It should be possible to route interrupts meant to be handled by + non-secure software (Non-secure interrupts) to the last executed exception + level in the normal world when the execution is in secure world at + exception levels lower than EL3. This could be done with or without the + knowledge of software executing in Secure-EL1/Secure-EL0. The choice of + approach should be governed by the secure software. This requirement + ensures that non-secure software is able to execute in tandem with the + secure software without overriding it. + +Concepts +-------- + +Interrupt types +~~~~~~~~~~~~~~~ + +The framework categorises an interrupt to be one of the following depending upon +the exception level(s) it is handled in. + +#. Secure EL1 interrupt. This type of interrupt can be routed to EL3 or + Secure-EL1 depending upon the security state of the current execution + context. It is always handled in Secure-EL1. + +#. Non-secure interrupt. This type of interrupt can be routed to EL3, + Secure-EL1, Non-secure EL1 or EL2 depending upon the security state of the + current execution context. It is always handled in either Non-secure EL1 + or EL2. + +#. EL3 interrupt. This type of interrupt can be routed to EL3 or Secure-EL1 + depending upon the security state of the current execution context. It is + always handled in EL3. + +The following constants define the various interrupt types in the framework +implementation. + +:: + + #define INTR_TYPE_S_EL1 0 + #define INTR_TYPE_EL3 1 + #define INTR_TYPE_NS 2 + +Routing model +~~~~~~~~~~~~~ + +A type of interrupt can be either generated as an FIQ or an IRQ. The target +exception level of an interrupt type is configured through the FIQ and IRQ bits +in the Secure Configuration Register at EL3 (``SCR_EL3.FIQ`` and ``SCR_EL3.IRQ`` +bits). When ``SCR_EL3.FIQ``\ =1, FIQs are routed to EL3. Otherwise they are routed +to the First Exception Level (FEL) capable of handling interrupts. When +``SCR_EL3.IRQ``\ =1, IRQs are routed to EL3. Otherwise they are routed to the +FEL. This register is configured independently by EL3 software for each security +state prior to entry into a lower exception level in that security state. + +A routing model for a type of interrupt (generated as FIQ or IRQ) is defined as +its target exception level for each security state. It is represented by a +single bit for each security state. A value of ``0`` means that the interrupt +should be routed to the FEL. A value of ``1`` means that the interrupt should be +routed to EL3. A routing model is applicable only when execution is not in EL3. + +The default routing model for an interrupt type is to route it to the FEL in +either security state. + +Valid routing models +~~~~~~~~~~~~~~~~~~~~ + +The framework considers certain routing models for each type of interrupt to be +incorrect as they conflict with the requirements mentioned in Section 1. The +following sub-sections describe all the possible routing models and specify +which ones are valid or invalid. EL3 interrupts are currently supported only +for GIC version 3.0 (Arm GICv3) and only the Secure-EL1 and Non-secure interrupt +types are supported for GIC version 2.0 (Arm GICv2) (see `Assumptions in +Interrupt Management Framework`_). The terminology used in the following +sub-sections is explained below. + +#. **CSS**. Current Security State. ``0`` when secure and ``1`` when non-secure + +#. **TEL3**. Target Exception Level 3. ``0`` when targeted to the FEL. ``1`` when + targeted to EL3. + +Secure-EL1 interrupts +^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + secure state. This is a valid routing model as secure software is in + control of handling secure interrupts. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure + state. This is a valid routing model as secure software in EL3 can + handover the interrupt to Secure-EL1 for handling. + +#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in + non-secure state. This is an invalid routing model as a secure interrupt + is not visible to the secure software which violates the motivation behind + the Arm Security Extensions. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is a valid routing model as secure software in EL3 + can handover the interrupt to Secure-EL1 for handling. + +Non-secure interrupts +^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + secure state. This allows the secure software to trap non-secure + interrupts, perform its book-keeping and hand the interrupt to the + non-secure software through EL3. This is a valid routing model as secure + software is in control of how its execution is preempted by non-secure + interrupts. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure + state. This is a valid routing model as secure software in EL3 can save + the state of software in Secure-EL1/Secure-EL0 before handing the + interrupt to non-secure software. This model requires additional + coordination between Secure-EL1 and EL3 software to ensure that the + former's state is correctly saved by the latter. + +#. **CSS=1, TEL3=0**. Interrupt is routed to FEL when execution is in + non-secure state. This is a valid routing model as a non-secure interrupt + is handled by non-secure software. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is an invalid routing model as there is no valid + reason to route the interrupt to EL3 software and then hand it back to + non-secure software for handling. + +EL3 interrupts +^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + Secure-EL1/Secure-EL0. This is a valid routing model as secure software + in Secure-EL1/Secure-EL0 is in control of how its execution is preempted + by EL3 interrupt and can handover the interrupt to EL3 for handling. + + However, when ``EL3_EXCEPTION_HANDLING`` is ``1``, this routing model is + invalid as EL3 interrupts are unconditionally routed to EL3, and EL3 + interrupts will always preempt Secure EL1/EL0 execution. See `exception + handling`__ documentation. + + .. __: exception-handling.rst#interrupt-handling + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in + Secure-EL1/Secure-EL0. This is a valid routing model as secure software + in EL3 can handle the interrupt. + +#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in + non-secure state. This is an invalid routing model as a secure interrupt + is not visible to the secure software which violates the motivation behind + the Arm Security Extensions. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is a valid routing model as secure software in EL3 + can handle the interrupt. + +Mapping of interrupt type to signal +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The framework is meant to work with any interrupt controller implemented by a +platform. A interrupt controller could generate a type of interrupt as either an +FIQ or IRQ signal to the CPU depending upon the current security state. The +mapping between the type and signal is known only to the platform. The framework +uses this information to determine whether the IRQ or the FIQ bit should be +programmed in ``SCR_EL3`` while applying the routing model for a type of +interrupt. The platform provides this information through the +``plat_interrupt_type_to_line()`` API (described in the +`Porting Guide`_). For example, on the FVP port when the platform uses an Arm GICv2 +interrupt controller, Secure-EL1 interrupts are signaled through the FIQ signal +while Non-secure interrupts are signaled through the IRQ signal. This applies +when execution is in either security state. + +Effect of mapping of several interrupt types to one signal +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It should be noted that if more than one interrupt type maps to a single +interrupt signal, and if any one of the interrupt type sets **TEL3=1** for a +particular security state, then interrupt signal will be routed to EL3 when in +that security state. This means that all the other interrupt types using the +same interrupt signal will be forced to the same routing model. This should be +borne in mind when choosing the routing model for an interrupt type. + +For example, in Arm GICv3, when the execution context is Secure-EL1/ +Secure-EL0, both the EL3 and the non secure interrupt types map to the FIQ +signal. So if either one of the interrupt type sets the routing model so +that **TEL3=1** when **CSS=0**, the FIQ bit in ``SCR_EL3`` will be programmed to +route the FIQ signal to EL3 when executing in Secure-EL1/Secure-EL0, thereby +effectively routing the other interrupt type also to EL3. + +Assumptions in Interrupt Management Framework +--------------------------------------------- + +The framework makes the following assumptions to simplify its implementation. + +#. Although the framework has support for 2 types of secure interrupts (EL3 + and Secure-EL1 interrupt), only interrupt controller architectures + like Arm GICv3 has architectural support for EL3 interrupts in the form of + Group 0 interrupts. In Arm GICv2, all secure interrupts are assumed to be + handled in Secure-EL1. They can be delivered to Secure-EL1 via EL3 but they + cannot be handled in EL3. + +#. Interrupt exceptions (``PSTATE.I`` and ``F`` bits) are masked during execution + in EL3. + +#. Interrupt management: the following sections describe how interrupts are + managed by the interrupt handling framework. This entails: + + #. Providing an interface to allow registration of a handler and + specification of the routing model for a type of interrupt. + + #. Implementing support to hand control of an interrupt type to its + registered handler when the interrupt is generated. + +Both aspects of interrupt management involve various components in the secure +software stack spanning from EL3 to Secure-EL1. These components are described +in the section `Software components`_. The framework stores information +associated with each type of interrupt in the following data structure. + +.. code:: c + + typedef struct intr_type_desc { + interrupt_type_handler_t handler; + uint32_t flags; + uint32_t scr_el3[2]; + } intr_type_desc_t; + +The ``flags`` field stores the routing model for the interrupt type in +bits[1:0]. Bit[0] stores the routing model when execution is in the secure +state. Bit[1] stores the routing model when execution is in the non-secure +state. As mentioned in Section `Routing model`_, a value of ``0`` implies that +the interrupt should be targeted to the FEL. A value of ``1`` implies that it +should be targeted to EL3. The remaining bits are reserved and SBZ. The helper +macro ``set_interrupt_rm_flag()`` should be used to set the bits in the +``flags`` parameter. + +The ``scr_el3[2]`` field also stores the routing model but as a mapping of the +model in the ``flags`` field to the corresponding bit in the ``SCR_EL3`` for each +security state. + +The framework also depends upon the platform port to configure the interrupt +controller to distinguish between secure and non-secure interrupts. The platform +is expected to be aware of the secure devices present in the system and their +associated interrupt numbers. It should configure the interrupt controller to +enable the secure interrupts, ensure that their priority is always higher than +the non-secure interrupts and target them to the primary CPU. It should also +export the interface described in the `Porting Guide`_ to enable +handling of interrupts. + +In the remainder of this document, for the sake of simplicity a Arm GICv2 system +is considered and it is assumed that the FIQ signal is used to generate Secure-EL1 +interrupts and the IRQ signal is used to generate non-secure interrupts in either +security state. EL3 interrupts are not considered. + +Software components +------------------- + +Roles and responsibilities for interrupt management are sub-divided between the +following components of software running in EL3 and Secure-EL1. Each component is +briefly described below. + +#. EL3 Runtime Firmware. This component is common to all ports of TF-A. + +#. Secure Payload Dispatcher (SPD) service. This service interfaces with the + Secure Payload (SP) software which runs in Secure-EL1/Secure-EL0 and is + responsible for switching execution between secure and non-secure states. + A switch is triggered by a Secure Monitor Call and it uses the APIs + exported by the Context management library to implement this functionality. + Switching execution between the two security states is a requirement for + interrupt management as well. This results in a significant dependency on + the SPD service. TF-A implements an example Test Secure Payload Dispatcher + (TSPD) service. + + An SPD service plugs into the EL3 runtime firmware and could be common to + some ports of TF-A. + +#. Secure Payload (SP). On a production system, the Secure Payload corresponds + to a Secure OS which runs in Secure-EL1/Secure-EL0. It interfaces with the + SPD service to manage communication with non-secure software. TF-A + implements an example secure payload called Test Secure Payload (TSP) + which runs only in Secure-EL1. + + A Secure payload implementation could be common to some ports of TF-A, + just like the SPD service. + +Interrupt registration +---------------------- + +This section describes in detail the role of each software component (see +`Software components`_) during the registration of a handler for an interrupt +type. + +EL3 runtime firmware +~~~~~~~~~~~~~~~~~~~~ + +This component declares the following prototype for a handler of an interrupt type. + +.. code:: c + + typedef uint64_t (*interrupt_type_handler_t)(uint32_t id, + uint32_t flags, + void *handle, + void *cookie); + +The ``id`` is parameter is reserved and could be used in the future for passing +the interrupt id of the highest pending interrupt only if there is a foolproof +way of determining the id. Currently it contains ``INTR_ID_UNAVAILABLE``. + +The ``flags`` parameter contains miscellaneous information as follows. + +#. Security state, bit[0]. This bit indicates the security state of the lower + exception level when the interrupt was generated. A value of ``1`` means + that it was in the non-secure state. A value of ``0`` indicates that it was + in the secure state. This bit can be used by the handler to ensure that + interrupt was generated and routed as per the routing model specified + during registration. + +#. Reserved, bits[31:1]. The remaining bits are reserved for future use. + +The ``handle`` parameter points to the ``cpu_context`` structure of the current CPU +for the security state specified in the ``flags`` parameter. + +Once the handler routine completes, execution will return to either the secure +or non-secure state. The handler routine must return a pointer to +``cpu_context`` structure of the current CPU for the target security state. On +AArch64, this return value is currently ignored by the caller as the +appropriate ``cpu_context`` to be used is expected to be set by the handler +via the context management library APIs. +A portable interrupt handler implementation must set the target context both in +the structure pointed to by the returned pointer and via the context management +library APIs. The handler should treat all error conditions as critical errors +and take appropriate action within its implementation e.g. use assertion +failures. + +The runtime firmware provides the following API for registering a handler for a +particular type of interrupt. A Secure Payload Dispatcher service should use +this API to register a handler for Secure-EL1 and optionally for non-secure +interrupts. This API also requires the caller to specify the routing model for +the type of interrupt. + +.. code:: c + + int32_t register_interrupt_type_handler(uint32_t type, + interrupt_type_handler handler, + uint64_t flags); + +The ``type`` parameter can be one of the three interrupt types listed above i.e. +``INTR_TYPE_S_EL1``, ``INTR_TYPE_NS`` & ``INTR_TYPE_EL3``. The ``flags`` parameter +is as described in Section 2. + +The function will return ``0`` upon a successful registration. It will return +``-EALREADY`` in case a handler for the interrupt type has already been +registered. If the ``type`` is unrecognised or the ``flags`` or the ``handler`` are +invalid it will return ``-EINVAL``. + +Interrupt routing is governed by the configuration of the ``SCR_EL3.FIQ/IRQ`` bits +prior to entry into a lower exception level in either security state. The +context management library maintains a copy of the ``SCR_EL3`` system register for +each security state in the ``cpu_context`` structure of each CPU. It exports the +following APIs to let EL3 Runtime Firmware program and retrieve the routing +model for each security state for the current CPU. The value of ``SCR_EL3`` stored +in the ``cpu_context`` is used by the ``el3_exit()`` function to program the +``SCR_EL3`` register prior to returning from the EL3 exception level. + +.. code:: c + + uint32_t cm_get_scr_el3(uint32_t security_state); + void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value); + +``cm_get_scr_el3()`` returns the value of the ``SCR_EL3`` register for the specified +security state of the current CPU. ``cm_write_scr_el3()`` writes a ``0`` or ``1`` to +the bit specified by ``bit_pos``. ``register_interrupt_type_handler()`` invokes +``set_routing_model()`` API which programs the ``SCR_EL3`` according to the routing +model using the ``cm_get_scr_el3()`` and ``cm_write_scr_el3_bit()`` APIs. + +It is worth noting that in the current implementation of the framework, the EL3 +runtime firmware is responsible for programming the routing model. The SPD is +responsible for ensuring that the routing model has been adhered to upon +receiving an interrupt. + +.. _spd-int-registration: + +Secure payload dispatcher +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A SPD service is responsible for determining and maintaining the interrupt +routing model supported by itself and the Secure Payload. It is also responsible +for ferrying interrupts between secure and non-secure software depending upon +the routing model. It could determine the routing model at build time or at +runtime. It must use this information to register a handler for each interrupt +type using the ``register_interrupt_type_handler()`` API in EL3 runtime firmware. + +If the routing model is not known to the SPD service at build time, then it must +be provided by the SP as the result of its initialisation. The SPD should +program the routing model only after SP initialisation has completed e.g. in the +SPD initialisation function pointed to by the ``bl32_init`` variable. + +The SPD should determine the mechanism to pass control to the Secure Payload +after receiving an interrupt from the EL3 runtime firmware. This information +could either be provided to the SPD service at build time or by the SP at +runtime. + +Test secure payload dispatcher behavior +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Note:** where this document discusses ``TSP_NS_INTR_ASYNC_PREEMPT`` as being +``1``, the same results also apply when ``EL3_EXCEPTION_HANDLING`` is ``1``. + +The TSPD only handles Secure-EL1 interrupts and is provided with the following +routing model at build time. + +- Secure-EL1 interrupts are routed to EL3 when execution is in non-secure + state and are routed to the FEL when execution is in the secure state + i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=1** for Secure-EL1 interrupts + +- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is zero, the default routing + model is used for non-secure interrupts. They are routed to the FEL in + either security state i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=0** for + Non-secure interrupts. + +- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, then the + non secure interrupts are routed to EL3 when execution is in secure state + i.e **CSS=0, TEL3=1** for non-secure interrupts. This effectively preempts + Secure-EL1. The default routing model is used for non secure interrupts in + non-secure state. i.e **CSS=1, TEL3=0**. + +It performs the following actions in the ``tspd_init()`` function to fulfill the +requirements mentioned earlier. + +#. It passes control to the Test Secure Payload to perform its + initialisation. The TSP provides the address of the vector table + ``tsp_vectors`` in the SP which also includes the handler for Secure-EL1 + interrupts in the ``sel1_intr_entry`` field. The TSPD passes control to the TSP at + this address when it receives a Secure-EL1 interrupt. + + The handover agreement between the TSP and the TSPD requires that the TSPD + masks all interrupts (``PSTATE.DAIF`` bits) when it calls + ``tsp_sel1_intr_entry()``. The TSP has to preserve the callee saved general + purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use + ``x0-x18`` to enable its C runtime. + +#. The TSPD implements a handler function for Secure-EL1 interrupts. This + function is registered with the EL3 runtime firmware using the + ``register_interrupt_type_handler()`` API as follows + + .. code:: c + + /* Forward declaration */ + interrupt_type_handler tspd_secure_el1_interrupt_handler; + int32_t rc, flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tspd_secure_el1_interrupt_handler, + flags); + if (rc) + panic(); + +#. When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, the TSPD + implements a handler function for non-secure interrupts. This function is + registered with the EL3 runtime firmware using the + ``register_interrupt_type_handler()`` API as follows + + .. code:: c + + /* Forward declaration */ + interrupt_type_handler tspd_ns_interrupt_handler; + int32_t rc, flags = 0; + set_interrupt_rm_flag(flags, SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_NS, + tspd_ns_interrupt_handler, + flags); + if (rc) + panic(); + +.. _sp-int-registration: + +Secure payload +~~~~~~~~~~~~~~ + +A Secure Payload must implement an interrupt handling framework at Secure-EL1 +(Secure-EL1 IHF) to support its chosen interrupt routing model. Secure payload +execution will alternate between the below cases. + +#. In the code where IRQ, FIQ or both interrupts are enabled, if an interrupt + type is targeted to the FEL, then it will be routed to the Secure-EL1 + exception vector table. This is defined as the **asynchronous mode** of + handling interrupts. This mode applies to both Secure-EL1 and non-secure + interrupts. + +#. In the code where both interrupts are disabled, if an interrupt type is + targeted to the FEL, then execution will eventually migrate to the + non-secure state. Any non-secure interrupts will be handled as described + in the routing model where **CSS=1 and TEL3=0**. Secure-EL1 interrupts + will be routed to EL3 (as per the routing model where **CSS=1 and + TEL3=1**) where the SPD service will hand them to the SP. This is defined + as the **synchronous mode** of handling interrupts. + +The interrupt handling framework implemented by the SP should support one or +both these interrupt handling models depending upon the chosen routing model. + +The following list briefly describes how the choice of a valid routing model +(see `Valid routing models`_) effects the implementation of the Secure-EL1 +IHF. If the choice of the interrupt routing model is not known to the SPD +service at compile time, then the SP should pass this information to the SPD +service at runtime during its initialisation phase. + +As mentioned earlier, an Arm GICv2 system is considered and it is assumed that +the FIQ signal is used to generate Secure-EL1 interrupts and the IRQ signal +is used to generate non-secure interrupts in either security state. + +Secure payload IHF design w.r.t secure-EL1 interrupts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. If ``PSTATE.F=0``, Secure-EL1 interrupts will be + triggered at one of the Secure-EL1 FIQ exception vectors. The Secure-EL1 + IHF should implement support for handling FIQ interrupts asynchronously. + + If ``PSTATE.F=1`` then Secure-EL1 interrupts will be handled as per the + synchronous interrupt handling model. The SP could implement this scenario + by exporting a separate entrypoint for Secure-EL1 interrupts to the SPD + service during the registration phase. The SPD service would also need to + know the state of the system, general purpose and the ``PSTATE`` registers + in which it should arrange to return execution to the SP. The SP should + provide this information in an implementation defined way during the + registration phase if it is not known to the SPD service at build time. + +#. **CSS=1, TEL3=1**. Interrupts are routed to EL3 when execution is in + non-secure state. They should be handled through the synchronous interrupt + handling model as described in 1. above. + +#. **CSS=0, TEL3=1**. Secure-EL1 interrupts are routed to EL3 when execution + is in secure state. They will not be visible to the SP. The ``PSTATE.F`` bit + in Secure-EL1/Secure-EL0 will not mask FIQs. The EL3 runtime firmware will + call the handler registered by the SPD service for Secure-EL1 interrupts. + Secure-EL1 IHF should then handle all Secure-EL1 interrupt through the + synchronous interrupt handling model described in 1. above. + +Secure payload IHF design w.r.t non-secure interrupts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. If ``PSTATE.I=0``, non-secure interrupts will be + triggered at one of the Secure-EL1 IRQ exception vectors . The Secure-EL1 + IHF should co-ordinate with the SPD service to transfer execution to the + non-secure state where the interrupt should be handled e.g the SP could + allocate a function identifier to issue a SMC64 or SMC32 to the SPD + service which indicates that the SP execution has been preempted by a + non-secure interrupt. If this function identifier is not known to the SPD + service at compile time then the SP could provide it during the + registration phase. + + If ``PSTATE.I=1`` then the non-secure interrupt will pend until execution + resumes in the non-secure state. + +#. **CSS=0, TEL3=1**. Non-secure interrupts are routed to EL3. They will not + be visible to the SP. The ``PSTATE.I`` bit in Secure-EL1/Secure-EL0 will + have not effect. The SPD service should register a non-secure interrupt + handler which should save the SP state correctly and resume execution in + the non-secure state where the interrupt will be handled. The Secure-EL1 + IHF does not need to take any action. + +#. **CSS=1, TEL3=0**. Non-secure interrupts are handled in the FEL in + non-secure state (EL1/EL2) and are not visible to the SP. This routing + model does not affect the SP behavior. + +A Secure Payload must also ensure that all Secure-EL1 interrupts are correctly +configured at the interrupt controller by the platform port of the EL3 runtime +firmware. It should configure any additional Secure-EL1 interrupts which the EL3 +runtime firmware is not aware of through its platform port. + +Test secure payload behavior +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is +described in Section `Secure Payload Dispatcher`__. It is known to the TSPD +service at build time. + +.. __: #spd-int-registration + +The TSP implements an entrypoint (``tsp_sel1_intr_entry()``) for handling Secure-EL1 +interrupts taken in non-secure state and routed through the TSPD service +(synchronous handling model). It passes the reference to this entrypoint via +``tsp_vectors`` to the TSPD service. + +The TSP also replaces the default exception vector table referenced through the +``early_exceptions`` variable, with a vector table capable of handling FIQ and IRQ +exceptions taken at the same (Secure-EL1) exception level. This table is +referenced through the ``tsp_exceptions`` variable and programmed into the +VBAR_EL1. It caters for the asynchronous handling model. + +The TSP also programs the Secure Physical Timer in the Arm Generic Timer block +to raise a periodic interrupt (every half a second) for the purpose of testing +interrupt management across all the software components listed in `Software +components`_. + +Interrupt handling +------------------ + +This section describes in detail the role of each software component (see +Section `Software components`_) in handling an interrupt of a particular type. + +EL3 runtime firmware +~~~~~~~~~~~~~~~~~~~~ + +The EL3 runtime firmware populates the IRQ and FIQ exception vectors referenced +by the ``runtime_exceptions`` variable as follows. + +#. IRQ and FIQ exceptions taken from the current exception level with + ``SP_EL0`` or ``SP_EL3`` are reported as irrecoverable error conditions. As + mentioned earlier, EL3 runtime firmware always executes with the + ``PSTATE.I`` and ``PSTATE.F`` bits set. + +#. The following text describes how the IRQ and FIQ exceptions taken from a + lower exception level using AArch64 or AArch32 are handled. + +When an interrupt is generated, the vector for each interrupt type is +responsible for: + +#. Saving the entire general purpose register context (x0-x30) immediately + upon exception entry. The registers are saved in the per-cpu ``cpu_context`` + data structure referenced by the ``SP_EL3``\ register. + +#. Saving the ``ELR_EL3``, ``SP_EL0`` and ``SPSR_EL3`` system registers in the + per-cpu ``cpu_context`` data structure referenced by the ``SP_EL3`` register. + +#. Switching to the C runtime stack by restoring the ``CTX_RUNTIME_SP`` value + from the per-cpu ``cpu_context`` data structure in ``SP_EL0`` and + executing the ``msr spsel, #0`` instruction. + +#. Determining the type of interrupt. Secure-EL1 interrupts will be signaled + at the FIQ vector. Non-secure interrupts will be signaled at the IRQ + vector. The platform should implement the following API to determine the + type of the pending interrupt. + + .. code:: c + + uint32_t plat_ic_get_interrupt_type(void); + + It should return either ``INTR_TYPE_S_EL1`` or ``INTR_TYPE_NS``. + +#. Determining the handler for the type of interrupt that has been generated. + The following API has been added for this purpose. + + .. code:: c + + interrupt_type_handler get_interrupt_type_handler(uint32_t interrupt_type); + + It returns the reference to the registered handler for this interrupt + type. The ``handler`` is retrieved from the ``intr_type_desc_t`` structure as + described in Section 2. ``NULL`` is returned if no handler has been + registered for this type of interrupt. This scenario is reported as an + irrecoverable error condition. + +#. Calling the registered handler function for the interrupt type generated. + The ``id`` parameter is set to ``INTR_ID_UNAVAILABLE`` currently. The id along + with the current security state and a reference to the ``cpu_context_t`` + structure for the current security state are passed to the handler function + as its arguments. + + The handler function returns a reference to the per-cpu ``cpu_context_t`` + structure for the target security state. + +#. Calling ``el3_exit()`` to return from EL3 into a lower exception level in + the security state determined by the handler routine. The ``el3_exit()`` + function is responsible for restoring the register context from the + ``cpu_context_t`` data structure for the target security state. + +Secure payload dispatcher +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interrupt entry +^^^^^^^^^^^^^^^ + +The SPD service begins handling an interrupt when the EL3 runtime firmware calls +the handler function for that type of interrupt. The SPD service is responsible +for the following: + +#. Validating the interrupt. This involves ensuring that the interrupt was + generated according to the interrupt routing model specified by the SPD + service during registration. It should use the security state of the + exception level (passed in the ``flags`` parameter of the handler) where + the interrupt was taken from to determine this. If the interrupt is not + recognised then the handler should treat it as an irrecoverable error + condition. + + An SPD service can register a handler for Secure-EL1 and/or Non-secure + interrupts. A non-secure interrupt should never be routed to EL3 from + from non-secure state. Also if a routing model is chosen where Secure-EL1 + interrupts are routed to S-EL1 when execution is in Secure state, then a + S-EL1 interrupt should never be routed to EL3 from secure state. The handler + could use the security state flag to check this. + +#. Determining whether a context switch is required. This depends upon the + routing model and interrupt type. For non secure and S-EL1 interrupt, + if the security state of the execution context where the interrupt was + generated is not the same as the security state required for handling + the interrupt, a context switch is required. The following 2 cases + require a context switch from secure to non-secure or vice-versa: + + #. A Secure-EL1 interrupt taken from the non-secure state should be + routed to the Secure Payload. + + #. A non-secure interrupt taken from the secure state should be routed + to the last known non-secure exception level. + + The SPD service must save the system register context of the current + security state. It must then restore the system register context of the + target security state. It should use the ``cm_set_next_eret_context()`` API + to ensure that the next ``cpu_context`` to be restored is of the target + security state. + + If the target state is secure then execution should be handed to the SP as + per the synchronous interrupt handling model it implements. A Secure-EL1 + interrupt can be routed to EL3 while execution is in the SP. This implies + that SP execution can be preempted while handling an interrupt by a + another higher priority Secure-EL1 interrupt or a EL3 interrupt. The SPD + service should be able to handle this preemption or manage secure interrupt + priorities before handing control to the SP. + +#. Setting the return value of the handler to the per-cpu ``cpu_context`` if + the interrupt has been successfully validated and ready to be handled at a + lower exception level. + +The routing model allows non-secure interrupts to interrupt Secure-EL1 when in +secure state if it has been configured to do so. The SPD service and the SP +should implement a mechanism for routing these interrupts to the last known +exception level in the non-secure state. The former should save the SP context, +restore the non-secure context and arrange for entry into the non-secure state +so that the interrupt can be handled. + +Interrupt exit +^^^^^^^^^^^^^^ + +When the Secure Payload has finished handling a Secure-EL1 interrupt, it could +return control back to the SPD service through a SMC32 or SMC64. The SPD service +should handle this secure monitor call so that execution resumes in the +exception level and the security state from where the Secure-EL1 interrupt was +originally taken. + +Test secure payload dispatcher Secure-EL1 interrupt handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The example TSPD service registers a handler for Secure-EL1 interrupts taken +from the non-secure state. During execution in S-EL1, the TSPD expects that the +Secure-EL1 interrupts are handled in S-EL1 by TSP. Its handler +``tspd_secure_el1_interrupt_handler()`` expects only to be invoked for Secure-EL1 +originating from the non-secure state. It takes the following actions upon being +invoked. + +#. It uses the security state provided in the ``flags`` parameter to ensure + that the secure interrupt originated from the non-secure state. It asserts + if this is not the case. + +#. It saves the system register context for the non-secure state by calling + ``cm_el1_sysregs_context_save(NON_SECURE);``. + +#. It sets the ``ELR_EL3`` system register to ``tsp_sel1_intr_entry`` and sets the + ``SPSR_EL3.DAIF`` bits in the secure CPU context. It sets ``x0`` to + ``TSP_HANDLE_SEL1_INTR_AND_RETURN``. If the TSP was preempted earlier by a non + secure interrupt during ``yielding`` SMC processing, save the registers that + will be trashed, which is the ``ELR_EL3`` and ``SPSR_EL3``, in order to be able + to re-enter TSP for Secure-EL1 interrupt processing. It does not need to + save any other secure context since the TSP is expected to preserve it + (see section `Test secure payload dispatcher behavior`_). + +#. It restores the system register context for the secure state by calling + ``cm_el1_sysregs_context_restore(SECURE);``. + +#. It ensures that the secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(SECURE);``. + +#. It returns the per-cpu ``cpu_context`` to indicate that the interrupt can + now be handled by the SP. ``x1`` is written with the value of ``elr_el3`` + register for the non-secure state. This information is used by the SP for + debugging purposes. + +The figure below describes how the interrupt handling is implemented by the TSPD +when a Secure-EL1 interrupt is generated when execution is in the non-secure +state. + +|Image 1| + +The TSP issues an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier to +signal completion of interrupt handling. + +The TSPD service takes the following actions in ``tspd_smc_handler()`` function +upon receiving an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier: + +#. It ensures that the call originated from the secure state otherwise + execution returns to the non-secure state with ``SMC_UNK`` in ``x0``. + +#. It restores the saved ``ELR_EL3`` and ``SPSR_EL3`` system registers back to + the secure CPU context (see step 3 above) in case the TSP had been preempted + by a non secure interrupt earlier. + +#. It restores the system register context for the non-secure state by + calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. + +#. It ensures that the non-secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. + +#. ``tspd_smc_handler()`` returns a reference to the non-secure ``cpu_context`` + as the return value. + +Test secure payload dispatcher non-secure interrupt handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The TSP in Secure-EL1 can be preempted by a non-secure interrupt during +``yielding`` SMC processing or by a higher priority EL3 interrupt during +Secure-EL1 interrupt processing. When ``EL3_EXCEPTION_HANDLING`` is ``0``, only +non-secure interrupts can cause preemption of TSP since there are no EL3 +interrupts in the system. With ``EL3_EXCEPTION_HANDLING=1`` however, any EL3 +interrupt may preempt Secure execution. + +It should be noted that while TSP is preempted, the TSPD only allows entry into +the TSP either for Secure-EL1 interrupt handling or for resuming the preempted +``yielding`` SMC in response to the ``TSP_FID_RESUME`` SMC from the normal world. +(See Section `Implication of preempted SMC on Non-Secure Software`_). + +The non-secure interrupt triggered in Secure-EL1 during ``yielding`` SMC +processing can be routed to either EL3 or Secure-EL1 and is controlled by build +option ``TSP_NS_INTR_ASYNC_PREEMPT`` (see Section `Test secure payload +dispatcher behavior`_). If the build option is set, the TSPD will set the +routing model for the non-secure interrupt to be routed to EL3 from secure state +i.e. **TEL3=1, CSS=0** and registers ``tspd_ns_interrupt_handler()`` as the +non-secure interrupt handler. The ``tspd_ns_interrupt_handler()`` on being +invoked ensures that the interrupt originated from the secure state and disables +routing of non-secure interrupts from secure state to EL3. This is to prevent +further preemption (by a non-secure interrupt) when TSP is reentered for +handling Secure-EL1 interrupts that triggered while execution was in the normal +world. The ``tspd_ns_interrupt_handler()`` then invokes +``tspd_handle_sp_preemption()`` for further handling. + +If the ``TSP_NS_INTR_ASYNC_PREEMPT`` build option is zero (default), the default +routing model for non-secure interrupt in secure state is in effect +i.e. **TEL3=0, CSS=0**. During ``yielding`` SMC processing, the IRQ +exceptions are unmasked i.e. ``PSTATE.I=0``, and a non-secure interrupt will +trigger at Secure-EL1 IRQ exception vector. The TSP saves the general purpose +register context and issues an SMC with ``TSP_PREEMPTED`` as the function +identifier to signal preemption of TSP. The TSPD SMC handler, +``tspd_smc_handler()``, ensures that the SMC call originated from the +secure state otherwise execution returns to the non-secure state with +``SMC_UNK`` in ``x0``. It then invokes ``tspd_handle_sp_preemption()`` for +further handling. + +The ``tspd_handle_sp_preemption()`` takes the following actions upon being +invoked: + +#. It saves the system register context for the secure state by calling + ``cm_el1_sysregs_context_save(SECURE)``. + +#. It restores the system register context for the non-secure state by + calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. + +#. It ensures that the non-secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. + +#. ``SMC_PREEMPTED`` is set in x0 and return to non secure state after + restoring non secure context. + +The Normal World is expected to resume the TSP after the ``yielding`` SMC +preemption by issuing an SMC with ``TSP_FID_RESUME`` as the function identifier +(see section `Implication of preempted SMC on Non-Secure Software`_). The TSPD +service takes the following actions in ``tspd_smc_handler()`` function upon +receiving this SMC: + +#. It ensures that the call originated from the non secure state. An + assertion is raised otherwise. + +#. Checks whether the TSP needs a resume i.e check if it was preempted. It + then saves the system register context for the non-secure state by calling + ``cm_el1_sysregs_context_save(NON_SECURE)``. + +#. Restores the secure context by calling + ``cm_el1_sysregs_context_restore(SECURE)`` + +#. It ensures that the secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(SECURE)``. + +#. ``tspd_smc_handler()`` returns a reference to the secure ``cpu_context`` as the + return value. + +The figure below describes how the TSP/TSPD handle a non-secure interrupt when +it is generated during execution in the TSP with ``PSTATE.I`` = 0 when the +``TSP_NS_INTR_ASYNC_PREEMPT`` build flag is 0. + +|Image 2| + +Secure payload +~~~~~~~~~~~~~~ + +The SP should implement one or both of the synchronous and asynchronous +interrupt handling models depending upon the interrupt routing model it has +chosen (as described in section `Secure Payload`__). + +.. __: #sp-int-registration + +In the synchronous model, it should begin handling a Secure-EL1 interrupt after +receiving control from the SPD service at an entrypoint agreed upon during build +time or during the registration phase. Before handling the interrupt, the SP +should save any Secure-EL1 system register context which is needed for resuming +normal execution in the SP later e.g. ``SPSR_EL1``, ``ELR_EL1``. After handling +the interrupt, the SP could return control back to the exception level and +security state where the interrupt was originally taken from. The SP should use +an SMC32 or SMC64 to ask the SPD service to do this. + +In the asynchronous model, the Secure Payload is responsible for handling +non-secure and Secure-EL1 interrupts at the IRQ and FIQ vectors in its exception +vector table when ``PSTATE.I`` and ``PSTATE.F`` bits are 0. As described earlier, +when a non-secure interrupt is generated, the SP should coordinate with the SPD +service to pass control back to the non-secure state in the last known exception +level. This will allow the non-secure interrupt to be handled in the non-secure +state. + +Test secure payload behavior +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The TSPD hands control of a Secure-EL1 interrupt to the TSP at the +``tsp_sel1_intr_entry()``. The TSP handles the interrupt while ensuring that the +handover agreement described in Section `Test secure payload dispatcher +behavior`_ is maintained. It updates some statistics by calling +``tsp_update_sync_sel1_intr_stats()``. It then calls +``tsp_common_int_handler()`` which. + +#. Checks whether the interrupt is the secure physical timer interrupt. It + uses the platform API ``plat_ic_get_pending_interrupt_id()`` to get the + interrupt number. If it is not the secure physical timer interrupt, then + that means that a higher priority interrupt has preempted it. Invoke + ``tsp_handle_preemption()`` to handover control back to EL3 by issuing + an SMC with ``TSP_PREEMPTED`` as the function identifier. + +#. Handles the secure timer interrupt interrupt by acknowledging it using the + ``plat_ic_acknowledge_interrupt()`` platform API, calling + ``tsp_generic_timer_handler()`` to reprogram the secure physical generic + timer and calling the ``plat_ic_end_of_interrupt()`` platform API to signal + end of interrupt processing. + +The TSP passes control back to the TSPD by issuing an SMC64 with +``TSP_HANDLED_S_EL1_INTR`` as the function identifier. + +The TSP handles interrupts under the asynchronous model as follows. + +#. Secure-EL1 interrupts are handled by calling the ``tsp_common_int_handler()`` + function. The function has been described above. + +#. Non-secure interrupts are handled by calling the ``tsp_common_int_handler()`` + function which ends up invoking ``tsp_handle_preemption()`` and issuing an + SMC64 with ``TSP_PREEMPTED`` as the function identifier. Execution resumes at + the instruction that follows this SMC instruction when the TSPD hands control + to the TSP in response to an SMC with ``TSP_FID_RESUME`` as the function + identifier from the non-secure state (see section `Test secure payload + dispatcher non-secure interrupt handling`_). + +Other considerations +-------------------- + +Implication of preempted SMC on Non-Secure Software +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A ``yielding`` SMC call to Secure payload can be preempted by a non-secure +interrupt and the execution can return to the non-secure world for handling +the interrupt (For details on ``yielding`` SMC refer `SMC calling convention`_). +In this case, the SMC call has not completed its execution and the execution +must return back to the secure payload to resume the preempted SMC call. +This can be achieved by issuing an SMC call which instructs to resume the +preempted SMC. + +A ``fast`` SMC cannot be preempted and hence this case will not happen for +a fast SMC call. + +In the Test Secure Payload implementation, ``TSP_FID_RESUME`` is designated +as the resume SMC FID. It is important to note that ``TSP_FID_RESUME`` is a +``yielding`` SMC which means it too can be be preempted. The typical non +secure software sequence for issuing a ``yielding`` SMC would look like this, +assuming ``P.STATE.I=0`` in the non secure state : + +.. code:: c + + int rc; + rc = smc(TSP_YIELD_SMC_FID, ...); /* Issue a Yielding SMC call */ + /* The pending non-secure interrupt is handled by the interrupt handler + and returns back here. */ + while (rc == SMC_PREEMPTED) { /* Check if the SMC call is preempted */ + rc = smc(TSP_FID_RESUME); /* Issue resume SMC call */ + } + +The ``TSP_YIELD_SMC_FID`` is any ``yielding`` SMC function identifier and the smc() +function invokes a SMC call with the required arguments. The pending non-secure +interrupt causes an IRQ exception and the IRQ handler registered at the +exception vector handles the non-secure interrupt and returns. The return value +from the SMC call is tested for ``SMC_PREEMPTED`` to check whether it is +preempted. If it is, then the resume SMC call ``TSP_FID_RESUME`` is issued. The +return value of the SMC call is tested again to check if it is preempted. +This is done in a loop till the SMC call succeeds or fails. If a ``yielding`` +SMC is preempted, until it is resumed using ``TSP_FID_RESUME`` SMC and +completed, the current TSPD prevents any other SMC call from re-entering +TSP by returning ``SMC_UNK`` error. + +-------------- + +*Copyright (c) 2014-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Porting Guide: ../getting_started/porting-guide.rst +.. _SMC calling convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + +.. |Image 1| image:: diagrams/sec-int-handling.png?raw=true +.. |Image 2| image:: diagrams/non-sec-int-handling.png?raw=true diff --git a/docs/design/psci-pd-tree.rst b/docs/design/psci-pd-tree.rst new file mode 100644 index 0000000..2e2163a --- /dev/null +++ b/docs/design/psci-pd-tree.rst @@ -0,0 +1,311 @@ +PSCI Power Domain Tree design +============================= + + + + +.. contents:: + +-------------- + +Requirements +------------ + +#. A platform must export the ``plat_get_aff_count()`` and + ``plat_get_aff_state()`` APIs to enable the generic PSCI code to + populate a tree that describes the hierarchy of power domains in the + system. This approach is inflexible because a change to the topology + requires a change in the code. + + It would be much simpler for the platform to describe its power domain tree + in a data structure. + +#. The generic PSCI code generates MPIDRs in order to populate the power domain + tree. It also uses an MPIDR to find a node in the tree. The assumption that + a platform will use exactly the same MPIDRs as generated by the generic PSCI + code is not scalable. The use of an MPIDR also restricts the number of + levels in the power domain tree to four. + + Therefore, there is a need to decouple allocation of MPIDRs from the + mechanism used to populate the power domain topology tree. + +#. The current arrangement of the power domain tree requires a binary search + over the sibling nodes at a particular level to find a specified power + domain node. During a power management operation, the tree is traversed from + a 'start' to an 'end' power level. The binary search is required to find the + node at each level. The natural way to perform this traversal is to + start from a leaf node and follow the parent node pointer to reach the end + level. + + Therefore, there is a need to define data structures that implement the tree in + a way which facilitates such a traversal. + +#. The attributes of a core power domain differ from the attributes of power + domains at higher levels. For example, only a core power domain can be identified + using an MPIDR. There is no requirement to perform state coordination while + performing a power management operation on the core power domain. + + Therefore, there is a need to implement the tree in a way which facilitates this + distinction between a leaf and non-leaf node and any associated + optimizations. + +-------------- + +Design +------ + +Describing a power domain tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To fulfill requirement 1., the existing platform APIs +``plat_get_aff_count()`` and ``plat_get_aff_state()`` have been +removed. A platform must define an array of unsigned chars such that: + +#. The first entry in the array specifies the number of power domains at the + highest power level implemented in the platform. This caters for platforms + where the power domain tree does not have a single root node, for example, + the FVP has two cluster power domains at the highest level (1). + +#. Each subsequent entry corresponds to a power domain and contains the number + of power domains that are its direct children. + +#. The size of the array minus the first entry will be equal to the number of + non-leaf power domains. + +#. The value in each entry in the array is used to find the number of entries + to consider at the next level. The sum of the values (number of children) of + all the entries at a level specifies the number of entries in the array for + the next level. + +The following example power domain topology tree will be used to describe the +above text further. The leaf and non-leaf nodes in this tree have been numbered +separately. + +:: + + +-+ + |0| + +-+ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + +-+ +-+ + |1| |2| + +-+ +-+ + / \ / \ + / \ / \ + / \ / \ + / \ / \ + +-+ +-+ +-+ +-+ + |3| |4| |5| |6| + +-+ +-+ +-+ +-+ + +---+-----+ +----+----| +----+----+ +----+-----+-----+ + | | | | | | | | | | | | | + | | | | | | | | | | | | | + v v v v v v v v v v v v v + +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+ + |0| |1| |2| |3| |4| |5| |6| |7| |8| |9| |10| |11| |12| + +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+ + +This tree is defined by the platform as the array described above as follows: + +:: + + #define PLAT_NUM_POWER_DOMAINS 20 + #define PLATFORM_CORE_COUNT 13 + #define PSCI_NUM_NON_CPU_PWR_DOMAINS \ + (PLAT_NUM_POWER_DOMAINS - PLATFORM_CORE_COUNT) + + unsigned char plat_power_domain_tree_desc[] = { 1, 2, 2, 2, 3, 3, 3, 4}; + +Removing assumptions about MPIDRs used in a platform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To fulfill requirement 2., it is assumed that the platform assigns a +unique number (core index) between ``0`` and ``PLAT_CORE_COUNT - 1`` to each core +power domain. MPIDRs could be allocated in any manner and will not be used to +populate the tree. + +``plat_core_pos_by_mpidr(mpidr)`` will return the core index for the core +corresponding to the MPIDR. It will return an error (-1) if an MPIDR is passed +which is not allocated or corresponds to an absent core. The semantics of this +platform API have changed since it is required to validate the passed MPIDR. It +has been made a mandatory API as a result. + +Another mandatory API, ``plat_my_core_pos()`` has been added to return the core +index for the calling core. This API provides a more lightweight mechanism to get +the index since there is no need to validate the MPIDR of the calling core. + +The platform should assign the core indices (as illustrated in the diagram above) +such that, if the core nodes are numbered from left to right, then the index +for a core domain will be the same as the index returned by +``plat_core_pos_by_mpidr()`` or ``plat_my_core_pos()`` for that core. This +relationship allows the core nodes to be allocated in a separate array +(requirement 4.) during ``psci_setup()`` in such an order that the index of the +core in the array is the same as the return value from these APIs. + +Dealing with holes in MPIDR allocation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For platforms where the number of allocated MPIDRs is equal to the number of +core power domains, for example, Juno and FVPs, the logic to convert an MPIDR to +a core index should remain unchanged. Both Juno and FVP use a simple collision +proof hash function to do this. + +It is possible that on some platforms, the allocation of MPIDRs is not +contiguous or certain cores have been disabled. This essentially means that the +MPIDRs have been sparsely allocated, that is, the size of the range of MPIDRs +used by the platform is not equal to the number of core power domains. + +The platform could adopt one of the following approaches to deal with this +scenario: + +#. Implement more complex logic to convert a valid MPIDR to a core index while + maintaining the relationship described earlier. This means that the power + domain tree descriptor will not describe any core power domains which are + disabled or absent. Entries will not be allocated in the tree for these + domains. + +#. Treat unallocated MPIDRs and disabled cores as absent but still describe them + in the power domain descriptor, that is, the number of core nodes described + is equal to the size of the range of MPIDRs allocated. This approach will + lead to memory wastage since entries will be allocated in the tree but will + allow use of a simpler logic to convert an MPIDR to a core index. + +Traversing through and distinguishing between core and non-core power domains +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To fulfill requirement 3 and 4, separate data structures have been defined +to represent leaf and non-leaf power domain nodes in the tree. + +.. code:: c + + /******************************************************************************* + * The following two data structures implement the power domain tree. The tree + * is used to track the state of all the nodes i.e. power domain instances + * described by the platform. The tree consists of nodes that describe CPU power + * domains i.e. leaf nodes and all other power domains which are parents of a + * CPU power domain i.e. non-leaf nodes. + ******************************************************************************/ + typedef struct non_cpu_pwr_domain_node { + /* + * Index of the first CPU power domain node level 0 which has this node + * as its parent. + */ + unsigned int cpu_start_idx; + + /* + * Number of CPU power domains which are siblings of the domain indexed + * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx + * -> cpu_start_idx + ncpus' have this node as their parent. + */ + unsigned int ncpus; + + /* Index of the parent power domain node */ + unsigned int parent_node; + + ----- + } non_cpu_pd_node_t; + + typedef struct cpu_pwr_domain_node { + u_register_t mpidr; + + /* Index of the parent power domain node */ + unsigned int parent_node; + + ----- + } cpu_pd_node_t; + +The power domain tree is implemented as a combination of the following data +structures. + +:: + + non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS]; + cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT]; + +Populating the power domain tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``populate_power_domain_tree()`` function in ``psci_setup.c`` implements the +algorithm to parse the power domain descriptor exported by the platform to +populate the two arrays. It is essentially a breadth-first-search. The nodes for +each level starting from the root are laid out one after another in the +``psci_non_cpu_pd_nodes`` and ``psci_cpu_pd_nodes`` arrays as follows: + +:: + + psci_non_cpu_pd_nodes -> [[Level 3 nodes][Level 2 nodes][Level 1 nodes]] + psci_cpu_pd_nodes -> [Level 0 nodes] + +For the example power domain tree illustrated above, the ``psci_cpu_pd_nodes`` +will be populated as follows. The value in each entry is the index of the parent +node. Other fields have been ignored for simplicity. + +:: + + +-------------+ ^ + CPU0 | 3 | | + +-------------+ | + CPU1 | 3 | | + +-------------+ | + CPU2 | 3 | | + +-------------+ | + CPU3 | 4 | | + +-------------+ | + CPU4 | 4 | | + +-------------+ | + CPU5 | 4 | | PLATFORM_CORE_COUNT + +-------------+ | + CPU6 | 5 | | + +-------------+ | + CPU7 | 5 | | + +-------------+ | + CPU8 | 5 | | + +-------------+ | + CPU9 | 6 | | + +-------------+ | + CPU10 | 6 | | + +-------------+ | + CPU11 | 6 | | + +-------------+ | + CPU12 | 6 | v + +-------------+ + +The ``psci_non_cpu_pd_nodes`` array will be populated as follows. The value in +each entry is the index of the parent node. + +:: + + +-------------+ ^ + PD0 | -1 | | + +-------------+ | + PD1 | 0 | | + +-------------+ | + PD2 | 0 | | + +-------------+ | + PD3 | 1 | | PLAT_NUM_POWER_DOMAINS - + +-------------+ | PLATFORM_CORE_COUNT + PD4 | 1 | | + +-------------+ | + PD5 | 2 | | + +-------------+ | + PD6 | 2 | | + +-------------+ v + +Each core can find its node in the ``psci_cpu_pd_nodes`` array using the +``plat_my_core_pos()`` function. When a core is turned on, the normal world +provides an MPIDR. The ``plat_core_pos_by_mpidr()`` function is used to validate +the MPIDR before using it to find the corresponding core node. The non-core power +domain nodes do not need to be identified. + +-------------- + +*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* diff --git a/docs/design/reset-design.rst b/docs/design/reset-design.rst new file mode 100644 index 0000000..1473851 --- /dev/null +++ b/docs/design/reset-design.rst @@ -0,0 +1,165 @@ +Trusted Firmware-A reset design +=============================== + + + + +.. contents:: + +This document describes the high-level design of the framework to handle CPU +resets in Trusted Firmware-A (TF-A). It also describes how the platform +integrator can tailor this code to the system configuration to some extent, +resulting in a simplified and more optimised boot flow. + +This document should be used in conjunction with the `Firmware Design`_, which +provides greater implementation details around the reset code, specifically +for the cold boot path. + +General reset code flow +----------------------- + +The TF-A reset code is implemented in BL1 by default. The following high-level +diagram illustrates this: + +|Default reset code flow| + +This diagram shows the default, unoptimised reset flow. Depending on the system +configuration, some of these steps might be unnecessary. The following sections +guide the platform integrator by indicating which build options exclude which +steps, depending on the capability of the platform. + +Note: If BL31 is used as the TF-A entry point instead of BL1, the diagram +above is still relevant, as all these operations will occur in BL31 in +this case. Please refer to section 6 "Using BL31 entrypoint as the reset +address" for more information. + +Programmable CPU reset address +------------------------------ + +By default, TF-A assumes that the CPU reset address is not programmable. +Therefore, all CPUs start at the same address (typically address 0) whenever +they reset. Further logic is then required to identify whether it is a cold or +warm boot to direct CPUs to the right execution path. + +If the reset vector address (reflected in the reset vector base address register +``RVBAR_EL3``) is programmable then it is possible to make each CPU start directly +at the right address, both on a cold and warm reset. Therefore, the boot type +detection can be skipped, resulting in the following boot flow: + +|Reset code flow with programmable reset address| + +To enable this boot flow, compile TF-A with ``PROGRAMMABLE_RESET_ADDRESS=1``. +This option only affects the TF-A reset image, which is BL1 by default or BL31 if +``RESET_TO_BL31=1``. + +On both the FVP and Juno platforms, the reset vector address is not programmable +so both ports use ``PROGRAMMABLE_RESET_ADDRESS=0``. + +Cold boot on a single CPU +------------------------- + +By default, TF-A assumes that several CPUs may be released out of reset. +Therefore, the cold boot code has to arbitrate access to hardware resources +shared amongst CPUs. This is done by nominating one of the CPUs as the primary, +which is responsible for initialising shared hardware and coordinating the boot +flow with the other CPUs. + +If the platform guarantees that only a single CPU will ever be brought up then +no arbitration is required. The notion of primary/secondary CPU itself no longer +applies. This results in the following boot flow: + +|Reset code flow with single CPU released out of reset| + +To enable this boot flow, compile TF-A with ``COLD_BOOT_SINGLE_CPU=1``. This +option only affects the TF-A reset image, which is BL1 by default or BL31 if +``RESET_TO_BL31=1``. + +On both the FVP and Juno platforms, although only one core is powered up by +default, there are platform-specific ways to release any number of cores out of +reset. Therefore, both platform ports use ``COLD_BOOT_SINGLE_CPU=0``. + +Programmable CPU reset address, Cold boot on a single CPU +--------------------------------------------------------- + +It is obviously possible to combine both optimisations on platforms that have +a programmable CPU reset address and which release a single CPU out of reset. +This results in the following boot flow: + + +|Reset code flow with programmable reset address and single CPU released out of reset| + +To enable this boot flow, compile TF-A with both ``COLD_BOOT_SINGLE_CPU=1`` +and ``PROGRAMMABLE_RESET_ADDRESS=1``. These options only affect the TF-A reset +image, which is BL1 by default or BL31 if ``RESET_TO_BL31=1``. + +Using BL31 entrypoint as the reset address +------------------------------------------ + +On some platforms the runtime firmware (BL3x images) for the application +processors are loaded by some firmware running on a secure system processor +on the SoC, rather than by BL1 and BL2 running on the primary application +processor. For this type of SoC it is desirable for the application processor +to always reset to BL31 which eliminates the need for BL1 and BL2. + +TF-A provides a build-time option ``RESET_TO_BL31`` that includes some additional +logic in the BL31 entry point to support this use case. + +In this configuration, the platform's Trusted Boot Firmware must ensure that +BL31 is loaded to its runtime address, which must match the CPU's ``RVBAR_EL3`` +reset vector base address, before the application processor is powered on. +Additionally, platform software is responsible for loading the other BL3x images +required and providing entry point information for them to BL31. Loading these +images might be done by the Trusted Boot Firmware or by platform code in BL31. + +Although the Arm FVP platform does not support programming the reset base +address dynamically at run-time, it is possible to set the initial value of the +``RVBAR_EL3`` register at start-up. This feature is provided on the Base FVP only. +It allows the Arm FVP port to support the ``RESET_TO_BL31`` configuration, in +which case the ``bl31.bin`` image must be loaded to its run address in Trusted +SRAM and all CPU reset vectors be changed from the default ``0x0`` to this run +address. See the `User Guide`_ for details of running the FVP models in this way. + +Although technically it would be possible to program the reset base address with +the right support in the SCP firmware, this is currently not implemented so the +Juno port doesn't support the ``RESET_TO_BL31`` configuration. + +The ``RESET_TO_BL31`` configuration requires some additions and changes in the +BL31 functionality: + +Determination of boot path +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In this configuration, BL31 uses the same reset framework and code as the one +described for BL1 above. Therefore, it is affected by the +``PROGRAMMABLE_RESET_ADDRESS`` and ``COLD_BOOT_SINGLE_CPU`` build options in the +same way. + +In the default, unoptimised BL31 reset flow, on a warm boot a CPU is directed +to the PSCI implementation via a platform defined mechanism. On a cold boot, +the platform must place any secondary CPUs into a safe state while the primary +CPU executes a modified BL31 initialization, as described below. + +Platform initialization +~~~~~~~~~~~~~~~~~~~~~~~ + +In this configuration, when the CPU resets to BL31 there are no parameters that +can be passed in registers by previous boot stages. Instead, the platform code +in BL31 needs to know, or be able to determine, the location of the BL32 (if +required) and BL33 images and provide this information in response to the +``bl31_plat_get_next_image_ep_info()`` function. + +Additionally, platform software is responsible for carrying out any security +initialisation, for example programming a TrustZone address space controller. +This might be done by the Trusted Boot Firmware or by platform code in BL31. + +-------------- + +*Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.* + +.. _Firmware Design: firmware-design.rst +.. _User Guide: ../getting_started/user-guide.rst + +.. |Default reset code flow| image:: ../diagrams/default_reset_code.png?raw=true +.. |Reset code flow with programmable reset address| image:: ../diagrams/reset_code_no_boot_type_check.png?raw=true +.. |Reset code flow with single CPU released out of reset| image:: ../diagrams/reset_code_no_cpu_check.png?raw=true +.. |Reset code flow with programmable reset address and single CPU released out of reset| image:: ../diagrams/reset_code_no_checks.png?raw=true diff --git a/docs/design/trusted-board-boot.rst b/docs/design/trusted-board-boot.rst new file mode 100644 index 0000000..ae21bf0 --- /dev/null +++ b/docs/design/trusted-board-boot.rst @@ -0,0 +1,239 @@ +Trusted Board Boot Design Guide +=============================== + + + + +.. contents:: + +The Trusted Board Boot (TBB) feature prevents malicious firmware from running on +the platform by authenticating all firmware images up to and including the +normal world bootloader. It does this by establishing a Chain of Trust using +Public-Key-Cryptography Standards (PKCS). + +This document describes the design of Trusted Firmware-A (TF-A) TBB, which is an +implementation of the `Trusted Board Boot Requirements (TBBR)`_ specification, +Arm DEN0006D. It should be used in conjunction with the `Firmware Update`_ +design document, which implements a specific aspect of the TBBR. + +Chain of Trust +-------------- + +A Chain of Trust (CoT) starts with a set of implicitly trusted components. On +the Arm development platforms, these components are: + +- A SHA-256 hash of the Root of Trust Public Key (ROTPK). It is stored in the + trusted root-key storage registers. + +- The BL1 image, on the assumption that it resides in ROM so cannot be + tampered with. + +The remaining components in the CoT are either certificates or boot loader +images. The certificates follow the `X.509 v3`_ standard. This standard +enables adding custom extensions to the certificates, which are used to store +essential information to establish the CoT. + +In the TBB CoT all certificates are self-signed. There is no need for a +Certificate Authority (CA) because the CoT is not established by verifying the +validity of a certificate's issuer but by the content of the certificate +extensions. To sign the certificates, the PKCS#1 SHA-256 with RSA Encryption +signature scheme is used with a RSA key length of 2048 bits. Future version of +TF-A will support additional cryptographic algorithms. + +The certificates are categorised as "Key" and "Content" certificates. Key +certificates are used to verify public keys which have been used to sign content +certificates. Content certificates are used to store the hash of a boot loader +image. An image can be authenticated by calculating its hash and matching it +with the hash extracted from the content certificate. The SHA-256 function is +used to calculate all hashes. The public keys and hashes are included as +non-standard extension fields in the `X.509 v3`_ certificates. + +The keys used to establish the CoT are: + +- **Root of trust key** + + The private part of this key is used to sign the BL2 content certificate and + the trusted key certificate. The public part is the ROTPK. + +- **Trusted world key** + + The private part is used to sign the key certificates corresponding to the + secure world images (SCP_BL2, BL31 and BL32). The public part is stored in + one of the extension fields in the trusted world certificate. + +- **Non-trusted world key** + + The private part is used to sign the key certificate corresponding to the + non secure world image (BL33). The public part is stored in one of the + extension fields in the trusted world certificate. + +- **BL3-X keys** + + For each of SCP_BL2, BL31, BL32 and BL33, the private part is used to + sign the content certificate for the BL3-X image. The public part is stored + in one of the extension fields in the corresponding key certificate. + +The following images are included in the CoT: + +- BL1 +- BL2 +- SCP_BL2 (optional) +- BL31 +- BL33 +- BL32 (optional) + +The following certificates are used to authenticate the images. + +- **BL2 content certificate** + + It is self-signed with the private part of the ROT key. It contains a hash + of the BL2 image. + +- **Trusted key certificate** + + It is self-signed with the private part of the ROT key. It contains the + public part of the trusted world key and the public part of the non-trusted + world key. + +- **SCP_BL2 key certificate** + + It is self-signed with the trusted world key. It contains the public part of + the SCP_BL2 key. + +- **SCP_BL2 content certificate** + + It is self-signed with the SCP_BL2 key. It contains a hash of the SCP_BL2 + image. + +- **BL31 key certificate** + + It is self-signed with the trusted world key. It contains the public part of + the BL31 key. + +- **BL31 content certificate** + + It is self-signed with the BL31 key. It contains a hash of the BL31 image. + +- **BL32 key certificate** + + It is self-signed with the trusted world key. It contains the public part of + the BL32 key. + +- **BL32 content certificate** + + It is self-signed with the BL32 key. It contains a hash of the BL32 image. + +- **BL33 key certificate** + + It is self-signed with the non-trusted world key. It contains the public + part of the BL33 key. + +- **BL33 content certificate** + + It is self-signed with the BL33 key. It contains a hash of the BL33 image. + +The SCP_BL2 and BL32 certificates are optional, but they must be present if the +corresponding SCP_BL2 or BL32 images are present. + +Trusted Board Boot Sequence +--------------------------- + +The CoT is verified through the following sequence of steps. The system panics +if any of the steps fail. + +- BL1 loads and verifies the BL2 content certificate. The issuer public key is + read from the verified certificate. A hash of that key is calculated and + compared with the hash of the ROTPK read from the trusted root-key storage + registers. If they match, the BL2 hash is read from the certificate. + + Note: the matching operation is platform specific and is currently + unimplemented on the Arm development platforms. + +- BL1 loads the BL2 image. Its hash is calculated and compared with the hash + read from the certificate. Control is transferred to the BL2 image if all + the comparisons succeed. + +- BL2 loads and verifies the trusted key certificate. The issuer public key is + read from the verified certificate. A hash of that key is calculated and + compared with the hash of the ROTPK read from the trusted root-key storage + registers. If the comparison succeeds, BL2 reads and saves the trusted and + non-trusted world public keys from the verified certificate. + +The next two steps are executed for each of the SCP_BL2, BL31 & BL32 images. +The steps for the optional SCP_BL2 and BL32 images are skipped if these images +are not present. + +- BL2 loads and verifies the BL3x key certificate. The certificate signature + is verified using the trusted world public key. If the signature + verification succeeds, BL2 reads and saves the BL3x public key from the + certificate. + +- BL2 loads and verifies the BL3x content certificate. The signature is + verified using the BL3x public key. If the signature verification succeeds, + BL2 reads and saves the BL3x image hash from the certificate. + +The next two steps are executed only for the BL33 image. + +- BL2 loads and verifies the BL33 key certificate. If the signature + verification succeeds, BL2 reads and saves the BL33 public key from the + certificate. + +- BL2 loads and verifies the BL33 content certificate. If the signature + verification succeeds, BL2 reads and saves the BL33 image hash from the + certificate. + +The next step is executed for all the boot loader images. + +- BL2 calculates the hash of each image. It compares it with the hash obtained + from the corresponding content certificate. The image authentication succeeds + if the hashes match. + +The Trusted Board Boot implementation spans both generic and platform-specific +BL1 and BL2 code, and in tool code on the host build machine. The feature is +enabled through use of specific build flags as described in the `User Guide`_. + +On the host machine, a tool generates the certificates, which are included in +the FIP along with the boot loader images. These certificates are loaded in +Trusted SRAM using the IO storage framework. They are then verified by an +Authentication module included in TF-A. + +The mechanism used for generating the FIP and the Authentication module are +described in the following sections. + +Authentication Framework +------------------------ + +The authentication framework included in TF-A provides support to implement +the desired trusted boot sequence. Arm platforms use this framework to +implement the boot requirements specified in the `TBBR-client`_ document. + +More information about the authentication framework can be found in the +`Auth Framework`_ document. + +Certificate Generation Tool +--------------------------- + +The ``cert_create`` tool is built and runs on the host machine as part of the +TF-A build process when ``GENERATE_COT=1``. It takes the boot loader images +and keys as inputs (keys must be in PEM format) and generates the +certificates (in DER format) required to establish the CoT. New keys can be +generated by the tool in case they are not provided. The certificates are then +passed as inputs to the ``fiptool`` utility for creating the FIP. + +The certificates are also stored individually in the in the output build +directory. + +The tool resides in the ``tools/cert_create`` directory. It uses OpenSSL SSL +library version 1.0.1 or later to generate the X.509 certificates. Instructions +for building and using the tool can be found in the `User Guide`_. + +-------------- + +*Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Firmware Update: firmware-update.rst +.. _X.509 v3: https://tools.ietf.org/rfc/rfc5280.txt +.. _User Guide: ../getting_started/user-guide.rst +.. _Auth Framework: auth-framework.rst +.. _TBBR-client: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a +.. _Trusted Board Boot Requirements (TBBR): `TBBR-client`_ diff --git a/docs/exception-handling.rst b/docs/exception-handling.rst deleted file mode 100644 index b7cd69d..0000000 --- a/docs/exception-handling.rst +++ /dev/null @@ -1,636 +0,0 @@ -Exception Handling Framework in Trusted Firmware-A -================================================== - - -.. section-numbering:: - :suffix: . - -.. contents:: - :depth: 2 - -.. |EHF| replace:: Exception Handling Framework -.. |TF-A| replace:: Trusted Firmware-A - -This document describes various aspects of handling exceptions by Runtime -Firmware (BL31) that are targeted at EL3, other than SMCs. The |EHF| takes care -of the following exceptions when targeted at EL3: - -- Interrupts -- Synchronous External Aborts -- Asynchronous External Aborts - -|TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is -described in the `Firmware Design document`__. However, the |EHF| changes the -semantics of `interrupt handling`__ and `synchronous exceptions`__ other than -SMCs. - -.. __: firmware-design.rst#handling-an-smc -.. __: `Interrupt handling`_ -.. __: `Effect on SMC calls`_ - -The |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to -``1``, and is only available for AArch64 systems. - -Introduction ------------- - -Through various control bits in the ``SCR_EL3`` register, the Arm architecture -allows for asynchronous exceptions to be routed to EL3. As described in the -`Interrupt Framework Design`_ document, depending on the chosen interrupt -routing model, TF-A appropriately sets the ``FIQ`` and ``IRQ`` bits of -``SCR_EL3`` register to effect this routing. For most use cases, other than for -the purpose of facilitating context switch between Normal and Secure worlds, -FIQs and IRQs routed to EL3 are not required to be handled in EL3. - -However, the evolving system and standards landscape demands that various -exceptions are targeted at and handled in EL3. For instance: - -- Starting with ARMv8.2 architecture extension, many RAS features have been - introduced to the Arm architecture. With RAS features implemented, various - components of the system may use one of the asynchronous exceptions to signal - error conditions to PEs. These error conditions are of critical nature, and - it's imperative that corrective or remedial actions are taken at the earliest - opportunity. Therefore, a *Firmware-first Handling* approach is generally - followed in response to RAS events in the system. - -- The Arm `SDEI specification`_ defines interfaces through which Normal world - interacts with the Runtime Firmware in order to request notification of - system events. The SDEI specification requires that these events are notified - even when the Normal world executes with the exceptions masked. This too - implies that firmware-first handling is required, where the events are first - received by the EL3 firmware, and then dispatched to Normal world through - purely software mechanism. - -For |TF-A|, firmware-first handling means that asynchronous exceptions are -suitably routed to EL3, and the Runtime Firmware (BL31) is extended to include -software components that are capable of handling those exceptions that target -EL3. These components—referred to as *dispatchers* [#spd]_ in general—may -choose to: - -.. _delegation-use-cases: - -- Receive and handle exceptions entirely in EL3, meaning the exceptions - handling terminates in EL3. - -- Receive exceptions, but handle part of the exception in EL3, and delegate the - rest of the handling to a dedicated software stack running at lower Secure - ELs. In this scheme, the handling spans various secure ELs. - -- Receive exceptions, but handle part of the exception in EL3, and delegate - processing of the error to dedicated software stack running at lower secure - ELs (as above); additionally, the Normal world may also be required to - participate in the handling, or be notified of such events (for example, as - an SDEI event). In this scheme, exception handling potentially and maximally - spans all ELs in both Secure and Normal worlds. - -On any given system, all of the above handling models may be employed -independently depending on platform choice and the nature of the exception -received. - -.. [#spd] Not to be confused with `Secure Payload Dispatcher`__, which is an - EL3 component that operates in EL3 on behalf of Secure OS. - -.. __: firmware-design.rst#secure-el1-payloads-and-dispatchers - -The role of Exception Handling Framework ----------------------------------------- - -Corollary to the use cases cited above, the primary role of the |EHF| is to -facilitate firmware-first handling of exceptions on Arm systems. The |EHF| thus -enables multiple exception dispatchers in runtime firmware to co-exist, register -for, and handle exceptions targeted at EL3. This section outlines the basics, -and the rest of this document expands the various aspects of the |EHF|. - -In order to arbitrate exception handling among dispatchers, the |EHF| operation -is based on a priority scheme. This priority scheme is closely tied to how the -Arm GIC architecture defines it, although it's applied to non-interrupt -exceptions too (SErrors, for example). - -The platform is required to `partition`__ the Secure priority space into -priority levels as applicable for the Secure software stack. It then assigns the -dispatchers to one or more priority levels. The dispatchers then register -handlers for the priority levels at runtime. A dispatcher can register handlers -for more than one priority level. - -.. __: `Partitioning priority levels`_ - - -.. _ehf-figure: - -.. image:: draw.io/ehf.svg - -A priority level is *active* when a handler at that priority level is currently -executing in EL3, or has delegated the execution to a lower EL. For interrupts, -this is implicit when an interrupt is targeted and acknowledged at EL3, and the -priority of the acknowledged interrupt is used to match its registered handler. -The priority level is likewise implicitly deactivated when the interrupt -handling concludes by EOIing the interrupt. - -Non-interrupt exceptions (SErrors, for example) don't have a notion of priority. -In order for the priority arbitration to work, the |EHF| provides APIs in order -for these non-interrupt exceptions to assume a priority, and to interwork with -interrupts. Dispatchers handling such exceptions must therefore explicitly -activate and deactivate the respective priority level as and when they're -handled or delegated. - -Because priority activation and deactivation for interrupt handling is implicit -and involves GIC priority masking, it's impossible for a lower priority -interrupt to preempt a higher priority one. By extension, this means that a -lower priority dispatcher cannot preempt a higher-priority one. Priority -activation and deactivation for non-interrupt exceptions, however, has to be -explicit. The |EHF| therefore disallows for lower priority level to be activated -whilst a higher priority level is active, and would result in a panic. -Likewise, a panic would result if it's attempted to deactivate a lower priority -level when a higher priority level is active. - -In essence, priority level activation and deactivation conceptually works like a -stack—priority levels stack up in strictly increasing fashion, and need to be -unstacked in strictly the reverse order. For interrupts, the GIC ensures this is -the case; for non-interrupts, the |EHF| monitors and asserts this. See -`Transition of priority levels`_. - -Interrupt handling ------------------- - -The |EHF| is a client of *Interrupt Management Framework*, and registers the -top-level handler for interrupts that target EL3, as described in the `Interrupt -Framework Design`_ document. This has the following implications. - -- On GICv3 systems, when executing in S-EL1, pending Non-secure interrupts of - sufficient priority are signalled as FIQs, and therefore will be routed to - EL3. As a result, S-EL1 software cannot expect to handle Non-secure - interrupts at S-EL1. Essentially, this deprecates the routing mode described - as `CSS=0, TEL3=0`__. - - .. __: interrupt-framework-design.rst#el3-interrupts - - In order for S-EL1 software to handle Non-secure interrupts while having - |EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts - are received at EL3, but are then `synchronously`__ handled over to S-EL1. - - .. __: interrupt-framework-design.rst#secure-payload - -- On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is - set to ``1`` so that *Group 0* interrupts target EL3. - -- While executing in Secure world, |EHF| sets GIC Priority Mask Register to the - lowest Secure priority. This means that no Non-secure interrupts can preempt - Secure execution. See `Effect on SMC calls`_ for more details. - -As mentioned above, with |EHF|, the platform is required to partition *Group 0* -interrupts into distinct priority levels. A dispatcher that chooses to receive -interrupts can then *own* one or more priority levels, and register interrupt -handlers for them. A given priority level can be assigned to only one handler. A -dispatcher may register more than one priority level. - -Dispatchers are assigned interrupt priority levels in two steps: - -Partitioning priority levels -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Interrupts are associated to dispatchers by way of grouping and assigning -interrupts to a priority level. In other words, all interrupts that are to -target a particular dispatcher should fall in a particular priority level. For -priority assignment: - -- Of the 8 bits of priority that Arm GIC architecture permits, bit 7 must be 0 - (secure space). - -- Depending on the number of dispatchers to support, the platform must choose - to use the top *n* of the 7 remaining bits to identify and assign interrupts - to individual dispatchers. Choosing *n* bits supports up to 2\ :sup:`n` - distinct dispatchers. For example, by choosing 2 additional bits (i.e., bits - 6 and 5), the platform can partition into 4 secure priority ranges: ``0x0``, - ``0x20``, ``0x40``, and ``0x60``. See `Interrupt handling example`_. - -Note: - - The Arm GIC architecture requires that a GIC implementation that supports two - security states must implement at least 32 priority levels; i.e., at least 5 - upper bits of the 8 bits are writeable. In the scheme described above, when - choosing *n* bits for priority range assignment, the platform must ensure - that at least ``n+1`` top bits of GIC priority are writeable. - -The priority thus assigned to an interrupt is also used to determine the -priority of delegated execution in lower ELs. Delegated execution in lower EL is -associated with a priority level chosen with ``ehf_activate_priority()`` API -(described `later`__). The chosen priority level also determines the interrupts -masked while executing in a lower EL, therefore controls preemption of delegated -execution. - -.. __: `ehf-apis`_ - -The platform expresses the chosen priority levels by declaring an array of -priority level descriptors. Each entry in the array is of type -``ehf_pri_desc_t``, and declares a priority level, and shall be populated by the -``EHF_PRI_DESC()`` macro. - -Note: - - The macro ``EHF_PRI_DESC()`` installs the descriptors in the array at a - computed index, and not necessarily where the macro is placed in the array. - The size of the array might therefore be larger than what it appears to be. - The ``ARRAY_SIZE()`` macro therefore should be used to determine the size of - array. - -Finally, this array of descriptors is exposed to |EHF| via the -``EHF_REGISTER_PRIORITIES()`` macro. - -Refer to the `Interrupt handling example`_ for usage. See also: `Interrupt -Prioritisation Considerations`_. - -Programming priority -~~~~~~~~~~~~~~~~~~~~ - -The text in `Partitioning priority levels`_ only describes how the platform -expresses the required levels of priority. It however doesn't choose interrupts -nor program the required priority in GIC. - -The `Firmware Design guide`__ explains methods for configuring secure -interrupts. |EHF| requires the platform to enumerate interrupt properties (as -opposed to just numbers) of Secure interrupts. The priority of secure interrupts -must match that as determined in the `Partitioning priority levels`_ section above. - -.. __: firmware-design.rst#configuring-secure-interrupts - -See `Limitations`_, and also refer to `Interrupt handling example`_ for -illustration. - -Registering handler -------------------- - -Dispatchers register handlers for their priority levels through the following -API: - -.. code:: c - - int ehf_register_priority_handler(int pri, ehf_handler_t handler) - -The API takes two arguments: - -- The priority level for which the handler is being registered; - -- The handler to be registered. The handler must be aligned to 4 bytes. - -If a dispatcher owns more than one priority levels, it has to call the API for -each of them. - -The API will succeed, and return ``0``, only if: - -- There exists a descriptor with the priority level requested. - -- There are no handlers already registered by a previous call to the API. - -Otherwise, the API returns ``-1``. - -The interrupt handler should have the following signature: - -.. code:: c - - typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle, - void *cookie); - -The parameters are as obtained from the top-level `EL3 interrupt handler`__. - -.. __: interrupt-framework-design.rst#el3-runtime-firmware - -The `SDEI dispatcher`__, for example, expects the platform to allocate two -different priority levels—``PLAT_SDEI_CRITICAL_PRI``, and -``PLAT_SDEI_NORMAL_PRI``—and registers the same handler to handle both levels. - -.. __: sdei.rst - -Interrupt handling example --------------------------- - -The following annotated snippet demonstrates how a platform might choose to -assign interrupts to fictitious dispatchers: - -.. code:: c - - #include - #include - #include - - ... - - /* - * This platform uses 2 bits for interrupt association. In total, 3 upper - * bits are in use. - * - * 7 6 5 3 0 - * .-.-.-.----------. - * |0|b|b| ..0.. | - * '-'-'-'----------' - */ - #define PLAT_PRI_BITS 2 - - /* Priorities for individual dispatchers */ - #define DISP0_PRIO 0x00 /* Not used */ - #define DISP1_PRIO 0x20 - #define DISP2_PRIO 0x40 - #define DISP3_PRIO 0x60 - - /* Install priority level descriptors for each dispatcher */ - ehf_pri_desc_t plat_exceptions[] = { - EHF_PRI_DESC(PLAT_PRI_BITS, DISP1_PRIO), - EHF_PRI_DESC(PLAT_PRI_BITS, DISP2_PRIO), - EHF_PRI_DESC(PLAT_PRI_BITS, DISP3_PRIO), - }; - - /* Expose priority descriptors to Exception Handling Framework */ - EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions), - PLAT_PRI_BITS); - - ... - - /* List interrupt properties for GIC driver. All interrupts target EL3 */ - const interrupt_prop_t plat_interrupts[] = { - /* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */ - INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), - INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), - - /* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */ - INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), - INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), - - /* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */ - INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), - INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), - }; - - ... - - /* Dispatcher 1 registers its handler */ - ehf_register_priority_handler(DISP1_PRIO, disp1_handler); - - /* Dispatcher 2 registers its handler */ - ehf_register_priority_handler(DISP2_PRIO, disp2_handler); - - /* Dispatcher 3 registers its handler */ - ehf_register_priority_handler(DISP3_PRIO, disp3_handler); - - ... - -See also the `Build-time flow`_ and the `Run-time flow`_. - -Activating and Deactivating priorities --------------------------------------- - -A priority level is said to be *active* when an exception of that priority is -being handled: for interrupts, this is implied when the interrupt is -acknowledged; for non-interrupt exceptions, such as SErrors or `SDEI explicit -dispatches`__, this has to be done via calling ``ehf_activate_priority()``. See -`Run-time flow`_. - -.. __: sdei.rst#explicit-dispatch-of-events - -Conversely, when the dispatcher has reached a logical resolution for the cause -of the exception, the corresponding priority level ought to be deactivated. As -above, for interrupts, this is implied when the interrupt is EOId in the GIC; -for other exceptions, this has to be done via calling -``ehf_deactivate_priority()``. - -Thanks to `different provisions`__ for exception delegation, there are -potentially more than one work flow for deactivation: - -.. __: `delegation-use-cases`_ - -.. _deactivation workflows: - -- The dispatcher has addressed the cause of the exception, and decided to take - no further action. In this case, the dispatcher's handler deactivates the - priority level before returning to the |EHF|. Runtime firmware, upon exit - through an ``ERET``, resumes execution before the interrupt occurred. - -- The dispatcher has to delegate the execution to lower ELs, and the cause of - the exception can be considered resolved only when the lower EL returns - signals complete (via an ``SMC``) at a future point in time. The following - sequence ensues: - - #. The dispatcher calls ``setjmp()`` to setup a jump point, and arranges to - enter a lower EL upon the next ``ERET``. - - #. Through the ensuing ``ERET`` from runtime firmware, execution is delegated - to a lower EL. - - #. The lower EL completes its execution, and signals completion via an - ``SMC``. - - #. The ``SMC`` is handled by the same dispatcher that handled the exception - previously. Noticing the conclusion of exception handling, the dispatcher - does ``longjmp()`` to resume beyond the previous jump point. - -As mentioned above, the |EHF| provides the following APIs for activating and -deactivating interrupt: - -.. _ehf-apis: - -- ``ehf_activate_priority()`` activates the supplied priority level, but only - if the current active priority is higher than the given one; otherwise - panics. Also, to prevent interruption by physical interrupts of lower - priority, the |EHF| programs the *Priority Mask Register* corresponding to - the PE to the priority being activated. Dispatchers typically only need to - call this when handling exceptions other than interrupts, and it needs to - delegate execution to a lower EL at a desired priority level. - -- ``ehf_deactivate_priority()`` deactivates a given priority, but only if the - current active priority is equal to the given one; otherwise panics. |EHF| - also restores the *Priority Mask Register* corresponding to the PE to the - priority before the call to ``ehf_activate_priority()``. Dispatchers - typically only need to call this after handling exceptions other than - interrupts. - -The calling of APIs are subject to allowed `transitions`__. See also the -`Run-time flow`_. - -.. __: `Transition of priority levels`_ - -Transition of priority levels ------------------------------ - -The |EHF| APIs ``ehf_activate_priority()`` and ``ehf_deactivate_priority()`` can -be called to transition the current priority level on a PE. A given sequence of -calls to these APIs are subject to the following conditions: - -- For activation, the |EHF| only allows for the priority to increase (i.e. - numeric value decreases); - -- For deactivation, the |EHF| only allows for the priority to decrease (i.e. - numeric value increases). Additionally, the priority being deactivated is - required to be the current priority. - -If these are violated, a panic will result. - -Effect on SMC calls -------------------- - -In general, Secure execution is regarded as more important than Non-secure -execution. As discussed elsewhere in this document, EL3 execution, and any -delegated execution thereafter, has the effect of raising GIC's priority -mask—either implicitly by acknowledging Secure interrupts, or when dispatchers -call ``ehf_activate_priority()``. As a result, Non-secure interrupts cannot -preempt any Secure execution. - -SMCs from Non-secure world are synchronous exceptions, and are mechanisms for -Non-secure world to request Secure services. They're broadly classified as -*Fast* or *Yielding* (see `SMCCC`__). - -.. __: `http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html` - -- *Fast* SMCs are atomic from the caller's point of view. I.e., they return - to the caller only when the Secure world has finished serving the request. - Any Non-secure interrupts that become pending meanwhile cannot preempt Secure - execution. - -- *Yielding* SMCs carry the semantics of a preemptible, lower-priority request. - A pending Non-secure interrupt can preempt Secure execution handling a - Yielding SMC. I.e., the caller might observe a Yielding SMC returning when - either: - - #. Secure world completes the request, and the caller would find ``SMC_OK`` - as the return code. - - #. A Non-secure interrupt preempts Secure execution. Non-secure interrupt is - handled, and Non-secure execution resumes after ``SMC`` instruction. - - The dispatcher handling a Yielding SMC must provide a different return code - to the Non-secure caller to distinguish the latter case. This return code, - however, is not standardised (unlike ``SMC_UNKNOWN`` or ``SMC_OK``, for - example), so will vary across dispatchers that handle the request. - -For the latter case above, dispatchers before |EHF| expect Non-secure interrupts -to be taken to S-EL1 [#irq]_, so would get a chance to populate the designated -preempted error code before yielding to Non-secure world. - -The introduction of |EHF| changes the behaviour as described in `Interrupt -handling`_. - -When |EHF| is enabled, in order to allow Non-secure interrupts to preempt -Yielding SMC handling, the dispatcher must call ``ehf_allow_ns_preemption()`` -API. The API takes one argument, the error code to be returned to the Non-secure -world upon getting preempted. - -.. [#irq] In case of GICv2, Non-secure interrupts while in S-EL1 were signalled - as IRQs, and in case of GICv3, FIQs. - -Build-time flow ---------------- - -Please refer to the `figure`__ above. - -.. __: `ehf-figure`_ - -The build-time flow involves the following steps: - -#. Platform assigns priorities by installing priority level descriptors for - individual dispatchers, as described in `Partitioning priority levels`_. - -#. Platform provides interrupt properties to GIC driver, as described in - `Programming priority`_. - -#. Dispatcher calling ``ehf_register_priority_handler()`` to register an - interrupt handler. - -Also refer to the `Interrupt handling example`_. - -Run-time flow -------------- - -.. _interrupt-flow: - -The following is an example flow for interrupts: - -#. The GIC driver, during initialization, iterates through the platform-supplied - interrupt properties (see `Programming priority`_), and configures the - interrupts. This programs the appropriate priority and group (Group 0) on - interrupts belonging to different dispatchers. - -#. The |EHF|, during its initialisation, registers a top-level interrupt handler - with the `Interrupt Management Framework`__ for EL3 interrupts. This also - results in setting the routing bits in ``SCR_EL3``. - - .. __: interrupt-framework-design.rst#el3-runtime-firmware - -#. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0 - interrupt, and is taken to EL3. - -#. The top-level EL3 interrupt handler executes. The handler acknowledges the - interrupt, reads its *Running Priority*, and from that, determines the - dispatcher handler. - -#. The |EHF| programs the *Priority Mask Register* of the PE to the priority of - the interrupt received. - -#. The |EHF| marks that priority level *active*, and jumps to the dispatcher - handler. - -#. Once the dispatcher handler finishes its job, it has to immediately - *deactivate* the priority level before returning to the |EHF|. See - `deactivation workflows`_. - -.. _non-interrupt-flow: - -The following is an example flow for exceptions that targets EL3 other than -interrupt: - -#. The platform provides handlers for the specific kind of exception. - -#. The exception arrives, and the corresponding handler is executed. - -#. The handler calls ``ehf_activate_priority()`` to activate the required - priority level. This also has the effect of raising GIC priority mask, thus - preventing interrupts of lower priority from preempting the handling. The - handler may choose to do the handling entirely in EL3 or delegate to a lower - EL. - -#. Once exception handling concludes, the handler calls - ``ehf_deactivate_priority()`` to deactivate the priority level activated - earlier. This also has the effect of lowering GIC priority mask to what it - was before. - -Interrupt Prioritisation Considerations ---------------------------------------- - -The GIC priority scheme, by design, prioritises Secure interrupts over Normal -world ones. The platform further assigns relative priorities amongst Secure -dispatchers through |EHF|. - -As mentioned in `Partitioning priority levels`_, interrupts targeting distinct -dispatchers fall in distinct priority levels. Because they're routed via the -GIC, interrupt delivery to the PE is subject to GIC prioritisation rules. In -particular, when an interrupt is being handled by the PE (i.e., the interrupt is -in *Active* state), only interrupts of higher priority are signalled to the PE, -even if interrupts of same or lower priority are pending. This has the side -effect of one dispatcher being starved of interrupts by virtue of another -dispatcher handling its (higher priority) interrupts. - -The |EHF| doesn't enforce a particular prioritisation policy, but the platform -should carefully consider the assignment of priorities to dispatchers integrated -into runtime firmware. The platform should sensibly delineate priority to -various dispatchers according to their nature. In particular, dispatchers of -critical nature (RAS, for example) should be assigned higher priority than -others (SDEI, for example); and within SDEI, Critical priority SDEI should be -assigned higher priority than Normal ones. - -Limitations ------------ - -The |EHF| has the following limitations: - -- Although there could be up to 128 Secure dispatchers supported by the GIC - priority scheme, the size of descriptor array exposed with - ``EHF_REGISTER_PRIORITIES()`` macro is currently limited to 32. This serves most - expected use cases. This may be expanded in the future, should use cases - demand so. - -- The platform must ensure that the priority assigned to the dispatcher in the - exception descriptor and the programmed priority of interrupts handled by the - dispatcher match. The |EHF| cannot verify that this has been followed. - ----- - -*Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.* - -.. _Interrupt Framework Design: interrupt-framework-design.rst -.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst deleted file mode 100644 index 8384c9c..0000000 --- a/docs/firmware-design.rst +++ /dev/null @@ -1,2688 +0,0 @@ -Trusted Firmware-A design -========================= - - -.. section-numbering:: - :suffix: . - -.. contents:: - -Trusted Firmware-A (TF-A) implements a subset of the Trusted Board Boot -Requirements (TBBR) Platform Design Document (PDD) [1]_ for Arm reference -platforms. The TBB sequence starts when the platform is powered on and runs up -to the stage where it hands-off control to firmware running in the normal -world in DRAM. This is the cold boot path. - -TF-A also implements the Power State Coordination Interface PDD [2]_ as a -runtime service. PSCI is the interface from normal world software to firmware -implementing power management use-cases (for example, secondary CPU boot, -hotplug and idle). Normal world software can access TF-A runtime services via -the Arm SMC (Secure Monitor Call) instruction. The SMC instruction must be -used as mandated by the SMC Calling Convention [3]_. - -TF-A implements a framework for configuring and managing interrupts generated -in either security state. The details of the interrupt management framework -and its design can be found in TF-A Interrupt Management Design guide [4]_. - -TF-A also implements a library for setting up and managing the translation -tables. The details of this library can be found in `Xlat_tables design`_. - -TF-A can be built to support either AArch64 or AArch32 execution state. - -Cold boot ---------- - -The cold boot path starts when the platform is physically turned on. If -``COLD_BOOT_SINGLE_CPU=0``, one of the CPUs released from reset is chosen as the -primary CPU, and the remaining CPUs are considered secondary CPUs. The primary -CPU is chosen through platform-specific means. The cold boot path is mainly -executed by the primary CPU, other than essential CPU initialization executed by -all CPUs. The secondary CPUs are kept in a safe platform-specific state until -the primary CPU has performed enough initialization to boot them. - -Refer to the `Reset Design`_ for more information on the effect of the -``COLD_BOOT_SINGLE_CPU`` platform build option. - -The cold boot path in this implementation of TF-A depends on the execution -state. For AArch64, it is divided into five steps (in order of execution): - -- Boot Loader stage 1 (BL1) *AP Trusted ROM* -- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* -- Boot Loader stage 3-1 (BL31) *EL3 Runtime Software* -- Boot Loader stage 3-2 (BL32) *Secure-EL1 Payload* (optional) -- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* - -For AArch32, it is divided into four steps (in order of execution): - -- Boot Loader stage 1 (BL1) *AP Trusted ROM* -- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* -- Boot Loader stage 3-2 (BL32) *EL3 Runtime Software* -- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* - -Arm development platforms (Fixed Virtual Platforms (FVPs) and Juno) implement a -combination of the following types of memory regions. Each bootloader stage uses -one or more of these memory regions. - -- Regions accessible from both non-secure and secure states. For example, - non-trusted SRAM, ROM and DRAM. -- Regions accessible from only the secure state. For example, trusted SRAM and - ROM. The FVPs also implement the trusted DRAM which is statically - configured. Additionally, the Base FVPs and Juno development platform - configure the TrustZone Controller (TZC) to create a region in the DRAM - which is accessible only from the secure state. - -The sections below provide the following details: - -- dynamic configuration of Boot Loader stages -- initialization and execution of the first three stages during cold boot -- specification of the EL3 Runtime Software (BL31 for AArch64 and BL32 for - AArch32) entrypoint requirements for use by alternative Trusted Boot - Firmware in place of the provided BL1 and BL2 - -Dynamic Configuration during cold boot -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Each of the Boot Loader stages may be dynamically configured if required by the -platform. The Boot Loader stage may optionally specify a firmware -configuration file and/or hardware configuration file as listed below: - -- HW_CONFIG - The hardware configuration file. Can be shared by all Boot Loader - stages and also by the Normal World Rich OS. -- TB_FW_CONFIG - Trusted Boot Firmware configuration file. Shared between BL1 - and BL2. -- SOC_FW_CONFIG - SoC Firmware configuration file. Used by BL31. -- TOS_FW_CONFIG - Trusted OS Firmware configuration file. Used by Trusted OS - (BL32). -- NT_FW_CONFIG - Non Trusted Firmware configuration file. Used by Non-trusted - firmware (BL33). - -The Arm development platforms use the Flattened Device Tree format for the -dynamic configuration files. - -Each Boot Loader stage can pass up to 4 arguments via registers to the next -stage. BL2 passes the list of the next images to execute to the *EL3 Runtime -Software* (BL31 for AArch64 and BL32 for AArch32) via `arg0`. All the other -arguments are platform defined. The Arm development platforms use the following -convention: - -- BL1 passes the address of a meminfo_t structure to BL2 via ``arg1``. This - structure contains the memory layout available to BL2. -- When dynamic configuration files are present, the firmware configuration for - the next Boot Loader stage is populated in the first available argument and - the generic hardware configuration is passed the next available argument. - For example, - - - If TB_FW_CONFIG is loaded by BL1, then its address is passed in ``arg0`` - to BL2. - - If HW_CONFIG is loaded by BL1, then its address is passed in ``arg2`` to - BL2. Note, ``arg1`` is already used for meminfo_t. - - If SOC_FW_CONFIG is loaded by BL2, then its address is passed in ``arg1`` - to BL31. Note, ``arg0`` is used to pass the list of executable images. - - Similarly, if HW_CONFIG is loaded by BL1 or BL2, then its address is - passed in ``arg2`` to BL31. - - For other BL3x images, if the firmware configuration file is loaded by - BL2, then its address is passed in ``arg0`` and if HW_CONFIG is loaded - then its address is passed in ``arg1``. - -BL1 -~~~ - -This stage begins execution from the platform's reset vector at EL3. The reset -address is platform dependent but it is usually located in a Trusted ROM area. -The BL1 data section is copied to trusted SRAM at runtime. - -On the Arm development platforms, BL1 code starts execution from the reset -vector defined by the constant ``BL1_RO_BASE``. The BL1 data section is copied -to the top of trusted SRAM as defined by the constant ``BL1_RW_BASE``. - -The functionality implemented by this stage is as follows. - -Determination of boot path -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Whenever a CPU is released from reset, BL1 needs to distinguish between a warm -boot and a cold boot. This is done using platform-specific mechanisms (see the -``plat_get_my_entrypoint()`` function in the `Porting Guide`_). In the case of a -warm boot, a CPU is expected to continue execution from a separate -entrypoint. In the case of a cold boot, the secondary CPUs are placed in a safe -platform-specific state (see the ``plat_secondary_cold_boot_setup()`` function in -the `Porting Guide`_) while the primary CPU executes the remaining cold boot path -as described in the following sections. - -This step only applies when ``PROGRAMMABLE_RESET_ADDRESS=0``. Refer to the -`Reset Design`_ for more information on the effect of the -``PROGRAMMABLE_RESET_ADDRESS`` platform build option. - -Architectural initialization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -BL1 performs minimal architectural initialization as follows. - -- Exception vectors - - BL1 sets up simple exception vectors for both synchronous and asynchronous - exceptions. The default behavior upon receiving an exception is to populate - a status code in the general purpose register ``X0/R0`` and call the - ``plat_report_exception()`` function (see the `Porting Guide`_). The status - code is one of: - - For AArch64: - - :: - - 0x0 : Synchronous exception from Current EL with SP_EL0 - 0x1 : IRQ exception from Current EL with SP_EL0 - 0x2 : FIQ exception from Current EL with SP_EL0 - 0x3 : System Error exception from Current EL with SP_EL0 - 0x4 : Synchronous exception from Current EL with SP_ELx - 0x5 : IRQ exception from Current EL with SP_ELx - 0x6 : FIQ exception from Current EL with SP_ELx - 0x7 : System Error exception from Current EL with SP_ELx - 0x8 : Synchronous exception from Lower EL using aarch64 - 0x9 : IRQ exception from Lower EL using aarch64 - 0xa : FIQ exception from Lower EL using aarch64 - 0xb : System Error exception from Lower EL using aarch64 - 0xc : Synchronous exception from Lower EL using aarch32 - 0xd : IRQ exception from Lower EL using aarch32 - 0xe : FIQ exception from Lower EL using aarch32 - 0xf : System Error exception from Lower EL using aarch32 - - For AArch32: - - :: - - 0x10 : User mode - 0x11 : FIQ mode - 0x12 : IRQ mode - 0x13 : SVC mode - 0x16 : Monitor mode - 0x17 : Abort mode - 0x1a : Hypervisor mode - 0x1b : Undefined mode - 0x1f : System mode - - The ``plat_report_exception()`` implementation on the Arm FVP port programs - the Versatile Express System LED register in the following format to - indicate the occurrence of an unexpected exception: - - :: - - SYS_LED[0] - Security state (Secure=0/Non-Secure=1) - SYS_LED[2:1] - Exception Level (EL3=0x3, EL2=0x2, EL1=0x1, EL0=0x0) - For AArch32 it is always 0x0 - SYS_LED[7:3] - Exception Class (Sync/Async & origin). This is the value - of the status code - - A write to the LED register reflects in the System LEDs (S6LED0..7) in the - CLCD window of the FVP. - - BL1 does not expect to receive any exceptions other than the SMC exception. - For the latter, BL1 installs a simple stub. The stub expects to receive a - limited set of SMC types (determined by their function IDs in the general - purpose register ``X0/R0``): - - - ``BL1_SMC_RUN_IMAGE``: This SMC is raised by BL2 to make BL1 pass control - to EL3 Runtime Software. - - All SMCs listed in section "BL1 SMC Interface" in the `Firmware Update`_ - Design Guide are supported for AArch64 only. These SMCs are currently - not supported when BL1 is built for AArch32. - - Any other SMC leads to an assertion failure. - -- CPU initialization - - BL1 calls the ``reset_handler()`` function which in turn calls the CPU - specific reset handler function (see the section: "CPU specific operations - framework"). - -- Control register setup (for AArch64) - - - ``SCTLR_EL3``. Instruction cache is enabled by setting the ``SCTLR_EL3.I`` - bit. Alignment and stack alignment checking is enabled by setting the - ``SCTLR_EL3.A`` and ``SCTLR_EL3.SA`` bits. Exception endianness is set to - little-endian by clearing the ``SCTLR_EL3.EE`` bit. - - - ``SCR_EL3``. The register width of the next lower exception level is set - to AArch64 by setting the ``SCR.RW`` bit. The ``SCR.EA`` bit is set to trap - both External Aborts and SError Interrupts in EL3. The ``SCR.SIF`` bit is - also set to disable instruction fetches from Non-secure memory when in - secure state. - - - ``CPTR_EL3``. Accesses to the ``CPACR_EL1`` register from EL1 or EL2, or the - ``CPTR_EL2`` register from EL2 are configured to not trap to EL3 by - clearing the ``CPTR_EL3.TCPAC`` bit. Access to the trace functionality is - configured not to trap to EL3 by clearing the ``CPTR_EL3.TTA`` bit. - Instructions that access the registers associated with Floating Point - and Advanced SIMD execution are configured to not trap to EL3 by - clearing the ``CPTR_EL3.TFP`` bit. - - - ``DAIF``. The SError interrupt is enabled by clearing the SError interrupt - mask bit. - - - ``MDCR_EL3``. The trap controls, ``MDCR_EL3.TDOSA``, ``MDCR_EL3.TDA`` and - ``MDCR_EL3.TPM``, are set so that accesses to the registers they control - do not trap to EL3. AArch64 Secure self-hosted debug is disabled by - setting the ``MDCR_EL3.SDD`` bit. Also ``MDCR_EL3.SPD32`` is set to - disable AArch32 Secure self-hosted privileged debug from S-EL1. - -- Control register setup (for AArch32) - - - ``SCTLR``. Instruction cache is enabled by setting the ``SCTLR.I`` bit. - Alignment checking is enabled by setting the ``SCTLR.A`` bit. - Exception endianness is set to little-endian by clearing the - ``SCTLR.EE`` bit. - - - ``SCR``. The ``SCR.SIF`` bit is set to disable instruction fetches from - Non-secure memory when in secure state. - - - ``CPACR``. Allow execution of Advanced SIMD instructions at PL0 and PL1, - by clearing the ``CPACR.ASEDIS`` bit. Access to the trace functionality - is configured not to trap to undefined mode by clearing the - ``CPACR.TRCDIS`` bit. - - - ``NSACR``. Enable non-secure access to Advanced SIMD functionality and - system register access to implemented trace registers. - - - ``FPEXC``. Enable access to the Advanced SIMD and floating-point - functionality from all Exception levels. - - - ``CPSR.A``. The Asynchronous data abort interrupt is enabled by clearing - the Asynchronous data abort interrupt mask bit. - - - ``SDCR``. The ``SDCR.SPD`` field is set to disable AArch32 Secure - self-hosted privileged debug. - -Platform initialization -^^^^^^^^^^^^^^^^^^^^^^^ - -On Arm platforms, BL1 performs the following platform initializations: - -- Enable the Trusted Watchdog. -- Initialize the console. -- Configure the Interconnect to enable hardware coherency. -- Enable the MMU and map the memory it needs to access. -- Configure any required platform storage to load the next bootloader image - (BL2). -- If the BL1 dynamic configuration file, ``TB_FW_CONFIG``, is available, then - load it to the platform defined address and make it available to BL2 via - ``arg0``. -- Configure the system timer and program the `CNTFRQ_EL0` for use by NS-BL1U - and NS-BL2U firmware update images. - -Firmware Update detection and execution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -After performing platform setup, BL1 common code calls -``bl1_plat_get_next_image_id()`` to determine if `Firmware Update`_ is required or -to proceed with the normal boot process. If the platform code returns -``BL2_IMAGE_ID`` then the normal boot sequence is executed as described in the -next section, else BL1 assumes that `Firmware Update`_ is required and execution -passes to the first image in the `Firmware Update`_ process. In either case, BL1 -retrieves a descriptor of the next image by calling ``bl1_plat_get_image_desc()``. -The image descriptor contains an ``entry_point_info_t`` structure, which BL1 -uses to initialize the execution state of the next image. - -BL2 image load and execution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In the normal boot flow, BL1 execution continues as follows: - -#. BL1 prints the following string from the primary CPU to indicate successful - execution of the BL1 stage: - - :: - - "Booting Trusted Firmware" - -#. BL1 loads a BL2 raw binary image from platform storage, at a - platform-specific base address. Prior to the load, BL1 invokes - ``bl1_plat_handle_pre_image_load()`` which allows the platform to update or - use the image information. If the BL2 image file is not present or if - there is not enough free trusted SRAM the following error message is - printed: - - :: - - "Failed to load BL2 firmware." - -#. BL1 invokes ``bl1_plat_handle_post_image_load()`` which again is intended - for platforms to take further action after image load. This function must - populate the necessary arguments for BL2, which may also include the memory - layout. Further description of the memory layout can be found later - in this document. - -#. BL1 passes control to the BL2 image at Secure EL1 (for AArch64) or at - Secure SVC mode (for AArch32), starting from its load address. - -BL2 -~~~ - -BL1 loads and passes control to BL2 at Secure-EL1 (for AArch64) or at Secure -SVC mode (for AArch32) . BL2 is linked against and loaded at a platform-specific -base address (more information can be found later in this document). -The functionality implemented by BL2 is as follows. - -Architectural initialization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For AArch64, BL2 performs the minimal architectural initialization required -for subsequent stages of TF-A and normal world software. EL1 and EL0 are given -access to Floating Point and Advanced SIMD registers by clearing the -``CPACR.FPEN`` bits. - -For AArch32, the minimal architectural initialization required for subsequent -stages of TF-A and normal world software is taken care of in BL1 as both BL1 -and BL2 execute at PL1. - -Platform initialization -^^^^^^^^^^^^^^^^^^^^^^^ - -On Arm platforms, BL2 performs the following platform initializations: - -- Initialize the console. -- Configure any required platform storage to allow loading further bootloader - images. -- Enable the MMU and map the memory it needs to access. -- Perform platform security setup to allow access to controlled components. -- Reserve some memory for passing information to the next bootloader image - EL3 Runtime Software and populate it. -- Define the extents of memory available for loading each subsequent - bootloader image. -- If BL1 has passed TB_FW_CONFIG dynamic configuration file in ``arg0``, - then parse it. - -Image loading in BL2 -^^^^^^^^^^^^^^^^^^^^ - -BL2 generic code loads the images based on the list of loadable images -provided by the platform. BL2 passes the list of executable images -provided by the platform to the next handover BL image. - -The list of loadable images provided by the platform may also contain -dynamic configuration files. The files are loaded and can be parsed as -needed in the ``bl2_plat_handle_post_image_load()`` function. These -configuration files can be passed to next Boot Loader stages as arguments -by updating the corresponding entrypoint information in this function. - -SCP_BL2 (System Control Processor Firmware) image load -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Some systems have a separate System Control Processor (SCP) for power, clock, -reset and system control. BL2 loads the optional SCP_BL2 image from platform -storage into a platform-specific region of secure memory. The subsequent -handling of SCP_BL2 is platform specific. For example, on the Juno Arm -development platform port the image is transferred into SCP's internal memory -using the Boot Over MHU (BOM) protocol after being loaded in the trusted SRAM -memory. The SCP executes SCP_BL2 and signals to the Application Processor (AP) -for BL2 execution to continue. - -EL3 Runtime Software image load -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -BL2 loads the EL3 Runtime Software image from platform storage into a platform- -specific address in trusted SRAM. If there is not enough memory to load the -image or image is missing it leads to an assertion failure. - -AArch64 BL32 (Secure-EL1 Payload) image load -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -BL2 loads the optional BL32 image from platform storage into a platform- -specific region of secure memory. The image executes in the secure world. BL2 -relies on BL31 to pass control to the BL32 image, if present. Hence, BL2 -populates a platform-specific area of memory with the entrypoint/load-address -of the BL32 image. The value of the Saved Processor Status Register (``SPSR``) -for entry into BL32 is not determined by BL2, it is initialized by the -Secure-EL1 Payload Dispatcher (see later) within BL31, which is responsible for -managing interaction with BL32. This information is passed to BL31. - -BL33 (Non-trusted Firmware) image load -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -BL2 loads the BL33 image (e.g. UEFI or other test or boot software) from -platform storage into non-secure memory as defined by the platform. - -BL2 relies on EL3 Runtime Software to pass control to BL33 once secure state -initialization is complete. Hence, BL2 populates a platform-specific area of -memory with the entrypoint and Saved Program Status Register (``SPSR``) of the -normal world software image. The entrypoint is the load address of the BL33 -image. The ``SPSR`` is determined as specified in Section 5.13 of the -`PSCI PDD`_. This information is passed to the EL3 Runtime Software. - -AArch64 BL31 (EL3 Runtime Software) execution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -BL2 execution continues as follows: - -#. BL2 passes control back to BL1 by raising an SMC, providing BL1 with the - BL31 entrypoint. The exception is handled by the SMC exception handler - installed by BL1. - -#. BL1 turns off the MMU and flushes the caches. It clears the - ``SCTLR_EL3.M/I/C`` bits, flushes the data cache to the point of coherency - and invalidates the TLBs. - -#. BL1 passes control to BL31 at the specified entrypoint at EL3. - -Running BL2 at EL3 execution level -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Some platforms have a non-TF-A Boot ROM that expects the next boot stage -to execute at EL3. On these platforms, TF-A BL1 is a waste of memory -as its only purpose is to ensure TF-A BL2 is entered at S-EL1. To avoid -this waste, a special mode enables BL2 to execute at EL3, which allows -a non-TF-A Boot ROM to load and jump directly to BL2. This mode is selected -when the build flag BL2_AT_EL3 is enabled. The main differences in this -mode are: - -#. BL2 includes the reset code and the mailbox mechanism to differentiate - cold boot and warm boot. It runs at EL3 doing the arch - initialization required for EL3. - -#. BL2 does not receive the meminfo information from BL1 anymore. This - information can be passed by the Boot ROM or be internal to the - BL2 image. - -#. Since BL2 executes at EL3, BL2 jumps directly to the next image, - instead of invoking the RUN_IMAGE SMC call. - - -We assume 3 different types of BootROM support on the platform: - -#. The Boot ROM always jumps to the same address, for both cold - and warm boot. In this case, we will need to keep a resident part - of BL2 whose memory cannot be reclaimed by any other image. The - linker script defines the symbols __TEXT_RESIDENT_START__ and - __TEXT_RESIDENT_END__ that allows the platform to configure - correctly the memory map. -#. The platform has some mechanism to indicate the jump address to the - Boot ROM. Platform code can then program the jump address with - psci_warmboot_entrypoint during cold boot. -#. The platform has some mechanism to program the reset address using - the PROGRAMMABLE_RESET_ADDRESS feature. Platform code can then - program the reset address with psci_warmboot_entrypoint during - cold boot, bypassing the boot ROM for warm boot. - -In the last 2 cases, no part of BL2 needs to remain resident at -runtime. In the first 2 cases, we expect the Boot ROM to be able to -differentiate between warm and cold boot, to avoid loading BL2 again -during warm boot. - -This functionality can be tested with FVP loading the image directly -in memory and changing the address where the system jumps at reset. -For example: - - -C cluster0.cpu0.RVBAR=0x4022000 - --data cluster0.cpu0=bl2.bin@0x4022000 - -With this configuration, FVP is like a platform of the first case, -where the Boot ROM jumps always to the same address. For simplification, -BL32 is loaded in DRAM in this case, to avoid other images reclaiming -BL2 memory. - - -AArch64 BL31 -~~~~~~~~~~~~ - -The image for this stage is loaded by BL2 and BL1 passes control to BL31 at -EL3. BL31 executes solely in trusted SRAM. BL31 is linked against and -loaded at a platform-specific base address (more information can be found later -in this document). The functionality implemented by BL31 is as follows. - -Architectural initialization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Currently, BL31 performs a similar architectural initialization to BL1 as -far as system register settings are concerned. Since BL1 code resides in ROM, -architectural initialization in BL31 allows override of any previous -initialization done by BL1. - -BL31 initializes the per-CPU data framework, which provides a cache of -frequently accessed per-CPU data optimised for fast, concurrent manipulation -on different CPUs. This buffer includes pointers to per-CPU contexts, crash -buffer, CPU reset and power down operations, PSCI data, platform data and so on. - -It then replaces the exception vectors populated by BL1 with its own. BL31 -exception vectors implement more elaborate support for handling SMCs since this -is the only mechanism to access the runtime services implemented by BL31 (PSCI -for example). BL31 checks each SMC for validity as specified by the -`SMC calling convention PDD`_ before passing control to the required SMC -handler routine. - -BL31 programs the ``CNTFRQ_EL0`` register with the clock frequency of the system -counter, which is provided by the platform. - -Platform initialization -^^^^^^^^^^^^^^^^^^^^^^^ - -BL31 performs detailed platform initialization, which enables normal world -software to function correctly. - -On Arm platforms, this consists of the following: - -- Initialize the console. -- Configure the Interconnect to enable hardware coherency. -- Enable the MMU and map the memory it needs to access. -- Initialize the generic interrupt controller. -- Initialize the power controller device. -- Detect the system topology. - -Runtime services initialization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -BL31 is responsible for initializing the runtime services. One of them is PSCI. - -As part of the PSCI initializations, BL31 detects the system topology. It also -initializes the data structures that implement the state machine used to track -the state of power domain nodes. The state can be one of ``OFF``, ``RUN`` or -``RETENTION``. All secondary CPUs are initially in the ``OFF`` state. The cluster -that the primary CPU belongs to is ``ON``; any other cluster is ``OFF``. It also -initializes the locks that protect them. BL31 accesses the state of a CPU or -cluster immediately after reset and before the data cache is enabled in the -warm boot path. It is not currently possible to use 'exclusive' based spinlocks, -therefore BL31 uses locks based on Lamport's Bakery algorithm instead. - -The runtime service framework and its initialization is described in more -detail in the "EL3 runtime services framework" section below. - -Details about the status of the PSCI implementation are provided in the -"Power State Coordination Interface" section below. - -AArch64 BL32 (Secure-EL1 Payload) image initialization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If a BL32 image is present then there must be a matching Secure-EL1 Payload -Dispatcher (SPD) service (see later for details). During initialization -that service must register a function to carry out initialization of BL32 -once the runtime services are fully initialized. BL31 invokes such a -registered function to initialize BL32 before running BL33. This initialization -is not necessary for AArch32 SPs. - -Details on BL32 initialization and the SPD's role are described in the -"Secure-EL1 Payloads and Dispatchers" section below. - -BL33 (Non-trusted Firmware) execution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -EL3 Runtime Software initializes the EL2 or EL1 processor context for normal- -world cold boot, ensuring that no secure state information finds its way into -the non-secure execution state. EL3 Runtime Software uses the entrypoint -information provided by BL2 to jump to the Non-trusted firmware image (BL33) -at the highest available Exception Level (EL2 if available, otherwise EL1). - -Using alternative Trusted Boot Firmware in place of BL1 & BL2 (AArch64 only) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Some platforms have existing implementations of Trusted Boot Firmware that -would like to use TF-A BL31 for the EL3 Runtime Software. To enable this -firmware architecture it is important to provide a fully documented and stable -interface between the Trusted Boot Firmware and BL31. - -Future changes to the BL31 interface will be done in a backwards compatible -way, and this enables these firmware components to be independently enhanced/ -updated to develop and exploit new functionality. - -Required CPU state when calling ``bl31_entrypoint()`` during cold boot -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This function must only be called by the primary CPU. - -On entry to this function the calling primary CPU must be executing in AArch64 -EL3, little-endian data access, and all interrupt sources masked: - -:: - - PSTATE.EL = 3 - PSTATE.RW = 1 - PSTATE.DAIF = 0xf - SCTLR_EL3.EE = 0 - -X0 and X1 can be used to pass information from the Trusted Boot Firmware to the -platform code in BL31: - -:: - - X0 : Reserved for common TF-A information - X1 : Platform specific information - -BL31 zero-init sections (e.g. ``.bss``) should not contain valid data on entry, -these will be zero filled prior to invoking platform setup code. - -Use of the X0 and X1 parameters -''''''''''''''''''''''''''''''' - -The parameters are platform specific and passed from ``bl31_entrypoint()`` to -``bl31_early_platform_setup()``. The value of these parameters is never directly -used by the common BL31 code. - -The convention is that ``X0`` conveys information regarding the BL31, BL32 and -BL33 images from the Trusted Boot firmware and ``X1`` can be used for other -platform specific purpose. This convention allows platforms which use TF-A's -BL1 and BL2 images to transfer additional platform specific information from -Secure Boot without conflicting with future evolution of TF-A using ``X0`` to -pass a ``bl31_params`` structure. - -BL31 common and SPD initialization code depends on image and entrypoint -information about BL33 and BL32, which is provided via BL31 platform APIs. -This information is required until the start of execution of BL33. This -information can be provided in a platform defined manner, e.g. compiled into -the platform code in BL31, or provided in a platform defined memory location -by the Trusted Boot firmware, or passed from the Trusted Boot Firmware via the -Cold boot Initialization parameters. This data may need to be cleaned out of -the CPU caches if it is provided by an earlier boot stage and then accessed by -BL31 platform code before the caches are enabled. - -TF-A's BL2 implementation passes a ``bl31_params`` structure in -``X0`` and the Arm development platforms interpret this in the BL31 platform -code. - -MMU, Data caches & Coherency -'''''''''''''''''''''''''''' - -BL31 does not depend on the enabled state of the MMU, data caches or -interconnect coherency on entry to ``bl31_entrypoint()``. If these are disabled -on entry, these should be enabled during ``bl31_plat_arch_setup()``. - -Data structures used in the BL31 cold boot interface -'''''''''''''''''''''''''''''''''''''''''''''''''''' - -These structures are designed to support compatibility and independent -evolution of the structures and the firmware images. For example, a version of -BL31 that can interpret the BL3x image information from different versions of -BL2, a platform that uses an extended entry_point_info structure to convey -additional register information to BL31, or a ELF image loader that can convey -more details about the firmware images. - -To support these scenarios the structures are versioned and sized, which enables -BL31 to detect which information is present and respond appropriately. The -``param_header`` is defined to capture this information: - -.. code:: c - - typedef struct param_header { - uint8_t type; /* type of the structure */ - uint8_t version; /* version of this structure */ - uint16_t size; /* size of this structure in bytes */ - uint32_t attr; /* attributes: unused bits SBZ */ - } param_header_t; - -The structures using this format are ``entry_point_info``, ``image_info`` and -``bl31_params``. The code that allocates and populates these structures must set -the header fields appropriately, and the ``SET_PARAM_HEAD()`` a macro is defined -to simplify this action. - -Required CPU state for BL31 Warm boot initialization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -When requesting a CPU power-on, or suspending a running CPU, TF-A provides -the platform power management code with a Warm boot initialization -entry-point, to be invoked by the CPU immediately after the reset handler. -On entry to the Warm boot initialization function the calling CPU must be in -AArch64 EL3, little-endian data access and all interrupt sources masked: - -:: - - PSTATE.EL = 3 - PSTATE.RW = 1 - PSTATE.DAIF = 0xf - SCTLR_EL3.EE = 0 - -The PSCI implementation will initialize the processor state and ensure that the -platform power management code is then invoked as required to initialize all -necessary system, cluster and CPU resources. - -AArch32 EL3 Runtime Software entrypoint interface -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To enable this firmware architecture it is important to provide a fully -documented and stable interface between the Trusted Boot Firmware and the -AArch32 EL3 Runtime Software. - -Future changes to the entrypoint interface will be done in a backwards -compatible way, and this enables these firmware components to be independently -enhanced/updated to develop and exploit new functionality. - -Required CPU state when entering during cold boot -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This function must only be called by the primary CPU. - -On entry to this function the calling primary CPU must be executing in AArch32 -EL3, little-endian data access, and all interrupt sources masked: - -:: - - PSTATE.AIF = 0x7 - SCTLR.EE = 0 - -R0 and R1 are used to pass information from the Trusted Boot Firmware to the -platform code in AArch32 EL3 Runtime Software: - -:: - - R0 : Reserved for common TF-A information - R1 : Platform specific information - -Use of the R0 and R1 parameters -''''''''''''''''''''''''''''''' - -The parameters are platform specific and the convention is that ``R0`` conveys -information regarding the BL3x images from the Trusted Boot firmware and ``R1`` -can be used for other platform specific purpose. This convention allows -platforms which use TF-A's BL1 and BL2 images to transfer additional platform -specific information from Secure Boot without conflicting with future -evolution of TF-A using ``R0`` to pass a ``bl_params`` structure. - -The AArch32 EL3 Runtime Software is responsible for entry into BL33. This -information can be obtained in a platform defined manner, e.g. compiled into -the AArch32 EL3 Runtime Software, or provided in a platform defined memory -location by the Trusted Boot firmware, or passed from the Trusted Boot Firmware -via the Cold boot Initialization parameters. This data may need to be cleaned -out of the CPU caches if it is provided by an earlier boot stage and then -accessed by AArch32 EL3 Runtime Software before the caches are enabled. - -When using AArch32 EL3 Runtime Software, the Arm development platforms pass a -``bl_params`` structure in ``R0`` from BL2 to be interpreted by AArch32 EL3 Runtime -Software platform code. - -MMU, Data caches & Coherency -'''''''''''''''''''''''''''' - -AArch32 EL3 Runtime Software must not depend on the enabled state of the MMU, -data caches or interconnect coherency in its entrypoint. They must be explicitly -enabled if required. - -Data structures used in cold boot interface -''''''''''''''''''''''''''''''''''''''''''' - -The AArch32 EL3 Runtime Software cold boot interface uses ``bl_params`` instead -of ``bl31_params``. The ``bl_params`` structure is based on the convention -described in AArch64 BL31 cold boot interface section. - -Required CPU state for warm boot initialization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -When requesting a CPU power-on, or suspending a running CPU, AArch32 EL3 -Runtime Software must ensure execution of a warm boot initialization entrypoint. -If TF-A BL1 is used and the PROGRAMMABLE_RESET_ADDRESS build flag is false, -then AArch32 EL3 Runtime Software must ensure that BL1 branches to the warm -boot entrypoint by arranging for the BL1 platform function, -plat_get_my_entrypoint(), to return a non-zero value. - -In this case, the warm boot entrypoint must be in AArch32 EL3, little-endian -data access and all interrupt sources masked: - -:: - - PSTATE.AIF = 0x7 - SCTLR.EE = 0 - -The warm boot entrypoint may be implemented by using TF-A -``psci_warmboot_entrypoint()`` function. In that case, the platform must fulfil -the pre-requisites mentioned in the `PSCI Library integration guide`_. - -EL3 runtime services framework ------------------------------- - -Software executing in the non-secure state and in the secure state at exception -levels lower than EL3 will request runtime services using the Secure Monitor -Call (SMC) instruction. These requests will follow the convention described in -the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function -identifiers to each SMC request and describes how arguments are passed and -returned. - -The EL3 runtime services framework enables the development of services by -different providers that can be easily integrated into final product firmware. -The following sections describe the framework which facilitates the -registration, initialization and use of runtime services in EL3 Runtime -Software (BL31). - -The design of the runtime services depends heavily on the concepts and -definitions described in the `SMCCC`_, in particular SMC Function IDs, Owning -Entity Numbers (OEN), Fast and Yielding calls, and the SMC32 and SMC64 calling -conventions. Please refer to that document for more detailed explanation of -these terms. - -The following runtime services are expected to be implemented first. They have -not all been instantiated in the current implementation. - -#. Standard service calls - - This service is for management of the entire system. The Power State - Coordination Interface (`PSCI`_) is the first set of standard service calls - defined by Arm (see PSCI section later). - -#. Secure-EL1 Payload Dispatcher service - - If a system runs a Trusted OS or other Secure-EL1 Payload (SP) then - it also requires a *Secure Monitor* at EL3 to switch the EL1 processor - context between the normal world (EL1/EL2) and trusted world (Secure-EL1). - The Secure Monitor will make these world switches in response to SMCs. The - `SMCCC`_ provides for such SMCs with the Trusted OS Call and Trusted - Application Call OEN ranges. - - The interface between the EL3 Runtime Software and the Secure-EL1 Payload is - not defined by the `SMCCC`_ or any other standard. As a result, each - Secure-EL1 Payload requires a specific Secure Monitor that runs as a runtime - service - within TF-A this service is referred to as the Secure-EL1 Payload - Dispatcher (SPD). - - TF-A provides a Test Secure-EL1 Payload (TSP) and its associated Dispatcher - (TSPD). Details of SPD design and TSP/TSPD operation are described in the - "Secure-EL1 Payloads and Dispatchers" section below. - -#. CPU implementation service - - This service will provide an interface to CPU implementation specific - services for a given platform e.g. access to processor errata workarounds. - This service is currently unimplemented. - -Additional services for Arm Architecture, SiP and OEM calls can be implemented. -Each implemented service handles a range of SMC function identifiers as -described in the `SMCCC`_. - -Registration -~~~~~~~~~~~~ - -A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying -the name of the service, the range of OENs covered, the type of service and -initialization and call handler functions. This macro instantiates a ``const struct rt_svc_desc`` for the service with these details (see ``runtime_svc.h``). -This structure is allocated in a special ELF section ``rt_svc_descs``, enabling -the framework to find all service descriptors included into BL31. - -The specific service for a SMC Function is selected based on the OEN and call -type of the Function ID, and the framework uses that information in the service -descriptor to identify the handler for the SMC Call. - -The service descriptors do not include information to identify the precise set -of SMC function identifiers supported by this service implementation, the -security state from which such calls are valid nor the capability to support -64-bit and/or 32-bit callers (using SMC32 or SMC64). Responding appropriately -to these aspects of a SMC call is the responsibility of the service -implementation, the framework is focused on integration of services from -different providers and minimizing the time taken by the framework before the -service handler is invoked. - -Details of the parameters, requirements and behavior of the initialization and -call handling functions are provided in the following sections. - -Initialization -~~~~~~~~~~~~~~ - -``runtime_svc_init()`` in ``runtime_svc.c`` initializes the runtime services -framework running on the primary CPU during cold boot as part of the BL31 -initialization. This happens prior to initializing a Trusted OS and running -Normal world boot firmware that might in turn use these services. -Initialization involves validating each of the declared runtime service -descriptors, calling the service initialization function and populating the -index used for runtime lookup of the service. - -The BL31 linker script collects all of the declared service descriptors into a -single array and defines symbols that allow the framework to locate and traverse -the array, and determine its size. - -The framework does basic validation of each descriptor to halt firmware -initialization if service declaration errors are detected. The framework does -not check descriptors for the following error conditions, and may behave in an -unpredictable manner under such scenarios: - -#. Overlapping OEN ranges -#. Multiple descriptors for the same range of OENs and ``call_type`` -#. Incorrect range of owning entity numbers for a given ``call_type`` - -Once validated, the service ``init()`` callback is invoked. This function carries -out any essential EL3 initialization before servicing requests. The ``init()`` -function is only invoked on the primary CPU during cold boot. If the service -uses per-CPU data this must either be initialized for all CPUs during this call, -or be done lazily when a CPU first issues an SMC call to that service. If -``init()`` returns anything other than ``0``, this is treated as an initialization -error and the service is ignored: this does not cause the firmware to halt. - -The OEN and call type fields present in the SMC Function ID cover a total of -128 distinct services, but in practice a single descriptor can cover a range of -OENs, e.g. SMCs to call a Trusted OS function. To optimize the lookup of a -service handler, the framework uses an array of 128 indices that map every -distinct OEN/call-type combination either to one of the declared services or to -indicate the service is not handled. This ``rt_svc_descs_indices[]`` array is -populated for all of the OENs covered by a service after the service ``init()`` -function has reported success. So a service that fails to initialize will never -have it's ``handle()`` function invoked. - -The following figure shows how the ``rt_svc_descs_indices[]`` index maps the SMC -Function ID call type and OEN onto a specific service handler in the -``rt_svc_descs[]`` array. - -|Image 1| - -Handling an SMC -~~~~~~~~~~~~~~~ - -When the EL3 runtime services framework receives a Secure Monitor Call, the SMC -Function ID is passed in W0 from the lower exception level (as per the -`SMCCC`_). If the calling register width is AArch32, it is invalid to invoke an -SMC Function which indicates the SMC64 calling convention: such calls are -ignored and return the Unknown SMC Function Identifier result code ``0xFFFFFFFF`` -in R0/X0. - -Bit[31] (fast/yielding call) and bits[29:24] (owning entity number) of the SMC -Function ID are combined to index into the ``rt_svc_descs_indices[]`` array. The -resulting value might indicate a service that has no handler, in this case the -framework will also report an Unknown SMC Function ID. Otherwise, the value is -used as a further index into the ``rt_svc_descs[]`` array to locate the required -service and handler. - -The service's ``handle()`` callback is provided with five of the SMC parameters -directly, the others are saved into memory for retrieval (if needed) by the -handler. The handler is also provided with an opaque ``handle`` for use with the -supporting library for parameter retrieval, setting return values and context -manipulation; and with ``flags`` indicating the security state of the caller. The -framework finally sets up the execution stack for the handler, and invokes the -services ``handle()`` function. - -On return from the handler the result registers are populated in X0-X3 before -restoring the stack and CPU state and returning from the original SMC. - -Exception Handling Framework ----------------------------- - -Please refer to the `Exception Handling Framework`_ document. - -Power State Coordination Interface ----------------------------------- - -TODO: Provide design walkthrough of PSCI implementation. - -The PSCI v1.1 specification categorizes APIs as optional and mandatory. All the -mandatory APIs in PSCI v1.1, PSCI v1.0 and in PSCI v0.2 draft specification -`Power State Coordination Interface PDD`_ are implemented. The table lists -the PSCI v1.1 APIs and their support in generic code. - -An API implementation might have a dependency on platform code e.g. CPU_SUSPEND -requires the platform to export a part of the implementation. Hence the level -of support of the mandatory APIs depends upon the support exported by the -platform port as well. The Juno and FVP (all variants) platforms export all the -required support. - -+-----------------------------+-------------+-------------------------------+ -| PSCI v1.1 API | Supported | Comments | -+=============================+=============+===============================+ -| ``PSCI_VERSION`` | Yes | The version returned is 1.1 | -+-----------------------------+-------------+-------------------------------+ -| ``CPU_SUSPEND`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``CPU_OFF`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``CPU_ON`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``AFFINITY_INFO`` | Yes | | -+-----------------------------+-------------+-------------------------------+ -| ``MIGRATE`` | Yes\*\* | | -+-----------------------------+-------------+-------------------------------+ -| ``MIGRATE_INFO_TYPE`` | Yes\*\* | | -+-----------------------------+-------------+-------------------------------+ -| ``MIGRATE_INFO_CPU`` | Yes\*\* | | -+-----------------------------+-------------+-------------------------------+ -| ``SYSTEM_OFF`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``SYSTEM_RESET`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``PSCI_FEATURES`` | Yes | | -+-----------------------------+-------------+-------------------------------+ -| ``CPU_FREEZE`` | No | | -+-----------------------------+-------------+-------------------------------+ -| ``CPU_DEFAULT_SUSPEND`` | No | | -+-----------------------------+-------------+-------------------------------+ -| ``NODE_HW_STATE`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``SYSTEM_SUSPEND`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``PSCI_SET_SUSPEND_MODE`` | No | | -+-----------------------------+-------------+-------------------------------+ -| ``PSCI_STAT_RESIDENCY`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``PSCI_STAT_COUNT`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``SYSTEM_RESET2`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``MEM_PROTECT`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ -| ``MEM_PROTECT_CHECK_RANGE`` | Yes\* | | -+-----------------------------+-------------+-------------------------------+ - -\*Note : These PSCI APIs require platform power management hooks to be -registered with the generic PSCI code to be supported. - -\*\*Note : These PSCI APIs require appropriate Secure Payload Dispatcher -hooks to be registered with the generic PSCI code to be supported. - -The PSCI implementation in TF-A is a library which can be integrated with -AArch64 or AArch32 EL3 Runtime Software for Armv8-A systems. A guide to -integrating PSCI library with AArch32 EL3 Runtime Software can be found -`here`_. - -Secure-EL1 Payloads and Dispatchers ------------------------------------ - -On a production system that includes a Trusted OS running in Secure-EL1/EL0, -the Trusted OS is coupled with a companion runtime service in the BL31 -firmware. This service is responsible for the initialisation of the Trusted -OS and all communications with it. The Trusted OS is the BL32 stage of the -boot flow in TF-A. The firmware will attempt to locate, load and execute a -BL32 image. - -TF-A uses a more general term for the BL32 software that runs at Secure-EL1 - -the *Secure-EL1 Payload* - as it is not always a Trusted OS. - -TF-A provides a Test Secure-EL1 Payload (TSP) and a Test Secure-EL1 Payload -Dispatcher (TSPD) service as an example of how a Trusted OS is supported on a -production system using the Runtime Services Framework. On such a system, the -Test BL32 image and service are replaced by the Trusted OS and its dispatcher -service. The TF-A build system expects that the dispatcher will define the -build flag ``NEED_BL32`` to enable it to include the BL32 in the build either -as a binary or to compile from source depending on whether the ``BL32`` build -option is specified or not. - -The TSP runs in Secure-EL1. It is designed to demonstrate synchronous -communication with the normal-world software running in EL1/EL2. Communication -is initiated by the normal-world software - -- either directly through a Fast SMC (as defined in the `SMCCC`_) - -- or indirectly through a `PSCI`_ SMC. The `PSCI`_ implementation in turn - informs the TSPD about the requested power management operation. This allows - the TSP to prepare for or respond to the power state change - -The TSPD service is responsible for. - -- Initializing the TSP - -- Routing requests and responses between the secure and the non-secure - states during the two types of communications just described - -Initializing a BL32 Image -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Secure-EL1 Payload Dispatcher (SPD) service is responsible for initializing -the BL32 image. It needs access to the information passed by BL2 to BL31 to do -so. This is provided by: - -.. code:: c - - entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t); - -which returns a reference to the ``entry_point_info`` structure corresponding to -the image which will be run in the specified security state. The SPD uses this -API to get entry point information for the SECURE image, BL32. - -In the absence of a BL32 image, BL31 passes control to the normal world -bootloader image (BL33). When the BL32 image is present, it is typical -that the SPD wants control to be passed to BL32 first and then later to BL33. - -To do this the SPD has to register a BL32 initialization function during -initialization of the SPD service. The BL32 initialization function has this -prototype: - -.. code:: c - - int32_t init(void); - -and is registered using the ``bl31_register_bl32_init()`` function. - -TF-A supports two approaches for the SPD to pass control to BL32 before -returning through EL3 and running the non-trusted firmware (BL33): - -#. In the BL32 setup function, use ``bl31_set_next_image_type()`` to - request that the exit from ``bl31_main()`` is to the BL32 entrypoint in - Secure-EL1. BL31 will exit to BL32 using the asynchronous method by - calling ``bl31_prepare_next_image_entry()`` and ``el3_exit()``. - - When the BL32 has completed initialization at Secure-EL1, it returns to - BL31 by issuing an SMC, using a Function ID allocated to the SPD. On - receipt of this SMC, the SPD service handler should switch the CPU context - from trusted to normal world and use the ``bl31_set_next_image_type()`` and - ``bl31_prepare_next_image_entry()`` functions to set up the initial return to - the normal world firmware BL33. On return from the handler the framework - will exit to EL2 and run BL33. - -#. The BL32 setup function registers an initialization function using - ``bl31_register_bl32_init()`` which provides a SPD-defined mechanism to - invoke a 'world-switch synchronous call' to Secure-EL1 to run the BL32 - entrypoint. - NOTE: The Test SPD service included with TF-A provides one implementation - of such a mechanism. - - On completion BL32 returns control to BL31 via a SMC, and on receipt the - SPD service handler invokes the synchronous call return mechanism to return - to the BL32 initialization function. On return from this function, - ``bl31_main()`` will set up the return to the normal world firmware BL33 and - continue the boot process in the normal world. - -Crash Reporting in BL31 ------------------------ - -BL31 implements a scheme for reporting the processor state when an unhandled -exception is encountered. The reporting mechanism attempts to preserve all the -register contents and report it via a dedicated UART (PL011 console). BL31 -reports the general purpose, EL3, Secure EL1 and some EL2 state registers. - -A dedicated per-CPU crash stack is maintained by BL31 and this is retrieved via -the per-CPU pointer cache. The implementation attempts to minimise the memory -required for this feature. The file ``crash_reporting.S`` contains the -implementation for crash reporting. - -The sample crash output is shown below. - -:: - - x0 :0x000000004F00007C - x1 :0x0000000007FFFFFF - x2 :0x0000000004014D50 - x3 :0x0000000000000000 - x4 :0x0000000088007998 - x5 :0x00000000001343AC - x6 :0x0000000000000016 - x7 :0x00000000000B8A38 - x8 :0x00000000001343AC - x9 :0x00000000000101A8 - x10 :0x0000000000000002 - x11 :0x000000000000011C - x12 :0x00000000FEFDC644 - x13 :0x00000000FED93FFC - x14 :0x0000000000247950 - x15 :0x00000000000007A2 - x16 :0x00000000000007A4 - x17 :0x0000000000247950 - x18 :0x0000000000000000 - x19 :0x00000000FFFFFFFF - x20 :0x0000000004014D50 - x21 :0x000000000400A38C - x22 :0x0000000000247950 - x23 :0x0000000000000010 - x24 :0x0000000000000024 - x25 :0x00000000FEFDC868 - x26 :0x00000000FEFDC86A - x27 :0x00000000019EDEDC - x28 :0x000000000A7CFDAA - x29 :0x0000000004010780 - x30 :0x000000000400F004 - scr_el3 :0x0000000000000D3D - sctlr_el3 :0x0000000000C8181F - cptr_el3 :0x0000000000000000 - tcr_el3 :0x0000000080803520 - daif :0x00000000000003C0 - mair_el3 :0x00000000000004FF - spsr_el3 :0x00000000800003CC - elr_el3 :0x000000000400C0CC - ttbr0_el3 :0x00000000040172A0 - esr_el3 :0x0000000096000210 - sp_el3 :0x0000000004014D50 - far_el3 :0x000000004F00007C - spsr_el1 :0x0000000000000000 - elr_el1 :0x0000000000000000 - spsr_abt :0x0000000000000000 - spsr_und :0x0000000000000000 - spsr_irq :0x0000000000000000 - spsr_fiq :0x0000000000000000 - sctlr_el1 :0x0000000030C81807 - actlr_el1 :0x0000000000000000 - cpacr_el1 :0x0000000000300000 - csselr_el1 :0x0000000000000002 - sp_el1 :0x0000000004028800 - esr_el1 :0x0000000000000000 - ttbr0_el1 :0x000000000402C200 - ttbr1_el1 :0x0000000000000000 - mair_el1 :0x00000000000004FF - amair_el1 :0x0000000000000000 - tcr_el1 :0x0000000000003520 - tpidr_el1 :0x0000000000000000 - tpidr_el0 :0x0000000000000000 - tpidrro_el0 :0x0000000000000000 - dacr32_el2 :0x0000000000000000 - ifsr32_el2 :0x0000000000000000 - par_el1 :0x0000000000000000 - far_el1 :0x0000000000000000 - afsr0_el1 :0x0000000000000000 - afsr1_el1 :0x0000000000000000 - contextidr_el1 :0x0000000000000000 - vbar_el1 :0x0000000004027000 - cntp_ctl_el0 :0x0000000000000000 - cntp_cval_el0 :0x0000000000000000 - cntv_ctl_el0 :0x0000000000000000 - cntv_cval_el0 :0x0000000000000000 - cntkctl_el1 :0x0000000000000000 - sp_el0 :0x0000000004010780 - -Guidelines for Reset Handlers ------------------------------ - -TF-A implements a framework that allows CPU and platform ports to perform -actions very early after a CPU is released from reset in both the cold and warm -boot paths. This is done by calling the ``reset_handler()`` function in both -the BL1 and BL31 images. It in turn calls the platform and CPU specific reset -handling functions. - -Details for implementing a CPU specific reset handler can be found in -Section 8. Details for implementing a platform specific reset handler can be -found in the `Porting Guide`_ (see the ``plat_reset_handler()`` function). - -When adding functionality to a reset handler, keep in mind that if a different -reset handling behavior is required between the first and the subsequent -invocations of the reset handling code, this should be detected at runtime. -In other words, the reset handler should be able to detect whether an action has -already been performed and act as appropriate. Possible courses of actions are, -e.g. skip the action the second time, or undo/redo it. - -Configuring secure interrupts ------------------------------ - -The GIC driver is responsible for performing initial configuration of secure -interrupts on the platform. To this end, the platform is expected to provide the -GIC driver (either GICv2 or GICv3, as selected by the platform) with the -interrupt configuration during the driver initialisation. - -Secure interrupt configuration are specified in an array of secure interrupt -properties. In this scheme, in both GICv2 and GICv3 driver data structures, the -``interrupt_props`` member points to an array of interrupt properties. Each -element of the array specifies the interrupt number and its attributes -(priority, group, configuration). Each element of the array shall be populated -by the macro ``INTR_PROP_DESC()``. The macro takes the following arguments: - -- 10-bit interrupt number, - -- 8-bit interrupt priority, - -- Interrupt type (one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1``, - ``INTR_TYPE_NS``), - -- Interrupt configuration (either ``GIC_INTR_CFG_LEVEL`` or - ``GIC_INTR_CFG_EDGE``). - -CPU specific operations framework ---------------------------------- - -Certain aspects of the Armv8-A architecture are implementation defined, -that is, certain behaviours are not architecturally defined, but must be -defined and documented by individual processor implementations. TF-A -implements a framework which categorises the common implementation defined -behaviours and allows a processor to export its implementation of that -behaviour. The categories are: - -#. Processor specific reset sequence. - -#. Processor specific power down sequences. - -#. Processor specific register dumping as a part of crash reporting. - -#. Errata status reporting. - -Each of the above categories fulfils a different requirement. - -#. allows any processor specific initialization before the caches and MMU - are turned on, like implementation of errata workarounds, entry into - the intra-cluster coherency domain etc. - -#. allows each processor to implement the power down sequence mandated in - its Technical Reference Manual (TRM). - -#. allows a processor to provide additional information to the developer - in the event of a crash, for example Cortex-A53 has registers which - can expose the data cache contents. - -#. allows a processor to define a function that inspects and reports the status - of all errata workarounds on that processor. - -Please note that only 2. is mandated by the TRM. - -The CPU specific operations framework scales to accommodate a large number of -different CPUs during power down and reset handling. The platform can specify -any CPU optimization it wants to enable for each CPU. It can also specify -the CPU errata workarounds to be applied for each CPU type during reset -handling by defining CPU errata compile time macros. Details on these macros -can be found in the `cpu-specific-build-macros.rst`_ file. - -The CPU specific operations framework depends on the ``cpu_ops`` structure which -needs to be exported for each type of CPU in the platform. It is defined in -``include/lib/cpus/aarch64/cpu_macros.S`` and has the following fields : ``midr``, -``reset_func()``, ``cpu_pwr_down_ops`` (array of power down functions) and -``cpu_reg_dump()``. - -The CPU specific files in ``lib/cpus`` export a ``cpu_ops`` data structure with -suitable handlers for that CPU. For example, ``lib/cpus/aarch64/cortex_a53.S`` -exports the ``cpu_ops`` for Cortex-A53 CPU. According to the platform -configuration, these CPU specific files must be included in the build by -the platform makefile. The generic CPU specific operations framework code exists -in ``lib/cpus/aarch64/cpu_helpers.S``. - -CPU specific Reset Handling -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -After a reset, the state of the CPU when it calls generic reset handler is: -MMU turned off, both instruction and data caches turned off and not part -of any coherency domain. - -The BL entrypoint code first invokes the ``plat_reset_handler()`` to allow -the platform to perform any system initialization required and any system -errata workarounds that needs to be applied. The ``get_cpu_ops_ptr()`` reads -the current CPU midr, finds the matching ``cpu_ops`` entry in the ``cpu_ops`` -array and returns it. Note that only the part number and implementer fields -in midr are used to find the matching ``cpu_ops`` entry. The ``reset_func()`` in -the returned ``cpu_ops`` is then invoked which executes the required reset -handling for that CPU and also any errata workarounds enabled by the platform. -This function must preserve the values of general purpose registers x20 to x29. - -Refer to Section "Guidelines for Reset Handlers" for general guidelines -regarding placement of code in a reset handler. - -CPU specific power down sequence -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -During the BL31 initialization sequence, the pointer to the matching ``cpu_ops`` -entry is stored in per-CPU data by ``init_cpu_ops()`` so that it can be quickly -retrieved during power down sequences. - -Various CPU drivers register handlers to perform power down at certain power -levels for that specific CPU. The PSCI service, upon receiving a power down -request, determines the highest power level at which to execute power down -sequence for a particular CPU. It uses the ``prepare_cpu_pwr_dwn()`` function to -pick the right power down handler for the requested level. The function -retrieves ``cpu_ops`` pointer member of per-CPU data, and from that, further -retrieves ``cpu_pwr_down_ops`` array, and indexes into the required level. If the -requested power level is higher than what a CPU driver supports, the handler -registered for highest level is invoked. - -At runtime the platform hooks for power down are invoked by the PSCI service to -perform platform specific operations during a power down sequence, for example -turning off CCI coherency during a cluster power down. - -CPU specific register reporting during crash -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If the crash reporting is enabled in BL31, when a crash occurs, the crash -reporting framework calls ``do_cpu_reg_dump`` which retrieves the matching -``cpu_ops`` using ``get_cpu_ops_ptr()`` function. The ``cpu_reg_dump()`` in -``cpu_ops`` is invoked, which then returns the CPU specific register values to -be reported and a pointer to the ASCII list of register names in a format -expected by the crash reporting framework. - -CPU errata status reporting -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Errata workarounds for CPUs supported in TF-A are applied during both cold and -warm boots, shortly after reset. Individual Errata workarounds are enabled as -build options. Some errata workarounds have potential run-time implications; -therefore some are enabled by default, others not. Platform ports shall -override build options to enable or disable errata as appropriate. The CPU -drivers take care of applying errata workarounds that are enabled and applicable -to a given CPU. Refer to the section titled *CPU Errata Workarounds* in `CPUBM`_ -for more information. - -Functions in CPU drivers that apply errata workaround must follow the -conventions listed below. - -The errata workaround must be authored as two separate functions: - -- One that checks for errata. This function must determine whether that errata - applies to the current CPU. Typically this involves matching the current - CPUs revision and variant against a value that's known to be affected by the - errata. If the function determines that the errata applies to this CPU, it - must return ``ERRATA_APPLIES``; otherwise, it must return - ``ERRATA_NOT_APPLIES``. The utility functions ``cpu_get_rev_var`` and - ``cpu_rev_var_ls`` functions may come in handy for this purpose. - -For an errata identified as ``E``, the check function must be named -``check_errata_E``. - -This function will be invoked at different times, both from assembly and from -C run time. Therefore it must follow AAPCS, and must not use stack. - -- Another one that applies the errata workaround. This function would call the - check function described above, and applies errata workaround if required. - -CPU drivers that apply errata workaround can optionally implement an assembly -function that report the status of errata workarounds pertaining to that CPU. -For a driver that registers the CPU, for example, ``cpux`` via ``declare_cpu_ops`` -macro, the errata reporting function, if it exists, must be named -``cpux_errata_report``. This function will always be called with MMU enabled; it -must follow AAPCS and may use stack. - -In a debug build of TF-A, on a CPU that comes out of reset, both BL1 and the -runtime firmware (BL31 in AArch64, and BL32 in AArch32) will invoke errata -status reporting function, if one exists, for that type of CPU. - -To report the status of each errata workaround, the function shall use the -assembler macro ``report_errata``, passing it: - -- The build option that enables the errata; - -- The name of the CPU: this must be the same identifier that CPU driver - registered itself with, using ``declare_cpu_ops``; - -- And the errata identifier: the identifier must match what's used in the - errata's check function described above. - -The errata status reporting function will be called once per CPU type/errata -combination during the software's active life time. - -It's expected that whenever an errata workaround is submitted to TF-A, the -errata reporting function is appropriately extended to report its status as -well. - -Reporting the status of errata workaround is for informational purpose only; it -has no functional significance. - -Memory layout of BL images --------------------------- - -Each bootloader image can be divided in 2 parts: - -- the static contents of the image. These are data actually stored in the - binary on the disk. In the ELF terminology, they are called ``PROGBITS`` - sections; - -- the run-time contents of the image. These are data that don't occupy any - space in the binary on the disk. The ELF binary just contains some - metadata indicating where these data will be stored at run-time and the - corresponding sections need to be allocated and initialized at run-time. - In the ELF terminology, they are called ``NOBITS`` sections. - -All PROGBITS sections are grouped together at the beginning of the image, -followed by all NOBITS sections. This is true for all TF-A images and it is -governed by the linker scripts. This ensures that the raw binary images are -as small as possible. If a NOBITS section was inserted in between PROGBITS -sections then the resulting binary file would contain zero bytes in place of -this NOBITS section, making the image unnecessarily bigger. Smaller images -allow faster loading from the FIP to the main memory. - -Linker scripts and symbols -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Each bootloader stage image layout is described by its own linker script. The -linker scripts export some symbols into the program symbol table. Their values -correspond to particular addresses. TF-A code can refer to these symbols to -figure out the image memory layout. - -Linker symbols follow the following naming convention in TF-A. - -- ``__
_START__`` - - Start address of a given section named ``
``. - -- ``__
_END__`` - - End address of a given section named ``
``. If there is an alignment - constraint on the section's end address then ``__
_END__`` corresponds - to the end address of the section's actual contents, rounded up to the right - boundary. Refer to the value of ``__
_UNALIGNED_END__`` to know the - actual end address of the section's contents. - -- ``__
_UNALIGNED_END__`` - - End address of a given section named ``
`` without any padding or - rounding up due to some alignment constraint. - -- ``__
_SIZE__`` - - Size (in bytes) of a given section named ``
``. If there is an - alignment constraint on the section's end address then ``__
_SIZE__`` - corresponds to the size of the section's actual contents, rounded up to the - right boundary. In other words, ``__
_SIZE__ = __
_END__ - _
_START__``. Refer to the value of ``__
_UNALIGNED_SIZE__`` - to know the actual size of the section's contents. - -- ``__
_UNALIGNED_SIZE__`` - - Size (in bytes) of a given section named ``
`` without any padding or - rounding up due to some alignment constraint. In other words, - ``__
_UNALIGNED_SIZE__ = __
_UNALIGNED_END__ - __
_START__``. - -Some of the linker symbols are mandatory as TF-A code relies on them to be -defined. They are listed in the following subsections. Some of them must be -provided for each bootloader stage and some are specific to a given bootloader -stage. - -The linker scripts define some extra, optional symbols. They are not actually -used by any code but they help in understanding the bootloader images' memory -layout as they are easy to spot in the link map files. - -Common linker symbols -^^^^^^^^^^^^^^^^^^^^^ - -All BL images share the following requirements: - -- The BSS section must be zero-initialised before executing any C code. -- The coherent memory section (if enabled) must be zero-initialised as well. -- The MMU setup code needs to know the extents of the coherent and read-only - memory regions to set the right memory attributes. When - ``SEPARATE_CODE_AND_RODATA=1``, it needs to know more specifically how the - read-only memory region is divided between code and data. - -The following linker symbols are defined for this purpose: - -- ``__BSS_START__`` -- ``__BSS_SIZE__`` -- ``__COHERENT_RAM_START__`` Must be aligned on a page-size boundary. -- ``__COHERENT_RAM_END__`` Must be aligned on a page-size boundary. -- ``__COHERENT_RAM_UNALIGNED_SIZE__`` -- ``__RO_START__`` -- ``__RO_END__`` -- ``__TEXT_START__`` -- ``__TEXT_END__`` -- ``__RODATA_START__`` -- ``__RODATA_END__`` - -BL1's linker symbols -^^^^^^^^^^^^^^^^^^^^ - -BL1 being the ROM image, it has additional requirements. BL1 resides in ROM and -it is entirely executed in place but it needs some read-write memory for its -mutable data. Its ``.data`` section (i.e. its allocated read-write data) must be -relocated from ROM to RAM before executing any C code. - -The following additional linker symbols are defined for BL1: - -- ``__BL1_ROM_END__`` End address of BL1's ROM contents, covering its code - and ``.data`` section in ROM. -- ``__DATA_ROM_START__`` Start address of the ``.data`` section in ROM. Must be - aligned on a 16-byte boundary. -- ``__DATA_RAM_START__`` Address in RAM where the ``.data`` section should be - copied over. Must be aligned on a 16-byte boundary. -- ``__DATA_SIZE__`` Size of the ``.data`` section (in ROM or RAM). -- ``__BL1_RAM_START__`` Start address of BL1 read-write data. -- ``__BL1_RAM_END__`` End address of BL1 read-write data. - -How to choose the right base addresses for each bootloader stage image -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There is currently no support for dynamic image loading in TF-A. This means -that all bootloader images need to be linked against their ultimate runtime -locations and the base addresses of each image must be chosen carefully such -that images don't overlap each other in an undesired way. As the code grows, -the base addresses might need adjustments to cope with the new memory layout. - -The memory layout is completely specific to the platform and so there is no -general recipe for choosing the right base addresses for each bootloader image. -However, there are tools to aid in understanding the memory layout. These are -the link map files: ``build///bl/bl.map``, with ```` -being the stage bootloader. They provide a detailed view of the memory usage of -each image. Among other useful information, they provide the end address of -each image. - -- ``bl1.map`` link map file provides ``__BL1_RAM_END__`` address. -- ``bl2.map`` link map file provides ``__BL2_END__`` address. -- ``bl31.map`` link map file provides ``__BL31_END__`` address. -- ``bl32.map`` link map file provides ``__BL32_END__`` address. - -For each bootloader image, the platform code must provide its start address -as well as a limit address that it must not overstep. The latter is used in the -linker scripts to check that the image doesn't grow past that address. If that -happens, the linker will issue a message similar to the following: - -:: - - aarch64-none-elf-ld: BLx has exceeded its limit. - -Additionally, if the platform memory layout implies some image overlaying like -on FVP, BL31 and TSP need to know the limit address that their PROGBITS -sections must not overstep. The platform code must provide those. - -TF-A does not provide any mechanism to verify at boot time that the memory -to load a new image is free to prevent overwriting a previously loaded image. -The platform must specify the memory available in the system for all the -relevant BL images to be loaded. - -For example, in the case of BL1 loading BL2, ``bl1_plat_sec_mem_layout()`` will -return the region defined by the platform where BL1 intends to load BL2. The -``load_image()`` function performs bounds check for the image size based on the -base and maximum image size provided by the platforms. Platforms must take -this behaviour into account when defining the base/size for each of the images. - -Memory layout on Arm development platforms -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The following list describes the memory layout on the Arm development platforms: - -- A 4KB page of shared memory is used for communication between Trusted - Firmware and the platform's power controller. This is located at the base of - Trusted SRAM. The amount of Trusted SRAM available to load the bootloader - images is reduced by the size of the shared memory. - - The shared memory is used to store the CPUs' entrypoint mailbox. On Juno, - this is also used for the MHU payload when passing messages to and from the - SCP. - -- Another 4 KB page is reserved for passing memory layout between BL1 and BL2 - and also the dynamic firmware configurations. - -- On FVP, BL1 is originally sitting in the Trusted ROM at address ``0x0``. On - Juno, BL1 resides in flash memory at address ``0x0BEC0000``. BL1 read-write - data are relocated to the top of Trusted SRAM at runtime. - -- BL2 is loaded below BL1 RW - -- EL3 Runtime Software, BL31 for AArch64 and BL32 for AArch32 (e.g. SP_MIN), - is loaded at the top of the Trusted SRAM, such that its NOBITS sections will - overwrite BL1 R/W data and BL2. This implies that BL1 global variables - remain valid only until execution reaches the EL3 Runtime Software entry - point during a cold boot. - -- On Juno, SCP_BL2 is loaded temporarily into the EL3 Runtime Software memory - region and transfered to the SCP before being overwritten by EL3 Runtime - Software. - -- BL32 (for AArch64) can be loaded in one of the following locations: - - - Trusted SRAM - - Trusted DRAM (FVP only) - - Secure region of DRAM (top 16MB of DRAM configured by the TrustZone - controller) - - When BL32 (for AArch64) is loaded into Trusted SRAM, it is loaded below - BL31. - -The location of the BL32 image will result in different memory maps. This is -illustrated for both FVP and Juno in the following diagrams, using the TSP as -an example. - -Note: Loading the BL32 image in TZC secured DRAM doesn't change the memory -layout of the other images in Trusted SRAM. - -CONFIG section in memory layouts shown below contains: - -:: - - +--------------------+ - |bl2_mem_params_descs| - |--------------------| - | fw_configs | - +--------------------+ - -``bl2_mem_params_descs`` contains parameters passed from BL2 to next the -BL image during boot. - -``fw_configs`` includes soc_fw_config, tos_fw_config and tb_fw_config. - -**FVP with TSP in Trusted SRAM with firmware configs :** -(These diagrams only cover the AArch64 case) - -:: - - DRAM - 0xffffffff +----------+ - : : - |----------| - |HW_CONFIG | - 0x83000000 |----------| (non-secure) - | | - 0x80000000 +----------+ - - Trusted SRAM - 0x04040000 +----------+ loaded by BL2 +----------------+ - | BL1 (rw) | <<<<<<<<<<<<< | | - |----------| <<<<<<<<<<<<< | BL31 NOBITS | - | BL2 | <<<<<<<<<<<<< | | - |----------| <<<<<<<<<<<<< |----------------| - | | <<<<<<<<<<<<< | BL31 PROGBITS | - | | <<<<<<<<<<<<< |----------------| - | | <<<<<<<<<<<<< | BL32 | - 0x04002000 +----------+ +----------------+ - | CONFIG | - 0x04001000 +----------+ - | Shared | - 0x04000000 +----------+ - - Trusted ROM - 0x04000000 +----------+ - | BL1 (ro) | - 0x00000000 +----------+ - -**FVP with TSP in Trusted DRAM with firmware configs (default option):** - -:: - - DRAM - 0xffffffff +--------------+ - : : - |--------------| - | HW_CONFIG | - 0x83000000 |--------------| (non-secure) - | | - 0x80000000 +--------------+ - - Trusted DRAM - 0x08000000 +--------------+ - | BL32 | - 0x06000000 +--------------+ - - Trusted SRAM - 0x04040000 +--------------+ loaded by BL2 +----------------+ - | BL1 (rw) | <<<<<<<<<<<<< | | - |--------------| <<<<<<<<<<<<< | BL31 NOBITS | - | BL2 | <<<<<<<<<<<<< | | - |--------------| <<<<<<<<<<<<< |----------------| - | | <<<<<<<<<<<<< | BL31 PROGBITS | - | | +----------------+ - +--------------+ - | CONFIG | - 0x04001000 +--------------+ - | Shared | - 0x04000000 +--------------+ - - Trusted ROM - 0x04000000 +--------------+ - | BL1 (ro) | - 0x00000000 +--------------+ - -**FVP with TSP in TZC-Secured DRAM with firmware configs :** - -:: - - DRAM - 0xffffffff +----------+ - | BL32 | (secure) - 0xff000000 +----------+ - | | - |----------| - |HW_CONFIG | - 0x83000000 |----------| (non-secure) - | | - 0x80000000 +----------+ - - Trusted SRAM - 0x04040000 +----------+ loaded by BL2 +----------------+ - | BL1 (rw) | <<<<<<<<<<<<< | | - |----------| <<<<<<<<<<<<< | BL31 NOBITS | - | BL2 | <<<<<<<<<<<<< | | - |----------| <<<<<<<<<<<<< |----------------| - | | <<<<<<<<<<<<< | BL31 PROGBITS | - | | +----------------+ - 0x04002000 +----------+ - | CONFIG | - 0x04001000 +----------+ - | Shared | - 0x04000000 +----------+ - - Trusted ROM - 0x04000000 +----------+ - | BL1 (ro) | - 0x00000000 +----------+ - -**Juno with BL32 in Trusted SRAM :** - -:: - - Flash0 - 0x0C000000 +----------+ - : : - 0x0BED0000 |----------| - | BL1 (ro) | - 0x0BEC0000 |----------| - : : - 0x08000000 +----------+ BL31 is loaded - after SCP_BL2 has - Trusted SRAM been sent to SCP - 0x04040000 +----------+ loaded by BL2 +----------------+ - | BL1 (rw) | <<<<<<<<<<<<< | | - |----------| <<<<<<<<<<<<< | BL31 NOBITS | - | BL2 | <<<<<<<<<<<<< | | - |----------| <<<<<<<<<<<<< |----------------| - | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | - |----------| <<<<<<<<<<<<< |----------------| - | | <<<<<<<<<<<<< | BL32 | - | | +----------------+ - | | - 0x04001000 +----------+ - | MHU | - 0x04000000 +----------+ - -**Juno with BL32 in TZC-secured DRAM :** - -:: - - DRAM - 0xFFE00000 +----------+ - | BL32 | (secure) - 0xFF000000 |----------| - | | - : : (non-secure) - | | - 0x80000000 +----------+ - - Flash0 - 0x0C000000 +----------+ - : : - 0x0BED0000 |----------| - | BL1 (ro) | - 0x0BEC0000 |----------| - : : - 0x08000000 +----------+ BL31 is loaded - after SCP_BL2 has - Trusted SRAM been sent to SCP - 0x04040000 +----------+ loaded by BL2 +----------------+ - | BL1 (rw) | <<<<<<<<<<<<< | | - |----------| <<<<<<<<<<<<< | BL31 NOBITS | - | BL2 | <<<<<<<<<<<<< | | - |----------| <<<<<<<<<<<<< |----------------| - | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | - |----------| +----------------+ - 0x04001000 +----------+ - | MHU | - 0x04000000 +----------+ - -Library at ROM ---------------- - -Please refer to the `ROMLIB Design`_ document. - -Firmware Image Package (FIP) ----------------------------- - -Using a Firmware Image Package (FIP) allows for packing bootloader images (and -potentially other payloads) into a single archive that can be loaded by TF-A -from non-volatile platform storage. A driver to load images from a FIP has -been added to the storage layer and allows a package to be read from supported -platform storage. A tool to create Firmware Image Packages is also provided -and described below. - -Firmware Image Package layout -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The FIP layout consists of a table of contents (ToC) followed by payload data. -The ToC itself has a header followed by one or more table entries. The ToC is -terminated by an end marker entry, and since the size of the ToC is 0 bytes, -the offset equals the total size of the FIP file. All ToC entries describe some -payload data that has been appended to the end of the binary package. With the -information provided in the ToC entry the corresponding payload data can be -retrieved. - -:: - - ------------------ - | ToC Header | - |----------------| - | ToC Entry 0 | - |----------------| - | ToC Entry 1 | - |----------------| - | ToC End Marker | - |----------------| - | | - | Data 0 | - | | - |----------------| - | | - | Data 1 | - | | - ------------------ - -The ToC header and entry formats are described in the header file -``include/tools_share/firmware_image_package.h``. This file is used by both the -tool and TF-A. - -The ToC header has the following fields: - -:: - - `name`: The name of the ToC. This is currently used to validate the header. - `serial_number`: A non-zero number provided by the creation tool - `flags`: Flags associated with this data. - Bits 0-31: Reserved - Bits 32-47: Platform defined - Bits 48-63: Reserved - -A ToC entry has the following fields: - -:: - - `uuid`: All files are referred to by a pre-defined Universally Unique - IDentifier [UUID] . The UUIDs are defined in - `include/tools_share/firmware_image_package.h`. The platform translates - the requested image name into the corresponding UUID when accessing the - package. - `offset_address`: The offset address at which the corresponding payload data - can be found. The offset is calculated from the ToC base address. - `size`: The size of the corresponding payload data in bytes. - `flags`: Flags associated with this entry. None are yet defined. - -Firmware Image Package creation tool -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The FIP creation tool can be used to pack specified images into a binary -package that can be loaded by TF-A from platform storage. The tool currently -only supports packing bootloader images. Additional image definitions can be -added to the tool as required. - -The tool can be found in ``tools/fiptool``. - -Loading from a Firmware Image Package (FIP) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Firmware Image Package (FIP) driver can load images from a binary package on -non-volatile platform storage. For the Arm development platforms, this is -currently NOR FLASH. - -Bootloader images are loaded according to the platform policy as specified by -the function ``plat_get_image_source()``. For the Arm development platforms, this -means the platform will attempt to load images from a Firmware Image Package -located at the start of NOR FLASH0. - -The Arm development platforms' policy is to only allow loading of a known set of -images. The platform policy can be modified to allow additional images. - -Use of coherent memory in TF-A ------------------------------- - -There might be loss of coherency when physical memory with mismatched -shareability, cacheability and memory attributes is accessed by multiple CPUs -(refer to section B2.9 of `Arm ARM`_ for more details). This possibility occurs -in TF-A during power up/down sequences when coherency, MMU and caches are -turned on/off incrementally. - -TF-A defines coherent memory as a region of memory with Device nGnRE attributes -in the translation tables. The translation granule size in TF-A is 4KB. This -is the smallest possible size of the coherent memory region. - -By default, all data structures which are susceptible to accesses with -mismatched attributes from various CPUs are allocated in a coherent memory -region (refer to section 2.1 of `Porting Guide`_). The coherent memory region -accesses are Outer Shareable, non-cacheable and they can be accessed -with the Device nGnRE attributes when the MMU is turned on. Hence, at the -expense of at least an extra page of memory, TF-A is able to work around -coherency issues due to mismatched memory attributes. - -The alternative to the above approach is to allocate the susceptible data -structures in Normal WriteBack WriteAllocate Inner shareable memory. This -approach requires the data structures to be designed so that it is possible to -work around the issue of mismatched memory attributes by performing software -cache maintenance on them. - -Disabling the use of coherent memory in TF-A -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It might be desirable to avoid the cost of allocating coherent memory on -platforms which are memory constrained. TF-A enables inclusion of coherent -memory in firmware images through the build flag ``USE_COHERENT_MEM``. -This flag is enabled by default. It can be disabled to choose the second -approach described above. - -The below sections analyze the data structures allocated in the coherent memory -region and the changes required to allocate them in normal memory. - -Coherent memory usage in PSCI implementation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``psci_non_cpu_pd_nodes`` data structure stores the platform's power domain -tree information for state management of power domains. By default, this data -structure is allocated in the coherent memory region in TF-A because it can be -accessed by multiple CPUs, either with caches enabled or disabled. - -.. code:: c - - typedef struct non_cpu_pwr_domain_node { - /* - * Index of the first CPU power domain node level 0 which has this node - * as its parent. - */ - unsigned int cpu_start_idx; - - /* - * Number of CPU power domains which are siblings of the domain indexed - * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx - * -> cpu_start_idx + ncpus' have this node as their parent. - */ - unsigned int ncpus; - - /* - * Index of the parent power domain node. - */ - unsigned int parent_node; - - plat_local_state_t local_state; - - unsigned char level; - - /* For indexing the psci_lock array*/ - unsigned char lock_index; - } non_cpu_pd_node_t; - -In order to move this data structure to normal memory, the use of each of its -fields must be analyzed. Fields like ``cpu_start_idx``, ``ncpus``, ``parent_node`` -``level`` and ``lock_index`` are only written once during cold boot. Hence removing -them from coherent memory involves only doing a clean and invalidate of the -cache lines after these fields are written. - -The field ``local_state`` can be concurrently accessed by multiple CPUs in -different cache states. A Lamport's Bakery lock ``psci_locks`` is used to ensure -mutual exclusion to this field and a clean and invalidate is needed after it -is written. - -Bakery lock data -~~~~~~~~~~~~~~~~ - -The bakery lock data structure ``bakery_lock_t`` is allocated in coherent memory -and is accessed by multiple CPUs with mismatched attributes. ``bakery_lock_t`` is -defined as follows: - -.. code:: c - - typedef struct bakery_lock { - /* - * The lock_data is a bit-field of 2 members: - * Bit[0] : choosing. This field is set when the CPU is - * choosing its bakery number. - * Bits[1 - 15] : number. This is the bakery number allocated. - */ - volatile uint16_t lock_data[BAKERY_LOCK_MAX_CPUS]; - } bakery_lock_t; - -It is a characteristic of Lamport's Bakery algorithm that the volatile per-CPU -fields can be read by all CPUs but only written to by the owning CPU. - -Depending upon the data cache line size, the per-CPU fields of the -``bakery_lock_t`` structure for multiple CPUs may exist on a single cache line. -These per-CPU fields can be read and written during lock contention by multiple -CPUs with mismatched memory attributes. Since these fields are a part of the -lock implementation, they do not have access to any other locking primitive to -safeguard against the resulting coherency issues. As a result, simple software -cache maintenance is not enough to allocate them in coherent memory. Consider -the following example. - -CPU0 updates its per-CPU field with data cache enabled. This write updates a -local cache line which contains a copy of the fields for other CPUs as well. Now -CPU1 updates its per-CPU field of the ``bakery_lock_t`` structure with data cache -disabled. CPU1 then issues a DCIVAC operation to invalidate any stale copies of -its field in any other cache line in the system. This operation will invalidate -the update made by CPU0 as well. - -To use bakery locks when ``USE_COHERENT_MEM`` is disabled, the lock data structure -has been redesigned. The changes utilise the characteristic of Lamport's Bakery -algorithm mentioned earlier. The bakery_lock structure only allocates the memory -for a single CPU. The macro ``DEFINE_BAKERY_LOCK`` allocates all the bakery locks -needed for a CPU into a section ``bakery_lock``. The linker allocates the memory -for other cores by using the total size allocated for the bakery_lock section -and multiplying it with (PLATFORM_CORE_COUNT - 1). This enables software to -perform software cache maintenance on the lock data structure without running -into coherency issues associated with mismatched attributes. - -The bakery lock data structure ``bakery_info_t`` is defined for use when -``USE_COHERENT_MEM`` is disabled as follows: - -.. code:: c - - typedef struct bakery_info { - /* - * The lock_data is a bit-field of 2 members: - * Bit[0] : choosing. This field is set when the CPU is - * choosing its bakery number. - * Bits[1 - 15] : number. This is the bakery number allocated. - */ - volatile uint16_t lock_data; - } bakery_info_t; - -The ``bakery_info_t`` represents a single per-CPU field of one lock and -the combination of corresponding ``bakery_info_t`` structures for all CPUs in the -system represents the complete bakery lock. The view in memory for a system -with n bakery locks are: - -:: - - bakery_lock section start - |----------------| - | `bakery_info_t`| <-- Lock_0 per-CPU field - | Lock_0 | for CPU0 - |----------------| - | `bakery_info_t`| <-- Lock_1 per-CPU field - | Lock_1 | for CPU0 - |----------------| - | .... | - |----------------| - | `bakery_info_t`| <-- Lock_N per-CPU field - | Lock_N | for CPU0 - ------------------ - | XXXXX | - | Padding to | - | next Cache WB | <--- Calculate PERCPU_BAKERY_LOCK_SIZE, allocate - | Granule | continuous memory for remaining CPUs. - ------------------ - | `bakery_info_t`| <-- Lock_0 per-CPU field - | Lock_0 | for CPU1 - |----------------| - | `bakery_info_t`| <-- Lock_1 per-CPU field - | Lock_1 | for CPU1 - |----------------| - | .... | - |----------------| - | `bakery_info_t`| <-- Lock_N per-CPU field - | Lock_N | for CPU1 - ------------------ - | XXXXX | - | Padding to | - | next Cache WB | - | Granule | - ------------------ - -Consider a system of 2 CPUs with 'N' bakery locks as shown above. For an -operation on Lock_N, the corresponding ``bakery_info_t`` in both CPU0 and CPU1 -``bakery_lock`` section need to be fetched and appropriate cache operations need -to be performed for each access. - -On Arm Platforms, bakery locks are used in psci (``psci_locks``) and power controller -driver (``arm_lock``). - -Non Functional Impact of removing coherent memory -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Removal of the coherent memory region leads to the additional software overhead -of performing cache maintenance for the affected data structures. However, since -the memory where the data structures are allocated is cacheable, the overhead is -mostly mitigated by an increase in performance. - -There is however a performance impact for bakery locks, due to: - -- Additional cache maintenance operations, and -- Multiple cache line reads for each lock operation, since the bakery locks - for each CPU are distributed across different cache lines. - -The implementation has been optimized to minimize this additional overhead. -Measurements indicate that when bakery locks are allocated in Normal memory, the -minimum latency of acquiring a lock is on an average 3-4 micro seconds whereas -in Device memory the same is 2 micro seconds. The measurements were done on the -Juno Arm development platform. - -As mentioned earlier, almost a page of memory can be saved by disabling -``USE_COHERENT_MEM``. Each platform needs to consider these trade-offs to decide -whether coherent memory should be used. If a platform disables -``USE_COHERENT_MEM`` and needs to use bakery locks in the porting layer, it can -optionally define macro ``PLAT_PERCPU_BAKERY_LOCK_SIZE`` (see the -`Porting Guide`_). Refer to the reference platform code for examples. - -Isolating code and read-only data on separate memory pages ----------------------------------------------------------- - -In the Armv8-A VMSA, translation table entries include fields that define the -properties of the target memory region, such as its access permissions. The -smallest unit of memory that can be addressed by a translation table entry is -a memory page. Therefore, if software needs to set different permissions on two -memory regions then it needs to map them using different memory pages. - -The default memory layout for each BL image is as follows: - -:: - - | ... | - +-------------------+ - | Read-write data | - +-------------------+ Page boundary - | | - +-------------------+ - | Exception vectors | - +-------------------+ 2 KB boundary - | | - +-------------------+ - | Read-only data | - +-------------------+ - | Code | - +-------------------+ BLx_BASE - -Note: The 2KB alignment for the exception vectors is an architectural -requirement. - -The read-write data start on a new memory page so that they can be mapped with -read-write permissions, whereas the code and read-only data below are configured -as read-only. - -However, the read-only data are not aligned on a page boundary. They are -contiguous to the code. Therefore, the end of the code section and the beginning -of the read-only data one might share a memory page. This forces both to be -mapped with the same memory attributes. As the code needs to be executable, this -means that the read-only data stored on the same memory page as the code are -executable as well. This could potentially be exploited as part of a security -attack. - -TF provides the build flag ``SEPARATE_CODE_AND_RODATA`` to isolate the code and -read-only data on separate memory pages. This in turn allows independent control -of the access permissions for the code and read-only data. In this case, -platform code gets a finer-grained view of the image layout and can -appropriately map the code region as executable and the read-only data as -execute-never. - -This has an impact on memory footprint, as padding bytes need to be introduced -between the code and read-only data to ensure the segregation of the two. To -limit the memory cost, this flag also changes the memory layout such that the -code and exception vectors are now contiguous, like so: - -:: - - | ... | - +-------------------+ - | Read-write data | - +-------------------+ Page boundary - | | - +-------------------+ - | Read-only data | - +-------------------+ Page boundary - | | - +-------------------+ - | Exception vectors | - +-------------------+ 2 KB boundary - | | - +-------------------+ - | Code | - +-------------------+ BLx_BASE - -With this more condensed memory layout, the separation of read-only data will -add zero or one page to the memory footprint of each BL image. Each platform -should consider the trade-off between memory footprint and security. - -This build flag is disabled by default, minimising memory footprint. On Arm -platforms, it is enabled. - -Publish and Subscribe Framework -------------------------------- - -The Publish and Subscribe Framework allows EL3 components to define and publish -events, to which other EL3 components can subscribe. - -The following macros are provided by the framework: - -- ``REGISTER_PUBSUB_EVENT(event)``: Defines an event, and takes one argument, - the event name, which must be a valid C identifier. All calls to - ``REGISTER_PUBSUB_EVENT`` macro must be placed in the file - ``pubsub_events.h``. - -- ``PUBLISH_EVENT_ARG(event, arg)``: Publishes a defined event, by iterating - subscribed handlers and calling them in turn. The handlers will be passed the - parameter ``arg``. The expected use-case is to broadcast an event. - -- ``PUBLISH_EVENT(event)``: Like ``PUBLISH_EVENT_ARG``, except that the value - ``NULL`` is passed to subscribed handlers. - -- ``SUBSCRIBE_TO_EVENT(event, handler)``: Registers the ``handler`` to - subscribe to ``event``. The handler will be executed whenever the ``event`` - is published. - -- ``for_each_subscriber(event, subscriber)``: Iterates through all handlers - subscribed for ``event``. ``subscriber`` must be a local variable of type - ``pubsub_cb_t *``, and will point to each subscribed handler in turn during - iteration. This macro can be used for those patterns that none of the - ``PUBLISH_EVENT_*()`` macros cover. - -Publishing an event that wasn't defined using ``REGISTER_PUBSUB_EVENT`` will -result in build error. Subscribing to an undefined event however won't. - -Subscribed handlers must be of type ``pubsub_cb_t``, with following function -signature: - -:: - - typedef void* (*pubsub_cb_t)(const void *arg); - -There may be arbitrary number of handlers registered to the same event. The -order in which subscribed handlers are notified when that event is published is -not defined. Subscribed handlers may be executed in any order; handlers should -not assume any relative ordering amongst them. - -Publishing an event on a PE will result in subscribed handlers executing on that -PE only; it won't cause handlers to execute on a different PE. - -Note that publishing an event on a PE blocks until all the subscribed handlers -finish executing on the PE. - -TF-A generic code publishes and subscribes to some events within. Platform -ports are discouraged from subscribing to them. These events may be withdrawn, -renamed, or have their semantics altered in the future. Platforms may however -register, publish, and subscribe to platform-specific events. - -Publish and Subscribe Example -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A publisher that wants to publish event ``foo`` would: - -- Define the event ``foo`` in the ``pubsub_events.h``. - - :: - - REGISTER_PUBSUB_EVENT(foo); - -- Depending on the nature of event, use one of ``PUBLISH_EVENT_*()`` macros to - publish the event at the appropriate path and time of execution. - -A subscriber that wants to subscribe to event ``foo`` published above would -implement: - -.. code:: c - - void *foo_handler(const void *arg) - { - void *result; - - /* Do handling ... */ - - return result; - } - - SUBSCRIBE_TO_EVENT(foo, foo_handler); - - -Reclaiming the BL31 initialization code -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A significant amount of the code used for the initialization of BL31 is never -needed again after boot time. In order to reduce the runtime memory -footprint, the memory used for this code can be reclaimed after initialization -has finished and be used for runtime data. - -The build option ``RECLAIM_INIT_CODE`` can be set to mark this boot time code -with a ``.text.init.*`` attribute which can be filtered and placed suitably -within the BL image for later reclamation by the platform. The platform can -specify the filter and the memory region for this init section in BL31 via the -plat.ld.S linker script. For example, on the FVP, this section is placed -overlapping the secondary CPU stacks so that after the cold boot is done, this -memory can be reclaimed for the stacks. The init memory section is initially -mapped with ``RO``, ``EXECUTE`` attributes. After BL31 initialization has -completed, the FVP changes the attributes of this section to ``RW``, -``EXECUTE_NEVER`` allowing it to be used for runtime data. The memory attributes -are changed within the ``bl31_plat_runtime_setup`` platform hook. The init -section section can be reclaimed for any data which is accessed after cold -boot initialization and it is upto the platform to make the decision. - -Performance Measurement Framework ---------------------------------- - -The Performance Measurement Framework (PMF) facilitates collection of -timestamps by registered services and provides interfaces to retrieve them -from within TF-A. A platform can choose to expose appropriate SMCs to -retrieve these collected timestamps. - -By default, the global physical counter is used for the timestamp -value and is read via ``CNTPCT_EL0``. The framework allows to retrieve -timestamps captured by other CPUs. - -Timestamp identifier format -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A PMF timestamp is uniquely identified across the system via the -timestamp ID or ``tid``. The ``tid`` is composed as follows: - -:: - - Bits 0-7: The local timestamp identifier. - Bits 8-9: Reserved. - Bits 10-15: The service identifier. - Bits 16-31: Reserved. - -#. The service identifier. Each PMF service is identified by a - service name and a service identifier. Both the service name and - identifier are unique within the system as a whole. - -#. The local timestamp identifier. This identifier is unique within a given - service. - -Registering a PMF service -~~~~~~~~~~~~~~~~~~~~~~~~~ - -To register a PMF service, the ``PMF_REGISTER_SERVICE()`` macro from ``pmf.h`` -is used. The arguments required are the service name, the service ID, -the total number of local timestamps to be captured and a set of flags. - -The ``flags`` field can be specified as a bitwise-OR of the following values: - -:: - - PMF_STORE_ENABLE: The timestamp is stored in memory for later retrieval. - PMF_DUMP_ENABLE: The timestamp is dumped on the serial console. - -The ``PMF_REGISTER_SERVICE()`` reserves memory to store captured -timestamps in a PMF specific linker section at build time. -Additionally, it defines necessary functions to capture and -retrieve a particular timestamp for the given service at runtime. - -The macro ``PMF_REGISTER_SERVICE()`` only enables capturing PMF timestamps -from within TF-A. In order to retrieve timestamps from outside of TF-A, the -``PMF_REGISTER_SERVICE_SMC()`` macro must be used instead. This macro -accepts the same set of arguments as the ``PMF_REGISTER_SERVICE()`` -macro but additionally supports retrieving timestamps using SMCs. - -Capturing a timestamp -~~~~~~~~~~~~~~~~~~~~~ - -PMF timestamps are stored in a per-service timestamp region. On a -system with multiple CPUs, each timestamp is captured and stored -in a per-CPU cache line aligned memory region. - -Having registered the service, the ``PMF_CAPTURE_TIMESTAMP()`` macro can be -used to capture a timestamp at the location where it is used. The macro -takes the service name, a local timestamp identifier and a flag as arguments. - -The ``flags`` field argument can be zero, or ``PMF_CACHE_MAINT`` which -instructs PMF to do cache maintenance following the capture. Cache -maintenance is required if any of the service's timestamps are captured -with data cache disabled. - -To capture a timestamp in assembly code, the caller should use -``pmf_calc_timestamp_addr`` macro (defined in ``pmf_asm_macros.S``) to -calculate the address of where the timestamp would be stored. The -caller should then read ``CNTPCT_EL0`` register to obtain the timestamp -and store it at the determined address for later retrieval. - -Retrieving a timestamp -~~~~~~~~~~~~~~~~~~~~~~ - -From within TF-A, timestamps for individual CPUs can be retrieved using either -``PMF_GET_TIMESTAMP_BY_MPIDR()`` or ``PMF_GET_TIMESTAMP_BY_INDEX()`` macros. -These macros accept the CPU's MPIDR value, or its ordinal position -respectively. - -From outside TF-A, timestamps for individual CPUs can be retrieved by calling -into ``pmf_smc_handler()``. - -.. code:: c - - Interface : pmf_smc_handler() - Argument : unsigned int smc_fid, u_register_t x1, - u_register_t x2, u_register_t x3, - u_register_t x4, void *cookie, - void *handle, u_register_t flags - Return : uintptr_t - - smc_fid: Holds the SMC identifier which is either `PMF_SMC_GET_TIMESTAMP_32` - when the caller of the SMC is running in AArch32 mode - or `PMF_SMC_GET_TIMESTAMP_64` when the caller is running in AArch64 mode. - x1: Timestamp identifier. - x2: The `mpidr` of the CPU for which the timestamp has to be retrieved. - This can be the `mpidr` of a different core to the one initiating - the SMC. In that case, service specific cache maintenance may be - required to ensure the updated copy of the timestamp is returned. - x3: A flags value that is either 0 or `PMF_CACHE_MAINT`. If - `PMF_CACHE_MAINT` is passed, then the PMF code will perform a - cache invalidate before reading the timestamp. This ensures - an updated copy is returned. - -The remaining arguments, ``x4``, ``cookie``, ``handle`` and ``flags`` are unused -in this implementation. - -PMF code structure -~~~~~~~~~~~~~~~~~~ - -#. ``pmf_main.c`` consists of core functions that implement service registration, - initialization, storing, dumping and retrieving timestamps. - -#. ``pmf_smc.c`` contains the SMC handling for registered PMF services. - -#. ``pmf.h`` contains the public interface to Performance Measurement Framework. - -#. ``pmf_asm_macros.S`` consists of macros to facilitate capturing timestamps in - assembly code. - -#. ``pmf_helpers.h`` is an internal header used by ``pmf.h``. - -Armv8-A Architecture Extensions -------------------------------- - -TF-A makes use of Armv8-A Architecture Extensions where applicable. This -section lists the usage of Architecture Extensions, and build flags -controlling them. - -In general, and unless individually mentioned, the build options -``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` select the Architecture Extension to -target when building TF-A. Subsequent Arm Architecture Extensions are backward -compatible with previous versions. - -The build system only requires that ``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` have a -valid numeric value. These build options only control whether or not -Architecture Extension-specific code is included in the build. Otherwise, TF-A -targets the base Armv8.0-A architecture; i.e. as if ``ARM_ARCH_MAJOR`` == 8 -and ``ARM_ARCH_MINOR`` == 0, which are also their respective default values. - -See also the *Summary of build options* in `User Guide`_. - -For details on the Architecture Extension and available features, please refer -to the respective Architecture Extension Supplement. - -Armv8.1-A -~~~~~~~~~ - -This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` >= 8, or when -``ARM_ARCH_MAJOR`` == 8 and ``ARM_ARCH_MINOR`` >= 1. - -- The Compare and Swap instruction is used to implement spinlocks. Otherwise, - the load-/store-exclusive instruction pair is used. - -Armv8.2-A -~~~~~~~~~ - -- The presence of ARMv8.2-TTCNP is detected at runtime. When it is present, the - Common not Private (TTBRn_ELx.CnP) bit is enabled to indicate that multiple - Processing Elements in the same Inner Shareable domain use the same - translation table entries for a given stage of translation for a particular - translation regime. - -Armv8.3-A -~~~~~~~~~ - -- Pointer authentication features of Armv8.3-A are unconditionally enabled in - the Non-secure world so that lower ELs are allowed to use them without - causing a trap to EL3. - - In order to enable the Secure world to use it, ``CTX_INCLUDE_PAUTH_REGS`` - must be set to 1. This will add all pointer authentication system registers - to the context that is saved when doing a world switch. - - The TF-A itself has support for pointer authentication at runtime - that can be enabled by setting both options ``ENABLE_PAUTH`` and - ``CTX_INCLUDE_PAUTH_REGS`` to 1. This enables pointer authentication in BL1, - BL2, BL31, and the TSP if it is used. - - These options are experimental features. - - Note that Pointer Authentication is enabled for Non-secure world irrespective - of the value of these build flags if the CPU supports it. - - If ``ARM_ARCH_MAJOR == 8`` and ``ARM_ARCH_MINOR >= 3`` the code footprint of - enabling PAuth is lower because the compiler will use the optimized - PAuth instructions rather than the backwards-compatible ones. - -Armv7-A -~~~~~~~ - -This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 7. - -There are several Armv7-A extensions available. Obviously the TrustZone -extension is mandatory to support the TF-A bootloader and runtime services. - -Platform implementing an Armv7-A system can to define from its target -Cortex-A architecture through ``ARM_CORTEX_A = yes`` in their -``platform.mk`` script. For example ``ARM_CORTEX_A15=yes`` for a -Cortex-A15 target. - -Platform can also set ``ARM_WITH_NEON=yes`` to enable neon support. -Note that using neon at runtime has constraints on non secure wolrd context. -TF-A does not yet provide VFP context management. - -Directive ``ARM_CORTEX_A`` and ``ARM_WITH_NEON`` are used to set -the toolchain target architecture directive. - -Platform may choose to not define straight the toolchain target architecture -directive by defining ``MARCH32_DIRECTIVE``. -I.e: - -:: - - MARCH32_DIRECTIVE := -mach=armv7-a - -Code Structure --------------- - -TF-A code is logically divided between the three boot loader stages mentioned -in the previous sections. The code is also divided into the following -categories (present as directories in the source code): - -- **Platform specific.** Choice of architecture specific code depends upon - the platform. -- **Common code.** This is platform and architecture agnostic code. -- **Library code.** This code comprises of functionality commonly used by all - other code. The PSCI implementation and other EL3 runtime frameworks reside - as Library components. -- **Stage specific.** Code specific to a boot stage. -- **Drivers.** -- **Services.** EL3 runtime services (eg: SPD). Specific SPD services - reside in the ``services/spd`` directory (e.g. ``services/spd/tspd``). - -Each boot loader stage uses code from one or more of the above mentioned -categories. Based upon the above, the code layout looks like this: - -:: - - Directory Used by BL1? Used by BL2? Used by BL31? - bl1 Yes No No - bl2 No Yes No - bl31 No No Yes - plat Yes Yes Yes - drivers Yes No Yes - common Yes Yes Yes - lib Yes Yes Yes - services No No Yes - -The build system provides a non configurable build option IMAGE_BLx for each -boot loader stage (where x = BL stage). e.g. for BL1 , IMAGE_BL1 will be -defined by the build system. This enables TF-A to compile certain code only -for specific boot loader stages - -All assembler files have the ``.S`` extension. The linker source files for each -boot stage have the extension ``.ld.S``. These are processed by GCC to create the -linker scripts which have the extension ``.ld``. - -FDTs provide a description of the hardware platform and are used by the Linux -kernel at boot time. These can be found in the ``fdts`` directory. - -References ----------- - -.. [#] `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D)`_ -.. [#] `Power State Coordination Interface PDD`_ -.. [#] `SMC Calling Convention PDD`_ -.. [#] `TF-A Interrupt Management Design guide`_. - --------------- - -*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* - -.. _Reset Design: ./reset-design.rst -.. _Porting Guide: ./porting-guide.rst -.. _Firmware Update: ./firmware-update.rst -.. _PSCI PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf -.. _SMC calling convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf -.. _PSCI Library integration guide: ./psci-lib-integration-guide.rst -.. _SMCCC: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf -.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf -.. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf -.. _here: ./psci-lib-integration-guide.rst -.. _cpu-specific-build-macros.rst: ./cpu-specific-build-macros.rst -.. _CPUBM: ./cpu-specific-build-macros.rst -.. _Arm ARM: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a.e/index.html -.. _User Guide: ./user-guide.rst -.. _SMC Calling Convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf -.. _TF-A Interrupt Management Design guide: ./interrupt-framework-design.rst -.. _Xlat_tables design: xlat-tables-lib-v2-design.rst -.. _Exception Handling Framework: exception-handling.rst -.. _ROMLIB Design: romlib-design.rst -.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a - -.. |Image 1| image:: diagrams/rt-svc-descs-layout.png?raw=true diff --git a/docs/firmware-update.rst b/docs/firmware-update.rst deleted file mode 100644 index 1f07f76..0000000 --- a/docs/firmware-update.rst +++ /dev/null @@ -1,412 +0,0 @@ -Trusted Firmware-A - Firmware Update design guide -================================================= - - -.. section-numbering:: - :suffix: . - -.. contents:: - --------------- - -Introduction ------------- - -This document describes the design of the Firmware Update (FWU) feature, which -enables authenticated firmware to update firmware images from external -interfaces such as USB, UART, SD-eMMC, NAND, NOR or Ethernet to SoC Non-Volatile -memories such as NAND Flash, LPPDR2-NVM or any memory determined by the -platform. This feature functions even when the current firmware in the system -is corrupt or missing; it therefore may be used as a recovery mode. It may also -be complemented by other, higher level firmware update software. - -FWU implements a specific part of the Trusted Board Boot Requirements (TBBR) -specification, Arm DEN0006C-1. It should be used in conjunction with the -`Trusted Board Boot`_ design document, which describes the image authentication -parts of the Trusted Firmware-A (TF-A) TBBR implementation. - -Scope -~~~~~ - -This document describes the secure world FWU design. It is beyond its scope to -describe how normal world FWU images should operate. To implement normal world -FWU images, please refer to the "Non-Trusted Firmware Updater" requirements in -the TBBR. - -FWU Overview ------------- - -The FWU boot flow is primarily mediated by BL1. Since BL1 executes in ROM, and -it is usually desirable to minimize the amount of ROM code, the design allows -some parts of FWU to be implemented in other secure and normal world images. -Platform code may choose which parts are implemented in which images but the -general expectation is: - -- BL1 handles: - - - Detection and initiation of the FWU boot flow. - - Copying images from non-secure to secure memory - - FWU image authentication - - Context switching between the normal and secure world during the FWU - process. - -- Other secure world FWU images handle platform initialization required by - the FWU process. -- Normal world FWU images handle loading of firmware images from external - interfaces to non-secure memory. - -The primary requirements of the FWU feature are: - -#. Export a BL1 SMC interface to interoperate with other FWU images executing - at other Exception Levels. -#. Export a platform interface to provide FWU common code with the information - it needs, and to enable platform specific FWU functionality. See the - `Porting Guide`_ for details of this interface. - -TF-A uses abbreviated image terminology for FWU images like for other TF-A -images. An overview of this terminology can be found `here`_. - -The following diagram shows the FWU boot flow for Arm development platforms. -Arm CSS platforms like Juno have a System Control Processor (SCP), and these -use all defined FWU images. Other platforms may use a subset of these. - -|Flow Diagram| - -Image Identification --------------------- - -Each FWU image and certificate is identified by a unique ID, defined by the -platform, which BL1 uses to fetch an image descriptor (``image_desc_t``) via a -call to ``bl1_plat_get_image_desc()``. The same ID is also used to prepare the -Chain of Trust (Refer to the `Authentication Framework Design`_ -for more information). - -The image descriptor includes the following information: - -- Executable or non-executable image. This indicates whether the normal world - is permitted to request execution of a secure world FWU image (after - authentication). Secure world certificates and non-AP images are examples - of non-executable images. -- Secure or non-secure image. This indicates whether the image is - authenticated/executed in secure or non-secure memory. -- Image base address and size. -- Image entry point configuration (an ``entry_point_info_t``). -- FWU image state. - -BL1 uses the FWU image descriptors to: - -- Validate the arguments of FWU SMCs -- Manage the state of the FWU process -- Initialize the execution state of the next FWU image. - -FWU State Machine ------------------ - -BL1 maintains state for each FWU image during FWU execution. FWU images at lower -Exception Levels raise SMCs to invoke FWU functionality in BL1, which causes -BL1 to update its FWU image state. The BL1 image states and valid state -transitions are shown in the diagram below. Note that secure images have a more -complex state machine than non-secure images. - -|FWU state machine| - -The following is a brief description of the supported states: - -- RESET: This is the initial state of every image at the start of FWU. - Authentication failure also leads to this state. A secure - image may yield to this state if it has completed execution. - It can also be reached by using ``FWU_SMC_IMAGE_RESET``. - -- COPYING: This is the state of a secure image while BL1 is copying it - in blocks from non-secure to secure memory. - -- COPIED: This is the state of a secure image when BL1 has completed - copying it to secure memory. - -- AUTHENTICATED: This is the state of an image when BL1 has successfully - authenticated it. - -- EXECUTED: This is the state of a secure, executable image when BL1 has - passed execution control to it. - -- INTERRUPTED: This is the state of a secure, executable image after it has - requested BL1 to resume normal world execution. - -BL1 SMC Interface ------------------ - -BL1_SMC_CALL_COUNT -~~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x0 - - Return: - uint32_t - -This SMC returns the number of SMCs supported by BL1. - -BL1_SMC_UID -~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x1 - - Return: - UUID : 32 bits in each of w0-w3 (or r0-r3 for AArch32 callers) - -This SMC returns the 128-bit `Universally Unique Identifier`_ for the -BL1 SMC service. - -BL1_SMC_VERSION -~~~~~~~~~~~~~~~ - -:: - - Argument: - uint32_t function ID : 0x3 - - Return: - uint32_t : Bits [31:16] Major Version - Bits [15:0] Minor Version - -This SMC returns the current version of the BL1 SMC service. - -BL1_SMC_RUN_IMAGE -~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x4 - entry_point_info_t *ep_info - - Return: - void - - Pre-conditions: - if (normal world caller) synchronous exception - if (ep_info not EL3) synchronous exception - -This SMC passes execution control to an EL3 image described by the provided -``entry_point_info_t`` structure. In the normal TF-A boot flow, BL2 invokes -this SMC for BL1 to pass execution control to BL31. - -FWU_SMC_IMAGE_COPY -~~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x10 - unsigned int image_id - uintptr_t image_addr - unsigned int block_size - unsigned int image_size - - Return: - int : 0 (Success) - : -ENOMEM - : -EPERM - - Pre-conditions: - if (image_id is invalid) return -EPERM - if (image_id is non-secure image) return -EPERM - if (image_id state is not (RESET or COPYING)) return -EPERM - if (secure world caller) return -EPERM - if (image_addr + block_size overflows) return -ENOMEM - if (image destination address + image_size overflows) return -ENOMEM - if (source block is in secure memory) return -ENOMEM - if (source block is not mapped into BL1) return -ENOMEM - if (image_size > free secure memory) return -ENOMEM - if (image overlaps another image) return -EPERM - -This SMC copies the secure image indicated by ``image_id`` from non-secure memory -to secure memory for later authentication. The image may be copied in a single -block or multiple blocks. In either case, the total size of the image must be -provided in ``image_size`` when invoking this SMC for the first time for each -image; it is ignored in subsequent calls (if any) for the same image. - -The ``image_addr`` and ``block_size`` specify the source memory block to copy from. -The destination address is provided by the platform code. - -If ``block_size`` is greater than the amount of remaining bytes to copy for this -image then the former is truncated to the latter. The copy operation is then -considered as complete and the FWU state machine transitions to the "COPIED" -state. If there is still more to copy, the FWU state machine stays in or -transitions to the COPYING state (depending on the previous state). - -When using multiple blocks, the source blocks do not necessarily need to be in -contiguous memory. - -Once the SMC is handled, BL1 returns from exception to the normal world caller. - -FWU_SMC_IMAGE_AUTH -~~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x11 - unsigned int image_id - uintptr_t image_addr - unsigned int image_size - - Return: - int : 0 (Success) - : -ENOMEM - : -EPERM - : -EAUTH - - Pre-conditions: - if (image_id is invalid) return -EPERM - if (secure world caller) - if (image_id state is not RESET) return -EPERM - if (image_addr/image_size is not mapped into BL1) return -ENOMEM - else // normal world caller - if (image_id is secure image) - if (image_id state is not COPIED) return -EPERM - else // image_id is non-secure image - if (image_id state is not RESET) return -EPERM - if (image_addr/image_size is in secure memory) return -ENOMEM - if (image_addr/image_size not mapped into BL1) return -ENOMEM - -This SMC authenticates the image specified by ``image_id``. If the image is in the -RESET state, BL1 authenticates the image in place using the provided -``image_addr`` and ``image_size``. If the image is a secure image in the COPIED -state, BL1 authenticates the image from the secure memory that BL1 previously -copied the image into. - -BL1 returns from exception to the caller. If authentication succeeds then BL1 -sets the image state to AUTHENTICATED. If authentication fails then BL1 returns -the -EAUTH error and sets the image state back to RESET. - -FWU_SMC_IMAGE_EXECUTE -~~~~~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x12 - unsigned int image_id - - Return: - int : 0 (Success) - : -EPERM - - Pre-conditions: - if (image_id is invalid) return -EPERM - if (secure world caller) return -EPERM - if (image_id is non-secure image) return -EPERM - if (image_id is non-executable image) return -EPERM - if (image_id state is not AUTHENTICATED) return -EPERM - -This SMC initiates execution of a previously authenticated image specified by -``image_id``, in the other security world to the caller. The current -implementation only supports normal world callers initiating execution of a -secure world image. - -BL1 saves the normal world caller's context, sets the secure image state to -EXECUTED, and returns from exception to the secure image. - -FWU_SMC_IMAGE_RESUME -~~~~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x13 - register_t image_param - - Return: - register_t : image_param (Success) - : -EPERM - - Pre-conditions: - if (normal world caller and no INTERRUPTED secure image) return -EPERM - -This SMC resumes execution in the other security world while there is a secure -image in the EXECUTED/INTERRUPTED state. - -For normal world callers, BL1 sets the previously interrupted secure image state -to EXECUTED. For secure world callers, BL1 sets the previously executing secure -image state to INTERRUPTED. In either case, BL1 saves the calling world's -context, restores the resuming world's context and returns from exception into -the resuming world. If the call is successful then the caller provided -``image_param`` is returned to the resumed world, otherwise an error code is -returned to the caller. - -FWU_SMC_SEC_IMAGE_DONE -~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x14 - - Return: - int : 0 (Success) - : -EPERM - - Pre-conditions: - if (normal world caller) return -EPERM - -This SMC indicates completion of a previously executing secure image. - -BL1 sets the previously executing secure image state to the RESET state, -restores the normal world context and returns from exception into the normal -world. - -FWU_SMC_UPDATE_DONE -~~~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x15 - register_t client_cookie - - Return: - N/A - -This SMC completes the firmware update process. BL1 calls the platform specific -function ``bl1_plat_fwu_done``, passing the optional argument ``client_cookie`` as -a ``void *``. The SMC does not return. - -FWU_SMC_IMAGE_RESET -~~~~~~~~~~~~~~~~~~~ - -:: - - Arguments: - uint32_t function ID : 0x16 - unsigned int image_id - - Return: - int : 0 (Success) - : -EPERM - - Pre-conditions: - if (secure world caller) return -EPERM - if (image in EXECUTED) return -EPERM - -This SMC sets the state of an image to RESET and zeroes the memory used by it. - -This is only allowed if the image is not being executed. - --------------- - -*Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.* - -.. _Trusted Board Boot: ./trusted-board-boot.rst -.. _Porting Guide: ./porting-guide.rst -.. _here: https://github.com/ARM-software/arm-trusted-firmware/wiki/ARM-Trusted-Firmware-Image-Terminology -.. _Authentication Framework Design: ./auth-framework.rst -.. _Universally Unique Identifier: https://tools.ietf.org/rfc/rfc4122.txt - -.. |Flow Diagram| image:: diagrams/fwu_flow.png?raw=true -.. |FWU state machine| image:: diagrams/fwu_states.png?raw=true diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst deleted file mode 100644 index 6aa04f0..0000000 --- a/docs/frequently-asked-questions.rst +++ /dev/null @@ -1,79 +0,0 @@ -Frequently-Asked Questions (FAQ) -================================ - -How do I update my changes? ---------------------------- - -Often it is necessary to update your patch set before it is merged. Refer to the -`Gerrit Upload Patch Set documentation`_ on how to do so. - -If you need to modify an existing patch set with multiple commits, refer to the -`Gerrit Replace Changes documentation`_. - -How long will my changes take to merge into ``integration``? ------------------------------------------------------------- - -This can vary a lot, depending on: - -* How important the patch set is considered by the TF maintainers. Where - possible, you should indicate the required timescales for merging the patch - set and the impact of any delay. Feel free to add a comment to your patch set - to get an estimate of when it will be merged. - -* The quality of the patch set. Patches are likely to be merged more quickly if - they follow the coding guidelines, have already had some code review, and have - been appropriately tested. - -* The impact of the patch set. For example, a patch that changes a key generic - API is likely to receive much greater scrutiny than a local change to a - specific platform port. - -* How much opportunity for external review is required. For example, the TF - maintainers may not wait for external review comments to merge trivial - bug-fixes but may wait up to a week to merge major changes, or ones requiring - feedback from specific parties. - -* How many other patch sets are waiting to be integrated and the risk of - conflict between the topics. - -* If there is a code freeze in place in preparation for the release. Please - refer the `release information`_ for more details. - -* The workload of the TF maintainers. - -How long will it take for my changes to go from ``integration`` to ``master``? ------------------------------------------------------------------------------- - -This depends on how many concurrent patches are being processed at the same -time. In simple cases where all potential regressions have already been tested, -the delay will be less than 1 day. If the TF maintainers are trying to merge -several things over the course of a few days, it might take up to a week. -Typically, it will be 1-2 days. - -The worst case is if the TF maintainers are trying to make a release while also -receiving patches that will not be merged into the release. In this case, the -patches will be merged onto ``integration``, which will temporarily diverge from -the release branch. The ``integration`` branch will be rebased onto ``master`` -after the release, and then ``master`` will be fast-forwarded to ``integration`` -1-2 days later. This whole process could take up 4 weeks. Please refer the -`release information`_ for code freeze dates. The TF maintainers will inform the -patch owner if this is going to happen. - -It is OK to create a patch based on commits that are only available in -``integration`` or another patch set, rather than ``master``. There is a risk -that the dependency commits will change (for example due to patch set rework or -integration problems). If this happens, the dependent patch will need reworking. - -What are these strange comments in my changes? ----------------------------------------------- - -All the comments from ``ci-bot-user`` are associated with Continuous Integration -infrastructure. The links published on the comment are not currently accessible, -but would be after the CI has been transitioned to `trustedfirmware.org`_. -Please refer to https://github.com/ARM-software/tf-issues/issues/681 for more -details on the timelines. - -.. _release information: release-information.rst -.. _Gerrit Upload Patch Set documentation: https://review.trustedfirmware.org/Documentation/intro-user.html#upload-patch-set -.. _Gerrit Replace Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html#push_replace -.. _trustedfirmware.org: https://www.trustedfirmware.org/ diff --git a/docs/getting_started/image-terminology.rst b/docs/getting_started/image-terminology.rst new file mode 100644 index 0000000..4dc1d73 --- /dev/null +++ b/docs/getting_started/image-terminology.rst @@ -0,0 +1,180 @@ +Image Terminology +================= + +.. section-numbering:: + :suffix: . + +.. contents:: + +This page contains the current name, abbreviated name and purpose of the various +images referred to in the Trusted Firmware project. + +General Notes +------------- + +- Some of the names and abbreviated names have changed to accomodate new + requirements. The changed names are as backward compatible as possible to + minimize confusion. Where applicable, the previous names are indicated. Some + code, documentation and build artefacts may still refer to the previous names; + these will inevitably take time to catch up. + +- The main name change is to prefix each image with the processor it corresponds + to (for example ``AP_``, ``SCP_``, ...). In situations where there is no + ambiguity (for example, within AP specific code/documentation), it is + permitted to omit the processor prefix (for example, just BL1 instead of + ``AP_BL1``). + +- Previously, the format for 3rd level images had 2 forms; ``BL3`` was either + suffixed with a dash ("-") followed by a number (for example, ``BL3-1``) or a + subscript number, depending on whether rich text formatting was available. + This was confusing and often the dash gets omitted in practice. Therefore the + new form is to just omit the dash and not use subscript formatting. + +- The names no longer contain dash ("-") characters at all. In some places (for + example, function names) it's not possible to use this character. All dashes + are either removed or replaced by underscores ("_"). + +- The abbreviation BL stands for BootLoader. This is a historical anomaly. + Clearly, many of these images are not BootLoaders, they are simply firmware + images. However, the BL abbreviation is now widely used and is retained for + backwards compatibility. + +- The image names are not case sensitive. For example, ``bl1`` is + interchangeable with ``BL1``, although mixed case should be avoided. + +Trusted Firmware Images +----------------------- + +AP Boot ROM: ``AP_BL1`` +~~~~~~~~~~~~~~~~~~~~~~~ + +Typically, this is the first code to execute on the AP and cannot be modified. +Its primary purpose is to perform the minimum intialization necessary to load +and authenticate an updateable AP firmware image into an executable RAM +location, then hand-off control to that image. + +AP RAM Firmware: ``AP_BL2`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the 2nd stage AP firmware. It is currently also known as the "Trusted +Boot Firmware". Its primary purpose is to perform any additional initialization +required to load and authenticate all 3rd level firmware images into their +executable RAM locations, then hand-off control to the EL3 Runtime Firmware. + +EL3 Runtime Firmware: ``AP_BL31`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Also known as "SoC AP firmware" or "EL3 monitor firmware". Its primary purpose +is to handle transitions between the normal and secure world. + +Secure-EL1 Payload (SP): ``AP_BL32`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Typically this is a TEE or Trusted OS, providing runtime secure services to the +normal world. However, it may refer to a more abstract Secure-EL1 Payload (SP). +Note that this abbreviation should only be used in systems where there is a +single or primary image executing at Secure-EL1. In systems where there are +potentially multiple SPs and there is no concept of a primary SP, this +abbreviation should be avoided; use the recommended **Other AP 3rd level +images** abbreviation instead. + +AP Normal World Firmware: ``AP_BL33`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For example, UEFI or uboot. Its primary purpose is to boot a normal world OS. + +Other AP 3rd level images: ``AP_BL3_XXX`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The abbreviated names of the existing 3rd level images imply a load/execution +ordering (for example, ``AP_BL31 -> AP_BL32 -> AP_BL33``). Some systems may +have additional images and/or a different load/execution ordering. The +abbreviated names of the existing images are retained for backward compatibility +but new 3rd level images should be suffixed with an underscore followed by text +identifier, not a number. + +In systems where 3rd level images are provided by different vendors, the +abbreviated name should identify the vendor as well as the image +function. For example, ``AP_BL3_ARM_RAS``. + +SCP Boot ROM: ``SCP_BL1`` (previously ``BL0``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Typically, this is the first code to execute on the SCP and cannot be modified. +Its primary purpose is to perform the minimum intialization necessary to load +and authenticate an updateable SCP firmware image into an executable RAM +location, then hand-off control to that image. This may be performed in +conjunction with other processor firmware (for example, ``AP_BL1`` and +``AP_BL2``). + +This image was previously abbreviated as ``BL0`` but in some systems, the SCP +may directly load/authenticate its own firmware. In these systems, it doesn't +make sense to interleave the image terminology for AP and SCP; both AP and SCP +Boot ROMs are ``BL1`` from their own point of view. + +SCP RAM Firmware: ``SCP_BL2`` (previously ``BL3-0``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the 2nd stage SCP firmware. It is currently also known as the "SCP +runtime firmware" but it could potentially be an intermediate firmware if the +SCP needs to load/authenticate multiple 3rd level images in future. + +This image was previously abbreviated as BL3-0 but from the SCP's point of view, +this has always been the 2nd stage firmware. The previous name is too +AP-centric. + +Firmware Update (FWU) Images +---------------------------- + +The terminology for these images has not been widely adopted yet but they have +to be considered in a production Trusted Board Boot solution. + +AP Firmware Update Boot ROM: ``AP_NS_BL1U`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Typically, this is the first normal world code to execute on the AP during a +firmware update operation, and cannot be modified. Its primary purpose is to +load subequent firmware update images from an external interface and communicate +with ``AP_BL1`` to authenticate those images. + +During firmware update, there are (potentially) multiple transitions between the +secure and normal world. The "level" of the BL image is relative to the world +it's in so it makes sense to encode "NS" in the normal world images. The absence +of "NS" implies a secure world image. + +AP Firmware Update Config: ``AP_BL2U`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This image does the minimum necessary AP secure world configuration required to +complete the firmware update operation. It is potentially a subset of ``AP_BL2`` +functionality. + +SCP Firmware Update Config: ``SCP_BL2U`` (previously ``BL2-U0``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This image does the minimum necessary SCP secure world configuration required to +complete the firmware update operation. It is potentially a subset of +``SCP_BL2`` functionality. + +AP Firmware Updater: ``AP_NS_BL2U`` (previously ``BL3-U``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the 2nd stage AP normal world firmware updater. Its primary purpose is +to load a new set of firmware images from an external interface and write them +into non-volatile storage. + +Other Processor Firmware Images +------------------------------- + +Some systems may have additional processors to the AP and SCP. For example, a +Management Control Processor (MCP). Images for these processors should follow +the same terminology, with the processor abbreviation prefix, followed by +underscore and the level of the firmware image. + +For example, + +MCP Boot ROM: ``MCP_BL1`` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +MCP RAM Firmware: ``MCP_BL2`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/getting_started/index.rst b/docs/getting_started/index.rst new file mode 100644 index 0000000..23608f8 --- /dev/null +++ b/docs/getting_started/index.rst @@ -0,0 +1,13 @@ +Getting Started +=============== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + user-guide + image-terminology + porting-guide + psci-lib-integration-guide + rt-svc-writers-guide diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst new file mode 100644 index 0000000..cad8b5c --- /dev/null +++ b/docs/getting_started/porting-guide.rst @@ -0,0 +1,2828 @@ +Trusted Firmware-A Porting Guide +================================ + + + +.. contents:: + +Introduction +------------ + +Porting Trusted Firmware-A (TF-A) to a new platform involves making some +mandatory and optional modifications for both the cold and warm boot paths. +Modifications consist of: + +- Implementing a platform-specific function or variable, +- Setting up the execution context in a certain way, or +- Defining certain constants (for example #defines). + +The platform-specific functions and variables are declared in +`include/plat/common/platform.h`_. The firmware provides a default implementation +of variables and functions to fulfill the optional requirements. These +implementations are all weakly defined; they are provided to ease the porting +effort. Each platform port can override them with its own implementation if the +default implementation is inadequate. + +Some modifications are common to all Boot Loader (BL) stages. Section 2 +discusses these in detail. The subsequent sections discuss the remaining +modifications for each BL stage in detail. + +This document should be read in conjunction with the TF-A `User Guide`_. + +Please refer to the `Platform compatibility policy`_ for the policy regarding +compatibility and deprecation of these porting interfaces. + +Only Arm development platforms (such as FVP and Juno) may use the +functions/definitions in ``include/plat/arm/common/`` and the corresponding +source files in ``plat/arm/common/``. This is done so that there are no +dependencies between platforms maintained by different people/companies. If you +want to use any of the functionality present in ``plat/arm`` files, please +create a pull request that moves the code to ``plat/common`` so that it can be +discussed. + +Common modifications +-------------------- + +This section covers the modifications that should be made by the platform for +each BL stage to correctly port the firmware stack. They are categorized as +either mandatory or optional. + +Common mandatory modifications +------------------------------ + +A platform port must enable the Memory Management Unit (MMU) as well as the +instruction and data caches for each BL stage. Setting up the translation +tables is the responsibility of the platform port because memory maps differ +across platforms. A memory translation library (see ``lib/xlat_tables/``) is +provided to help in this setup. + +Note that although this library supports non-identity mappings, this is intended +only for re-mapping peripheral physical addresses and allows platforms with high +I/O addresses to reduce their virtual address space. All other addresses +corresponding to code and data must currently use an identity mapping. + +Also, the only translation granule size supported in TF-A is 4KB, as various +parts of the code assume that is the case. It is not possible to switch to +16 KB or 64 KB granule sizes at the moment. + +In Arm standard platforms, each BL stage configures the MMU in the +platform-specific architecture setup function, ``blX_plat_arch_setup()``, and uses +an identity mapping for all addresses. + +If the build option ``USE_COHERENT_MEM`` is enabled, each platform can allocate a +block of identity mapped secure memory with Device-nGnRE attributes aligned to +page boundary (4K) for each BL stage. All sections which allocate coherent +memory are grouped under ``coherent_ram``. For ex: Bakery locks are placed in a +section identified by name ``bakery_lock`` inside ``coherent_ram`` so that its +possible for the firmware to place variables in it using the following C code +directive: + +:: + + __section("bakery_lock") + +Or alternatively the following assembler code directive: + +:: + + .section bakery_lock + +The ``coherent_ram`` section is a sum of all sections like ``bakery_lock`` which are +used to allocate any data structures that are accessed both when a CPU is +executing with its MMU and caches enabled, and when it's running with its MMU +and caches disabled. Examples are given below. + +The following variables, functions and constants must be defined by the platform +for the firmware to work correctly. + +File : platform_def.h [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each platform must ensure that a header file of this name is in the system +include path with the following constants defined. This will require updating +the list of ``PLAT_INCLUDES`` in the ``platform.mk`` file. + +Platform ports may optionally use the file `include/plat/common/common_def.h`_, +which provides typical values for some of the constants below. These values are +likely to be suitable for all platform ports. + +- **#define : PLATFORM_LINKER_FORMAT** + + Defines the linker format used by the platform, for example + ``elf64-littleaarch64``. + +- **#define : PLATFORM_LINKER_ARCH** + + Defines the processor architecture for the linker by the platform, for + example ``aarch64``. + +- **#define : PLATFORM_STACK_SIZE** + + Defines the normal stack memory available to each CPU. This constant is used + by `plat/common/aarch64/platform_mp_stack.S`_ and + `plat/common/aarch64/platform_up_stack.S`_. + +- **define : CACHE_WRITEBACK_GRANULE** + + Defines the size in bits of the largest cache line across all the cache + levels in the platform. + +- **#define : FIRMWARE_WELCOME_STR** + + Defines the character string printed by BL1 upon entry into the ``bl1_main()`` + function. + +- **#define : PLATFORM_CORE_COUNT** + + Defines the total number of CPUs implemented by the platform across all + clusters in the system. + +- **#define : PLAT_NUM_PWR_DOMAINS** + + Defines the total number of nodes in the power domain topology + tree at all the power domain levels used by the platform. + This macro is used by the PSCI implementation to allocate + data structures to represent power domain topology. + +- **#define : PLAT_MAX_PWR_LVL** + + Defines the maximum power domain level that the power management operations + should apply to. More often, but not always, the power domain level + corresponds to affinity level. This macro allows the PSCI implementation + to know the highest power domain level that it should consider for power + management operations in the system that the platform implements. For + example, the Base AEM FVP implements two clusters with a configurable + number of CPUs and it reports the maximum power domain level as 1. + +- **#define : PLAT_MAX_OFF_STATE** + + Defines the local power state corresponding to the deepest power down + possible at every power domain level in the platform. The local power + states for each level may be sparsely allocated between 0 and this value + with 0 being reserved for the RUN state. The PSCI implementation uses this + value to initialize the local power states of the power domain nodes and + to specify the requested power state for a PSCI_CPU_OFF call. + +- **#define : PLAT_MAX_RET_STATE** + + Defines the local power state corresponding to the deepest retention state + possible at every power domain level in the platform. This macro should be + a value less than PLAT_MAX_OFF_STATE and greater than 0. It is used by the + PSCI implementation to distinguish between retention and power down local + power states within PSCI_CPU_SUSPEND call. + +- **#define : PLAT_MAX_PWR_LVL_STATES** + + Defines the maximum number of local power states per power domain level + that the platform supports. The default value of this macro is 2 since + most platforms just support a maximum of two local power states at each + power domain level (power-down and retention). If the platform needs to + account for more local power states, then it must redefine this macro. + + Currently, this macro is used by the Generic PSCI implementation to size + the array used for PSCI_STAT_COUNT/RESIDENCY accounting. + +- **#define : BL1_RO_BASE** + + Defines the base address in secure ROM where BL1 originally lives. Must be + aligned on a page-size boundary. + +- **#define : BL1_RO_LIMIT** + + Defines the maximum address in secure ROM that BL1's actual content (i.e. + excluding any data section allocated at runtime) can occupy. + +- **#define : BL1_RW_BASE** + + Defines the base address in secure RAM where BL1's read-write data will live + at runtime. Must be aligned on a page-size boundary. + +- **#define : BL1_RW_LIMIT** + + Defines the maximum address in secure RAM that BL1's read-write data can + occupy at runtime. + +- **#define : BL2_BASE** + + Defines the base address in secure RAM where BL1 loads the BL2 binary image. + Must be aligned on a page-size boundary. This constant is not applicable + when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_LIMIT** + + Defines the maximum address in secure RAM that the BL2 image can occupy. + This constant is not applicable when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RO_BASE** + + Defines the base address in secure XIP memory where BL2 RO section originally + lives. Must be aligned on a page-size boundary. This constant is only needed + when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RO_LIMIT** + + Defines the maximum address in secure XIP memory that BL2's actual content + (i.e. excluding any data section allocated at runtime) can occupy. This + constant is only needed when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RW_BASE** + + Defines the base address in secure RAM where BL2's read-write data will live + at runtime. Must be aligned on a page-size boundary. This constant is only + needed when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RW_LIMIT** + + Defines the maximum address in secure RAM that BL2's read-write data can + occupy at runtime. This constant is only needed when BL2_IN_XIP_MEM is set + to '1'. + +- **#define : BL31_BASE** + + Defines the base address in secure RAM where BL2 loads the BL31 binary + image. Must be aligned on a page-size boundary. + +- **#define : BL31_LIMIT** + + Defines the maximum address in secure RAM that the BL31 image can occupy. + +For every image, the platform must define individual identifiers that will be +used by BL1 or BL2 to load the corresponding image into memory from non-volatile +storage. For the sake of performance, integer numbers will be used as +identifiers. The platform will use those identifiers to return the relevant +information about the image to be loaded (file handler, load address, +authentication information, etc.). The following image identifiers are +mandatory: + +- **#define : BL2_IMAGE_ID** + + BL2 image identifier, used by BL1 to load BL2. + +- **#define : BL31_IMAGE_ID** + + BL31 image identifier, used by BL2 to load BL31. + +- **#define : BL33_IMAGE_ID** + + BL33 image identifier, used by BL2 to load BL33. + +If Trusted Board Boot is enabled, the following certificate identifiers must +also be defined: + +- **#define : TRUSTED_BOOT_FW_CERT_ID** + + BL2 content certificate identifier, used by BL1 to load the BL2 content + certificate. + +- **#define : TRUSTED_KEY_CERT_ID** + + Trusted key certificate identifier, used by BL2 to load the trusted key + certificate. + +- **#define : SOC_FW_KEY_CERT_ID** + + BL31 key certificate identifier, used by BL2 to load the BL31 key + certificate. + +- **#define : SOC_FW_CONTENT_CERT_ID** + + BL31 content certificate identifier, used by BL2 to load the BL31 content + certificate. + +- **#define : NON_TRUSTED_FW_KEY_CERT_ID** + + BL33 key certificate identifier, used by BL2 to load the BL33 key + certificate. + +- **#define : NON_TRUSTED_FW_CONTENT_CERT_ID** + + BL33 content certificate identifier, used by BL2 to load the BL33 content + certificate. + +- **#define : FWU_CERT_ID** + + Firmware Update (FWU) certificate identifier, used by NS_BL1U to load the + FWU content certificate. + +- **#define : PLAT_CRYPTOCELL_BASE** + + This defines the base address of Arm® TrustZone® CryptoCell and must be + defined if CryptoCell crypto driver is used for Trusted Board Boot. For + capable Arm platforms, this driver is used if ``ARM_CRYPTOCELL_INTEG`` is + set. + +If the AP Firmware Updater Configuration image, BL2U is used, the following +must also be defined: + +- **#define : BL2U_BASE** + + Defines the base address in secure memory where BL1 copies the BL2U binary + image. Must be aligned on a page-size boundary. + +- **#define : BL2U_LIMIT** + + Defines the maximum address in secure memory that the BL2U image can occupy. + +- **#define : BL2U_IMAGE_ID** + + BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to BL2U. + +If the SCP Firmware Update Configuration Image, SCP_BL2U is used, the following +must also be defined: + +- **#define : SCP_BL2U_IMAGE_ID** + + SCP_BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to SCP_BL2U. + NOTE: TF-A does not provide source code for this image. + +If the Non-Secure Firmware Updater ROM, NS_BL1U is used, the following must +also be defined: + +- **#define : NS_BL1U_BASE** + + Defines the base address in non-secure ROM where NS_BL1U executes. + Must be aligned on a page-size boundary. + NOTE: TF-A does not provide source code for this image. + +- **#define : NS_BL1U_IMAGE_ID** + + NS_BL1U image identifier, used by BL1 to fetch an image descriptor + corresponding to NS_BL1U. + +If the Non-Secure Firmware Updater, NS_BL2U is used, the following must also +be defined: + +- **#define : NS_BL2U_BASE** + + Defines the base address in non-secure memory where NS_BL2U executes. + Must be aligned on a page-size boundary. + NOTE: TF-A does not provide source code for this image. + +- **#define : NS_BL2U_IMAGE_ID** + + NS_BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to NS_BL2U. + +For the the Firmware update capability of TRUSTED BOARD BOOT, the following +macros may also be defined: + +- **#define : PLAT_FWU_MAX_SIMULTANEOUS_IMAGES** + + Total number of images that can be loaded simultaneously. If the platform + doesn't specify any value, it defaults to 10. + +If a SCP_BL2 image is supported by the platform, the following constants must +also be defined: + +- **#define : SCP_BL2_IMAGE_ID** + + SCP_BL2 image identifier, used by BL2 to load SCP_BL2 into secure memory + from platform storage before being transferred to the SCP. + +- **#define : SCP_FW_KEY_CERT_ID** + + SCP_BL2 key certificate identifier, used by BL2 to load the SCP_BL2 key + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : SCP_FW_CONTENT_CERT_ID** + + SCP_BL2 content certificate identifier, used by BL2 to load the SCP_BL2 + content certificate (mandatory when Trusted Board Boot is enabled). + +If a BL32 image is supported by the platform, the following constants must +also be defined: + +- **#define : BL32_IMAGE_ID** + + BL32 image identifier, used by BL2 to load BL32. + +- **#define : TRUSTED_OS_FW_KEY_CERT_ID** + + BL32 key certificate identifier, used by BL2 to load the BL32 key + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : TRUSTED_OS_FW_CONTENT_CERT_ID** + + BL32 content certificate identifier, used by BL2 to load the BL32 content + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : BL32_BASE** + + Defines the base address in secure memory where BL2 loads the BL32 binary + image. Must be aligned on a page-size boundary. + +- **#define : BL32_LIMIT** + + Defines the maximum address that the BL32 image can occupy. + +If the Test Secure-EL1 Payload (TSP) instantiation of BL32 is supported by the +platform, the following constants must also be defined: + +- **#define : TSP_SEC_MEM_BASE** + + Defines the base address of the secure memory used by the TSP image on the + platform. This must be at the same address or below ``BL32_BASE``. + +- **#define : TSP_SEC_MEM_SIZE** + + Defines the size of the secure memory used by the BL32 image on the + platform. ``TSP_SEC_MEM_BASE`` and ``TSP_SEC_MEM_SIZE`` must fully + accommodate the memory required by the BL32 image, defined by ``BL32_BASE`` + and ``BL32_LIMIT``. + +- **#define : TSP_IRQ_SEC_PHY_TIMER** + + Defines the ID of the secure physical generic timer interrupt used by the + TSP's interrupt handling code. + +If the platform port uses the translation table library code, the following +constants must also be defined: + +- **#define : PLAT_XLAT_TABLES_DYNAMIC** + + Optional flag that can be set per-image to enable the dynamic allocation of + regions even when the MMU is enabled. If not defined, only static + functionality will be available, if defined and set to 1 it will also + include the dynamic functionality. + +- **#define : MAX_XLAT_TABLES** + + Defines the maximum number of translation tables that are allocated by the + translation table library code. To minimize the amount of runtime memory + used, choose the smallest value needed to map the required virtual addresses + for each BL stage. If ``PLAT_XLAT_TABLES_DYNAMIC`` flag is enabled for a BL + image, ``MAX_XLAT_TABLES`` must be defined to accommodate the dynamic regions + as well. + +- **#define : MAX_MMAP_REGIONS** + + Defines the maximum number of regions that are allocated by the translation + table library code. A region consists of physical base address, virtual base + address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as + defined in the ``mmap_region_t`` structure. The platform defines the regions + that should be mapped. Then, the translation table library will create the + corresponding tables and descriptors at runtime. To minimize the amount of + runtime memory used, choose the smallest value needed to register the + required regions for each BL stage. If ``PLAT_XLAT_TABLES_DYNAMIC`` flag is + enabled for a BL image, ``MAX_MMAP_REGIONS`` must be defined to accommodate + the dynamic regions as well. + +- **#define : PLAT_VIRT_ADDR_SPACE_SIZE** + + Defines the total size of the virtual address space in bytes. For example, + for a 32 bit virtual address space, this value should be ``(1ULL << 32)``. + +- **#define : PLAT_PHY_ADDR_SPACE_SIZE** + + Defines the total size of the physical address space in bytes. For example, + for a 32 bit physical address space, this value should be ``(1ULL << 32)``. + +If the platform port uses the IO storage framework, the following constants +must also be defined: + +- **#define : MAX_IO_DEVICES** + + Defines the maximum number of registered IO devices. Attempting to register + more devices than this value using ``io_register_device()`` will fail with + -ENOMEM. + +- **#define : MAX_IO_HANDLES** + + Defines the maximum number of open IO handles. Attempting to open more IO + entities than this value using ``io_open()`` will fail with -ENOMEM. + +- **#define : MAX_IO_BLOCK_DEVICES** + + Defines the maximum number of registered IO block devices. Attempting to + register more devices this value using ``io_dev_open()`` will fail + with -ENOMEM. MAX_IO_BLOCK_DEVICES should be less than MAX_IO_DEVICES. + With this macro, multiple block devices could be supported at the same + time. + +If the platform needs to allocate data within the per-cpu data framework in +BL31, it should define the following macro. Currently this is only required if +the platform decides not to use the coherent memory section by undefining the +``USE_COHERENT_MEM`` build flag. In this case, the framework allocates the +required memory within the the per-cpu data to minimize wastage. + +- **#define : PLAT_PCPU_DATA_SIZE** + + Defines the memory (in bytes) to be reserved within the per-cpu data + structure for use by the platform layer. + +The following constants are optional. They should be defined when the platform +memory layout implies some image overlaying like in Arm standard platforms. + +- **#define : BL31_PROGBITS_LIMIT** + + Defines the maximum address in secure RAM that the BL31's progbits sections + can occupy. + +- **#define : TSP_PROGBITS_LIMIT** + + Defines the maximum address that the TSP's progbits sections can occupy. + +If the platform port uses the PL061 GPIO driver, the following constant may +optionally be defined: + +- **PLAT_PL061_MAX_GPIOS** + Maximum number of GPIOs required by the platform. This allows control how + much memory is allocated for PL061 GPIO controllers. The default value is + + #. $(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) + +If the platform port uses the partition driver, the following constant may +optionally be defined: + +- **PLAT_PARTITION_MAX_ENTRIES** + Maximum number of partition entries required by the platform. This allows + control how much memory is allocated for partition entries. The default + value is 128. + `For example, define the build flag in platform.mk`_: + PLAT_PARTITION_MAX_ENTRIES := 12 + $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) + +The following constant is optional. It should be defined to override the default +behaviour of the ``assert()`` function (for example, to save memory). + +- **PLAT_LOG_LEVEL_ASSERT** + If ``PLAT_LOG_LEVEL_ASSERT`` is higher or equal than ``LOG_LEVEL_VERBOSE``, + ``assert()`` prints the name of the file, the line number and the asserted + expression. Else if it is higher than ``LOG_LEVEL_INFO``, it prints the file + name and the line number. Else if it is lower than ``LOG_LEVEL_INFO``, it + doesn't print anything to the console. If ``PLAT_LOG_LEVEL_ASSERT`` isn't + defined, it defaults to ``LOG_LEVEL``. + +If the platform port uses the Activity Monitor Unit, the following constants +may be defined: + +- **PLAT_AMU_GROUP1_COUNTERS_MASK** + This mask reflects the set of group counters that should be enabled. The + maximum number of group 1 counters supported by AMUv1 is 16 so the mask + can be at most 0xffff. If the platform does not define this mask, no group 1 + counters are enabled. If the platform defines this mask, the following + constant needs to also be defined. + +- **PLAT_AMU_GROUP1_NR_COUNTERS** + This value is used to allocate an array to save and restore the counters + specified by ``PLAT_AMU_GROUP1_COUNTERS_MASK`` on CPU suspend. + This value should be equal to the highest bit position set in the + mask, plus 1. The maximum number of group 1 counters in AMUv1 is 16. + +File : plat_macros.S [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each platform must ensure a file of this name is in the system include path with +the following macro defined. In the Arm development platforms, this file is +found in ``plat/arm/board//include/plat_macros.S``. + +- **Macro : plat_crash_print_regs** + + This macro allows the crash reporting routine to print relevant platform + registers in case of an unhandled exception in BL31. This aids in debugging + and this macro can be defined to be empty in case register reporting is not + desired. + + For instance, GIC or interconnect registers may be helpful for + troubleshooting. + +Handling Reset +-------------- + +BL1 by default implements the reset vector where execution starts from a cold +or warm boot. BL31 can be optionally set as a reset vector using the +``RESET_TO_BL31`` make variable. + +For each CPU, the reset vector code is responsible for the following tasks: + +#. Distinguishing between a cold boot and a warm boot. + +#. In the case of a cold boot and the CPU being a secondary CPU, ensuring that + the CPU is placed in a platform-specific state until the primary CPU + performs the necessary steps to remove it from this state. + +#. In the case of a warm boot, ensuring that the CPU jumps to a platform- + specific address in the BL31 image in the same processor mode as it was + when released from reset. + +The following functions need to be implemented by the platform port to enable +reset vector code to perform the above tasks. + +Function : plat_get_my_entrypoint() [mandatory when PROGRAMMABLE_RESET_ADDRESS == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uintptr_t + +This function is called with the MMU and caches disabled +(``SCTLR_EL3.M`` = 0 and ``SCTLR_EL3.C`` = 0). The function is responsible for +distinguishing between a warm and cold reset for the current CPU using +platform-specific means. If it's a warm reset, then it returns the warm +reset entrypoint point provided to ``plat_setup_psci_ops()`` during +BL31 initialization. If it's a cold reset then this function must return zero. + +This function does not follow the Procedure Call Standard used by the +Application Binary Interface for the Arm 64-bit architecture. The caller should +not assume that callee saved registers are preserved across a call to this +function. + +This function fulfills requirement 1 and 3 listed above. + +Note that for platforms that support programming the reset address, it is +expected that a CPU will start executing code directly at the right address, +both on a cold and warm reset. In this case, there is no need to identify the +type of reset nor to query the warm reset entrypoint. Therefore, implementing +this function is not required on such platforms. + +Function : plat_secondary_cold_boot_setup() [mandatory when COLD_BOOT_SINGLE_CPU == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + +This function is called with the MMU and data caches disabled. It is responsible +for placing the executing secondary CPU in a platform-specific state until the +primary CPU performs the necessary actions to bring it out of that state and +allow entry into the OS. This function must not return. + +In the Arm FVP port, when using the normal boot flow, each secondary CPU powers +itself off. The primary CPU is responsible for powering up the secondary CPUs +when normal world software requires them. When booting an EL3 payload instead, +they stay powered on and are put in a holding pen until their mailbox gets +populated. + +This function fulfills requirement 2 above. + +Note that for platforms that can't release secondary CPUs out of reset, only the +primary CPU will execute the cold boot code. Therefore, implementing this +function is not required on such platforms. + +Function : plat_is_my_cpu_primary() [mandatory when COLD_BOOT_SINGLE_CPU == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function identifies whether the current CPU is the primary CPU or a +secondary CPU. A return value of zero indicates that the CPU is not the +primary CPU, while a non-zero return value indicates that the CPU is the +primary CPU. + +Note that for platforms that can't release secondary CPUs out of reset, only the +primary CPU will execute the cold boot code. Therefore, there is no need to +distinguish between primary and secondary CPUs and implementing this function is +not required. + +Function : platform_mem_init() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function is called before any access to data is made by the firmware, in +order to carry out any essential memory initialization. + +Function: plat_get_rotpk_info() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, void **, unsigned int *, unsigned int * + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It returns a +pointer to the ROTPK stored in the platform (or a hash of it) and its length. +The ROTPK must be encoded in DER format according to the following ASN.1 +structure: + +:: + + AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL + } + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING + } + +In case the function returns a hash of the key: + +:: + + DigestInfo ::= SEQUENCE { + digestAlgorithm AlgorithmIdentifier, + digest OCTET STRING + } + +The function returns 0 on success. Any other value is treated as error by the +Trusted Board Boot. The function also reports extra information related +to the ROTPK in the flags parameter: + +:: + + ROTPK_IS_HASH : Indicates that the ROTPK returned by the platform is a + hash. + ROTPK_NOT_DEPLOYED : This allows the platform to skip certificate ROTPK + verification while the platform ROTPK is not deployed. + When this flag is set, the function does not need to + return a platform ROTPK, and the authentication + framework uses the ROTPK in the certificate without + verifying it against the platform value. This flag + must not be used in a deployed production environment. + +Function: plat_get_nv_ctr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, unsigned int * + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It returns the +non-volatile counter value stored in the platform in the second argument. The +cookie in the first argument may be used to select the counter in case the +platform provides more than one (for example, on platforms that use the default +TBBR CoT, the cookie will correspond to the OID values defined in +TRUSTED_FW_NVCOUNTER_OID or NON_TRUSTED_FW_NVCOUNTER_OID). + +The function returns 0 on success. Any other value means the counter value could +not be retrieved from the platform. + +Function: plat_set_nv_ctr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, unsigned int + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It sets a new +counter value in the platform. The cookie in the first argument may be used to +select the counter (as explained in plat_get_nv_ctr()). The second argument is +the updated counter value to be written to the NV counter. + +The function returns 0 on success. Any other value means the counter value could +not be updated. + +Function: plat_set_nv_ctr2() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, const auth_img_desc_t *, unsigned int + Return : int + +This function is optional when Trusted Board Boot is enabled. If this +interface is defined, then ``plat_set_nv_ctr()`` need not be defined. The +first argument passed is a cookie and is typically used to +differentiate between a Non Trusted NV Counter and a Trusted NV +Counter. The second argument is a pointer to an authentication image +descriptor and may be used to decide if the counter is allowed to be +updated or not. The third argument is the updated counter value to +be written to the NV counter. + +The function returns 0 on success. Any other value means the counter value +either could not be updated or the authentication image descriptor indicates +that it is not allowed to be updated. + +Common mandatory function modifications +--------------------------------------- + +The following functions are mandatory functions which need to be implemented +by the platform port. + +Function : plat_my_core_pos() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function returns the index of the calling CPU which is used as a +CPU-specific linear index into blocks of memory (for example while allocating +per-CPU stacks). This function will be invoked very early in the +initialization sequence which mandates that this function should be +implemented in assembly and should not rely on the availability of a C +runtime environment. This function can clobber x0 - x8 and must preserve +x9 - x29. + +This function plays a crucial role in the power domain topology framework in +PSCI and details of this can be found in `Power Domain Topology Design`_. + +Function : plat_core_pos_by_mpidr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t + Return : int + +This function validates the ``MPIDR`` of a CPU and converts it to an index, +which can be used as a CPU-specific linear index into blocks of memory. In +case the ``MPIDR`` is invalid, this function returns -1. This function will only +be invoked by BL31 after the power domain topology is initialized and can +utilize the C runtime environment. For further details about how TF-A +represents the power domain topology and how this relates to the linear CPU +index, please refer `Power Domain Topology Design`_. + +Function : plat_get_mbedtls_heap() [when TRUSTED_BOARD_BOOT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments : void **heap_addr, size_t *heap_size + Return : int + +This function is invoked during Mbed TLS library initialisation to get a heap, +by means of a starting address and a size. This heap will then be used +internally by the Mbed TLS library. Hence, each BL stage that utilises Mbed TLS +must be able to provide a heap to it. + +A helper function can be found in `drivers/auth/mbedtls/mbedtls_common.c` in +which a heap is statically reserved during compile time inside every image +(i.e. every BL stage) that utilises Mbed TLS. In this default implementation, +the function simply returns the address and size of this "pre-allocated" heap. +For a platform to use this default implementation, only a call to the helper +from inside plat_get_mbedtls_heap() body is enough and nothing else is needed. + +However, by writting their own implementation, platforms have the potential to +optimise memory usage. For example, on some Arm platforms, the Mbed TLS heap is +shared between BL1 and BL2 stages and, thus, the necessary space is not reserved +twice. + +On success the function should return 0 and a negative error code otherwise. + +Common optional modifications +----------------------------- + +The following are helper functions implemented by the firmware that perform +common platform-specific tasks. A platform may choose to override these +definitions. + +Function : plat_set_my_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function sets the current stack pointer to the normal memory stack that +has been allocated for the current CPU. For BL images that only require a +stack for the primary CPU, the UP version of the function is used. The size +of the stack allocated to each CPU is specified by the platform defined +constant ``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in `plat/common/aarch64/platform_up_stack.S`_ and +`plat/common/aarch64/platform_mp_stack.S`_ + +Function : plat_get_my_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uintptr_t + +This function returns the base address of the normal memory stack that +has been allocated for the current CPU. For BL images that only require a +stack for the primary CPU, the UP version of the function is used. The size +of the stack allocated to each CPU is specified by the platform defined +constant ``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in `plat/common/aarch64/platform_up_stack.S`_ and +`plat/common/aarch64/platform_mp_stack.S`_ + +Function : plat_report_exception() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +A platform may need to report various information about its status when an +exception is taken, for example the current exception level, the CPU security +state (secure/non-secure), the exception type, and so on. This function is +called in the following circumstances: + +- In BL1, whenever an exception is taken. +- In BL2, whenever an exception is taken. + +The default implementation doesn't do anything, to avoid making assumptions +about the way the platform displays its status information. + +For AArch64, this function receives the exception type as its argument. +Possible values for exceptions types are listed in the +`include/common/bl_common.h`_ header file. Note that these constants are not +related to any architectural exception code; they are just a TF-A convention. + +For AArch32, this function receives the exception mode as its argument. +Possible values for exception modes are listed in the +`include/lib/aarch32/arch.h`_ header file. + +Function : plat_reset_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +A platform may need to do additional initialization after reset. This function +allows the platform to do the platform specific intializations. Platform +specific errata workarounds could also be implemented here. The API should +preserve the values of callee saved registers x19 to x29. + +The default implementation doesn't do anything. If a platform needs to override +the default implementation, refer to the `Firmware Design`_ for general +guidelines. + +Function : plat_disable_acp() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This API allows a platform to disable the Accelerator Coherency Port (if +present) during a cluster power down sequence. The default weak implementation +doesn't do anything. Since this API is called during the power down sequence, +it has restrictions for stack usage and it can use the registers x0 - x17 as +scratch registers. It should preserve the value in x18 register as it is used +by the caller to store the return address. + +Function : plat_error_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Return : void + +This API is called when the generic code encounters an error situation from +which it cannot continue. It allows the platform to perform error reporting or +recovery actions (for example, reset the system). This function must not return. + +The parameter indicates the type of error using standard codes from ``errno.h``. +Possible errors reported by the generic code are: + +- ``-EAUTH``: a certificate or image could not be authenticated (when Trusted + Board Boot is enabled) +- ``-ENOENT``: the requested image or certificate could not be found or an IO + error was detected +- ``-ENOMEM``: resources exhausted. TF-A does not use dynamic memory, so this + error is usually an indication of an incorrect array size + +The default implementation simply spins. + +Function : plat_panic_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This API is called when the generic code encounters an unexpected error +situation from which it cannot recover. This function must not return, +and must be implemented in assembly because it may be called before the C +environment is initialized. + +Note: The address from where it was called is stored in x30 (Link Register). +The default implementation simply spins. + +Function : plat_get_bl_image_load_info() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bl_load_info_t * + +This function returns pointer to the list of images that the platform has +populated to load. This function is invoked in BL2 to load the +BL3xx images. + +Function : plat_get_next_bl_params() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bl_params_t * + +This function returns a pointer to the shared memory that the platform has +kept aside to pass TF-A related information that next BL image needs. This +function is invoked in BL2 to pass this information to the next BL +image. + +Function : plat_get_stack_protector_canary() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : u_register_t + +This function returns a random value that is used to initialize the canary used +when the stack protector is enabled with ENABLE_STACK_PROTECTOR. A predictable +value will weaken the protection as the attacker could easily write the right +value as part of the attack most of the time. Therefore, it should return a +true random number. + +Note: For the protection to be effective, the global data need to be placed at +a lower address than the stack bases. Failure to do so would allow an attacker +to overwrite the canary as part of the stack buffer overflow attack. + +Function : plat_flush_next_bl_params() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function flushes to main memory all the image params that are passed to +next image. This function is invoked in BL2 to flush this information +to the next BL image. + +Function : plat_log_get_prefix() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : const char * + +This function defines the prefix string corresponding to the `log_level` to be +prepended to all the log output from TF-A. The `log_level` (argument) will +correspond to one of the standard log levels defined in debug.h. The platform +can override the common implementation to define a different prefix string for +the log output. The implementation should be robust to future changes that +increase the number of log levels. + +Modifications specific to a Boot Loader stage +--------------------------------------------- + +Boot Loader Stage 1 (BL1) +------------------------- + +BL1 implements the reset vector where execution starts from after a cold or +warm boot. For each CPU, BL1 is responsible for the following tasks: + +#. Handling the reset as described in section 2.2 + +#. In the case of a cold boot and the CPU being the primary CPU, ensuring that + only this CPU executes the remaining BL1 code, including loading and passing + control to the BL2 stage. + +#. Identifying and starting the Firmware Update process (if required). + +#. Loading the BL2 image from non-volatile storage into secure memory at the + address specified by the platform defined constant ``BL2_BASE``. + +#. Populating a ``meminfo`` structure with the following information in memory, + accessible by BL2 immediately upon entry. + + :: + + meminfo.total_base = Base address of secure RAM visible to BL2 + meminfo.total_size = Size of secure RAM visible to BL2 + + By default, BL1 places this ``meminfo`` structure at the end of secure + memory visible to BL2. + + It is possible for the platform to decide where it wants to place the + ``meminfo`` structure for BL2 or restrict the amount of memory visible to + BL2 by overriding the weak default implementation of + ``bl1_plat_handle_post_image_load`` API. + +The following functions need to be implemented by the platform port to enable +BL1 to perform the above tasks. + +Function : bl1_early_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +On Arm standard platforms, this function: + +- Enables a secure instance of SP805 to act as the Trusted Watchdog. + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL1. + +- Enables issuing of snoop and DVM (Distributed Virtual Memory) requests to + the CCI slave interface corresponding to the cluster that includes the + primary CPU. + +Function : bl1_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function performs any platform-specific and architectural setup that the +platform requires. Platform-specific setup might include configuration of +memory controllers and the interconnect. + +In Arm standard platforms, this function enables the MMU. + +This function helps fulfill requirement 2 above. + +Function : bl1_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches enabled. It is responsible +for performing any remaining platform-specific setup that can occur after the +MMU and data cache have been enabled. + +if support for multiple boot sources is required, it initializes the boot +sequence used by plat_try_next_boot_source(). + +In Arm standard platforms, this function initializes the storage abstraction +layer used to load the next bootloader image. + +This function helps fulfill requirement 4 above. + +Function : bl1_plat_sec_mem_layout() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : meminfo * + +This function should only be called on the cold boot path. It executes with the +MMU and data caches enabled. The pointer returned by this function must point to +a ``meminfo`` structure containing the extents and availability of secure RAM for +the BL1 stage. + +:: + + meminfo.total_base = Base address of secure RAM visible to BL1 + meminfo.total_size = Size of secure RAM visible to BL1 + +This information is used by BL1 to load the BL2 image in secure RAM. BL1 also +populates a similar structure to tell BL2 the extents of memory available for +its own use. + +This function helps fulfill requirements 4 and 5 above. + +Function : bl1_plat_prepare_exit() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : entry_point_info_t * + Return : void + +This function is called prior to exiting BL1 in response to the +``BL1_SMC_RUN_IMAGE`` SMC request raised by BL2. It should be used to perform +platform specific clean up or bookkeeping operations before transferring +control to the next image. It receives the address of the ``entry_point_info_t`` +structure passed from BL2. This function runs with MMU disabled. + +Function : bl1_plat_set_ep_info() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, entry_point_info_t *ep_info + Return : void + +This function allows platforms to override ``ep_info`` for the given ``image_id``. + +The default implementation just returns. + +Function : bl1_plat_get_next_image_id() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This and the following function must be overridden to enable the FWU feature. + +BL1 calls this function after platform setup to identify the next image to be +loaded and executed. If the platform returns ``BL2_IMAGE_ID`` then BL1 proceeds +with the normal boot sequence, which loads and executes BL2. If the platform +returns a different image id, BL1 assumes that Firmware Update is required. + +The default implementation always returns ``BL2_IMAGE_ID``. The Arm development +platforms override this function to detect if firmware update is required, and +if so, return the first image in the firmware update process. + +Function : bl1_plat_get_image_desc() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : image_desc_t * + +BL1 calls this function to get the image descriptor information ``image_desc_t`` +for the provided ``image_id`` from the platform. + +The default implementation always returns a common BL2 image descriptor. Arm +standard platforms return an image descriptor corresponding to BL2 or one of +the firmware update images defined in the Trusted Board Boot Requirements +specification. + +Function : bl1_plat_handle_pre_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : int + +This function can be used by the platforms to update/use image information +corresponding to ``image_id``. This function is invoked in BL1, both in cold +boot and FWU code path, before loading the image. + +Function : bl1_plat_handle_post_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : int + +This function can be used by the platforms to update/use image information +corresponding to ``image_id``. This function is invoked in BL1, both in cold +boot and FWU code path, after loading and authenticating the image. + +The default weak implementation of this function calculates the amount of +Trusted SRAM that can be used by BL2 and allocates a ``meminfo_t`` +structure at the beginning of this free memory and populates it. The address +of ``meminfo_t`` structure is updated in ``arg1`` of the entrypoint +information to BL2. + +Function : bl1_plat_fwu_done() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, uintptr_t image_src, + unsigned int image_size + Return : void + +BL1 calls this function when the FWU process is complete. It must not return. +The platform may override this function to take platform specific action, for +example to initiate the normal boot flow. + +The default implementation spins forever. + +Function : bl1_plat_mem_check() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t mem_base, unsigned int mem_size, + unsigned int flags + Return : int + +BL1 calls this function while handling FWU related SMCs, more specifically when +copying or authenticating an image. Its responsibility is to ensure that the +region of memory identified by ``mem_base`` and ``mem_size`` is mapped in BL1, and +that this memory corresponds to either a secure or non-secure memory region as +indicated by the security state of the ``flags`` argument. + +This function can safely assume that the value resulting from the addition of +``mem_base`` and ``mem_size`` fits into a ``uintptr_t`` type variable and does not +overflow. + +This function must return 0 on success, a non-null error code otherwise. + +The default implementation of this function asserts therefore platforms must +override it when using the FWU feature. + +Boot Loader Stage 2 (BL2) +------------------------- + +The BL2 stage is executed only by the primary CPU, which is determined in BL1 +using the ``platform_is_primary_cpu()`` function. BL1 passed control to BL2 at +``BL2_BASE``. BL2 executes in Secure EL1 and and invokes +``plat_get_bl_image_load_info()`` to retrieve the list of images to load from +non-volatile storage to secure/non-secure RAM. After all the images are loaded +then BL2 invokes ``plat_get_next_bl_params()`` to get the list of executable +images to be passed to the next BL image. + +The following functions must be implemented by the platform port to enable BL2 +to perform the above tasks. + +Function : bl2_early_platform_setup2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. The 4 arguments are passed by BL1 to BL2 and these arguments +are platform specific. + +On Arm standard platforms, the arguments received are : + + arg0 - Points to load address of HW_CONFIG if present + + arg1 - ``meminfo`` structure populated by BL1. The platform copies + the contents of ``meminfo`` as it may be subsequently overwritten by BL2. + +On Arm standard platforms, this function also: + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL2. + +- Initializes the storage abstraction layer used to load further bootloader + images. It is necessary to do this early on platforms with a SCP_BL2 image, + since the later ``bl2_platform_setup`` must be done after SCP_BL2 is loaded. + +Function : bl2_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On Arm standard platforms, this function enables the MMU. + +Function : bl2_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl2_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to perform any platform initialization +specific to BL2. + +In Arm standard platforms, this function performs security setup, including +configuration of the TrustZone controller to allow non-secure masters access +to most of DRAM. Part of DRAM is reserved for secure world use. + +Function : bl2_plat_handle_pre_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This function can be used by the platforms to update/use image information +for given ``image_id``. This function is currently invoked in BL2 before +loading each image. + +Function : bl2_plat_handle_post_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This function can be used by the platforms to update/use image information +for given ``image_id``. This function is currently invoked in BL2 after +loading each image. + +Function : bl2_plat_preload_setup [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This optional function performs any BL2 platform initialization +required before image loading, that is not done later in +bl2_platform_setup(). Specifically, if support for multiple +boot sources is required, it initializes the boot sequence used by +plat_try_next_boot_source(). + +Function : plat_try_next_boot_source() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This optional function passes to the next boot source in the redundancy +sequence. + +This function moves the current boot redundancy source to the next +element in the boot sequence. If there are no more boot sources then it +must return 0, otherwise it must return 1. The default implementation +of this always returns 0. + +Boot Loader Stage 2 (BL2) at EL3 +-------------------------------- + +When the platform has a non-TF-A Boot ROM it is desirable to jump +directly to BL2 instead of TF-A BL1. In this case BL2 is expected to +execute at EL3 instead of executing at EL1. Refer to the `Firmware +Design`_ for more information. + +All mandatory functions of BL2 must be implemented, except the functions +bl2_early_platform_setup and bl2_el3_plat_arch_setup, because +their work is done now by bl2_el3_early_platform_setup and +bl2_el3_plat_arch_setup. These functions should generally implement +the bl1_plat_xxx() and bl2_plat_xxx() functionality combined. + + +Function : bl2_el3_early_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. This function receives four parameters which can be used +by the platform to pass any needed information from the Boot ROM to BL2. + +On Arm standard platforms, this function does the following: + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL2. + +- Initializes the storage abstraction layer used to load further bootloader + images. It is necessary to do this early on platforms with a SCP_BL2 image, + since the later ``bl2_platform_setup`` must be done after SCP_BL2 is loaded. + +- Initializes the private variables that define the memory layout used. + +Function : bl2_el3_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On Arm standard platforms, this function enables the MMU. + +Function : bl2_el3_plat_prepare_exit() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function is called prior to exiting BL2 and run the next image. +It should be used to perform platform specific clean up or bookkeeping +operations before transferring control to the next image. This function +runs with MMU disabled. + +FWU Boot Loader Stage 2 (BL2U) +------------------------------ + +The AP Firmware Updater Configuration, BL2U, is an optional part of the FWU +process and is executed only by the primary CPU. BL1 passes control to BL2U at +``BL2U_BASE``. BL2U executes in Secure-EL1 and is responsible for: + +#. (Optional) Transferring the optional SCP_BL2U binary image from AP secure + memory to SCP RAM. BL2U uses the SCP_BL2U ``image_info`` passed by BL1. + ``SCP_BL2U_BASE`` defines the address in AP secure memory where SCP_BL2U + should be copied from. Subsequent handling of the SCP_BL2U image is + implemented by the platform specific ``bl2u_plat_handle_scp_bl2u()`` function. + If ``SCP_BL2U_BASE`` is not defined then this step is not performed. + +#. Any platform specific setup required to perform the FWU process. For + example, Arm standard platforms initialize the TZC controller so that the + normal world can access DDR memory. + +The following functions must be implemented by the platform port to enable +BL2U to perform the tasks mentioned above. + +Function : bl2u_early_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : meminfo *mem_info, void *plat_info + Return : void + +This function executes with the MMU and data caches disabled. It is only +called by the primary CPU. The arguments to this function is the address +of the ``meminfo`` structure and platform specific info provided by BL1. + +The platform may copy the contents of the ``mem_info`` and ``plat_info`` into +private storage as the original memory may be subsequently overwritten by BL2U. + +On Arm CSS platforms ``plat_info`` is interpreted as an ``image_info_t`` structure, +to extract SCP_BL2U image information, which is then copied into a private +variable. + +Function : bl2u_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only +called by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms, for example enabling the MMU (since the memory +map differs across platforms). + +Function : bl2u_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl2u_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to perform any platform initialization +specific to BL2U. + +In Arm standard platforms, this function performs security setup, including +configuration of the TrustZone controller to allow non-secure masters access +to most of DRAM. Part of DRAM is reserved for secure world use. + +Function : bl2u_plat_handle_scp_bl2u() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This function is used to perform any platform-specific actions required to +handle the SCP firmware. Typically it transfers the image into SCP memory using +a platform-specific protocol and waits until SCP executes it and signals to the +Application Processor (AP) for BL2U execution to continue. + +This function returns 0 on success, a negative error code otherwise. +This function is included if SCP_BL2U_BASE is defined. + +Boot Loader Stage 3-1 (BL31) +---------------------------- + +During cold boot, the BL31 stage is executed only by the primary CPU. This is +determined in BL1 using the ``platform_is_primary_cpu()`` function. BL1 passes +control to BL31 at ``BL31_BASE``. During warm boot, BL31 is executed by all +CPUs. BL31 executes at EL3 and is responsible for: + +#. Re-initializing all architectural and platform state. Although BL1 performs + some of this initialization, BL31 remains resident in EL3 and must ensure + that EL3 architectural and platform state is completely initialized. It + should make no assumptions about the system state when it receives control. + +#. Passing control to a normal world BL image, pre-loaded at a platform- + specific address by BL2. On ARM platforms, BL31 uses the ``bl_params`` list + populated by BL2 in memory to do this. + +#. Providing runtime firmware services. Currently, BL31 only implements a + subset of the Power State Coordination Interface (PSCI) API as a runtime + service. See Section 3.3 below for details of porting the PSCI + implementation. + +#. Optionally passing control to the BL32 image, pre-loaded at a platform- + specific address by BL2. BL31 exports a set of APIs that allow runtime + services to specify the security state in which the next image should be + executed and run the corresponding image. On ARM platforms, BL31 uses the + ``bl_params`` list populated by BL2 in memory to do this. + +If BL31 is a reset vector, It also needs to handle the reset as specified in +section 2.2 before the tasks described above. + +The following functions must be implemented by the platform port to enable BL31 +to perform the above tasks. + +Function : bl31_early_platform_setup2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. BL2 can pass 4 arguments to BL31 and these arguments are +platform specific. + +In Arm standard platforms, the arguments received are : + + arg0 - The pointer to the head of `bl_params_t` list + which is list of executable images following BL31, + + arg1 - Points to load address of SOC_FW_CONFIG if present + + arg2 - Points to load address of HW_CONFIG if present + + arg3 - A special value to verify platform parameters from BL2 to BL31. Not + used in release builds. + +The function runs through the `bl_param_t` list and extracts the entry point +information for BL32 and BL33. It also performs the following: + +- Initialize a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL31. + +- Enable issuing of snoop and DVM (Distributed Virtual Memory) requests to the + CCI slave interface corresponding to the cluster that includes the primary + CPU. + +Function : bl31_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On Arm standard platforms, this function enables the MMU. + +Function : bl31_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl31_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to complete platform initialization so that both +BL31 runtime services and normal world software can function correctly. + +On Arm standard platforms, this function does the following: + +- Initialize the generic interrupt controller. + + Depending on the GIC driver selected by the platform, the appropriate GICv2 + or GICv3 initialization will be done, which mainly consists of: + + - Enable secure interrupts in the GIC CPU interface. + - Disable the legacy interrupt bypass mechanism. + - Configure the priority mask register to allow interrupts of all priorities + to be signaled to the CPU interface. + - Mark SGIs 8-15 and the other secure interrupts on the platform as secure. + - Target all secure SPIs to CPU0. + - Enable these secure interrupts in the GIC distributor. + - Configure all other interrupts as non-secure. + - Enable signaling of secure interrupts in the GIC distributor. + +- Enable system-level implementation of the generic timer counter through the + memory mapped interface. + +- Grant access to the system counter timer module + +- Initialize the power controller device. + + In particular, initialise the locks that prevent concurrent accesses to the + power controller device. + +Function : bl31_plat_runtime_setup() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +The purpose of this function is allow the platform to perform any BL31 runtime +setup just prior to BL31 exit during cold boot. The default weak +implementation of this function will invoke ``console_switch_state()`` to switch +console output to consoles marked for use in the ``runtime`` state. + +Function : bl31_plat_get_next_image_ep_info() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : entry_point_info * + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. + +This function is called by ``bl31_main()`` to retrieve information provided by +BL2 for the next image in the security state specified by the argument. BL31 +uses this information to pass control to that image in the specified security +state. This function must return a pointer to the ``entry_point_info`` structure +(that was copied during ``bl31_early_platform_setup()``) if the image exists. It +should return NULL otherwise. + +Function : bl31_plat_enable_mmu [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : void + +This function enables the MMU. The boot code calls this function with MMU and +caches disabled. This function should program necessary registers to enable +translation, and upon return, the MMU on the calling PE must be enabled. + +The function must honor flags passed in the first argument. These flags are +defined by the translation library, and can be found in the file +``include/lib/xlat_tables/xlat_mmu_helpers.h``. + +On DynamIQ systems, this function must not use stack while enabling MMU, which +is how the function in xlat table library version 2 is implemented. + +Function : plat_init_apiakey [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint64_t * + +This function populates the ``plat_apiakey`` array that contains the values used +to set the ``APIAKey{Hi,Lo}_EL1`` registers. It returns a pointer to this array. + +The value should be obtained from a reliable source of randomness. + +This function is only needed if ARMv8.3 pointer authentication is used in the +Trusted Firmware by building with ``ENABLE_PAUTH=1``. + +Function : plat_get_syscnt_freq2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function is used by the architecture setup code to retrieve the counter +frequency for the CPU's generic timer. This value will be programmed into the +``CNTFRQ_EL0`` register. In Arm standard platforms, it returns the base frequency +of the system counter, which is retrieved from the first entry in the frequency +modes table. + +#define : PLAT_PERCPU_BAKERY_LOCK_SIZE [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When ``USE_COHERENT_MEM = 0``, this constant defines the total memory (in +bytes) aligned to the cache line boundary that should be allocated per-cpu to +accommodate all the bakery locks. + +If this constant is not defined when ``USE_COHERENT_MEM = 0``, the linker +calculates the size of the ``bakery_lock`` input section, aligns it to the +nearest ``CACHE_WRITEBACK_GRANULE``, multiplies it with ``PLATFORM_CORE_COUNT`` +and stores the result in a linker symbol. This constant prevents a platform +from relying on the linker and provide a more efficient mechanism for +accessing per-cpu bakery lock information. + +If this constant is defined and its value is not equal to the value +calculated by the linker then a link time assertion is raised. A compile time +assertion is raised if the value of the constant is not aligned to the cache +line boundary. + +SDEI porting requirements +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The SDEI dispatcher requires the platform to provide the following macros +and functions, of which some are optional, and some others mandatory. + +Macros +...... + +Macro: PLAT_SDEI_NORMAL_PRI [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This macro must be defined to the EL3 exception priority level associated with +Normal SDEI events on the platform. This must have a higher value (therefore of +lower priority) than ``PLAT_SDEI_CRITICAL_PRI``. + +Macro: PLAT_SDEI_CRITICAL_PRI [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This macro must be defined to the EL3 exception priority level associated with +Critical SDEI events on the platform. This must have a lower value (therefore of +higher priority) than ``PLAT_SDEI_NORMAL_PRI``. + +**Note**: SDEI exception priorities must be the lowest among Secure priorities. +Among the SDEI exceptions, Critical SDEI priority must be higher than Normal +SDEI priority. + +Functions +......... + +Function: int plat_sdei_validate_entry_point(uintptr_t ep) [optional] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: uintptr_t + Return: int + +This function validates the address of client entry points provided for both +event registration and *Complete and Resume* SDEI calls. The function takes one +argument, which is the address of the handler the SDEI client requested to +register. The function must return ``0`` for successful validation, or ``-1`` +upon failure. + +The default implementation always returns ``0``. On Arm platforms, this function +is implemented to translate the entry point to physical address, and further to +ensure that the address is located in Non-secure DRAM. + +Function: void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr) [optional] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: uint64_t + Argument: unsigned int + Return: void + +SDEI specification requires that a PE comes out of reset with the events masked. +The client therefore is expected to call ``PE_UNMASK`` to unmask SDEI events on +the PE. No SDEI events can be dispatched until such time. + +Should a PE receive an interrupt that was bound to an SDEI event while the +events are masked on the PE, the dispatcher implementation invokes the function +``plat_sdei_handle_masked_trigger``. The MPIDR of the PE that received the +interrupt and the interrupt ID are passed as parameters. + +The default implementation only prints out a warning message. + +Power State Coordination Interface (in BL31) +-------------------------------------------- + +The TF-A implementation of the PSCI API is based around the concept of a +*power domain*. A *power domain* is a CPU or a logical group of CPUs which +share some state on which power management operations can be performed as +specified by `PSCI`_. Each CPU in the system is assigned a cpu index which is +a unique number between ``0`` and ``PLATFORM_CORE_COUNT - 1``. The +*power domains* are arranged in a hierarchical tree structure and each +*power domain* can be identified in a system by the cpu index of any CPU that +is part of that domain and a *power domain level*. A processing element (for +example, a CPU) is at level 0. If the *power domain* node above a CPU is a +logical grouping of CPUs that share some state, then level 1 is that group of +CPUs (for example, a cluster), and level 2 is a group of clusters (for +example, the system). More details on the power domain topology and its +organization can be found in `Power Domain Topology Design`_. + +BL31's platform initialization code exports a pointer to the platform-specific +power management operations required for the PSCI implementation to function +correctly. This information is populated in the ``plat_psci_ops`` structure. The +PSCI implementation calls members of the ``plat_psci_ops`` structure for performing +power management operations on the power domains. For example, the target +CPU is specified by its ``MPIDR`` in a PSCI ``CPU_ON`` call. The ``pwr_domain_on()`` +handler (if present) is called for the CPU power domain. + +The ``power-state`` parameter of a PSCI ``CPU_SUSPEND`` call can be used to +describe composite power states specific to a platform. The PSCI implementation +defines a generic representation of the power-state parameter, which is an +array of local power states where each index corresponds to a power domain +level. Each entry contains the local power state the power domain at that power +level could enter. It depends on the ``validate_power_state()`` handler to +convert the power-state parameter (possibly encoding a composite power state) +passed in a PSCI ``CPU_SUSPEND`` call to this representation. + +The following functions form part of platform port of PSCI functionality. + +Function : plat_psci_stat_accounting_start() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_power_state_t * + Return : void + +This is an optional hook that platforms can implement for residency statistics +accounting before entering a low power state. The ``pwr_domain_state`` field of +``state_info`` (first argument) can be inspected if stat accounting is done +differently at CPU level versus higher levels. As an example, if the element at +index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down +state, special hardware logic may be programmed in order to keep track of the +residency statistics. For higher levels (array indices > 0), the residency +statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the +default implementation will use PMF to capture timestamps. + +Function : plat_psci_stat_accounting_stop() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_power_state_t * + Return : void + +This is an optional hook that platforms can implement for residency statistics +accounting after exiting from a low power state. The ``pwr_domain_state`` field +of ``state_info`` (first argument) can be inspected if stat accounting is done +differently at CPU level versus higher levels. As an example, if the element at +index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down +state, special hardware logic may be programmed in order to keep track of the +residency statistics. For higher levels (array indices > 0), the residency +statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the +default implementation will use PMF to capture timestamps. + +Function : plat_psci_stat_get_residency() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const psci_power_state_t *, int + Return : u_register_t + +This is an optional interface that is is invoked after resuming from a low power +state and provides the time spent resident in that low power state by the power +domain at a particular power domain level. When a CPU wakes up from suspend, +all its parent power domain levels are also woken up. The generic PSCI code +invokes this function for each parent power domain that is resumed and it +identified by the ``lvl`` (first argument) parameter. The ``state_info`` (second +argument) describes the low power state that the power domain has resumed from. +The current CPU is the first CPU in the power domain to resume from the low +power state and the ``last_cpu_idx`` (third parameter) is the index of the last +CPU in the power domain to suspend and may be needed to calculate the residency +for that power domain. + +Function : plat_get_target_pwr_state() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const plat_local_state_t *, unsigned int + Return : plat_local_state_t + +The PSCI generic code uses this function to let the platform participate in +state coordination during a power management operation. The function is passed +a pointer to an array of platform specific local power state ``states`` (second +argument) which contains the requested power state for each CPU at a particular +power domain level ``lvl`` (first argument) within the power domain. The function +is expected to traverse this array of upto ``ncpus`` (third argument) and return +a coordinated target power state by the comparing all the requested power +states. The target power state should not be deeper than any of the requested +power states. + +A weak definition of this API is provided by default wherein it assumes +that the platform assigns a local state value in order of increasing depth +of the power state i.e. for two power states X & Y, if X < Y +then X represents a shallower power state than Y. As a result, the +coordinated target local power state for a power domain will be the minimum +of the requested local power state values. + +Function : plat_get_power_domain_tree_desc() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : const unsigned char * + +This function returns a pointer to the byte array containing the power domain +topology tree description. The format and method to construct this array are +described in `Power Domain Topology Design`_. The BL31 PSCI initialization code +requires this array to be described by the platform, either statically or +dynamically, to initialize the power domain topology tree. In case the array +is populated dynamically, then plat_core_pos_by_mpidr() and +plat_my_core_pos() should also be implemented suitably so that the topology +tree description matches the CPU indices returned by these APIs. These APIs +together form the platform interface for the PSCI topology framework. + +Function : plat_setup_psci_ops() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t, const plat_psci_ops ** + Return : int + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only +called by the primary CPU. + +This function is called by PSCI initialization code. Its purpose is to let +the platform layer know about the warm boot entrypoint through the +``sec_entrypoint`` (first argument) and to export handler routines for +platform-specific psci power management actions by populating the passed +pointer with a pointer to BL31's private ``plat_psci_ops`` structure. + +A description of each member of this structure is given below. Please refer to +the Arm FVP specific implementation of these handlers in +`plat/arm/board/fvp/fvp_pm.c`_ as an example. For each PSCI function that the +platform wants to support, the associated operation or operations in this +structure must be provided and implemented (Refer section 4 of +`Firmware Design`_ for the PSCI API supported in TF-A). To disable a PSCI +function in a platform port, the operation should be removed from this +structure instead of providing an empty implementation. + +plat_psci_ops.cpu_standby() +........................... + +Perform the platform-specific actions to enter the standby state for a cpu +indicated by the passed argument. This provides a fast path for CPU standby +wherein overheads of PSCI state management and lock acquisition is avoided. +For this handler to be invoked by the PSCI ``CPU_SUSPEND`` API implementation, +the suspend state type specified in the ``power-state`` parameter should be +STANDBY and the target power domain level specified should be the CPU. The +handler should put the CPU into a low power retention state (usually by +issuing a wfi instruction) and ensure that it can be woken up from that +state by a normal interrupt. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_on() +............................. + +Perform the platform specific actions to power on a CPU, specified +by the ``MPIDR`` (first argument). The generic code expects the platform to +return PSCI_E_SUCCESS on success or PSCI_E_INTERN_FAIL for any failure. + +plat_psci_ops.pwr_domain_off() +.............................. + +Perform the platform specific actions to prepare to power off the calling CPU +and its higher parent power domain levels as indicated by the ``target_state`` +(first argument). It is called by the PSCI ``CPU_OFF`` API implementation. + +The ``target_state`` encodes the platform coordinated target local power states +for the CPU power domain and its parent power domain levels. The handler +needs to perform power management operation corresponding to the local state +at each power level. + +For this handler, the local power state for the CPU power domain will be a +power down state where as it could be either power down, retention or run state +for the higher power domain levels depending on the result of state +coordination. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_suspend_pwrdown_early() [optional] +........................................................... + +This optional function may be used as a performance optimization to replace +or complement pwr_domain_suspend() on some platforms. Its calling semantics +are identical to pwr_domain_suspend(), except the PSCI implementation only +calls this function when suspending to a power down state, and it guarantees +that data caches are enabled. + +When HW_ASSISTED_COHERENCY = 0, the PSCI implementation disables data caches +before calling pwr_domain_suspend(). If the target_state corresponds to a +power down state and it is safe to perform some or all of the platform +specific actions in that function with data caches enabled, it may be more +efficient to move those actions to this function. When HW_ASSISTED_COHERENCY += 1, data caches remain enabled throughout, and so there is no advantage to +moving platform specific actions to this function. + +plat_psci_ops.pwr_domain_suspend() +.................................. + +Perform the platform specific actions to prepare to suspend the calling +CPU and its higher parent power domain levels as indicated by the +``target_state`` (first argument). It is called by the PSCI ``CPU_SUSPEND`` +API implementation. + +The ``target_state`` has a similar meaning as described in +the ``pwr_domain_off()`` operation. It encodes the platform coordinated +target local power states for the CPU power domain and its parent +power domain levels. The handler needs to perform power management operation +corresponding to the local state at each power level. The generic code +expects the handler to succeed. + +The difference between turning a power domain off versus suspending it is that +in the former case, the power domain is expected to re-initialize its state +when it is next powered on (see ``pwr_domain_on_finish()``). In the latter +case, the power domain is expected to save enough state so that it can resume +execution by restoring this state when its powered on (see +``pwr_domain_suspend_finish()``). + +When suspending a core, the platform can also choose to power off the GICv3 +Redistributor and ITS through an implementation-defined sequence. To achieve +this safely, the ITS context must be saved first. The architectural part is +implemented by the ``gicv3_its_save_disable()`` helper, but most of the needed +sequence is implementation defined and it is therefore the responsibility of +the platform code to implement the necessary sequence. Then the GIC +Redistributor context can be saved using the ``gicv3_rdistif_save()`` helper. +Powering off the Redistributor requires the implementation to support it and it +is the responsibility of the platform code to execute the right implementation +defined sequence. + +When a system suspend is requested, the platform can also make use of the +``gicv3_distif_save()`` helper to save the context of the GIC Distributor after +it has saved the context of the Redistributors and ITS of all the cores in the +system. The context of the Distributor can be large and may require it to be +allocated in a special area if it cannot fit in the platform's global static +data, for example in DRAM. The Distributor can then be powered down using an +implementation-defined sequence. + +plat_psci_ops.pwr_domain_pwr_down_wfi() +....................................... + +This is an optional function and, if implemented, is expected to perform +platform specific actions including the ``wfi`` invocation which allows the +CPU to powerdown. Since this function is invoked outside the PSCI locks, +the actions performed in this hook must be local to the CPU or the platform +must ensure that races between multiple CPUs cannot occur. + +The ``target_state`` has a similar meaning as described in the ``pwr_domain_off()`` +operation and it encodes the platform coordinated target local power states for +the CPU power domain and its parent power domain levels. This function must +not return back to the caller. + +If this function is not implemented by the platform, PSCI generic +implementation invokes ``psci_power_down_wfi()`` for power down. + +plat_psci_ops.pwr_domain_on_finish() +.................................... + +This function is called by the PSCI implementation after the calling CPU is +powered on and released from reset in response to an earlier PSCI ``CPU_ON`` call. +It performs the platform-specific setup required to initialize enough state for +this CPU to enter the normal world and also provide secure runtime firmware +services. + +The ``target_state`` (first argument) is the prior state of the power domains +immediately before the CPU was turned on. It indicates which power domains +above the CPU might require initialization due to having previously been in +low power states. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_suspend_finish() +......................................... + +This function is called by the PSCI implementation after the calling CPU is +powered on and released from reset in response to an asynchronous wakeup +event, for example a timer interrupt that was programmed by the CPU during the +``CPU_SUSPEND`` call or ``SYSTEM_SUSPEND`` call. It performs the platform-specific +setup required to restore the saved state for this CPU to resume execution +in the normal world and also provide secure runtime firmware services. + +The ``target_state`` (first argument) has a similar meaning as described in +the ``pwr_domain_on_finish()`` operation. The generic code expects the platform +to succeed. + +If the Distributor, Redistributors or ITS have been powered off as part of a +suspend, their context must be restored in this function in the reverse order +to how they were saved during suspend sequence. + +plat_psci_ops.system_off() +.......................... + +This function is called by PSCI implementation in response to a ``SYSTEM_OFF`` +call. It performs the platform-specific system poweroff sequence after +notifying the Secure Payload Dispatcher. + +plat_psci_ops.system_reset() +............................ + +This function is called by PSCI implementation in response to a ``SYSTEM_RESET`` +call. It performs the platform-specific system reset sequence after +notifying the Secure Payload Dispatcher. + +plat_psci_ops.validate_power_state() +.................................... + +This function is called by the PSCI implementation during the ``CPU_SUSPEND`` +call to validate the ``power_state`` parameter of the PSCI API and if valid, +populate it in ``req_state`` (second argument) array as power domain level +specific local states. If the ``power_state`` is invalid, the platform must +return PSCI_E_INVALID_PARAMS as error, which is propagated back to the +normal world PSCI client. + +plat_psci_ops.validate_ns_entrypoint() +...................................... + +This function is called by the PSCI implementation during the ``CPU_SUSPEND``, +``SYSTEM_SUSPEND`` and ``CPU_ON`` calls to validate the non-secure ``entry_point`` +parameter passed by the normal world. If the ``entry_point`` is invalid, +the platform must return PSCI_E_INVALID_ADDRESS as error, which is +propagated back to the normal world PSCI client. + +plat_psci_ops.get_sys_suspend_power_state() +........................................... + +This function is called by the PSCI implementation during the ``SYSTEM_SUSPEND`` +call to get the ``req_state`` parameter from platform which encodes the power +domain level specific local states to suspend to system affinity level. The +``req_state`` will be utilized to do the PSCI state coordination and +``pwr_domain_suspend()`` will be invoked with the coordinated target state to +enter system suspend. + +plat_psci_ops.get_pwr_lvl_state_idx() +..................................... + +This is an optional function and, if implemented, is invoked by the PSCI +implementation to convert the ``local_state`` (first argument) at a specified +``pwr_lvl`` (second argument) to an index between 0 and +``PLAT_MAX_PWR_LVL_STATES`` - 1. This function is only needed if the platform +supports more than two local power states at each power domain level, that is +``PLAT_MAX_PWR_LVL_STATES`` is greater than 2, and needs to account for these +local power states. + +plat_psci_ops.translate_power_state_by_mpidr() +.............................................. + +This is an optional function and, if implemented, verifies the ``power_state`` +(second argument) parameter of the PSCI API corresponding to a target power +domain. The target power domain is identified by using both ``MPIDR`` (first +argument) and the power domain level encoded in ``power_state``. The power domain +level specific local states are to be extracted from ``power_state`` and be +populated in the ``output_state`` (third argument) array. The functionality +is similar to the ``validate_power_state`` function described above and is +envisaged to be used in case the validity of ``power_state`` depend on the +targeted power domain. If the ``power_state`` is invalid for the targeted power +domain, the platform must return PSCI_E_INVALID_PARAMS as error. If this +function is not implemented, then the generic implementation relies on +``validate_power_state`` function to translate the ``power_state``. + +This function can also be used in case the platform wants to support local +power state encoding for ``power_state`` parameter of PSCI_STAT_COUNT/RESIDENCY +APIs as described in Section 5.18 of `PSCI`_. + +plat_psci_ops.get_node_hw_state() +................................. + +This is an optional function. If implemented this function is intended to return +the power state of a node (identified by the first parameter, the ``MPIDR``) in +the power domain topology (identified by the second parameter, ``power_level``), +as retrieved from a power controller or equivalent component on the platform. +Upon successful completion, the implementation must map and return the final +status among ``HW_ON``, ``HW_OFF`` or ``HW_STANDBY``. Upon encountering failures, it +must return either ``PSCI_E_INVALID_PARAMS`` or ``PSCI_E_NOT_SUPPORTED`` as +appropriate. + +Implementations are not expected to handle ``power_levels`` greater than +``PLAT_MAX_PWR_LVL``. + +plat_psci_ops.system_reset2() +............................. + +This is an optional function. If implemented this function is +called during the ``SYSTEM_RESET2`` call to perform a reset +based on the first parameter ``reset_type`` as specified in +`PSCI`_. The parameter ``cookie`` can be used to pass additional +reset information. If the ``reset_type`` is not supported, the +function must return ``PSCI_E_NOT_SUPPORTED``. For architectural +resets, all failures must return ``PSCI_E_INVALID_PARAMETERS`` +and vendor reset can return other PSCI error codes as defined +in `PSCI`_. On success this function will not return. + +plat_psci_ops.write_mem_protect() +................................. + +This is an optional function. If implemented it enables or disables the +``MEM_PROTECT`` functionality based on the value of ``val``. +A non-zero value enables ``MEM_PROTECT`` and a value of zero +disables it. Upon encountering failures it must return a negative value +and on success it must return 0. + +plat_psci_ops.read_mem_protect() +................................ + +This is an optional function. If implemented it returns the current +state of ``MEM_PROTECT`` via the ``val`` parameter. Upon encountering +failures it must return a negative value and on success it must +return 0. + +plat_psci_ops.mem_protect_chk() +............................... + +This is an optional function. If implemented it checks if a memory +region defined by a base address ``base`` and with a size of ``length`` +bytes is protected by ``MEM_PROTECT``. If the region is protected +then it must return 0, otherwise it must return a negative number. + +Interrupt Management framework (in BL31) +---------------------------------------- + +BL31 implements an Interrupt Management Framework (IMF) to manage interrupts +generated in either security state and targeted to EL1 or EL2 in the non-secure +state or EL3/S-EL1 in the secure state. The design of this framework is +described in the `IMF Design Guide`_ + +A platform should export the following APIs to support the IMF. The following +text briefly describes each API and its implementation in Arm standard +platforms. The API implementation depends upon the type of interrupt controller +present in the platform. Arm standard platform layer supports both +`Arm Generic Interrupt Controller version 2.0 (GICv2)`_ +and `3.0 (GICv3)`_. Juno builds the Arm platform layer to use GICv2 and the +FVP can be configured to use either GICv2 or GICv3 depending on the build flag +``FVP_USE_GIC_DRIVER`` (See FVP platform specific build options in +`User Guide`_ for more details). + +See also: `Interrupt Controller Abstraction APIs`__. + +.. __: ../design/platform-interrupt-controller-API.rst + +Function : plat_interrupt_type_to_line() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t, uint32_t + Return : uint32_t + +The Arm processor signals an interrupt exception either through the IRQ or FIQ +interrupt line. The specific line that is signaled depends on how the interrupt +controller (IC) reports different interrupt types from an execution context in +either security state. The IMF uses this API to determine which interrupt line +the platform IC uses to signal each type of interrupt supported by the framework +from a given security state. This API must be invoked at EL3. + +The first parameter will be one of the ``INTR_TYPE_*`` values (see +`IMF Design Guide`_) indicating the target type of the interrupt, the second parameter is the +security state of the originating execution context. The return result is the +bit position in the ``SCR_EL3`` register of the respective interrupt trap: IRQ=1, +FIQ=2. + +In the case of Arm standard platforms using GICv2, S-EL1 interrupts are +configured as FIQs and Non-secure interrupts as IRQs from either security +state. + +In the case of Arm standard platforms using GICv3, the interrupt line to be +configured depends on the security state of the execution context when the +interrupt is signalled and are as follows: + +- The S-EL1 interrupts are signaled as IRQ in S-EL0/1 context and as FIQ in + NS-EL0/1/2 context. +- The Non secure interrupts are signaled as FIQ in S-EL0/1 context and as IRQ + in the NS-EL0/1/2 context. +- The EL3 interrupts are signaled as FIQ in both S-EL0/1 and NS-EL0/1/2 + context. + +Function : plat_ic_get_pending_interrupt_type() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API returns the type of the highest priority pending interrupt at the +platform IC. The IMF uses the interrupt type to retrieve the corresponding +handler function. ``INTR_TYPE_INVAL`` is returned when there is no interrupt +pending. The valid interrupt types that can be returned are ``INTR_TYPE_EL3``, +``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``. This API must be invoked at EL3. + +In the case of Arm standard platforms using GICv2, the *Highest Priority +Pending Interrupt Register* (``GICC_HPPIR``) is read to determine the id of +the pending interrupt. The type of interrupt depends upon the id value as +follows. + +#. id < 1022 is reported as a S-EL1 interrupt +#. id = 1022 is reported as a Non-secure interrupt. +#. id = 1023 is reported as an invalid interrupt type. + +In the case of Arm standard platforms using GICv3, the system register +``ICC_HPPIR0_EL1``, *Highest Priority Pending group 0 Interrupt Register*, +is read to determine the id of the pending interrupt. The type of interrupt +depends upon the id value as follows. + +#. id = ``PENDING_G1S_INTID`` (1020) is reported as a S-EL1 interrupt +#. id = ``PENDING_G1NS_INTID`` (1021) is reported as a Non-secure interrupt. +#. id = ``GIC_SPURIOUS_INTERRUPT`` (1023) is reported as an invalid interrupt type. +#. All other interrupt id's are reported as EL3 interrupt. + +Function : plat_ic_get_pending_interrupt_id() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API returns the id of the highest priority pending interrupt at the +platform IC. ``INTR_ID_UNAVAILABLE`` is returned when there is no interrupt +pending. + +In the case of Arm standard platforms using GICv2, the *Highest Priority +Pending Interrupt Register* (``GICC_HPPIR``) is read to determine the id of the +pending interrupt. The id that is returned by API depends upon the value of +the id read from the interrupt controller as follows. + +#. id < 1022. id is returned as is. +#. id = 1022. The *Aliased Highest Priority Pending Interrupt Register* + (``GICC_AHPPIR``) is read to determine the id of the non-secure interrupt. + This id is returned by the API. +#. id = 1023. ``INTR_ID_UNAVAILABLE`` is returned. + +In the case of Arm standard platforms using GICv3, if the API is invoked from +EL3, the system register ``ICC_HPPIR0_EL1``, *Highest Priority Pending Interrupt +group 0 Register*, is read to determine the id of the pending interrupt. The id +that is returned by API depends upon the value of the id read from the +interrupt controller as follows. + +#. id < ``PENDING_G1S_INTID`` (1020). id is returned as is. +#. id = ``PENDING_G1S_INTID`` (1020) or ``PENDING_G1NS_INTID`` (1021). The system + register ``ICC_HPPIR1_EL1``, *Highest Priority Pending Interrupt group 1 + Register* is read to determine the id of the group 1 interrupt. This id + is returned by the API as long as it is a valid interrupt id +#. If the id is any of the special interrupt identifiers, + ``INTR_ID_UNAVAILABLE`` is returned. + +When the API invoked from S-EL1 for GICv3 systems, the id read from system +register ``ICC_HPPIR1_EL1``, *Highest Priority Pending group 1 Interrupt +Register*, is returned if is not equal to GIC_SPURIOUS_INTERRUPT (1023) else +``INTR_ID_UNAVAILABLE`` is returned. + +Function : plat_ic_acknowledge_interrupt() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API is used by the CPU to indicate to the platform IC that processing of +the highest pending interrupt has begun. It should return the raw, unmodified +value obtained from the interrupt controller when acknowledging an interrupt. +The actual interrupt number shall be extracted from this raw value using the API +`plat_ic_get_interrupt_id()`__. + +.. __: ../design/platform-interrupt-controller-API.rst#function-unsigned-int-plat-ic-get-interrupt-id-unsigned-int-raw-optional + +This function in Arm standard platforms using GICv2, reads the *Interrupt +Acknowledge Register* (``GICC_IAR``). This changes the state of the highest +priority pending interrupt from pending to active in the interrupt controller. +It returns the value read from the ``GICC_IAR``, unmodified. + +In the case of Arm standard platforms using GICv3, if the API is invoked +from EL3, the function reads the system register ``ICC_IAR0_EL1``, *Interrupt +Acknowledge Register group 0*. If the API is invoked from S-EL1, the function +reads the system register ``ICC_IAR1_EL1``, *Interrupt Acknowledge Register +group 1*. The read changes the state of the highest pending interrupt from +pending to active in the interrupt controller. The value read is returned +unmodified. + +The TSP uses this API to start processing of the secure physical timer +interrupt. + +Function : plat_ic_end_of_interrupt() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : void + +This API is used by the CPU to indicate to the platform IC that processing of +the interrupt corresponding to the id (passed as the parameter) has +finished. The id should be the same as the id returned by the +``plat_ic_acknowledge_interrupt()`` API. + +Arm standard platforms write the id to the *End of Interrupt Register* +(``GICC_EOIR``) in case of GICv2, and to ``ICC_EOIR0_EL1`` or ``ICC_EOIR1_EL1`` +system register in case of GICv3 depending on where the API is invoked from, +EL3 or S-EL1. This deactivates the corresponding interrupt in the interrupt +controller. + +The TSP uses this API to finish processing of the secure physical timer +interrupt. + +Function : plat_ic_get_interrupt_type() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : uint32_t + +This API returns the type of the interrupt id passed as the parameter. +``INTR_TYPE_INVAL`` is returned if the id is invalid. If the id is valid, a valid +interrupt type (one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``) is +returned depending upon how the interrupt has been configured by the platform +IC. This API must be invoked at EL3. + +Arm standard platforms using GICv2 configures S-EL1 interrupts as Group0 interrupts +and Non-secure interrupts as Group1 interrupts. It reads the group value +corresponding to the interrupt id from the relevant *Interrupt Group Register* +(``GICD_IGROUPRn``). It uses the group value to determine the type of interrupt. + +In the case of Arm standard platforms using GICv3, both the *Interrupt Group +Register* (``GICD_IGROUPRn``) and *Interrupt Group Modifier Register* +(``GICD_IGRPMODRn``) is read to figure out whether the interrupt is configured +as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt. + +Crash Reporting mechanism (in BL31) +----------------------------------- + +BL31 implements a crash reporting mechanism which prints the various registers +of the CPU to enable quick crash analysis and debugging. This mechanism relies +on the platform implementing ``plat_crash_console_init``, +``plat_crash_console_putc`` and ``plat_crash_console_flush``. + +The file ``plat/common/aarch64/crash_console_helpers.S`` contains sample +implementation of all of them. Platforms may include this file to their +makefiles in order to benefit from them. By default, they will cause the crash +output to be routed over the normal console infrastructure and get printed on +consoles configured to output in crash state. ``console_set_scope()`` can be +used to control whether a console is used for crash output. +NOTE: Platforms are responsible for making sure that they only mark consoles for +use in the crash scope that are able to support this, i.e. that are written in +assembly and conform with the register clobber rules for putc() (x0-x2, x16-x17) +and flush() (x0-x3, x16-x17) crash callbacks. + +In some cases (such as debugging very early crashes that happen before the +normal boot console can be set up), platforms may want to control crash output +more explicitly. These platforms may instead provide custom implementations for +these. They are executed outside of a C environment and without a stack. Many +console drivers provide functions named ``console_xxx_core_init/putc/flush`` +that are designed to be used by these functions. See Arm platforms (like juno) +for an example of this. + +Function : plat_crash_console_init [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This API is used by the crash reporting mechanism to initialize the crash +console. It must only use the general purpose registers x0 through x7 to do the +initialization and returns 1 on success. + +Function : plat_crash_console_putc [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Return : int + +This API is used by the crash reporting mechanism to print a character on the +designated crash console. It must only use general purpose registers x1 and +x2 to do its work. The parameter and the return value are in general purpose +register x0. + +Function : plat_crash_console_flush [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This API is used by the crash reporting mechanism to force write of all buffered +data on the designated crash console. It should only use general purpose +registers x0 through x5 to do its work. The return value is 0 on successful +completion; otherwise the return value is -1. + +External Abort handling and RAS Support +--------------------------------------- + +Function : plat_ea_handler +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : uint64_t + Argument : void * + Argument : void * + Argument : uint64_t + Return : void + +This function is invoked by the RAS framework for the platform to handle an +External Abort received at EL3. The intention of the function is to attempt to +resolve the cause of External Abort and return; if that's not possible, to +initiate orderly shutdown of the system. + +The first parameter (``int ea_reason``) indicates the reason for External Abort. +Its value is one of ``ERROR_EA_*`` constants defined in ``ea_handle.h``. + +The second parameter (``uint64_t syndrome``) is the respective syndrome +presented to EL3 after having received the External Abort. Depending on the +nature of the abort (as can be inferred from the ``ea_reason`` parameter), this +can be the content of either ``ESR_EL3`` or ``DISR_EL1``. + +The third parameter (``void *cookie``) is unused for now. The fourth parameter +(``void *handle``) is a pointer to the preempted context. The fifth parameter +(``uint64_t flags``) indicates the preempted security state. These parameters +are received from the top-level exception handler. + +If ``RAS_EXTENSION`` is set to ``1``, the default implementation of this +function iterates through RAS handlers registered by the platform. If any of the +RAS handlers resolve the External Abort, no further action is taken. + +If ``RAS_EXTENSION`` is set to ``0``, or if none of the platform RAS handlers +could resolve the External Abort, the default implementation prints an error +message, and panics. + +Function : plat_handle_uncontainable_ea +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : uint64_t + Return : void + +This function is invoked by the RAS framework when an External Abort of +Uncontainable type is received at EL3. Due to the critical nature of +Uncontainable errors, the intention of this function is to initiate orderly +shutdown of the system, and is not expected to return. + +This function must be implemented in assembly. + +The first and second parameters are the same as that of ``plat_ea_handler``. + +The default implementation of this function calls +``report_unhandled_exception``. + +Function : plat_handle_double_fault +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : uint64_t + Return : void + +This function is invoked by the RAS framework when another External Abort is +received at EL3 while one is already being handled. I.e., a call to +``plat_ea_handler`` is outstanding. Due to its critical nature, the intention of +this function is to initiate orderly shutdown of the system, and is not expected +recover or return. + +This function must be implemented in assembly. + +The first and second parameters are the same as that of ``plat_ea_handler``. + +The default implementation of this function calls +``report_unhandled_exception``. + +Function : plat_handle_el3_ea +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Return : void + +This function is invoked when an External Abort is received while executing in +EL3. Due to its critical nature, the intention of this function is to initiate +orderly shutdown of the system, and is not expected recover or return. + +This function must be implemented in assembly. + +The default implementation of this function calls +``report_unhandled_exception``. + +Build flags +----------- + +There are some build flags which can be defined by the platform to control +inclusion or exclusion of certain BL stages from the FIP image. These flags +need to be defined in the platform makefile which will get included by the +build system. + +- **NEED_BL33** + By default, this flag is defined ``yes`` by the build system and ``BL33`` + build option should be supplied as a build option. The platform has the + option of excluding the BL33 image in the ``fip`` image by defining this flag + to ``no``. If any of the options ``EL3_PAYLOAD_BASE`` or ``PRELOADED_BL33_BASE`` + are used, this flag will be set to ``no`` automatically. + +C Library +--------- + +To avoid subtle toolchain behavioral dependencies, the header files provided +by the compiler are not used. The software is built with the ``-nostdinc`` flag +to ensure no headers are included from the toolchain inadvertently. Instead the +required headers are included in the TF-A source tree. The library only +contains those C library definitions required by the local implementation. If +more functionality is required, the needed library functions will need to be +added to the local implementation. + +Some C headers have been obtained from `FreeBSD`_ and `SCC`_, while others have +been written specifically for TF-A. Fome implementation files have been obtained +from `FreeBSD`_, others have been written specifically for TF-A as well. The +files can be found in ``include/lib/libc`` and ``lib/libc``. + +SCC can be found in http://www.simple-cc.org/. A copy of the `FreeBSD`_ sources +can be obtained from http://github.com/freebsd/freebsd. + +Storage abstraction layer +------------------------- + +In order to improve platform independence and portability an storage abstraction +layer is used to load data from non-volatile platform storage. + +Each platform should register devices and their drivers via the Storage layer. +These drivers then need to be initialized by bootloader phases as +required in their respective ``blx_platform_setup()`` functions. Currently +storage access is only required by BL1 and BL2 phases. The ``load_image()`` +function uses the storage layer to access non-volatile platform storage. + +It is mandatory to implement at least one storage driver. For the Arm +development platforms the Firmware Image Package (FIP) driver is provided as +the default means to load data from storage (see the "Firmware Image Package" +section in the `User Guide`_). The storage layer is described in the header file +``include/drivers/io/io_storage.h``. The implementation of the common library +is in ``drivers/io/io_storage.c`` and the driver files are located in +``drivers/io/``. + +Each IO driver must provide ``io_dev_*`` structures, as described in +``drivers/io/io_driver.h``. These are returned via a mandatory registration +function that is called on platform initialization. The semi-hosting driver +implementation in ``io_semihosting.c`` can be used as an example. + +The Storage layer provides mechanisms to initialize storage devices before +IO operations are called. The basic operations supported by the layer +include ``open()``, ``close()``, ``read()``, ``write()``, ``size()`` and ``seek()``. +Drivers do not have to implement all operations, but each platform must +provide at least one driver for a device capable of supporting generic +operations such as loading a bootloader image. + +The current implementation only allows for known images to be loaded by the +firmware. These images are specified by using their identifiers, as defined in +``include/plat/common/common_def.h`` (or a separate header file included from +there). The platform layer (``plat_get_image_source()``) then returns a reference +to a device and a driver-specific ``spec`` which will be understood by the driver +to allow access to the image data. + +The layer is designed in such a way that is it possible to chain drivers with +other drivers. For example, file-system drivers may be implemented on top of +physical block devices, both represented by IO devices with corresponding +drivers. In such a case, the file-system "binding" with the block device may +be deferred until the file-system device is initialised. + +The abstraction currently depends on structures being statically allocated +by the drivers and callers, as the system does not yet provide a means of +dynamically allocating memory. This may also have the affect of limiting the +amount of open resources per driver. + +-------------- + +*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* + +.. _include/plat/common/platform.h: ../include/plat/common/platform.h +.. _include/plat/arm/common/plat_arm.h: ../include/plat/arm/common/plat_arm.h%5D +.. _User Guide: user-guide.rst +.. _include/plat/common/common_def.h: ../include/plat/common/common_def.h +.. _include/plat/arm/common/arm_def.h: ../include/plat/arm/common/arm_def.h +.. _plat/common/aarch64/platform_mp_stack.S: ../plat/common/aarch64/platform_mp_stack.S +.. _plat/common/aarch64/platform_up_stack.S: ../plat/common/aarch64/platform_up_stack.S +.. _For example, define the build flag in platform.mk: PLAT_PL061_MAX_GPIOS%20:=%20160 +.. _Power Domain Topology Design: psci-pd-tree.rst +.. _include/common/bl_common.h: ../include/common/bl_common.h +.. _include/lib/aarch32/arch.h: ../include/lib/aarch32/arch.h +.. _Firmware Design: firmware-design.rst +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _plat/arm/board/fvp/fvp_pm.c: ../plat/arm/board/fvp/fvp_pm.c +.. _Platform compatibility policy: ./platform-compatibility-policy.rst +.. _IMF Design Guide: interrupt-framework-design.rst +.. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html +.. _3.0 (GICv3): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0069b/index.html +.. _FreeBSD: https://www.freebsd.org +.. _SCC: http://www.simple-cc.org/ diff --git a/docs/getting_started/psci-lib-integration-guide.rst b/docs/getting_started/psci-lib-integration-guide.rst new file mode 100644 index 0000000..c8cf3f3 --- /dev/null +++ b/docs/getting_started/psci-lib-integration-guide.rst @@ -0,0 +1,552 @@ +PSCI Library Integration guide for Armv8-A AArch32 systems +========================================================== + + + +.. contents:: + +This document describes the PSCI library interface with a focus on how to +integrate with a suitable Trusted OS for an Armv8-A AArch32 system. The PSCI +Library implements the PSCI Standard as described in `PSCI spec`_ and is meant +to be integrated with EL3 Runtime Software which invokes the PSCI Library +interface appropriately. **EL3 Runtime Software** refers to software executing +at the highest secure privileged mode, which is EL3 in AArch64 or Secure SVC/ +Monitor mode in AArch32, and provides runtime services to the non-secure world. +The runtime service request is made via SMC (Secure Monitor Call) and the call +must adhere to `SMCCC`_. In AArch32, EL3 Runtime Software may additionally +include Trusted OS functionality. A minimal AArch32 Secure Payload, SP-MIN, is +provided in Trusted Firmware-A (TF-A) to illustrate the usage and integration +of the PSCI library. The description of PSCI library interface and its +integration with EL3 Runtime Software in this document is targeted towards +AArch32 systems. + +Generic call sequence for PSCI Library interface (AArch32) +---------------------------------------------------------- + +The generic call sequence of PSCI Library interfaces (see +`PSCI Library Interface`_) during cold boot in AArch32 +system is described below: + +#. After cold reset, the EL3 Runtime Software performs its cold boot + initialization including the PSCI library pre-requisites mentioned in + `PSCI Library Interface`_, and also the necessary platform + setup. + +#. Call ``psci_setup()`` in Monitor mode. + +#. Optionally call ``psci_register_spd_pm_hook()`` to register callbacks to + do bookkeeping for the EL3 Runtime Software during power management. + +#. Call ``psci_prepare_next_non_secure_ctx()`` to initialize the non-secure CPU + context. + +#. Get the non-secure ``cpu_context_t`` for the current CPU by calling + ``cm_get_context()`` , then programming the registers in the non-secure + context and exiting to non-secure world. If the EL3 Runtime Software needs + additional configuration to be set for non-secure context, like routing + FIQs to the secure world, the values of the registers can be modified prior + to programming. See `PSCI CPU context management`_ for more + details on CPU context management. + +The generic call sequence of PSCI library interfaces during warm boot in +AArch32 systems is described below: + +#. After warm reset, the EL3 Runtime Software performs the necessary warm + boot initialization including the PSCI library pre-requisites mentioned in + `PSCI Library Interface`_ (Note that the Data cache + **must not** be enabled). + +#. Call ``psci_warmboot_entrypoint()`` in Monitor mode. This interface + initializes/restores the non-secure CPU context as well. + +#. Do step 5 of the cold boot call sequence described above. + +The generic call sequence of PSCI library interfaces on receipt of a PSCI SMC +on an AArch32 system is described below: + +#. On receipt of an SMC, save the register context as per `SMCCC`_. + +#. If the SMC function identifier corresponds to a SMC32 PSCI API, construct + the appropriate arguments and call the ``psci_smc_handler()`` interface. + The invocation may or may not return back to the caller depending on + whether the PSCI API resulted in power down of the CPU. + +#. If ``psci_smc_handler()`` returns, populate the return value in R0 (AArch32)/ + X0 (AArch64) and restore other registers as per `SMCCC`_. + +PSCI CPU context management +--------------------------- + +PSCI library is in charge of initializing/restoring the non-secure CPU system +registers according to `PSCI specification`_ during cold/warm boot. +This is referred to as ``PSCI CPU Context Management``. Registers that need to +be preserved across CPU power down/power up cycles are maintained in +``cpu_context_t`` data structure. The initialization of other non-secure CPU +system registers which do not require coordination with the EL3 Runtime +Software is done directly by the PSCI library (see ``cm_prepare_el3_exit()``). + +The EL3 Runtime Software is responsible for managing register context +during switch between Normal and Secure worlds. The register context to be +saved and restored depends on the mechanism used to trigger the world switch. +For example, if the world switch was triggered by an SMC call, then the +registers need to be saved and restored according to `SMCCC`_. In AArch64, +due to the tight integration with BL31, both BL31 and PSCI library +use the same ``cpu_context_t`` data structure for PSCI CPU context management +and register context management during world switch. This cannot be assumed +for AArch32 EL3 Runtime Software since most AArch32 Trusted OSes already implement +a mechanism for register context management during world switch. Hence, when +the PSCI library is integrated with a AArch32 EL3 Runtime Software, the +``cpu_context_t`` is stripped down for just PSCI CPU context management. + +During cold/warm boot, after invoking appropriate PSCI library interfaces, it +is expected that the EL3 Runtime Software will query the ``cpu_context_t`` and +write appropriate values to the corresponding system registers. This mechanism +resolves 2 additional problems for AArch32 EL3 Runtime Software: + +#. Values for certain system registers like SCR and SCTLR cannot be + unilaterally determined by PSCI library and need inputs from the EL3 + Runtime Software. Using ``cpu_context_t`` as an intermediary data store + allows EL3 Runtime Software to modify the register values appropriately + before programming them. + +#. The PSCI library provides appropriate LR and SPSR values (entrypoint + information) for exit into non-secure world. Using ``cpu_context_t`` as an + intermediary data store allows the EL3 Runtime Software to store these + values safely until it is ready for exit to non-secure world. + +Currently the ``cpu_context_t`` data structure for AArch32 stores the following +registers: R0 - R3, LR (R14), SCR, SPSR, SCTLR. + +The EL3 Runtime Software must implement accessors to get/set pointers +to CPU context ``cpu_context_t`` data and these are described in +`CPU Context management API`_. + +PSCI Library Interface +---------------------- + +The PSCI library implements the `PSCI Specification`_. The interfaces +to this library are declared in ``psci_lib.h`` and are as listed below: + +.. code:: c + + u_register_t psci_smc_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4, void *cookie, + void *handle, u_register_t flags); + int psci_setup(const psci_lib_args_t *lib_args); + void psci_warmboot_entrypoint(void); + void psci_register_spd_pm_hook(const spd_pm_ops_t *pm); + void psci_prepare_next_non_secure_ctx(entry_point_info_t *next_image_info); + +The CPU context data 'cpu_context_t' is programmed to the registers differently +when PSCI is integrated with an AArch32 EL3 Runtime Software compared to +when the PSCI is integrated with an AArch64 EL3 Runtime Software (BL31). For +example, in the case of AArch64, there is no need to retrieve ``cpu_context_t`` +data and program the registers as it will done implicitly as part of +``el3_exit``. The description below of the PSCI interfaces is targeted at +integration with an AArch32 EL3 Runtime Software. + +The PSCI library is responsible for initializing/restoring the non-secure world +to an appropriate state after boot and may choose to directly program the +non-secure system registers. The PSCI generic code takes care not to directly +modify any of the system registers affecting the secure world and instead +returns the values to be programmed to these registers via ``cpu_context_t``. +The EL3 Runtime Software is responsible for programming those registers and +can use the proposed values provided in the ``cpu_context_t``, modifying the +values if required. + +PSCI library needs the flexibility to access both secure and non-secure +copies of banked registers. Hence it needs to be invoked in Monitor mode +for AArch32 and in EL3 for AArch64. The NS bit in SCR (in AArch32) or SCR_EL3 +(in AArch64) must be set to 0. Additional requirements for the PSCI library +interfaces are: + +- Instruction cache must be enabled +- Both IRQ and FIQ must be masked for the current CPU +- The page tables must be setup and the MMU enabled +- The C runtime environment must be setup and stack initialized +- The Data cache must be enabled prior to invoking any of the PSCI library + interfaces except for ``psci_warmboot_entrypoint()``. For + ``psci_warmboot_entrypoint()``, if the build option ``HW_ASSISTED_COHERENCY`` + is enabled however, data caches are expected to be enabled. + +Further requirements for each interface can be found in the interface +description. + +Interface : psci_setup() +~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_lib_args_t *lib_args + Return : void + +This function is to be called by the primary CPU during cold boot before +any other interface to the PSCI library. It takes ``lib_args``, a const pointer +to ``psci_lib_args_t``, as the argument. The ``psci_lib_args_t`` is a versioned +structure and is declared in ``psci_lib.h`` header as follows: + +.. code:: c + + typedef struct psci_lib_args { + /* The version information of PSCI Library Interface */ + param_header_t h; + /* The warm boot entrypoint function */ + mailbox_entrypoint_t mailbox_ep; + } psci_lib_args_t; + +The first field ``h``, of ``param_header_t`` type, provides the version +information. The second field ``mailbox_ep`` is the warm boot entrypoint address +and is used to configure the platform mailbox. Helper macros are provided in +``psci_lib.h`` to construct the ``lib_args`` argument statically or during +runtime. Prior to calling the ``psci_setup()`` interface, the platform setup for +cold boot must have completed. Major actions performed by this interface are: + +- Initializes architecture. +- Initializes PSCI power domain and state coordination data structures. +- Calls ``plat_setup_psci_ops()`` with warm boot entrypoint ``mailbox_ep`` as + argument. +- Calls ``cm_set_context_by_index()`` (see + `CPU Context management API`_) for all the CPUs in the + platform + +Interface : psci_prepare_next_non_secure_ctx() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : entry_point_info_t *next_image_info + Return : void + +After ``psci_setup()`` and prior to exit to the non-secure world, this function +must be called by the EL3 Runtime Software to initialize the non-secure world +context. The non-secure world entrypoint information ``next_image_info`` (first +argument) will be used to determine the non-secure context. After this function +returns, the EL3 Runtime Software must retrieve the ``cpu_context_t`` (using +cm_get_context()) for the current CPU and program the registers prior to exit +to the non-secure world. + +Interface : psci_register_spd_pm_hook() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const spd_pm_ops_t * + Return : void + +As explained in `Secure payload power management callback`_, +the EL3 Runtime Software may want to perform some bookkeeping during power +management operations. This function is used to register the ``spd_pm_ops_t`` +(first argument) callbacks with the PSCI library which will be called +appropriately during power management. Calling this function is optional and +need to be called by the primary CPU during the cold boot sequence after +``psci_setup()`` has completed. + +Interface : psci_smc_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4, void *cookie, + void *handle, u_register_t flags + Return : u_register_t + +This function is the top level handler for SMCs which fall within the +PSCI service range specified in `SMCCC`_. The function ID ``smc_fid`` (first +argument) determines the PSCI API to be called. The ``x1`` to ``x4`` (2nd to 5th +arguments), are the values of the registers r1 - r4 (in AArch32) or x1 - x4 +(in AArch64) when the SMC is received. These are the arguments to PSCI API as +described in `PSCI spec`_. The 'flags' (8th argument) is a bit field parameter +and is detailed in 'smccc.h' header. It includes whether the call is from the +secure or non-secure world. The ``cookie`` (6th argument) and the ``handle`` +(7th argument) are not used and are reserved for future use. + +The return value from this interface is the return value from the underlying +PSCI API corresponding to ``smc_fid``. This function may not return back to the +caller if PSCI API causes power down of the CPU. In this case, when the CPU +wakes up, it will start execution from the warm reset address. + +Interface : psci_warmboot_entrypoint() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function performs the warm boot initialization/restoration as mandated by +`PSCI spec`_. For AArch32, on wakeup from power down the CPU resets to secure SVC +mode and the EL3 Runtime Software must perform the prerequisite initializations +mentioned at top of this section. This function must be called with Data cache +disabled (unless build option ``HW_ASSISTED_COHERENCY`` is enabled) but with MMU +initialized and enabled. The major actions performed by this function are: + +- Invalidates the stack and enables the data cache. +- Initializes architecture and PSCI state coordination. +- Restores/Initializes the peripheral drivers to the required state via + appropriate ``plat_psci_ops_t`` hooks +- Restores the EL3 Runtime Software context via appropriate ``spd_pm_ops_t`` + callbacks. +- Restores/Initializes the non-secure context and populates the + ``cpu_context_t`` for the current CPU. + +Upon the return of this function, the EL3 Runtime Software must retrieve the +non-secure ``cpu_context_t`` using ``cm_get_context()`` and program the registers +prior to exit to the non-secure world. + +EL3 Runtime Software dependencies +--------------------------------- + +The PSCI Library includes supporting frameworks like context management, +cpu operations (cpu_ops) and per-cpu data framework. Other helper library +functions like bakery locks and spin locks are also included in the library. +The dependencies which must be fulfilled by the EL3 Runtime Software +for integration with PSCI library are described below. + +General dependencies +~~~~~~~~~~~~~~~~~~~~ + +The PSCI library being a Multiprocessor (MP) implementation, EL3 Runtime +Software must provide an SMC handling framework capable of MP adhering to +`SMCCC`_ specification. + +The EL3 Runtime Software must also export cache maintenance primitives +and some helper utilities for assert, print and memory operations as listed +below. The TF-A source tree provides implementations for all +these functions but the EL3 Runtime Software may use its own implementation. + +**Functions : assert(), memcpy(), memset(), printf()** + +These must be implemented as described in ISO C Standard. + +**Function : flush_dcache_range()** + +:: + + Argument : uintptr_t addr, size_t size + Return : void + +This function cleans and invalidates (flushes) the data cache for memory +at address ``addr`` (first argument) address and of size ``size`` (second argument). + +**Function : inv_dcache_range()** + +:: + + Argument : uintptr_t addr, size_t size + Return : void + +This function invalidates (flushes) the data cache for memory at address +``addr`` (first argument) address and of size ``size`` (second argument). + +**Function : do_panic()** + +:: + + Argument : void + Return : void + +This function will be called by the PSCI library on encountering a critical +failure that cannot be recovered from. This function **must not** return. + +CPU Context management API +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The CPU context management data memory is statically allocated by PSCI library +in BSS section. The PSCI library requires the EL3 Runtime Software to implement +APIs to store and retrieve pointers to this CPU context data. SP-MIN +demonstrates how these APIs can be implemented but the EL3 Runtime Software can +choose a more optimal implementation (like dedicating the secure TPIDRPRW +system register (in AArch32) for storing these pointers). + +**Function : cm_set_context_by_index()** + +:: + + Argument : unsigned int cpu_idx, void *context, unsigned int security_state + Return : void + +This function is called during cold boot when the ``psci_setup()`` PSCI library +interface is called. + +This function must store the pointer to the CPU context data, ``context`` (2nd +argument), for the specified ``security_state`` (3rd argument) and CPU identified +by ``cpu_idx`` (first argument). The ``security_state`` will always be non-secure +when called by PSCI library and this argument is retained for compatibility +with BL31. The ``cpu_idx`` will correspond to the index returned by the +``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. + +The actual method of storing the ``context`` pointers is implementation specific. +For example, SP-MIN stores the pointers in the array ``sp_min_cpu_ctx_ptr`` +declared in ``sp_min_main.c``. + +**Function : cm_get_context()** + +:: + + Argument : uint32_t security_state + Return : void * + +This function must return the pointer to the ``cpu_context_t`` structure for +the specified ``security_state`` (first argument) for the current CPU. The caller +must ensure that ``cm_set_context_by_index`` is called first and the appropriate +context pointers are stored prior to invoking this API. The ``security_state`` +will always be non-secure when called by PSCI library and this argument +is retained for compatibility with BL31. + +**Function : cm_get_context_by_index()** + +:: + + Argument : unsigned int cpu_idx, unsigned int security_state + Return : void * + +This function must return the pointer to the ``cpu_context_t`` structure for +the specified ``security_state`` (second argument) for the CPU identified by +``cpu_idx`` (first argument). The caller must ensure that +``cm_set_context_by_index`` is called first and the appropriate context +pointers are stored prior to invoking this API. The ``security_state`` will +always be non-secure when called by PSCI library and this argument is +retained for compatibility with BL31. The ``cpu_idx`` will correspond to the +index returned by the ``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. + +Platform API +~~~~~~~~~~~~ + +The platform layer abstracts the platform-specific details from the generic +PSCI library. The following platform APIs/macros must be defined by the EL3 +Runtime Software for integration with the PSCI library. + +The mandatory platform APIs are: + +- plat_my_core_pos +- plat_core_pos_by_mpidr +- plat_get_syscnt_freq2 +- plat_get_power_domain_tree_desc +- plat_setup_psci_ops +- plat_reset_handler +- plat_panic_handler +- plat_get_my_stack + +The mandatory platform macros are: + +- PLATFORM_CORE_COUNT +- PLAT_MAX_PWR_LVL +- PLAT_NUM_PWR_DOMAINS +- CACHE_WRITEBACK_GRANULE +- PLAT_MAX_OFF_STATE +- PLAT_MAX_RET_STATE +- PLAT_MAX_PWR_LVL_STATES (optional) +- PLAT_PCPU_DATA_SIZE (optional) + +The details of these APIs/macros can be found in `Porting Guide`_. + +All platform specific operations for power management are done via +``plat_psci_ops_t`` callbacks registered by the platform when +``plat_setup_psci_ops()`` API is called. The description of each of +the callbacks in ``plat_psci_ops_t`` can be found in PSCI section of the +`Porting Guide`_. If any these callbacks are not registered, then the +PSCI API associated with that callback will not be supported by PSCI +library. + +Secure payload power management callback +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +During PSCI power management operations, the EL3 Runtime Software may +need to perform some bookkeeping, and PSCI library provides +``spd_pm_ops_t`` callbacks for this purpose. These hooks must be +populated and registered by using ``psci_register_spd_pm_hook()`` PSCI +library interface. + +Typical bookkeeping during PSCI power management calls include save/restore +of the EL3 Runtime Software context. Also if the EL3 Runtime Software makes +use of secure interrupts, then these interrupts must also be managed +appropriately during CPU power down/power up. Any secure interrupt targeted +to the current CPU must be disabled or re-targeted to other running CPU prior +to power down of the current CPU. During power up, these interrupt can be +enabled/re-targeted back to the current CPU. + +.. code:: c + + typedef struct spd_pm_ops { + void (*svc_on)(u_register_t target_cpu); + int32_t (*svc_off)(u_register_t __unused); + void (*svc_suspend)(u_register_t max_off_pwrlvl); + void (*svc_on_finish)(u_register_t __unused); + void (*svc_suspend_finish)(u_register_t max_off_pwrlvl); + int32_t (*svc_migrate)(u_register_t from_cpu, u_register_t to_cpu); + int32_t (*svc_migrate_info)(u_register_t *resident_cpu); + void (*svc_system_off)(void); + void (*svc_system_reset)(void); + } spd_pm_ops_t; + +A brief description of each callback is given below: + +- svc_on, svc_off, svc_on_finish + + The ``svc_on``, ``svc_off`` callbacks are called during PSCI_CPU_ON, + PSCI_CPU_OFF APIs respectively. The ``svc_on_finish`` is called when the + target CPU of PSCI_CPU_ON API powers up and executes the + ``psci_warmboot_entrypoint()`` PSCI library interface. + +- svc_suspend, svc_suspend_finish + + The ``svc_suspend`` callback is called during power down bu either + PSCI_SUSPEND or PSCI_SYSTEM_SUSPEND APIs. The ``svc_suspend_finish`` is + called when the CPU wakes up from suspend and executes the + ``psci_warmboot_entrypoint()`` PSCI library interface. The ``max_off_pwrlvl`` + (first parameter) denotes the highest power domain level being powered down + to or woken up from suspend. + +- svc_system_off, svc_system_reset + + These callbacks are called during PSCI_SYSTEM_OFF and PSCI_SYSTEM_RESET + PSCI APIs respectively. + +- svc_migrate_info + + This callback is called in response to PSCI_MIGRATE_INFO_TYPE or + PSCI_MIGRATE_INFO_UP_CPU APIs. The return value of this callback must + correspond to the return value of PSCI_MIGRATE_INFO_TYPE API as described + in `PSCI spec`_. If the secure payload is a Uniprocessor (UP) + implementation, then it must update the mpidr of the CPU it is resident in + via ``resident_cpu`` (first argument). The updates to ``resident_cpu`` is + ignored if the secure payload is a multiprocessor (MP) implementation. + +- svc_migrate + + This callback is only relevant if the secure payload in EL3 Runtime + Software is a Uniprocessor (UP) implementation and supports migration from + the current CPU ``from_cpu`` (first argument) to another CPU ``to_cpu`` + (second argument). This callback is called in response to PSCI_MIGRATE + API. This callback is never called if the secure payload is a + Multiprocessor (MP) implementation. + +CPU operations +~~~~~~~~~~~~~~ + +The CPU operations (cpu_ops) framework implement power down sequence specific +to the CPU and the details of which can be found in the +``CPU specific operations framework`` section of `Firmware Design`_. The TF-A +tree implements the ``cpu_ops`` for various supported CPUs and the EL3 Runtime +Software needs to include the required ``cpu_ops`` in its build. The start and +end of the ``cpu_ops`` descriptors must be exported by the EL3 Runtime Software +via the ``__CPU_OPS_START__`` and ``__CPU_OPS_END__`` linker symbols. + +The ``cpu_ops`` descriptors also include reset sequences and may include errata +workarounds for the CPU. The EL3 Runtime Software can choose to call this +during cold/warm reset if it does not implement its own reset sequence/errata +workarounds. + +-------------- + +*Copyright (c) 2016-2018, Arm Limited and Contributors. All rights reserved.* + +.. _PSCI spec: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _SMCCC: https://silver.arm.com/download/ARM_and_AMBA_Architecture/AR570-DA-80002-r0p0-00rel0/ARM_DEN0028A_SMC_Calling_Convention.pdf +.. _PSCI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _PSCI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _Porting Guide: ../getting_started/porting-guide.rst +.. _Firmware Design: ../design/firmware-design.rst diff --git a/docs/getting_started/rt-svc-writers-guide.rst b/docs/getting_started/rt-svc-writers-guide.rst new file mode 100644 index 0000000..f4d786c --- /dev/null +++ b/docs/getting_started/rt-svc-writers-guide.rst @@ -0,0 +1,311 @@ +Trusted Firmware-A EL3 runtime service writer's guide +===================================================== + + + +.. contents:: + +Introduction +------------ + +This document describes how to add a runtime service to the EL3 Runtime +Firmware component of Trusted Firmware-A (TF-A), BL31. + +Software executing in the normal world and in the trusted world at exception +levels lower than EL3 will request runtime services using the Secure Monitor +Call (SMC) instruction. These requests will follow the convention described in +the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function +identifiers to each SMC request and describes how arguments are passed and +results are returned. + +SMC Functions are grouped together based on the implementor of the service, for +example a subset of the Function IDs are designated as "OEM Calls" (see `SMCCC`_ +for full details). The EL3 runtime services framework in BL31 enables the +independent implementation of services for each group, which are then compiled +into the BL31 image. This simplifies the integration of common software from +Arm to support `PSCI`_, Secure Monitor for a Trusted OS and SoC specific +software. The common runtime services framework ensures that SMC Functions are +dispatched to their respective service implementation - the `Firmware Design`_ +provides details of how this is achieved. + +The interface and operation of the runtime services depends heavily on the +concepts and definitions described in the `SMCCC`_, in particular SMC Function +IDs, Owning Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and +SMC64 calling conventions. Please refer to that document for a full explanation +of these terms. + +Owning Entities, Call Types and Function IDs +-------------------------------------------- + +The SMC Function Identifier includes a OEN field. These values and their +meaning are described in `SMCCC`_ and summarized in table 1 below. Some entities +are allocated a range of of OENs. The OEN must be interpreted in conjunction +with the SMC call type, which is either *Fast* or *Yielding*. Fast calls are +uninterruptible whereas Yielding calls can be pre-empted. The majority of +Owning Entities only have allocated ranges for Fast calls: Yielding calls are +reserved exclusively for Trusted OS providers or for interoperability with +legacy 32-bit software that predates the `SMCCC`_. + +:: + + Type OEN Service + Fast 0 Arm Architecture calls + Fast 1 CPU Service calls + Fast 2 SiP Service calls + Fast 3 OEM Service calls + Fast 4 Standard Service calls + Fast 5-47 Reserved for future use + Fast 48-49 Trusted Application calls + Fast 50-63 Trusted OS calls + + Yielding 0- 1 Reserved for existing Armv7-A calls + Yielding 2-63 Trusted OS Standard Calls + +*Table 1: Service types and their corresponding Owning Entity Numbers* + +Each individual entity can allocate the valid identifiers within the entity +range as they need - it is not necessary to coordinate with other entities of +the same type. For example, two SoC providers can use the same Function ID +within the SiP Service calls OEN range to mean different things - as these +calls should be specific to the SoC. The Standard Runtime Calls OEN is used for +services defined by Arm standards, such as `PSCI`_. + +The SMC Function ID also indicates whether the call has followed the SMC32 +calling convention, where all parameters are 32-bit, or the SMC64 calling +convention, where the parameters are 64-bit. The framework identifies and +rejects invalid calls that use the SMC64 calling convention but that originate +from an AArch32 caller. + +The EL3 runtime services framework uses the call type and OEN to identify a +specific handler for each SMC call, but it is expected that an individual +handler will be responsible for all SMC Functions within a given service type. + +Getting started +--------------- + +TF-A has a `services`_ directory in the source tree under which +each owning entity can place the implementation of its runtime service. The +`PSCI`_ implementation is located here in the `lib/psci`_ directory. + +Runtime service sources will need to include the `runtime_svc.h`_ header file. + +Registering a runtime service +----------------------------- + +A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying +the name of the service, the range of OENs covered, the type of service and +initialization and call handler functions. + +:: + + #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) + +- ``_name`` is used to identify the data structure declared by this macro, and + is also used for diagnostic purposes + +- ``_start`` and ``_end`` values must be based on the ``OEN_*`` values defined in + `smccc.h`_ + +- ``_type`` must be one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` + +- ``_setup`` is the initialization function with the ``rt_svc_init`` signature: + + .. code:: c + + typedef int32_t (*rt_svc_init)(void); + +- ``_smch`` is the SMC handler function with the ``rt_svc_handle`` signature: + + .. code:: c + + typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, + u_register_t x1, u_register_t x2, + u_register_t x3, u_register_t x4, + void *cookie, + void *handle, + u_register_t flags); + +Details of the requirements and behavior of the two callbacks is provided in +the following sections. + +During initialization the services framework validates each declared service +to ensure that the following conditions are met: + +#. The ``_start`` OEN is not greater than the ``_end`` OEN +#. The ``_end`` OEN does not exceed the maximum OEN value (63) +#. The ``_type`` is one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` +#. ``_setup`` and ``_smch`` routines have been specified + +`std_svc_setup.c`_ provides an example of registering a runtime service: + +.. code:: c + + /* Register Standard Service Calls as runtime service */ + DECLARE_RT_SVC( + std_svc, + OEN_STD_START, + OEN_STD_END, + SMC_TYPE_FAST, + std_svc_setup, + std_svc_smc_handler + ); + +Initializing a runtime service +------------------------------ + +Runtime services are initialized once, during cold boot, by the primary CPU +after platform and architectural initialization is complete. The framework +performs basic validation of the declared service before calling +the service initialization function (``_setup`` in the declaration). This +function must carry out any essential EL3 initialization prior to receiving a +SMC Function call via the handler function. + +On success, the initialization function must return ``0``. Any other return value +will cause the framework to issue a diagnostic: + +:: + + Error initializing runtime service + +and then ignore the service - the system will continue to boot but SMC calls +will not be passed to the service handler and instead return the *Unknown SMC +Function ID* result ``0xFFFFFFFF``. + +If the system must not be allowed to proceed without the service, the +initialization function must itself cause the firmware boot to be halted. + +If the service uses per-CPU data this must either be initialized for all CPUs +during this call, or be done lazily when a CPU first issues an SMC call to that +service. + +Handling runtime service requests +--------------------------------- + +SMC calls for a service are forwarded by the framework to the service's SMC +handler function (``_smch`` in the service declaration). This function must have +the following signature: + +.. code:: c + + typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, + u_register_t x1, u_register_t x2, + u_register_t x3, u_register_t x4, + void *cookie, + void *handle, + u_register_t flags); + +The handler is responsible for: + +#. Determining that ``smc_fid`` is a valid and supported SMC Function ID, + otherwise completing the request with the *Unknown SMC Function ID*: + + .. code:: c + + SMC_RET1(handle, SMC_UNK); + +#. Determining if the requested function is valid for the calling security + state. SMC Calls can be made from both the normal and trusted worlds and + the framework will forward all calls to the service handler. + + The ``flags`` parameter to this function indicates the caller security state + in bit[0], where a value of ``1`` indicates a non-secure caller. The + ``is_caller_secure(flags)`` and ``is_caller_non_secure(flags)`` can be used to + test this condition. + + If invalid, the request should be completed with: + + .. code:: c + + SMC_RET1(handle, SMC_UNK); + +#. Truncating parameters for calls made using the SMC32 calling convention. + Such calls can be determined by checking the CC field in bit[30] of the + ``smc_fid`` parameter, for example by using: + + :: + + if (GET_SMC_CC(smc_fid) == SMC_32) ... + + For such calls, the upper bits of the parameters x1-x4 and the saved + parameters X5-X7 are UNDEFINED and must be explicitly ignored by the + handler. This can be done by truncating the values to a suitable 32-bit + integer type before use, for example by ensuring that functions defined + to handle individual SMC Functions use appropriate 32-bit parameters. + +#. Providing the service requested by the SMC Function, utilizing the + immediate parameters x1-x4 and/or the additional saved parameters X5-X7. + The latter can be retrieved using the ``SMC_GET_GP(handle, ref)`` function, + supplying the appropriate ``CTX_GPREG_Xn`` reference, e.g. + + .. code:: c + + uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6); + +#. Implementing the standard SMC32 Functions that provide information about + the implementation of the service. These are the Call Count, Implementor + UID and Revision Details for each service documented in section 6 of the + `SMCCC`_. + + TF-A expects owning entities to follow this recommendation. + +#. Returning the result to the caller. The `SMCCC`_ allows for up to 256 bits + of return value in SMC64 using X0-X3 and 128 bits in SMC32 using W0-W3. The + framework provides a family of macros to set the multi-register return + value and complete the handler: + + .. code:: c + + SMC_RET1(handle, x0); + SMC_RET2(handle, x0, x1); + SMC_RET3(handle, x0, x1, x2); + SMC_RET4(handle, x0, x1, x2, x3); + +The ``cookie`` parameter to the handler is reserved for future use and can be +ignored. The ``handle`` is returned by the SMC handler - completion of the +handler function must always be via one of the ``SMC_RETn()`` macros. + +NOTE: The PSCI and Test Secure-EL1 Payload Dispatcher services do not follow +all of the above requirements yet. + +Services that contain multiple sub-services +------------------------------------------- + +It is possible that a single owning entity implements multiple sub-services. For +example, the Standard calls service handles ``0x84000000``-``0x8400FFFF`` and +``0xC4000000``-``0xC400FFFF`` functions. Within that range, the `PSCI`_ service +handles the ``0x84000000``-``0x8400001F`` and ``0xC4000000``-``0xC400001F`` functions. +In that respect, `PSCI`_ is a 'sub-service' of the Standard calls service. In +future, there could be additional such sub-services in the Standard calls +service which perform independent functions. + +In this situation it may be valuable to introduce a second level framework to +enable independent implementation of sub-services. Such a framework might look +very similar to the current runtime services framework, but using a different +part of the SMC Function ID to identify the sub-service. TF-A does not provide +such a framework at present. + +Secure-EL1 Payload Dispatcher service (SPD) +------------------------------------------- + +Services that handle SMC Functions targeting a Trusted OS, Trusted Application, +or other Secure-EL1 Payload are special. These services need to manage the +Secure-EL1 context, provide the *Secure Monitor* functionality of switching +between the normal and secure worlds, deliver SMC Calls through to Secure-EL1 +and generally manage the Secure-EL1 Payload through CPU power-state transitions. + +TODO: Provide details of the additional work required to implement a SPD and +the BL31 support for these services. Or a reference to the document that will +provide this information.... + +-------------- + +*Copyright (c) 2014-2018, Arm Limited and Contributors. All rights reserved.* + +.. _SMCCC: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _Firmware Design: ../designb_documents/firmware-design.rst +.. _services: ../../services +.. _lib/psci: ../../lib/psci +.. _runtime_svc.h: ../../include/common/runtime_svc.h +.. _smccc.h: ../../include/lib/smccc.h +.. _std_svc_setup.c: ../../services/std_svc/std_svc_setup.c diff --git a/docs/getting_started/user-guide.rst b/docs/getting_started/user-guide.rst new file mode 100644 index 0000000..3cc5f3c --- /dev/null +++ b/docs/getting_started/user-guide.rst @@ -0,0 +1,2142 @@ +Trusted Firmware-A User Guide +============================= + + + + +.. contents:: + +This document describes how to build Trusted Firmware-A (TF-A) and run it with a +tested set of other software components using defined configurations on the Juno +Arm development platform and Arm Fixed Virtual Platform (FVP) models. It is +possible to use other software components, configurations and platforms but that +is outside the scope of this document. + +This document assumes that the reader has previous experience running a fully +bootable Linux software stack on Juno or FVP using the prebuilt binaries and +filesystems provided by `Linaro`_. Further information may be found in the +`Linaro instructions`_. It also assumes that the user understands the role of +the different software components required to boot a Linux system: + +- Specific firmware images required by the platform (e.g. SCP firmware on Juno) +- Normal world bootloader (e.g. UEFI or U-Boot) +- Device tree +- Linux kernel image +- Root filesystem + +This document also assumes that the user is familiar with the `FVP models`_ and +the different command line options available to launch the model. + +This document should be used in conjunction with the `Firmware Design`_. + +Host machine requirements +------------------------- + +The minimum recommended machine specification for building the software and +running the FVP models is a dual-core processor running at 2GHz with 12GB of +RAM. For best performance, use a machine with a quad-core processor running at +2.6GHz with 16GB of RAM. + +The software has been tested on Ubuntu 16.04 LTS (64-bit). Packages used for +building the software were installed from that distribution unless otherwise +specified. + +The software has also been built on Windows 7 Enterprise SP1, using CMD.EXE, +Cygwin, and Msys (MinGW) shells, using version 5.3.1 of the GNU toolchain. + +Tools +----- + +Install the required packages to build TF-A with the following command: + +:: + + sudo apt-get install device-tree-compiler build-essential gcc make git libssl-dev + +TF-A has been tested with Linaro Release 18.04. + +Download and install the AArch32 or AArch64 little-endian GCC cross compiler. If +you would like to use the latest features available, download GCC 8.2-2019.01 +compiler from `arm Developer page`_. Otherwise, the `Linaro Release Notes`_ +documents which version of the compiler to use for a given Linaro Release. Also, +these `Linaro instructions`_ provide further guidance and a script, which can be +used to download Linaro deliverables automatically. + +Optionally, TF-A can be built using clang version 4.0 or newer or Arm +Compiler 6. See instructions below on how to switch the default compiler. + +In addition, the following optional packages and tools may be needed: + +- ``device-tree-compiler`` (dtc) package if you need to rebuild the Flattened Device + Tree (FDT) source files (``.dts`` files) provided with this software. The + version of dtc must be 1.4.6 or above. + +- For debugging, Arm `Development Studio 5 (DS-5)`_. + +- To create and modify the diagram files included in the documentation, `Dia`_. + This tool can be found in most Linux distributions. Inkscape is needed to + generate the actual \*.png files. + +Getting the TF-A source code +---------------------------- + +Clone the repository from the Gerrit server. The project details may be found +on the `arm-trusted-firmware-a project page`_. We recommend the "`Clone with +commit-msg hook`" clone method, which will setup the git commit hook that +automatically generates and inserts appropriate `Change-Id:` lines in your +commit messages. + +Checking source code style +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Trusted Firmware follows the `Linux Coding Style`_ . When making changes to the +source, for submission to the project, the source must be in compliance with +this style guide. + +Additional, project-specific guidelines are defined in the `Trusted Firmware-A +Coding Guidelines`_ document. + +To assist with coding style compliance, the project Makefile contains two +targets which both utilise the `checkpatch.pl` script that ships with the Linux +source tree. The project also defines certain *checkpatch* options in the +``.checkpatch.conf`` file in the top-level directory. + +**Note:** Checkpatch errors will gate upstream merging of pull requests. +Checkpatch warnings will not gate merging but should be reviewed and fixed if +possible. + +To check the entire source tree, you must first download copies of +``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available +in the `Linux master tree`_ *scripts* directory, then set the ``CHECKPATCH`` +environment variable to point to ``checkpatch.pl`` (with the other 2 files in +the same directory) and build the `checkcodebase` target: + +:: + + make CHECKPATCH=/linux/scripts/checkpatch.pl checkcodebase + +To just check the style on the files that differ between your local branch and +the remote master, use: + +:: + + make CHECKPATCH=/linux/scripts/checkpatch.pl checkpatch + +If you wish to check your patch against something other than the remote master, +set the ``BASE_COMMIT`` variable to your desired branch. By default, ``BASE_COMMIT`` +is set to ``origin/master``. + +Building TF-A +------------- + +- Before building TF-A, the environment variable ``CROSS_COMPILE`` must point + to the Linaro cross compiler. + + For AArch64: + + :: + + export CROSS_COMPILE=/bin/aarch64-linux-gnu- + + For AArch32: + + :: + + export CROSS_COMPILE=/bin/arm-linux-gnueabihf- + + It is possible to build TF-A using Clang or Arm Compiler 6. To do so + ``CC`` needs to point to the clang or armclang binary, which will + also select the clang or armclang assembler. Be aware that the + GNU linker is used by default. In case of being needed the linker + can be overridden using the ``LD`` variable. Clang linker version 6 is + known to work with TF-A. + + In both cases ``CROSS_COMPILE`` should be set as described above. + + Arm Compiler 6 will be selected when the base name of the path assigned + to ``CC`` matches the string 'armclang'. + + For AArch64 using Arm Compiler 6: + + :: + + export CROSS_COMPILE=/bin/aarch64-linux-gnu- + make CC=/bin/armclang PLAT= all + + Clang will be selected when the base name of the path assigned to ``CC`` + contains the string 'clang'. This is to allow both clang and clang-X.Y + to work. + + For AArch64 using clang: + + :: + + export CROSS_COMPILE=/bin/aarch64-linux-gnu- + make CC=/bin/clang PLAT= all + +- Change to the root directory of the TF-A source tree and build. + + For AArch64: + + :: + + make PLAT= all + + For AArch32: + + :: + + make PLAT= ARCH=aarch32 AARCH32_SP=sp_min all + + Notes: + + - If ``PLAT`` is not specified, ``fvp`` is assumed by default. See the + `Summary of build options`_ for more information on available build + options. + + - (AArch32 only) Currently only ``PLAT=fvp`` is supported. + + - (AArch32 only) ``AARCH32_SP`` is the AArch32 EL3 Runtime Software and it + corresponds to the BL32 image. A minimal ``AARCH32_SP``, sp_min, is + provided by TF-A to demonstrate how PSCI Library can be integrated with + an AArch32 EL3 Runtime Software. Some AArch32 EL3 Runtime Software may + include other runtime services, for example Trusted OS services. A guide + to integrate PSCI library with AArch32 EL3 Runtime Software can be found + `here`_. + + - (AArch64 only) The TSP (Test Secure Payload), corresponding to the BL32 + image, is not compiled in by default. Refer to the + `Building the Test Secure Payload`_ section below. + + - By default this produces a release version of the build. To produce a + debug version instead, refer to the "Debugging options" section below. + + - The build process creates products in a ``build`` directory tree, building + the objects and binaries for each boot loader stage in separate + sub-directories. The following boot loader binary files are created + from the corresponding ELF files: + + - ``build///bl1.bin`` + - ``build///bl2.bin`` + - ``build///bl31.bin`` (AArch64 only) + - ``build///bl32.bin`` (mandatory for AArch32) + + where ```` is the name of the chosen platform and ```` + is either ``debug`` or ``release``. The actual number of images might differ + depending on the platform. + +- Build products for a specific build variant can be removed using: + + :: + + make DEBUG= PLAT= clean + + ... where ```` is ``0`` or ``1``, as specified when building. + + The build tree can be removed completely using: + + :: + + make realclean + +Summary of build options +~~~~~~~~~~~~~~~~~~~~~~~~ + +The TF-A build system supports the following build options. Unless mentioned +otherwise, these options are expected to be specified at the build command +line and are not to be modified in any component makefiles. Note that the +build system doesn't track dependency for build options. Therefore, if any of +the build options are changed from a previous build, a clean build must be +performed. + +Common build options +^^^^^^^^^^^^^^^^^^^^ + +- ``AARCH32_INSTRUCTION_SET``: Choose the AArch32 instruction set that the + compiler should use. Valid values are T32 and A32. It defaults to T32 due to + code having a smaller resulting size. + +- ``AARCH32_SP`` : Choose the AArch32 Secure Payload component to be built as + as the BL32 image when ``ARCH=aarch32``. The value should be the path to the + directory containing the SP source, relative to the ``bl32/``; the directory + is expected to contain a makefile called ``.mk``. + +- ``ARCH`` : Choose the target build architecture for TF-A. It can take either + ``aarch64`` or ``aarch32`` as values. By default, it is defined to + ``aarch64``. + +- ``ARM_ARCH_MAJOR``: The major version of Arm Architecture to target when + compiling TF-A. Its value must be numeric, and defaults to 8 . See also, + *Armv8 Architecture Extensions* and *Armv7 Architecture Extensions* in + `Firmware Design`_. + +- ``ARM_ARCH_MINOR``: The minor version of Arm Architecture to target when + compiling TF-A. Its value must be a numeric, and defaults to 0. See also, + *Armv8 Architecture Extensions* in `Firmware Design`_. + +- ``BL2``: This is an optional build option which specifies the path to BL2 + image for the ``fip`` target. In this case, the BL2 in the TF-A will not be + built. + +- ``BL2U``: This is an optional build option which specifies the path to + BL2U image. In this case, the BL2U in TF-A will not be built. + +- ``BL2_AT_EL3``: This is an optional build option that enables the use of + BL2 at EL3 execution level. + +- ``BL2_IN_XIP_MEM``: In some use-cases BL2 will be stored in eXecute In Place + (XIP) memory, like BL1. In these use-cases, it is necessary to initialize + the RW sections in RAM, while leaving the RO sections in place. This option + enable this use-case. For now, this option is only supported when BL2_AT_EL3 + is set to '1'. + +- ``BL31``: This is an optional build option which specifies the path to + BL31 image for the ``fip`` target. In this case, the BL31 in TF-A will not + be built. + +- ``BL31_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL31 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BL32``: This is an optional build option which specifies the path to + BL32 image for the ``fip`` target. In this case, the BL32 in TF-A will not + be built. + +- ``BL32_EXTRA1``: This is an optional build option which specifies the path to + Trusted OS Extra1 image for the ``fip`` target. + +- ``BL32_EXTRA2``: This is an optional build option which specifies the path to + Trusted OS Extra2 image for the ``fip`` target. + +- ``BL32_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL32 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BL33``: Path to BL33 image in the host file system. This is mandatory for + ``fip`` target in case TF-A BL2 is used. + +- ``BL33_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL33 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BUILD_MESSAGE_TIMESTAMP``: String used to identify the time and date of the + compilation of each build. It must be set to a C string (including quotes + where applicable). Defaults to a string that contains the time and date of + the compilation. + +- ``BUILD_STRING``: Input string for VERSION_STRING, which allows the TF-A + build to be uniquely identified. Defaults to the current git commit id. + +- ``CFLAGS``: Extra user options appended on the compiler's command line in + addition to the options set by the build system. + +- ``COLD_BOOT_SINGLE_CPU``: This option indicates whether the platform may + release several CPUs out of reset. It can take either 0 (several CPUs may be + brought up) or 1 (only one CPU will ever be brought up during cold reset). + Default is 0. If the platform always brings up a single CPU, there is no + need to distinguish between primary and secondary CPUs and the boot path can + be optimised. The ``plat_is_my_cpu_primary()`` and + ``plat_secondary_cold_boot_setup()`` platform porting interfaces do not need + to be implemented in this case. + +- ``CRASH_REPORTING``: A non-zero value enables a console dump of processor + register state when an unexpected exception occurs during execution of + BL31. This option defaults to the value of ``DEBUG`` - i.e. by default + this is only enabled for a debug build of the firmware. + +- ``CREATE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the + certificate generation tool to create new keys in case no valid keys are + present or specified. Allowed options are '0' or '1'. Default is '1'. + +- ``CTX_INCLUDE_AARCH32_REGS`` : Boolean option that, when set to 1, will cause + the AArch32 system registers to be included when saving and restoring the + CPU context. The option must be set to 0 for AArch64-only platforms (that + is on hardware that does not implement AArch32, or at least not at EL1 and + higher ELs). Default value is 1. + +- ``CTX_INCLUDE_FPREGS``: Boolean option that, when set to 1, will cause the FP + registers to be included when saving and restoring the CPU context. Default + is 0. + +- ``CTX_INCLUDE_PAUTH_REGS``: Boolean option that, when set to 1, allows + Pointer Authentication for **Secure world**. This will cause the + Armv8.3-PAuth registers to be included when saving and restoring the CPU + context as part of a world switch. Default value is 0. Pointer Authentication + is an experimental feature. + + Note that, if the CPU supports it, Pointer Authentication is allowed for + Non-secure world irrespectively of the value of this flag. "Allowed" means + that accesses to PAuth-related registers or execution of PAuth-related + instructions will not be trapped to EL3. As such, usage or not of PAuth in + Non-secure world images, depends on those images themselves. + +- ``DEBUG``: Chooses between a debug and release build. It can take either 0 + (release) or 1 (debug) as values. 0 is the default. + +- ``DISABLE_BIN_GENERATION``: Boolean option to disable the generation + of the binary image. If set to 1, then only the ELF image is built. + 0 is the default. + +- ``DYN_DISABLE_AUTH``: Provides the capability to dynamically disable Trusted + Board Boot authentication at runtime. This option is meant to be enabled only + for development platforms. ``TRUSTED_BOARD_BOOT`` flag must be set if this + flag has to be enabled. 0 is the default. + +- ``EL3_PAYLOAD_BASE``: This option enables booting an EL3 payload instead of + the normal boot flow. It must specify the entry point address of the EL3 + payload. Please refer to the "Booting an EL3 payload" section for more + details. + +- ``ENABLE_AMU``: Boolean option to enable Activity Monitor Unit extensions. + This is an optional architectural feature available on v8.4 onwards. Some + v8.2 implementations also implement an AMU and this option can be used to + enable this feature on those systems as well. Default is 0. + +- ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()`` + are compiled out. For debug builds, this option defaults to 1, and calls to + ``assert()`` are left in place. For release builds, this option defaults to 0 + and calls to ``assert()`` function are compiled out. This option can be set + independently of ``DEBUG``. It can also be used to hide any auxiliary code + that is only required for the assertion and does not fit in the assertion + itself. + +- ``ENABLE_BACKTRACE``: This option controls whether to enables backtrace + dumps or not. It is supported in both AArch64 and AArch32. However, in + AArch32 the format of the frame records are not defined in the AAPCS and they + are defined by the implementation. This implementation of backtrace only + supports the format used by GCC when T32 interworking is disabled. For this + reason enabling this option in AArch32 will force the compiler to only + generate A32 code. This option is enabled by default only in AArch64 debug + builds, but this behaviour can be overridden in each platform's Makefile or + in the build command line. + +- ``ENABLE_MPAM_FOR_LOWER_ELS``: Boolean option to enable lower ELs to use MPAM + feature. MPAM is an optional Armv8.4 extension that enables various memory + system components and resources to define partitions; software running at + various ELs can assign themselves to desired partition to control their + performance aspects. + + When this option is set to ``1``, EL3 allows lower ELs to access their own + MPAM registers without trapping into EL3. This option doesn't make use of + partitioning in EL3, however. Platform initialisation code should configure + and use partitions in EL3 as required. This option defaults to ``0``. + +- ``ENABLE_PAUTH``: Boolean option to enable Armv8.3 Pointer Authentication + for **TF-A BL images themselves**. If enabled, the compiler must support the + ``-msign-return-address`` option. This flag defaults to 0. Pointer + Authentication is an experimental feature. + + If this flag is enabled, ``CTX_INCLUDE_PAUTH_REGS`` must also be enabled. + +- ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE) + support within generic code in TF-A. This option is currently only supported + in BL31. Default is 0. + +- ``ENABLE_PMF``: Boolean option to enable support for optional Performance + Measurement Framework(PMF). Default is 0. + +- ``ENABLE_PSCI_STAT``: Boolean option to enable support for optional PSCI + functions ``PSCI_STAT_RESIDENCY`` and ``PSCI_STAT_COUNT``. Default is 0. + In the absence of an alternate stat collection backend, ``ENABLE_PMF`` must + be enabled. If ``ENABLE_PMF`` is set, the residency statistics are tracked in + software. + +- ``ENABLE_RUNTIME_INSTRUMENTATION``: Boolean option to enable runtime + instrumentation which injects timestamp collection points into TF-A to + allow runtime performance to be measured. Currently, only PSCI is + instrumented. Enabling this option enables the ``ENABLE_PMF`` build option + as well. Default is 0. + +- ``ENABLE_SPE_FOR_LOWER_ELS`` : Boolean option to enable Statistical Profiling + extensions. This is an optional architectural feature for AArch64. + The default is 1 but is automatically disabled when the target architecture + is AArch32. + +- ``ENABLE_SPM`` : Boolean option to enable the Secure Partition Manager (SPM). + Refer to the `Secure Partition Manager Design guide`_ for more details about + this feature. Default is 0. + +- ``ENABLE_SVE_FOR_NS``: Boolean option to enable Scalable Vector Extension + (SVE) for the Non-secure world only. SVE is an optional architectural feature + for AArch64. Note that when SVE is enabled for the Non-secure world, access + to SIMD and floating-point functionality from the Secure world is disabled. + This is to avoid corruption of the Non-secure world data in the Z-registers + which are aliased by the SIMD and FP registers. The build option is not + compatible with the ``CTX_INCLUDE_FPREGS`` build option, and will raise an + assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS`` set to + 1. The default is 1 but is automatically disabled when the target + architecture is AArch32. + +- ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection + checks in GCC. Allowed values are "all", "strong", "default" and "none". The + default value is set to "none". "strong" is the recommended stack protection + level if this feature is desired. "none" disables the stack protection. For + all values other than "none", the ``plat_get_stack_protector_canary()`` + platform hook needs to be implemented. The value is passed as the last + component of the option ``-fstack-protector-$ENABLE_STACK_PROTECTOR``. + +- ``ERROR_DEPRECATED``: This option decides whether to treat the usage of + deprecated platform APIs, helper functions or drivers within Trusted + Firmware as error. It can take the value 1 (flag the use of deprecated + APIs as error) or 0. The default is 0. + +- ``EL3_EXCEPTION_HANDLING``: When set to ``1``, enable handling of exceptions + targeted at EL3. When set ``0`` (default), no exceptions are expected or + handled at EL3, and a panic will result. This is supported only for AArch64 + builds. + +- ``FAULT_INJECTION_SUPPORT``: ARMv8.4 extensions introduced support for fault + injection from lower ELs, and this build option enables lower ELs to use + Error Records accessed via System Registers to inject faults. This is + applicable only to AArch64 builds. + + This feature is intended for testing purposes only, and is advisable to keep + disabled for production images. + +- ``FIP_NAME``: This is an optional build option which specifies the FIP + filename for the ``fip`` target. Default is ``fip.bin``. + +- ``FWU_FIP_NAME``: This is an optional build option which specifies the FWU + FIP filename for the ``fwu_fip`` target. Default is ``fwu_fip.bin``. + +- ``GENERATE_COT``: Boolean flag used to build and execute the ``cert_create`` + tool to create certificates as per the Chain of Trust described in + `Trusted Board Boot`_. The build system then calls ``fiptool`` to + include the certificates in the FIP and FWU_FIP. Default value is '0'. + + Specify both ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=1`` to include support + for the Trusted Board Boot feature in the BL1 and BL2 images, to generate + the corresponding certificates, and to include those certificates in the + FIP and FWU_FIP. + + Note that if ``TRUSTED_BOARD_BOOT=0`` and ``GENERATE_COT=1``, the BL1 and BL2 + images will not include support for Trusted Board Boot. The FIP will still + include the corresponding certificates. This FIP can be used to verify the + Chain of Trust on the host machine through other mechanisms. + + Note that if ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=0``, the BL1 and BL2 + images will include support for Trusted Board Boot, but the FIP and FWU_FIP + will not include the corresponding certificates, causing a boot failure. + +- ``GICV2_G0_FOR_EL3``: Unlike GICv3, the GICv2 architecture doesn't have + inherent support for specific EL3 type interrupts. Setting this build option + to ``1`` assumes GICv2 *Group 0* interrupts are expected to target EL3, both + by `platform abstraction layer`__ and `Interrupt Management Framework`__. + This allows GICv2 platforms to enable features requiring EL3 interrupt type. + This also means that all GICv2 Group 0 interrupts are delivered to EL3, and + the Secure Payload interrupts needs to be synchronously handed over to Secure + EL1 for handling. The default value of this option is ``0``, which means the + Group 0 interrupts are assumed to be handled by Secure EL1. + + .. __: `platform-interrupt-controller-API.rst` + .. __: `interrupt-framework-design.rst` + +- ``HANDLE_EA_EL3_FIRST``: When set to ``1``, External Aborts and SError + Interrupts will be always trapped in EL3 i.e. in BL31 at runtime. When set to + ``0`` (default), these exceptions will be trapped in the current exception + level (or in EL1 if the current exception level is EL0). + +- ``HW_ASSISTED_COHERENCY``: On most Arm systems to-date, platform-specific + software operations are required for CPUs to enter and exit coherency. + However, newer systems exist where CPUs' entry to and exit from coherency + is managed in hardware. Such systems require software to only initiate these + operations, and the rest is managed in hardware, minimizing active software + management. In such systems, this boolean option enables TF-A to carry out + build and run-time optimizations during boot and power management operations. + This option defaults to 0 and if it is enabled, then it implies + ``WARMBOOT_ENABLE_DCACHE_EARLY`` is also enabled. + + If this flag is disabled while the platform which TF-A is compiled for + includes cores that manage coherency in hardware, then a compilation error is + generated. This is based on the fact that a system cannot have, at the same + time, cores that manage coherency in hardware and cores that don't. In other + words, a platform cannot have, at the same time, cores that require + ``HW_ASSISTED_COHERENCY=1`` and cores that require + ``HW_ASSISTED_COHERENCY=0``. + + Note that, when ``HW_ASSISTED_COHERENCY`` is enabled, version 2 of + translation library (xlat tables v2) must be used; version 1 of translation + library is not supported. + +- ``JUNO_AARCH32_EL3_RUNTIME``: This build flag enables you to execute EL3 + runtime software in AArch32 mode, which is required to run AArch32 on Juno. + By default this flag is set to '0'. Enabling this flag builds BL1 and BL2 in + AArch64 and facilitates the loading of ``SP_MIN`` and BL33 as AArch32 executable + images. + +- ``KEY_ALG``: This build flag enables the user to select the algorithm to be + used for generating the PKCS keys and subsequent signing of the certificate. + It accepts 3 values: ``rsa``, ``rsa_1_5`` and ``ecdsa``. The option + ``rsa_1_5`` is the legacy PKCS#1 RSA 1.5 algorithm which is not TBBR + compliant and is retained only for compatibility. The default value of this + flag is ``rsa`` which is the TBBR compliant PKCS#1 RSA 2.1 scheme. + +- ``HASH_ALG``: This build flag enables the user to select the secure hash + algorithm. It accepts 3 values: ``sha256``, ``sha384`` and ``sha512``. + The default value of this flag is ``sha256``. + +- ``LDFLAGS``: Extra user options appended to the linkers' command line in + addition to the one set by the build system. + +- ``LOG_LEVEL``: Chooses the log level, which controls the amount of console log + output compiled into the build. This should be one of the following: + + :: + + 0 (LOG_LEVEL_NONE) + 10 (LOG_LEVEL_ERROR) + 20 (LOG_LEVEL_NOTICE) + 30 (LOG_LEVEL_WARNING) + 40 (LOG_LEVEL_INFO) + 50 (LOG_LEVEL_VERBOSE) + + All log output up to and including the selected log level is compiled into + the build. The default value is 40 in debug builds and 20 in release builds. + +- ``NON_TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It + specifies the file that contains the Non-Trusted World private key in PEM + format. If ``SAVE_KEYS=1``, this file name will be used to save the key. + +- ``NS_BL2U``: Path to NS_BL2U image in the host file system. This image is + optional. It is only needed if the platform makefile specifies that it + is required in order to build the ``fwu_fip`` target. + +- ``NS_TIMER_SWITCH``: Enable save and restore for non-secure timer register + contents upon world switch. It can take either 0 (don't save and restore) or + 1 (do save and restore). 0 is the default. An SPD may set this to 1 if it + wants the timer registers to be saved and restored. + +- ``OVERRIDE_LIBC``: This option allows platforms to override the default libc + for the BL image. It can be either 0 (include) or 1 (remove). The default + value is 0. + +- ``PL011_GENERIC_UART``: Boolean option to indicate the PL011 driver that + the underlying hardware is not a full PL011 UART but a minimally compliant + generic UART, which is a subset of the PL011. The driver will not access + any register that is not part of the SBSA generic UART specification. + Default value is 0 (a full PL011 compliant UART is present). + +- ``PLAT``: Choose a platform to build TF-A for. The chosen platform name + must be subdirectory of any depth under ``plat/``, and must contain a + platform makefile named ``platform.mk``. For example, to build TF-A for the + Arm Juno board, select PLAT=juno. + +- ``PRELOADED_BL33_BASE``: This option enables booting a preloaded BL33 image + instead of the normal boot flow. When defined, it must specify the entry + point address for the preloaded BL33 image. This option is incompatible with + ``EL3_PAYLOAD_BASE``. If both are defined, ``EL3_PAYLOAD_BASE`` has priority + over ``PRELOADED_BL33_BASE``. + +- ``PROGRAMMABLE_RESET_ADDRESS``: This option indicates whether the reset + vector address can be programmed or is fixed on the platform. It can take + either 0 (fixed) or 1 (programmable). Default is 0. If the platform has a + programmable reset address, it is expected that a CPU will start executing + code directly at the right address, both on a cold and warm reset. In this + case, there is no need to identify the entrypoint on boot and the boot path + can be optimised. The ``plat_get_my_entrypoint()`` platform porting interface + does not need to be implemented in this case. + +- ``PSCI_EXTENDED_STATE_ID``: As per PSCI1.0 Specification, there are 2 formats + possible for the PSCI power-state parameter: original and extended State-ID + formats. This flag if set to 1, configures the generic PSCI layer to use the + extended format. The default value of this flag is 0, which means by default + the original power-state format is used by the PSCI implementation. This flag + should be specified by the platform makefile and it governs the return value + of PSCI_FEATURES API for CPU_SUSPEND smc function id. When this option is + enabled on Arm platforms, the option ``ARM_RECOM_STATE_ID_ENC`` needs to be + set to 1 as well. + +- ``RAS_EXTENSION``: When set to ``1``, enable Armv8.2 RAS features. RAS features + are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2 + or later CPUs. + + When ``RAS_EXTENSION`` is set to ``1``, ``HANDLE_EA_EL3_FIRST`` must also be + set to ``1``. + + This option is disabled by default. + +- ``RESET_TO_BL31``: Enable BL31 entrypoint as the CPU reset vector instead + of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1 + entrypoint) or 1 (CPU reset to BL31 entrypoint). + The default value is 0. + +- ``RESET_TO_SP_MIN``: SP_MIN is the minimal AArch32 Secure Payload provided + in TF-A. This flag configures SP_MIN entrypoint as the CPU reset vector + instead of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1 + entrypoint) or 1 (CPU reset to SP_MIN entrypoint). The default value is 0. + +- ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the ROT private key in PEM format. If ``SAVE_KEYS=1``, this + file name will be used to save the key. + +- ``SAVE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the + certificate generation tool to save the keys used to establish the Chain of + Trust. Allowed options are '0' or '1'. Default is '0' (do not save). + +- ``SCP_BL2``: Path to SCP_BL2 image in the host file system. This image is optional. + If a SCP_BL2 image is present then this option must be passed for the ``fip`` + target. + +- ``SCP_BL2_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the SCP_BL2 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``SCP_BL2U``: Path to SCP_BL2U image in the host file system. This image is + optional. It is only needed if the platform makefile specifies that it + is required in order to build the ``fwu_fip`` target. + +- ``SDEI_SUPPORT``: Setting this to ``1`` enables support for Software + Delegated Exception Interface to BL31 image. This defaults to ``0``. + + When set to ``1``, the build option ``EL3_EXCEPTION_HANDLING`` must also be + set to ``1``. + +- ``SEPARATE_CODE_AND_RODATA``: Whether code and read-only data should be + isolated on separate memory pages. This is a trade-off between security and + memory usage. See "Isolating code and read-only data on separate memory + pages" section in `Firmware Design`_. This flag is disabled by default and + affects all BL images. + +- ``SPD``: Choose a Secure Payload Dispatcher component to be built into TF-A. + This build option is only valid if ``ARCH=aarch64``. The value should be + the path to the directory containing the SPD source, relative to + ``services/spd/``; the directory is expected to contain a makefile called + ``.mk``. + +- ``SPIN_ON_BL1_EXIT``: This option introduces an infinite loop in BL1. It can + take either 0 (no loop) or 1 (add a loop). 0 is the default. This loop stops + execution in BL1 just before handing over to BL31. At this point, all + firmware images have been loaded in memory, and the MMU and caches are + turned off. Refer to the "Debugging options" section for more details. + +- ``SP_MIN_WITH_SECURE_FIQ``: Boolean flag to indicate the SP_MIN handles + secure interrupts (caught through the FIQ line). Platforms can enable + this directive if they need to handle such interruption. When enabled, + the FIQ are handled in monitor mode and non secure world is not allowed + to mask these events. Platforms that enable FIQ handling in SP_MIN shall + implement the api ``sp_min_plat_fiq_handler()``. The default value is 0. + +- ``TRUSTED_BOARD_BOOT``: Boolean flag to include support for the Trusted Board + Boot feature. When set to '1', BL1 and BL2 images include support to load + and verify the certificates and images in a FIP, and BL1 includes support + for the Firmware Update. The default value is '0'. Generation and inclusion + of certificates in the FIP and FWU_FIP depends upon the value of the + ``GENERATE_COT`` option. + + Note: This option depends on ``CREATE_KEYS`` to be enabled. If the keys + already exist in disk, they will be overwritten without further notice. + +- ``TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It + specifies the file that contains the Trusted World private key in PEM + format. If ``SAVE_KEYS=1``, this file name will be used to save the key. + +- ``TSP_INIT_ASYNC``: Choose BL32 initialization method as asynchronous or + synchronous, (see "Initializing a BL32 Image" section in + `Firmware Design`_). It can take the value 0 (BL32 is initialized using + synchronous method) or 1 (BL32 is initialized using asynchronous method). + Default is 0. + +- ``TSP_NS_INTR_ASYNC_PREEMPT``: A non zero value enables the interrupt + routing model which routes non-secure interrupts asynchronously from TSP + to EL3 causing immediate preemption of TSP. The EL3 is responsible + for saving and restoring the TSP context in this routing model. The + default routing model (when the value is 0) is to route non-secure + interrupts to TSP allowing it to save its context and hand over + synchronously to EL3 via an SMC. + + Note: when ``EL3_EXCEPTION_HANDLING`` is ``1``, ``TSP_NS_INTR_ASYNC_PREEMPT`` + must also be set to ``1``. + +- ``USE_ARM_LINK``: This flag determines whether to enable support for ARM + linker. When the ``LINKER`` build variable points to the armlink linker, + this flag is enabled automatically. To enable support for armlink, platforms + will have to provide a scatter file for the BL image. Currently, Tegra + platforms use the armlink support to compile BL3-1 images. + +- ``USE_COHERENT_MEM``: This flag determines whether to include the coherent + memory region in the BL memory map or not (see "Use of Coherent memory in + TF-A" section in `Firmware Design`_). It can take the value 1 + (Coherent memory region is included) or 0 (Coherent memory region is + excluded). Default is 1. + +- ``USE_ROMLIB``: This flag determines whether library at ROM will be used. + This feature creates a library of functions to be placed in ROM and thus + reduces SRAM usage. Refer to `Library at ROM`_ for further details. Default + is 0. + +- ``V``: Verbose build. If assigned anything other than 0, the build commands + are printed. Default is 0. + +- ``VERSION_STRING``: String used in the log output for each TF-A image. + Defaults to a string formed by concatenating the version number, build type + and build string. + +- ``WARMBOOT_ENABLE_DCACHE_EARLY`` : Boolean option to enable D-cache early on + the CPU after warm boot. This is applicable for platforms which do not + require interconnect programming to enable cache coherency (eg: single + cluster platforms). If this option is enabled, then warm boot path + enables D-caches immediately after enabling MMU. This option defaults to 0. + +Arm development platform specific build options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``ARM_BL31_IN_DRAM``: Boolean option to select loading of BL31 in TZC secured + DRAM. By default, BL31 is in the secure SRAM. Set this flag to 1 to load + BL31 in TZC secured DRAM. If TSP is present, then setting this option also + sets the TSP location to DRAM and ignores the ``ARM_TSP_RAM_LOCATION`` build + flag. + +- ``ARM_CONFIG_CNTACR``: boolean option to unlock access to the ``CNTBase`` + frame registers by setting the ``CNTCTLBase.CNTACR`` register bits. The + frame number ```` is defined by ``PLAT_ARM_NSTIMER_FRAME_ID``, which should + match the frame used by the Non-Secure image (normally the Linux kernel). + Default is true (access to the frame is allowed). + +- ``ARM_DISABLE_TRUSTED_WDOG``: boolean option to disable the Trusted Watchdog. + By default, Arm platforms use a watchdog to trigger a system reset in case + an error is encountered during the boot process (for example, when an image + could not be loaded or authenticated). The watchdog is enabled in the early + platform setup hook at BL1 and disabled in the BL1 prepare exit hook. The + Trusted Watchdog may be disabled at build time for testing or development + purposes. + +- ``ARM_LINUX_KERNEL_AS_BL33``: The Linux kernel expects registers x0-x3 to + have specific values at boot. This boolean option allows the Trusted Firmware + to have a Linux kernel image as BL33 by preparing the registers to these + values before jumping to BL33. This option defaults to 0 (disabled). For + AArch64 ``RESET_TO_BL31`` and for AArch32 ``RESET_TO_SP_MIN`` must be 1 when + using it. If this option is set to 1, ``ARM_PRELOADED_DTB_BASE`` must be set + to the location of a device tree blob (DTB) already loaded in memory. The + Linux Image address must be specified using the ``PRELOADED_BL33_BASE`` + option. + +- ``ARM_PLAT_MT``: This flag determines whether the Arm platform layer has to + cater for the multi-threading ``MT`` bit when accessing MPIDR. When this flag + is set, the functions which deal with MPIDR assume that the ``MT`` bit in + MPIDR is set and access the bit-fields in MPIDR accordingly. Default value of + this flag is 0. Note that this option is not used on FVP platforms. + +- ``ARM_RECOM_STATE_ID_ENC``: The PSCI1.0 specification recommends an encoding + for the construction of composite state-ID in the power-state parameter. + The existing PSCI clients currently do not support this encoding of + State-ID yet. Hence this flag is used to configure whether to use the + recommended State-ID encoding or not. The default value of this flag is 0, + in which case the platform is configured to expect NULL in the State-ID + field of power-state parameter. + +- ``ARM_ROTPK_LOCATION``: used when ``TRUSTED_BOARD_BOOT=1``. It specifies the + location of the ROTPK hash returned by the function ``plat_get_rotpk_info()`` + for Arm platforms. Depending on the selected option, the proper private key + must be specified using the ``ROT_KEY`` option when building the Trusted + Firmware. This private key will be used by the certificate generation tool + to sign the BL2 and Trusted Key certificates. Available options for + ``ARM_ROTPK_LOCATION`` are: + + - ``regs`` : return the ROTPK hash stored in the Trusted root-key storage + registers. The private key corresponding to this ROTPK hash is not + currently available. + - ``devel_rsa`` : return a development public key hash embedded in the BL1 + and BL2 binaries. This hash has been obtained from the RSA public key + ``arm_rotpk_rsa.der``, located in ``plat/arm/board/common/rotpk``. To use + this option, ``arm_rotprivk_rsa.pem`` must be specified as ``ROT_KEY`` when + creating the certificates. + - ``devel_ecdsa`` : return a development public key hash embedded in the BL1 + and BL2 binaries. This hash has been obtained from the ECDSA public key + ``arm_rotpk_ecdsa.der``, located in ``plat/arm/board/common/rotpk``. To use + this option, ``arm_rotprivk_ecdsa.pem`` must be specified as ``ROT_KEY`` + when creating the certificates. + +- ``ARM_TSP_RAM_LOCATION``: location of the TSP binary. Options: + + - ``tsram`` : Trusted SRAM (default option when TBB is not enabled) + - ``tdram`` : Trusted DRAM (if available) + - ``dram`` : Secure region in DRAM (default option when TBB is enabled, + configured by the TrustZone controller) + +- ``ARM_XLAT_TABLES_LIB_V1``: boolean option to compile TF-A with version 1 + of the translation tables library instead of version 2. It is set to 0 by + default, which selects version 2. + +- ``ARM_CRYPTOCELL_INTEG`` : bool option to enable TF-A to invoke Arm® + TrustZone® CryptoCell functionality for Trusted Board Boot on capable Arm + platforms. If this option is specified, then the path to the CryptoCell + SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag. + +For a better understanding of these options, the Arm development platform memory +map is explained in the `Firmware Design`_. + +Arm CSS platform specific build options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``CSS_DETECT_PRE_1_7_0_SCP``: Boolean flag to detect SCP version + incompatibility. Version 1.7.0 of the SCP firmware made a non-backwards + compatible change to the MTL protocol, used for AP/SCP communication. + TF-A no longer supports earlier SCP versions. If this option is set to 1 + then TF-A will detect if an earlier version is in use. Default is 1. + +- ``CSS_LOAD_SCP_IMAGES``: Boolean flag, which when set, adds SCP_BL2 and + SCP_BL2U to the FIP and FWU_FIP respectively, and enables them to be loaded + during boot. Default is 1. + +- ``CSS_USE_SCMI_SDS_DRIVER``: Boolean flag which selects SCMI/SDS drivers + instead of SCPI/BOM driver for communicating with the SCP during power + management operations and for SCP RAM Firmware transfer. If this option + is set to 1, then SCMI/SDS drivers will be used. Default is 0. + +Arm FVP platform specific build options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``FVP_CLUSTER_COUNT`` : Configures the cluster count to be used to + build the topology tree within TF-A. By default TF-A is configured for dual + cluster topology and this option can be used to override the default value. + +- ``FVP_INTERCONNECT_DRIVER``: Selects the interconnect driver to be built. The + default interconnect driver depends on the value of ``FVP_CLUSTER_COUNT`` as + explained in the options below: + + - ``FVP_CCI`` : The CCI driver is selected. This is the default + if 0 < ``FVP_CLUSTER_COUNT`` <= 2. + - ``FVP_CCN`` : The CCN driver is selected. This is the default + if ``FVP_CLUSTER_COUNT`` > 2. + +- ``FVP_MAX_CPUS_PER_CLUSTER``: Sets the maximum number of CPUs implemented in + a single cluster. This option defaults to 4. + +- ``FVP_MAX_PE_PER_CPU``: Sets the maximum number of PEs implemented on any CPU + in the system. This option defaults to 1. Note that the build option + ``ARM_PLAT_MT`` doesn't have any effect on FVP platforms. + +- ``FVP_USE_GIC_DRIVER`` : Selects the GIC driver to be built. Options: + + - ``FVP_GIC600`` : The GIC600 implementation of GICv3 is selected + - ``FVP_GICV2`` : The GICv2 only driver is selected + - ``FVP_GICV3`` : The GICv3 only driver is selected (default option) + +- ``FVP_USE_SP804_TIMER`` : Use the SP804 timer instead of the Generic Timer + for functions that wait for an arbitrary time length (udelay and mdelay). + The default value is 0. + +- ``FVP_HW_CONFIG_DTS`` : Specify the path to the DTS file to be compiled + to DTB and packaged in FIP as the HW_CONFIG. See `Firmware Design`_ for + details on HW_CONFIG. By default, this is initialized to a sensible DTS + file in ``fdts/`` folder depending on other build options. But some cases, + like shifted affinity format for MPIDR, cannot be detected at build time + and this option is needed to specify the appropriate DTS file. + +- ``FVP_HW_CONFIG`` : Specify the path to the HW_CONFIG blob to be packaged in + FIP. See `Firmware Design`_ for details on HW_CONFIG. This option is + similar to the ``FVP_HW_CONFIG_DTS`` option, but it directly specifies the + HW_CONFIG blob instead of the DTS file. This option is useful to override + the default HW_CONFIG selected by the build system. + +ARM JUNO platform specific build options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``JUNO_TZMP1`` : Boolean option to configure Juno to be used for TrustZone + Media Protection (TZ-MP1). Default value of this flag is 0. + +Debugging options +~~~~~~~~~~~~~~~~~ + +To compile a debug version and make the build more verbose use + +:: + + make PLAT= DEBUG=1 V=1 all + +AArch64 GCC uses DWARF version 4 debugging symbols by default. Some tools (for +example DS-5) might not support this and may need an older version of DWARF +symbols to be emitted by GCC. This can be achieved by using the +``-gdwarf-`` flag, with the version being set to 2 or 3. Setting the +version to 2 is recommended for DS-5 versions older than 5.16. + +When debugging logic problems it might also be useful to disable all compiler +optimizations by using ``-O0``. + +NOTE: Using ``-O0`` could cause output images to be larger and base addresses +might need to be recalculated (see the **Memory layout on Arm development +platforms** section in the `Firmware Design`_). + +Extra debug options can be passed to the build system by setting ``CFLAGS`` or +``LDFLAGS``: + +.. code:: makefile + + CFLAGS='-O0 -gdwarf-2' \ + make PLAT= DEBUG=1 V=1 all + +Note that using ``-Wl,`` style compilation driver options in ``CFLAGS`` will be +ignored as the linker is called directly. + +It is also possible to introduce an infinite loop to help in debugging the +post-BL2 phase of TF-A. This can be done by rebuilding BL1 with the +``SPIN_ON_BL1_EXIT=1`` build flag. Refer to the `Summary of build options`_ +section. In this case, the developer may take control of the target using a +debugger when indicated by the console output. When using DS-5, the following +commands can be used: + +:: + + # Stop target execution + interrupt + + # + # Prepare your debugging environment, e.g. set breakpoints + # + + # Jump over the debug loop + set var $AARCH64::$Core::$PC = $AARCH64::$Core::$PC + 4 + + # Resume execution + continue + +Building the Test Secure Payload +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The TSP is coupled with a companion runtime service in the BL31 firmware, +called the TSPD. Therefore, if you intend to use the TSP, the BL31 image +must be recompiled as well. For more information on SPs and SPDs, see the +`Secure-EL1 Payloads and Dispatchers`_ section in the `Firmware Design`_. + +First clean the TF-A build directory to get rid of any previous BL31 binary. +Then to build the TSP image use: + +:: + + make PLAT= SPD=tspd all + +An additional boot loader binary file is created in the ``build`` directory: + +:: + + build///bl32.bin + + +Building and using the FIP tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Firmware Image Package (FIP) is a packaging format used by TF-A to package +firmware images in a single binary. The number and type of images that should +be packed in a FIP is platform specific and may include TF-A images and other +firmware images required by the platform. For example, most platforms require +a BL33 image which corresponds to the normal world bootloader (e.g. UEFI or +U-Boot). + +The TF-A build system provides the make target ``fip`` to create a FIP file +for the specified platform using the FIP creation tool included in the TF-A +project. Examples below show how to build a FIP file for FVP, packaging TF-A +and BL33 images. + +For AArch64: + +:: + + make PLAT=fvp BL33=/bl33.bin fip + +For AArch32: + +:: + + make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33=/bl33.bin fip + +The resulting FIP may be found in: + +:: + + build/fvp//fip.bin + +For advanced operations on FIP files, it is also possible to independently build +the tool and create or modify FIPs using this tool. To do this, follow these +steps: + +It is recommended to remove old artifacts before building the tool: + +:: + + make -C tools/fiptool clean + +Build the tool: + +:: + + make [DEBUG=1] [V=1] fiptool + +The tool binary can be located in: + +:: + + ./tools/fiptool/fiptool + +Invoking the tool with ``help`` will print a help message with all available +options. + +Example 1: create a new Firmware package ``fip.bin`` that contains BL2 and BL31: + +:: + + ./tools/fiptool/fiptool create \ + --tb-fw build///bl2.bin \ + --soc-fw build///bl31.bin \ + fip.bin + +Example 2: view the contents of an existing Firmware package: + +:: + + ./tools/fiptool/fiptool info /fip.bin + +Example 3: update the entries of an existing Firmware package: + +:: + + # Change the BL2 from Debug to Release version + ./tools/fiptool/fiptool update \ + --tb-fw build//release/bl2.bin \ + build//debug/fip.bin + +Example 4: unpack all entries from an existing Firmware package: + +:: + + # Images will be unpacked to the working directory + ./tools/fiptool/fiptool unpack /fip.bin + +Example 5: remove an entry from an existing Firmware package: + +:: + + ./tools/fiptool/fiptool remove \ + --tb-fw build//debug/fip.bin + +Note that if the destination FIP file exists, the create, update and +remove operations will automatically overwrite it. + +The unpack operation will fail if the images already exist at the +destination. In that case, use -f or --force to continue. + +More information about FIP can be found in the `Firmware Design`_ document. + +Building FIP images with support for Trusted Board Boot +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Trusted Board Boot primarily consists of the following two features: + +- Image Authentication, described in `Trusted Board Boot`_, and +- Firmware Update, described in `Firmware Update`_ + +The following steps should be followed to build FIP and (optionally) FWU_FIP +images with support for these features: + +#. Fulfill the dependencies of the ``mbedtls`` cryptographic and image parser + modules by checking out a recent version of the `mbed TLS Repository`_. It + is important to use a version that is compatible with TF-A and fixes any + known security vulnerabilities. See `mbed TLS Security Center`_ for more + information. The latest version of TF-A is tested with tag + ``mbedtls-2.16.0``. + + The ``drivers/auth/mbedtls/mbedtls_*.mk`` files contain the list of mbed TLS + source files the modules depend upon. + ``include/drivers/auth/mbedtls/mbedtls_config.h`` contains the configuration + options required to build the mbed TLS sources. + + Note that the mbed TLS library is licensed under the Apache version 2.0 + license. Using mbed TLS source code will affect the licensing of TF-A + binaries that are built using this library. + +#. To build the FIP image, ensure the following command line variables are set + while invoking ``make`` to build TF-A: + + - ``MBEDTLS_DIR=`` + - ``TRUSTED_BOARD_BOOT=1`` + - ``GENERATE_COT=1`` + + In the case of Arm platforms, the location of the ROTPK hash must also be + specified at build time. Two locations are currently supported (see + ``ARM_ROTPK_LOCATION`` build option): + + - ``ARM_ROTPK_LOCATION=regs``: the ROTPK hash is obtained from the Trusted + root-key storage registers present in the platform. On Juno, this + registers are read-only. On FVP Base and Cortex models, the registers + are read-only, but the value can be specified using the command line + option ``bp.trusted_key_storage.public_key`` when launching the model. + On both Juno and FVP models, the default value corresponds to an + ECDSA-SECP256R1 public key hash, whose private part is not currently + available. + + - ``ARM_ROTPK_LOCATION=devel_rsa``: use the ROTPK hash that is hardcoded + in the Arm platform port. The private/public RSA key pair may be + found in ``plat/arm/board/common/rotpk``. + + - ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the ROTPK hash that is hardcoded + in the Arm platform port. The private/public ECDSA key pair may be + found in ``plat/arm/board/common/rotpk``. + + Example of command line using RSA development keys: + + :: + + MBEDTLS_DIR= \ + make PLAT= TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33=/ \ + all fip + + The result of this build will be the bl1.bin and the fip.bin binaries. This + FIP will include the certificates corresponding to the Chain of Trust + described in the TBBR-client document. These certificates can also be found + in the output build directory. + +#. The optional FWU_FIP contains any additional images to be loaded from + Non-Volatile storage during the `Firmware Update`_ process. To build the + FWU_FIP, any FWU images required by the platform must be specified on the + command line. On Arm development platforms like Juno, these are: + + - NS_BL2U. The AP non-secure Firmware Updater image. + - SCP_BL2U. The SCP Firmware Update Configuration image. + + Example of Juno command line for generating both ``fwu`` and ``fwu_fip`` + targets using RSA development: + + :: + + MBEDTLS_DIR= \ + make PLAT=juno TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33=/ \ + SCP_BL2=/ \ + SCP_BL2U=/ \ + NS_BL2U=/ \ + all fip fwu_fip + + Note: The BL2U image will be built by default and added to the FWU_FIP. + The user may override this by adding ``BL2U=/`` + to the command line above. + + Note: Building and installing the non-secure and SCP FWU images (NS_BL1U, + NS_BL2U and SCP_BL2U) is outside the scope of this document. + + The result of this build will be bl1.bin, fip.bin and fwu_fip.bin binaries. + Both the FIP and FWU_FIP will include the certificates corresponding to the + Chain of Trust described in the TBBR-client document. These certificates + can also be found in the output build directory. + +Building the Certificate Generation Tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``cert_create`` tool is built as part of the TF-A build process when the +``fip`` make target is specified and TBB is enabled (as described in the +previous section), but it can also be built separately with the following +command: + +:: + + make PLAT= [DEBUG=1] [V=1] certtool + +For platforms that require their own IDs in certificate files, the generic +'cert_create' tool can be built with the following command. Note that the target +platform must define its IDs within a ``platform_oid.h`` header file for the +build to succeed. + +:: + + make PLAT= USE_TBBR_DEFS=0 [DEBUG=1] [V=1] certtool + +``DEBUG=1`` builds the tool in debug mode. ``V=1`` makes the build process more +verbose. The following command should be used to obtain help about the tool: + +:: + + ./tools/cert_create/cert_create -h + +Building a FIP for Juno and FVP +------------------------------- + +This section provides Juno and FVP specific instructions to build Trusted +Firmware, obtain the additional required firmware, and pack it all together in +a single FIP binary. It assumes that a `Linaro Release`_ has been installed. + +Note: Pre-built binaries for AArch32 are available from Linaro Release 16.12 +onwards. Before that release, pre-built binaries are only available for AArch64. + +Note: Follow the full instructions for one platform before switching to a +different one. Mixing instructions for different platforms may result in +corrupted binaries. + +Note: The uboot image downloaded by the Linaro workspace script does not always +match the uboot image packaged as BL33 in the corresponding fip file. It is +recommended to use the version that is packaged in the fip file using the +instructions below. + +Note: For the FVP, the kernel FDT is packaged in FIP during build and loaded +by the firmware at runtime. See `Obtaining the Flattened Device Trees`_ +section for more info on selecting the right FDT to use. + +#. Clean the working directory + + :: + + make realclean + +#. Obtain SCP_BL2 (Juno) and BL33 (all platforms) + + Use the fiptool to extract the SCP_BL2 and BL33 images from the FIP + package included in the Linaro release: + + :: + + # Build the fiptool + make [DEBUG=1] [V=1] fiptool + + # Unpack firmware images from Linaro FIP + ./tools/fiptool/fiptool unpack /fip.bin + + The unpack operation will result in a set of binary images extracted to the + current working directory. The SCP_BL2 image corresponds to + ``scp-fw.bin`` and BL33 corresponds to ``nt-fw.bin``. + + Note: The fiptool will complain if the images to be unpacked already + exist in the current directory. If that is the case, either delete those + files or use the ``--force`` option to overwrite. + + Note: For AArch32, the instructions below assume that nt-fw.bin is a normal + world boot loader that supports AArch32. + +#. Build TF-A images and create a new FIP for FVP + + :: + + # AArch64 + make PLAT=fvp BL33=nt-fw.bin all fip + + # AArch32 + make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33=nt-fw.bin all fip + +#. Build TF-A images and create a new FIP for Juno + + For AArch64: + + Building for AArch64 on Juno simply requires the addition of ``SCP_BL2`` + as a build parameter. + + :: + + make PLAT=juno BL33=nt-fw.bin SCP_BL2=scp-fw.bin all fip + + For AArch32: + + Hardware restrictions on Juno prevent cold reset into AArch32 execution mode, + therefore BL1 and BL2 must be compiled for AArch64, and BL32 is compiled + separately for AArch32. + + - Before building BL32, the environment variable ``CROSS_COMPILE`` must point + to the AArch32 Linaro cross compiler. + + :: + + export CROSS_COMPILE=/bin/arm-linux-gnueabihf- + + - Build BL32 in AArch32. + + :: + + make ARCH=aarch32 PLAT=juno AARCH32_SP=sp_min \ + RESET_TO_SP_MIN=1 JUNO_AARCH32_EL3_RUNTIME=1 bl32 + + - Save ``bl32.bin`` to a temporary location and clean the build products. + + :: + + cp /bl32.bin + make realclean + + - Before building BL1 and BL2, the environment variable ``CROSS_COMPILE`` + must point to the AArch64 Linaro cross compiler. + + :: + + export CROSS_COMPILE=/bin/aarch64-linux-gnu- + + - The following parameters should be used to build BL1 and BL2 in AArch64 + and point to the BL32 file. + + :: + + make ARCH=aarch64 PLAT=juno JUNO_AARCH32_EL3_RUNTIME=1 \ + BL33=nt-fw.bin SCP_BL2=scp-fw.bin \ + BL32=/bl32.bin all fip + +The resulting BL1 and FIP images may be found in: + +:: + + # Juno + ./build/juno/release/bl1.bin + ./build/juno/release/fip.bin + + # FVP + ./build/fvp/release/bl1.bin + ./build/fvp/release/fip.bin + + +Booting Firmware Update images +------------------------------------- + +When Firmware Update (FWU) is enabled there are at least 2 new images +that have to be loaded, the Non-Secure FWU ROM (NS-BL1U), and the +FWU FIP. + +Juno +~~~~ + +The new images must be programmed in flash memory by adding +an entry in the ``SITE1/HBI0262x/images.txt`` configuration file +on the Juno SD card (where ``x`` depends on the revision of the Juno board). +Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory +programming" for more information. User should ensure these do not +overlap with any other entries in the file. + +:: + + NOR10UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE + NOR10ADDRESS: 0x00400000 ;Image Flash Address [ns_bl2u_base_address] + NOR10FILE: \SOFTWARE\fwu_fip.bin ;Image File Name + NOR10LOAD: 00000000 ;Image Load Address + NOR10ENTRY: 00000000 ;Image Entry Point + + NOR11UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE + NOR11ADDRESS: 0x03EB8000 ;Image Flash Address [ns_bl1u_base_address] + NOR11FILE: \SOFTWARE\ns_bl1u.bin ;Image File Name + NOR11LOAD: 00000000 ;Image Load Address + +The address ns_bl1u_base_address is the value of NS_BL1U_BASE - 0x8000000. +In the same way, the address ns_bl2u_base_address is the value of +NS_BL2U_BASE - 0x8000000. + +FVP +~~~ + +The additional fip images must be loaded with: + +:: + + --data cluster0.cpu0="/ns_bl1u.bin"@0x0beb8000 [ns_bl1u_base_address] + --data cluster0.cpu0="/fwu_fip.bin"@0x08400000 [ns_bl2u_base_address] + +The address ns_bl1u_base_address is the value of NS_BL1U_BASE. +In the same way, the address ns_bl2u_base_address is the value of +NS_BL2U_BASE. + + +EL3 payloads alternative boot flow +---------------------------------- + +On a pre-production system, the ability to execute arbitrary, bare-metal code at +the highest exception level is required. It allows full, direct access to the +hardware, for example to run silicon soak tests. + +Although it is possible to implement some baremetal secure firmware from +scratch, this is a complex task on some platforms, depending on the level of +configuration required to put the system in the expected state. + +Rather than booting a baremetal application, a possible compromise is to boot +``EL3 payloads`` through TF-A instead. This is implemented as an alternative +boot flow, where a modified BL2 boots an EL3 payload, instead of loading the +other BL images and passing control to BL31. It reduces the complexity of +developing EL3 baremetal code by: + +- putting the system into a known architectural state; +- taking care of platform secure world initialization; +- loading the SCP_BL2 image if required by the platform. + +When booting an EL3 payload on Arm standard platforms, the configuration of the +TrustZone controller is simplified such that only region 0 is enabled and is +configured to permit secure access only. This gives full access to the whole +DRAM to the EL3 payload. + +The system is left in the same state as when entering BL31 in the default boot +flow. In particular: + +- Running in EL3; +- Current state is AArch64; +- Little-endian data access; +- All exceptions disabled; +- MMU disabled; +- Caches disabled. + +Booting an EL3 payload +~~~~~~~~~~~~~~~~~~~~~~ + +The EL3 payload image is a standalone image and is not part of the FIP. It is +not loaded by TF-A. Therefore, there are 2 possible scenarios: + +- The EL3 payload may reside in non-volatile memory (NVM) and execute in + place. In this case, booting it is just a matter of specifying the right + address in NVM through ``EL3_PAYLOAD_BASE`` when building TF-A. + +- The EL3 payload needs to be loaded in volatile memory (e.g. DRAM) at + run-time. + +To help in the latter scenario, the ``SPIN_ON_BL1_EXIT=1`` build option can be +used. The infinite loop that it introduces in BL1 stops execution at the right +moment for a debugger to take control of the target and load the payload (for +example, over JTAG). + +It is expected that this loading method will work in most cases, as a debugger +connection is usually available in a pre-production system. The user is free to +use any other platform-specific mechanism to load the EL3 payload, though. + +Booting an EL3 payload on FVP +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The EL3 payloads boot flow requires the CPU's mailbox to be cleared at reset for +the secondary CPUs holding pen to work properly. Unfortunately, its reset value +is undefined on the FVP platform and the FVP platform code doesn't clear it. +Therefore, one must modify the way the model is normally invoked in order to +clear the mailbox at start-up. + +One way to do that is to create an 8-byte file containing all zero bytes using +the following command: + +:: + + dd if=/dev/zero of=mailbox.dat bs=1 count=8 + +and pre-load it into the FVP memory at the mailbox address (i.e. ``0x04000000``) +using the following model parameters: + +:: + + --data cluster0.cpu0=mailbox.dat@0x04000000 [Base FVPs] + --data=mailbox.dat@0x04000000 [Foundation FVP] + +To provide the model with the EL3 payload image, the following methods may be +used: + +#. If the EL3 payload is able to execute in place, it may be programmed into + flash memory. On Base Cortex and AEM FVPs, the following model parameter + loads it at the base address of the NOR FLASH1 (the NOR FLASH0 is already + used for the FIP): + + :: + + -C bp.flashloader1.fname="/" + + On Foundation FVP, there is no flash loader component and the EL3 payload + may be programmed anywhere in flash using method 3 below. + +#. When using the ``SPIN_ON_BL1_EXIT=1`` loading method, the following DS-5 + command may be used to load the EL3 payload ELF image over JTAG: + + :: + + load /el3-payload.elf + +#. The EL3 payload may be pre-loaded in volatile memory using the following + model parameters: + + :: + + --data cluster0.cpu0="/el3-payload>"@address [Base FVPs] + --data="/"@address [Foundation FVP] + + The address provided to the FVP must match the ``EL3_PAYLOAD_BASE`` address + used when building TF-A. + +Booting an EL3 payload on Juno +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the EL3 payload is able to execute in place, it may be programmed in flash +memory by adding an entry in the ``SITE1/HBI0262x/images.txt`` configuration file +on the Juno SD card (where ``x`` depends on the revision of the Juno board). +Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory +programming" for more information. + +Alternatively, the same DS-5 command mentioned in the FVP section above can +be used to load the EL3 payload's ELF file over JTAG on Juno. + +Preloaded BL33 alternative boot flow +------------------------------------ + +Some platforms have the ability to preload BL33 into memory instead of relying +on TF-A to load it. This may simplify packaging of the normal world code and +improve performance in a development environment. When secure world cold boot +is complete, TF-A simply jumps to a BL33 base address provided at build time. + +For this option to be used, the ``PRELOADED_BL33_BASE`` build option has to be +used when compiling TF-A. For example, the following command will create a FIP +without a BL33 and prepare to jump to a BL33 image loaded at address +0x80000000: + +:: + + make PRELOADED_BL33_BASE=0x80000000 PLAT=fvp all fip + +Boot of a preloaded kernel image on Base FVP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following example uses a simplified boot flow by directly jumping from the +TF-A to the Linux kernel, which will use a ramdisk as filesystem. This can be +useful if both the kernel and the device tree blob (DTB) are already present in +memory (like in FVP). + +For example, if the kernel is loaded at ``0x80080000`` and the DTB is loaded at +address ``0x82000000``, the firmware can be built like this: + +:: + + CROSS_COMPILE=aarch64-linux-gnu- \ + make PLAT=fvp DEBUG=1 \ + RESET_TO_BL31=1 \ + ARM_LINUX_KERNEL_AS_BL33=1 \ + PRELOADED_BL33_BASE=0x80080000 \ + ARM_PRELOADED_DTB_BASE=0x82000000 \ + all fip + +Now, it is needed to modify the DTB so that the kernel knows the address of the +ramdisk. The following script generates a patched DTB from the provided one, +assuming that the ramdisk is loaded at address ``0x84000000``. Note that this +script assumes that the user is using a ramdisk image prepared for U-Boot, like +the ones provided by Linaro. If using a ramdisk without this header,the ``0x40`` +offset in ``INITRD_START`` has to be removed. + +.. code:: bash + + #!/bin/bash + + # Path to the input DTB + KERNEL_DTB=/ + # Path to the output DTB + PATCHED_KERNEL_DTB=/ + # Base address of the ramdisk + INITRD_BASE=0x84000000 + # Path to the ramdisk + INITRD=/ + + # Skip uboot header (64 bytes) + INITRD_START=$(printf "0x%x" $((${INITRD_BASE} + 0x40)) ) + INITRD_SIZE=$(stat -Lc %s ${INITRD}) + INITRD_END=$(printf "0x%x" $((${INITRD_BASE} + ${INITRD_SIZE})) ) + + CHOSEN_NODE=$(echo \ + "/ { \ + chosen { \ + linux,initrd-start = <${INITRD_START}>; \ + linux,initrd-end = <${INITRD_END}>; \ + }; \ + };") + + echo $(dtc -O dts -I dtb ${KERNEL_DTB}) ${CHOSEN_NODE} | \ + dtc -O dtb -o ${PATCHED_KERNEL_DTB} - + +And the FVP binary can be run with the following command: + +:: + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBAR=0x04020000 \ + -C cluster0.cpu1.RVBAR=0x04020000 \ + -C cluster0.cpu2.RVBAR=0x04020000 \ + -C cluster0.cpu3.RVBAR=0x04020000 \ + -C cluster1.cpu0.RVBAR=0x04020000 \ + -C cluster1.cpu1.RVBAR=0x04020000 \ + -C cluster1.cpu2.RVBAR=0x04020000 \ + -C cluster1.cpu3.RVBAR=0x04020000 \ + --data cluster0.cpu0="/bl31.bin"@0x04020000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Boot of a preloaded kernel image on Juno +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Trusted Firmware must be compiled in a similar way as for FVP explained +above. The process to load binaries to memory is the one explained in +`Booting an EL3 payload on Juno`_. + +Running the software on FVP +--------------------------- + +The latest version of the AArch64 build of TF-A has been tested on the following +Arm FVPs without shifted affinities, and that do not support threaded CPU cores +(64-bit host machine only). + +The FVP models used are Version 11.6 Build 45, unless otherwise stated. + +- ``FVP_Base_AEMv8A-AEMv8A`` +- ``FVP_Base_AEMv8A-AEMv8A-AEMv8A-AEMv8A-CCN502`` +- ``FVP_Base_RevC-2xAEMv8A`` +- ``FVP_Base_Cortex-A32x4`` +- ``FVP_Base_Cortex-A35x4`` +- ``FVP_Base_Cortex-A53x4`` +- ``FVP_Base_Cortex-A55x4+Cortex-A75x4`` +- ``FVP_Base_Cortex-A55x4`` +- ``FVP_Base_Cortex-A57x1-A53x1`` +- ``FVP_Base_Cortex-A57x2-A53x4`` +- ``FVP_Base_Cortex-A57x4-A53x4`` +- ``FVP_Base_Cortex-A57x4`` +- ``FVP_Base_Cortex-A72x4-A53x4`` +- ``FVP_Base_Cortex-A72x4`` +- ``FVP_Base_Cortex-A73x4-A53x4`` +- ``FVP_Base_Cortex-A73x4`` +- ``FVP_Base_Cortex-A75x4`` +- ``FVP_Base_Cortex-A76x4`` +- ``FVP_Base_Cortex-A76AEx4`` +- ``FVP_Base_Cortex-A76AEx8`` +- ``FVP_Base_Neoverse-N1x4`` +- ``FVP_Base_Deimos`` +- ``FVP_CSS_SGI-575`` (Version 11.3 build 42) +- ``FVP_CSS_SGM-775`` (Version 11.3 build 42) +- ``FVP_RD_E1Edge`` (Version 11.3 build 42) +- ``FVP_RD_N1Edge`` +- ``Foundation_Platform`` + +The latest version of the AArch32 build of TF-A has been tested on the following +Arm FVPs without shifted affinities, and that do not support threaded CPU cores +(64-bit host machine only). + +- ``FVP_Base_AEMv8A-AEMv8A`` +- ``FVP_Base_Cortex-A32x4`` + +NOTE: The ``FVP_Base_RevC-2xAEMv8A`` FVP only supports shifted affinities, which +is not compatible with legacy GIC configurations. Therefore this FVP does not +support these legacy GIC configurations. + +NOTE: The build numbers quoted above are those reported by launching the FVP +with the ``--version`` parameter. + +NOTE: Linaro provides a ramdisk image in prebuilt FVP configurations and full +file systems that can be downloaded separately. To run an FVP with a virtio +file system image an additional FVP configuration option +``-C bp.virtioblockdevice.image_path="/`` can be +used. + +NOTE: The software will not work on Version 1.0 of the Foundation FVP. +The commands below would report an ``unhandled argument`` error in this case. + +NOTE: FVPs can be launched with ``--cadi-server`` option such that a +CADI-compliant debugger (for example, Arm DS-5) can connect to and control its +execution. + +NOTE: Since FVP model Version 11.0 Build 11.0.34 and Version 8.5 Build 0.8.5202 +the internal synchronisation timings changed compared to older versions of the +models. The models can be launched with ``-Q 100`` option if they are required +to match the run time characteristics of the older versions. + +The Foundation FVP is a cut down version of the AArch64 Base FVP. It can be +downloaded for free from `Arm's website`_. + +The Cortex-A models listed above are also available to download from +`Arm's website`_. + +Please refer to the FVP documentation for a detailed description of the model +parameter options. A brief description of the important ones that affect TF-A +and normal world software behavior is provided below. + +Obtaining the Flattened Device Trees +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Depending on the FVP configuration and Linux configuration used, different +FDT files are required. FDT source files for the Foundation and Base FVPs can +be found in the TF-A source directory under ``fdts/``. The Foundation FVP has +a subset of the Base FVP components. For example, the Foundation FVP lacks +CLCD and MMC support, and has only one CPU cluster. + +Note: It is not recommended to use the FDTs built along the kernel because not +all FDTs are available from there. + +The dynamic configuration capability is enabled in the firmware for FVPs. +This means that the firmware can authenticate and load the FDT if present in +FIP. A default FDT is packaged into FIP during the build based on +the build configuration. This can be overridden by using the ``FVP_HW_CONFIG`` +or ``FVP_HW_CONFIG_DTS`` build options (refer to the +`Arm FVP platform specific build options`_ section for detail on the options). + +- ``fvp-base-gicv2-psci.dts`` + + For use with models such as the Cortex-A57-A53 Base FVPs without shifted + affinities and with Base memory map configuration. + +- ``fvp-base-gicv2-psci-aarch32.dts`` + + For use with models such as the Cortex-A32 Base FVPs without shifted + affinities and running Linux in AArch32 state with Base memory map + configuration. + +- ``fvp-base-gicv3-psci.dts`` + + For use with models such as the Cortex-A57-A53 Base FVPs without shifted + affinities and with Base memory map configuration and Linux GICv3 support. + +- ``fvp-base-gicv3-psci-1t.dts`` + + For use with models such as the AEMv8-RevC Base FVP with shifted affinities, + single threaded CPUs, Base memory map configuration and Linux GICv3 support. + +- ``fvp-base-gicv3-psci-dynamiq.dts`` + + For use with models as the Cortex-A55-A75 Base FVPs with shifted affinities, + single cluster, single threaded CPUs, Base memory map configuration and Linux + GICv3 support. + +- ``fvp-base-gicv3-psci-aarch32.dts`` + + For use with models such as the Cortex-A32 Base FVPs without shifted + affinities and running Linux in AArch32 state with Base memory map + configuration and Linux GICv3 support. + +- ``fvp-foundation-gicv2-psci.dts`` + + For use with Foundation FVP with Base memory map configuration. + +- ``fvp-foundation-gicv3-psci.dts`` + + (Default) For use with Foundation FVP with Base memory map configuration + and Linux GICv3 support. + +Running on the Foundation FVP with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``Foundation_Platform`` parameters should be used to boot Linux with +4 CPUs using the AArch64 build of TF-A. + +:: + + /Foundation_Platform \ + --cores=4 \ + --arm-v8.0 \ + --secure-memory \ + --visualization \ + --gicv3 \ + --data="/"@0x0 \ + --data="/"@0x08000000 \ + --data="/"@0x80080000 \ + --data="/"@0x84000000 + +Notes: + +- BL1 is loaded at the start of the Trusted ROM. +- The Firmware Image Package is loaded at the start of NOR FLASH0. +- The firmware loads the FDT packaged in FIP to the DRAM. The FDT load address + is specified via the ``hw_config_addr`` property in `TB_FW_CONFIG for FVP`_. +- The default use-case for the Foundation FVP is to use the ``--gicv3`` option + and enable the GICv3 device in the model. Note that without this option, + the Foundation FVP defaults to legacy (Versatile Express) memory map which + is not supported by TF-A. +- In order for TF-A to run correctly on the Foundation FVP, the architecture + versions must match. The Foundation FVP defaults to the highest v8.x + version it supports but the default build for TF-A is for v8.0. To avoid + issues either start the Foundation FVP to use v8.0 architecture using the + ``--arm-v8.0`` option, or build TF-A with an appropriate value for + ``ARM_ARCH_MINOR``. + +Running on the AEMv8 Base FVP with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_RevC-2xAEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch64 build of TF-A. + +:: + + /FVP_Base_RevC-2xAEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Note: The ``FVP_Base_RevC-2xAEMv8A`` has shifted affinities and requires a +specific DTS for all the CPUs to be loaded. + +Running on the AEMv8 Base FVP (AArch32) with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch32 build of TF-A. + +:: + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.CONFIG64=0 \ + -C cluster0.cpu1.CONFIG64=0 \ + -C cluster0.cpu2.CONFIG64=0 \ + -C cluster0.cpu3.CONFIG64=0 \ + -C cluster1.cpu0.CONFIG64=0 \ + -C cluster1.cpu1.CONFIG64=0 \ + -C cluster1.cpu2.CONFIG64=0 \ + -C cluster1.cpu3.CONFIG64=0 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the Cortex-A57-A53 Base FVP with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to +boot Linux with 8 CPUs using the AArch64 build of TF-A. + +:: + + /FVP_Base_Cortex-A57x4-A53x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the Cortex-A32 Base FVP (AArch32) with reset to BL1 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to +boot Linux with 4 CPUs using the AArch32 build of TF-A. + +:: + + /FVP_Base_Cortex-A32x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the AEMv8 Base FVP with reset to BL31 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_RevC-2xAEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch64 build of TF-A. + +:: + + /FVP_Base_RevC-2xAEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBAR=0x04010000 \ + -C cluster0.cpu1.RVBAR=0x04010000 \ + -C cluster0.cpu2.RVBAR=0x04010000 \ + -C cluster0.cpu3.RVBAR=0x04010000 \ + -C cluster1.cpu0.RVBAR=0x04010000 \ + -C cluster1.cpu1.RVBAR=0x04010000 \ + -C cluster1.cpu2.RVBAR=0x04010000 \ + -C cluster1.cpu3.RVBAR=0x04010000 \ + --data cluster0.cpu0="/"@0x04010000 \ + --data cluster0.cpu0="/"@0xff000000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Notes: + +- If Position Independent Executable (PIE) support is enabled for BL31 + in this config, it can be loaded at any valid address for execution. + +- Since a FIP is not loaded when using BL31 as reset entrypoint, the + ``--data=""@`` + parameter is needed to load the individual bootloader images in memory. + BL32 image is only needed if BL31 has been built to expect a Secure-EL1 + Payload. For the same reason, the FDT needs to be compiled from the DT source + and loaded via the ``--data cluster0.cpu0="/"@0x82000000`` + parameter. + +- The ``FVP_Base_RevC-2xAEMv8A`` has shifted affinities and requires a + specific DTS for all the CPUs to be loaded. + +- The ``-C cluster.cpu.RVBAR=@`` parameter, where + X and Y are the cluster and CPU numbers respectively, is used to set the + reset vector for each core. + +- Changing the default value of ``ARM_TSP_RAM_LOCATION`` will also require + changing the value of + ``--data=""@`` to the new value of + ``BL32_BASE``. + +Running on the AEMv8 Base FVP (AArch32) with reset to SP_MIN entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch32 build of TF-A. + +:: + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.CONFIG64=0 \ + -C cluster0.cpu1.CONFIG64=0 \ + -C cluster0.cpu2.CONFIG64=0 \ + -C cluster0.cpu3.CONFIG64=0 \ + -C cluster1.cpu0.CONFIG64=0 \ + -C cluster1.cpu1.CONFIG64=0 \ + -C cluster1.cpu2.CONFIG64=0 \ + -C cluster1.cpu3.CONFIG64=0 \ + -C cluster0.cpu0.RVBAR=0x04002000 \ + -C cluster0.cpu1.RVBAR=0x04002000 \ + -C cluster0.cpu2.RVBAR=0x04002000 \ + -C cluster0.cpu3.RVBAR=0x04002000 \ + -C cluster1.cpu0.RVBAR=0x04002000 \ + -C cluster1.cpu1.RVBAR=0x04002000 \ + -C cluster1.cpu2.RVBAR=0x04002000 \ + -C cluster1.cpu3.RVBAR=0x04002000 \ + --data cluster0.cpu0="/"@0x04002000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Note: The load address of ```` depends on the value ``BL32_BASE``. +It should match the address programmed into the RVBAR register as well. + +Running on the Cortex-A57-A53 Base FVP with reset to BL31 entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to +boot Linux with 8 CPUs using the AArch64 build of TF-A. + +:: + + /FVP_Base_Cortex-A57x4-A53x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBARADDR=0x04010000 \ + -C cluster0.cpu1.RVBARADDR=0x04010000 \ + -C cluster0.cpu2.RVBARADDR=0x04010000 \ + -C cluster0.cpu3.RVBARADDR=0x04010000 \ + -C cluster1.cpu0.RVBARADDR=0x04010000 \ + -C cluster1.cpu1.RVBARADDR=0x04010000 \ + -C cluster1.cpu2.RVBARADDR=0x04010000 \ + -C cluster1.cpu3.RVBARADDR=0x04010000 \ + --data cluster0.cpu0="/"@0x04010000 \ + --data cluster0.cpu0="/"@0xff000000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the Cortex-A32 Base FVP (AArch32) with reset to SP_MIN entrypoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to +boot Linux with 4 CPUs using the AArch32 build of TF-A. + +:: + + /FVP_Base_Cortex-A32x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBARADDR=0x04002000 \ + -C cluster0.cpu1.RVBARADDR=0x04002000 \ + -C cluster0.cpu2.RVBARADDR=0x04002000 \ + -C cluster0.cpu3.RVBARADDR=0x04002000 \ + --data cluster0.cpu0="/"@0x04002000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running the software on Juno +---------------------------- + +This version of TF-A has been tested on variants r0, r1 and r2 of Juno. + +To execute the software stack on Juno, the version of the Juno board recovery +image indicated in the `Linaro Release Notes`_ must be installed. If you have an +earlier version installed or are unsure which version is installed, please +re-install the recovery image by following the +`Instructions for using Linaro's deliverables on Juno`_. + +Preparing TF-A images +~~~~~~~~~~~~~~~~~~~~~ + +After building TF-A, the files ``bl1.bin`` and ``fip.bin`` need copying to the +``SOFTWARE/`` directory of the Juno SD card. + +Other Juno software information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Please visit the `Arm Platforms Portal`_ to get support and obtain any other Juno +software information. Please also refer to the `Juno Getting Started Guide`_ to +get more detailed information about the Juno Arm development platform and how to +configure it. + +Testing SYSTEM SUSPEND on Juno +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The SYSTEM SUSPEND is a PSCI API which can be used to implement system suspend +to RAM. For more details refer to section 5.16 of `PSCI`_. To test system suspend +on Juno, at the linux shell prompt, issue the following command: + +:: + + echo +10 > /sys/class/rtc/rtc0/wakealarm + echo -n mem > /sys/power/state + +The Juno board should suspend to RAM and then wakeup after 10 seconds due to +wakeup interrupt from RTC. + +-------------- + +*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* + +.. _arm Developer page: https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloads +.. _Linaro: `Linaro Release Notes`_ +.. _Linaro Release: `Linaro Release Notes`_ +.. _Linaro Release Notes: https://community.arm.com/dev-platforms/w/docs/226/old-release-notes +.. _Linaro instructions: https://community.arm.com/dev-platforms/w/docs/304/arm-reference-platforms-deliverables +.. _Instructions for using Linaro's deliverables on Juno: https://community.arm.com/dev-platforms/w/docs/303/juno +.. _Arm Platforms Portal: https://community.arm.com/dev-platforms/ +.. _Development Studio 5 (DS-5): https://developer.arm.com/products/software-development-tools/ds-5-development-studio +.. _arm-trusted-firmware-a project page: https://review.trustedfirmware.org/admin/projects/TF-A/trusted-firmware-a +.. _`Linux Coding Style`: https://www.kernel.org/doc/html/latest/process/coding-style.html +.. _Linux master tree: https://github.com/torvalds/linux/tree/master/ +.. _Dia: https://wiki.gnome.org/Apps/Dia/Download +.. _here: psci-lib-integration-guide.rst +.. _Trusted Board Boot: trusted-board-boot.rst +.. _TB_FW_CONFIG for FVP: ../plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts +.. _Secure-EL1 Payloads and Dispatchers: firmware-design.rst#user-content-secure-el1-payloads-and-dispatchers +.. _Firmware Update: firmware-update.rst +.. _Firmware Design: firmware-design.rst +.. _mbed TLS Repository: https://github.com/ARMmbed/mbedtls.git +.. _mbed TLS Security Center: https://tls.mbed.org/security +.. _Arm's website: `FVP models`_ +.. _FVP models: https://developer.arm.com/products/system-design/fixed-virtual-platforms +.. _Juno Getting Started Guide: http://infocenter.arm.com/help/topic/com.arm.doc.dui0928e/DUI0928E_juno_arm_development_platform_gsg.pdf +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Secure Partition Manager Design guide: secure-partition-manager-design.rst +.. _`Trusted Firmware-A Coding Guidelines`: coding-guidelines.rst +.. _`Library at ROM`: romlib-design.rst diff --git a/docs/image-terminology.rst b/docs/image-terminology.rst deleted file mode 100644 index 4dc1d73..0000000 --- a/docs/image-terminology.rst +++ /dev/null @@ -1,180 +0,0 @@ -Image Terminology -================= - -.. section-numbering:: - :suffix: . - -.. contents:: - -This page contains the current name, abbreviated name and purpose of the various -images referred to in the Trusted Firmware project. - -General Notes -------------- - -- Some of the names and abbreviated names have changed to accomodate new - requirements. The changed names are as backward compatible as possible to - minimize confusion. Where applicable, the previous names are indicated. Some - code, documentation and build artefacts may still refer to the previous names; - these will inevitably take time to catch up. - -- The main name change is to prefix each image with the processor it corresponds - to (for example ``AP_``, ``SCP_``, ...). In situations where there is no - ambiguity (for example, within AP specific code/documentation), it is - permitted to omit the processor prefix (for example, just BL1 instead of - ``AP_BL1``). - -- Previously, the format for 3rd level images had 2 forms; ``BL3`` was either - suffixed with a dash ("-") followed by a number (for example, ``BL3-1``) or a - subscript number, depending on whether rich text formatting was available. - This was confusing and often the dash gets omitted in practice. Therefore the - new form is to just omit the dash and not use subscript formatting. - -- The names no longer contain dash ("-") characters at all. In some places (for - example, function names) it's not possible to use this character. All dashes - are either removed or replaced by underscores ("_"). - -- The abbreviation BL stands for BootLoader. This is a historical anomaly. - Clearly, many of these images are not BootLoaders, they are simply firmware - images. However, the BL abbreviation is now widely used and is retained for - backwards compatibility. - -- The image names are not case sensitive. For example, ``bl1`` is - interchangeable with ``BL1``, although mixed case should be avoided. - -Trusted Firmware Images ------------------------ - -AP Boot ROM: ``AP_BL1`` -~~~~~~~~~~~~~~~~~~~~~~~ - -Typically, this is the first code to execute on the AP and cannot be modified. -Its primary purpose is to perform the minimum intialization necessary to load -and authenticate an updateable AP firmware image into an executable RAM -location, then hand-off control to that image. - -AP RAM Firmware: ``AP_BL2`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This is the 2nd stage AP firmware. It is currently also known as the "Trusted -Boot Firmware". Its primary purpose is to perform any additional initialization -required to load and authenticate all 3rd level firmware images into their -executable RAM locations, then hand-off control to the EL3 Runtime Firmware. - -EL3 Runtime Firmware: ``AP_BL31`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Also known as "SoC AP firmware" or "EL3 monitor firmware". Its primary purpose -is to handle transitions between the normal and secure world. - -Secure-EL1 Payload (SP): ``AP_BL32`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Typically this is a TEE or Trusted OS, providing runtime secure services to the -normal world. However, it may refer to a more abstract Secure-EL1 Payload (SP). -Note that this abbreviation should only be used in systems where there is a -single or primary image executing at Secure-EL1. In systems where there are -potentially multiple SPs and there is no concept of a primary SP, this -abbreviation should be avoided; use the recommended **Other AP 3rd level -images** abbreviation instead. - -AP Normal World Firmware: ``AP_BL33`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For example, UEFI or uboot. Its primary purpose is to boot a normal world OS. - -Other AP 3rd level images: ``AP_BL3_XXX`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The abbreviated names of the existing 3rd level images imply a load/execution -ordering (for example, ``AP_BL31 -> AP_BL32 -> AP_BL33``). Some systems may -have additional images and/or a different load/execution ordering. The -abbreviated names of the existing images are retained for backward compatibility -but new 3rd level images should be suffixed with an underscore followed by text -identifier, not a number. - -In systems where 3rd level images are provided by different vendors, the -abbreviated name should identify the vendor as well as the image -function. For example, ``AP_BL3_ARM_RAS``. - -SCP Boot ROM: ``SCP_BL1`` (previously ``BL0``) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Typically, this is the first code to execute on the SCP and cannot be modified. -Its primary purpose is to perform the minimum intialization necessary to load -and authenticate an updateable SCP firmware image into an executable RAM -location, then hand-off control to that image. This may be performed in -conjunction with other processor firmware (for example, ``AP_BL1`` and -``AP_BL2``). - -This image was previously abbreviated as ``BL0`` but in some systems, the SCP -may directly load/authenticate its own firmware. In these systems, it doesn't -make sense to interleave the image terminology for AP and SCP; both AP and SCP -Boot ROMs are ``BL1`` from their own point of view. - -SCP RAM Firmware: ``SCP_BL2`` (previously ``BL3-0``) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This is the 2nd stage SCP firmware. It is currently also known as the "SCP -runtime firmware" but it could potentially be an intermediate firmware if the -SCP needs to load/authenticate multiple 3rd level images in future. - -This image was previously abbreviated as BL3-0 but from the SCP's point of view, -this has always been the 2nd stage firmware. The previous name is too -AP-centric. - -Firmware Update (FWU) Images ----------------------------- - -The terminology for these images has not been widely adopted yet but they have -to be considered in a production Trusted Board Boot solution. - -AP Firmware Update Boot ROM: ``AP_NS_BL1U`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Typically, this is the first normal world code to execute on the AP during a -firmware update operation, and cannot be modified. Its primary purpose is to -load subequent firmware update images from an external interface and communicate -with ``AP_BL1`` to authenticate those images. - -During firmware update, there are (potentially) multiple transitions between the -secure and normal world. The "level" of the BL image is relative to the world -it's in so it makes sense to encode "NS" in the normal world images. The absence -of "NS" implies a secure world image. - -AP Firmware Update Config: ``AP_BL2U`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This image does the minimum necessary AP secure world configuration required to -complete the firmware update operation. It is potentially a subset of ``AP_BL2`` -functionality. - -SCP Firmware Update Config: ``SCP_BL2U`` (previously ``BL2-U0``) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This image does the minimum necessary SCP secure world configuration required to -complete the firmware update operation. It is potentially a subset of -``SCP_BL2`` functionality. - -AP Firmware Updater: ``AP_NS_BL2U`` (previously ``BL3-U``) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This is the 2nd stage AP normal world firmware updater. Its primary purpose is -to load a new set of firmware images from an external interface and write them -into non-volatile storage. - -Other Processor Firmware Images -------------------------------- - -Some systems may have additional processors to the AP and SCP. For example, a -Management Control Processor (MCP). Images for these processors should follow -the same terminology, with the processor abbreviation prefix, followed by -underscore and the level of the firmware image. - -For example, - -MCP Boot ROM: ``MCP_BL1`` -~~~~~~~~~~~~~~~~~~~~~~~~~ - -MCP RAM Firmware: ``MCP_BL2`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/index.rst b/docs/index.rst index a6c1ca9..f4c7386 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,43 +1,21 @@ -Arm Trusted Firmware-A Documentation Index -========================================== +Trusted Firmware-A Documentation +================================ .. toctree:: :maxdepth: 1 - :caption: Design Documents + :caption: Contents - arm-sip-service - auth-framework - - .. toctree:: - :maxdepth: 1 - :caption: Release Notes + getting_started/index + process/index + components/index + design/index + plat/index + perf/index + security_advisories/index + readme change-log - - .. toctree:: - :maxdepth: 1 - :caption: Guides - - .. toctree:: - :maxdepth: 1 - :caption: Policies - cpu-specific-build-macros - exception-handling - firmware-design - firmware-update - interrupt-framework-design - platform-compatibility-policy - platform-interrupt-controller-API - porting-guide - psci-lib-integration-guide - psci-pd-tree - ras - reset-design - rt-svc-writers-guide - sdei - secure-partition-manager-design - trusted-board-boot - user-guide - xlat-tables-lib-v2-design + maintainers + acknowledgements Indices and tables ================== diff --git a/docs/interrupt-framework-design.rst b/docs/interrupt-framework-design.rst deleted file mode 100644 index 58130cd..0000000 --- a/docs/interrupt-framework-design.rst +++ /dev/null @@ -1,1025 +0,0 @@ -Trusted Firmware-A interrupt management design guide -==================================================== - - -.. section-numbering:: - :suffix: . - -.. contents:: - -This framework is responsible for managing interrupts routed to EL3. It also -allows EL3 software to configure the interrupt routing behavior. Its main -objective is to implement the following two requirements. - -#. It should be possible to route interrupts meant to be handled by secure - software (Secure interrupts) to EL3, when execution is in non-secure state - (normal world). The framework should then take care of handing control of - the interrupt to either software in EL3 or Secure-EL1 depending upon the - software configuration and the GIC implementation. This requirement ensures - that secure interrupts are under the control of the secure software with - respect to their delivery and handling without the possibility of - intervention from non-secure software. - -#. It should be possible to route interrupts meant to be handled by - non-secure software (Non-secure interrupts) to the last executed exception - level in the normal world when the execution is in secure world at - exception levels lower than EL3. This could be done with or without the - knowledge of software executing in Secure-EL1/Secure-EL0. The choice of - approach should be governed by the secure software. This requirement - ensures that non-secure software is able to execute in tandem with the - secure software without overriding it. - -Concepts --------- - -Interrupt types -~~~~~~~~~~~~~~~ - -The framework categorises an interrupt to be one of the following depending upon -the exception level(s) it is handled in. - -#. Secure EL1 interrupt. This type of interrupt can be routed to EL3 or - Secure-EL1 depending upon the security state of the current execution - context. It is always handled in Secure-EL1. - -#. Non-secure interrupt. This type of interrupt can be routed to EL3, - Secure-EL1, Non-secure EL1 or EL2 depending upon the security state of the - current execution context. It is always handled in either Non-secure EL1 - or EL2. - -#. EL3 interrupt. This type of interrupt can be routed to EL3 or Secure-EL1 - depending upon the security state of the current execution context. It is - always handled in EL3. - -The following constants define the various interrupt types in the framework -implementation. - -:: - - #define INTR_TYPE_S_EL1 0 - #define INTR_TYPE_EL3 1 - #define INTR_TYPE_NS 2 - -Routing model -~~~~~~~~~~~~~ - -A type of interrupt can be either generated as an FIQ or an IRQ. The target -exception level of an interrupt type is configured through the FIQ and IRQ bits -in the Secure Configuration Register at EL3 (``SCR_EL3.FIQ`` and ``SCR_EL3.IRQ`` -bits). When ``SCR_EL3.FIQ``\ =1, FIQs are routed to EL3. Otherwise they are routed -to the First Exception Level (FEL) capable of handling interrupts. When -``SCR_EL3.IRQ``\ =1, IRQs are routed to EL3. Otherwise they are routed to the -FEL. This register is configured independently by EL3 software for each security -state prior to entry into a lower exception level in that security state. - -A routing model for a type of interrupt (generated as FIQ or IRQ) is defined as -its target exception level for each security state. It is represented by a -single bit for each security state. A value of ``0`` means that the interrupt -should be routed to the FEL. A value of ``1`` means that the interrupt should be -routed to EL3. A routing model is applicable only when execution is not in EL3. - -The default routing model for an interrupt type is to route it to the FEL in -either security state. - -Valid routing models -~~~~~~~~~~~~~~~~~~~~ - -The framework considers certain routing models for each type of interrupt to be -incorrect as they conflict with the requirements mentioned in Section 1. The -following sub-sections describe all the possible routing models and specify -which ones are valid or invalid. EL3 interrupts are currently supported only -for GIC version 3.0 (Arm GICv3) and only the Secure-EL1 and Non-secure interrupt -types are supported for GIC version 2.0 (Arm GICv2) (see `Assumptions in -Interrupt Management Framework`_). The terminology used in the following -sub-sections is explained below. - -#. **CSS**. Current Security State. ``0`` when secure and ``1`` when non-secure - -#. **TEL3**. Target Exception Level 3. ``0`` when targeted to the FEL. ``1`` when - targeted to EL3. - -Secure-EL1 interrupts -^^^^^^^^^^^^^^^^^^^^^ - -#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in - secure state. This is a valid routing model as secure software is in - control of handling secure interrupts. - -#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure - state. This is a valid routing model as secure software in EL3 can - handover the interrupt to Secure-EL1 for handling. - -#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in - non-secure state. This is an invalid routing model as a secure interrupt - is not visible to the secure software which violates the motivation behind - the Arm Security Extensions. - -#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in - non-secure state. This is a valid routing model as secure software in EL3 - can handover the interrupt to Secure-EL1 for handling. - -Non-secure interrupts -^^^^^^^^^^^^^^^^^^^^^ - -#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in - secure state. This allows the secure software to trap non-secure - interrupts, perform its book-keeping and hand the interrupt to the - non-secure software through EL3. This is a valid routing model as secure - software is in control of how its execution is preempted by non-secure - interrupts. - -#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure - state. This is a valid routing model as secure software in EL3 can save - the state of software in Secure-EL1/Secure-EL0 before handing the - interrupt to non-secure software. This model requires additional - coordination between Secure-EL1 and EL3 software to ensure that the - former's state is correctly saved by the latter. - -#. **CSS=1, TEL3=0**. Interrupt is routed to FEL when execution is in - non-secure state. This is a valid routing model as a non-secure interrupt - is handled by non-secure software. - -#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in - non-secure state. This is an invalid routing model as there is no valid - reason to route the interrupt to EL3 software and then hand it back to - non-secure software for handling. - -EL3 interrupts -^^^^^^^^^^^^^^ - -#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in - Secure-EL1/Secure-EL0. This is a valid routing model as secure software - in Secure-EL1/Secure-EL0 is in control of how its execution is preempted - by EL3 interrupt and can handover the interrupt to EL3 for handling. - - However, when ``EL3_EXCEPTION_HANDLING`` is ``1``, this routing model is - invalid as EL3 interrupts are unconditionally routed to EL3, and EL3 - interrupts will always preempt Secure EL1/EL0 execution. See `exception - handling`__ documentation. - - .. __: exception-handling.rst#interrupt-handling - -#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in - Secure-EL1/Secure-EL0. This is a valid routing model as secure software - in EL3 can handle the interrupt. - -#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in - non-secure state. This is an invalid routing model as a secure interrupt - is not visible to the secure software which violates the motivation behind - the Arm Security Extensions. - -#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in - non-secure state. This is a valid routing model as secure software in EL3 - can handle the interrupt. - -Mapping of interrupt type to signal -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The framework is meant to work with any interrupt controller implemented by a -platform. A interrupt controller could generate a type of interrupt as either an -FIQ or IRQ signal to the CPU depending upon the current security state. The -mapping between the type and signal is known only to the platform. The framework -uses this information to determine whether the IRQ or the FIQ bit should be -programmed in ``SCR_EL3`` while applying the routing model for a type of -interrupt. The platform provides this information through the -``plat_interrupt_type_to_line()`` API (described in the -`Porting Guide`_). For example, on the FVP port when the platform uses an Arm GICv2 -interrupt controller, Secure-EL1 interrupts are signaled through the FIQ signal -while Non-secure interrupts are signaled through the IRQ signal. This applies -when execution is in either security state. - -Effect of mapping of several interrupt types to one signal -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It should be noted that if more than one interrupt type maps to a single -interrupt signal, and if any one of the interrupt type sets **TEL3=1** for a -particular security state, then interrupt signal will be routed to EL3 when in -that security state. This means that all the other interrupt types using the -same interrupt signal will be forced to the same routing model. This should be -borne in mind when choosing the routing model for an interrupt type. - -For example, in Arm GICv3, when the execution context is Secure-EL1/ -Secure-EL0, both the EL3 and the non secure interrupt types map to the FIQ -signal. So if either one of the interrupt type sets the routing model so -that **TEL3=1** when **CSS=0**, the FIQ bit in ``SCR_EL3`` will be programmed to -route the FIQ signal to EL3 when executing in Secure-EL1/Secure-EL0, thereby -effectively routing the other interrupt type also to EL3. - -Assumptions in Interrupt Management Framework ---------------------------------------------- - -The framework makes the following assumptions to simplify its implementation. - -#. Although the framework has support for 2 types of secure interrupts (EL3 - and Secure-EL1 interrupt), only interrupt controller architectures - like Arm GICv3 has architectural support for EL3 interrupts in the form of - Group 0 interrupts. In Arm GICv2, all secure interrupts are assumed to be - handled in Secure-EL1. They can be delivered to Secure-EL1 via EL3 but they - cannot be handled in EL3. - -#. Interrupt exceptions (``PSTATE.I`` and ``F`` bits) are masked during execution - in EL3. - -#. Interrupt management: the following sections describe how interrupts are - managed by the interrupt handling framework. This entails: - - #. Providing an interface to allow registration of a handler and - specification of the routing model for a type of interrupt. - - #. Implementing support to hand control of an interrupt type to its - registered handler when the interrupt is generated. - -Both aspects of interrupt management involve various components in the secure -software stack spanning from EL3 to Secure-EL1. These components are described -in the section `Software components`_. The framework stores information -associated with each type of interrupt in the following data structure. - -.. code:: c - - typedef struct intr_type_desc { - interrupt_type_handler_t handler; - uint32_t flags; - uint32_t scr_el3[2]; - } intr_type_desc_t; - -The ``flags`` field stores the routing model for the interrupt type in -bits[1:0]. Bit[0] stores the routing model when execution is in the secure -state. Bit[1] stores the routing model when execution is in the non-secure -state. As mentioned in Section `Routing model`_, a value of ``0`` implies that -the interrupt should be targeted to the FEL. A value of ``1`` implies that it -should be targeted to EL3. The remaining bits are reserved and SBZ. The helper -macro ``set_interrupt_rm_flag()`` should be used to set the bits in the -``flags`` parameter. - -The ``scr_el3[2]`` field also stores the routing model but as a mapping of the -model in the ``flags`` field to the corresponding bit in the ``SCR_EL3`` for each -security state. - -The framework also depends upon the platform port to configure the interrupt -controller to distinguish between secure and non-secure interrupts. The platform -is expected to be aware of the secure devices present in the system and their -associated interrupt numbers. It should configure the interrupt controller to -enable the secure interrupts, ensure that their priority is always higher than -the non-secure interrupts and target them to the primary CPU. It should also -export the interface described in the `Porting Guide`_ to enable -handling of interrupts. - -In the remainder of this document, for the sake of simplicity a Arm GICv2 system -is considered and it is assumed that the FIQ signal is used to generate Secure-EL1 -interrupts and the IRQ signal is used to generate non-secure interrupts in either -security state. EL3 interrupts are not considered. - -Software components -------------------- - -Roles and responsibilities for interrupt management are sub-divided between the -following components of software running in EL3 and Secure-EL1. Each component is -briefly described below. - -#. EL3 Runtime Firmware. This component is common to all ports of TF-A. - -#. Secure Payload Dispatcher (SPD) service. This service interfaces with the - Secure Payload (SP) software which runs in Secure-EL1/Secure-EL0 and is - responsible for switching execution between secure and non-secure states. - A switch is triggered by a Secure Monitor Call and it uses the APIs - exported by the Context management library to implement this functionality. - Switching execution between the two security states is a requirement for - interrupt management as well. This results in a significant dependency on - the SPD service. TF-A implements an example Test Secure Payload Dispatcher - (TSPD) service. - - An SPD service plugs into the EL3 runtime firmware and could be common to - some ports of TF-A. - -#. Secure Payload (SP). On a production system, the Secure Payload corresponds - to a Secure OS which runs in Secure-EL1/Secure-EL0. It interfaces with the - SPD service to manage communication with non-secure software. TF-A - implements an example secure payload called Test Secure Payload (TSP) - which runs only in Secure-EL1. - - A Secure payload implementation could be common to some ports of TF-A, - just like the SPD service. - -Interrupt registration ----------------------- - -This section describes in detail the role of each software component (see -`Software components`_) during the registration of a handler for an interrupt -type. - -EL3 runtime firmware -~~~~~~~~~~~~~~~~~~~~ - -This component declares the following prototype for a handler of an interrupt type. - -.. code:: c - - typedef uint64_t (*interrupt_type_handler_t)(uint32_t id, - uint32_t flags, - void *handle, - void *cookie); - -The ``id`` is parameter is reserved and could be used in the future for passing -the interrupt id of the highest pending interrupt only if there is a foolproof -way of determining the id. Currently it contains ``INTR_ID_UNAVAILABLE``. - -The ``flags`` parameter contains miscellaneous information as follows. - -#. Security state, bit[0]. This bit indicates the security state of the lower - exception level when the interrupt was generated. A value of ``1`` means - that it was in the non-secure state. A value of ``0`` indicates that it was - in the secure state. This bit can be used by the handler to ensure that - interrupt was generated and routed as per the routing model specified - during registration. - -#. Reserved, bits[31:1]. The remaining bits are reserved for future use. - -The ``handle`` parameter points to the ``cpu_context`` structure of the current CPU -for the security state specified in the ``flags`` parameter. - -Once the handler routine completes, execution will return to either the secure -or non-secure state. The handler routine must return a pointer to -``cpu_context`` structure of the current CPU for the target security state. On -AArch64, this return value is currently ignored by the caller as the -appropriate ``cpu_context`` to be used is expected to be set by the handler -via the context management library APIs. -A portable interrupt handler implementation must set the target context both in -the structure pointed to by the returned pointer and via the context management -library APIs. The handler should treat all error conditions as critical errors -and take appropriate action within its implementation e.g. use assertion -failures. - -The runtime firmware provides the following API for registering a handler for a -particular type of interrupt. A Secure Payload Dispatcher service should use -this API to register a handler for Secure-EL1 and optionally for non-secure -interrupts. This API also requires the caller to specify the routing model for -the type of interrupt. - -.. code:: c - - int32_t register_interrupt_type_handler(uint32_t type, - interrupt_type_handler handler, - uint64_t flags); - -The ``type`` parameter can be one of the three interrupt types listed above i.e. -``INTR_TYPE_S_EL1``, ``INTR_TYPE_NS`` & ``INTR_TYPE_EL3``. The ``flags`` parameter -is as described in Section 2. - -The function will return ``0`` upon a successful registration. It will return -``-EALREADY`` in case a handler for the interrupt type has already been -registered. If the ``type`` is unrecognised or the ``flags`` or the ``handler`` are -invalid it will return ``-EINVAL``. - -Interrupt routing is governed by the configuration of the ``SCR_EL3.FIQ/IRQ`` bits -prior to entry into a lower exception level in either security state. The -context management library maintains a copy of the ``SCR_EL3`` system register for -each security state in the ``cpu_context`` structure of each CPU. It exports the -following APIs to let EL3 Runtime Firmware program and retrieve the routing -model for each security state for the current CPU. The value of ``SCR_EL3`` stored -in the ``cpu_context`` is used by the ``el3_exit()`` function to program the -``SCR_EL3`` register prior to returning from the EL3 exception level. - -.. code:: c - - uint32_t cm_get_scr_el3(uint32_t security_state); - void cm_write_scr_el3_bit(uint32_t security_state, - uint32_t bit_pos, - uint32_t value); - -``cm_get_scr_el3()`` returns the value of the ``SCR_EL3`` register for the specified -security state of the current CPU. ``cm_write_scr_el3()`` writes a ``0`` or ``1`` to -the bit specified by ``bit_pos``. ``register_interrupt_type_handler()`` invokes -``set_routing_model()`` API which programs the ``SCR_EL3`` according to the routing -model using the ``cm_get_scr_el3()`` and ``cm_write_scr_el3_bit()`` APIs. - -It is worth noting that in the current implementation of the framework, the EL3 -runtime firmware is responsible for programming the routing model. The SPD is -responsible for ensuring that the routing model has been adhered to upon -receiving an interrupt. - -.. _spd-int-registration: - -Secure payload dispatcher -~~~~~~~~~~~~~~~~~~~~~~~~~ - -A SPD service is responsible for determining and maintaining the interrupt -routing model supported by itself and the Secure Payload. It is also responsible -for ferrying interrupts between secure and non-secure software depending upon -the routing model. It could determine the routing model at build time or at -runtime. It must use this information to register a handler for each interrupt -type using the ``register_interrupt_type_handler()`` API in EL3 runtime firmware. - -If the routing model is not known to the SPD service at build time, then it must -be provided by the SP as the result of its initialisation. The SPD should -program the routing model only after SP initialisation has completed e.g. in the -SPD initialisation function pointed to by the ``bl32_init`` variable. - -The SPD should determine the mechanism to pass control to the Secure Payload -after receiving an interrupt from the EL3 runtime firmware. This information -could either be provided to the SPD service at build time or by the SP at -runtime. - -Test secure payload dispatcher behavior -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**Note:** where this document discusses ``TSP_NS_INTR_ASYNC_PREEMPT`` as being -``1``, the same results also apply when ``EL3_EXCEPTION_HANDLING`` is ``1``. - -The TSPD only handles Secure-EL1 interrupts and is provided with the following -routing model at build time. - -- Secure-EL1 interrupts are routed to EL3 when execution is in non-secure - state and are routed to the FEL when execution is in the secure state - i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=1** for Secure-EL1 interrupts - -- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is zero, the default routing - model is used for non-secure interrupts. They are routed to the FEL in - either security state i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=0** for - Non-secure interrupts. - -- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, then the - non secure interrupts are routed to EL3 when execution is in secure state - i.e **CSS=0, TEL3=1** for non-secure interrupts. This effectively preempts - Secure-EL1. The default routing model is used for non secure interrupts in - non-secure state. i.e **CSS=1, TEL3=0**. - -It performs the following actions in the ``tspd_init()`` function to fulfill the -requirements mentioned earlier. - -#. It passes control to the Test Secure Payload to perform its - initialisation. The TSP provides the address of the vector table - ``tsp_vectors`` in the SP which also includes the handler for Secure-EL1 - interrupts in the ``sel1_intr_entry`` field. The TSPD passes control to the TSP at - this address when it receives a Secure-EL1 interrupt. - - The handover agreement between the TSP and the TSPD requires that the TSPD - masks all interrupts (``PSTATE.DAIF`` bits) when it calls - ``tsp_sel1_intr_entry()``. The TSP has to preserve the callee saved general - purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use - ``x0-x18`` to enable its C runtime. - -#. The TSPD implements a handler function for Secure-EL1 interrupts. This - function is registered with the EL3 runtime firmware using the - ``register_interrupt_type_handler()`` API as follows - - .. code:: c - - /* Forward declaration */ - interrupt_type_handler tspd_secure_el1_interrupt_handler; - int32_t rc, flags = 0; - set_interrupt_rm_flag(flags, NON_SECURE); - rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, - tspd_secure_el1_interrupt_handler, - flags); - if (rc) - panic(); - -#. When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, the TSPD - implements a handler function for non-secure interrupts. This function is - registered with the EL3 runtime firmware using the - ``register_interrupt_type_handler()`` API as follows - - .. code:: c - - /* Forward declaration */ - interrupt_type_handler tspd_ns_interrupt_handler; - int32_t rc, flags = 0; - set_interrupt_rm_flag(flags, SECURE); - rc = register_interrupt_type_handler(INTR_TYPE_NS, - tspd_ns_interrupt_handler, - flags); - if (rc) - panic(); - -.. _sp-int-registration: - -Secure payload -~~~~~~~~~~~~~~ - -A Secure Payload must implement an interrupt handling framework at Secure-EL1 -(Secure-EL1 IHF) to support its chosen interrupt routing model. Secure payload -execution will alternate between the below cases. - -#. In the code where IRQ, FIQ or both interrupts are enabled, if an interrupt - type is targeted to the FEL, then it will be routed to the Secure-EL1 - exception vector table. This is defined as the **asynchronous mode** of - handling interrupts. This mode applies to both Secure-EL1 and non-secure - interrupts. - -#. In the code where both interrupts are disabled, if an interrupt type is - targeted to the FEL, then execution will eventually migrate to the - non-secure state. Any non-secure interrupts will be handled as described - in the routing model where **CSS=1 and TEL3=0**. Secure-EL1 interrupts - will be routed to EL3 (as per the routing model where **CSS=1 and - TEL3=1**) where the SPD service will hand them to the SP. This is defined - as the **synchronous mode** of handling interrupts. - -The interrupt handling framework implemented by the SP should support one or -both these interrupt handling models depending upon the chosen routing model. - -The following list briefly describes how the choice of a valid routing model -(see `Valid routing models`_) effects the implementation of the Secure-EL1 -IHF. If the choice of the interrupt routing model is not known to the SPD -service at compile time, then the SP should pass this information to the SPD -service at runtime during its initialisation phase. - -As mentioned earlier, an Arm GICv2 system is considered and it is assumed that -the FIQ signal is used to generate Secure-EL1 interrupts and the IRQ signal -is used to generate non-secure interrupts in either security state. - -Secure payload IHF design w.r.t secure-EL1 interrupts -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#. **CSS=0, TEL3=0**. If ``PSTATE.F=0``, Secure-EL1 interrupts will be - triggered at one of the Secure-EL1 FIQ exception vectors. The Secure-EL1 - IHF should implement support for handling FIQ interrupts asynchronously. - - If ``PSTATE.F=1`` then Secure-EL1 interrupts will be handled as per the - synchronous interrupt handling model. The SP could implement this scenario - by exporting a separate entrypoint for Secure-EL1 interrupts to the SPD - service during the registration phase. The SPD service would also need to - know the state of the system, general purpose and the ``PSTATE`` registers - in which it should arrange to return execution to the SP. The SP should - provide this information in an implementation defined way during the - registration phase if it is not known to the SPD service at build time. - -#. **CSS=1, TEL3=1**. Interrupts are routed to EL3 when execution is in - non-secure state. They should be handled through the synchronous interrupt - handling model as described in 1. above. - -#. **CSS=0, TEL3=1**. Secure-EL1 interrupts are routed to EL3 when execution - is in secure state. They will not be visible to the SP. The ``PSTATE.F`` bit - in Secure-EL1/Secure-EL0 will not mask FIQs. The EL3 runtime firmware will - call the handler registered by the SPD service for Secure-EL1 interrupts. - Secure-EL1 IHF should then handle all Secure-EL1 interrupt through the - synchronous interrupt handling model described in 1. above. - -Secure payload IHF design w.r.t non-secure interrupts -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#. **CSS=0, TEL3=0**. If ``PSTATE.I=0``, non-secure interrupts will be - triggered at one of the Secure-EL1 IRQ exception vectors . The Secure-EL1 - IHF should co-ordinate with the SPD service to transfer execution to the - non-secure state where the interrupt should be handled e.g the SP could - allocate a function identifier to issue a SMC64 or SMC32 to the SPD - service which indicates that the SP execution has been preempted by a - non-secure interrupt. If this function identifier is not known to the SPD - service at compile time then the SP could provide it during the - registration phase. - - If ``PSTATE.I=1`` then the non-secure interrupt will pend until execution - resumes in the non-secure state. - -#. **CSS=0, TEL3=1**. Non-secure interrupts are routed to EL3. They will not - be visible to the SP. The ``PSTATE.I`` bit in Secure-EL1/Secure-EL0 will - have not effect. The SPD service should register a non-secure interrupt - handler which should save the SP state correctly and resume execution in - the non-secure state where the interrupt will be handled. The Secure-EL1 - IHF does not need to take any action. - -#. **CSS=1, TEL3=0**. Non-secure interrupts are handled in the FEL in - non-secure state (EL1/EL2) and are not visible to the SP. This routing - model does not affect the SP behavior. - -A Secure Payload must also ensure that all Secure-EL1 interrupts are correctly -configured at the interrupt controller by the platform port of the EL3 runtime -firmware. It should configure any additional Secure-EL1 interrupts which the EL3 -runtime firmware is not aware of through its platform port. - -Test secure payload behavior -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is -described in Section `Secure Payload Dispatcher`__. It is known to the TSPD -service at build time. - -.. __: #spd-int-registration - -The TSP implements an entrypoint (``tsp_sel1_intr_entry()``) for handling Secure-EL1 -interrupts taken in non-secure state and routed through the TSPD service -(synchronous handling model). It passes the reference to this entrypoint via -``tsp_vectors`` to the TSPD service. - -The TSP also replaces the default exception vector table referenced through the -``early_exceptions`` variable, with a vector table capable of handling FIQ and IRQ -exceptions taken at the same (Secure-EL1) exception level. This table is -referenced through the ``tsp_exceptions`` variable and programmed into the -VBAR_EL1. It caters for the asynchronous handling model. - -The TSP also programs the Secure Physical Timer in the Arm Generic Timer block -to raise a periodic interrupt (every half a second) for the purpose of testing -interrupt management across all the software components listed in `Software -components`_. - -Interrupt handling ------------------- - -This section describes in detail the role of each software component (see -Section `Software components`_) in handling an interrupt of a particular type. - -EL3 runtime firmware -~~~~~~~~~~~~~~~~~~~~ - -The EL3 runtime firmware populates the IRQ and FIQ exception vectors referenced -by the ``runtime_exceptions`` variable as follows. - -#. IRQ and FIQ exceptions taken from the current exception level with - ``SP_EL0`` or ``SP_EL3`` are reported as irrecoverable error conditions. As - mentioned earlier, EL3 runtime firmware always executes with the - ``PSTATE.I`` and ``PSTATE.F`` bits set. - -#. The following text describes how the IRQ and FIQ exceptions taken from a - lower exception level using AArch64 or AArch32 are handled. - -When an interrupt is generated, the vector for each interrupt type is -responsible for: - -#. Saving the entire general purpose register context (x0-x30) immediately - upon exception entry. The registers are saved in the per-cpu ``cpu_context`` - data structure referenced by the ``SP_EL3``\ register. - -#. Saving the ``ELR_EL3``, ``SP_EL0`` and ``SPSR_EL3`` system registers in the - per-cpu ``cpu_context`` data structure referenced by the ``SP_EL3`` register. - -#. Switching to the C runtime stack by restoring the ``CTX_RUNTIME_SP`` value - from the per-cpu ``cpu_context`` data structure in ``SP_EL0`` and - executing the ``msr spsel, #0`` instruction. - -#. Determining the type of interrupt. Secure-EL1 interrupts will be signaled - at the FIQ vector. Non-secure interrupts will be signaled at the IRQ - vector. The platform should implement the following API to determine the - type of the pending interrupt. - - .. code:: c - - uint32_t plat_ic_get_interrupt_type(void); - - It should return either ``INTR_TYPE_S_EL1`` or ``INTR_TYPE_NS``. - -#. Determining the handler for the type of interrupt that has been generated. - The following API has been added for this purpose. - - .. code:: c - - interrupt_type_handler get_interrupt_type_handler(uint32_t interrupt_type); - - It returns the reference to the registered handler for this interrupt - type. The ``handler`` is retrieved from the ``intr_type_desc_t`` structure as - described in Section 2. ``NULL`` is returned if no handler has been - registered for this type of interrupt. This scenario is reported as an - irrecoverable error condition. - -#. Calling the registered handler function for the interrupt type generated. - The ``id`` parameter is set to ``INTR_ID_UNAVAILABLE`` currently. The id along - with the current security state and a reference to the ``cpu_context_t`` - structure for the current security state are passed to the handler function - as its arguments. - - The handler function returns a reference to the per-cpu ``cpu_context_t`` - structure for the target security state. - -#. Calling ``el3_exit()`` to return from EL3 into a lower exception level in - the security state determined by the handler routine. The ``el3_exit()`` - function is responsible for restoring the register context from the - ``cpu_context_t`` data structure for the target security state. - -Secure payload dispatcher -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Interrupt entry -^^^^^^^^^^^^^^^ - -The SPD service begins handling an interrupt when the EL3 runtime firmware calls -the handler function for that type of interrupt. The SPD service is responsible -for the following: - -#. Validating the interrupt. This involves ensuring that the interrupt was - generated according to the interrupt routing model specified by the SPD - service during registration. It should use the security state of the - exception level (passed in the ``flags`` parameter of the handler) where - the interrupt was taken from to determine this. If the interrupt is not - recognised then the handler should treat it as an irrecoverable error - condition. - - An SPD service can register a handler for Secure-EL1 and/or Non-secure - interrupts. A non-secure interrupt should never be routed to EL3 from - from non-secure state. Also if a routing model is chosen where Secure-EL1 - interrupts are routed to S-EL1 when execution is in Secure state, then a - S-EL1 interrupt should never be routed to EL3 from secure state. The handler - could use the security state flag to check this. - -#. Determining whether a context switch is required. This depends upon the - routing model and interrupt type. For non secure and S-EL1 interrupt, - if the security state of the execution context where the interrupt was - generated is not the same as the security state required for handling - the interrupt, a context switch is required. The following 2 cases - require a context switch from secure to non-secure or vice-versa: - - #. A Secure-EL1 interrupt taken from the non-secure state should be - routed to the Secure Payload. - - #. A non-secure interrupt taken from the secure state should be routed - to the last known non-secure exception level. - - The SPD service must save the system register context of the current - security state. It must then restore the system register context of the - target security state. It should use the ``cm_set_next_eret_context()`` API - to ensure that the next ``cpu_context`` to be restored is of the target - security state. - - If the target state is secure then execution should be handed to the SP as - per the synchronous interrupt handling model it implements. A Secure-EL1 - interrupt can be routed to EL3 while execution is in the SP. This implies - that SP execution can be preempted while handling an interrupt by a - another higher priority Secure-EL1 interrupt or a EL3 interrupt. The SPD - service should be able to handle this preemption or manage secure interrupt - priorities before handing control to the SP. - -#. Setting the return value of the handler to the per-cpu ``cpu_context`` if - the interrupt has been successfully validated and ready to be handled at a - lower exception level. - -The routing model allows non-secure interrupts to interrupt Secure-EL1 when in -secure state if it has been configured to do so. The SPD service and the SP -should implement a mechanism for routing these interrupts to the last known -exception level in the non-secure state. The former should save the SP context, -restore the non-secure context and arrange for entry into the non-secure state -so that the interrupt can be handled. - -Interrupt exit -^^^^^^^^^^^^^^ - -When the Secure Payload has finished handling a Secure-EL1 interrupt, it could -return control back to the SPD service through a SMC32 or SMC64. The SPD service -should handle this secure monitor call so that execution resumes in the -exception level and the security state from where the Secure-EL1 interrupt was -originally taken. - -Test secure payload dispatcher Secure-EL1 interrupt handling -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The example TSPD service registers a handler for Secure-EL1 interrupts taken -from the non-secure state. During execution in S-EL1, the TSPD expects that the -Secure-EL1 interrupts are handled in S-EL1 by TSP. Its handler -``tspd_secure_el1_interrupt_handler()`` expects only to be invoked for Secure-EL1 -originating from the non-secure state. It takes the following actions upon being -invoked. - -#. It uses the security state provided in the ``flags`` parameter to ensure - that the secure interrupt originated from the non-secure state. It asserts - if this is not the case. - -#. It saves the system register context for the non-secure state by calling - ``cm_el1_sysregs_context_save(NON_SECURE);``. - -#. It sets the ``ELR_EL3`` system register to ``tsp_sel1_intr_entry`` and sets the - ``SPSR_EL3.DAIF`` bits in the secure CPU context. It sets ``x0`` to - ``TSP_HANDLE_SEL1_INTR_AND_RETURN``. If the TSP was preempted earlier by a non - secure interrupt during ``yielding`` SMC processing, save the registers that - will be trashed, which is the ``ELR_EL3`` and ``SPSR_EL3``, in order to be able - to re-enter TSP for Secure-EL1 interrupt processing. It does not need to - save any other secure context since the TSP is expected to preserve it - (see section `Test secure payload dispatcher behavior`_). - -#. It restores the system register context for the secure state by calling - ``cm_el1_sysregs_context_restore(SECURE);``. - -#. It ensures that the secure CPU context is used to program the next - exception return from EL3 by calling ``cm_set_next_eret_context(SECURE);``. - -#. It returns the per-cpu ``cpu_context`` to indicate that the interrupt can - now be handled by the SP. ``x1`` is written with the value of ``elr_el3`` - register for the non-secure state. This information is used by the SP for - debugging purposes. - -The figure below describes how the interrupt handling is implemented by the TSPD -when a Secure-EL1 interrupt is generated when execution is in the non-secure -state. - -|Image 1| - -The TSP issues an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier to -signal completion of interrupt handling. - -The TSPD service takes the following actions in ``tspd_smc_handler()`` function -upon receiving an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier: - -#. It ensures that the call originated from the secure state otherwise - execution returns to the non-secure state with ``SMC_UNK`` in ``x0``. - -#. It restores the saved ``ELR_EL3`` and ``SPSR_EL3`` system registers back to - the secure CPU context (see step 3 above) in case the TSP had been preempted - by a non secure interrupt earlier. - -#. It restores the system register context for the non-secure state by - calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. - -#. It ensures that the non-secure CPU context is used to program the next - exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. - -#. ``tspd_smc_handler()`` returns a reference to the non-secure ``cpu_context`` - as the return value. - -Test secure payload dispatcher non-secure interrupt handling -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The TSP in Secure-EL1 can be preempted by a non-secure interrupt during -``yielding`` SMC processing or by a higher priority EL3 interrupt during -Secure-EL1 interrupt processing. When ``EL3_EXCEPTION_HANDLING`` is ``0``, only -non-secure interrupts can cause preemption of TSP since there are no EL3 -interrupts in the system. With ``EL3_EXCEPTION_HANDLING=1`` however, any EL3 -interrupt may preempt Secure execution. - -It should be noted that while TSP is preempted, the TSPD only allows entry into -the TSP either for Secure-EL1 interrupt handling or for resuming the preempted -``yielding`` SMC in response to the ``TSP_FID_RESUME`` SMC from the normal world. -(See Section `Implication of preempted SMC on Non-Secure Software`_). - -The non-secure interrupt triggered in Secure-EL1 during ``yielding`` SMC -processing can be routed to either EL3 or Secure-EL1 and is controlled by build -option ``TSP_NS_INTR_ASYNC_PREEMPT`` (see Section `Test secure payload -dispatcher behavior`_). If the build option is set, the TSPD will set the -routing model for the non-secure interrupt to be routed to EL3 from secure state -i.e. **TEL3=1, CSS=0** and registers ``tspd_ns_interrupt_handler()`` as the -non-secure interrupt handler. The ``tspd_ns_interrupt_handler()`` on being -invoked ensures that the interrupt originated from the secure state and disables -routing of non-secure interrupts from secure state to EL3. This is to prevent -further preemption (by a non-secure interrupt) when TSP is reentered for -handling Secure-EL1 interrupts that triggered while execution was in the normal -world. The ``tspd_ns_interrupt_handler()`` then invokes -``tspd_handle_sp_preemption()`` for further handling. - -If the ``TSP_NS_INTR_ASYNC_PREEMPT`` build option is zero (default), the default -routing model for non-secure interrupt in secure state is in effect -i.e. **TEL3=0, CSS=0**. During ``yielding`` SMC processing, the IRQ -exceptions are unmasked i.e. ``PSTATE.I=0``, and a non-secure interrupt will -trigger at Secure-EL1 IRQ exception vector. The TSP saves the general purpose -register context and issues an SMC with ``TSP_PREEMPTED`` as the function -identifier to signal preemption of TSP. The TSPD SMC handler, -``tspd_smc_handler()``, ensures that the SMC call originated from the -secure state otherwise execution returns to the non-secure state with -``SMC_UNK`` in ``x0``. It then invokes ``tspd_handle_sp_preemption()`` for -further handling. - -The ``tspd_handle_sp_preemption()`` takes the following actions upon being -invoked: - -#. It saves the system register context for the secure state by calling - ``cm_el1_sysregs_context_save(SECURE)``. - -#. It restores the system register context for the non-secure state by - calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. - -#. It ensures that the non-secure CPU context is used to program the next - exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. - -#. ``SMC_PREEMPTED`` is set in x0 and return to non secure state after - restoring non secure context. - -The Normal World is expected to resume the TSP after the ``yielding`` SMC -preemption by issuing an SMC with ``TSP_FID_RESUME`` as the function identifier -(see section `Implication of preempted SMC on Non-Secure Software`_). The TSPD -service takes the following actions in ``tspd_smc_handler()`` function upon -receiving this SMC: - -#. It ensures that the call originated from the non secure state. An - assertion is raised otherwise. - -#. Checks whether the TSP needs a resume i.e check if it was preempted. It - then saves the system register context for the non-secure state by calling - ``cm_el1_sysregs_context_save(NON_SECURE)``. - -#. Restores the secure context by calling - ``cm_el1_sysregs_context_restore(SECURE)`` - -#. It ensures that the secure CPU context is used to program the next - exception return from EL3 by calling ``cm_set_next_eret_context(SECURE)``. - -#. ``tspd_smc_handler()`` returns a reference to the secure ``cpu_context`` as the - return value. - -The figure below describes how the TSP/TSPD handle a non-secure interrupt when -it is generated during execution in the TSP with ``PSTATE.I`` = 0 when the -``TSP_NS_INTR_ASYNC_PREEMPT`` build flag is 0. - -|Image 2| - -Secure payload -~~~~~~~~~~~~~~ - -The SP should implement one or both of the synchronous and asynchronous -interrupt handling models depending upon the interrupt routing model it has -chosen (as described in section `Secure Payload`__). - -.. __: #sp-int-registration - -In the synchronous model, it should begin handling a Secure-EL1 interrupt after -receiving control from the SPD service at an entrypoint agreed upon during build -time or during the registration phase. Before handling the interrupt, the SP -should save any Secure-EL1 system register context which is needed for resuming -normal execution in the SP later e.g. ``SPSR_EL1``, ``ELR_EL1``. After handling -the interrupt, the SP could return control back to the exception level and -security state where the interrupt was originally taken from. The SP should use -an SMC32 or SMC64 to ask the SPD service to do this. - -In the asynchronous model, the Secure Payload is responsible for handling -non-secure and Secure-EL1 interrupts at the IRQ and FIQ vectors in its exception -vector table when ``PSTATE.I`` and ``PSTATE.F`` bits are 0. As described earlier, -when a non-secure interrupt is generated, the SP should coordinate with the SPD -service to pass control back to the non-secure state in the last known exception -level. This will allow the non-secure interrupt to be handled in the non-secure -state. - -Test secure payload behavior -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The TSPD hands control of a Secure-EL1 interrupt to the TSP at the -``tsp_sel1_intr_entry()``. The TSP handles the interrupt while ensuring that the -handover agreement described in Section `Test secure payload dispatcher -behavior`_ is maintained. It updates some statistics by calling -``tsp_update_sync_sel1_intr_stats()``. It then calls -``tsp_common_int_handler()`` which. - -#. Checks whether the interrupt is the secure physical timer interrupt. It - uses the platform API ``plat_ic_get_pending_interrupt_id()`` to get the - interrupt number. If it is not the secure physical timer interrupt, then - that means that a higher priority interrupt has preempted it. Invoke - ``tsp_handle_preemption()`` to handover control back to EL3 by issuing - an SMC with ``TSP_PREEMPTED`` as the function identifier. - -#. Handles the secure timer interrupt interrupt by acknowledging it using the - ``plat_ic_acknowledge_interrupt()`` platform API, calling - ``tsp_generic_timer_handler()`` to reprogram the secure physical generic - timer and calling the ``plat_ic_end_of_interrupt()`` platform API to signal - end of interrupt processing. - -The TSP passes control back to the TSPD by issuing an SMC64 with -``TSP_HANDLED_S_EL1_INTR`` as the function identifier. - -The TSP handles interrupts under the asynchronous model as follows. - -#. Secure-EL1 interrupts are handled by calling the ``tsp_common_int_handler()`` - function. The function has been described above. - -#. Non-secure interrupts are handled by calling the ``tsp_common_int_handler()`` - function which ends up invoking ``tsp_handle_preemption()`` and issuing an - SMC64 with ``TSP_PREEMPTED`` as the function identifier. Execution resumes at - the instruction that follows this SMC instruction when the TSPD hands control - to the TSP in response to an SMC with ``TSP_FID_RESUME`` as the function - identifier from the non-secure state (see section `Test secure payload - dispatcher non-secure interrupt handling`_). - -Other considerations --------------------- - -Implication of preempted SMC on Non-Secure Software -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A ``yielding`` SMC call to Secure payload can be preempted by a non-secure -interrupt and the execution can return to the non-secure world for handling -the interrupt (For details on ``yielding`` SMC refer `SMC calling convention`_). -In this case, the SMC call has not completed its execution and the execution -must return back to the secure payload to resume the preempted SMC call. -This can be achieved by issuing an SMC call which instructs to resume the -preempted SMC. - -A ``fast`` SMC cannot be preempted and hence this case will not happen for -a fast SMC call. - -In the Test Secure Payload implementation, ``TSP_FID_RESUME`` is designated -as the resume SMC FID. It is important to note that ``TSP_FID_RESUME`` is a -``yielding`` SMC which means it too can be be preempted. The typical non -secure software sequence for issuing a ``yielding`` SMC would look like this, -assuming ``P.STATE.I=0`` in the non secure state : - -.. code:: c - - int rc; - rc = smc(TSP_YIELD_SMC_FID, ...); /* Issue a Yielding SMC call */ - /* The pending non-secure interrupt is handled by the interrupt handler - and returns back here. */ - while (rc == SMC_PREEMPTED) { /* Check if the SMC call is preempted */ - rc = smc(TSP_FID_RESUME); /* Issue resume SMC call */ - } - -The ``TSP_YIELD_SMC_FID`` is any ``yielding`` SMC function identifier and the smc() -function invokes a SMC call with the required arguments. The pending non-secure -interrupt causes an IRQ exception and the IRQ handler registered at the -exception vector handles the non-secure interrupt and returns. The return value -from the SMC call is tested for ``SMC_PREEMPTED`` to check whether it is -preempted. If it is, then the resume SMC call ``TSP_FID_RESUME`` is issued. The -return value of the SMC call is tested again to check if it is preempted. -This is done in a loop till the SMC call succeeds or fails. If a ``yielding`` -SMC is preempted, until it is resumed using ``TSP_FID_RESUME`` SMC and -completed, the current TSPD prevents any other SMC call from re-entering -TSP by returning ``SMC_UNK`` error. - --------------- - -*Copyright (c) 2014-2019, Arm Limited and Contributors. All rights reserved.* - -.. _Porting Guide: ./porting-guide.rst -.. _SMC calling convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html - -.. |Image 1| image:: diagrams/sec-int-handling.png?raw=true -.. |Image 2| image:: diagrams/non-sec-int-handling.png?raw=true diff --git a/docs/maintainers.rst b/docs/maintainers.rst new file mode 100644 index 0000000..0fa909f --- /dev/null +++ b/docs/maintainers.rst @@ -0,0 +1,294 @@ +Trusted Firmware-A maintainers +============================== + +Trusted Firmware-A (TF-A) is an Arm maintained project. All contributions are +ultimately merged by the maintainers listed below. Technical ownership of some +parts of the codebase is delegated to the sub-maintainers listed below. An +acknowledgement from these sub-maintainers may be required before the +maintainers merge a contribution. + +Main maintainers +---------------- +:M: Dan Handley +:G: `danh-arm`_ +:M: Dimitris Papastamos +:G: `dp-arm`_ +:M: Soby Mathew +:G: `soby-mathew`_ + +Allwinner ARMv8 platform port +----------------------------- +:M: Andre Przywara +:G: `Andre-ARM`_ +:M: Samuel Holland +:G: `smaeul`_ +:F: docs/plat/allwinner.rst +:F: plat/allwinner/ +:F: drivers/allwinner/ + +Amlogic Meson S905 (GXBB) platform port +--------------------------------------- +:M: Andre Przywara +:G: `Andre-ARM`_ +:F: docs/plat/meson-gxbb.rst +:F: drivers/meson/ +:F: plat/meson/gxbb/ + +Amlogic Meson S905x (GXL) platform port +--------------------------------------- +:M: Remi Pommarel +:G: `remi-triplefault`_ +:F: docs/plat/meson-gxl.rst +:F: drivers/meson/gxl +:F: plat/meson/gxl/ + +Armv7-A architecture port +------------------------- +:M: Etienne Carriere +:G: `etienne-lms`_ + +Arm System Guidance for Infrastructure / Mobile FVP platforms +------------------------------------------------------------- +:M: Nariman Poushin +:G: `npoushin`_ +:M: Thomas Abraham +:G: `thomas-arm`_ +:F: plat/arm/css/sgi/ +:F: plat/arm/css/sgm/ +:F: plat/arm/board/sgi575/ +:F: plat/arm/board/sgm775/ + +Console API framework +--------------------- +:M: Julius Werner +:G: `jwerner-chromium`_ +:F: drivers/console/ +:F: include/drivers/console.h +:F: plat/common/aarch64/crash_console_helpers.S + +coreboot support libraries +-------------------------- +:M: Julius Werner +:G: `jwerner-chromium`_ +:F: drivers/coreboot/ +:F: include/drivers/coreboot/ +:F: include/lib/coreboot.h +:F: lib/coreboot/ + +eMMC/UFS drivers +---------------- +:M: Haojian Zhuang +:G: `hzhuang1`_ +:F: drivers/partition/ +:F: drivers/synopsys/emmc/ +:F: drivers/synopsys/ufs/ +:F: drivers/ufs/ +:F: include/drivers/dw_ufs.h +:F: include/drivers/ufs.h +:F: include/drivers/synopsys/dw_mmc.h + +HiSilicon HiKey and HiKey960 platform ports +------------------------------------------- +:M: Haojian Zhuang +:G: `hzhuang1`_ +:F: docs/plat/hikey.rst +:F: docs/plat/hikey960.rst +:F: plat/hisilicon/hikey/ +:F: plat/hisilicon/hikey960/ + +HiSilicon Poplar platform port +------------------------------ +:M: Shawn Guo +:G: `shawnguo2`_ +:F: docs/plat/poplar.rst +:F: plat/hisilicon/poplar/ + +Intel SocFPGA platform ports +---------------------------- +:M: Tien Hock Loh +:G: `thloh85-intel` +:F: plat/intel/soc + +MediaTek platform ports +----------------------- +:M: Yidi Lin (林以廸) +:G: `mtk09422`_ +:F: plat/mediatek/ + +Marvell platform ports and SoC drivers +-------------------------------------- +:M: Konstantin Porotchkin +:G: `kostapr`_ +:F: docs/marvell/ +:F: plat/marvell/ +:F: drivers/marvell/ +:F: tools/marvell/ + +NVidia platform ports +--------------------- +:M: Varun Wadekar +:G: `vwadekar`_ +:F: docs/plat/nvidia-tegra.rst +:F: include/lib/cpus/aarch64/denver.h +:F: lib/cpus/aarch64/denver.S +:F: plat/nvidia/ + +NXP QorIQ Layerscape platform ports +----------------------------------- +:M: Jiafei Pan +:G: `qoriq-open-source`_ +:F: docs/plat/ls1043a.rst +:F: plat/layerscape/ + +NXP i.MX 7 WaRP7 platform port and SoC drivers +---------------------------------------------- +:M: Bryan O'Donoghue +:G: `bryanodonoghue`_ +:M: Jun Nie +:G: `niej`_ +:F: docs/plat/warp7.rst +:F: plat/imx/common/ +:F: plat/imx/imx7/ +:F: drivers/imx/timer/ +:F: drivers/imx/uart/ +:F: drivers/imx/usdhc/ + +NXP i.MX 8 platform port +------------------------ +:M: Anson Huang +:G: `Anson-Huang`_ +:F: docs/plat/imx8.rst +:F: plat/imx/ + +NXP i.MX8M platform port +------------------------ +:M: Jacky Bai +:G: `JackyBai`_ +:F: doc/plat/imx8m.rst +:F: plat/imx/imx8m/ + +OP-TEE dispatcher +----------------- +:M: Jens Wiklander +:G: `jenswi-linaro`_ +:F: docs/spd/optee-dispatcher.rst +:F: services/spd/opteed/ + +QEMU platform port +------------------ +:M: Jens Wiklander +:G: `jenswi-linaro`_ +:F: docs/plat/qemu.rst +:F: plat/qemu/ + +Raspberry Pi 3 platform port +---------------------------- +:M: Ying-Chun Liu (PaulLiu) +:G: `grandpaul`_ +:F: docs/plat/rpi3.rst +:F: plat/rpi3/ +:F: drivers/rpi3/ +:F: include/drivers/rpi3/ + +Renesas rcar-gen3 platform port +------------------------------- +:M: Jorge Ramirez-Ortiz +:G: `ldts`_ +:M: Marek Vasut +:G: `marex`_ +:F: docs/plat/rcar-gen3.rst +:F: plat/renesas/rcar +:F: drivers/renesas/rcar +:F: tools/renesas/rcar_layout_create + +RockChip platform port +---------------------- +:M: Tony Xie +:G: `TonyXie06`_ +:G: `rockchip-linux`_ +:M: Heiko Stuebner +:G: `mmind`_ +:F: plat/rockchip/ + +STM32MP1 platform port +---------------------- +:M: Yann Gautier +:G: `Yann-lms`_ +:F: docs/plat/stm32mp1.rst +:F: drivers/st/ +:F: fdts/stm32\* +:F: include/drivers/st/ +:F: include/dt-bindings/\*/stm32\* +:F: plat/st/ +:F: tools/stm32image/ + +Synquacer platform port +----------------------- +:M: Sumit Garg +:G: `b49020`_ +:F: docs/plat/synquacer.rst +:F: plat/socionext/synquacer/ + +Texas Instruments platform port +------------------------------- +:M: Andrew F. Davis +:G: `glneo`_ +:F: docs/plat/ti-k3.rst +:F: plat/ti/ + +TLK/Trusty secure payloads +-------------------------- +:M: Varun Wadekar +:G: `vwadekar`_ +:F: docs/spd/tlk-dispatcher.rst +:F: docs/spd/trusty-dispatcher.rst +:F: include/bl32/payloads/tlk.h +:F: services/spd/tlkd/ +:F: services/spd/trusty/ + +UniPhier platform port +---------------------- +:M: Masahiro Yamada +:G: `masahir0y`_ +:F: docs/plat/socionext-uniphier.rst +:F: plat/socionext/uniphier/ + +Xilinx platform port +-------------------- +:M: Siva Durga Prasad Paladugu +:G: `sivadur`_ +:F: docs/plat/xilinx-zynqmp.rst +:F: plat/xilinx/ + +.. _Andre-ARM: https://github.com/Andre-ARM +.. _Anson-Huang: https://github.com/Anson-Huang +.. _bryanodonoghue: https://github.com/bryanodonoghue +.. _b49020: https://github.com/b49020 +.. _danh-arm: https://github.com/danh-arm +.. _dp-arm: https://github.com/dp-arm +.. _etienne-lms: https://github.com/etienne-lms +.. _glneo: https://github.com/glneo +.. _hzhuang1: https://github.com/hzhuang1 +.. _JackyBai: https://github.com/JackyBai +.. _jenswi-linaro: https://github.com/jenswi-linaro +.. _ldts: https://github.com/ldts +.. _marex: https://github.com/marex +.. _niej: https://github.com/niej +.. _kostapr: https://github.com/kostapr +.. _masahir0y: https://github.com/masahir0y +.. _mmind: https://github.com/mmind +.. _mtk09422: https://github.com/mtk09422 +.. _npoushin: https://github.com/npoushin +.. _qoriq-open-source: https://github.com/qoriq-open-source +.. _remi-triplefault: https://github.com/repk +.. _rockchip-linux: https://github.com/rockchip-linux +.. _shawnguo2: https://github.com/shawnguo2 +.. _sivadur: https://github.com/sivadur +.. _smaeul: https://github.com/smaeul +.. _soby-mathew: https://github.com/soby-mathew +.. _thomas-arm: https://github.com/thomas-arm +.. _TonyXie06: https://github.com/TonyXie06 +.. _vwadekar: https://github.com/vwadekar +.. _Yann-lms: https://github.com/Yann-lms +.. _grandpaul: https://github.com/grandpaul +.. _jwerner-chromium: https://github.com/jwerner-chromium diff --git a/docs/marvell/build.txt b/docs/marvell/build.txt deleted file mode 100644 index 7b75196..0000000 --- a/docs/marvell/build.txt +++ /dev/null @@ -1,194 +0,0 @@ -TF-A Build Instructions -====================== - -This section describes how to compile the ARM Trusted Firmware (TF-A) project for Marvell's platforms. - -Build Instructions ------------------- -(1) Set the cross compiler:: - - > export CROSS_COMPILE=/path/to/toolchain/aarch64-linux-gnu- - -(2) Set path for FIP images: - - Set U-Boot image path (relatively to TF-A root or absolute path):: - - > export BL33=path/to/u-boot.bin - - For example: if U-Boot project (and its images) is located at ~/project/u-boot, - BL33 should be ~/project/u-boot/u-boot.bin - - .. note:: - - u-boot.bin should be used and not u-boot-spl.bin - - Set MSS/SCP image path (mandatory only for Armada80x0):: - - > export SCP_BL2=path/to/mrvl_scp_bl2*.img - -(3) Armada-37x0 build requires WTP tools installation. - - See below in the section "Tools and external components installation". - Install ARM 32-bit cross compiler, which is required for building WTMI image for CM3:: - - > sudo apt-get install gcc-arm-linux-gnueabi - -(4) Clean previous build residuals (if any):: - - > make distclean - -(5) Build TF-A: - - There are several build options: - - - DEBUG: default is without debug information (=0). in order to enable it use DEBUG=1 - Must be disabled when building UART recovery images due to current console driver - implementation that is not compatible with Xmodem protocol used for boot image download. - - - LOG_LEVEL: defines the level of logging which will be purged to the default output port. - - LOG_LEVEL_NONE 0 - LOG_LEVEL_ERROR 10 - LOG_LEVEL_NOTICE 20 - LOG_LEVEL_WARNING 30 - LOG_LEVEL_INFO 40 - LOG_LEVEL_VERBOSE 50 - - - USE_COHERENT_MEM: This flag determines whether to include the coherent memory region in the - BL memory map or not. - - - LLC_ENABLE: Flag defining the LLC (L3) cache state. The cache is enabled by default (LLC_ENABLE=1). - - - MARVELL_SECURE_BOOT: build trusted(=1)/non trusted(=0) image, default is non trusted. - - - BLE_PATH: - Points to BLE (Binary ROM extension) sources folder. Only required for A8K builds. - The parameter is optional, its default value is "plat/marvell/a8k/common/ble". - - - MV_DDR_PATH: - For A7/8K, use this parameter to point to mv_ddr driver sources to allow BLE build. For A37x0, - it is used for ddr_tool build. - Usage example: MV_DDR_PATH=path/to/mv_ddr - The parameter is optional for A7/8K, when this parameter is not set, the mv_ddr - sources are expected to be located at: drivers/marvell/mv_ddr. However, the parameter - is necessary for A37x0. - For the mv_ddr source location, check the section "Tools and external components installation" - - - DDR_TOPOLOGY: For Armada37x0 only, the DDR topology map index/name, default is 0. - Supported Options: - - DDR3 1CS (0): DB-88F3720-DDR3-Modular (512MB); EspressoBIN (512MB) - - DDR4 1CS (1): DB-88F3720-DDR4-Modular (512MB) - - DDR3 2CS (2): EspressoBIN V3-V5 (1GB) - - DDR4 2CS (3): DB-88F3720-DDR4-Modular (4GB) - - DDR3 1CS (4): DB-88F3720-DDR3-Modular (1GB) - - DDR4 1CS (5): EspressoBin V7 (1GB) - - DDR4 2CS (6): EspressoBin V7 (2GB) - - CUSTOMER (CUST): Customer board, DDR3 1CS 512MB - - - CLOCKSPRESET: For Armada37x0 only, the clock tree configuration preset including CPU and DDR frequency, - default is CPU_800_DDR_800. - - CPU_600_DDR_600 - CPU at 600 MHz, DDR at 600 MHz - - CPU_800_DDR_800 - CPU at 800 MHz, DDR at 800 MHz - - CPU_1000_DDR_800 - CPU at 1000 MHz, DDR at 800 MHz - - CPU_1200_DDR_750 - CPU at 1200 MHz, DDR at 750 MHz - - - BOOTDEV: For Armada37x0 only, the flash boot device, default is SPINOR, - Currently, Armada37x0 only supports SPINOR, SPINAND, EMMCNORM and SATA: - - - SPINOR - SPI NOR flash boot - - SPINAND - SPI NAND flash boot - - EMMCNORM - eMMC Download Mode - Download boot loader or program code from eMMC flash into CM3 or CA53 - Requires full initialization and command sequence - - SATA - SATA device boot - - - PARTNUM: For Armada37x0 only, the boot partition number, default is 0. To boot from eMMC, the value - should be aligned with the parameter in U-Boot with name of CONFIG_SYS_MMC_ENV_PART, whose - value by default is 1. - For details about CONFIG_SYS_MMC_ENV_PART, please refer to the U-Boot build instructions. - - - WTMI_IMG: For Armada37x0 only, the path of the WTMI image can point to an image which does - nothing, an image which supports EFUSE or a customized CM3 firmware binary. The default image - is wtmi.bin that built from sources in WTP folder, which is the next option. If the default - image is OK, then this option should be skipped. - - - WTP: For Armada37x0 only, use this parameter to point to wtptools source code directory, which - can be found as a3700_utils.zip in the release. - Usage example: WTP=/path/to/a3700_utils - - For example, in order to build the image in debug mode with log level up to 'notice' level run:: - - > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 PLAT= all fip - - And if we want to build a Armada37x0 image in debug mode with log level up to 'notice' level, - the image has the preset CPU at 1000 MHz, preset DDR3 at 800 MHz, the DDR topology of DDR4 2CS, - the image boot from SPI NOR flash partition 0, and the image is non trusted in WTP, the command - line is as following:: - - > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 CLOCKSPRESET=CPU_1000_DDR_800 \ - MARVELL_SECURE_BOOT=0 DDR_TOPOLOGY=3 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 all fip - - Supported MARVELL_PLATFORM are: - - a3700 (for both A3720 DB and EspressoBin) - - a70x0 - - a70x0_amc (for AMC board) - - a80x0 - - a80x0_mcbin (for MacciatoBin) - -Special Build Flags --------------------- - - PLAT_RECOVERY_IMAGE_ENABLE: When set this option to enable secondary recovery function when build - atf. In order to build UART recovery image this operation should be disabled for a70x0 and a80x0 - because of hardware limitation (boot from secondary image can interrupt UART recovery process). - This MACRO definition is set in plat/marvell/a8k/common/include/platform_def.h file - -(for more information about build options, please refer to section 'Summary of build options' in TF-A user-guide: - https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/user-guide.md) - - -Build output -------------- -Marvell's TF-A compilation generates 7 files: - - ble.bin - BLe image - - bl1.bin - BL1 image - - bl2.bin - BL2 image - - bl31.bin - BL31 image - - fip.bin - FIP image (contains BL2, BL31 & BL33 (U-Boot) images) - - boot-image.bin - TF-A image (contains BL1 and FIP images) - - flash-image.bin - Image which contains boot-image.bin and SPL image; - should be placed on the boot flash/device. - - -Tools and external components installation -========================================== - -Armada37x0 Builds require installation of 3 components -------------------------------------------------------- - -(1) ARM cross compiler capable of building images for the service CPU (CM3). - This component is usually included in the Linux host packages. - On Debian/Ubuntu hosts the default GNU ARM tool chain can be installed - using the following command:: - - > sudo apt-get install gcc-arm-linux-gnueabi - - Only if required, the default tool chain prefix "arm-linux-gnueabi-" can be - overwritten using the environment variable CROSS_CM3. - Example for BASH shell:: - - > export CROSS_CM3=/opt/arm-cross/bin/arm-linux-gnueabi - -(2) DDR initialization library sources (mv_ddr) available at the following repository - (use the "mv_ddr-armada-atf-mainline" branch):: - https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git - -(3) Armada3700 tools available at the following repository (use the latest release branch):: - https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell.git - -Armada70x0 and Armada80x0 Builds require installation of an additional component --------------------------------------------------------------------------------- - -(1) DDR initialization library sources (mv_ddr) available at the following repository - (use the "mv_ddr-armada-atf-mainline" branch):: - https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git - diff --git a/docs/marvell/misc/mvebu-a8k-addr-map.txt b/docs/marvell/misc/mvebu-a8k-addr-map.txt deleted file mode 100644 index 586e8b7..0000000 --- a/docs/marvell/misc/mvebu-a8k-addr-map.txt +++ /dev/null @@ -1,47 +0,0 @@ -Address decoding flow and address translation units of Marvell Armada 8K SoC family - -+--------------------------------------------------------------------------------------------------+ -| +-------------+ +--------------+ | -| | Memory +----- DRAM CS | | -|+------------+ +-----------+ +-----------+ | Controller | +--------------+ | -|| AP DMA | | | | | +-------------+ | -|| SD/eMMC | | CA72 CPUs | | AP MSS | +-------------+ | -|| MCI-0/1 | | | | | | Memory | | -|+------+-----+ +--+--------+ +--------+--+ +------------+ | Controller | +-------------+ | -| | | | | +----- Translaton | |AP | | -| | | | | | +-------------+ |Configuration| | -| | | +-----+ +-------------------------Space | | -| | | +-------------+ | CCU | +-------------+ | -| | | | MMU +---------+ Windows | +-----------+ +-------------+ | -| | +-| translation | | Lookup +---- +--------- AP SPI | | -| | +-------------+ | | | | +-------------+ | -| | +-------------+ | | | IO | +-------------+ | -| +------------| SMMU +---------+ | | Windows +--------- AP MCI0/1 | | -| | translation | +------------+ | Lookup | +-------------+ | -| +---------+---+ | | +-------------+ | -| - | | +--------- AP STM | | -| +----------------- | | +-------------+ | -| AP | | +-+---------+ | -+---------------------------------------------------------------|----------------------------------+ -+-------------|-------------------------------------------------|----------------------------------+ -| CP | +-------------+ +------+-----+ +-------------------+ | -| | | | | +------- SB CFG Space | | -| | | DIOB | | | +-------------------+ | -| | | Windows ----------------- IOB | +-------------------+ | -| | | Control | | Windows +------| SB PCIe-0 - PCIe2 | | -| | | | | Lookup | +-------------------+ | -| | +------+------+ | | +-------------------+ | -| | | | +------+ SB NAND | | -| | | +------+-----+ +-------------------+ | -| | | | | -| | | | | -| +------------------+ +------------+ +------+-----+ +-------------------+ | -| | Network Engine | | | | +------- SB SPI-0/SPI-1 | | -| | Security Engine | | PCIe, MSS | | RUNIT | +-------------------+ | -| | SATA, USB | | DMA | | Windows | +-------------------+ | -| | SD/eMMC | | | | Lookup +------- SB Device Bus | | -| | TDM, I2C | | | | | +-------------------+ | -| +------------------+ +------------+ +------------+ | -| | -+--------------------------------------------------------------------------------------------------+ - diff --git a/docs/marvell/misc/mvebu-amb.txt b/docs/marvell/misc/mvebu-amb.txt deleted file mode 100644 index 2a7a41e..0000000 --- a/docs/marvell/misc/mvebu-amb.txt +++ /dev/null @@ -1,45 +0,0 @@ -AMB - AXI MBUS address decoding -------------------------------- - -AXI to M-bridge decoding unit driver for Marvell Armada 8K and 8K+ SoCs. - -- The Runit offers a second level of address windows lookup. It is used to map transaction towards -the CD BootROM, SPI0, SPI1 and Device bus (NOR). -- The Runit contains eight configurable windows. Each window defines a contiguous, -address space and the properties associated with that address space. - -Unit Bank ATTR -Device-Bus DEV_BOOT_CS 0x2F - DEV_CS0 0x3E - DEV_CS1 0x3D - DEV_CS2 0x3B - DEV_CS3 0x37 -SPI-0 SPI_A_CS0 0x1E - SPI_A_CS1 0x5E - SPI_A_CS2 0x9E - SPI_A_CS3 0xDE - SPI_A_CS4 0x1F - SPI_A_CS5 0x5F - SPI_A_CS6 0x9F - SPI_A_CS7 0xDF -SPI1 SPI_B_CS0 0x1A - SPI_B_CS1 0x5A - SPI_B_CS2 0x9A - SPI_B_CS3 0xDA -BOOT_ROM BOOT_ROM 0x1D -UART UART 0x01 - -Mandatory functions: - - marvell_get_amb_memory_map - returns the AMB windows configuration and the number of windows - -Mandatory structures: - amb_memory_map - Array that include the configuration of the windows - every window/entry is a struct which has 2 parameters: - - base address of the window - - Attribute of the window - -Examples: - struct addr_map_win amb_memory_map[] = { - {0xf900, AMB_DEV_CS0_ID}, - }; diff --git a/docs/marvell/misc/mvebu-ccu.txt b/docs/marvell/misc/mvebu-ccu.txt deleted file mode 100644 index 9764027..0000000 --- a/docs/marvell/misc/mvebu-ccu.txt +++ /dev/null @@ -1,23 +0,0 @@ -Marvell CCU address decoding bindings -===================================== - -CCU configration driver (1st stage address translation) for Marvell Armada 8K and 8K+ SoCs. - -The CCU node includes a description of the address decoding configuration. - -Mandatory functions: - - marvell_get_ccu_memory_map - return the CCU windows configuration and the number of windows - of the specific AP. - -Mandatory structures: - ccu_memory_map - Array that includes the configuration of the windows - every window/entry is a struct which has 3 parameters: - - Base address of the window - - Size of the window - - Target-ID of the window - -Example: - struct addr_map_win ccu_memory_map[] = { - {0x00000000f2000000, 0x00000000e000000, IO_0_TID}, /* IO window */ - }; diff --git a/docs/marvell/misc/mvebu-io-win.txt b/docs/marvell/misc/mvebu-io-win.txt deleted file mode 100644 index c83ad1f..0000000 --- a/docs/marvell/misc/mvebu-io-win.txt +++ /dev/null @@ -1,35 +0,0 @@ -Marvell IO WIN address decoding bindings -===================================== - -IO Window configration driver (2nd stage address translation) for Marvell Armada 8K and 8K+ SoCs. - -The IO WIN includes a description of the address decoding configuration. - -Transactions that are decoded by CCU windows as IO peripheral, have an additional -layer of decoding. This additional address decoding layer defines one of the -following targets: - 0x0 = BootRom - 0x1 = STM (Serial Trace Macro-cell, a programmer's port into trace stream) - 0x2 = SPI direct access - 0x3 = PCIe registers - 0x4 = MCI Port - 0x5 = PCIe port - -Mandatory functions: - - marvell_get_io_win_memory_map - returns the IO windows configuration and the number of windows - of the specific AP. - -Mandatory structures: - io_win_memory_map - Array that include the configuration of the windows - every window/entry is a struct which has 3 parameters: - - Base address of the window - - Size of the window - - Target-ID of the window - -Example: - struct addr_map_win io_win_memory_map[] = { - {0x00000000fe000000, 0x000000001f00000, PCIE_PORT_TID}, /* PCIe window 31Mb for PCIe port*/ - {0x00000000ffe00000, 0x000000000100000, PCIE_REGS_TID}, /* PCI-REG window 64Kb for PCIe-reg*/ - {0x00000000f6000000, 0x000000000100000, MCIPHY_TID}, /* MCI window 1Mb for PHY-reg*/ - }; diff --git a/docs/marvell/misc/mvebu-iob.txt b/docs/marvell/misc/mvebu-iob.txt deleted file mode 100644 index 97ec09d..0000000 --- a/docs/marvell/misc/mvebu-iob.txt +++ /dev/null @@ -1,40 +0,0 @@ -Marvell IOB address decoding bindings -===================================== - -IO bridge configration driver (3rd stage address translation) for Marvell Armada 8K and 8K+ SoCs. - -The IOB includes a description of the address decoding configuration. - -IOB supports up to n (in CP110 n=24) windows for external memory transaction. -When a transaction passes through the IOB, its address is compared to each of -the enabled windows. If there is a hit and it passes the security checks, it is -advanced to the target port. - -Mandatory functions: - - marvell_get_iob_memory_map - returns the IOB windows configuration and the number of windows - -Mandatory structures: - iob_memory_map - Array that include the configuration of the windows - every window/entry is a struct which has 3 parameters: - - Base address of the window - - Size of the window - - Target-ID of the window - -Target ID options: - - 0x0 = Internal configuration space - - 0x1 = MCI0 - - 0x2 = PEX1_X1 - - 0x3 = PEX2_X1 - - 0x4 = PEX0_X4 - - 0x5 = NAND flash - - 0x6 = RUNIT (NOR/SPI/BootRoom) - - 0x7 = MCI1 - -Example: - struct addr_map_win iob_memory_map[] = { - {0x00000000f7000000, 0x0000000001000000, PEX1_TID}, /* PEX1_X1 window */ - {0x00000000f8000000, 0x0000000001000000, PEX2_TID}, /* PEX2_X1 window */ - {0x00000000f6000000, 0x0000000001000000, PEX0_TID}, /* PEX0_X4 window */ - {0x00000000f9000000, 0x0000000001000000, NAND_TID} /* NAND window */ - }; diff --git a/docs/marvell/porting.txt b/docs/marvell/porting.txt deleted file mode 100644 index f9a39a0..0000000 --- a/docs/marvell/porting.txt +++ /dev/null @@ -1,118 +0,0 @@ -.. _porting: - -TF-A Porting Guide -================= - -This section describes how to port TF-A to a customer board, assuming that the SoC being used is already supported -in TF-A. - - -Source Code Structure ---------------------- -- The customer platform specific code shall reside under "plat/marvell//_cust" - (e.g. 'plat/marvell/a8k/a7040_cust'). -- The platform name for build purposes is called "_cust" (e.g. a7040_cust). -- The build system will reuse all files from within the soc directory, and take only the porting - files from the customer platform directory. - -Files that require porting are located at "plat/marvell//_cust" directory. - - -Armada-70x0/Armada-80x0 Porting -------------------------------- - - - SoC Physical Address Map (marvell_plat_config.c): - - This file describes the SoC physical memory mapping to be used for the CCU, IOWIN, AXI-MBUS and IOB - address decode units (Refer to the functional spec for more details). - - In most cases, using the default address decode windows should work OK. - - In cases where a special physical address map is needed (e.g. Special size for PCIe MEM windows, - large memory mapped SPI flash...), then porting of the SoC memory map is required. - - Note: For a detailed information on how CCU, IOWIN, AXI-MBUS & IOB work, please refer to the SoC functional spec, - and under "docs/marvell/misc/mvebu-[ccu/iob/amb/io-win].txt" files. - - - boot loader recovery (marvell_plat_config.c): - - Background: - boot rom can skip the current image and choose to boot from next position if a specific value - (0xDEADB002) is returned by the ble main function. This feature is used for boot loader recovery - by booting from a valid flash-image saved in next position on flash (e.g. address 2M in SPI flash). - - Supported options to implement the skip request are: - - GPIO - - I2C - - User defined - - - Porting: - Under marvell_plat_config.c, implement struct skip_image that includes specific board parameters. - .. warning:: to disable this feature make sure the struct skip_image is not implemented. - - - Example: - In A7040-DB specific implementation (plat/marvell/a8k/a70x0/board/marvell_plat_config.c), - the image skip is implemented using GPIO: mpp 33 (SW5). - - Before resetting the board make sure there is a valid image on the next flash address: - -tftp [valid address] flash-image.bin - -sf update [valid address] 0x2000000 [size] - - Press reset and keep pressing the button connected to the chosen GPIO pin. A skip image request - message is printed on the screen and boot rom boots from the saved image at the next position. - - - DDR Porting (dram_port.c): - - This file defines the dram topology and parameters of the target board. - - The DDR code is part of the BLE component, which is an extension of ARM Trusted Firmware (TF-A). - - The DDR driver called mv_ddr is released separately apart from TF-A sources. - - The BLE and consequently, the DDR init code is executed at the early stage of the boot process. - - Each supported platform of the TF-A has its own DDR porting file called dram_port.c located at - ``atf/plat/marvell/a8k//board`` directory. - - Please refer to '/doc/porting_guide.txt' for detailed porting description. - - The build target directory is "build//release/ble". - - - Comphy Porting (phy-porting-layer.h or phy-default-porting-layer.h) - - Background: - Some of the comphy's parameters value depend on the HW connection between the SoC and the PHY. Every - board type has specific HW characteristics like wire length. Due to those differences some comphy - parameters vary between board types. Therefore each board type can have its own list of values for - all relevant comphy parameters. The PHY porting layer specifies which parameters need to be suited and - the board designer should provide relevant values. - - .. seealso:: - For XFI/SFI comphy type there is procedure "rx_training" which eases process of suiting some of - the parameters. Please see :ref:`uboot_cmd` section: rx_training. - - The PHY porting layer simplifies updating static values per board type, which are now grouped in one place. - - .. note:: - The parameters for the same type of comphy may vary even for the same board type, it is because - the lanes from comphy-x to some PHY may have different HW characteristic than lanes from - comphy-y to the same (multiplexed) or other PHY. - - - Porting: - The porting layer for PHY was introduced in TF-A. There is one file - ``drivers/marvell/comphy/phy-default-porting-layer.h`` which contains the defaults. Those default - parameters are used only if there is no appropriate phy-porting-layer.h file under: - ``plat/marvell///board/phy-porting-layer.h``. If the phy-porting-layer.h exists, - the phy-default-porting-layer.h is not going to be included. - - .. warning:: - Not all comphy types are already reworked to support the PHY porting layer, currently the porting - layer is supported for XFI/SFI and SATA comphy types. - - The easiest way to prepare the PHY porting layer for custom board is to copy existing example to a new - platform: - - - cp ``plat/marvell/a8k/a80x0/board/phy-porting-layer.h`` "plat/marvell///board/phy-porting-layer.h" - - adjust relevant parameters or - - if different comphy index is used for specific feature, move it to proper table entry and then adjust. - - .. note:: - The final table size with comphy parameters can be different, depending on the CP module count for - given SoC type. - - - Example: - Example porting layer for armada-8040-db is under: ``plat/marvell/a8k/a80x0/board/phy-porting-layer.h`` - - .. note:: - If there is no PHY porting layer for new platform (missing phy-porting-layer.h), the default - values are used (drivers/marvell/comphy/phy-default-porting-layer.h) and the user is warned: - - .. warning:: - "Using default comphy parameters - it may be required to suit them for your board". diff --git a/docs/perf/index.rst b/docs/perf/index.rst new file mode 100644 index 0000000..50833b8 --- /dev/null +++ b/docs/perf/index.rst @@ -0,0 +1,9 @@ +Performance & Testing +===================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + psci-performance-juno diff --git a/docs/perf/psci-performance-juno.rst b/docs/perf/psci-performance-juno.rst new file mode 100644 index 0000000..caed8bf --- /dev/null +++ b/docs/perf/psci-performance-juno.rst @@ -0,0 +1,288 @@ +PSCI Performance Measurements on Arm Juno Development Platform +============================================================== + +This document summarises the findings of performance measurements of key +operations in the ARM Trusted Firmware (TF) Power State Coordination Interface +(PSCI) implementation, using the in-built Performance Measurement Framework +(PMF) and runtime instrumentation timestamps. + +Method +------ + +We used the `Juno R1 platform`_ for these tests, which has 4 x Cortex-A53 and 2 +x Cortex-A57 clusters running at the following frequencies: + ++-----------------+--------------------+ +| Domain | Frequency (MHz) | ++=================+====================+ +| Cortex-A57 | 900 (nominal) | ++-----------------+--------------------+ +| Cortex-A53 | 650 (underdrive) | ++-----------------+--------------------+ +| AXI subsystem | 533 | ++-----------------+--------------------+ + +Juno supports CPU, cluster and system power down states, corresponding to power +levels 0, 1 and 2 respectively. It does not support any retention states. + +We used the upstream `TF master as of 31/01/2017`_, building the platform using +the ``ENABLE_RUNTIME_INSTRUMENTATION`` option: + +:: + + make PLAT=juno ENABLE_RUNTIME_INSTRUMENTATION=1 \ + SCP_BL2= \ + BL33= \ + all fip + +When using the debug build of TF, there was no noticeable difference in the +results. + +The tests are based on an ARM-internal test framework. The release build of this +framework was used because the results in the debug build became skewed; the +console output prevented some of the tests from executing in parallel. + +The tests consist of both parallel and sequential tests, which are broadly +described as follows: + +- **Parallel Tests** This type of test powers on all the non-lead CPUs and + brings them and the lead CPU to a common synchronization point. The lead CPU + then initiates the test on all CPUs in parallel. + +- **Sequential Tests** This type of test powers on each non-lead CPU in + sequence. The lead CPU initiates the test on a non-lead CPU then waits for the + test to complete before proceeding to the next non-lead CPU. The lead CPU then + executes the test on itself. + +In the results below, CPUs 0-3 refer to CPUs in the little cluster (A53) and +CPUs 4-5 refer to CPUs in the big cluster (A57). In all cases CPU 4 is the lead +CPU. + +``PSCI_ENTRY`` refers to the time taken from entering the TF PSCI implementation +to the point the hardware enters the low power state (WFI). Referring to the TF +runtime instrumentation points, this corresponds to: +``(RT_INSTR_ENTER_HW_LOW_PWR - RT_INSTR_ENTER_PSCI)``. + +``PSCI_EXIT`` refers to the time taken from the point the hardware exits the low +power state to exiting the TF PSCI implementation. This corresponds to: +``(RT_INSTR_EXIT_PSCI - RT_INSTR_EXIT_HW_LOW_PWR)``. + +``CFLUSH_OVERHEAD`` refers to the part of ``PSCI_ENTRY`` taken to flush the +caches. This corresponds to: ``(RT_INSTR_EXIT_CFLUSH - RT_INSTR_ENTER_CFLUSH)``. + +Note there is very little variance observed in the values given (~1us), although +the values for each CPU are sometimes interchanged, depending on the order in +which locks are acquired. Also, there is very little variance observed between +executing the tests sequentially in a single boot or rebooting between tests. + +Given that runtime instrumentation using PMF is invasive, there is a small +(unquantified) overhead on the results. PMF uses the generic counter for +timestamps, which runs at 50MHz on Juno. + +Results and Commentary +---------------------- + +``CPU_SUSPEND`` to deepest power level on all CPUs in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 27 | 20 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 114 | 86 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 202 | 58 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 375 | 29 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 20 | 22 | 6 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 290 | 18 | 206 | ++-------+---------------------+--------------------+--------------------------+ + +A large variance in ``PSCI_ENTRY`` and ``PSCI_EXIT`` times across CPUs is +observed due to TF PSCI lock contention. In the worst case, CPU 3 has to wait +for the 3 other CPUs in the cluster (0-2) to complete ``PSCI_ENTRY`` and release +the lock before proceeding. + +The ``CFLUSH_OVERHEAD`` times for CPUs 3 and 5 are higher because they are the +last CPUs in their respective clusters to power down, therefore both the L1 and +L2 caches are flushed. + +The ``CFLUSH_OVERHEAD`` time for CPU 5 is a lot larger than that for CPU 3 +because the L2 cache size for the big cluster is lot larger (2MB) compared to +the little cluster (1MB). + +``CPU_SUSPEND`` to power level 0 on all CPUs in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 116 | 14 | 8 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 204 | 14 | 8 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 287 | 13 | 8 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 376 | 13 | 9 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 29 | 15 | 7 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 21 | 15 | 8 | ++-------+---------------------+--------------------+--------------------------+ + +There is no lock contention in TF generic code at power level 0 but the large +variance in ``PSCI_ENTRY`` times across CPUs is due to lock contention in Juno +platform code. The platform lock is used to mediate access to a single SCP +communication channel. This is compounded by the SCP firmware waiting for each +AP CPU to enter WFI before making the channel available to other CPUs, which +effectively serializes the SCP power down commands from all CPUs. + +On platforms with a more efficient CPU power down mechanism, it should be +possible to make the ``PSCI_ENTRY`` times smaller and consistent. + +The ``PSCI_EXIT`` times are consistent across all CPUs because TF does not +require locks at power level 0. + +The ``CFLUSH_OVERHEAD`` times for all CPUs are small and consistent since only +the cache associated with power level 0 is flushed (L1). + +``CPU_SUSPEND`` to deepest power level on all CPUs in sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 195 | 22 | 180 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 21 | 17 | 6 | ++-------+---------------------+--------------------+--------------------------+ + +The ``CLUSH_OVERHEAD`` times for lead CPU 4 and all CPUs in the non-lead cluster +are large because all other CPUs in the cluster are powered down during the +test. The ``CPU_SUSPEND`` call powers down to the cluster level, requiring a +flush of both L1 and L2 caches. + +The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little +CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared +to the little cluster (1MB). + +The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are low because lead +CPU 4 continues to run while CPU 5 is suspended. Hence CPU 5 only powers down to +level 0, which only requires L1 cache flush. + +``CPU_SUSPEND`` to power level 0 on all CPUs in sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 22 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 22 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 21 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 22 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 17 | 14 | 6 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 18 | 15 | 6 | ++-------+---------------------+--------------------+--------------------------+ + +Here the times are small and consistent since there is no contention and it is +only necessary to flush the cache to power level 0 (L1). This is the best case +scenario. + +The ``PSCI_ENTRY`` times for CPUs in the big cluster are slightly smaller than +for the CPUs in little cluster due to greater CPU performance. + +The ``PSCI_EXIT`` times are generally lower than in the last test because the +cluster remains powered on throughout the test and there is less code to execute +on power on (for example, no need to enter CCI coherency) + +``CPU_OFF`` on all non-lead CPUs in sequence then ``CPU_SUSPEND`` on lead CPU to deepest power level +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The test sequence here is as follows: + +1. Call ``CPU_ON`` and ``CPU_OFF`` on each non-lead CPU in sequence. + +2. Program wake up timer and suspend the lead CPU to the deepest power level. + +3. Call ``CPU_ON`` on non-lead CPU to get the timestamps from each CPU. + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 110 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 110 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 110 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 111 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 195 | 22 | 181 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 20 | 23 | 6 | ++-------+---------------------+--------------------+--------------------------+ + +The ``CFLUSH_OVERHEAD`` times for all little CPUs are large because all other +CPUs in that cluster are powerered down during the test. The ``CPU_OFF`` call +powers down to the cluster level, requiring a flush of both L1 and L2 caches. + +The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are small because +lead CPU 4 is running and CPU 5 only powers down to level 0, which only requires +an L1 cache flush. + +The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little +CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared +to the little cluster (1MB). + +The ``PSCI_EXIT`` times for CPUs in the big cluster are slightly smaller than +for CPUs in the little cluster due to greater CPU performance. These times +generally are greater than the ``PSCI_EXIT`` times in the ``CPU_SUSPEND`` tests +because there is more code to execute in the "on finisher" compared to the +"suspend finisher" (for example, GIC redistributor register programming). + +``PSCI_VERSION`` on all CPUs in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since very little code is associated with ``PSCI_VERSION``, this test +approximates the round trip latency for handling a fast SMC at EL3 in TF. + ++-------+-------------------+ +| CPU | TOTAL TIME (ns) | ++=======+===================+ +| 0 | 3020 | ++-------+-------------------+ +| 1 | 2940 | ++-------+-------------------+ +| 2 | 2980 | ++-------+-------------------+ +| 3 | 3060 | ++-------+-------------------+ +| 4 | 520 | ++-------+-------------------+ +| 5 | 720 | ++-------+-------------------+ + +The times for the big CPUs are less than the little CPUs due to greater CPU +performance. + +We suspect the time for lead CPU 4 is shorter than CPU 5 due to subtle cache +effects, given that these measurements are at the nano-second level. + +.. _Juno R1 platform: https://www.arm.com/files/pdf/Juno_r1_ARM_Dev_datasheet.pdf +.. _TF master as of 31/01/2017: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/?id=c38b36d diff --git a/docs/plat/index.rst b/docs/plat/index.rst new file mode 100644 index 0000000..3a917f3 --- /dev/null +++ b/docs/plat/index.rst @@ -0,0 +1,29 @@ +Platform Ports +============== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + allwinner + fvp_ve + imx8 + imx8m + intel-stratix10 + ls1043a + meson-gxbb + meson-gxl + mt8183 + nvidia-tegra + poplar + qemu + rcar-gen3 + rockchip + rpi3 + socionext-uniphier + stm32mp1 + synquacer + ti-k3 + warp7 + xilinx-zynqmp diff --git a/docs/plat/marvell/build.txt b/docs/plat/marvell/build.txt new file mode 100644 index 0000000..7b75196 --- /dev/null +++ b/docs/plat/marvell/build.txt @@ -0,0 +1,194 @@ +TF-A Build Instructions +====================== + +This section describes how to compile the ARM Trusted Firmware (TF-A) project for Marvell's platforms. + +Build Instructions +------------------ +(1) Set the cross compiler:: + + > export CROSS_COMPILE=/path/to/toolchain/aarch64-linux-gnu- + +(2) Set path for FIP images: + + Set U-Boot image path (relatively to TF-A root or absolute path):: + + > export BL33=path/to/u-boot.bin + + For example: if U-Boot project (and its images) is located at ~/project/u-boot, + BL33 should be ~/project/u-boot/u-boot.bin + + .. note:: + + u-boot.bin should be used and not u-boot-spl.bin + + Set MSS/SCP image path (mandatory only for Armada80x0):: + + > export SCP_BL2=path/to/mrvl_scp_bl2*.img + +(3) Armada-37x0 build requires WTP tools installation. + + See below in the section "Tools and external components installation". + Install ARM 32-bit cross compiler, which is required for building WTMI image for CM3:: + + > sudo apt-get install gcc-arm-linux-gnueabi + +(4) Clean previous build residuals (if any):: + + > make distclean + +(5) Build TF-A: + + There are several build options: + + - DEBUG: default is without debug information (=0). in order to enable it use DEBUG=1 + Must be disabled when building UART recovery images due to current console driver + implementation that is not compatible with Xmodem protocol used for boot image download. + + - LOG_LEVEL: defines the level of logging which will be purged to the default output port. + + LOG_LEVEL_NONE 0 + LOG_LEVEL_ERROR 10 + LOG_LEVEL_NOTICE 20 + LOG_LEVEL_WARNING 30 + LOG_LEVEL_INFO 40 + LOG_LEVEL_VERBOSE 50 + + - USE_COHERENT_MEM: This flag determines whether to include the coherent memory region in the + BL memory map or not. + + - LLC_ENABLE: Flag defining the LLC (L3) cache state. The cache is enabled by default (LLC_ENABLE=1). + + - MARVELL_SECURE_BOOT: build trusted(=1)/non trusted(=0) image, default is non trusted. + + - BLE_PATH: + Points to BLE (Binary ROM extension) sources folder. Only required for A8K builds. + The parameter is optional, its default value is "plat/marvell/a8k/common/ble". + + - MV_DDR_PATH: + For A7/8K, use this parameter to point to mv_ddr driver sources to allow BLE build. For A37x0, + it is used for ddr_tool build. + Usage example: MV_DDR_PATH=path/to/mv_ddr + The parameter is optional for A7/8K, when this parameter is not set, the mv_ddr + sources are expected to be located at: drivers/marvell/mv_ddr. However, the parameter + is necessary for A37x0. + For the mv_ddr source location, check the section "Tools and external components installation" + + - DDR_TOPOLOGY: For Armada37x0 only, the DDR topology map index/name, default is 0. + Supported Options: + - DDR3 1CS (0): DB-88F3720-DDR3-Modular (512MB); EspressoBIN (512MB) + - DDR4 1CS (1): DB-88F3720-DDR4-Modular (512MB) + - DDR3 2CS (2): EspressoBIN V3-V5 (1GB) + - DDR4 2CS (3): DB-88F3720-DDR4-Modular (4GB) + - DDR3 1CS (4): DB-88F3720-DDR3-Modular (1GB) + - DDR4 1CS (5): EspressoBin V7 (1GB) + - DDR4 2CS (6): EspressoBin V7 (2GB) + - CUSTOMER (CUST): Customer board, DDR3 1CS 512MB + + - CLOCKSPRESET: For Armada37x0 only, the clock tree configuration preset including CPU and DDR frequency, + default is CPU_800_DDR_800. + - CPU_600_DDR_600 - CPU at 600 MHz, DDR at 600 MHz + - CPU_800_DDR_800 - CPU at 800 MHz, DDR at 800 MHz + - CPU_1000_DDR_800 - CPU at 1000 MHz, DDR at 800 MHz + - CPU_1200_DDR_750 - CPU at 1200 MHz, DDR at 750 MHz + + - BOOTDEV: For Armada37x0 only, the flash boot device, default is SPINOR, + Currently, Armada37x0 only supports SPINOR, SPINAND, EMMCNORM and SATA: + + - SPINOR - SPI NOR flash boot + - SPINAND - SPI NAND flash boot + - EMMCNORM - eMMC Download Mode + Download boot loader or program code from eMMC flash into CM3 or CA53 + Requires full initialization and command sequence + - SATA - SATA device boot + + - PARTNUM: For Armada37x0 only, the boot partition number, default is 0. To boot from eMMC, the value + should be aligned with the parameter in U-Boot with name of CONFIG_SYS_MMC_ENV_PART, whose + value by default is 1. + For details about CONFIG_SYS_MMC_ENV_PART, please refer to the U-Boot build instructions. + + - WTMI_IMG: For Armada37x0 only, the path of the WTMI image can point to an image which does + nothing, an image which supports EFUSE or a customized CM3 firmware binary. The default image + is wtmi.bin that built from sources in WTP folder, which is the next option. If the default + image is OK, then this option should be skipped. + + - WTP: For Armada37x0 only, use this parameter to point to wtptools source code directory, which + can be found as a3700_utils.zip in the release. + Usage example: WTP=/path/to/a3700_utils + + For example, in order to build the image in debug mode with log level up to 'notice' level run:: + + > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 PLAT= all fip + + And if we want to build a Armada37x0 image in debug mode with log level up to 'notice' level, + the image has the preset CPU at 1000 MHz, preset DDR3 at 800 MHz, the DDR topology of DDR4 2CS, + the image boot from SPI NOR flash partition 0, and the image is non trusted in WTP, the command + line is as following:: + + > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 CLOCKSPRESET=CPU_1000_DDR_800 \ + MARVELL_SECURE_BOOT=0 DDR_TOPOLOGY=3 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 all fip + + Supported MARVELL_PLATFORM are: + - a3700 (for both A3720 DB and EspressoBin) + - a70x0 + - a70x0_amc (for AMC board) + - a80x0 + - a80x0_mcbin (for MacciatoBin) + +Special Build Flags +-------------------- + - PLAT_RECOVERY_IMAGE_ENABLE: When set this option to enable secondary recovery function when build + atf. In order to build UART recovery image this operation should be disabled for a70x0 and a80x0 + because of hardware limitation (boot from secondary image can interrupt UART recovery process). + This MACRO definition is set in plat/marvell/a8k/common/include/platform_def.h file + +(for more information about build options, please refer to section 'Summary of build options' in TF-A user-guide: + https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/user-guide.md) + + +Build output +------------- +Marvell's TF-A compilation generates 7 files: + - ble.bin - BLe image + - bl1.bin - BL1 image + - bl2.bin - BL2 image + - bl31.bin - BL31 image + - fip.bin - FIP image (contains BL2, BL31 & BL33 (U-Boot) images) + - boot-image.bin - TF-A image (contains BL1 and FIP images) + - flash-image.bin - Image which contains boot-image.bin and SPL image; + should be placed on the boot flash/device. + + +Tools and external components installation +========================================== + +Armada37x0 Builds require installation of 3 components +------------------------------------------------------- + +(1) ARM cross compiler capable of building images for the service CPU (CM3). + This component is usually included in the Linux host packages. + On Debian/Ubuntu hosts the default GNU ARM tool chain can be installed + using the following command:: + + > sudo apt-get install gcc-arm-linux-gnueabi + + Only if required, the default tool chain prefix "arm-linux-gnueabi-" can be + overwritten using the environment variable CROSS_CM3. + Example for BASH shell:: + + > export CROSS_CM3=/opt/arm-cross/bin/arm-linux-gnueabi + +(2) DDR initialization library sources (mv_ddr) available at the following repository + (use the "mv_ddr-armada-atf-mainline" branch):: + https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git + +(3) Armada3700 tools available at the following repository (use the latest release branch):: + https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell.git + +Armada70x0 and Armada80x0 Builds require installation of an additional component +-------------------------------------------------------------------------------- + +(1) DDR initialization library sources (mv_ddr) available at the following repository + (use the "mv_ddr-armada-atf-mainline" branch):: + https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git + diff --git a/docs/plat/marvell/misc/mvebu-a8k-addr-map.txt b/docs/plat/marvell/misc/mvebu-a8k-addr-map.txt new file mode 100644 index 0000000..586e8b7 --- /dev/null +++ b/docs/plat/marvell/misc/mvebu-a8k-addr-map.txt @@ -0,0 +1,47 @@ +Address decoding flow and address translation units of Marvell Armada 8K SoC family + ++--------------------------------------------------------------------------------------------------+ +| +-------------+ +--------------+ | +| | Memory +----- DRAM CS | | +|+------------+ +-----------+ +-----------+ | Controller | +--------------+ | +|| AP DMA | | | | | +-------------+ | +|| SD/eMMC | | CA72 CPUs | | AP MSS | +-------------+ | +|| MCI-0/1 | | | | | | Memory | | +|+------+-----+ +--+--------+ +--------+--+ +------------+ | Controller | +-------------+ | +| | | | | +----- Translaton | |AP | | +| | | | | | +-------------+ |Configuration| | +| | | +-----+ +-------------------------Space | | +| | | +-------------+ | CCU | +-------------+ | +| | | | MMU +---------+ Windows | +-----------+ +-------------+ | +| | +-| translation | | Lookup +---- +--------- AP SPI | | +| | +-------------+ | | | | +-------------+ | +| | +-------------+ | | | IO | +-------------+ | +| +------------| SMMU +---------+ | | Windows +--------- AP MCI0/1 | | +| | translation | +------------+ | Lookup | +-------------+ | +| +---------+---+ | | +-------------+ | +| - | | +--------- AP STM | | +| +----------------- | | +-------------+ | +| AP | | +-+---------+ | ++---------------------------------------------------------------|----------------------------------+ ++-------------|-------------------------------------------------|----------------------------------+ +| CP | +-------------+ +------+-----+ +-------------------+ | +| | | | | +------- SB CFG Space | | +| | | DIOB | | | +-------------------+ | +| | | Windows ----------------- IOB | +-------------------+ | +| | | Control | | Windows +------| SB PCIe-0 - PCIe2 | | +| | | | | Lookup | +-------------------+ | +| | +------+------+ | | +-------------------+ | +| | | | +------+ SB NAND | | +| | | +------+-----+ +-------------------+ | +| | | | | +| | | | | +| +------------------+ +------------+ +------+-----+ +-------------------+ | +| | Network Engine | | | | +------- SB SPI-0/SPI-1 | | +| | Security Engine | | PCIe, MSS | | RUNIT | +-------------------+ | +| | SATA, USB | | DMA | | Windows | +-------------------+ | +| | SD/eMMC | | | | Lookup +------- SB Device Bus | | +| | TDM, I2C | | | | | +-------------------+ | +| +------------------+ +------------+ +------------+ | +| | ++--------------------------------------------------------------------------------------------------+ + diff --git a/docs/plat/marvell/misc/mvebu-amb.txt b/docs/plat/marvell/misc/mvebu-amb.txt new file mode 100644 index 0000000..2a7a41e --- /dev/null +++ b/docs/plat/marvell/misc/mvebu-amb.txt @@ -0,0 +1,45 @@ +AMB - AXI MBUS address decoding +------------------------------- + +AXI to M-bridge decoding unit driver for Marvell Armada 8K and 8K+ SoCs. + +- The Runit offers a second level of address windows lookup. It is used to map transaction towards +the CD BootROM, SPI0, SPI1 and Device bus (NOR). +- The Runit contains eight configurable windows. Each window defines a contiguous, +address space and the properties associated with that address space. + +Unit Bank ATTR +Device-Bus DEV_BOOT_CS 0x2F + DEV_CS0 0x3E + DEV_CS1 0x3D + DEV_CS2 0x3B + DEV_CS3 0x37 +SPI-0 SPI_A_CS0 0x1E + SPI_A_CS1 0x5E + SPI_A_CS2 0x9E + SPI_A_CS3 0xDE + SPI_A_CS4 0x1F + SPI_A_CS5 0x5F + SPI_A_CS6 0x9F + SPI_A_CS7 0xDF +SPI1 SPI_B_CS0 0x1A + SPI_B_CS1 0x5A + SPI_B_CS2 0x9A + SPI_B_CS3 0xDA +BOOT_ROM BOOT_ROM 0x1D +UART UART 0x01 + +Mandatory functions: + - marvell_get_amb_memory_map + returns the AMB windows configuration and the number of windows + +Mandatory structures: + amb_memory_map - Array that include the configuration of the windows + every window/entry is a struct which has 2 parameters: + - base address of the window + - Attribute of the window + +Examples: + struct addr_map_win amb_memory_map[] = { + {0xf900, AMB_DEV_CS0_ID}, + }; diff --git a/docs/plat/marvell/misc/mvebu-ccu.txt b/docs/plat/marvell/misc/mvebu-ccu.txt new file mode 100644 index 0000000..9764027 --- /dev/null +++ b/docs/plat/marvell/misc/mvebu-ccu.txt @@ -0,0 +1,23 @@ +Marvell CCU address decoding bindings +===================================== + +CCU configration driver (1st stage address translation) for Marvell Armada 8K and 8K+ SoCs. + +The CCU node includes a description of the address decoding configuration. + +Mandatory functions: + - marvell_get_ccu_memory_map + return the CCU windows configuration and the number of windows + of the specific AP. + +Mandatory structures: + ccu_memory_map - Array that includes the configuration of the windows + every window/entry is a struct which has 3 parameters: + - Base address of the window + - Size of the window + - Target-ID of the window + +Example: + struct addr_map_win ccu_memory_map[] = { + {0x00000000f2000000, 0x00000000e000000, IO_0_TID}, /* IO window */ + }; diff --git a/docs/plat/marvell/misc/mvebu-io-win.txt b/docs/plat/marvell/misc/mvebu-io-win.txt new file mode 100644 index 0000000..c83ad1f --- /dev/null +++ b/docs/plat/marvell/misc/mvebu-io-win.txt @@ -0,0 +1,35 @@ +Marvell IO WIN address decoding bindings +===================================== + +IO Window configration driver (2nd stage address translation) for Marvell Armada 8K and 8K+ SoCs. + +The IO WIN includes a description of the address decoding configuration. + +Transactions that are decoded by CCU windows as IO peripheral, have an additional +layer of decoding. This additional address decoding layer defines one of the +following targets: + 0x0 = BootRom + 0x1 = STM (Serial Trace Macro-cell, a programmer's port into trace stream) + 0x2 = SPI direct access + 0x3 = PCIe registers + 0x4 = MCI Port + 0x5 = PCIe port + +Mandatory functions: + - marvell_get_io_win_memory_map + returns the IO windows configuration and the number of windows + of the specific AP. + +Mandatory structures: + io_win_memory_map - Array that include the configuration of the windows + every window/entry is a struct which has 3 parameters: + - Base address of the window + - Size of the window + - Target-ID of the window + +Example: + struct addr_map_win io_win_memory_map[] = { + {0x00000000fe000000, 0x000000001f00000, PCIE_PORT_TID}, /* PCIe window 31Mb for PCIe port*/ + {0x00000000ffe00000, 0x000000000100000, PCIE_REGS_TID}, /* PCI-REG window 64Kb for PCIe-reg*/ + {0x00000000f6000000, 0x000000000100000, MCIPHY_TID}, /* MCI window 1Mb for PHY-reg*/ + }; diff --git a/docs/plat/marvell/misc/mvebu-iob.txt b/docs/plat/marvell/misc/mvebu-iob.txt new file mode 100644 index 0000000..97ec09d --- /dev/null +++ b/docs/plat/marvell/misc/mvebu-iob.txt @@ -0,0 +1,40 @@ +Marvell IOB address decoding bindings +===================================== + +IO bridge configration driver (3rd stage address translation) for Marvell Armada 8K and 8K+ SoCs. + +The IOB includes a description of the address decoding configuration. + +IOB supports up to n (in CP110 n=24) windows for external memory transaction. +When a transaction passes through the IOB, its address is compared to each of +the enabled windows. If there is a hit and it passes the security checks, it is +advanced to the target port. + +Mandatory functions: + - marvell_get_iob_memory_map + returns the IOB windows configuration and the number of windows + +Mandatory structures: + iob_memory_map - Array that include the configuration of the windows + every window/entry is a struct which has 3 parameters: + - Base address of the window + - Size of the window + - Target-ID of the window + +Target ID options: + - 0x0 = Internal configuration space + - 0x1 = MCI0 + - 0x2 = PEX1_X1 + - 0x3 = PEX2_X1 + - 0x4 = PEX0_X4 + - 0x5 = NAND flash + - 0x6 = RUNIT (NOR/SPI/BootRoom) + - 0x7 = MCI1 + +Example: + struct addr_map_win iob_memory_map[] = { + {0x00000000f7000000, 0x0000000001000000, PEX1_TID}, /* PEX1_X1 window */ + {0x00000000f8000000, 0x0000000001000000, PEX2_TID}, /* PEX2_X1 window */ + {0x00000000f6000000, 0x0000000001000000, PEX0_TID}, /* PEX0_X4 window */ + {0x00000000f9000000, 0x0000000001000000, NAND_TID} /* NAND window */ + }; diff --git a/docs/plat/marvell/porting.txt b/docs/plat/marvell/porting.txt new file mode 100644 index 0000000..f9a39a0 --- /dev/null +++ b/docs/plat/marvell/porting.txt @@ -0,0 +1,118 @@ +.. _porting: + +TF-A Porting Guide +================= + +This section describes how to port TF-A to a customer board, assuming that the SoC being used is already supported +in TF-A. + + +Source Code Structure +--------------------- +- The customer platform specific code shall reside under "plat/marvell//_cust" + (e.g. 'plat/marvell/a8k/a7040_cust'). +- The platform name for build purposes is called "_cust" (e.g. a7040_cust). +- The build system will reuse all files from within the soc directory, and take only the porting + files from the customer platform directory. + +Files that require porting are located at "plat/marvell//_cust" directory. + + +Armada-70x0/Armada-80x0 Porting +------------------------------- + + - SoC Physical Address Map (marvell_plat_config.c): + - This file describes the SoC physical memory mapping to be used for the CCU, IOWIN, AXI-MBUS and IOB + address decode units (Refer to the functional spec for more details). + - In most cases, using the default address decode windows should work OK. + - In cases where a special physical address map is needed (e.g. Special size for PCIe MEM windows, + large memory mapped SPI flash...), then porting of the SoC memory map is required. + - Note: For a detailed information on how CCU, IOWIN, AXI-MBUS & IOB work, please refer to the SoC functional spec, + and under "docs/marvell/misc/mvebu-[ccu/iob/amb/io-win].txt" files. + + - boot loader recovery (marvell_plat_config.c): + - Background: + boot rom can skip the current image and choose to boot from next position if a specific value + (0xDEADB002) is returned by the ble main function. This feature is used for boot loader recovery + by booting from a valid flash-image saved in next position on flash (e.g. address 2M in SPI flash). + + Supported options to implement the skip request are: + - GPIO + - I2C + - User defined + + - Porting: + Under marvell_plat_config.c, implement struct skip_image that includes specific board parameters. + .. warning:: to disable this feature make sure the struct skip_image is not implemented. + + - Example: + In A7040-DB specific implementation (plat/marvell/a8k/a70x0/board/marvell_plat_config.c), + the image skip is implemented using GPIO: mpp 33 (SW5). + + Before resetting the board make sure there is a valid image on the next flash address: + -tftp [valid address] flash-image.bin + -sf update [valid address] 0x2000000 [size] + + Press reset and keep pressing the button connected to the chosen GPIO pin. A skip image request + message is printed on the screen and boot rom boots from the saved image at the next position. + + - DDR Porting (dram_port.c): + - This file defines the dram topology and parameters of the target board. + - The DDR code is part of the BLE component, which is an extension of ARM Trusted Firmware (TF-A). + - The DDR driver called mv_ddr is released separately apart from TF-A sources. + - The BLE and consequently, the DDR init code is executed at the early stage of the boot process. + - Each supported platform of the TF-A has its own DDR porting file called dram_port.c located at + ``atf/plat/marvell/a8k//board`` directory. + - Please refer to '/doc/porting_guide.txt' for detailed porting description. + - The build target directory is "build//release/ble". + + - Comphy Porting (phy-porting-layer.h or phy-default-porting-layer.h) + - Background: + Some of the comphy's parameters value depend on the HW connection between the SoC and the PHY. Every + board type has specific HW characteristics like wire length. Due to those differences some comphy + parameters vary between board types. Therefore each board type can have its own list of values for + all relevant comphy parameters. The PHY porting layer specifies which parameters need to be suited and + the board designer should provide relevant values. + + .. seealso:: + For XFI/SFI comphy type there is procedure "rx_training" which eases process of suiting some of + the parameters. Please see :ref:`uboot_cmd` section: rx_training. + + The PHY porting layer simplifies updating static values per board type, which are now grouped in one place. + + .. note:: + The parameters for the same type of comphy may vary even for the same board type, it is because + the lanes from comphy-x to some PHY may have different HW characteristic than lanes from + comphy-y to the same (multiplexed) or other PHY. + + - Porting: + The porting layer for PHY was introduced in TF-A. There is one file + ``drivers/marvell/comphy/phy-default-porting-layer.h`` which contains the defaults. Those default + parameters are used only if there is no appropriate phy-porting-layer.h file under: + ``plat/marvell///board/phy-porting-layer.h``. If the phy-porting-layer.h exists, + the phy-default-porting-layer.h is not going to be included. + + .. warning:: + Not all comphy types are already reworked to support the PHY porting layer, currently the porting + layer is supported for XFI/SFI and SATA comphy types. + + The easiest way to prepare the PHY porting layer for custom board is to copy existing example to a new + platform: + + - cp ``plat/marvell/a8k/a80x0/board/phy-porting-layer.h`` "plat/marvell///board/phy-porting-layer.h" + - adjust relevant parameters or + - if different comphy index is used for specific feature, move it to proper table entry and then adjust. + + .. note:: + The final table size with comphy parameters can be different, depending on the CP module count for + given SoC type. + + - Example: + Example porting layer for armada-8040-db is under: ``plat/marvell/a8k/a80x0/board/phy-porting-layer.h`` + + .. note:: + If there is no PHY porting layer for new platform (missing phy-porting-layer.h), the default + values are used (drivers/marvell/comphy/phy-default-porting-layer.h) and the user is warned: + + .. warning:: + "Using default comphy parameters - it may be required to suit them for your board". diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst index a22bfc6..122b1de 100644 --- a/docs/plat/rpi3.rst +++ b/docs/plat/rpi3.rst @@ -1,8 +1,7 @@ Trusted Firmware-A for Raspberry Pi 3 ===================================== -.. section-numbering:: - :suffix: . + .. contents:: diff --git a/docs/platform-compatibility-policy.rst b/docs/platform-compatibility-policy.rst deleted file mode 100644 index 6bab447..0000000 --- a/docs/platform-compatibility-policy.rst +++ /dev/null @@ -1,45 +0,0 @@ -TF-A Platform Compatibility Policy -================================== - - -.. section-numbering:: - :suffix: . - -.. contents:: - --------------- - -Introduction ------------- - -This document clarifies the project's policy around compatibility for upstream -platforms. - -Platform compatibility policy ------------------------------ - -Platform compatibility is mainly affected by changes to Platform APIs (as -documented in the `Porting Guide`_), driver APIs (like the GICv3 drivers) or -library interfaces (like xlat_table library). The project will try to maintain -compatibility for upstream platforms. Due to evolving requirements and -enhancements, there might be changes affecting platform compatibility which -means the previous interface needs to be deprecated and a new interface -introduced to replace it. In case the migration to the new interface is trivial, -the contributor of the change is expected to make good effort to migrate the -upstream platforms to the new interface. - -The `Release information`_ documents the deprecated interfaces and the intended -release after which it will be removed. When an interface is deprecated, the -page must be updated to indicate the release after which the interface will be -removed. This must be at least 1 full release cycle in future. For non-trivial -interface changes, a `tf-issue`_ should be posted to notify platforms that they -should migrate away from the deprecated interfaces. Platforms are expected to -migrate before the removal of the deprecated interface. - --------------- - -*Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.* - -.. _Porting Guide: ./porting-guide.rst -.. _Release information: https://github.com/ARM-software/arm-trusted-firmware/wiki/TF-A-Release-information#removal-of-deprecated-interfaces -.. _tf-issue: https://github.com/ARM-software/tf-issues/issues diff --git a/docs/platform-interrupt-controller-API.rst b/docs/platform-interrupt-controller-API.rst deleted file mode 100644 index ad68709..0000000 --- a/docs/platform-interrupt-controller-API.rst +++ /dev/null @@ -1,313 +0,0 @@ -Platform Interrupt Controller API documentation -=============================================== - -.. section-numbering:: - :suffix: . - -.. contents:: - -This document lists the optional platform interrupt controller API that -abstracts the runtime configuration and control of interrupt controller from the -generic code. The mandatory APIs are described in the `porting guide`__. - -.. __: porting-guide.rst#interrupt-management-framework-in-bl31 - -Function: unsigned int plat_ic_get_running_priority(void); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : unsigned int - -This API should return the priority of the interrupt the PE is currently -servicing. This must be be called only after an interrupt has already been -acknowledged via ``plat_ic_acknowledge_interrupt``. - -In the case of Arm standard platforms using GIC, the *Running Priority Register* -is read to determine the priority of the interrupt. - -Function: int plat_ic_is_spi(unsigned int id); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : int - -The API should return whether the interrupt ID (first parameter) is categorized -as a Shared Peripheral Interrupt. Shared Peripheral Interrupts are typically -associated to system-wide peripherals, and these interrupts can target any PE in -the system. - -Function: int plat_ic_is_ppi(unsigned int id); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : int - -The API should return whether the interrupt ID (first parameter) is categorized -as a Private Peripheral Interrupt. Private Peripheral Interrupts are typically -associated with peripherals that are private to each PE. Interrupts from private -peripherals target to that PE only. - -Function: int plat_ic_is_sgi(unsigned int id); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : int - -The API should return whether the interrupt ID (first parameter) is categorized -as a Software Generated Interrupt. Software Generated Interrupts are raised by -explicit programming by software, and are typically used in inter-PE -communication. Secure SGIs are reserved for use by Secure world software. - -Function: unsigned int plat_ic_get_interrupt_active(unsigned int id); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : int - -This API should return the *active* status of the interrupt ID specified by the -first parameter, ``id``. - -In case of Arm standard platforms using GIC, the implementation of the API reads -the GIC *Set Active Register* to read and return the active status of the -interrupt. - -Function: void plat_ic_enable_interrupt(unsigned int id); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : void - -This API should enable the interrupt ID specified by the first parameter, -``id``. PEs in the system are expected to receive only enabled interrupts. - -In case of Arm standard platforms using GIC, the implementation of the API -inserts barrier to make memory updates visible before enabling interrupt, and -then writes to GIC *Set Enable Register* to enable the interrupt. - -Function: void plat_ic_disable_interrupt(unsigned int id); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : void - -This API should disable the interrupt ID specified by the first parameter, -``id``. PEs in the system are not expected to receive disabled interrupts. - -In case of Arm standard platforms using GIC, the implementation of the API -writes to GIC *Clear Enable Register* to disable the interrupt, and inserts -barrier to make memory updates visible afterwards. - -Function: void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Argument : unsigned int - Return : void - -This API should set the priority of the interrupt specified by first parameter -``id`` to the value set by the second parameter ``priority``. - -In case of Arm standard platforms using GIC, the implementation of the API -writes to GIC *Priority Register* set interrupt priority. - -Function: int plat_ic_has_interrupt_type(unsigned int type); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : int - -This API should return whether the platform supports a given interrupt type. The -parameter ``type`` shall be one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1``, or -``INTR_TYPE_NS``. - -In case of Arm standard platforms using GICv3, the implementation of the API -returns ``1`` for all interrupt types. - -In case of Arm standard platforms using GICv2, the API always return ``1`` for -``INTR_TYPE_NS``. Return value for other types depends on the value of build -option ``GICV2_G0_FOR_EL3``: - -- For interrupt type ``INTR_TYPE_EL3``: - - - When ``GICV2_G0_FOR_EL3`` is ``0``, it returns ``0``, indicating no support - for EL3 interrupts. - - - When ``GICV2_G0_FOR_EL3`` is ``1``, it returns ``1``, indicating support for - EL3 interrupts. - -- For interrupt type ``INTR_TYPE_S_EL1``: - - - When ``GICV2_G0_FOR_EL3`` is ``0``, it returns ``1``, indicating support for - Secure EL1 interrupts. - - - When ``GICV2_G0_FOR_EL3`` is ``1``, it returns ``0``, indicating no support - for Secure EL1 interrupts. - -Function: void plat_ic_set_interrupt_type(unsigned int id, unsigned int type); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Argument : unsigned int - Return : void - -This API should set the interrupt specified by first parameter ``id`` to the -type specified by second parameter ``type``. The ``type`` parameter can be -one of: - -- ``INTR_TYPE_NS``: interrupt is meant to be consumed by the Non-secure world. - -- ``INTR_TYPE_S_EL1``: interrupt is meant to be consumed by Secure EL1. - -- ``INTR_TYPE_EL3``: interrupt is meant to be consumed by EL3. - -In case of Arm standard platforms using GIC, the implementation of the API -writes to the GIC *Group Register* and *Group Modifier Register* (only GICv3) to -assign the interrupt to the right group. - -For GICv3: - -- ``INTR_TYPE_NS`` maps to Group 1 interrupt. - -- ``INTR_TYPE_S_EL1`` maps to Secure Group 1 interrupt. - -- ``INTR_TYPE_EL3`` maps to Secure Group 0 interrupt. - -For GICv2: - -- ``INTR_TYPE_NS`` maps to Group 1 interrupt. - -- When the build option ``GICV2_G0_FOR_EL3`` is set to ``0`` (the default), - ``INTR_TYPE_S_EL1`` maps to Group 0. Otherwise, ``INTR_TYPE_EL3`` maps to - Group 0 interrupt. - -Function: void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : int - Argument : u_register_t - Return : void - -This API should raise an EL3 SGI. The first parameter, ``sgi_num``, specifies -the ID of the SGI. The second parameter, ``target``, must be the MPIDR of the -target PE. - -In case of Arm standard platforms using GIC, the implementation of the API -inserts barrier to make memory updates visible before raising SGI, then writes -to appropriate *SGI Register* in order to raise the EL3 SGI. - -Function: void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, u_register_t mpidr); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Argument : unsigned int - Argument : u_register_t - Return : void - -This API should set the routing mode of Share Peripheral Interrupt (SPI) -specified by first parameter ``id`` to that specified by the second parameter -``routing_mode``. - -The ``routing_mode`` parameter can be one of: - -- ``INTR_ROUTING_MODE_ANY`` means the interrupt can be routed to any PE in the - system. The ``mpidr`` parameter is ignored in this case. - -- ``INTR_ROUTING_MODE_PE`` means the interrupt is routed to the PE whose MPIDR - value is specified by the parameter ``mpidr``. - -In case of Arm standard platforms using GIC, the implementation of the API -writes to the GIC *Target Register* (GICv2) or *Route Register* (GICv3) to set -the routing. - -Function: void plat_ic_set_interrupt_pending(unsigned int id); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : void - -This API should set the interrupt specified by first parameter ``id`` to -*Pending*. - -In case of Arm standard platforms using GIC, the implementation of the API -inserts barrier to make memory updates visible before setting interrupt pending, -and writes to the GIC *Set Pending Register* to set the interrupt pending -status. - -Function: void plat_ic_clear_interrupt_pending(unsigned int id); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : void - -This API should clear the *Pending* status of the interrupt specified by first -parameter ``id``. - -In case of Arm standard platforms using GIC, the implementation of the API -writes to the GIC *Clear Pending Register* to clear the interrupt pending -status, and inserts barrier to make memory updates visible afterwards. - -Function: unsigned int plat_ic_set_priority_mask(unsigned int id); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : int - -This API should set the priority mask (first parameter) in the interrupt -controller such that only interrupts of higher priority than the supplied one -may be signalled to the PE. The API should return the current priority value -that it's overwriting. - -In case of Arm standard platforms using GIC, the implementation of the API -inserts to order memory updates before updating mask, then writes to the GIC -*Priority Mask Register*, and make sure memory updates are visible before -potential trigger due to mask update. - -Function: unsigned int plat_ic_get_interrupt_id(unsigned int raw); [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : unsigned int - -This API should extract and return the interrupt number from the raw value -obtained by the acknowledging the interrupt (read using -``plat_ic_acknowledge_interrupt()``). If the interrupt ID is invalid, this API -should return ``INTR_ID_UNAVAILABLE``. - -In case of Arm standard platforms using GIC, the implementation of the API -masks out the interrupt ID field from the acknowledged value from GIC. - ----- - -*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst deleted file mode 100644 index 6244a63..0000000 --- a/docs/porting-guide.rst +++ /dev/null @@ -1,2832 +0,0 @@ -Trusted Firmware-A Porting Guide -================================ - - -.. section-numbering:: - :suffix: . - -.. contents:: - --------------- - -Introduction ------------- - -Porting Trusted Firmware-A (TF-A) to a new platform involves making some -mandatory and optional modifications for both the cold and warm boot paths. -Modifications consist of: - -- Implementing a platform-specific function or variable, -- Setting up the execution context in a certain way, or -- Defining certain constants (for example #defines). - -The platform-specific functions and variables are declared in -`include/plat/common/platform.h`_. The firmware provides a default implementation -of variables and functions to fulfill the optional requirements. These -implementations are all weakly defined; they are provided to ease the porting -effort. Each platform port can override them with its own implementation if the -default implementation is inadequate. - -Some modifications are common to all Boot Loader (BL) stages. Section 2 -discusses these in detail. The subsequent sections discuss the remaining -modifications for each BL stage in detail. - -This document should be read in conjunction with the TF-A `User Guide`_. - -Please refer to the `Platform compatibility policy`_ for the policy regarding -compatibility and deprecation of these porting interfaces. - -Only Arm development platforms (such as FVP and Juno) may use the -functions/definitions in ``include/plat/arm/common/`` and the corresponding -source files in ``plat/arm/common/``. This is done so that there are no -dependencies between platforms maintained by different people/companies. If you -want to use any of the functionality present in ``plat/arm`` files, please -create a pull request that moves the code to ``plat/common`` so that it can be -discussed. - -Common modifications --------------------- - -This section covers the modifications that should be made by the platform for -each BL stage to correctly port the firmware stack. They are categorized as -either mandatory or optional. - -Common mandatory modifications ------------------------------- - -A platform port must enable the Memory Management Unit (MMU) as well as the -instruction and data caches for each BL stage. Setting up the translation -tables is the responsibility of the platform port because memory maps differ -across platforms. A memory translation library (see ``lib/xlat_tables/``) is -provided to help in this setup. - -Note that although this library supports non-identity mappings, this is intended -only for re-mapping peripheral physical addresses and allows platforms with high -I/O addresses to reduce their virtual address space. All other addresses -corresponding to code and data must currently use an identity mapping. - -Also, the only translation granule size supported in TF-A is 4KB, as various -parts of the code assume that is the case. It is not possible to switch to -16 KB or 64 KB granule sizes at the moment. - -In Arm standard platforms, each BL stage configures the MMU in the -platform-specific architecture setup function, ``blX_plat_arch_setup()``, and uses -an identity mapping for all addresses. - -If the build option ``USE_COHERENT_MEM`` is enabled, each platform can allocate a -block of identity mapped secure memory with Device-nGnRE attributes aligned to -page boundary (4K) for each BL stage. All sections which allocate coherent -memory are grouped under ``coherent_ram``. For ex: Bakery locks are placed in a -section identified by name ``bakery_lock`` inside ``coherent_ram`` so that its -possible for the firmware to place variables in it using the following C code -directive: - -:: - - __section("bakery_lock") - -Or alternatively the following assembler code directive: - -:: - - .section bakery_lock - -The ``coherent_ram`` section is a sum of all sections like ``bakery_lock`` which are -used to allocate any data structures that are accessed both when a CPU is -executing with its MMU and caches enabled, and when it's running with its MMU -and caches disabled. Examples are given below. - -The following variables, functions and constants must be defined by the platform -for the firmware to work correctly. - -File : platform_def.h [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Each platform must ensure that a header file of this name is in the system -include path with the following constants defined. This will require updating -the list of ``PLAT_INCLUDES`` in the ``platform.mk`` file. - -Platform ports may optionally use the file `include/plat/common/common_def.h`_, -which provides typical values for some of the constants below. These values are -likely to be suitable for all platform ports. - -- **#define : PLATFORM_LINKER_FORMAT** - - Defines the linker format used by the platform, for example - ``elf64-littleaarch64``. - -- **#define : PLATFORM_LINKER_ARCH** - - Defines the processor architecture for the linker by the platform, for - example ``aarch64``. - -- **#define : PLATFORM_STACK_SIZE** - - Defines the normal stack memory available to each CPU. This constant is used - by `plat/common/aarch64/platform_mp_stack.S`_ and - `plat/common/aarch64/platform_up_stack.S`_. - -- **define : CACHE_WRITEBACK_GRANULE** - - Defines the size in bits of the largest cache line across all the cache - levels in the platform. - -- **#define : FIRMWARE_WELCOME_STR** - - Defines the character string printed by BL1 upon entry into the ``bl1_main()`` - function. - -- **#define : PLATFORM_CORE_COUNT** - - Defines the total number of CPUs implemented by the platform across all - clusters in the system. - -- **#define : PLAT_NUM_PWR_DOMAINS** - - Defines the total number of nodes in the power domain topology - tree at all the power domain levels used by the platform. - This macro is used by the PSCI implementation to allocate - data structures to represent power domain topology. - -- **#define : PLAT_MAX_PWR_LVL** - - Defines the maximum power domain level that the power management operations - should apply to. More often, but not always, the power domain level - corresponds to affinity level. This macro allows the PSCI implementation - to know the highest power domain level that it should consider for power - management operations in the system that the platform implements. For - example, the Base AEM FVP implements two clusters with a configurable - number of CPUs and it reports the maximum power domain level as 1. - -- **#define : PLAT_MAX_OFF_STATE** - - Defines the local power state corresponding to the deepest power down - possible at every power domain level in the platform. The local power - states for each level may be sparsely allocated between 0 and this value - with 0 being reserved for the RUN state. The PSCI implementation uses this - value to initialize the local power states of the power domain nodes and - to specify the requested power state for a PSCI_CPU_OFF call. - -- **#define : PLAT_MAX_RET_STATE** - - Defines the local power state corresponding to the deepest retention state - possible at every power domain level in the platform. This macro should be - a value less than PLAT_MAX_OFF_STATE and greater than 0. It is used by the - PSCI implementation to distinguish between retention and power down local - power states within PSCI_CPU_SUSPEND call. - -- **#define : PLAT_MAX_PWR_LVL_STATES** - - Defines the maximum number of local power states per power domain level - that the platform supports. The default value of this macro is 2 since - most platforms just support a maximum of two local power states at each - power domain level (power-down and retention). If the platform needs to - account for more local power states, then it must redefine this macro. - - Currently, this macro is used by the Generic PSCI implementation to size - the array used for PSCI_STAT_COUNT/RESIDENCY accounting. - -- **#define : BL1_RO_BASE** - - Defines the base address in secure ROM where BL1 originally lives. Must be - aligned on a page-size boundary. - -- **#define : BL1_RO_LIMIT** - - Defines the maximum address in secure ROM that BL1's actual content (i.e. - excluding any data section allocated at runtime) can occupy. - -- **#define : BL1_RW_BASE** - - Defines the base address in secure RAM where BL1's read-write data will live - at runtime. Must be aligned on a page-size boundary. - -- **#define : BL1_RW_LIMIT** - - Defines the maximum address in secure RAM that BL1's read-write data can - occupy at runtime. - -- **#define : BL2_BASE** - - Defines the base address in secure RAM where BL1 loads the BL2 binary image. - Must be aligned on a page-size boundary. This constant is not applicable - when BL2_IN_XIP_MEM is set to '1'. - -- **#define : BL2_LIMIT** - - Defines the maximum address in secure RAM that the BL2 image can occupy. - This constant is not applicable when BL2_IN_XIP_MEM is set to '1'. - -- **#define : BL2_RO_BASE** - - Defines the base address in secure XIP memory where BL2 RO section originally - lives. Must be aligned on a page-size boundary. This constant is only needed - when BL2_IN_XIP_MEM is set to '1'. - -- **#define : BL2_RO_LIMIT** - - Defines the maximum address in secure XIP memory that BL2's actual content - (i.e. excluding any data section allocated at runtime) can occupy. This - constant is only needed when BL2_IN_XIP_MEM is set to '1'. - -- **#define : BL2_RW_BASE** - - Defines the base address in secure RAM where BL2's read-write data will live - at runtime. Must be aligned on a page-size boundary. This constant is only - needed when BL2_IN_XIP_MEM is set to '1'. - -- **#define : BL2_RW_LIMIT** - - Defines the maximum address in secure RAM that BL2's read-write data can - occupy at runtime. This constant is only needed when BL2_IN_XIP_MEM is set - to '1'. - -- **#define : BL31_BASE** - - Defines the base address in secure RAM where BL2 loads the BL31 binary - image. Must be aligned on a page-size boundary. - -- **#define : BL31_LIMIT** - - Defines the maximum address in secure RAM that the BL31 image can occupy. - -For every image, the platform must define individual identifiers that will be -used by BL1 or BL2 to load the corresponding image into memory from non-volatile -storage. For the sake of performance, integer numbers will be used as -identifiers. The platform will use those identifiers to return the relevant -information about the image to be loaded (file handler, load address, -authentication information, etc.). The following image identifiers are -mandatory: - -- **#define : BL2_IMAGE_ID** - - BL2 image identifier, used by BL1 to load BL2. - -- **#define : BL31_IMAGE_ID** - - BL31 image identifier, used by BL2 to load BL31. - -- **#define : BL33_IMAGE_ID** - - BL33 image identifier, used by BL2 to load BL33. - -If Trusted Board Boot is enabled, the following certificate identifiers must -also be defined: - -- **#define : TRUSTED_BOOT_FW_CERT_ID** - - BL2 content certificate identifier, used by BL1 to load the BL2 content - certificate. - -- **#define : TRUSTED_KEY_CERT_ID** - - Trusted key certificate identifier, used by BL2 to load the trusted key - certificate. - -- **#define : SOC_FW_KEY_CERT_ID** - - BL31 key certificate identifier, used by BL2 to load the BL31 key - certificate. - -- **#define : SOC_FW_CONTENT_CERT_ID** - - BL31 content certificate identifier, used by BL2 to load the BL31 content - certificate. - -- **#define : NON_TRUSTED_FW_KEY_CERT_ID** - - BL33 key certificate identifier, used by BL2 to load the BL33 key - certificate. - -- **#define : NON_TRUSTED_FW_CONTENT_CERT_ID** - - BL33 content certificate identifier, used by BL2 to load the BL33 content - certificate. - -- **#define : FWU_CERT_ID** - - Firmware Update (FWU) certificate identifier, used by NS_BL1U to load the - FWU content certificate. - -- **#define : PLAT_CRYPTOCELL_BASE** - - This defines the base address of Arm® TrustZone® CryptoCell and must be - defined if CryptoCell crypto driver is used for Trusted Board Boot. For - capable Arm platforms, this driver is used if ``ARM_CRYPTOCELL_INTEG`` is - set. - -If the AP Firmware Updater Configuration image, BL2U is used, the following -must also be defined: - -- **#define : BL2U_BASE** - - Defines the base address in secure memory where BL1 copies the BL2U binary - image. Must be aligned on a page-size boundary. - -- **#define : BL2U_LIMIT** - - Defines the maximum address in secure memory that the BL2U image can occupy. - -- **#define : BL2U_IMAGE_ID** - - BL2U image identifier, used by BL1 to fetch an image descriptor - corresponding to BL2U. - -If the SCP Firmware Update Configuration Image, SCP_BL2U is used, the following -must also be defined: - -- **#define : SCP_BL2U_IMAGE_ID** - - SCP_BL2U image identifier, used by BL1 to fetch an image descriptor - corresponding to SCP_BL2U. - NOTE: TF-A does not provide source code for this image. - -If the Non-Secure Firmware Updater ROM, NS_BL1U is used, the following must -also be defined: - -- **#define : NS_BL1U_BASE** - - Defines the base address in non-secure ROM where NS_BL1U executes. - Must be aligned on a page-size boundary. - NOTE: TF-A does not provide source code for this image. - -- **#define : NS_BL1U_IMAGE_ID** - - NS_BL1U image identifier, used by BL1 to fetch an image descriptor - corresponding to NS_BL1U. - -If the Non-Secure Firmware Updater, NS_BL2U is used, the following must also -be defined: - -- **#define : NS_BL2U_BASE** - - Defines the base address in non-secure memory where NS_BL2U executes. - Must be aligned on a page-size boundary. - NOTE: TF-A does not provide source code for this image. - -- **#define : NS_BL2U_IMAGE_ID** - - NS_BL2U image identifier, used by BL1 to fetch an image descriptor - corresponding to NS_BL2U. - -For the the Firmware update capability of TRUSTED BOARD BOOT, the following -macros may also be defined: - -- **#define : PLAT_FWU_MAX_SIMULTANEOUS_IMAGES** - - Total number of images that can be loaded simultaneously. If the platform - doesn't specify any value, it defaults to 10. - -If a SCP_BL2 image is supported by the platform, the following constants must -also be defined: - -- **#define : SCP_BL2_IMAGE_ID** - - SCP_BL2 image identifier, used by BL2 to load SCP_BL2 into secure memory - from platform storage before being transferred to the SCP. - -- **#define : SCP_FW_KEY_CERT_ID** - - SCP_BL2 key certificate identifier, used by BL2 to load the SCP_BL2 key - certificate (mandatory when Trusted Board Boot is enabled). - -- **#define : SCP_FW_CONTENT_CERT_ID** - - SCP_BL2 content certificate identifier, used by BL2 to load the SCP_BL2 - content certificate (mandatory when Trusted Board Boot is enabled). - -If a BL32 image is supported by the platform, the following constants must -also be defined: - -- **#define : BL32_IMAGE_ID** - - BL32 image identifier, used by BL2 to load BL32. - -- **#define : TRUSTED_OS_FW_KEY_CERT_ID** - - BL32 key certificate identifier, used by BL2 to load the BL32 key - certificate (mandatory when Trusted Board Boot is enabled). - -- **#define : TRUSTED_OS_FW_CONTENT_CERT_ID** - - BL32 content certificate identifier, used by BL2 to load the BL32 content - certificate (mandatory when Trusted Board Boot is enabled). - -- **#define : BL32_BASE** - - Defines the base address in secure memory where BL2 loads the BL32 binary - image. Must be aligned on a page-size boundary. - -- **#define : BL32_LIMIT** - - Defines the maximum address that the BL32 image can occupy. - -If the Test Secure-EL1 Payload (TSP) instantiation of BL32 is supported by the -platform, the following constants must also be defined: - -- **#define : TSP_SEC_MEM_BASE** - - Defines the base address of the secure memory used by the TSP image on the - platform. This must be at the same address or below ``BL32_BASE``. - -- **#define : TSP_SEC_MEM_SIZE** - - Defines the size of the secure memory used by the BL32 image on the - platform. ``TSP_SEC_MEM_BASE`` and ``TSP_SEC_MEM_SIZE`` must fully - accommodate the memory required by the BL32 image, defined by ``BL32_BASE`` - and ``BL32_LIMIT``. - -- **#define : TSP_IRQ_SEC_PHY_TIMER** - - Defines the ID of the secure physical generic timer interrupt used by the - TSP's interrupt handling code. - -If the platform port uses the translation table library code, the following -constants must also be defined: - -- **#define : PLAT_XLAT_TABLES_DYNAMIC** - - Optional flag that can be set per-image to enable the dynamic allocation of - regions even when the MMU is enabled. If not defined, only static - functionality will be available, if defined and set to 1 it will also - include the dynamic functionality. - -- **#define : MAX_XLAT_TABLES** - - Defines the maximum number of translation tables that are allocated by the - translation table library code. To minimize the amount of runtime memory - used, choose the smallest value needed to map the required virtual addresses - for each BL stage. If ``PLAT_XLAT_TABLES_DYNAMIC`` flag is enabled for a BL - image, ``MAX_XLAT_TABLES`` must be defined to accommodate the dynamic regions - as well. - -- **#define : MAX_MMAP_REGIONS** - - Defines the maximum number of regions that are allocated by the translation - table library code. A region consists of physical base address, virtual base - address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as - defined in the ``mmap_region_t`` structure. The platform defines the regions - that should be mapped. Then, the translation table library will create the - corresponding tables and descriptors at runtime. To minimize the amount of - runtime memory used, choose the smallest value needed to register the - required regions for each BL stage. If ``PLAT_XLAT_TABLES_DYNAMIC`` flag is - enabled for a BL image, ``MAX_MMAP_REGIONS`` must be defined to accommodate - the dynamic regions as well. - -- **#define : PLAT_VIRT_ADDR_SPACE_SIZE** - - Defines the total size of the virtual address space in bytes. For example, - for a 32 bit virtual address space, this value should be ``(1ULL << 32)``. - -- **#define : PLAT_PHY_ADDR_SPACE_SIZE** - - Defines the total size of the physical address space in bytes. For example, - for a 32 bit physical address space, this value should be ``(1ULL << 32)``. - -If the platform port uses the IO storage framework, the following constants -must also be defined: - -- **#define : MAX_IO_DEVICES** - - Defines the maximum number of registered IO devices. Attempting to register - more devices than this value using ``io_register_device()`` will fail with - -ENOMEM. - -- **#define : MAX_IO_HANDLES** - - Defines the maximum number of open IO handles. Attempting to open more IO - entities than this value using ``io_open()`` will fail with -ENOMEM. - -- **#define : MAX_IO_BLOCK_DEVICES** - - Defines the maximum number of registered IO block devices. Attempting to - register more devices this value using ``io_dev_open()`` will fail - with -ENOMEM. MAX_IO_BLOCK_DEVICES should be less than MAX_IO_DEVICES. - With this macro, multiple block devices could be supported at the same - time. - -If the platform needs to allocate data within the per-cpu data framework in -BL31, it should define the following macro. Currently this is only required if -the platform decides not to use the coherent memory section by undefining the -``USE_COHERENT_MEM`` build flag. In this case, the framework allocates the -required memory within the the per-cpu data to minimize wastage. - -- **#define : PLAT_PCPU_DATA_SIZE** - - Defines the memory (in bytes) to be reserved within the per-cpu data - structure for use by the platform layer. - -The following constants are optional. They should be defined when the platform -memory layout implies some image overlaying like in Arm standard platforms. - -- **#define : BL31_PROGBITS_LIMIT** - - Defines the maximum address in secure RAM that the BL31's progbits sections - can occupy. - -- **#define : TSP_PROGBITS_LIMIT** - - Defines the maximum address that the TSP's progbits sections can occupy. - -If the platform port uses the PL061 GPIO driver, the following constant may -optionally be defined: - -- **PLAT_PL061_MAX_GPIOS** - Maximum number of GPIOs required by the platform. This allows control how - much memory is allocated for PL061 GPIO controllers. The default value is - - #. $(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) - -If the platform port uses the partition driver, the following constant may -optionally be defined: - -- **PLAT_PARTITION_MAX_ENTRIES** - Maximum number of partition entries required by the platform. This allows - control how much memory is allocated for partition entries. The default - value is 128. - `For example, define the build flag in platform.mk`_: - PLAT_PARTITION_MAX_ENTRIES := 12 - $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) - -The following constant is optional. It should be defined to override the default -behaviour of the ``assert()`` function (for example, to save memory). - -- **PLAT_LOG_LEVEL_ASSERT** - If ``PLAT_LOG_LEVEL_ASSERT`` is higher or equal than ``LOG_LEVEL_VERBOSE``, - ``assert()`` prints the name of the file, the line number and the asserted - expression. Else if it is higher than ``LOG_LEVEL_INFO``, it prints the file - name and the line number. Else if it is lower than ``LOG_LEVEL_INFO``, it - doesn't print anything to the console. If ``PLAT_LOG_LEVEL_ASSERT`` isn't - defined, it defaults to ``LOG_LEVEL``. - -If the platform port uses the Activity Monitor Unit, the following constants -may be defined: - -- **PLAT_AMU_GROUP1_COUNTERS_MASK** - This mask reflects the set of group counters that should be enabled. The - maximum number of group 1 counters supported by AMUv1 is 16 so the mask - can be at most 0xffff. If the platform does not define this mask, no group 1 - counters are enabled. If the platform defines this mask, the following - constant needs to also be defined. - -- **PLAT_AMU_GROUP1_NR_COUNTERS** - This value is used to allocate an array to save and restore the counters - specified by ``PLAT_AMU_GROUP1_COUNTERS_MASK`` on CPU suspend. - This value should be equal to the highest bit position set in the - mask, plus 1. The maximum number of group 1 counters in AMUv1 is 16. - -File : plat_macros.S [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Each platform must ensure a file of this name is in the system include path with -the following macro defined. In the Arm development platforms, this file is -found in ``plat/arm/board//include/plat_macros.S``. - -- **Macro : plat_crash_print_regs** - - This macro allows the crash reporting routine to print relevant platform - registers in case of an unhandled exception in BL31. This aids in debugging - and this macro can be defined to be empty in case register reporting is not - desired. - - For instance, GIC or interconnect registers may be helpful for - troubleshooting. - -Handling Reset --------------- - -BL1 by default implements the reset vector where execution starts from a cold -or warm boot. BL31 can be optionally set as a reset vector using the -``RESET_TO_BL31`` make variable. - -For each CPU, the reset vector code is responsible for the following tasks: - -#. Distinguishing between a cold boot and a warm boot. - -#. In the case of a cold boot and the CPU being a secondary CPU, ensuring that - the CPU is placed in a platform-specific state until the primary CPU - performs the necessary steps to remove it from this state. - -#. In the case of a warm boot, ensuring that the CPU jumps to a platform- - specific address in the BL31 image in the same processor mode as it was - when released from reset. - -The following functions need to be implemented by the platform port to enable -reset vector code to perform the above tasks. - -Function : plat_get_my_entrypoint() [mandatory when PROGRAMMABLE_RESET_ADDRESS == 0] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : uintptr_t - -This function is called with the MMU and caches disabled -(``SCTLR_EL3.M`` = 0 and ``SCTLR_EL3.C`` = 0). The function is responsible for -distinguishing between a warm and cold reset for the current CPU using -platform-specific means. If it's a warm reset, then it returns the warm -reset entrypoint point provided to ``plat_setup_psci_ops()`` during -BL31 initialization. If it's a cold reset then this function must return zero. - -This function does not follow the Procedure Call Standard used by the -Application Binary Interface for the Arm 64-bit architecture. The caller should -not assume that callee saved registers are preserved across a call to this -function. - -This function fulfills requirement 1 and 3 listed above. - -Note that for platforms that support programming the reset address, it is -expected that a CPU will start executing code directly at the right address, -both on a cold and warm reset. In this case, there is no need to identify the -type of reset nor to query the warm reset entrypoint. Therefore, implementing -this function is not required on such platforms. - -Function : plat_secondary_cold_boot_setup() [mandatory when COLD_BOOT_SINGLE_CPU == 0] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - -This function is called with the MMU and data caches disabled. It is responsible -for placing the executing secondary CPU in a platform-specific state until the -primary CPU performs the necessary actions to bring it out of that state and -allow entry into the OS. This function must not return. - -In the Arm FVP port, when using the normal boot flow, each secondary CPU powers -itself off. The primary CPU is responsible for powering up the secondary CPUs -when normal world software requires them. When booting an EL3 payload instead, -they stay powered on and are put in a holding pen until their mailbox gets -populated. - -This function fulfills requirement 2 above. - -Note that for platforms that can't release secondary CPUs out of reset, only the -primary CPU will execute the cold boot code. Therefore, implementing this -function is not required on such platforms. - -Function : plat_is_my_cpu_primary() [mandatory when COLD_BOOT_SINGLE_CPU == 0] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : unsigned int - -This function identifies whether the current CPU is the primary CPU or a -secondary CPU. A return value of zero indicates that the CPU is not the -primary CPU, while a non-zero return value indicates that the CPU is the -primary CPU. - -Note that for platforms that can't release secondary CPUs out of reset, only the -primary CPU will execute the cold boot code. Therefore, there is no need to -distinguish between primary and secondary CPUs and implementing this function is -not required. - -Function : platform_mem_init() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function is called before any access to data is made by the firmware, in -order to carry out any essential memory initialization. - -Function: plat_get_rotpk_info() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void *, void **, unsigned int *, unsigned int * - Return : int - -This function is mandatory when Trusted Board Boot is enabled. It returns a -pointer to the ROTPK stored in the platform (or a hash of it) and its length. -The ROTPK must be encoded in DER format according to the following ASN.1 -structure: - -:: - - AlgorithmIdentifier ::= SEQUENCE { - algorithm OBJECT IDENTIFIER, - parameters ANY DEFINED BY algorithm OPTIONAL - } - - SubjectPublicKeyInfo ::= SEQUENCE { - algorithm AlgorithmIdentifier, - subjectPublicKey BIT STRING - } - -In case the function returns a hash of the key: - -:: - - DigestInfo ::= SEQUENCE { - digestAlgorithm AlgorithmIdentifier, - digest OCTET STRING - } - -The function returns 0 on success. Any other value is treated as error by the -Trusted Board Boot. The function also reports extra information related -to the ROTPK in the flags parameter: - -:: - - ROTPK_IS_HASH : Indicates that the ROTPK returned by the platform is a - hash. - ROTPK_NOT_DEPLOYED : This allows the platform to skip certificate ROTPK - verification while the platform ROTPK is not deployed. - When this flag is set, the function does not need to - return a platform ROTPK, and the authentication - framework uses the ROTPK in the certificate without - verifying it against the platform value. This flag - must not be used in a deployed production environment. - -Function: plat_get_nv_ctr() -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void *, unsigned int * - Return : int - -This function is mandatory when Trusted Board Boot is enabled. It returns the -non-volatile counter value stored in the platform in the second argument. The -cookie in the first argument may be used to select the counter in case the -platform provides more than one (for example, on platforms that use the default -TBBR CoT, the cookie will correspond to the OID values defined in -TRUSTED_FW_NVCOUNTER_OID or NON_TRUSTED_FW_NVCOUNTER_OID). - -The function returns 0 on success. Any other value means the counter value could -not be retrieved from the platform. - -Function: plat_set_nv_ctr() -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void *, unsigned int - Return : int - -This function is mandatory when Trusted Board Boot is enabled. It sets a new -counter value in the platform. The cookie in the first argument may be used to -select the counter (as explained in plat_get_nv_ctr()). The second argument is -the updated counter value to be written to the NV counter. - -The function returns 0 on success. Any other value means the counter value could -not be updated. - -Function: plat_set_nv_ctr2() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void *, const auth_img_desc_t *, unsigned int - Return : int - -This function is optional when Trusted Board Boot is enabled. If this -interface is defined, then ``plat_set_nv_ctr()`` need not be defined. The -first argument passed is a cookie and is typically used to -differentiate between a Non Trusted NV Counter and a Trusted NV -Counter. The second argument is a pointer to an authentication image -descriptor and may be used to decide if the counter is allowed to be -updated or not. The third argument is the updated counter value to -be written to the NV counter. - -The function returns 0 on success. Any other value means the counter value -either could not be updated or the authentication image descriptor indicates -that it is not allowed to be updated. - -Common mandatory function modifications ---------------------------------------- - -The following functions are mandatory functions which need to be implemented -by the platform port. - -Function : plat_my_core_pos() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : unsigned int - -This function returns the index of the calling CPU which is used as a -CPU-specific linear index into blocks of memory (for example while allocating -per-CPU stacks). This function will be invoked very early in the -initialization sequence which mandates that this function should be -implemented in assembly and should not rely on the availability of a C -runtime environment. This function can clobber x0 - x8 and must preserve -x9 - x29. - -This function plays a crucial role in the power domain topology framework in -PSCI and details of this can be found in `Power Domain Topology Design`_. - -Function : plat_core_pos_by_mpidr() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : u_register_t - Return : int - -This function validates the ``MPIDR`` of a CPU and converts it to an index, -which can be used as a CPU-specific linear index into blocks of memory. In -case the ``MPIDR`` is invalid, this function returns -1. This function will only -be invoked by BL31 after the power domain topology is initialized and can -utilize the C runtime environment. For further details about how TF-A -represents the power domain topology and how this relates to the linear CPU -index, please refer `Power Domain Topology Design`_. - -Function : plat_get_mbedtls_heap() [when TRUSTED_BOARD_BOOT == 1] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Arguments : void **heap_addr, size_t *heap_size - Return : int - -This function is invoked during Mbed TLS library initialisation to get a heap, -by means of a starting address and a size. This heap will then be used -internally by the Mbed TLS library. Hence, each BL stage that utilises Mbed TLS -must be able to provide a heap to it. - -A helper function can be found in `drivers/auth/mbedtls/mbedtls_common.c` in -which a heap is statically reserved during compile time inside every image -(i.e. every BL stage) that utilises Mbed TLS. In this default implementation, -the function simply returns the address and size of this "pre-allocated" heap. -For a platform to use this default implementation, only a call to the helper -from inside plat_get_mbedtls_heap() body is enough and nothing else is needed. - -However, by writting their own implementation, platforms have the potential to -optimise memory usage. For example, on some Arm platforms, the Mbed TLS heap is -shared between BL1 and BL2 stages and, thus, the necessary space is not reserved -twice. - -On success the function should return 0 and a negative error code otherwise. - -Common optional modifications ------------------------------ - -The following are helper functions implemented by the firmware that perform -common platform-specific tasks. A platform may choose to override these -definitions. - -Function : plat_set_my_stack() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function sets the current stack pointer to the normal memory stack that -has been allocated for the current CPU. For BL images that only require a -stack for the primary CPU, the UP version of the function is used. The size -of the stack allocated to each CPU is specified by the platform defined -constant ``PLATFORM_STACK_SIZE``. - -Common implementations of this function for the UP and MP BL images are -provided in `plat/common/aarch64/platform_up_stack.S`_ and -`plat/common/aarch64/platform_mp_stack.S`_ - -Function : plat_get_my_stack() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : uintptr_t - -This function returns the base address of the normal memory stack that -has been allocated for the current CPU. For BL images that only require a -stack for the primary CPU, the UP version of the function is used. The size -of the stack allocated to each CPU is specified by the platform defined -constant ``PLATFORM_STACK_SIZE``. - -Common implementations of this function for the UP and MP BL images are -provided in `plat/common/aarch64/platform_up_stack.S`_ and -`plat/common/aarch64/platform_mp_stack.S`_ - -Function : plat_report_exception() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : void - -A platform may need to report various information about its status when an -exception is taken, for example the current exception level, the CPU security -state (secure/non-secure), the exception type, and so on. This function is -called in the following circumstances: - -- In BL1, whenever an exception is taken. -- In BL2, whenever an exception is taken. - -The default implementation doesn't do anything, to avoid making assumptions -about the way the platform displays its status information. - -For AArch64, this function receives the exception type as its argument. -Possible values for exceptions types are listed in the -`include/common/bl_common.h`_ header file. Note that these constants are not -related to any architectural exception code; they are just a TF-A convention. - -For AArch32, this function receives the exception mode as its argument. -Possible values for exception modes are listed in the -`include/lib/aarch32/arch.h`_ header file. - -Function : plat_reset_handler() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -A platform may need to do additional initialization after reset. This function -allows the platform to do the platform specific intializations. Platform -specific errata workarounds could also be implemented here. The API should -preserve the values of callee saved registers x19 to x29. - -The default implementation doesn't do anything. If a platform needs to override -the default implementation, refer to the `Firmware Design`_ for general -guidelines. - -Function : plat_disable_acp() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This API allows a platform to disable the Accelerator Coherency Port (if -present) during a cluster power down sequence. The default weak implementation -doesn't do anything. Since this API is called during the power down sequence, -it has restrictions for stack usage and it can use the registers x0 - x17 as -scratch registers. It should preserve the value in x18 register as it is used -by the caller to store the return address. - -Function : plat_error_handler() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : int - Return : void - -This API is called when the generic code encounters an error situation from -which it cannot continue. It allows the platform to perform error reporting or -recovery actions (for example, reset the system). This function must not return. - -The parameter indicates the type of error using standard codes from ``errno.h``. -Possible errors reported by the generic code are: - -- ``-EAUTH``: a certificate or image could not be authenticated (when Trusted - Board Boot is enabled) -- ``-ENOENT``: the requested image or certificate could not be found or an IO - error was detected -- ``-ENOMEM``: resources exhausted. TF-A does not use dynamic memory, so this - error is usually an indication of an incorrect array size - -The default implementation simply spins. - -Function : plat_panic_handler() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This API is called when the generic code encounters an unexpected error -situation from which it cannot recover. This function must not return, -and must be implemented in assembly because it may be called before the C -environment is initialized. - -Note: The address from where it was called is stored in x30 (Link Register). -The default implementation simply spins. - -Function : plat_get_bl_image_load_info() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : bl_load_info_t * - -This function returns pointer to the list of images that the platform has -populated to load. This function is invoked in BL2 to load the -BL3xx images. - -Function : plat_get_next_bl_params() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : bl_params_t * - -This function returns a pointer to the shared memory that the platform has -kept aside to pass TF-A related information that next BL image needs. This -function is invoked in BL2 to pass this information to the next BL -image. - -Function : plat_get_stack_protector_canary() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : u_register_t - -This function returns a random value that is used to initialize the canary used -when the stack protector is enabled with ENABLE_STACK_PROTECTOR. A predictable -value will weaken the protection as the attacker could easily write the right -value as part of the attack most of the time. Therefore, it should return a -true random number. - -Note: For the protection to be effective, the global data need to be placed at -a lower address than the stack bases. Failure to do so would allow an attacker -to overwrite the canary as part of the stack buffer overflow attack. - -Function : plat_flush_next_bl_params() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function flushes to main memory all the image params that are passed to -next image. This function is invoked in BL2 to flush this information -to the next BL image. - -Function : plat_log_get_prefix() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : const char * - -This function defines the prefix string corresponding to the `log_level` to be -prepended to all the log output from TF-A. The `log_level` (argument) will -correspond to one of the standard log levels defined in debug.h. The platform -can override the common implementation to define a different prefix string for -the log output. The implementation should be robust to future changes that -increase the number of log levels. - -Modifications specific to a Boot Loader stage ---------------------------------------------- - -Boot Loader Stage 1 (BL1) -------------------------- - -BL1 implements the reset vector where execution starts from after a cold or -warm boot. For each CPU, BL1 is responsible for the following tasks: - -#. Handling the reset as described in section 2.2 - -#. In the case of a cold boot and the CPU being the primary CPU, ensuring that - only this CPU executes the remaining BL1 code, including loading and passing - control to the BL2 stage. - -#. Identifying and starting the Firmware Update process (if required). - -#. Loading the BL2 image from non-volatile storage into secure memory at the - address specified by the platform defined constant ``BL2_BASE``. - -#. Populating a ``meminfo`` structure with the following information in memory, - accessible by BL2 immediately upon entry. - - :: - - meminfo.total_base = Base address of secure RAM visible to BL2 - meminfo.total_size = Size of secure RAM visible to BL2 - - By default, BL1 places this ``meminfo`` structure at the end of secure - memory visible to BL2. - - It is possible for the platform to decide where it wants to place the - ``meminfo`` structure for BL2 or restrict the amount of memory visible to - BL2 by overriding the weak default implementation of - ``bl1_plat_handle_post_image_load`` API. - -The following functions need to be implemented by the platform port to enable -BL1 to perform the above tasks. - -Function : bl1_early_platform_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function executes with the MMU and data caches disabled. It is only called -by the primary CPU. - -On Arm standard platforms, this function: - -- Enables a secure instance of SP805 to act as the Trusted Watchdog. - -- Initializes a UART (PL011 console), which enables access to the ``printf`` - family of functions in BL1. - -- Enables issuing of snoop and DVM (Distributed Virtual Memory) requests to - the CCI slave interface corresponding to the cluster that includes the - primary CPU. - -Function : bl1_plat_arch_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function performs any platform-specific and architectural setup that the -platform requires. Platform-specific setup might include configuration of -memory controllers and the interconnect. - -In Arm standard platforms, this function enables the MMU. - -This function helps fulfill requirement 2 above. - -Function : bl1_platform_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function executes with the MMU and data caches enabled. It is responsible -for performing any remaining platform-specific setup that can occur after the -MMU and data cache have been enabled. - -if support for multiple boot sources is required, it initializes the boot -sequence used by plat_try_next_boot_source(). - -In Arm standard platforms, this function initializes the storage abstraction -layer used to load the next bootloader image. - -This function helps fulfill requirement 4 above. - -Function : bl1_plat_sec_mem_layout() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : meminfo * - -This function should only be called on the cold boot path. It executes with the -MMU and data caches enabled. The pointer returned by this function must point to -a ``meminfo`` structure containing the extents and availability of secure RAM for -the BL1 stage. - -:: - - meminfo.total_base = Base address of secure RAM visible to BL1 - meminfo.total_size = Size of secure RAM visible to BL1 - -This information is used by BL1 to load the BL2 image in secure RAM. BL1 also -populates a similar structure to tell BL2 the extents of memory available for -its own use. - -This function helps fulfill requirements 4 and 5 above. - -Function : bl1_plat_prepare_exit() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : entry_point_info_t * - Return : void - -This function is called prior to exiting BL1 in response to the -``BL1_SMC_RUN_IMAGE`` SMC request raised by BL2. It should be used to perform -platform specific clean up or bookkeeping operations before transferring -control to the next image. It receives the address of the ``entry_point_info_t`` -structure passed from BL2. This function runs with MMU disabled. - -Function : bl1_plat_set_ep_info() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int image_id, entry_point_info_t *ep_info - Return : void - -This function allows platforms to override ``ep_info`` for the given ``image_id``. - -The default implementation just returns. - -Function : bl1_plat_get_next_image_id() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : unsigned int - -This and the following function must be overridden to enable the FWU feature. - -BL1 calls this function after platform setup to identify the next image to be -loaded and executed. If the platform returns ``BL2_IMAGE_ID`` then BL1 proceeds -with the normal boot sequence, which loads and executes BL2. If the platform -returns a different image id, BL1 assumes that Firmware Update is required. - -The default implementation always returns ``BL2_IMAGE_ID``. The Arm development -platforms override this function to detect if firmware update is required, and -if so, return the first image in the firmware update process. - -Function : bl1_plat_get_image_desc() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int image_id - Return : image_desc_t * - -BL1 calls this function to get the image descriptor information ``image_desc_t`` -for the provided ``image_id`` from the platform. - -The default implementation always returns a common BL2 image descriptor. Arm -standard platforms return an image descriptor corresponding to BL2 or one of -the firmware update images defined in the Trusted Board Boot Requirements -specification. - -Function : bl1_plat_handle_pre_image_load() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int image_id - Return : int - -This function can be used by the platforms to update/use image information -corresponding to ``image_id``. This function is invoked in BL1, both in cold -boot and FWU code path, before loading the image. - -Function : bl1_plat_handle_post_image_load() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int image_id - Return : int - -This function can be used by the platforms to update/use image information -corresponding to ``image_id``. This function is invoked in BL1, both in cold -boot and FWU code path, after loading and authenticating the image. - -The default weak implementation of this function calculates the amount of -Trusted SRAM that can be used by BL2 and allocates a ``meminfo_t`` -structure at the beginning of this free memory and populates it. The address -of ``meminfo_t`` structure is updated in ``arg1`` of the entrypoint -information to BL2. - -Function : bl1_plat_fwu_done() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int image_id, uintptr_t image_src, - unsigned int image_size - Return : void - -BL1 calls this function when the FWU process is complete. It must not return. -The platform may override this function to take platform specific action, for -example to initiate the normal boot flow. - -The default implementation spins forever. - -Function : bl1_plat_mem_check() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : uintptr_t mem_base, unsigned int mem_size, - unsigned int flags - Return : int - -BL1 calls this function while handling FWU related SMCs, more specifically when -copying or authenticating an image. Its responsibility is to ensure that the -region of memory identified by ``mem_base`` and ``mem_size`` is mapped in BL1, and -that this memory corresponds to either a secure or non-secure memory region as -indicated by the security state of the ``flags`` argument. - -This function can safely assume that the value resulting from the addition of -``mem_base`` and ``mem_size`` fits into a ``uintptr_t`` type variable and does not -overflow. - -This function must return 0 on success, a non-null error code otherwise. - -The default implementation of this function asserts therefore platforms must -override it when using the FWU feature. - -Boot Loader Stage 2 (BL2) -------------------------- - -The BL2 stage is executed only by the primary CPU, which is determined in BL1 -using the ``platform_is_primary_cpu()`` function. BL1 passed control to BL2 at -``BL2_BASE``. BL2 executes in Secure EL1 and and invokes -``plat_get_bl_image_load_info()`` to retrieve the list of images to load from -non-volatile storage to secure/non-secure RAM. After all the images are loaded -then BL2 invokes ``plat_get_next_bl_params()`` to get the list of executable -images to be passed to the next BL image. - -The following functions must be implemented by the platform port to enable BL2 -to perform the above tasks. - -Function : bl2_early_platform_setup2() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : u_register_t, u_register_t, u_register_t, u_register_t - Return : void - -This function executes with the MMU and data caches disabled. It is only called -by the primary CPU. The 4 arguments are passed by BL1 to BL2 and these arguments -are platform specific. - -On Arm standard platforms, the arguments received are : - - arg0 - Points to load address of HW_CONFIG if present - - arg1 - ``meminfo`` structure populated by BL1. The platform copies - the contents of ``meminfo`` as it may be subsequently overwritten by BL2. - -On Arm standard platforms, this function also: - -- Initializes a UART (PL011 console), which enables access to the ``printf`` - family of functions in BL2. - -- Initializes the storage abstraction layer used to load further bootloader - images. It is necessary to do this early on platforms with a SCP_BL2 image, - since the later ``bl2_platform_setup`` must be done after SCP_BL2 is loaded. - -Function : bl2_plat_arch_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function executes with the MMU and data caches disabled. It is only called -by the primary CPU. - -The purpose of this function is to perform any architectural initialization -that varies across platforms. - -On Arm standard platforms, this function enables the MMU. - -Function : bl2_platform_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function may execute with the MMU and data caches enabled if the platform -port does the necessary initialization in ``bl2_plat_arch_setup()``. It is only -called by the primary CPU. - -The purpose of this function is to perform any platform initialization -specific to BL2. - -In Arm standard platforms, this function performs security setup, including -configuration of the TrustZone controller to allow non-secure masters access -to most of DRAM. Part of DRAM is reserved for secure world use. - -Function : bl2_plat_handle_pre_image_load() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : int - -This function can be used by the platforms to update/use image information -for given ``image_id``. This function is currently invoked in BL2 before -loading each image. - -Function : bl2_plat_handle_post_image_load() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int - Return : int - -This function can be used by the platforms to update/use image information -for given ``image_id``. This function is currently invoked in BL2 after -loading each image. - -Function : bl2_plat_preload_setup [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This optional function performs any BL2 platform initialization -required before image loading, that is not done later in -bl2_platform_setup(). Specifically, if support for multiple -boot sources is required, it initializes the boot sequence used by -plat_try_next_boot_source(). - -Function : plat_try_next_boot_source() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : int - -This optional function passes to the next boot source in the redundancy -sequence. - -This function moves the current boot redundancy source to the next -element in the boot sequence. If there are no more boot sources then it -must return 0, otherwise it must return 1. The default implementation -of this always returns 0. - -Boot Loader Stage 2 (BL2) at EL3 --------------------------------- - -When the platform has a non-TF-A Boot ROM it is desirable to jump -directly to BL2 instead of TF-A BL1. In this case BL2 is expected to -execute at EL3 instead of executing at EL1. Refer to the `Firmware -Design`_ for more information. - -All mandatory functions of BL2 must be implemented, except the functions -bl2_early_platform_setup and bl2_el3_plat_arch_setup, because -their work is done now by bl2_el3_early_platform_setup and -bl2_el3_plat_arch_setup. These functions should generally implement -the bl1_plat_xxx() and bl2_plat_xxx() functionality combined. - - -Function : bl2_el3_early_platform_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : u_register_t, u_register_t, u_register_t, u_register_t - Return : void - -This function executes with the MMU and data caches disabled. It is only called -by the primary CPU. This function receives four parameters which can be used -by the platform to pass any needed information from the Boot ROM to BL2. - -On Arm standard platforms, this function does the following: - -- Initializes a UART (PL011 console), which enables access to the ``printf`` - family of functions in BL2. - -- Initializes the storage abstraction layer used to load further bootloader - images. It is necessary to do this early on platforms with a SCP_BL2 image, - since the later ``bl2_platform_setup`` must be done after SCP_BL2 is loaded. - -- Initializes the private variables that define the memory layout used. - -Function : bl2_el3_plat_arch_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function executes with the MMU and data caches disabled. It is only called -by the primary CPU. - -The purpose of this function is to perform any architectural initialization -that varies across platforms. - -On Arm standard platforms, this function enables the MMU. - -Function : bl2_el3_plat_prepare_exit() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function is called prior to exiting BL2 and run the next image. -It should be used to perform platform specific clean up or bookkeeping -operations before transferring control to the next image. This function -runs with MMU disabled. - -FWU Boot Loader Stage 2 (BL2U) ------------------------------- - -The AP Firmware Updater Configuration, BL2U, is an optional part of the FWU -process and is executed only by the primary CPU. BL1 passes control to BL2U at -``BL2U_BASE``. BL2U executes in Secure-EL1 and is responsible for: - -#. (Optional) Transferring the optional SCP_BL2U binary image from AP secure - memory to SCP RAM. BL2U uses the SCP_BL2U ``image_info`` passed by BL1. - ``SCP_BL2U_BASE`` defines the address in AP secure memory where SCP_BL2U - should be copied from. Subsequent handling of the SCP_BL2U image is - implemented by the platform specific ``bl2u_plat_handle_scp_bl2u()`` function. - If ``SCP_BL2U_BASE`` is not defined then this step is not performed. - -#. Any platform specific setup required to perform the FWU process. For - example, Arm standard platforms initialize the TZC controller so that the - normal world can access DDR memory. - -The following functions must be implemented by the platform port to enable -BL2U to perform the tasks mentioned above. - -Function : bl2u_early_platform_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : meminfo *mem_info, void *plat_info - Return : void - -This function executes with the MMU and data caches disabled. It is only -called by the primary CPU. The arguments to this function is the address -of the ``meminfo`` structure and platform specific info provided by BL1. - -The platform may copy the contents of the ``mem_info`` and ``plat_info`` into -private storage as the original memory may be subsequently overwritten by BL2U. - -On Arm CSS platforms ``plat_info`` is interpreted as an ``image_info_t`` structure, -to extract SCP_BL2U image information, which is then copied into a private -variable. - -Function : bl2u_plat_arch_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function executes with the MMU and data caches disabled. It is only -called by the primary CPU. - -The purpose of this function is to perform any architectural initialization -that varies across platforms, for example enabling the MMU (since the memory -map differs across platforms). - -Function : bl2u_platform_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function may execute with the MMU and data caches enabled if the platform -port does the necessary initialization in ``bl2u_plat_arch_setup()``. It is only -called by the primary CPU. - -The purpose of this function is to perform any platform initialization -specific to BL2U. - -In Arm standard platforms, this function performs security setup, including -configuration of the TrustZone controller to allow non-secure masters access -to most of DRAM. Part of DRAM is reserved for secure world use. - -Function : bl2u_plat_handle_scp_bl2u() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : int - -This function is used to perform any platform-specific actions required to -handle the SCP firmware. Typically it transfers the image into SCP memory using -a platform-specific protocol and waits until SCP executes it and signals to the -Application Processor (AP) for BL2U execution to continue. - -This function returns 0 on success, a negative error code otherwise. -This function is included if SCP_BL2U_BASE is defined. - -Boot Loader Stage 3-1 (BL31) ----------------------------- - -During cold boot, the BL31 stage is executed only by the primary CPU. This is -determined in BL1 using the ``platform_is_primary_cpu()`` function. BL1 passes -control to BL31 at ``BL31_BASE``. During warm boot, BL31 is executed by all -CPUs. BL31 executes at EL3 and is responsible for: - -#. Re-initializing all architectural and platform state. Although BL1 performs - some of this initialization, BL31 remains resident in EL3 and must ensure - that EL3 architectural and platform state is completely initialized. It - should make no assumptions about the system state when it receives control. - -#. Passing control to a normal world BL image, pre-loaded at a platform- - specific address by BL2. On ARM platforms, BL31 uses the ``bl_params`` list - populated by BL2 in memory to do this. - -#. Providing runtime firmware services. Currently, BL31 only implements a - subset of the Power State Coordination Interface (PSCI) API as a runtime - service. See Section 3.3 below for details of porting the PSCI - implementation. - -#. Optionally passing control to the BL32 image, pre-loaded at a platform- - specific address by BL2. BL31 exports a set of APIs that allow runtime - services to specify the security state in which the next image should be - executed and run the corresponding image. On ARM platforms, BL31 uses the - ``bl_params`` list populated by BL2 in memory to do this. - -If BL31 is a reset vector, It also needs to handle the reset as specified in -section 2.2 before the tasks described above. - -The following functions must be implemented by the platform port to enable BL31 -to perform the above tasks. - -Function : bl31_early_platform_setup2() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : u_register_t, u_register_t, u_register_t, u_register_t - Return : void - -This function executes with the MMU and data caches disabled. It is only called -by the primary CPU. BL2 can pass 4 arguments to BL31 and these arguments are -platform specific. - -In Arm standard platforms, the arguments received are : - - arg0 - The pointer to the head of `bl_params_t` list - which is list of executable images following BL31, - - arg1 - Points to load address of SOC_FW_CONFIG if present - - arg2 - Points to load address of HW_CONFIG if present - - arg3 - A special value to verify platform parameters from BL2 to BL31. Not - used in release builds. - -The function runs through the `bl_param_t` list and extracts the entry point -information for BL32 and BL33. It also performs the following: - -- Initialize a UART (PL011 console), which enables access to the ``printf`` - family of functions in BL31. - -- Enable issuing of snoop and DVM (Distributed Virtual Memory) requests to the - CCI slave interface corresponding to the cluster that includes the primary - CPU. - -Function : bl31_plat_arch_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function executes with the MMU and data caches disabled. It is only called -by the primary CPU. - -The purpose of this function is to perform any architectural initialization -that varies across platforms. - -On Arm standard platforms, this function enables the MMU. - -Function : bl31_platform_setup() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function may execute with the MMU and data caches enabled if the platform -port does the necessary initialization in ``bl31_plat_arch_setup()``. It is only -called by the primary CPU. - -The purpose of this function is to complete platform initialization so that both -BL31 runtime services and normal world software can function correctly. - -On Arm standard platforms, this function does the following: - -- Initialize the generic interrupt controller. - - Depending on the GIC driver selected by the platform, the appropriate GICv2 - or GICv3 initialization will be done, which mainly consists of: - - - Enable secure interrupts in the GIC CPU interface. - - Disable the legacy interrupt bypass mechanism. - - Configure the priority mask register to allow interrupts of all priorities - to be signaled to the CPU interface. - - Mark SGIs 8-15 and the other secure interrupts on the platform as secure. - - Target all secure SPIs to CPU0. - - Enable these secure interrupts in the GIC distributor. - - Configure all other interrupts as non-secure. - - Enable signaling of secure interrupts in the GIC distributor. - -- Enable system-level implementation of the generic timer counter through the - memory mapped interface. - -- Grant access to the system counter timer module - -- Initialize the power controller device. - - In particular, initialise the locks that prevent concurrent accesses to the - power controller device. - -Function : bl31_plat_runtime_setup() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -The purpose of this function is allow the platform to perform any BL31 runtime -setup just prior to BL31 exit during cold boot. The default weak -implementation of this function will invoke ``console_switch_state()`` to switch -console output to consoles marked for use in the ``runtime`` state. - -Function : bl31_plat_get_next_image_ep_info() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : uint32_t - Return : entry_point_info * - -This function may execute with the MMU and data caches enabled if the platform -port does the necessary initializations in ``bl31_plat_arch_setup()``. - -This function is called by ``bl31_main()`` to retrieve information provided by -BL2 for the next image in the security state specified by the argument. BL31 -uses this information to pass control to that image in the specified security -state. This function must return a pointer to the ``entry_point_info`` structure -(that was copied during ``bl31_early_platform_setup()``) if the image exists. It -should return NULL otherwise. - -Function : bl31_plat_enable_mmu [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : uint32_t - Return : void - -This function enables the MMU. The boot code calls this function with MMU and -caches disabled. This function should program necessary registers to enable -translation, and upon return, the MMU on the calling PE must be enabled. - -The function must honor flags passed in the first argument. These flags are -defined by the translation library, and can be found in the file -``include/lib/xlat_tables/xlat_mmu_helpers.h``. - -On DynamIQ systems, this function must not use stack while enabling MMU, which -is how the function in xlat table library version 2 is implemented. - -Function : plat_init_apiakey [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : uint64_t * - -This function populates the ``plat_apiakey`` array that contains the values used -to set the ``APIAKey{Hi,Lo}_EL1`` registers. It returns a pointer to this array. - -The value should be obtained from a reliable source of randomness. - -This function is only needed if ARMv8.3 pointer authentication is used in the -Trusted Firmware by building with ``ENABLE_PAUTH=1``. - -Function : plat_get_syscnt_freq2() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : unsigned int - -This function is used by the architecture setup code to retrieve the counter -frequency for the CPU's generic timer. This value will be programmed into the -``CNTFRQ_EL0`` register. In Arm standard platforms, it returns the base frequency -of the system counter, which is retrieved from the first entry in the frequency -modes table. - -#define : PLAT_PERCPU_BAKERY_LOCK_SIZE [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When ``USE_COHERENT_MEM = 0``, this constant defines the total memory (in -bytes) aligned to the cache line boundary that should be allocated per-cpu to -accommodate all the bakery locks. - -If this constant is not defined when ``USE_COHERENT_MEM = 0``, the linker -calculates the size of the ``bakery_lock`` input section, aligns it to the -nearest ``CACHE_WRITEBACK_GRANULE``, multiplies it with ``PLATFORM_CORE_COUNT`` -and stores the result in a linker symbol. This constant prevents a platform -from relying on the linker and provide a more efficient mechanism for -accessing per-cpu bakery lock information. - -If this constant is defined and its value is not equal to the value -calculated by the linker then a link time assertion is raised. A compile time -assertion is raised if the value of the constant is not aligned to the cache -line boundary. - -SDEI porting requirements -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The SDEI dispatcher requires the platform to provide the following macros -and functions, of which some are optional, and some others mandatory. - -Macros -...... - -Macro: PLAT_SDEI_NORMAL_PRI [mandatory] -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This macro must be defined to the EL3 exception priority level associated with -Normal SDEI events on the platform. This must have a higher value (therefore of -lower priority) than ``PLAT_SDEI_CRITICAL_PRI``. - -Macro: PLAT_SDEI_CRITICAL_PRI [mandatory] -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This macro must be defined to the EL3 exception priority level associated with -Critical SDEI events on the platform. This must have a lower value (therefore of -higher priority) than ``PLAT_SDEI_NORMAL_PRI``. - -**Note**: SDEI exception priorities must be the lowest among Secure priorities. -Among the SDEI exceptions, Critical SDEI priority must be higher than Normal -SDEI priority. - -Functions -......... - -Function: int plat_sdei_validate_entry_point(uintptr_t ep) [optional] -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -:: - - Argument: uintptr_t - Return: int - -This function validates the address of client entry points provided for both -event registration and *Complete and Resume* SDEI calls. The function takes one -argument, which is the address of the handler the SDEI client requested to -register. The function must return ``0`` for successful validation, or ``-1`` -upon failure. - -The default implementation always returns ``0``. On Arm platforms, this function -is implemented to translate the entry point to physical address, and further to -ensure that the address is located in Non-secure DRAM. - -Function: void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr) [optional] -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -:: - - Argument: uint64_t - Argument: unsigned int - Return: void - -SDEI specification requires that a PE comes out of reset with the events masked. -The client therefore is expected to call ``PE_UNMASK`` to unmask SDEI events on -the PE. No SDEI events can be dispatched until such time. - -Should a PE receive an interrupt that was bound to an SDEI event while the -events are masked on the PE, the dispatcher implementation invokes the function -``plat_sdei_handle_masked_trigger``. The MPIDR of the PE that received the -interrupt and the interrupt ID are passed as parameters. - -The default implementation only prints out a warning message. - -Power State Coordination Interface (in BL31) --------------------------------------------- - -The TF-A implementation of the PSCI API is based around the concept of a -*power domain*. A *power domain* is a CPU or a logical group of CPUs which -share some state on which power management operations can be performed as -specified by `PSCI`_. Each CPU in the system is assigned a cpu index which is -a unique number between ``0`` and ``PLATFORM_CORE_COUNT - 1``. The -*power domains* are arranged in a hierarchical tree structure and each -*power domain* can be identified in a system by the cpu index of any CPU that -is part of that domain and a *power domain level*. A processing element (for -example, a CPU) is at level 0. If the *power domain* node above a CPU is a -logical grouping of CPUs that share some state, then level 1 is that group of -CPUs (for example, a cluster), and level 2 is a group of clusters (for -example, the system). More details on the power domain topology and its -organization can be found in `Power Domain Topology Design`_. - -BL31's platform initialization code exports a pointer to the platform-specific -power management operations required for the PSCI implementation to function -correctly. This information is populated in the ``plat_psci_ops`` structure. The -PSCI implementation calls members of the ``plat_psci_ops`` structure for performing -power management operations on the power domains. For example, the target -CPU is specified by its ``MPIDR`` in a PSCI ``CPU_ON`` call. The ``pwr_domain_on()`` -handler (if present) is called for the CPU power domain. - -The ``power-state`` parameter of a PSCI ``CPU_SUSPEND`` call can be used to -describe composite power states specific to a platform. The PSCI implementation -defines a generic representation of the power-state parameter, which is an -array of local power states where each index corresponds to a power domain -level. Each entry contains the local power state the power domain at that power -level could enter. It depends on the ``validate_power_state()`` handler to -convert the power-state parameter (possibly encoding a composite power state) -passed in a PSCI ``CPU_SUSPEND`` call to this representation. - -The following functions form part of platform port of PSCI functionality. - -Function : plat_psci_stat_accounting_start() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : const psci_power_state_t * - Return : void - -This is an optional hook that platforms can implement for residency statistics -accounting before entering a low power state. The ``pwr_domain_state`` field of -``state_info`` (first argument) can be inspected if stat accounting is done -differently at CPU level versus higher levels. As an example, if the element at -index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down -state, special hardware logic may be programmed in order to keep track of the -residency statistics. For higher levels (array indices > 0), the residency -statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the -default implementation will use PMF to capture timestamps. - -Function : plat_psci_stat_accounting_stop() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : const psci_power_state_t * - Return : void - -This is an optional hook that platforms can implement for residency statistics -accounting after exiting from a low power state. The ``pwr_domain_state`` field -of ``state_info`` (first argument) can be inspected if stat accounting is done -differently at CPU level versus higher levels. As an example, if the element at -index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down -state, special hardware logic may be programmed in order to keep track of the -residency statistics. For higher levels (array indices > 0), the residency -statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the -default implementation will use PMF to capture timestamps. - -Function : plat_psci_stat_get_residency() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int, const psci_power_state_t *, int - Return : u_register_t - -This is an optional interface that is is invoked after resuming from a low power -state and provides the time spent resident in that low power state by the power -domain at a particular power domain level. When a CPU wakes up from suspend, -all its parent power domain levels are also woken up. The generic PSCI code -invokes this function for each parent power domain that is resumed and it -identified by the ``lvl`` (first argument) parameter. The ``state_info`` (second -argument) describes the low power state that the power domain has resumed from. -The current CPU is the first CPU in the power domain to resume from the low -power state and the ``last_cpu_idx`` (third parameter) is the index of the last -CPU in the power domain to suspend and may be needed to calculate the residency -for that power domain. - -Function : plat_get_target_pwr_state() [optional] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : unsigned int, const plat_local_state_t *, unsigned int - Return : plat_local_state_t - -The PSCI generic code uses this function to let the platform participate in -state coordination during a power management operation. The function is passed -a pointer to an array of platform specific local power state ``states`` (second -argument) which contains the requested power state for each CPU at a particular -power domain level ``lvl`` (first argument) within the power domain. The function -is expected to traverse this array of upto ``ncpus`` (third argument) and return -a coordinated target power state by the comparing all the requested power -states. The target power state should not be deeper than any of the requested -power states. - -A weak definition of this API is provided by default wherein it assumes -that the platform assigns a local state value in order of increasing depth -of the power state i.e. for two power states X & Y, if X < Y -then X represents a shallower power state than Y. As a result, the -coordinated target local power state for a power domain will be the minimum -of the requested local power state values. - -Function : plat_get_power_domain_tree_desc() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : const unsigned char * - -This function returns a pointer to the byte array containing the power domain -topology tree description. The format and method to construct this array are -described in `Power Domain Topology Design`_. The BL31 PSCI initialization code -requires this array to be described by the platform, either statically or -dynamically, to initialize the power domain topology tree. In case the array -is populated dynamically, then plat_core_pos_by_mpidr() and -plat_my_core_pos() should also be implemented suitably so that the topology -tree description matches the CPU indices returned by these APIs. These APIs -together form the platform interface for the PSCI topology framework. - -Function : plat_setup_psci_ops() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : uintptr_t, const plat_psci_ops ** - Return : int - -This function may execute with the MMU and data caches enabled if the platform -port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only -called by the primary CPU. - -This function is called by PSCI initialization code. Its purpose is to let -the platform layer know about the warm boot entrypoint through the -``sec_entrypoint`` (first argument) and to export handler routines for -platform-specific psci power management actions by populating the passed -pointer with a pointer to BL31's private ``plat_psci_ops`` structure. - -A description of each member of this structure is given below. Please refer to -the Arm FVP specific implementation of these handlers in -`plat/arm/board/fvp/fvp_pm.c`_ as an example. For each PSCI function that the -platform wants to support, the associated operation or operations in this -structure must be provided and implemented (Refer section 4 of -`Firmware Design`_ for the PSCI API supported in TF-A). To disable a PSCI -function in a platform port, the operation should be removed from this -structure instead of providing an empty implementation. - -plat_psci_ops.cpu_standby() -........................... - -Perform the platform-specific actions to enter the standby state for a cpu -indicated by the passed argument. This provides a fast path for CPU standby -wherein overheads of PSCI state management and lock acquisition is avoided. -For this handler to be invoked by the PSCI ``CPU_SUSPEND`` API implementation, -the suspend state type specified in the ``power-state`` parameter should be -STANDBY and the target power domain level specified should be the CPU. The -handler should put the CPU into a low power retention state (usually by -issuing a wfi instruction) and ensure that it can be woken up from that -state by a normal interrupt. The generic code expects the handler to succeed. - -plat_psci_ops.pwr_domain_on() -............................. - -Perform the platform specific actions to power on a CPU, specified -by the ``MPIDR`` (first argument). The generic code expects the platform to -return PSCI_E_SUCCESS on success or PSCI_E_INTERN_FAIL for any failure. - -plat_psci_ops.pwr_domain_off() -.............................. - -Perform the platform specific actions to prepare to power off the calling CPU -and its higher parent power domain levels as indicated by the ``target_state`` -(first argument). It is called by the PSCI ``CPU_OFF`` API implementation. - -The ``target_state`` encodes the platform coordinated target local power states -for the CPU power domain and its parent power domain levels. The handler -needs to perform power management operation corresponding to the local state -at each power level. - -For this handler, the local power state for the CPU power domain will be a -power down state where as it could be either power down, retention or run state -for the higher power domain levels depending on the result of state -coordination. The generic code expects the handler to succeed. - -plat_psci_ops.pwr_domain_suspend_pwrdown_early() [optional] -........................................................... - -This optional function may be used as a performance optimization to replace -or complement pwr_domain_suspend() on some platforms. Its calling semantics -are identical to pwr_domain_suspend(), except the PSCI implementation only -calls this function when suspending to a power down state, and it guarantees -that data caches are enabled. - -When HW_ASSISTED_COHERENCY = 0, the PSCI implementation disables data caches -before calling pwr_domain_suspend(). If the target_state corresponds to a -power down state and it is safe to perform some or all of the platform -specific actions in that function with data caches enabled, it may be more -efficient to move those actions to this function. When HW_ASSISTED_COHERENCY -= 1, data caches remain enabled throughout, and so there is no advantage to -moving platform specific actions to this function. - -plat_psci_ops.pwr_domain_suspend() -.................................. - -Perform the platform specific actions to prepare to suspend the calling -CPU and its higher parent power domain levels as indicated by the -``target_state`` (first argument). It is called by the PSCI ``CPU_SUSPEND`` -API implementation. - -The ``target_state`` has a similar meaning as described in -the ``pwr_domain_off()`` operation. It encodes the platform coordinated -target local power states for the CPU power domain and its parent -power domain levels. The handler needs to perform power management operation -corresponding to the local state at each power level. The generic code -expects the handler to succeed. - -The difference between turning a power domain off versus suspending it is that -in the former case, the power domain is expected to re-initialize its state -when it is next powered on (see ``pwr_domain_on_finish()``). In the latter -case, the power domain is expected to save enough state so that it can resume -execution by restoring this state when its powered on (see -``pwr_domain_suspend_finish()``). - -When suspending a core, the platform can also choose to power off the GICv3 -Redistributor and ITS through an implementation-defined sequence. To achieve -this safely, the ITS context must be saved first. The architectural part is -implemented by the ``gicv3_its_save_disable()`` helper, but most of the needed -sequence is implementation defined and it is therefore the responsibility of -the platform code to implement the necessary sequence. Then the GIC -Redistributor context can be saved using the ``gicv3_rdistif_save()`` helper. -Powering off the Redistributor requires the implementation to support it and it -is the responsibility of the platform code to execute the right implementation -defined sequence. - -When a system suspend is requested, the platform can also make use of the -``gicv3_distif_save()`` helper to save the context of the GIC Distributor after -it has saved the context of the Redistributors and ITS of all the cores in the -system. The context of the Distributor can be large and may require it to be -allocated in a special area if it cannot fit in the platform's global static -data, for example in DRAM. The Distributor can then be powered down using an -implementation-defined sequence. - -plat_psci_ops.pwr_domain_pwr_down_wfi() -....................................... - -This is an optional function and, if implemented, is expected to perform -platform specific actions including the ``wfi`` invocation which allows the -CPU to powerdown. Since this function is invoked outside the PSCI locks, -the actions performed in this hook must be local to the CPU or the platform -must ensure that races between multiple CPUs cannot occur. - -The ``target_state`` has a similar meaning as described in the ``pwr_domain_off()`` -operation and it encodes the platform coordinated target local power states for -the CPU power domain and its parent power domain levels. This function must -not return back to the caller. - -If this function is not implemented by the platform, PSCI generic -implementation invokes ``psci_power_down_wfi()`` for power down. - -plat_psci_ops.pwr_domain_on_finish() -.................................... - -This function is called by the PSCI implementation after the calling CPU is -powered on and released from reset in response to an earlier PSCI ``CPU_ON`` call. -It performs the platform-specific setup required to initialize enough state for -this CPU to enter the normal world and also provide secure runtime firmware -services. - -The ``target_state`` (first argument) is the prior state of the power domains -immediately before the CPU was turned on. It indicates which power domains -above the CPU might require initialization due to having previously been in -low power states. The generic code expects the handler to succeed. - -plat_psci_ops.pwr_domain_suspend_finish() -......................................... - -This function is called by the PSCI implementation after the calling CPU is -powered on and released from reset in response to an asynchronous wakeup -event, for example a timer interrupt that was programmed by the CPU during the -``CPU_SUSPEND`` call or ``SYSTEM_SUSPEND`` call. It performs the platform-specific -setup required to restore the saved state for this CPU to resume execution -in the normal world and also provide secure runtime firmware services. - -The ``target_state`` (first argument) has a similar meaning as described in -the ``pwr_domain_on_finish()`` operation. The generic code expects the platform -to succeed. - -If the Distributor, Redistributors or ITS have been powered off as part of a -suspend, their context must be restored in this function in the reverse order -to how they were saved during suspend sequence. - -plat_psci_ops.system_off() -.......................... - -This function is called by PSCI implementation in response to a ``SYSTEM_OFF`` -call. It performs the platform-specific system poweroff sequence after -notifying the Secure Payload Dispatcher. - -plat_psci_ops.system_reset() -............................ - -This function is called by PSCI implementation in response to a ``SYSTEM_RESET`` -call. It performs the platform-specific system reset sequence after -notifying the Secure Payload Dispatcher. - -plat_psci_ops.validate_power_state() -.................................... - -This function is called by the PSCI implementation during the ``CPU_SUSPEND`` -call to validate the ``power_state`` parameter of the PSCI API and if valid, -populate it in ``req_state`` (second argument) array as power domain level -specific local states. If the ``power_state`` is invalid, the platform must -return PSCI_E_INVALID_PARAMS as error, which is propagated back to the -normal world PSCI client. - -plat_psci_ops.validate_ns_entrypoint() -...................................... - -This function is called by the PSCI implementation during the ``CPU_SUSPEND``, -``SYSTEM_SUSPEND`` and ``CPU_ON`` calls to validate the non-secure ``entry_point`` -parameter passed by the normal world. If the ``entry_point`` is invalid, -the platform must return PSCI_E_INVALID_ADDRESS as error, which is -propagated back to the normal world PSCI client. - -plat_psci_ops.get_sys_suspend_power_state() -........................................... - -This function is called by the PSCI implementation during the ``SYSTEM_SUSPEND`` -call to get the ``req_state`` parameter from platform which encodes the power -domain level specific local states to suspend to system affinity level. The -``req_state`` will be utilized to do the PSCI state coordination and -``pwr_domain_suspend()`` will be invoked with the coordinated target state to -enter system suspend. - -plat_psci_ops.get_pwr_lvl_state_idx() -..................................... - -This is an optional function and, if implemented, is invoked by the PSCI -implementation to convert the ``local_state`` (first argument) at a specified -``pwr_lvl`` (second argument) to an index between 0 and -``PLAT_MAX_PWR_LVL_STATES`` - 1. This function is only needed if the platform -supports more than two local power states at each power domain level, that is -``PLAT_MAX_PWR_LVL_STATES`` is greater than 2, and needs to account for these -local power states. - -plat_psci_ops.translate_power_state_by_mpidr() -.............................................. - -This is an optional function and, if implemented, verifies the ``power_state`` -(second argument) parameter of the PSCI API corresponding to a target power -domain. The target power domain is identified by using both ``MPIDR`` (first -argument) and the power domain level encoded in ``power_state``. The power domain -level specific local states are to be extracted from ``power_state`` and be -populated in the ``output_state`` (third argument) array. The functionality -is similar to the ``validate_power_state`` function described above and is -envisaged to be used in case the validity of ``power_state`` depend on the -targeted power domain. If the ``power_state`` is invalid for the targeted power -domain, the platform must return PSCI_E_INVALID_PARAMS as error. If this -function is not implemented, then the generic implementation relies on -``validate_power_state`` function to translate the ``power_state``. - -This function can also be used in case the platform wants to support local -power state encoding for ``power_state`` parameter of PSCI_STAT_COUNT/RESIDENCY -APIs as described in Section 5.18 of `PSCI`_. - -plat_psci_ops.get_node_hw_state() -................................. - -This is an optional function. If implemented this function is intended to return -the power state of a node (identified by the first parameter, the ``MPIDR``) in -the power domain topology (identified by the second parameter, ``power_level``), -as retrieved from a power controller or equivalent component on the platform. -Upon successful completion, the implementation must map and return the final -status among ``HW_ON``, ``HW_OFF`` or ``HW_STANDBY``. Upon encountering failures, it -must return either ``PSCI_E_INVALID_PARAMS`` or ``PSCI_E_NOT_SUPPORTED`` as -appropriate. - -Implementations are not expected to handle ``power_levels`` greater than -``PLAT_MAX_PWR_LVL``. - -plat_psci_ops.system_reset2() -............................. - -This is an optional function. If implemented this function is -called during the ``SYSTEM_RESET2`` call to perform a reset -based on the first parameter ``reset_type`` as specified in -`PSCI`_. The parameter ``cookie`` can be used to pass additional -reset information. If the ``reset_type`` is not supported, the -function must return ``PSCI_E_NOT_SUPPORTED``. For architectural -resets, all failures must return ``PSCI_E_INVALID_PARAMETERS`` -and vendor reset can return other PSCI error codes as defined -in `PSCI`_. On success this function will not return. - -plat_psci_ops.write_mem_protect() -................................. - -This is an optional function. If implemented it enables or disables the -``MEM_PROTECT`` functionality based on the value of ``val``. -A non-zero value enables ``MEM_PROTECT`` and a value of zero -disables it. Upon encountering failures it must return a negative value -and on success it must return 0. - -plat_psci_ops.read_mem_protect() -................................ - -This is an optional function. If implemented it returns the current -state of ``MEM_PROTECT`` via the ``val`` parameter. Upon encountering -failures it must return a negative value and on success it must -return 0. - -plat_psci_ops.mem_protect_chk() -............................... - -This is an optional function. If implemented it checks if a memory -region defined by a base address ``base`` and with a size of ``length`` -bytes is protected by ``MEM_PROTECT``. If the region is protected -then it must return 0, otherwise it must return a negative number. - -Interrupt Management framework (in BL31) ----------------------------------------- - -BL31 implements an Interrupt Management Framework (IMF) to manage interrupts -generated in either security state and targeted to EL1 or EL2 in the non-secure -state or EL3/S-EL1 in the secure state. The design of this framework is -described in the `IMF Design Guide`_ - -A platform should export the following APIs to support the IMF. The following -text briefly describes each API and its implementation in Arm standard -platforms. The API implementation depends upon the type of interrupt controller -present in the platform. Arm standard platform layer supports both -`Arm Generic Interrupt Controller version 2.0 (GICv2)`_ -and `3.0 (GICv3)`_. Juno builds the Arm platform layer to use GICv2 and the -FVP can be configured to use either GICv2 or GICv3 depending on the build flag -``FVP_USE_GIC_DRIVER`` (See FVP platform specific build options in -`User Guide`_ for more details). - -See also: `Interrupt Controller Abstraction APIs`__. - -.. __: platform-interrupt-controller-API.rst - -Function : plat_interrupt_type_to_line() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : uint32_t, uint32_t - Return : uint32_t - -The Arm processor signals an interrupt exception either through the IRQ or FIQ -interrupt line. The specific line that is signaled depends on how the interrupt -controller (IC) reports different interrupt types from an execution context in -either security state. The IMF uses this API to determine which interrupt line -the platform IC uses to signal each type of interrupt supported by the framework -from a given security state. This API must be invoked at EL3. - -The first parameter will be one of the ``INTR_TYPE_*`` values (see -`IMF Design Guide`_) indicating the target type of the interrupt, the second parameter is the -security state of the originating execution context. The return result is the -bit position in the ``SCR_EL3`` register of the respective interrupt trap: IRQ=1, -FIQ=2. - -In the case of Arm standard platforms using GICv2, S-EL1 interrupts are -configured as FIQs and Non-secure interrupts as IRQs from either security -state. - -In the case of Arm standard platforms using GICv3, the interrupt line to be -configured depends on the security state of the execution context when the -interrupt is signalled and are as follows: - -- The S-EL1 interrupts are signaled as IRQ in S-EL0/1 context and as FIQ in - NS-EL0/1/2 context. -- The Non secure interrupts are signaled as FIQ in S-EL0/1 context and as IRQ - in the NS-EL0/1/2 context. -- The EL3 interrupts are signaled as FIQ in both S-EL0/1 and NS-EL0/1/2 - context. - -Function : plat_ic_get_pending_interrupt_type() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : uint32_t - -This API returns the type of the highest priority pending interrupt at the -platform IC. The IMF uses the interrupt type to retrieve the corresponding -handler function. ``INTR_TYPE_INVAL`` is returned when there is no interrupt -pending. The valid interrupt types that can be returned are ``INTR_TYPE_EL3``, -``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``. This API must be invoked at EL3. - -In the case of Arm standard platforms using GICv2, the *Highest Priority -Pending Interrupt Register* (``GICC_HPPIR``) is read to determine the id of -the pending interrupt. The type of interrupt depends upon the id value as -follows. - -#. id < 1022 is reported as a S-EL1 interrupt -#. id = 1022 is reported as a Non-secure interrupt. -#. id = 1023 is reported as an invalid interrupt type. - -In the case of Arm standard platforms using GICv3, the system register -``ICC_HPPIR0_EL1``, *Highest Priority Pending group 0 Interrupt Register*, -is read to determine the id of the pending interrupt. The type of interrupt -depends upon the id value as follows. - -#. id = ``PENDING_G1S_INTID`` (1020) is reported as a S-EL1 interrupt -#. id = ``PENDING_G1NS_INTID`` (1021) is reported as a Non-secure interrupt. -#. id = ``GIC_SPURIOUS_INTERRUPT`` (1023) is reported as an invalid interrupt type. -#. All other interrupt id's are reported as EL3 interrupt. - -Function : plat_ic_get_pending_interrupt_id() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : uint32_t - -This API returns the id of the highest priority pending interrupt at the -platform IC. ``INTR_ID_UNAVAILABLE`` is returned when there is no interrupt -pending. - -In the case of Arm standard platforms using GICv2, the *Highest Priority -Pending Interrupt Register* (``GICC_HPPIR``) is read to determine the id of the -pending interrupt. The id that is returned by API depends upon the value of -the id read from the interrupt controller as follows. - -#. id < 1022. id is returned as is. -#. id = 1022. The *Aliased Highest Priority Pending Interrupt Register* - (``GICC_AHPPIR``) is read to determine the id of the non-secure interrupt. - This id is returned by the API. -#. id = 1023. ``INTR_ID_UNAVAILABLE`` is returned. - -In the case of Arm standard platforms using GICv3, if the API is invoked from -EL3, the system register ``ICC_HPPIR0_EL1``, *Highest Priority Pending Interrupt -group 0 Register*, is read to determine the id of the pending interrupt. The id -that is returned by API depends upon the value of the id read from the -interrupt controller as follows. - -#. id < ``PENDING_G1S_INTID`` (1020). id is returned as is. -#. id = ``PENDING_G1S_INTID`` (1020) or ``PENDING_G1NS_INTID`` (1021). The system - register ``ICC_HPPIR1_EL1``, *Highest Priority Pending Interrupt group 1 - Register* is read to determine the id of the group 1 interrupt. This id - is returned by the API as long as it is a valid interrupt id -#. If the id is any of the special interrupt identifiers, - ``INTR_ID_UNAVAILABLE`` is returned. - -When the API invoked from S-EL1 for GICv3 systems, the id read from system -register ``ICC_HPPIR1_EL1``, *Highest Priority Pending group 1 Interrupt -Register*, is returned if is not equal to GIC_SPURIOUS_INTERRUPT (1023) else -``INTR_ID_UNAVAILABLE`` is returned. - -Function : plat_ic_acknowledge_interrupt() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : uint32_t - -This API is used by the CPU to indicate to the platform IC that processing of -the highest pending interrupt has begun. It should return the raw, unmodified -value obtained from the interrupt controller when acknowledging an interrupt. -The actual interrupt number shall be extracted from this raw value using the API -`plat_ic_get_interrupt_id()`__. - -.. __: platform-interrupt-controller-API.rst#function-unsigned-int-plat-ic-get-interrupt-id-unsigned-int-raw-optional - -This function in Arm standard platforms using GICv2, reads the *Interrupt -Acknowledge Register* (``GICC_IAR``). This changes the state of the highest -priority pending interrupt from pending to active in the interrupt controller. -It returns the value read from the ``GICC_IAR``, unmodified. - -In the case of Arm standard platforms using GICv3, if the API is invoked -from EL3, the function reads the system register ``ICC_IAR0_EL1``, *Interrupt -Acknowledge Register group 0*. If the API is invoked from S-EL1, the function -reads the system register ``ICC_IAR1_EL1``, *Interrupt Acknowledge Register -group 1*. The read changes the state of the highest pending interrupt from -pending to active in the interrupt controller. The value read is returned -unmodified. - -The TSP uses this API to start processing of the secure physical timer -interrupt. - -Function : plat_ic_end_of_interrupt() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : uint32_t - Return : void - -This API is used by the CPU to indicate to the platform IC that processing of -the interrupt corresponding to the id (passed as the parameter) has -finished. The id should be the same as the id returned by the -``plat_ic_acknowledge_interrupt()`` API. - -Arm standard platforms write the id to the *End of Interrupt Register* -(``GICC_EOIR``) in case of GICv2, and to ``ICC_EOIR0_EL1`` or ``ICC_EOIR1_EL1`` -system register in case of GICv3 depending on where the API is invoked from, -EL3 or S-EL1. This deactivates the corresponding interrupt in the interrupt -controller. - -The TSP uses this API to finish processing of the secure physical timer -interrupt. - -Function : plat_ic_get_interrupt_type() [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : uint32_t - Return : uint32_t - -This API returns the type of the interrupt id passed as the parameter. -``INTR_TYPE_INVAL`` is returned if the id is invalid. If the id is valid, a valid -interrupt type (one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``) is -returned depending upon how the interrupt has been configured by the platform -IC. This API must be invoked at EL3. - -Arm standard platforms using GICv2 configures S-EL1 interrupts as Group0 interrupts -and Non-secure interrupts as Group1 interrupts. It reads the group value -corresponding to the interrupt id from the relevant *Interrupt Group Register* -(``GICD_IGROUPRn``). It uses the group value to determine the type of interrupt. - -In the case of Arm standard platforms using GICv3, both the *Interrupt Group -Register* (``GICD_IGROUPRn``) and *Interrupt Group Modifier Register* -(``GICD_IGRPMODRn``) is read to figure out whether the interrupt is configured -as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt. - -Crash Reporting mechanism (in BL31) ------------------------------------ - -BL31 implements a crash reporting mechanism which prints the various registers -of the CPU to enable quick crash analysis and debugging. This mechanism relies -on the platform implementing ``plat_crash_console_init``, -``plat_crash_console_putc`` and ``plat_crash_console_flush``. - -The file ``plat/common/aarch64/crash_console_helpers.S`` contains sample -implementation of all of them. Platforms may include this file to their -makefiles in order to benefit from them. By default, they will cause the crash -output to be routed over the normal console infrastructure and get printed on -consoles configured to output in crash state. ``console_set_scope()`` can be -used to control whether a console is used for crash output. -NOTE: Platforms are responsible for making sure that they only mark consoles for -use in the crash scope that are able to support this, i.e. that are written in -assembly and conform with the register clobber rules for putc() (x0-x2, x16-x17) -and flush() (x0-x3, x16-x17) crash callbacks. - -In some cases (such as debugging very early crashes that happen before the -normal boot console can be set up), platforms may want to control crash output -more explicitly. These platforms may instead provide custom implementations for -these. They are executed outside of a C environment and without a stack. Many -console drivers provide functions named ``console_xxx_core_init/putc/flush`` -that are designed to be used by these functions. See Arm platforms (like juno) -for an example of this. - -Function : plat_crash_console_init [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : int - -This API is used by the crash reporting mechanism to initialize the crash -console. It must only use the general purpose registers x0 through x7 to do the -initialization and returns 1 on success. - -Function : plat_crash_console_putc [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : int - Return : int - -This API is used by the crash reporting mechanism to print a character on the -designated crash console. It must only use general purpose registers x1 and -x2 to do its work. The parameter and the return value are in general purpose -register x0. - -Function : plat_crash_console_flush [mandatory] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : int - -This API is used by the crash reporting mechanism to force write of all buffered -data on the designated crash console. It should only use general purpose -registers x0 through x5 to do its work. The return value is 0 on successful -completion; otherwise the return value is -1. - -External Abort handling and RAS Support ---------------------------------------- - -Function : plat_ea_handler -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : int - Argument : uint64_t - Argument : void * - Argument : void * - Argument : uint64_t - Return : void - -This function is invoked by the RAS framework for the platform to handle an -External Abort received at EL3. The intention of the function is to attempt to -resolve the cause of External Abort and return; if that's not possible, to -initiate orderly shutdown of the system. - -The first parameter (``int ea_reason``) indicates the reason for External Abort. -Its value is one of ``ERROR_EA_*`` constants defined in ``ea_handle.h``. - -The second parameter (``uint64_t syndrome``) is the respective syndrome -presented to EL3 after having received the External Abort. Depending on the -nature of the abort (as can be inferred from the ``ea_reason`` parameter), this -can be the content of either ``ESR_EL3`` or ``DISR_EL1``. - -The third parameter (``void *cookie``) is unused for now. The fourth parameter -(``void *handle``) is a pointer to the preempted context. The fifth parameter -(``uint64_t flags``) indicates the preempted security state. These parameters -are received from the top-level exception handler. - -If ``RAS_EXTENSION`` is set to ``1``, the default implementation of this -function iterates through RAS handlers registered by the platform. If any of the -RAS handlers resolve the External Abort, no further action is taken. - -If ``RAS_EXTENSION`` is set to ``0``, or if none of the platform RAS handlers -could resolve the External Abort, the default implementation prints an error -message, and panics. - -Function : plat_handle_uncontainable_ea -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : int - Argument : uint64_t - Return : void - -This function is invoked by the RAS framework when an External Abort of -Uncontainable type is received at EL3. Due to the critical nature of -Uncontainable errors, the intention of this function is to initiate orderly -shutdown of the system, and is not expected to return. - -This function must be implemented in assembly. - -The first and second parameters are the same as that of ``plat_ea_handler``. - -The default implementation of this function calls -``report_unhandled_exception``. - -Function : plat_handle_double_fault -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : int - Argument : uint64_t - Return : void - -This function is invoked by the RAS framework when another External Abort is -received at EL3 while one is already being handled. I.e., a call to -``plat_ea_handler`` is outstanding. Due to its critical nature, the intention of -this function is to initiate orderly shutdown of the system, and is not expected -recover or return. - -This function must be implemented in assembly. - -The first and second parameters are the same as that of ``plat_ea_handler``. - -The default implementation of this function calls -``report_unhandled_exception``. - -Function : plat_handle_el3_ea -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Return : void - -This function is invoked when an External Abort is received while executing in -EL3. Due to its critical nature, the intention of this function is to initiate -orderly shutdown of the system, and is not expected recover or return. - -This function must be implemented in assembly. - -The default implementation of this function calls -``report_unhandled_exception``. - -Build flags ------------ - -There are some build flags which can be defined by the platform to control -inclusion or exclusion of certain BL stages from the FIP image. These flags -need to be defined in the platform makefile which will get included by the -build system. - -- **NEED_BL33** - By default, this flag is defined ``yes`` by the build system and ``BL33`` - build option should be supplied as a build option. The platform has the - option of excluding the BL33 image in the ``fip`` image by defining this flag - to ``no``. If any of the options ``EL3_PAYLOAD_BASE`` or ``PRELOADED_BL33_BASE`` - are used, this flag will be set to ``no`` automatically. - -C Library ---------- - -To avoid subtle toolchain behavioral dependencies, the header files provided -by the compiler are not used. The software is built with the ``-nostdinc`` flag -to ensure no headers are included from the toolchain inadvertently. Instead the -required headers are included in the TF-A source tree. The library only -contains those C library definitions required by the local implementation. If -more functionality is required, the needed library functions will need to be -added to the local implementation. - -Some C headers have been obtained from `FreeBSD`_ and `SCC`_, while others have -been written specifically for TF-A. Fome implementation files have been obtained -from `FreeBSD`_, others have been written specifically for TF-A as well. The -files can be found in ``include/lib/libc`` and ``lib/libc``. - -SCC can be found in http://www.simple-cc.org/. A copy of the `FreeBSD`_ sources -can be obtained from http://github.com/freebsd/freebsd. - -Storage abstraction layer -------------------------- - -In order to improve platform independence and portability an storage abstraction -layer is used to load data from non-volatile platform storage. - -Each platform should register devices and their drivers via the Storage layer. -These drivers then need to be initialized by bootloader phases as -required in their respective ``blx_platform_setup()`` functions. Currently -storage access is only required by BL1 and BL2 phases. The ``load_image()`` -function uses the storage layer to access non-volatile platform storage. - -It is mandatory to implement at least one storage driver. For the Arm -development platforms the Firmware Image Package (FIP) driver is provided as -the default means to load data from storage (see the "Firmware Image Package" -section in the `User Guide`_). The storage layer is described in the header file -``include/drivers/io/io_storage.h``. The implementation of the common library -is in ``drivers/io/io_storage.c`` and the driver files are located in -``drivers/io/``. - -Each IO driver must provide ``io_dev_*`` structures, as described in -``drivers/io/io_driver.h``. These are returned via a mandatory registration -function that is called on platform initialization. The semi-hosting driver -implementation in ``io_semihosting.c`` can be used as an example. - -The Storage layer provides mechanisms to initialize storage devices before -IO operations are called. The basic operations supported by the layer -include ``open()``, ``close()``, ``read()``, ``write()``, ``size()`` and ``seek()``. -Drivers do not have to implement all operations, but each platform must -provide at least one driver for a device capable of supporting generic -operations such as loading a bootloader image. - -The current implementation only allows for known images to be loaded by the -firmware. These images are specified by using their identifiers, as defined in -``include/plat/common/common_def.h`` (or a separate header file included from -there). The platform layer (``plat_get_image_source()``) then returns a reference -to a device and a driver-specific ``spec`` which will be understood by the driver -to allow access to the image data. - -The layer is designed in such a way that is it possible to chain drivers with -other drivers. For example, file-system drivers may be implemented on top of -physical block devices, both represented by IO devices with corresponding -drivers. In such a case, the file-system "binding" with the block device may -be deferred until the file-system device is initialised. - -The abstraction currently depends on structures being statically allocated -by the drivers and callers, as the system does not yet provide a means of -dynamically allocating memory. This may also have the affect of limiting the -amount of open resources per driver. - --------------- - -*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* - -.. _include/plat/common/platform.h: ../include/plat/common/platform.h -.. _include/plat/arm/common/plat_arm.h: ../include/plat/arm/common/plat_arm.h%5D -.. _User Guide: user-guide.rst -.. _include/plat/common/common_def.h: ../include/plat/common/common_def.h -.. _include/plat/arm/common/arm_def.h: ../include/plat/arm/common/arm_def.h -.. _plat/common/aarch64/platform_mp_stack.S: ../plat/common/aarch64/platform_mp_stack.S -.. _plat/common/aarch64/platform_up_stack.S: ../plat/common/aarch64/platform_up_stack.S -.. _For example, define the build flag in platform.mk: PLAT_PL061_MAX_GPIOS%20:=%20160 -.. _Power Domain Topology Design: psci-pd-tree.rst -.. _include/common/bl_common.h: ../include/common/bl_common.h -.. _include/lib/aarch32/arch.h: ../include/lib/aarch32/arch.h -.. _Firmware Design: firmware-design.rst -.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf -.. _plat/arm/board/fvp/fvp_pm.c: ../plat/arm/board/fvp/fvp_pm.c -.. _Platform compatibility policy: ./platform-compatibility-policy.rst -.. _IMF Design Guide: interrupt-framework-design.rst -.. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html -.. _3.0 (GICv3): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0069b/index.html -.. _FreeBSD: https://www.freebsd.org -.. _SCC: http://www.simple-cc.org/ diff --git a/docs/process/coding-guidelines.rst b/docs/process/coding-guidelines.rst new file mode 100644 index 0000000..644f828 --- /dev/null +++ b/docs/process/coding-guidelines.rst @@ -0,0 +1,554 @@ +Trusted Firmware-A Coding Guidelines +==================================== + + + +.. contents:: + +The following sections contain TF coding guidelines. They are continually +evolving and should not be considered "set in stone". Feel free to question them +and provide feedback. + +Some of the guidelines may also apply to other codebases. + +**Note:** the existing TF codebase does not necessarily comply with all the +below guidelines but the intent is for it to do so eventually. + +Checkpatch overrides +-------------------- + +Some checkpatch warnings in the TF codebase are deliberately ignored. These +include: + +- ``**WARNING: line over 80 characters**``: Although the codebase should + generally conform to the 80 character limit this is overly restrictive in some + cases. + +- ``**WARNING: Use of volatile is usually wrong``: see + `Why the “volatile” type class should not be used`_ . Although this document + contains some very useful information, there are several legimate uses of the + volatile keyword within the TF codebase. + +Headers and inclusion +--------------------- + +Header guards +^^^^^^^^^^^^^ + +For a header file called "some_driver.h" the style used by the Trusted Firmware +is: + +.. code:: c + + #ifndef SOME_DRIVER_H + #define SOME_DRIVER_H + +
+ + #endif /* SOME_DRIVER_H */ + +Include statement ordering +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All header files that are included by a source file must use the following, +grouped ordering. This is to improve readability (by making it easier to quickly +read through the list of headers) and maintainability. + +#. *System* includes: Header files from the standard *C* library, such as + ``stddef.h`` and ``string.h``. + +#. *Project* includes: Header files under the ``include/`` directory within TF + are *project* includes. + +#. *Platform* includes: Header files relating to a single, specific platform, + and which are located under the ``plat/`` directory within TF, + are *platform* includes. + +Within each group, ``#include`` statements must be in alphabetical order, +taking both the file and directory names into account. + +Groups must be separated by a single blank line for clarity. + +The example below illustrates the ordering rules using some contrived header +file names; this type of name reuse should be otherwise avoided. + +.. code:: c + + #include + + #include + #include + #include + #include + + #include "./a_header.h" + +Include statement variants +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Two variants of the ``#include`` directive are acceptable in the TF codebase. +Correct use of the two styles improves readability by suggesting the location +of the included header and reducing ambiguity in cases where generic and +platform-specific headers share a name. + +For header files that are in the same directory as the source file that is +including them, use the ``"..."`` variant. + +For header files that are **not** in the same directory as the source file that +is including them, use the ``<...>`` variant. + +Example (bl1_fwu.c): + +.. code:: c + + #include + #include + #include + + #include "bl1_private.h" + +Platform include paths +^^^^^^^^^^^^^^^^^^^^^^ + +Platforms are allowed to add more include paths to be passed to the compiler. +The ``PLAT_INCLUDES`` variable is used for this purpose. This is needed in +particular for the file ``platform_def.h``. + +Example: + +.. code:: c + + PLAT_INCLUDES += -Iinclude/plat/myplat/include + +Types and typedefs +------------------ + +Use of built-in *C* and *libc* data types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The TF codebase should be kept as portable as possible, especially since both +64-bit and 32-bit platforms are supported. To help with this, the following data +type usage guidelines should be followed: + +- Where possible, use the built-in *C* data types for variable storage (for + example, ``char``, ``int``, ``long long``, etc) instead of the standard *C99* + types. Most code is typically only concerned with the minimum size of the + data stored, which the built-in *C* types guarantee. + +- Avoid using the exact-size standard *C99* types in general (for example, + ``uint16_t``, ``uint32_t``, ``uint64_t``, etc) since they can prevent the + compiler from making optimizations. There are legitimate uses for them, + for example to represent data of a known structure. When using them in struct + definitions, consider how padding in the struct will work across architectures. + For example, extra padding may be introduced in AArch32 systems if a struct + member crosses a 32-bit boundary. + +- Use ``int`` as the default integer type - it's likely to be the fastest on all + systems. Also this can be assumed to be 32-bit as a consequence of the + `Procedure Call Standard for the Arm Architecture`_ and the `Procedure Call + Standard for the Arm 64-bit Architecture`_ . + +- Avoid use of ``short`` as this may end up being slower than ``int`` in some + systems. If a variable must be exactly 16-bit, use ``int16_t`` or + ``uint16_t``. + +- Avoid use of ``long``. This is guaranteed to be at least 32-bit but, given + that `int` is 32-bit on Arm platforms, there is no use for it. For integers of + at least 64-bit, use ``long long``. + +- Use ``char`` for storing text. Use ``uint8_t`` for storing other 8-bit data. + +- Use ``unsigned`` for integers that can never be negative (counts, + indices, sizes, etc). TF intends to comply with MISRA "essential type" coding + rules (10.X), where signed and unsigned types are considered different + essential types. Choosing the correct type will aid this. MISRA static + analysers will pick up any implicit signed/unsigned conversions that may lead + to unexpected behaviour. + +- For pointer types: + + - If an argument in a function declaration is pointing to a known type then + simply use a pointer to that type (for example: ``struct my_struct *``). + + - If a variable (including an argument in a function declaration) is pointing + to a general, memory-mapped address, an array of pointers or another + structure that is likely to require pointer arithmetic then use + ``uintptr_t``. This will reduce the amount of casting required in the code. + Avoid using ``unsigned long`` or ``unsigned long long`` for this purpose; it + may work but is less portable. + + - For other pointer arguments in a function declaration, use ``void *``. This + includes pointers to types that are abstracted away from the known API and + pointers to arbitrary data. This allows the calling function to pass a + pointer argument to the function without any explicit casting (the cast to + ``void *`` is implicit). The function implementation can then do the + appropriate casting to a specific type. + + - Use ``ptrdiff_t`` to compare the difference between 2 pointers. + +- Use ``size_t`` when storing the ``sizeof()`` something. + +- Use ``ssize_t`` when returning the ``sizeof()`` something from a function that + can also return an error code; the signed type allows for a negative return + code in case of error. This practice should be used sparingly. + +- Use ``u_register_t`` when it's important to store the contents of a register + in its native size (32-bit in AArch32 and 64-bit in AArch64). This is not a + standard *C99* type but is widely available in libc implementations, + including the FreeBSD version included with the TF codebase. Where possible, + cast the variable to a more appropriate type before interpreting the data. For + example, the following struct in ``ep_info.h`` could use this type to minimize + the storage required for the set of registers: + +.. code:: c + + typedef struct aapcs64_params { + u_register_t arg0; + u_register_t arg1; + u_register_t arg2; + u_register_t arg3; + u_register_t arg4; + u_register_t arg5; + u_register_t arg6; + u_register_t arg7; + } aapcs64_params_t; + +If some code wants to operate on ``arg0`` and knows that it represents a 32-bit +unsigned integer on all systems, cast it to ``unsigned int``. + +These guidelines should be updated if additional types are needed. + +Avoid anonymous typedefs of structs/enums in headers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For example, the following definition: + +.. code:: c + + typedef struct { + int arg1; + int arg2; + } my_struct_t; + + +is better written as: + +.. code:: c + + struct my_struct { + int arg1; + int arg2; + }; + +This allows function declarations in other header files that depend on the +struct/enum to forward declare the struct/enum instead of including the +entire header: + +.. code:: c + + #include + void my_func(my_struct_t *arg); + +instead of: + +.. code:: c + + struct my_struct; + void my_func(struct my_struct *arg); + +Some TF definitions use both a struct/enum name **and** a typedef name. This +is discouraged for new definitions as it makes it difficult for TF to comply +with MISRA rule 8.3, which states that "All declarations of an object or +function shall use the same names and type qualifiers". + +The Linux coding standards also discourage new typedefs and checkpatch emits +a warning for this. + +Existing typedefs will be retained for compatibility. + +Error handling and robustness +----------------------------- + +Using CASSERT to check for compile time data errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Where possible, use the ``CASSERT`` macro to check the validity of data known at +compile time instead of checking validity at runtime, to avoid unnecessary +runtime code. + +For example, this can be used to check that the assembler's and compiler's views +of the size of an array is the same. + +.. code:: c + + #include + + define MY_STRUCT_SIZE 8 /* Used by assembler source files */ + + struct my_struct { + uint32_t arg1; + uint32_t arg2; + }; + + CASSERT(MY_STRUCT_SIZE == sizeof(struct my_struct), assert_my_struct_size_mismatch); + + +If ``MY_STRUCT_SIZE`` in the above example were wrong then the compiler would +emit an error like this: + +.. code:: c + + my_struct.h:10:1: error: size of array ‘assert_my_struct_size_mismatch’ is negative + + +Using assert() to check for programming errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In general, each secure world TF image (BL1, BL2, BL31 and BL32) should be +treated as a tightly integrated package; the image builder should be aware of +and responsible for all functionality within the image, even if code within that +image is provided by multiple entities. This allows us to be more aggressive in +interpreting invalid state or bad function arguments as programming errors using +``assert()``, including arguments passed across platform porting interfaces. +This is in contrast to code in a Linux environment, which is less tightly +integrated and may attempt to be more defensive by passing the error back up the +call stack. + +Where possible, badly written TF code should fail early using ``assert()``. This +helps reduce the amount of untested conditional code. By default these +statements are not compiled into release builds, although this can be overridden +using the ``ENABLE_ASSERTIONS`` build flag. + +Examples: + +- Bad argument supplied to library function +- Bad argument provided by platform porting function +- Internal secure world image state is inconsistent + + +Handling integration errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Each secure world image may be provided by a different entity (for example, a +Trusted Boot vendor may provide the BL2 image, a TEE vendor may provide the BL32 +image and the OEM/SoC vendor may provide the other images). + +An image may contain bugs that are only visible when the images are integrated. +The system integrator may not even have access to the debug variants of all the +images in order to check if asserts are firing. For example, the release variant +of BL1 may have already been burnt into the SoC. Therefore, TF code that detects +an integration error should _not_ consider this a programming error, and should +always take action, even in release builds. + +If an integration error is considered non-critical it should be treated as a +recoverable error. If the error is considered critical it should be treated as +an unexpected unrecoverable error. + +Handling recoverable errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The secure world **must not** crash when supplied with bad data from an external +source. For example, data from the normal world or a hardware device. Similarly, +the secure world **must not** crash if it detects a non-critical problem within +itself or the system. It must make every effort to recover from the problem by +emitting a ``WARN`` message, performing any necessary error handling and +continuing. + +Examples: + +- Secure world receives SMC from normal world with bad arguments. +- Secure world receives SMC from normal world at an unexpected time. +- BL31 receives SMC from BL32 with bad arguments. +- BL31 receives SMC from BL32 at unexpected time. +- Secure world receives recoverable error from hardware device. Retrying the + operation may help here. +- Non-critical secure world service is not functioning correctly. +- BL31 SPD discovers minor configuration problem with corresponding SP. + +Handling unrecoverable errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In some cases it may not be possible for the secure world to recover from an +error. This situation should be handled in one of the following ways: + +1. If the unrecoverable error is unexpected then emit an ``ERROR`` message and + call ``panic()``. This will end up calling the platform-specific function + ``plat_panic_handler()``. +2. If the unrecoverable error is expected to occur in certain circumstances, + then emit an ``ERROR`` message and call the platform-specific function + ``plat_error_handler()``. + +Cases 1 and 2 are subtly different. A platform may implement ``plat_panic_handler`` +and ``plat_error_handler`` in the same way (for example, by waiting for a secure +watchdog to time-out or by invoking an interface on the platform's power +controller to reset the platform). However, ``plat_error_handler`` may take +additional action for some errors (for example, it may set a flag so the +platform resets into a different mode). Also, ``plat_panic_handler()`` may +implement additional debug functionality (for example, invoking a hardware +breakpoint). + +Examples of unexpected unrecoverable errors: + +- BL32 receives an unexpected SMC response from BL31 that it is unable to + recover from. +- BL31 Trusted OS SPD code discovers that BL2 has not loaded the corresponding + Trusted OS, which is critical for platform operation. +- Secure world discovers that a critical hardware device is an unexpected and + unrecoverable state. +- Secure world receives an unexpected and unrecoverable error from a critical + hardware device. +- Secure world discovers that it is running on unsupported hardware. + +Examples of expected unrecoverable errors: + +- BL1/BL2 fails to load the next image due to missing/corrupt firmware on disk. +- BL1/BL2 fails to authenticate the next image due to an invalid certificate. +- Secure world continuously receives recoverable errors from a hardware device + but is unable to proceed without a valid response. + +Handling critical unresponsiveness +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the secure world is waiting for a response from an external source (for +example, the normal world or a hardware device) which is critical for continued +operation, it must not wait indefinitely. It must have a mechanism (for example, +a secure watchdog) for resetting itself and/or the external source to prevent +the system from executing in this state indefinitely. + +Examples: + +- BL1 is waiting for the normal world to raise an SMC to proceed to the next + stage of the secure firmware update process. +- A Trusted OS is waiting for a response from a proxy in the normal world that + is critical for continued operation. +- Secure world is waiting for a hardware response that is critical for continued + operation. + +Security considerations +----------------------- + +Part of the security of a platform is handling errors correctly, as described in +the previous section. There are several other security considerations covered in +this section. + +Do not leak secrets to the normal world +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The secure world **must not** leak secrets to the normal world, for example in +response to an SMC. + +Handling Denial of Service attacks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The secure world **should never** crash or become unusable due to receiving too +many normal world requests (a *Denial of Service* or *DoS* attack). It should +have a mechanism for throttling or ignoring normal world requests. + +Performance considerations +-------------------------- + +Avoid printf and use logging macros +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``debug.h`` provides logging macros (for example, ``WARN`` and ``ERROR``) +which wrap ``tf_log`` and which allow the logging call to be compiled-out +depending on the ``make`` command. Use these macros to avoid print statements +being compiled unconditionally into the binary. + +Each logging macro has a numerical log level: + +.. code:: c + + #define LOG_LEVEL_NONE 0 + #define LOG_LEVEL_ERROR 10 + #define LOG_LEVEL_NOTICE 20 + #define LOG_LEVEL_WARNING 30 + #define LOG_LEVEL_INFO 40 + #define LOG_LEVEL_VERBOSE 50 + + +By default, all logging statements with a log level ``<= LOG_LEVEL_INFO`` will +be compiled into debug builds and all statements with a log level +``<= LOG_LEVEL_NOTICE`` will be compiled into release builds. This can be +overridden from the command line or by the platform makefile (although it may be +necessary to clean the build directory first). For example, to enable +``VERBOSE`` logging on FVP: + +``make PLAT=fvp LOG_LEVEL=50 all`` + +Use const data where possible +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For example, the following code: + +.. code:: c + + struct my_struct { + int arg1; + int arg2; + }; + + void init(struct my_struct *ptr); + + void main(void) + { + struct my_struct x; + x.arg1 = 1; + x.arg2 = 2; + init(&x); + } + +is better written as: + +.. code:: c + + struct my_struct { + int arg1; + int arg2; + }; + + void init(const struct my_struct *ptr); + + void main(void) + { + const struct my_struct x = { 1, 2 }; + init(&x); + } + +This allows the linker to put the data in a read-only data section instead of a +writeable data section, which may result in a smaller and faster binary. Note +that this may require dependent functions (``init()`` in the above example) to +have ``const`` arguments, assuming they don't need to modify the data. + +Library and driver code +----------------------- + +TF library code (under ``lib/`` and ``include/lib``) is any code that provides a +reusable interface to other code, potentially even to code outside of TF. + +In some systems drivers must conform to a specific driver framework to provide +services to the rest of the system. TF has no driver framework and the +distinction between a driver and library is somewhat subjective. + +A driver (under ``drivers/`` and ``include/drivers/``) is defined as code that +interfaces with hardware via a memory mapped interface. + +Some drivers (for example, the Arm CCI driver in ``include/drivers/arm/cci.h``) +provide a general purpose API to that specific hardware. Other drivers (for +example, the Arm PL011 console driver in ``drivers/arm/pl011/pl011_console.S``) +provide a specific hardware implementation of a more abstract library API. In +the latter case there may potentially be multiple drivers for the same hardware +device. + +Neither libraries nor drivers should depend on platform-specific code. If they +require platform-specific data (for example, a base address) to operate then +they should provide an initialization function that takes the platform-specific +data as arguments. + +TF common code (under ``common/`` and ``include/common/``) is code that is re-used +by other generic (non-platform-specific) TF code. It is effectively internal +library code. + +.. _`Why the “volatile” type class should not be used`: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html +.. _`Procedure Call Standard for the Arm Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf +.. _`Procedure Call Standard for the Arm 64-bit Architecture`: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf diff --git a/docs/process/contributing.rst b/docs/process/contributing.rst new file mode 100644 index 0000000..bd950e5 --- /dev/null +++ b/docs/process/contributing.rst @@ -0,0 +1,149 @@ +Contributing to Trusted Firmware-A +================================== + +Getting Started +--------------- + +- Make sure you have a Github account and you are logged on + `developer.trustedfirmware.org`_. +- Create an `issue`_ for your work if one does not already exist. This gives + everyone visibility of whether others are working on something similar. + + - If you intend to include Third Party IP in your contribution, please + raise a separate `issue`_ for this and ensure that the changes that + include Third Party IP are made on a separate topic branch. + +- Clone `arm-trusted-firmware-a`_ on your own machine as suggested on the + `User Guide`_. +- Create a local topic branch based on the `arm-trusted-firmware-a`_ ``master`` + branch. + +Making Changes +-------------- + +- Make commits of logical units. See these general `Git guidelines`_ for + contributing to a project. +- Follow the `Coding Guidelines`_. + + - Use the checkpatch.pl script provided with the Linux source tree. A + Makefile target is provided for convenience (see the "Checking source code + style" section in the `User Guide`_). + +- Keep the commits on topic. If you need to fix another bug or make another + enhancement, please create a separate `issue`_ and address it on a separate + topic branch. +- Avoid long commit series. If you do have a long series, consider whether + some commits should be squashed together or addressed in a separate topic. +- Make sure your commit messages are in the proper format. If a commit fixes + an `issue`_, include a reference. +- Where appropriate, please update the documentation. + + - Consider whether the `User Guide`_, `Porting Guide`_, `Firmware Design`_ + or other in-source documentation needs updating. + - Ensure that each changed file has the correct copyright and license + information. Files that entirely consist of contributions to this + project should have a copyright notice and BSD-3-Clause SPDX license + identifier of the form as shown in `license.rst`_. Files that contain + changes to imported Third Party IP files should retain their original + copyright and license notices. For significant contributions you may + add your own copyright notice in following format: + + :: + + Portions copyright (c) [XXXX-]YYYY, . All rights reserved. + + where XXXX is the year of first contribution (if different to YYYY) and + YYYY is the year of most recent contribution. is your name or + your company name. + - If you are submitting new files that you intend to be the technical + sub-maintainer for (for example, a new platform port), then also update + the `Maintainers`_ file. + - For topics with multiple commits, you should make all documentation + changes (and nothing else) in the last commit of the series. Otherwise, + include the documentation changes within the single commit. + +- Please test your changes. As a minimum, ensure that Linux boots on the + Foundation FVP. See `Running the software on FVP`_ for more information. For + more extensive testing, consider running the `TF-A Tests`_ against your + patches. + +Submitting Changes +------------------ + +- Ensure that each commit in the series has at least one ``Signed-off-by:`` + line, using your real name and email address. The names in the + ``Signed-off-by:`` and ``Author:`` lines must match. If anyone else + contributes to the commit, they must also add their own ``Signed-off-by:`` + line. By adding this line the contributor certifies the contribution is made + under the terms of the `Developer Certificate of Origin (DCO)`_. + + More details may be found in the `Gerrit Signed-off-by Lines guidelines`_. + +- Ensure that each commit also has a unique ``Change-Id:`` line. If you have + cloned the repository with the "`Clone with commit-msg hook`" clone method + (as advised on the `User Guide`_), this should already be the case. + + More details may be found in the `Gerrit Change-Ids documentation`_. + +- Submit your changes for review at https://review.trustedfirmware.org + targeting the ``integration`` branch. + + - The changes will then undergo further review and testing by the + `Maintainers`_. Any review comments will be made directly on your patch. + This may require you to do some rework. + + Refer to the `Gerrit Uploading Changes documentation`_ for more details. + +- When the changes are accepted, the `Maintainers`_ will integrate them. + + - Typically, the `Maintainers`_ will merge the changes into the + ``integration`` branch. + - If the changes are not based on a sufficiently-recent commit, or if they + cannot be automatically rebased, then the `Maintainers`_ may rebase it on + the ``master`` branch or ask you to do so. + - After final integration testing, the changes will make their way into the + ``master`` branch. If a problem is found during integration, the merge + commit will be removed from the ``integration`` branch and the + `Maintainers`_ will ask you to create a new patch set to resolve the + problem. + +Binary Components +----------------- + +- Platforms may depend on binary components submitted to the `Trusted Firmware + binary repository`_ if they require code that the contributor is unable or + unwilling to open-source. This should be used as a rare exception. +- All binary components must follow the contribution guidelines (in particular + licensing rules) outlined in the `readme.rst `_ file of + the binary repository. +- Binary components must be restricted to only the specific functionality that + cannot be open-sourced and must be linked into a larger open-source platform + port. The majority of the platform port must still be implemented in open + source. Platform ports that are merely a thin wrapper around a binary + component that contains all the actual code will not be accepted. +- Only platform port code (i.e. in the ``plat/`` directory) may rely on + binary components. Generic code must always be fully open-source. + +-------------- + +*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* + +.. _developer.trustedfirmware.org: https://developer.trustedfirmware.org +.. _issue: https://developer.trustedfirmware.org/project/board/1/ +.. _arm-trusted-firmware-a: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git +.. _Git guidelines: http://git-scm.com/book/ch5-2.html +.. _Coding Guidelines: ./docs/coding-guidelines.rst +.. _User Guide: ./docs/user-guide.rst +.. _Porting Guide: ./docs/porting-guide.rst +.. _Firmware Design: ./docs/firmware-design.rst +.. _license.rst: ./license.rst +.. _Acknowledgements: ./acknowledgements.rst +.. _Maintainers: ./maintainers.rst +.. _Running the software on FVP: ./docs/user-guide.rst#user-content-running-the-software-on-fvp +.. _Developer Certificate of Origin (DCO): ./dco.txt +.. _Gerrit Uploading Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html +.. _Gerrit Signed-off-by Lines guidelines: https://review.trustedfirmware.org/Documentation/user-signedoffby.html +.. _Gerrit Change-Ids documentation: https://review.trustedfirmware.org/Documentation/user-changeid.html +.. _TF-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/ +.. _Trusted Firmware binary repository: https://review.trustedfirmware.org/admin/repos/tf-binaries +.. _tf-binaries-readme: https://git.trustedfirmware.org/tf-binaries.git/tree/readme.rst diff --git a/docs/process/faq.rst b/docs/process/faq.rst new file mode 100644 index 0000000..6aa04f0 --- /dev/null +++ b/docs/process/faq.rst @@ -0,0 +1,79 @@ +Frequently-Asked Questions (FAQ) +================================ + +How do I update my changes? +--------------------------- + +Often it is necessary to update your patch set before it is merged. Refer to the +`Gerrit Upload Patch Set documentation`_ on how to do so. + +If you need to modify an existing patch set with multiple commits, refer to the +`Gerrit Replace Changes documentation`_. + +How long will my changes take to merge into ``integration``? +------------------------------------------------------------ + +This can vary a lot, depending on: + +* How important the patch set is considered by the TF maintainers. Where + possible, you should indicate the required timescales for merging the patch + set and the impact of any delay. Feel free to add a comment to your patch set + to get an estimate of when it will be merged. + +* The quality of the patch set. Patches are likely to be merged more quickly if + they follow the coding guidelines, have already had some code review, and have + been appropriately tested. + +* The impact of the patch set. For example, a patch that changes a key generic + API is likely to receive much greater scrutiny than a local change to a + specific platform port. + +* How much opportunity for external review is required. For example, the TF + maintainers may not wait for external review comments to merge trivial + bug-fixes but may wait up to a week to merge major changes, or ones requiring + feedback from specific parties. + +* How many other patch sets are waiting to be integrated and the risk of + conflict between the topics. + +* If there is a code freeze in place in preparation for the release. Please + refer the `release information`_ for more details. + +* The workload of the TF maintainers. + +How long will it take for my changes to go from ``integration`` to ``master``? +------------------------------------------------------------------------------ + +This depends on how many concurrent patches are being processed at the same +time. In simple cases where all potential regressions have already been tested, +the delay will be less than 1 day. If the TF maintainers are trying to merge +several things over the course of a few days, it might take up to a week. +Typically, it will be 1-2 days. + +The worst case is if the TF maintainers are trying to make a release while also +receiving patches that will not be merged into the release. In this case, the +patches will be merged onto ``integration``, which will temporarily diverge from +the release branch. The ``integration`` branch will be rebased onto ``master`` +after the release, and then ``master`` will be fast-forwarded to ``integration`` +1-2 days later. This whole process could take up 4 weeks. Please refer the +`release information`_ for code freeze dates. The TF maintainers will inform the +patch owner if this is going to happen. + +It is OK to create a patch based on commits that are only available in +``integration`` or another patch set, rather than ``master``. There is a risk +that the dependency commits will change (for example due to patch set rework or +integration problems). If this happens, the dependent patch will need reworking. + +What are these strange comments in my changes? +---------------------------------------------- + +All the comments from ``ci-bot-user`` are associated with Continuous Integration +infrastructure. The links published on the comment are not currently accessible, +but would be after the CI has been transitioned to `trustedfirmware.org`_. +Please refer to https://github.com/ARM-software/tf-issues/issues/681 for more +details on the timelines. + +.. _release information: release-information.rst +.. _Gerrit Upload Patch Set documentation: https://review.trustedfirmware.org/Documentation/intro-user.html#upload-patch-set +.. _Gerrit Replace Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html#push_replace +.. _trustedfirmware.org: https://www.trustedfirmware.org/ diff --git a/docs/process/index.rst b/docs/process/index.rst new file mode 100644 index 0000000..91f1beb --- /dev/null +++ b/docs/process/index.rst @@ -0,0 +1,14 @@ +Processes & Policies +==================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + release-information + security-center + platform-compatibility-policy + coding-guidelines + contributing + faq diff --git a/docs/process/platform-compatibility-policy.rst b/docs/process/platform-compatibility-policy.rst new file mode 100644 index 0000000..e977e63 --- /dev/null +++ b/docs/process/platform-compatibility-policy.rst @@ -0,0 +1,44 @@ +TF-A Platform Compatibility Policy +================================== + + + + +.. contents:: + +-------------- + +Introduction +------------ + +This document clarifies the project's policy around compatibility for upstream +platforms. + +Platform compatibility policy +----------------------------- + +Platform compatibility is mainly affected by changes to Platform APIs (as +documented in the `Porting Guide`_), driver APIs (like the GICv3 drivers) or +library interfaces (like xlat_table library). The project will try to maintain +compatibility for upstream platforms. Due to evolving requirements and +enhancements, there might be changes affecting platform compatibility which +means the previous interface needs to be deprecated and a new interface +introduced to replace it. In case the migration to the new interface is trivial, +the contributor of the change is expected to make good effort to migrate the +upstream platforms to the new interface. + +The `Release information`_ documents the deprecated interfaces and the intended +release after which it will be removed. When an interface is deprecated, the +page must be updated to indicate the release after which the interface will be +removed. This must be at least 1 full release cycle in future. For non-trivial +interface changes, a `tf-issue`_ should be posted to notify platforms that they +should migrate away from the deprecated interfaces. Platforms are expected to +migrate before the removal of the deprecated interface. + +-------------- + +*Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.* + +.. _Porting Guide: ../getting_started/porting-guide.rst +.. _Release information: https://github.com/ARM-software/arm-trusted-firmware/wiki/TF-A-Release-information#removal-of-deprecated-interfaces +.. _tf-issue: https://github.com/ARM-software/tf-issues/issues diff --git a/docs/process/release-information.rst b/docs/process/release-information.rst new file mode 100644 index 0000000..5531150 --- /dev/null +++ b/docs/process/release-information.rst @@ -0,0 +1,89 @@ +TF-A Release Information +======================== + +.. section-numbering:: + :suffix: . + +.. contents:: + +-------------- + +Project Release Cadence +----------------------- + +The project currently aims to do a release once every 6 months which will be +tagged on the master branch. There will be a code freeze (stop merging +non-essential PRs) up to 4 weeks prior to the target release date. The release +candidates will start appearing after this and only bug fixes or updates +required for the release will be merged. The maintainers are free to use their +judgement on what PRs are essential for the release. A release branch may be +created after code freeze if there are significant PRs that need merging onto +the integration branch during the merge window. + +The release testing will be performed on release candidates and depending on +issues found, additional release candidates may be created to fix the issues. + +:: + + |<----------6 months---------->| + |<---4 weeks--->| |<---4 weeks--->| + +-----------------------------------------------------------> time + | | | | + code freeze ver w.x code freeze ver y.z + + +Upcoming Releases +~~~~~~~~~~~~~~~~~ + +These are the estimated dates for the upcoming release. These may change +depending on project requirement and partner feedback. + ++-----------------+---------------------------+------------------------------+ +| Release Version | Target Date | Expected Code Freeze | ++=================+===========================+==============================+ +| v2.0 | 1st week of Oct '18 | 1st week of Sep '18 | ++-----------------+---------------------------+------------------------------+ +| v2.1 | 5th week of Mar '19 | 1st week of Mar '19 | ++-----------------+---------------------------+------------------------------+ + +Removal of Deprecated Interfaces +-------------------------------- + +As mentioned in the `Platform compatibility policy`_, this is a live document +cataloging all the deprecated interfaces in TF-A project and the Release version +after which it will be removed. + ++--------------------------------+-------------+---------+---------------------------------------------------------+ +| Interface | Deprecation | Removed | Comments | +| | Date | after | | +| | | Release | | ++================================+=============+=========+=========================================================+ +| Legacy Console API | Jan '18 | v2.1 | Deprecated in favour of ``MULTI_CONSOLE_API`` | ++--------------------------------+-------------+---------+---------------------------------------------------------+ +| Weak default | Oct '18 | v2.1 | The default implementations are defined in | +| ``plat_crash_console_*`` | | | `crash_console_helpers.S`_. The platforms have to | +| APIs | | | define ``plat_crash_console_*``. | ++--------------------------------+-------------+---------+---------------------------------------------------------+ +| ``finish_console_register`` | Oct '18 | v2.1 | The old version of the macro is deprecated. See commit | +| macro in | | | cc5859c_ for more details. | +| ``MULTI_CONSOLE_API`` | | | | ++--------------------------------+-------------+---------+---------------------------------------------------------+ +| Types ``tzc_action_t`` and | Oct '18 | v2.1 | Using logical operations such as OR in enumerations | +| ``tzc_region_attributes_t`` | | | goes against the MISRA guidelines. | ++--------------------------------+-------------+---------+---------------------------------------------------------+ +| Macro ``EL_IMPLEMENTED()`` | Oct '18 | v2.1 | Deprecated in favour of ``el_implemented()``. | ++--------------------------------+-------------+---------+---------------------------------------------------------+ +| ``get_afflvl_shift()``, | Dec '18 | v2.1 | Removed. | +| ``mpidr_mask_lower_afflvls()``,| | | | +| and ``eret()``. | | | | ++--------------------------------+-------------+---------+---------------------------------------------------------+ +| Extra include paths in the | Jan '18 | v2.1 | Now it is needed to use the full path of the common | +| Makefile in ``INCLUDES``. | | | header files. More information in commit 09d40e0e0828_. | ++--------------------------------+-------------+---------+---------------------------------------------------------+ + +*Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Platform compatibility policy: platform-compatibility-policy.rst +.. _crash_console_helpers.S: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/common/aarch64/crash_console_helpers.S +.. _cc5859c: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=cc5859ca19ff546c35eb0331000dae090b6eabcf +.. _09d40e0e0828: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=09d40e0e08283a249e7dce0e106c07c5141f9b7e diff --git a/docs/process/security-center.rst b/docs/process/security-center.rst new file mode 100644 index 0000000..672c563 --- /dev/null +++ b/docs/process/security-center.rst @@ -0,0 +1,103 @@ +Security Center +=============== + +Security Disclosures +-------------------- + +We disclose all security vulnerabilities we find or are advised about that are +relevant for ARM Trusted Firmware (TF). We encourage responsible disclosure of +vulnerabilities and inform users as best we can about all possible issues. + +We disclose TF vulnerabilities as Security Advisories. These are listed at the +bottom of this page and announced as issues in the `GitHub issue tracker`_ with +the "security-advisory" tag. You can receive notification emails for these by +watching that project. + +Found a Security Issue? +----------------------- + +Although we try to keep TF secure, we can only do so with the help of the +community of developers and security researchers. + +If you think you have found a security vulnerability, please *do not* report it +in the `GitHub issue tracker`_. Instead send an email to +trusted-firmware-security@arm.com + +Please include: + +* Trusted Firmware version (or commit) affected + +* A description of the concern or vulnerability + +* Details on how to replicate the vulnerability, including: + + - Configuration details + + - Proof of concept exploit code + + - Any additional software or tools required + +We recommend using `this PGP/GPG key`_ for encrypting the information. This key +is also available at http://keyserver.pgp.com and LDAP port 389 of the same +server. The fingerprint for this key is: + +:: + + 1309 2C19 22B4 8E87 F17B FE5C 3AB7 EFCB 45A0 DFD0 + +If you would like replies to be encrypted, please provide your public key. + +Please give us the time to respond to you and fix the vulnerability before going +public. We do our best to respond and fix any issues quickly. We also need to +ensure providers of products that use TF have a chance to consider the +implications of the vulnerability and its remedy. + +Afterwards, we encourage you to write-up your findings about the TF source code. + +Attribution +----------- + +We will name and thank you in the ``change-log.rst`` distributed with the source +code and in any published security advisory. + +Security Advisories +------------------- + ++-----------+------------------------------------------------------------------+ +| ID | Title | ++===========+==================================================================+ +| `TFV-1`_ | Malformed Firmware Update SMC can result in copy of unexpectedly | +| | large data into secure memory | ++-----------+------------------------------------------------------------------+ +| `TFV-2`_ | Enabled secure self-hosted invasive debug interface can allow | +| | normal world to panic secure world | ++-----------+------------------------------------------------------------------+ +| `TFV-3`_ | RO memory is always executable at AArch64 Secure EL1 | ++-----------+------------------------------------------------------------------+ +| `TFV-4`_ | Malformed Firmware Update SMC can result in copy or | +| | authentication of unexpected data in secure memory in AArch32 | +| | state | ++-----------+------------------------------------------------------------------+ +| `TFV-5`_ | Not initializing or saving/restoring PMCR_EL0 can leak secure | +| | world timing information | ++-----------+------------------------------------------------------------------+ +| `TFV-6`_ | Arm Trusted Firmware exposure to speculative processor | +| | vulnerabilities using cache timing side-channels | ++-----------+------------------------------------------------------------------+ +| `TFV-7`_ | Trusted Firmware-A exposure to cache speculation vulnerability | +| | Variant 4 | ++-----------+------------------------------------------------------------------+ +| `TFV-8`_ | Not saving x0 to x3 registers can leak information from one | +| | Normal World SMC client to another | ++-----------+------------------------------------------------------------------+ + +.. _GitHub issue tracker: https://github.com/ARM-software/tf-issues/issues +.. _this PGP/GPG key: security-reporting.asc +.. _TFV-1: ./security_advisories/security-advisory-tfv-1.rst +.. _TFV-2: ./security_advisories/security-advisory-tfv-2.rst +.. _TFV-3: ./security_advisories/security-advisory-tfv-3.rst +.. _TFV-4: ./security_advisories/security-advisory-tfv-4.rst +.. _TFV-5: ./security_advisories/security-advisory-tfv-5.rst +.. _TFV-6: ./security_advisories/security-advisory-tfv-6.rst +.. _TFV-7: ./security_advisories/security-advisory-tfv-7.rst +.. _TFV-8: ./security_advisories/security-advisory-tfv-8.rst diff --git a/docs/process/security-reporting.asc b/docs/process/security-reporting.asc new file mode 100644 index 0000000..8c41f7b --- /dev/null +++ b/docs/process/security-reporting.asc @@ -0,0 +1,45 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGP Desktop 10.2.0 (Build 2317) + +mQENBFey/QMBCACyxJaLsMYU794ZfzLdY172tHXRJfP0X3b34HU35G7kYl1zNiYc +/NoygtQdtDv/aW1B2A/YTNhGge+gX4BWAREd5CYDbdPEoMWC395/qbnmMmez7YNY +PEJ9Iq9e5AayAWwZTL1zgKwdvE+WTwWok/nMbsifJSEdhdrOIHNqRcZgplUUyZ2R +sDqFtSbACO3xj4Psk8KJ23Ax7UZgULouZOJaHOnyq8F9V/U7zWvX4Odf96XaC1Em +cUTsG0kQfa7Y4Hqqjzowq366I4k2o2LAtuLPWNCvq5jjEceLs2+qV4cNLgyL2dzO +wtUL6EdkrGfkxsPHpsVKXig4wjeX9ehCSqRlABEBAAG0PVRydXN0ZWQgRmlybXdh +cmUgU2VjdXJpdHkgPHRydXN0ZWQtZmlybXdhcmUtc2VjdXJpdHlAYXJtLmNvbT6J +AYwEEAECAHYFAley/SEwFIAAAAAAIAAHcHJlZmVycmVkLWVtYWlsLWVuY29kaW5n +QHBncC5jb21wZ3BtaW1lCAsJCAcDAgEKAhkBGRhsZGFwOi8va2V5c2VydmVyLnBn +cC5jb20FGwMAAAAFFgADAgEFHgEAAAAGFQgJCgMCAAoJEDq378tFoN/QFJsH/0ly +H91LYYzKIQrbolQw7Rp47lgzH88uN1rInYpW2GaTbjwPffAhYJ4VsN8RaiFskD9m +DjMg4vY8p0jPTCUX1Acq20Wq0Ybv3HcrtjUp4ie0+rLUi3043yJyKFMWkJC2Kr+p +SobnxSrAie4HDFUgSaPoh9Qf1zXEzOavdgcziMiyS5iVUf6NXYZ9z82OTZ6TdPKS +u+L5zOHTdrV3+hD54w00Xa+EIE7u4v0to6Uwm977508hyGuvpOVq+u7+S3qJQvnY ++JheStbgLsm6CyoRjyrlTE01ujAD6hI6Ef9yMgEljOBEy4phKAJ67SCRLEOiCp5U +YHFCULwhzIyg2y3WmZSJASIEEAECAAwFAlezAnwFAwASdQAACgkQlxC4m8pXrXzd +GAf/T8YEICI9qQt2vnCtCbBvVaTc2sAphVZ51kZVDqCDPB7znDtJYRBpi/9IPELt +mYwIElMx2mqmahVaeUghmbzmcLZe8QHUi8GanO1mh+ook6uyjRojSIq6VUVV5uUf +tuscfhpilOvUclqMqYEIgXfl08YwS40Kmmj0qokwad0co0zGQ8GEhlgMi2yvJfiG +fPS0Xcn1J0980E/VgJQCAKwZvukrbb32WVwuhgepqs/4/62PZNxglcErioFt6P0A +ik4t9Hr0uErqCeEKiYtmEw5e9ioRdX7CV+tJgIk907Tpv6E0iDFRJHmJBvmsz82O +stOazS3wZ5Xck7asTqkvoyo9Z7kBDQRXsv0DAQgAsmL1UUIWyoNmYJWixSPDmclP +0ul3T1FCOsIlWTeVeshnHByYdgZOfce78ETCUoq8G7qvYm4GRrEDpqVbxqTxJioP +4Li05WDdNCKzSoqWd8ADA48gYnnJEu2NhA7ZkEC6u3+Mdbmd3M0J6nsAWeE0BV1p +F5zI600sJuoH2QNWB7Kv5N3GCFE4IgCIH8MwDo4Y4FTZtygx4GjEtSExiOIz+bpX +2+GkFCQGpIyLHLP4FmQmrsNzsIdEyFuG0IdoVuQ2PtNLiw+Wkm7CXWgRmFx/dtPN +eVnOFWdbTtjBWVv/Z6zbANos2knfc75KR4FCQ6pWRvVeJuMuMopUDkfFDMtR8QAR +AQABiQJBBBgBAgErBQJXsv0EBRsMAAAAwF0gBBkBCAAGBQJXsv0DAAoJENaB8ph8 +s9hu/nsH/Rx696ZR+1vZi5qCTUwo6s0Qa15x4OuyJEM85VgMLVY7/MZpp1Y8If6u +A5BynQpy4QIPxIRsRx6twduW9/gb8UVhpMRPyuJ+5sSv0/KeUqkPbKSUGro2zGlR +sjqPrchi6uafWZqOR/y/DNkEvkgZZaP+f9xs2qWKuoF08yTioo76QoroA4DVuVAT +MkDFe9d3natAmfmjO4kvxuthg3y7R+sdXrCHpYYJZdbiR6gyj7e8whlSLwHQT3lz +7QBL/CvVvL/dmhu5pk8fsksbehepMQTkCJ6GGEamOPEhwh7IvlzhEt97U4uzjuMd +BPjqOCes+4QTmn/+lMTySG0kXxnHOEUACgkQOrfvy0Wg39D8Jgf/Uf3epkMOJ9xm +N1l5vW8tQQ6RR055YQxQ9P6JMyCQGEJmGOcvrasCho69wMQDy4AYVtJaZd25LH/3 +LX/lcyDOP4C9VYXM+IxlcaRmjBKqWx9UzQeeioIkfmjMpJFU846ZP1dacge0lPx8 +p6ocPbM0rkv0xuF/dwkDQd4BPSmv4/3/UM8FRoYo8Q7SHkDR98wJ8FCm6k9wRtWC +K/jzmBswY2TewAHom3jLzTM0FZ/n5Sini3EGAI2EvnQrxWRpeE7ZOkHKqLHEOaHl +zeST4U/cUgxhwgnhbGJ7zmrFsHpYnnZYM3mIKfQ3/EhksZ68TF9IB1tfUiQTij4r +9jWa0ybRdQ== +=nZZb +-----END PGP PUBLIC KEY BLOCK----- diff --git a/docs/psci-lib-integration-guide.rst b/docs/psci-lib-integration-guide.rst deleted file mode 100644 index 241ab3a..0000000 --- a/docs/psci-lib-integration-guide.rst +++ /dev/null @@ -1,554 +0,0 @@ -PSCI Library Integration guide for Armv8-A AArch32 systems -========================================================== - - -.. section-numbering:: - :suffix: . - -.. contents:: - -This document describes the PSCI library interface with a focus on how to -integrate with a suitable Trusted OS for an Armv8-A AArch32 system. The PSCI -Library implements the PSCI Standard as described in `PSCI spec`_ and is meant -to be integrated with EL3 Runtime Software which invokes the PSCI Library -interface appropriately. **EL3 Runtime Software** refers to software executing -at the highest secure privileged mode, which is EL3 in AArch64 or Secure SVC/ -Monitor mode in AArch32, and provides runtime services to the non-secure world. -The runtime service request is made via SMC (Secure Monitor Call) and the call -must adhere to `SMCCC`_. In AArch32, EL3 Runtime Software may additionally -include Trusted OS functionality. A minimal AArch32 Secure Payload, SP-MIN, is -provided in Trusted Firmware-A (TF-A) to illustrate the usage and integration -of the PSCI library. The description of PSCI library interface and its -integration with EL3 Runtime Software in this document is targeted towards -AArch32 systems. - -Generic call sequence for PSCI Library interface (AArch32) ----------------------------------------------------------- - -The generic call sequence of PSCI Library interfaces (see -`PSCI Library Interface`_) during cold boot in AArch32 -system is described below: - -#. After cold reset, the EL3 Runtime Software performs its cold boot - initialization including the PSCI library pre-requisites mentioned in - `PSCI Library Interface`_, and also the necessary platform - setup. - -#. Call ``psci_setup()`` in Monitor mode. - -#. Optionally call ``psci_register_spd_pm_hook()`` to register callbacks to - do bookkeeping for the EL3 Runtime Software during power management. - -#. Call ``psci_prepare_next_non_secure_ctx()`` to initialize the non-secure CPU - context. - -#. Get the non-secure ``cpu_context_t`` for the current CPU by calling - ``cm_get_context()`` , then programming the registers in the non-secure - context and exiting to non-secure world. If the EL3 Runtime Software needs - additional configuration to be set for non-secure context, like routing - FIQs to the secure world, the values of the registers can be modified prior - to programming. See `PSCI CPU context management`_ for more - details on CPU context management. - -The generic call sequence of PSCI library interfaces during warm boot in -AArch32 systems is described below: - -#. After warm reset, the EL3 Runtime Software performs the necessary warm - boot initialization including the PSCI library pre-requisites mentioned in - `PSCI Library Interface`_ (Note that the Data cache - **must not** be enabled). - -#. Call ``psci_warmboot_entrypoint()`` in Monitor mode. This interface - initializes/restores the non-secure CPU context as well. - -#. Do step 5 of the cold boot call sequence described above. - -The generic call sequence of PSCI library interfaces on receipt of a PSCI SMC -on an AArch32 system is described below: - -#. On receipt of an SMC, save the register context as per `SMCCC`_. - -#. If the SMC function identifier corresponds to a SMC32 PSCI API, construct - the appropriate arguments and call the ``psci_smc_handler()`` interface. - The invocation may or may not return back to the caller depending on - whether the PSCI API resulted in power down of the CPU. - -#. If ``psci_smc_handler()`` returns, populate the return value in R0 (AArch32)/ - X0 (AArch64) and restore other registers as per `SMCCC`_. - -PSCI CPU context management ---------------------------- - -PSCI library is in charge of initializing/restoring the non-secure CPU system -registers according to `PSCI specification`_ during cold/warm boot. -This is referred to as ``PSCI CPU Context Management``. Registers that need to -be preserved across CPU power down/power up cycles are maintained in -``cpu_context_t`` data structure. The initialization of other non-secure CPU -system registers which do not require coordination with the EL3 Runtime -Software is done directly by the PSCI library (see ``cm_prepare_el3_exit()``). - -The EL3 Runtime Software is responsible for managing register context -during switch between Normal and Secure worlds. The register context to be -saved and restored depends on the mechanism used to trigger the world switch. -For example, if the world switch was triggered by an SMC call, then the -registers need to be saved and restored according to `SMCCC`_. In AArch64, -due to the tight integration with BL31, both BL31 and PSCI library -use the same ``cpu_context_t`` data structure for PSCI CPU context management -and register context management during world switch. This cannot be assumed -for AArch32 EL3 Runtime Software since most AArch32 Trusted OSes already implement -a mechanism for register context management during world switch. Hence, when -the PSCI library is integrated with a AArch32 EL3 Runtime Software, the -``cpu_context_t`` is stripped down for just PSCI CPU context management. - -During cold/warm boot, after invoking appropriate PSCI library interfaces, it -is expected that the EL3 Runtime Software will query the ``cpu_context_t`` and -write appropriate values to the corresponding system registers. This mechanism -resolves 2 additional problems for AArch32 EL3 Runtime Software: - -#. Values for certain system registers like SCR and SCTLR cannot be - unilaterally determined by PSCI library and need inputs from the EL3 - Runtime Software. Using ``cpu_context_t`` as an intermediary data store - allows EL3 Runtime Software to modify the register values appropriately - before programming them. - -#. The PSCI library provides appropriate LR and SPSR values (entrypoint - information) for exit into non-secure world. Using ``cpu_context_t`` as an - intermediary data store allows the EL3 Runtime Software to store these - values safely until it is ready for exit to non-secure world. - -Currently the ``cpu_context_t`` data structure for AArch32 stores the following -registers: R0 - R3, LR (R14), SCR, SPSR, SCTLR. - -The EL3 Runtime Software must implement accessors to get/set pointers -to CPU context ``cpu_context_t`` data and these are described in -`CPU Context management API`_. - -PSCI Library Interface ----------------------- - -The PSCI library implements the `PSCI Specification`_. The interfaces -to this library are declared in ``psci_lib.h`` and are as listed below: - -.. code:: c - - u_register_t psci_smc_handler(uint32_t smc_fid, u_register_t x1, - u_register_t x2, u_register_t x3, - u_register_t x4, void *cookie, - void *handle, u_register_t flags); - int psci_setup(const psci_lib_args_t *lib_args); - void psci_warmboot_entrypoint(void); - void psci_register_spd_pm_hook(const spd_pm_ops_t *pm); - void psci_prepare_next_non_secure_ctx(entry_point_info_t *next_image_info); - -The CPU context data 'cpu_context_t' is programmed to the registers differently -when PSCI is integrated with an AArch32 EL3 Runtime Software compared to -when the PSCI is integrated with an AArch64 EL3 Runtime Software (BL31). For -example, in the case of AArch64, there is no need to retrieve ``cpu_context_t`` -data and program the registers as it will done implicitly as part of -``el3_exit``. The description below of the PSCI interfaces is targeted at -integration with an AArch32 EL3 Runtime Software. - -The PSCI library is responsible for initializing/restoring the non-secure world -to an appropriate state after boot and may choose to directly program the -non-secure system registers. The PSCI generic code takes care not to directly -modify any of the system registers affecting the secure world and instead -returns the values to be programmed to these registers via ``cpu_context_t``. -The EL3 Runtime Software is responsible for programming those registers and -can use the proposed values provided in the ``cpu_context_t``, modifying the -values if required. - -PSCI library needs the flexibility to access both secure and non-secure -copies of banked registers. Hence it needs to be invoked in Monitor mode -for AArch32 and in EL3 for AArch64. The NS bit in SCR (in AArch32) or SCR_EL3 -(in AArch64) must be set to 0. Additional requirements for the PSCI library -interfaces are: - -- Instruction cache must be enabled -- Both IRQ and FIQ must be masked for the current CPU -- The page tables must be setup and the MMU enabled -- The C runtime environment must be setup and stack initialized -- The Data cache must be enabled prior to invoking any of the PSCI library - interfaces except for ``psci_warmboot_entrypoint()``. For - ``psci_warmboot_entrypoint()``, if the build option ``HW_ASSISTED_COHERENCY`` - is enabled however, data caches are expected to be enabled. - -Further requirements for each interface can be found in the interface -description. - -Interface : psci_setup() -~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : const psci_lib_args_t *lib_args - Return : void - -This function is to be called by the primary CPU during cold boot before -any other interface to the PSCI library. It takes ``lib_args``, a const pointer -to ``psci_lib_args_t``, as the argument. The ``psci_lib_args_t`` is a versioned -structure and is declared in ``psci_lib.h`` header as follows: - -.. code:: c - - typedef struct psci_lib_args { - /* The version information of PSCI Library Interface */ - param_header_t h; - /* The warm boot entrypoint function */ - mailbox_entrypoint_t mailbox_ep; - } psci_lib_args_t; - -The first field ``h``, of ``param_header_t`` type, provides the version -information. The second field ``mailbox_ep`` is the warm boot entrypoint address -and is used to configure the platform mailbox. Helper macros are provided in -``psci_lib.h`` to construct the ``lib_args`` argument statically or during -runtime. Prior to calling the ``psci_setup()`` interface, the platform setup for -cold boot must have completed. Major actions performed by this interface are: - -- Initializes architecture. -- Initializes PSCI power domain and state coordination data structures. -- Calls ``plat_setup_psci_ops()`` with warm boot entrypoint ``mailbox_ep`` as - argument. -- Calls ``cm_set_context_by_index()`` (see - `CPU Context management API`_) for all the CPUs in the - platform - -Interface : psci_prepare_next_non_secure_ctx() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : entry_point_info_t *next_image_info - Return : void - -After ``psci_setup()`` and prior to exit to the non-secure world, this function -must be called by the EL3 Runtime Software to initialize the non-secure world -context. The non-secure world entrypoint information ``next_image_info`` (first -argument) will be used to determine the non-secure context. After this function -returns, the EL3 Runtime Software must retrieve the ``cpu_context_t`` (using -cm_get_context()) for the current CPU and program the registers prior to exit -to the non-secure world. - -Interface : psci_register_spd_pm_hook() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : const spd_pm_ops_t * - Return : void - -As explained in `Secure payload power management callback`_, -the EL3 Runtime Software may want to perform some bookkeeping during power -management operations. This function is used to register the ``spd_pm_ops_t`` -(first argument) callbacks with the PSCI library which will be called -appropriately during power management. Calling this function is optional and -need to be called by the primary CPU during the cold boot sequence after -``psci_setup()`` has completed. - -Interface : psci_smc_handler() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : uint32_t smc_fid, u_register_t x1, - u_register_t x2, u_register_t x3, - u_register_t x4, void *cookie, - void *handle, u_register_t flags - Return : u_register_t - -This function is the top level handler for SMCs which fall within the -PSCI service range specified in `SMCCC`_. The function ID ``smc_fid`` (first -argument) determines the PSCI API to be called. The ``x1`` to ``x4`` (2nd to 5th -arguments), are the values of the registers r1 - r4 (in AArch32) or x1 - x4 -(in AArch64) when the SMC is received. These are the arguments to PSCI API as -described in `PSCI spec`_. The 'flags' (8th argument) is a bit field parameter -and is detailed in 'smccc.h' header. It includes whether the call is from the -secure or non-secure world. The ``cookie`` (6th argument) and the ``handle`` -(7th argument) are not used and are reserved for future use. - -The return value from this interface is the return value from the underlying -PSCI API corresponding to ``smc_fid``. This function may not return back to the -caller if PSCI API causes power down of the CPU. In this case, when the CPU -wakes up, it will start execution from the warm reset address. - -Interface : psci_warmboot_entrypoint() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - Argument : void - Return : void - -This function performs the warm boot initialization/restoration as mandated by -`PSCI spec`_. For AArch32, on wakeup from power down the CPU resets to secure SVC -mode and the EL3 Runtime Software must perform the prerequisite initializations -mentioned at top of this section. This function must be called with Data cache -disabled (unless build option ``HW_ASSISTED_COHERENCY`` is enabled) but with MMU -initialized and enabled. The major actions performed by this function are: - -- Invalidates the stack and enables the data cache. -- Initializes architecture and PSCI state coordination. -- Restores/Initializes the peripheral drivers to the required state via - appropriate ``plat_psci_ops_t`` hooks -- Restores the EL3 Runtime Software context via appropriate ``spd_pm_ops_t`` - callbacks. -- Restores/Initializes the non-secure context and populates the - ``cpu_context_t`` for the current CPU. - -Upon the return of this function, the EL3 Runtime Software must retrieve the -non-secure ``cpu_context_t`` using ``cm_get_context()`` and program the registers -prior to exit to the non-secure world. - -EL3 Runtime Software dependencies ---------------------------------- - -The PSCI Library includes supporting frameworks like context management, -cpu operations (cpu_ops) and per-cpu data framework. Other helper library -functions like bakery locks and spin locks are also included in the library. -The dependencies which must be fulfilled by the EL3 Runtime Software -for integration with PSCI library are described below. - -General dependencies -~~~~~~~~~~~~~~~~~~~~ - -The PSCI library being a Multiprocessor (MP) implementation, EL3 Runtime -Software must provide an SMC handling framework capable of MP adhering to -`SMCCC`_ specification. - -The EL3 Runtime Software must also export cache maintenance primitives -and some helper utilities for assert, print and memory operations as listed -below. The TF-A source tree provides implementations for all -these functions but the EL3 Runtime Software may use its own implementation. - -**Functions : assert(), memcpy(), memset(), printf()** - -These must be implemented as described in ISO C Standard. - -**Function : flush_dcache_range()** - -:: - - Argument : uintptr_t addr, size_t size - Return : void - -This function cleans and invalidates (flushes) the data cache for memory -at address ``addr`` (first argument) address and of size ``size`` (second argument). - -**Function : inv_dcache_range()** - -:: - - Argument : uintptr_t addr, size_t size - Return : void - -This function invalidates (flushes) the data cache for memory at address -``addr`` (first argument) address and of size ``size`` (second argument). - -**Function : do_panic()** - -:: - - Argument : void - Return : void - -This function will be called by the PSCI library on encountering a critical -failure that cannot be recovered from. This function **must not** return. - -CPU Context management API -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The CPU context management data memory is statically allocated by PSCI library -in BSS section. The PSCI library requires the EL3 Runtime Software to implement -APIs to store and retrieve pointers to this CPU context data. SP-MIN -demonstrates how these APIs can be implemented but the EL3 Runtime Software can -choose a more optimal implementation (like dedicating the secure TPIDRPRW -system register (in AArch32) for storing these pointers). - -**Function : cm_set_context_by_index()** - -:: - - Argument : unsigned int cpu_idx, void *context, unsigned int security_state - Return : void - -This function is called during cold boot when the ``psci_setup()`` PSCI library -interface is called. - -This function must store the pointer to the CPU context data, ``context`` (2nd -argument), for the specified ``security_state`` (3rd argument) and CPU identified -by ``cpu_idx`` (first argument). The ``security_state`` will always be non-secure -when called by PSCI library and this argument is retained for compatibility -with BL31. The ``cpu_idx`` will correspond to the index returned by the -``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. - -The actual method of storing the ``context`` pointers is implementation specific. -For example, SP-MIN stores the pointers in the array ``sp_min_cpu_ctx_ptr`` -declared in ``sp_min_main.c``. - -**Function : cm_get_context()** - -:: - - Argument : uint32_t security_state - Return : void * - -This function must return the pointer to the ``cpu_context_t`` structure for -the specified ``security_state`` (first argument) for the current CPU. The caller -must ensure that ``cm_set_context_by_index`` is called first and the appropriate -context pointers are stored prior to invoking this API. The ``security_state`` -will always be non-secure when called by PSCI library and this argument -is retained for compatibility with BL31. - -**Function : cm_get_context_by_index()** - -:: - - Argument : unsigned int cpu_idx, unsigned int security_state - Return : void * - -This function must return the pointer to the ``cpu_context_t`` structure for -the specified ``security_state`` (second argument) for the CPU identified by -``cpu_idx`` (first argument). The caller must ensure that -``cm_set_context_by_index`` is called first and the appropriate context -pointers are stored prior to invoking this API. The ``security_state`` will -always be non-secure when called by PSCI library and this argument is -retained for compatibility with BL31. The ``cpu_idx`` will correspond to the -index returned by the ``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. - -Platform API -~~~~~~~~~~~~ - -The platform layer abstracts the platform-specific details from the generic -PSCI library. The following platform APIs/macros must be defined by the EL3 -Runtime Software for integration with the PSCI library. - -The mandatory platform APIs are: - -- plat_my_core_pos -- plat_core_pos_by_mpidr -- plat_get_syscnt_freq2 -- plat_get_power_domain_tree_desc -- plat_setup_psci_ops -- plat_reset_handler -- plat_panic_handler -- plat_get_my_stack - -The mandatory platform macros are: - -- PLATFORM_CORE_COUNT -- PLAT_MAX_PWR_LVL -- PLAT_NUM_PWR_DOMAINS -- CACHE_WRITEBACK_GRANULE -- PLAT_MAX_OFF_STATE -- PLAT_MAX_RET_STATE -- PLAT_MAX_PWR_LVL_STATES (optional) -- PLAT_PCPU_DATA_SIZE (optional) - -The details of these APIs/macros can be found in `Porting Guide`_. - -All platform specific operations for power management are done via -``plat_psci_ops_t`` callbacks registered by the platform when -``plat_setup_psci_ops()`` API is called. The description of each of -the callbacks in ``plat_psci_ops_t`` can be found in PSCI section of the -`Porting Guide`_. If any these callbacks are not registered, then the -PSCI API associated with that callback will not be supported by PSCI -library. - -Secure payload power management callback -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -During PSCI power management operations, the EL3 Runtime Software may -need to perform some bookkeeping, and PSCI library provides -``spd_pm_ops_t`` callbacks for this purpose. These hooks must be -populated and registered by using ``psci_register_spd_pm_hook()`` PSCI -library interface. - -Typical bookkeeping during PSCI power management calls include save/restore -of the EL3 Runtime Software context. Also if the EL3 Runtime Software makes -use of secure interrupts, then these interrupts must also be managed -appropriately during CPU power down/power up. Any secure interrupt targeted -to the current CPU must be disabled or re-targeted to other running CPU prior -to power down of the current CPU. During power up, these interrupt can be -enabled/re-targeted back to the current CPU. - -.. code:: c - - typedef struct spd_pm_ops { - void (*svc_on)(u_register_t target_cpu); - int32_t (*svc_off)(u_register_t __unused); - void (*svc_suspend)(u_register_t max_off_pwrlvl); - void (*svc_on_finish)(u_register_t __unused); - void (*svc_suspend_finish)(u_register_t max_off_pwrlvl); - int32_t (*svc_migrate)(u_register_t from_cpu, u_register_t to_cpu); - int32_t (*svc_migrate_info)(u_register_t *resident_cpu); - void (*svc_system_off)(void); - void (*svc_system_reset)(void); - } spd_pm_ops_t; - -A brief description of each callback is given below: - -- svc_on, svc_off, svc_on_finish - - The ``svc_on``, ``svc_off`` callbacks are called during PSCI_CPU_ON, - PSCI_CPU_OFF APIs respectively. The ``svc_on_finish`` is called when the - target CPU of PSCI_CPU_ON API powers up and executes the - ``psci_warmboot_entrypoint()`` PSCI library interface. - -- svc_suspend, svc_suspend_finish - - The ``svc_suspend`` callback is called during power down bu either - PSCI_SUSPEND or PSCI_SYSTEM_SUSPEND APIs. The ``svc_suspend_finish`` is - called when the CPU wakes up from suspend and executes the - ``psci_warmboot_entrypoint()`` PSCI library interface. The ``max_off_pwrlvl`` - (first parameter) denotes the highest power domain level being powered down - to or woken up from suspend. - -- svc_system_off, svc_system_reset - - These callbacks are called during PSCI_SYSTEM_OFF and PSCI_SYSTEM_RESET - PSCI APIs respectively. - -- svc_migrate_info - - This callback is called in response to PSCI_MIGRATE_INFO_TYPE or - PSCI_MIGRATE_INFO_UP_CPU APIs. The return value of this callback must - correspond to the return value of PSCI_MIGRATE_INFO_TYPE API as described - in `PSCI spec`_. If the secure payload is a Uniprocessor (UP) - implementation, then it must update the mpidr of the CPU it is resident in - via ``resident_cpu`` (first argument). The updates to ``resident_cpu`` is - ignored if the secure payload is a multiprocessor (MP) implementation. - -- svc_migrate - - This callback is only relevant if the secure payload in EL3 Runtime - Software is a Uniprocessor (UP) implementation and supports migration from - the current CPU ``from_cpu`` (first argument) to another CPU ``to_cpu`` - (second argument). This callback is called in response to PSCI_MIGRATE - API. This callback is never called if the secure payload is a - Multiprocessor (MP) implementation. - -CPU operations -~~~~~~~~~~~~~~ - -The CPU operations (cpu_ops) framework implement power down sequence specific -to the CPU and the details of which can be found in the -``CPU specific operations framework`` section of `Firmware Design`_. The TF-A -tree implements the ``cpu_ops`` for various supported CPUs and the EL3 Runtime -Software needs to include the required ``cpu_ops`` in its build. The start and -end of the ``cpu_ops`` descriptors must be exported by the EL3 Runtime Software -via the ``__CPU_OPS_START__`` and ``__CPU_OPS_END__`` linker symbols. - -The ``cpu_ops`` descriptors also include reset sequences and may include errata -workarounds for the CPU. The EL3 Runtime Software can choose to call this -during cold/warm reset if it does not implement its own reset sequence/errata -workarounds. - --------------- - -*Copyright (c) 2016-2018, Arm Limited and Contributors. All rights reserved.* - -.. _PSCI spec: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf -.. _SMCCC: https://silver.arm.com/download/ARM_and_AMBA_Architecture/AR570-DA-80002-r0p0-00rel0/ARM_DEN0028A_SMC_Calling_Convention.pdf -.. _PSCI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf -.. _PSCI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf -.. _Porting Guide: porting-guide.rst -.. _Firmware Design: ./firmware-design.rst diff --git a/docs/psci-pd-tree.rst b/docs/psci-pd-tree.rst deleted file mode 100644 index 9653725..0000000 --- a/docs/psci-pd-tree.rst +++ /dev/null @@ -1,312 +0,0 @@ -PSCI Power Domain Tree design -============================= - - -.. section-numbering:: - :suffix: . - -.. contents:: - --------------- - -Requirements ------------- - -#. A platform must export the ``plat_get_aff_count()`` and - ``plat_get_aff_state()`` APIs to enable the generic PSCI code to - populate a tree that describes the hierarchy of power domains in the - system. This approach is inflexible because a change to the topology - requires a change in the code. - - It would be much simpler for the platform to describe its power domain tree - in a data structure. - -#. The generic PSCI code generates MPIDRs in order to populate the power domain - tree. It also uses an MPIDR to find a node in the tree. The assumption that - a platform will use exactly the same MPIDRs as generated by the generic PSCI - code is not scalable. The use of an MPIDR also restricts the number of - levels in the power domain tree to four. - - Therefore, there is a need to decouple allocation of MPIDRs from the - mechanism used to populate the power domain topology tree. - -#. The current arrangement of the power domain tree requires a binary search - over the sibling nodes at a particular level to find a specified power - domain node. During a power management operation, the tree is traversed from - a 'start' to an 'end' power level. The binary search is required to find the - node at each level. The natural way to perform this traversal is to - start from a leaf node and follow the parent node pointer to reach the end - level. - - Therefore, there is a need to define data structures that implement the tree in - a way which facilitates such a traversal. - -#. The attributes of a core power domain differ from the attributes of power - domains at higher levels. For example, only a core power domain can be identified - using an MPIDR. There is no requirement to perform state coordination while - performing a power management operation on the core power domain. - - Therefore, there is a need to implement the tree in a way which facilitates this - distinction between a leaf and non-leaf node and any associated - optimizations. - --------------- - -Design ------- - -Describing a power domain tree -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To fulfill requirement 1., the existing platform APIs -``plat_get_aff_count()`` and ``plat_get_aff_state()`` have been -removed. A platform must define an array of unsigned chars such that: - -#. The first entry in the array specifies the number of power domains at the - highest power level implemented in the platform. This caters for platforms - where the power domain tree does not have a single root node, for example, - the FVP has two cluster power domains at the highest level (1). - -#. Each subsequent entry corresponds to a power domain and contains the number - of power domains that are its direct children. - -#. The size of the array minus the first entry will be equal to the number of - non-leaf power domains. - -#. The value in each entry in the array is used to find the number of entries - to consider at the next level. The sum of the values (number of children) of - all the entries at a level specifies the number of entries in the array for - the next level. - -The following example power domain topology tree will be used to describe the -above text further. The leaf and non-leaf nodes in this tree have been numbered -separately. - -:: - - +-+ - |0| - +-+ - / \ - / \ - / \ - / \ - / \ - / \ - / \ - / \ - / \ - / \ - +-+ +-+ - |1| |2| - +-+ +-+ - / \ / \ - / \ / \ - / \ / \ - / \ / \ - +-+ +-+ +-+ +-+ - |3| |4| |5| |6| - +-+ +-+ +-+ +-+ - +---+-----+ +----+----| +----+----+ +----+-----+-----+ - | | | | | | | | | | | | | - | | | | | | | | | | | | | - v v v v v v v v v v v v v - +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+ - |0| |1| |2| |3| |4| |5| |6| |7| |8| |9| |10| |11| |12| - +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+ - -This tree is defined by the platform as the array described above as follows: - -:: - - #define PLAT_NUM_POWER_DOMAINS 20 - #define PLATFORM_CORE_COUNT 13 - #define PSCI_NUM_NON_CPU_PWR_DOMAINS \ - (PLAT_NUM_POWER_DOMAINS - PLATFORM_CORE_COUNT) - - unsigned char plat_power_domain_tree_desc[] = { 1, 2, 2, 2, 3, 3, 3, 4}; - -Removing assumptions about MPIDRs used in a platform -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To fulfill requirement 2., it is assumed that the platform assigns a -unique number (core index) between ``0`` and ``PLAT_CORE_COUNT - 1`` to each core -power domain. MPIDRs could be allocated in any manner and will not be used to -populate the tree. - -``plat_core_pos_by_mpidr(mpidr)`` will return the core index for the core -corresponding to the MPIDR. It will return an error (-1) if an MPIDR is passed -which is not allocated or corresponds to an absent core. The semantics of this -platform API have changed since it is required to validate the passed MPIDR. It -has been made a mandatory API as a result. - -Another mandatory API, ``plat_my_core_pos()`` has been added to return the core -index for the calling core. This API provides a more lightweight mechanism to get -the index since there is no need to validate the MPIDR of the calling core. - -The platform should assign the core indices (as illustrated in the diagram above) -such that, if the core nodes are numbered from left to right, then the index -for a core domain will be the same as the index returned by -``plat_core_pos_by_mpidr()`` or ``plat_my_core_pos()`` for that core. This -relationship allows the core nodes to be allocated in a separate array -(requirement 4.) during ``psci_setup()`` in such an order that the index of the -core in the array is the same as the return value from these APIs. - -Dealing with holes in MPIDR allocation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For platforms where the number of allocated MPIDRs is equal to the number of -core power domains, for example, Juno and FVPs, the logic to convert an MPIDR to -a core index should remain unchanged. Both Juno and FVP use a simple collision -proof hash function to do this. - -It is possible that on some platforms, the allocation of MPIDRs is not -contiguous or certain cores have been disabled. This essentially means that the -MPIDRs have been sparsely allocated, that is, the size of the range of MPIDRs -used by the platform is not equal to the number of core power domains. - -The platform could adopt one of the following approaches to deal with this -scenario: - -#. Implement more complex logic to convert a valid MPIDR to a core index while - maintaining the relationship described earlier. This means that the power - domain tree descriptor will not describe any core power domains which are - disabled or absent. Entries will not be allocated in the tree for these - domains. - -#. Treat unallocated MPIDRs and disabled cores as absent but still describe them - in the power domain descriptor, that is, the number of core nodes described - is equal to the size of the range of MPIDRs allocated. This approach will - lead to memory wastage since entries will be allocated in the tree but will - allow use of a simpler logic to convert an MPIDR to a core index. - -Traversing through and distinguishing between core and non-core power domains -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To fulfill requirement 3 and 4, separate data structures have been defined -to represent leaf and non-leaf power domain nodes in the tree. - -.. code:: c - - /******************************************************************************* - * The following two data structures implement the power domain tree. The tree - * is used to track the state of all the nodes i.e. power domain instances - * described by the platform. The tree consists of nodes that describe CPU power - * domains i.e. leaf nodes and all other power domains which are parents of a - * CPU power domain i.e. non-leaf nodes. - ******************************************************************************/ - typedef struct non_cpu_pwr_domain_node { - /* - * Index of the first CPU power domain node level 0 which has this node - * as its parent. - */ - unsigned int cpu_start_idx; - - /* - * Number of CPU power domains which are siblings of the domain indexed - * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx - * -> cpu_start_idx + ncpus' have this node as their parent. - */ - unsigned int ncpus; - - /* Index of the parent power domain node */ - unsigned int parent_node; - - ----- - } non_cpu_pd_node_t; - - typedef struct cpu_pwr_domain_node { - u_register_t mpidr; - - /* Index of the parent power domain node */ - unsigned int parent_node; - - ----- - } cpu_pd_node_t; - -The power domain tree is implemented as a combination of the following data -structures. - -:: - - non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS]; - cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT]; - -Populating the power domain tree -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``populate_power_domain_tree()`` function in ``psci_setup.c`` implements the -algorithm to parse the power domain descriptor exported by the platform to -populate the two arrays. It is essentially a breadth-first-search. The nodes for -each level starting from the root are laid out one after another in the -``psci_non_cpu_pd_nodes`` and ``psci_cpu_pd_nodes`` arrays as follows: - -:: - - psci_non_cpu_pd_nodes -> [[Level 3 nodes][Level 2 nodes][Level 1 nodes]] - psci_cpu_pd_nodes -> [Level 0 nodes] - -For the example power domain tree illustrated above, the ``psci_cpu_pd_nodes`` -will be populated as follows. The value in each entry is the index of the parent -node. Other fields have been ignored for simplicity. - -:: - - +-------------+ ^ - CPU0 | 3 | | - +-------------+ | - CPU1 | 3 | | - +-------------+ | - CPU2 | 3 | | - +-------------+ | - CPU3 | 4 | | - +-------------+ | - CPU4 | 4 | | - +-------------+ | - CPU5 | 4 | | PLATFORM_CORE_COUNT - +-------------+ | - CPU6 | 5 | | - +-------------+ | - CPU7 | 5 | | - +-------------+ | - CPU8 | 5 | | - +-------------+ | - CPU9 | 6 | | - +-------------+ | - CPU10 | 6 | | - +-------------+ | - CPU11 | 6 | | - +-------------+ | - CPU12 | 6 | v - +-------------+ - -The ``psci_non_cpu_pd_nodes`` array will be populated as follows. The value in -each entry is the index of the parent node. - -:: - - +-------------+ ^ - PD0 | -1 | | - +-------------+ | - PD1 | 0 | | - +-------------+ | - PD2 | 0 | | - +-------------+ | - PD3 | 1 | | PLAT_NUM_POWER_DOMAINS - - +-------------+ | PLATFORM_CORE_COUNT - PD4 | 1 | | - +-------------+ | - PD5 | 2 | | - +-------------+ | - PD6 | 2 | | - +-------------+ v - -Each core can find its node in the ``psci_cpu_pd_nodes`` array using the -``plat_my_core_pos()`` function. When a core is turned on, the normal world -provides an MPIDR. The ``plat_core_pos_by_mpidr()`` function is used to validate -the MPIDR before using it to find the corresponding core node. The non-core power -domain nodes do not need to be identified. - --------------- - -*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* diff --git a/docs/psci-performance-juno.rst b/docs/psci-performance-juno.rst deleted file mode 100644 index caed8bf..0000000 --- a/docs/psci-performance-juno.rst +++ /dev/null @@ -1,288 +0,0 @@ -PSCI Performance Measurements on Arm Juno Development Platform -============================================================== - -This document summarises the findings of performance measurements of key -operations in the ARM Trusted Firmware (TF) Power State Coordination Interface -(PSCI) implementation, using the in-built Performance Measurement Framework -(PMF) and runtime instrumentation timestamps. - -Method ------- - -We used the `Juno R1 platform`_ for these tests, which has 4 x Cortex-A53 and 2 -x Cortex-A57 clusters running at the following frequencies: - -+-----------------+--------------------+ -| Domain | Frequency (MHz) | -+=================+====================+ -| Cortex-A57 | 900 (nominal) | -+-----------------+--------------------+ -| Cortex-A53 | 650 (underdrive) | -+-----------------+--------------------+ -| AXI subsystem | 533 | -+-----------------+--------------------+ - -Juno supports CPU, cluster and system power down states, corresponding to power -levels 0, 1 and 2 respectively. It does not support any retention states. - -We used the upstream `TF master as of 31/01/2017`_, building the platform using -the ``ENABLE_RUNTIME_INSTRUMENTATION`` option: - -:: - - make PLAT=juno ENABLE_RUNTIME_INSTRUMENTATION=1 \ - SCP_BL2= \ - BL33= \ - all fip - -When using the debug build of TF, there was no noticeable difference in the -results. - -The tests are based on an ARM-internal test framework. The release build of this -framework was used because the results in the debug build became skewed; the -console output prevented some of the tests from executing in parallel. - -The tests consist of both parallel and sequential tests, which are broadly -described as follows: - -- **Parallel Tests** This type of test powers on all the non-lead CPUs and - brings them and the lead CPU to a common synchronization point. The lead CPU - then initiates the test on all CPUs in parallel. - -- **Sequential Tests** This type of test powers on each non-lead CPU in - sequence. The lead CPU initiates the test on a non-lead CPU then waits for the - test to complete before proceeding to the next non-lead CPU. The lead CPU then - executes the test on itself. - -In the results below, CPUs 0-3 refer to CPUs in the little cluster (A53) and -CPUs 4-5 refer to CPUs in the big cluster (A57). In all cases CPU 4 is the lead -CPU. - -``PSCI_ENTRY`` refers to the time taken from entering the TF PSCI implementation -to the point the hardware enters the low power state (WFI). Referring to the TF -runtime instrumentation points, this corresponds to: -``(RT_INSTR_ENTER_HW_LOW_PWR - RT_INSTR_ENTER_PSCI)``. - -``PSCI_EXIT`` refers to the time taken from the point the hardware exits the low -power state to exiting the TF PSCI implementation. This corresponds to: -``(RT_INSTR_EXIT_PSCI - RT_INSTR_EXIT_HW_LOW_PWR)``. - -``CFLUSH_OVERHEAD`` refers to the part of ``PSCI_ENTRY`` taken to flush the -caches. This corresponds to: ``(RT_INSTR_EXIT_CFLUSH - RT_INSTR_ENTER_CFLUSH)``. - -Note there is very little variance observed in the values given (~1us), although -the values for each CPU are sometimes interchanged, depending on the order in -which locks are acquired. Also, there is very little variance observed between -executing the tests sequentially in a single boot or rebooting between tests. - -Given that runtime instrumentation using PMF is invasive, there is a small -(unquantified) overhead on the results. PMF uses the generic counter for -timestamps, which runs at 50MHz on Juno. - -Results and Commentary ----------------------- - -``CPU_SUSPEND`` to deepest power level on all CPUs in parallel -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -+-------+---------------------+--------------------+--------------------------+ -| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | -+=======+=====================+====================+==========================+ -| 0 | 27 | 20 | 5 | -+-------+---------------------+--------------------+--------------------------+ -| 1 | 114 | 86 | 5 | -+-------+---------------------+--------------------+--------------------------+ -| 2 | 202 | 58 | 5 | -+-------+---------------------+--------------------+--------------------------+ -| 3 | 375 | 29 | 94 | -+-------+---------------------+--------------------+--------------------------+ -| 4 | 20 | 22 | 6 | -+-------+---------------------+--------------------+--------------------------+ -| 5 | 290 | 18 | 206 | -+-------+---------------------+--------------------+--------------------------+ - -A large variance in ``PSCI_ENTRY`` and ``PSCI_EXIT`` times across CPUs is -observed due to TF PSCI lock contention. In the worst case, CPU 3 has to wait -for the 3 other CPUs in the cluster (0-2) to complete ``PSCI_ENTRY`` and release -the lock before proceeding. - -The ``CFLUSH_OVERHEAD`` times for CPUs 3 and 5 are higher because they are the -last CPUs in their respective clusters to power down, therefore both the L1 and -L2 caches are flushed. - -The ``CFLUSH_OVERHEAD`` time for CPU 5 is a lot larger than that for CPU 3 -because the L2 cache size for the big cluster is lot larger (2MB) compared to -the little cluster (1MB). - -``CPU_SUSPEND`` to power level 0 on all CPUs in parallel -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -+-------+---------------------+--------------------+--------------------------+ -| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | -+=======+=====================+====================+==========================+ -| 0 | 116 | 14 | 8 | -+-------+---------------------+--------------------+--------------------------+ -| 1 | 204 | 14 | 8 | -+-------+---------------------+--------------------+--------------------------+ -| 2 | 287 | 13 | 8 | -+-------+---------------------+--------------------+--------------------------+ -| 3 | 376 | 13 | 9 | -+-------+---------------------+--------------------+--------------------------+ -| 4 | 29 | 15 | 7 | -+-------+---------------------+--------------------+--------------------------+ -| 5 | 21 | 15 | 8 | -+-------+---------------------+--------------------+--------------------------+ - -There is no lock contention in TF generic code at power level 0 but the large -variance in ``PSCI_ENTRY`` times across CPUs is due to lock contention in Juno -platform code. The platform lock is used to mediate access to a single SCP -communication channel. This is compounded by the SCP firmware waiting for each -AP CPU to enter WFI before making the channel available to other CPUs, which -effectively serializes the SCP power down commands from all CPUs. - -On platforms with a more efficient CPU power down mechanism, it should be -possible to make the ``PSCI_ENTRY`` times smaller and consistent. - -The ``PSCI_EXIT`` times are consistent across all CPUs because TF does not -require locks at power level 0. - -The ``CFLUSH_OVERHEAD`` times for all CPUs are small and consistent since only -the cache associated with power level 0 is flushed (L1). - -``CPU_SUSPEND`` to deepest power level on all CPUs in sequence -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -+-------+---------------------+--------------------+--------------------------+ -| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | -+=======+=====================+====================+==========================+ -| 0 | 114 | 20 | 94 | -+-------+---------------------+--------------------+--------------------------+ -| 1 | 114 | 20 | 94 | -+-------+---------------------+--------------------+--------------------------+ -| 2 | 114 | 20 | 94 | -+-------+---------------------+--------------------+--------------------------+ -| 3 | 114 | 20 | 94 | -+-------+---------------------+--------------------+--------------------------+ -| 4 | 195 | 22 | 180 | -+-------+---------------------+--------------------+--------------------------+ -| 5 | 21 | 17 | 6 | -+-------+---------------------+--------------------+--------------------------+ - -The ``CLUSH_OVERHEAD`` times for lead CPU 4 and all CPUs in the non-lead cluster -are large because all other CPUs in the cluster are powered down during the -test. The ``CPU_SUSPEND`` call powers down to the cluster level, requiring a -flush of both L1 and L2 caches. - -The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little -CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared -to the little cluster (1MB). - -The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are low because lead -CPU 4 continues to run while CPU 5 is suspended. Hence CPU 5 only powers down to -level 0, which only requires L1 cache flush. - -``CPU_SUSPEND`` to power level 0 on all CPUs in sequence -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -+-------+---------------------+--------------------+--------------------------+ -| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | -+=======+=====================+====================+==========================+ -| 0 | 22 | 14 | 5 | -+-------+---------------------+--------------------+--------------------------+ -| 1 | 22 | 14 | 5 | -+-------+---------------------+--------------------+--------------------------+ -| 2 | 21 | 14 | 5 | -+-------+---------------------+--------------------+--------------------------+ -| 3 | 22 | 14 | 5 | -+-------+---------------------+--------------------+--------------------------+ -| 4 | 17 | 14 | 6 | -+-------+---------------------+--------------------+--------------------------+ -| 5 | 18 | 15 | 6 | -+-------+---------------------+--------------------+--------------------------+ - -Here the times are small and consistent since there is no contention and it is -only necessary to flush the cache to power level 0 (L1). This is the best case -scenario. - -The ``PSCI_ENTRY`` times for CPUs in the big cluster are slightly smaller than -for the CPUs in little cluster due to greater CPU performance. - -The ``PSCI_EXIT`` times are generally lower than in the last test because the -cluster remains powered on throughout the test and there is less code to execute -on power on (for example, no need to enter CCI coherency) - -``CPU_OFF`` on all non-lead CPUs in sequence then ``CPU_SUSPEND`` on lead CPU to deepest power level -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The test sequence here is as follows: - -1. Call ``CPU_ON`` and ``CPU_OFF`` on each non-lead CPU in sequence. - -2. Program wake up timer and suspend the lead CPU to the deepest power level. - -3. Call ``CPU_ON`` on non-lead CPU to get the timestamps from each CPU. - -+-------+---------------------+--------------------+--------------------------+ -| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | -+=======+=====================+====================+==========================+ -| 0 | 110 | 28 | 93 | -+-------+---------------------+--------------------+--------------------------+ -| 1 | 110 | 28 | 93 | -+-------+---------------------+--------------------+--------------------------+ -| 2 | 110 | 28 | 93 | -+-------+---------------------+--------------------+--------------------------+ -| 3 | 111 | 28 | 93 | -+-------+---------------------+--------------------+--------------------------+ -| 4 | 195 | 22 | 181 | -+-------+---------------------+--------------------+--------------------------+ -| 5 | 20 | 23 | 6 | -+-------+---------------------+--------------------+--------------------------+ - -The ``CFLUSH_OVERHEAD`` times for all little CPUs are large because all other -CPUs in that cluster are powerered down during the test. The ``CPU_OFF`` call -powers down to the cluster level, requiring a flush of both L1 and L2 caches. - -The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are small because -lead CPU 4 is running and CPU 5 only powers down to level 0, which only requires -an L1 cache flush. - -The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little -CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared -to the little cluster (1MB). - -The ``PSCI_EXIT`` times for CPUs in the big cluster are slightly smaller than -for CPUs in the little cluster due to greater CPU performance. These times -generally are greater than the ``PSCI_EXIT`` times in the ``CPU_SUSPEND`` tests -because there is more code to execute in the "on finisher" compared to the -"suspend finisher" (for example, GIC redistributor register programming). - -``PSCI_VERSION`` on all CPUs in parallel -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Since very little code is associated with ``PSCI_VERSION``, this test -approximates the round trip latency for handling a fast SMC at EL3 in TF. - -+-------+-------------------+ -| CPU | TOTAL TIME (ns) | -+=======+===================+ -| 0 | 3020 | -+-------+-------------------+ -| 1 | 2940 | -+-------+-------------------+ -| 2 | 2980 | -+-------+-------------------+ -| 3 | 3060 | -+-------+-------------------+ -| 4 | 520 | -+-------+-------------------+ -| 5 | 720 | -+-------+-------------------+ - -The times for the big CPUs are less than the little CPUs due to greater CPU -performance. - -We suspect the time for lead CPU 4 is shorter than CPU 5 due to subtle cache -effects, given that these measurements are at the nano-second level. - -.. _Juno R1 platform: https://www.arm.com/files/pdf/Juno_r1_ARM_Dev_datasheet.pdf -.. _TF master as of 31/01/2017: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/?id=c38b36d diff --git a/docs/ras.rst b/docs/ras.rst deleted file mode 100644 index ac4d019..0000000 --- a/docs/ras.rst +++ /dev/null @@ -1,258 +0,0 @@ -RAS support in Trusted Firmware-A -================================= - -.. section-numbering:: - :suffix: . - -.. contents:: - :depth: 2 - -.. |EHF| replace:: Exception Handling Framework -.. |TF-A| replace:: Trusted Firmware-A - -This document describes |TF-A| support for Arm Reliability, Availability, and -Serviceability (RAS) extensions. RAS is a mandatory extension for Armv8.2 and -later CPUs, and also an optional extension to the base Armv8.0 architecture. - -In conjunction with the |EHF|, support for RAS extension enables firmware-first -paradigm for handling platform errors: exceptions resulting from errors are -routed to and handled in EL3. Said errors are Synchronous External Abort (SEA), -Asynchronous External Abort (signalled as SErrors), Fault Handling and Error -Recovery interrupts. The |EHF| document mentions various `error handling -use-cases`__. - -.. __: exception-handling.rst#delegation-use-cases - -For the description of Arm RAS extensions, Standard Error Records, and the -precise definition of RAS terminology, please refer to the Arm Architecture -Reference Manual. The rest of this document assumes familiarity with -architecture and terminology. - -Overview --------- - -As mentioned above, the RAS support in |TF-A| enables routing to and handling of -exceptions resulting from platform errors in EL3. It allows the platform to -define an External Abort handler, and to register RAS nodes and interrupts. RAS -framework also provides `helpers`__ for accessing Standard Error Records as -introduced by the RAS extensions. - -.. __: `Standard Error Record helpers`_ - -The build option ``RAS_EXTENSION`` when set to ``1`` includes the RAS in run -time firmware; ``EL3_EXCEPTION_HANDLING`` and ``HANDLE_EA_EL3_FIRST`` must also -be set ``1``. - -.. _ras-figure: - -.. image:: draw.io/ras.svg - -See more on `Engaging the RAS framework`_. - -Platform APIs -------------- - -The RAS framework allows the platform to define handlers for External Abort, -Uncontainable Errors, Double Fault, and errors rising from EL3 execution. Please -refer to the porting guide for the `RAS platform API descriptions`__. - -.. __: porting-guide.rst#external-abort-handling-and-ras-support - -Registering RAS error records ------------------------------ - -RAS nodes are components in the system capable of signalling errors to PEs -through one one of the notification mechanisms—SEAs, SErrors, or interrupts. RAS -nodes contain one or more error records, which are registers through which the -nodes advertise various properties of the signalled error. Arm recommends that -error records are implemented in the Standard Error Record format. The RAS -architecture allows for error records to be accessible via system or -memory-mapped registers. - -The platform should enumerate the error records providing for each of them: - -- A handler to probe error records for errors; -- When the probing identifies an error, a handler to handle it; -- For memory-mapped error record, its base address and size in KB; for a system - register-accessed record, the start index of the record and number of - continuous records from that index; -- Any node-specific auxiliary data. - -With this information supplied, when the run time firmware receives one of the -notification mechanisms, the RAS framework can iterate through and probe error -records for error, and invoke the appropriate handler to handle it. - -The RAS framework provides the macros to populate error record information. The -macros are versioned, and the latest version as of this writing is 1. These -macros create a structure of type ``struct err_record_info`` from its arguments, -which are later passed to probe and error handlers. - -For memory-mapped error records: - -.. code:: c - - ERR_RECORD_MEMMAP_V1(base_addr, size_num_k, probe, handler, aux) - -And, for system register ones: - -.. code:: c - - ERR_RECORD_SYSREG_V1(idx_start, num_idx, probe, handler, aux) - -The probe handler must have the following prototype: - -.. code:: c - - typedef int (*err_record_probe_t)(const struct err_record_info *info, - int *probe_data); - -The probe handler must return a non-zero value if an error was detected, or 0 -otherwise. The ``probe_data`` output parameter can be used to pass any useful -information resulting from probe to the error handler (see `below`__). For -example, it could return the index of the record. - -.. __: `Standard Error Record helpers`_ - -The error handler must have the following prototype: - -.. code:: c - - typedef int (*err_record_handler_t)(const struct err_record_info *info, - int probe_data, const struct err_handler_data *const data); - -The ``data`` constant parameter describes the various properties of the error, -including the reason for the error, exception syndrome, and also ``flags``, -``cookie``, and ``handle`` parameters from the `top-level exception handler`__. - -.. __: interrupt-framework-design.rst#el3-interrupts - -The platform is expected populate an array using the macros above, and register -the it with the RAS framework using the macro ``REGISTER_ERR_RECORD_INFO()``, -passing it the name of the array describing the records. Note that the macro -must be used in the same file where the array is defined. - -Standard Error Record helpers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The |TF-A| RAS framework provides probe handlers for Standard Error Records, for -both memory-mapped and System Register accesses: - -.. code:: c - - int ras_err_ser_probe_memmap(const struct err_record_info *info, - int *probe_data); - - int ras_err_ser_probe_sysreg(const struct err_record_info *info, - int *probe_data); - -When the platform enumerates error records, for those records in the Standard -Error Record format, these helpers maybe used instead of rolling out their own. -Both helpers above: - -- Return non-zero value when an error is detected in a Standard Error Record; -- Set ``probe_data`` to the index of the error record upon detecting an error. - -Registering RAS interrupts --------------------------- - -RAS nodes can signal errors to the PE by raising Fault Handling and/or Error -Recovery interrupts. For the firmware-first handling paradigm for interrupts to -work, the platform must setup and register with |EHF|. See `Interaction with -Exception Handling Framework`_. - -For each RAS interrupt, the platform has to provide structure of type ``struct -ras_interrupt``: - -- Interrupt number; -- The associated error record information (pointer to the corresponding - ``struct err_record_info``); -- Optionally, a cookie. - -The platform is expected to define an array of ``struct ras_interrupt``, and -register it with the RAS framework using the macro -``REGISTER_RAS_INTERRUPTS()``, passing it the name of the array. Note that the -macro must be used in the same file where the array is defined. - -The array of ``struct ras_interrupt`` must be sorted in the increasing order of -interrupt number. This allows for fast look of handlers in order to service RAS -interrupts. - -Double-fault handling ---------------------- - -A Double Fault condition arises when an error is signalled to the PE while -handling of a previously signalled error is still underway. When a Double Fault -condition arises, the Arm RAS extensions only require for handler to perform -orderly shutdown of the system, as recovery may be impossible. - -The RAS extensions part of Armv8.4 introduced new architectural features to deal -with Double Fault conditions, specifically, the introduction of ``NMEA`` and -``EASE`` bits to ``SCR_EL3`` register. These were introduced to assist EL3 -software which runs part of its entry/exit routines with exceptions momentarily -masked—meaning, in such systems, External Aborts/SErrors are not immediately -handled when they occur, but only after the exceptions are unmasked again. - -|TF-A|, for legacy reasons, executes entire EL3 with all exceptions unmasked. -This means that all exceptions routed to EL3 are handled immediately. |TF-A| -thus is able to detect a Double Fault conditions in software, without needing -the intended advantages of Armv8.4 Double Fault architecture extensions. - -Double faults are fatal, and terminate at the platform double fault handler, and -doesn't return. - -Engaging the RAS framework --------------------------- - -Enabling RAS support is a platform choice constructed from three distinct, but -related, build options: - -- ``RAS_EXTENSION=1`` includes the RAS framework in the run time firmware; - -- ``EL3_EXCEPTION_HANDLING=1`` enables handling of exceptions at EL3. See - `Interaction with Exception Handling Framework`_; - -- ``HANDLE_EA_EL3_FIRST=1`` enables routing of External Aborts and SErrors to - EL3. - -The RAS support in |TF-A| introduces a default implementation of -``plat_ea_handler``, the External Abort handler in EL3. When ``RAS_EXTENSION`` -is set to ``1``, it'll first call ``ras_ea_handler()`` function, which is the -top-level RAS exception handler. ``ras_ea_handler`` is responsible for iterating -to through platform-supplied error records, probe them, and when an error is -identified, look up and invoke the corresponding error handler. - -Note that, if the platform chooses to override the ``plat_ea_handler`` function -and intend to use the RAS framework, it must explicitly call -``ras_ea_handler()`` from within. - -Similarly, for RAS interrupts, the framework defines -``ras_interrupt_handler()``. The RAS framework arranges for it to be invoked -when a RAS interrupt taken at EL3. The function bisects the platform-supplied -sorted array of interrupts to look up the error record information associated -with the interrupt number. That error handler for that record is then invoked to -handle the error. - -Interaction with Exception Handling Framework ---------------------------------------------- - -As mentioned in earlier sections, RAS framework interacts with the |EHF| to -arbitrate handling of RAS exceptions with others that are routed to EL3. This -means that the platform must partition a `priority level`__ for handling RAS -exceptions. The platform must then define the macro ``PLAT_RAS_PRI`` to the -priority level used for RAS exceptions. Platforms would typically want to -allocate the highest secure priority for RAS handling. - -.. __: exception-handling.rst#partitioning-priority-levels - -Handling of both `interrupt`__ and `non-interrupt`__ exceptions follow the -sequences outlined in the |EHF| documentation. I.e., for interrupts, the -priority management is implicit; but for non-interrupt exceptions, they're -explicit using `EHF APIs`__. - -.. __: exception-handling.rst#interrupt-flow -.. __: exception-handling.rst#non-interrupt-flow -.. __: exception-handling.rst#activating-and-deactivating-priorities - ----- - -*Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.* diff --git a/docs/readme.rst b/docs/readme.rst new file mode 100644 index 0000000..fc03555 --- /dev/null +++ b/docs/readme.rst @@ -0,0 +1,356 @@ +Trusted Firmware-A - version 2.1 +================================ + +.. section-numbering:: + :suffix: . + +.. contents:: + +Trusted Firmware-A (TF-A) provides a reference implementation of secure world +software for `Armv7-A and Armv8-A`_, including a `Secure Monitor`_ executing +at Exception Level 3 (EL3). It implements various Arm interface standards, +such as: + +- The `Power State Coordination Interface (PSCI)`_ +- `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT)`_ +- `SMC Calling Convention`_ +- `System Control and Management Interface (SCMI)`_ +- `Software Delegated Exception Interface (SDEI)`_ + +Where possible, the code is designed for reuse or porting to other Armv7-A and +Armv8-A model and hardware platforms. + +This release provides a suitable starting point for productization of secure +world boot and runtime firmware, in either the AArch32 or AArch64 execution +states. + +Users are encouraged to do their own security validation, including penetration +testing, on any secure world code derived from TF-A. + +Arm will continue development in collaboration with interested parties to +provide a full reference implementation of Secure Monitor code and Arm standards +to the benefit of all developers working with Armv7-A and Armv8-A TrustZone +technology. + +Documentation contents +---------------------- + +The `Trusted Firmware-A Documentation Contents`_ page contains an overview of +the documentation that is available, with links to facilitate easier browsing. + +License +------- + +The software is provided under a BSD-3-Clause `license`_. Contributions to this +project are accepted under the same license with developer sign-off as +described in the `Contributing Guidelines`_. + +This project contains code from other projects as listed below. The original +license text is included in those source files. + +- The libc source code is derived from `FreeBSD`_ and `SCC`_. FreeBSD uses + various BSD licenses, including BSD-3-Clause and BSD-2-Clause. The SCC code + is used under the BSD-3-Clause license with the author's permission. + +- The libfdt source code is disjunctively dual licensed + (GPL-2.0+ OR BSD-2-Clause). It is used by this project under the terms of + the BSD-2-Clause license. Any contributions to this code must be made under + the terms of both licenses. + +- The LLVM compiler-rt source code is disjunctively dual licensed + (NCSA OR MIT). It is used by this project under the terms of the NCSA + license (also known as the University of Illinois/NCSA Open Source License), + which is a permissive license compatible with BSD-3-Clause. Any + contributions to this code must be made under the terms of both licenses. + +- The zlib source code is licensed under the Zlib license, which is a + permissive license compatible with BSD-3-Clause. + +- Some STMicroelectronics platform source code is disjunctively dual licensed + (GPL-2.0+ OR BSD-3-Clause). It is used by this project under the terms of the + BSD-3-Clause license. Any contributions to this code must be made under the + terms of both licenses. + +Functionality +------------- + +- Initialization of the secure world, for example exception vectors, control + registers and interrupts for the platform. + +- Library support for CPU specific reset and power down sequences. This + includes support for errata workarounds and the latest Arm DynamIQ CPUs. + +- Drivers to enable standard initialization of Arm System IP, for example + Generic Interrupt Controller (GIC), Cache Coherent Interconnect (CCI), + Cache Coherent Network (CCN), Network Interconnect (NIC) and TrustZone + Controller (TZC). + +- A generic `SCMI`_ driver to interface with conforming power controllers, for + example the Arm System Control Processor (SCP). + +- SMC (Secure Monitor Call) handling, conforming to the `SMC Calling + Convention`_ using an EL3 runtime services framework. + +- `PSCI`_ library support for CPU, cluster and system power management + use-cases. + This library is pre-integrated with the AArch64 EL3 Runtime Software, and + is also suitable for integration with other AArch32 EL3 Runtime Software, + for example an AArch32 Secure OS. + +- A minimal AArch32 Secure Payload (SP\_MIN) to demonstrate `PSCI`_ library + integration with AArch32 EL3 Runtime Software. + +- Secure Monitor library code such as world switching, EL1 context management + and interrupt routing. + When a Secure-EL1 Payload (SP) is present, for example a Secure OS, the + AArch64 EL3 Runtime Software must be integrated with a Secure Payload + Dispatcher (SPD) component to customize the interaction with the SP. + +- A Test SP and SPD to demonstrate AArch64 Secure Monitor functionality and SP + interaction with PSCI. + +- SPDs for the `OP-TEE Secure OS`_, `NVIDIA Trusted Little Kernel`_ + and `Trusty Secure OS`_. + +- A Trusted Board Boot implementation, conforming to all mandatory TBBR + requirements. This includes image authentication, Firmware Update (or + recovery mode), and packaging of the various firmware images into a + Firmware Image Package (FIP). + +- Pre-integration of TBB with the Arm CryptoCell product, to take advantage of + its hardware Root of Trust and crypto acceleration services. + +- Reliability, Availability, and Serviceability (RAS) functionality, including + + - A Secure Partition Manager (SPM) to manage Secure Partitions in + Secure-EL0, which can be used to implement simple management and + security services. + + - An SDEI dispatcher to route interrupt-based SDEI events. + + - An Exception Handling Framework (EHF) that allows dispatching of EL3 + interrupts to their registered handlers, to facilitate firmware-first + error handling. + +- A dynamic configuration framework that enables each of the firmware images + to be configured at runtime if required by the platform. It also enables + loading of a hardware configuration (for example, a kernel device tree) + as part of the FIP, to be passed through the firmware stages. + +- Support for alternative boot flows, for example to support platforms where + the EL3 Runtime Software is loaded using other firmware or a separate + secure system processor, or where a non-TF-A ROM expects BL2 to be loaded + at EL3. + +- Support for the GCC, LLVM and Arm Compiler 6 toolchains. + +- Support for combining several libraries into a "romlib" image that may be + shared across images to reduce memory footprint. The romlib image is stored + in ROM but is accessed through a jump-table that may be stored + in read-write memory, allowing for the library code to be patched. + +- A prototype implementation of a Secure Partition Manager (SPM) that is based + on the SPCI Alpha 1 and SPRT draft specifications. + +- Support for ARMv8.3 pointer authentication in the normal and secure worlds. + The use of pointer authentication in the normal world is enabled whenever + architectural support is available, without the need for additional build + flags. Use of pointer authentication in the secure world remains an + experimental configuration at this time and requires the ``ENABLE_PAUTH`` + build flag to be set. + +- Position-Independent Executable (PIE) support. Initially for BL31 only, with + further support to be added in a future release. + +For a full description of functionality and implementation details, please +see the `Firmware Design`_ and supporting documentation. The `Change Log`_ +provides details of changes made since the last release. + +Platforms +--------- + +Various AArch32 and AArch64 builds of this release have been tested on r0, r1 +and r2 variants of the `Juno Arm Development Platform`_. + +The latest version of the AArch64 build of TF-A has been tested on the following +Arm FVPs without shifted affinities, and that do not support threaded CPU cores +(64-bit host machine only). + +The FVP models used are Version 11.5 Build 33, unless otherwise stated. + +- ``FVP_Base_AEMv8A-AEMv8A`` +- ``FVP_Base_AEMv8A-AEMv8A-AEMv8A-AEMv8A-CCN502`` +- ``FVP_Base_RevC-2xAEMv8A`` +- ``FVP_Base_Cortex-A32x4`` +- ``FVP_Base_Cortex-A35x4`` +- ``FVP_Base_Cortex-A53x4`` +- ``FVP_Base_Cortex-A55x4+Cortex-A75x4`` +- ``FVP_Base_Cortex-A55x4`` +- ``FVP_Base_Cortex-A57x1-A53x1`` +- ``FVP_Base_Cortex-A57x2-A53x4`` +- ``FVP_Base_Cortex-A57x4-A53x4`` +- ``FVP_Base_Cortex-A57x4`` +- ``FVP_Base_Cortex-A72x4-A53x4`` +- ``FVP_Base_Cortex-A72x4`` +- ``FVP_Base_Cortex-A73x4-A53x4`` +- ``FVP_Base_Cortex-A73x4`` +- ``FVP_Base_Cortex-A75x4`` +- ``FVP_Base_Cortex-A76x4`` +- ``FVP_Base_Cortex-A76AEx4`` (Tested with internal model) +- ``FVP_Base_Cortex-A76AEx8`` (Tested with internal model) +- ``FVP_Base_Neoverse-N1x4`` (Tested with internal model) +- ``FVP_Base_Deimos`` +- ``FVP_CSS_SGI-575`` (Version 11.3 build 42) +- ``FVP_CSS_SGM-775`` (Version 11.3 build 42) +- ``FVP_RD_E1Edge`` (Version 11.3 build 42) +- ``FVP_RD_N1Edge`` (Version 11.3 build 42) +- ``Foundation_Platform`` + +The latest version of the AArch32 build of TF-A has been tested on the following +Arm FVPs without shifted affinities, and that do not support threaded CPU cores +(64-bit host machine only). + +- ``FVP_Base_AEMv8A-AEMv8A`` +- ``FVP_Base_Cortex-A32x4`` + +NOTE: The ``FVP_Base_RevC-2xAEMv8A`` FVP only supports shifted affinities. + +The Foundation FVP can be downloaded free of charge. The Base FVPs can be +licensed from Arm. See the `Arm FVP website`_. + +All the above platforms have been tested with `Linaro Release 18.04`_. + +This release also contains the following platform support: + +- Allwinner sun50i_a64 and sun50i_h6 +- Amlogic Meson S905 (GXBB) +- Amlogic Meson S905x (GXL) +- Arm Juno Software Development Platform +- Arm Neoverse N1 System Development Platform (N1SDP) +- Arm Neoverse Reference Design N1 Edge (RD-N1-Edge) FVP +- Arm Neoverse Reference Design E1 Edge (RD-E1-Edge) FVP +- Arm SGI-575 and SGM-775 +- Arm Versatile Express FVP +- HiKey, HiKey960 and Poplar boards +- Intel Stratix 10 SoC FPGA +- Marvell Armada 3700 and 8K +- MediaTek MT6795 and MT8173 SoCs +- NVIDIA T132, T186 and T210 SoCs +- NXP QorIQ LS1043A, i.MX8MM, i.MX8MQ, i.MX8QX, i.MX8QM and i.MX7Solo WaRP7 +- QEMU +- Raspberry Pi 3 +- Renesas R-Car Generation 3 +- RockChip RK3328, RK3368 and RK3399 SoCs +- Socionext UniPhier SoC family and SynQuacer SC2A11 SoCs +- STMicroelectronics STM32MP1 +- Texas Instruments K3 SoCs +- Xilinx Versal and Zynq UltraScale + MPSoC + +Still to come +------------- + +- Support for additional platforms. + +- Refinements to Position Independent Executable (PIE) support. + +- Refinements to the SPCI-based SPM implementation as the draft SPCI and SPRT + specifications continue to evolve. + +- Documentation enhancements. + +- Ongoing support for new architectural features, CPUs and System IP. + +- Ongoing support for new Arm system architecture specifications. + +- Ongoing security hardening, optimization and quality improvements. + +For a full list of detailed issues in the current code, please see the `Change +Log`_ and the `issue tracker`_. + +Getting started +--------------- + +See the `User Guide`_ for instructions on how to download, install, build and +use TF-A with the Arm `FVP`_\ s. + +See the `Firmware Design`_ for information on how TF-A works. + +See the `Porting Guide`_ as well for information about how to use this +software on another Armv7-A or Armv8-A platform. + +See the `Contributing Guidelines`_ for information on how to contribute to this +project and the `Acknowledgments`_ file for a list of contributors to the +project. + +IRC channel +~~~~~~~~~~~ + +Development discussion takes place on the #trusted-firmware-a channel +on the Freenode IRC network. This is not an official support channel. +If you have an issue to raise, please use the `issue tracker`_. + +Feedback and support +~~~~~~~~~~~~~~~~~~~~ + +Arm welcomes any feedback on TF-A. If you think you have found a security +vulnerability, please report this using the process defined in the TF-A +`Security Center`_. For all other feedback, please use the +`issue tracker`_. + +Arm licensees may contact Arm directly via their partner managers. + +Security advisories +------------------- + +- `Security Advisory TFV-1`_ +- `Security Advisory TFV-2`_ +- `Security Advisory TFV-3`_ +- `Security Advisory TFV-4`_ +- `Security Advisory TFV-5`_ +- `Security Advisory TFV-6`_ +- `Security Advisory TFV-7`_ +- `Security Advisory TFV-8`_ + + +-------------- + +*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Armv7-A and Armv8-A: https://developer.arm.com/products/architecture/a-profile +.. _Secure Monitor: http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php +.. _Power State Coordination Interface (PSCI): PSCI_ +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a +.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf +.. _System Control and Management Interface (SCMI): SCMI_ +.. _SCMI: http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/DEN0056A_System_Control_and_Management_Interface.pdf +.. _Software Delegated Exception Interface (SDEI): SDEI_ +.. _SDEI: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _Juno Arm Development Platform: http://www.arm.com/products/tools/development-boards/versatile-express/juno-arm-development-platform.php +.. _Arm FVP website: FVP_ +.. _FVP: https://developer.arm.com/products/system-design/fixed-virtual-platforms +.. _Linaro Release 18.04: https://community.arm.com/dev-platforms/b/documents/posts/linaro-release-notes-deprecated#LinaroRelease18.04 +.. _OP-TEE Secure OS: https://github.com/OP-TEE/optee_os +.. _NVIDIA Trusted Little Kernel: http://nv-tegra.nvidia.com/gitweb/?p=3rdparty/ote_partner/tlk.git;a=summary +.. _Trusty Secure OS: https://source.android.com/security/trusty +.. _trustedfirmware.org: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git +.. _issue tracker: https://developer.trustedfirmware.org/project/board/1/ +.. _Security Center: ./docs/security-center.rst +.. _license: ./license.rst +.. _Contributing Guidelines: ./contributing.rst +.. _Acknowledgments: ./acknowledgements.rst +.. _Firmware Design: ./docs/firmware-design.rst +.. _Change Log: ./docs/change-log.rst +.. _User Guide: ./docs/user-guide.rst +.. _Porting Guide: ./docs/porting-guide.rst +.. _FreeBSD: http://www.freebsd.org +.. _SCC: http://www.simple-cc.org/ +.. _Security Advisory TFV-1: ./docs/security_advisories/security-advisory-tfv-1.rst +.. _Security Advisory TFV-2: ./docs/security_advisories/security-advisory-tfv-2.rst +.. _Security Advisory TFV-3: ./docs/security_advisories/security-advisory-tfv-3.rst +.. _Security Advisory TFV-4: ./docs/security_advisories/security-advisory-tfv-4.rst +.. _Security Advisory TFV-5: ./docs/security_advisories/security-advisory-tfv-5.rst +.. _Security Advisory TFV-6: ./docs/security_advisories/security-advisory-tfv-6.rst +.. _Security Advisory TFV-7: ./docs/security_advisories/security-advisory-tfv-7.rst +.. _Security Advisory TFV-8: ./docs/security_advisories/security-advisory-tfv-8.rst +.. _Trusted Firmware-A Documentation Contents: ./docs/contents.rst diff --git a/docs/release-information.rst b/docs/release-information.rst deleted file mode 100644 index 5531150..0000000 --- a/docs/release-information.rst +++ /dev/null @@ -1,89 +0,0 @@ -TF-A Release Information -======================== - -.. section-numbering:: - :suffix: . - -.. contents:: - --------------- - -Project Release Cadence ------------------------ - -The project currently aims to do a release once every 6 months which will be -tagged on the master branch. There will be a code freeze (stop merging -non-essential PRs) up to 4 weeks prior to the target release date. The release -candidates will start appearing after this and only bug fixes or updates -required for the release will be merged. The maintainers are free to use their -judgement on what PRs are essential for the release. A release branch may be -created after code freeze if there are significant PRs that need merging onto -the integration branch during the merge window. - -The release testing will be performed on release candidates and depending on -issues found, additional release candidates may be created to fix the issues. - -:: - - |<----------6 months---------->| - |<---4 weeks--->| |<---4 weeks--->| - +-----------------------------------------------------------> time - | | | | - code freeze ver w.x code freeze ver y.z - - -Upcoming Releases -~~~~~~~~~~~~~~~~~ - -These are the estimated dates for the upcoming release. These may change -depending on project requirement and partner feedback. - -+-----------------+---------------------------+------------------------------+ -| Release Version | Target Date | Expected Code Freeze | -+=================+===========================+==============================+ -| v2.0 | 1st week of Oct '18 | 1st week of Sep '18 | -+-----------------+---------------------------+------------------------------+ -| v2.1 | 5th week of Mar '19 | 1st week of Mar '19 | -+-----------------+---------------------------+------------------------------+ - -Removal of Deprecated Interfaces --------------------------------- - -As mentioned in the `Platform compatibility policy`_, this is a live document -cataloging all the deprecated interfaces in TF-A project and the Release version -after which it will be removed. - -+--------------------------------+-------------+---------+---------------------------------------------------------+ -| Interface | Deprecation | Removed | Comments | -| | Date | after | | -| | | Release | | -+================================+=============+=========+=========================================================+ -| Legacy Console API | Jan '18 | v2.1 | Deprecated in favour of ``MULTI_CONSOLE_API`` | -+--------------------------------+-------------+---------+---------------------------------------------------------+ -| Weak default | Oct '18 | v2.1 | The default implementations are defined in | -| ``plat_crash_console_*`` | | | `crash_console_helpers.S`_. The platforms have to | -| APIs | | | define ``plat_crash_console_*``. | -+--------------------------------+-------------+---------+---------------------------------------------------------+ -| ``finish_console_register`` | Oct '18 | v2.1 | The old version of the macro is deprecated. See commit | -| macro in | | | cc5859c_ for more details. | -| ``MULTI_CONSOLE_API`` | | | | -+--------------------------------+-------------+---------+---------------------------------------------------------+ -| Types ``tzc_action_t`` and | Oct '18 | v2.1 | Using logical operations such as OR in enumerations | -| ``tzc_region_attributes_t`` | | | goes against the MISRA guidelines. | -+--------------------------------+-------------+---------+---------------------------------------------------------+ -| Macro ``EL_IMPLEMENTED()`` | Oct '18 | v2.1 | Deprecated in favour of ``el_implemented()``. | -+--------------------------------+-------------+---------+---------------------------------------------------------+ -| ``get_afflvl_shift()``, | Dec '18 | v2.1 | Removed. | -| ``mpidr_mask_lower_afflvls()``,| | | | -| and ``eret()``. | | | | -+--------------------------------+-------------+---------+---------------------------------------------------------+ -| Extra include paths in the | Jan '18 | v2.1 | Now it is needed to use the full path of the common | -| Makefile in ``INCLUDES``. | | | header files. More information in commit 09d40e0e0828_. | -+--------------------------------+-------------+---------+---------------------------------------------------------+ - -*Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.* - -.. _Platform compatibility policy: platform-compatibility-policy.rst -.. _crash_console_helpers.S: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/common/aarch64/crash_console_helpers.S -.. _cc5859c: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=cc5859ca19ff546c35eb0331000dae090b6eabcf -.. _09d40e0e0828: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=09d40e0e08283a249e7dce0e106c07c5141f9b7e diff --git a/docs/reset-design.rst b/docs/reset-design.rst deleted file mode 100644 index 44ab609..0000000 --- a/docs/reset-design.rst +++ /dev/null @@ -1,166 +0,0 @@ -Trusted Firmware-A reset design -=============================== - - -.. section-numbering:: - :suffix: . - -.. contents:: - -This document describes the high-level design of the framework to handle CPU -resets in Trusted Firmware-A (TF-A). It also describes how the platform -integrator can tailor this code to the system configuration to some extent, -resulting in a simplified and more optimised boot flow. - -This document should be used in conjunction with the `Firmware Design`_, which -provides greater implementation details around the reset code, specifically -for the cold boot path. - -General reset code flow ------------------------ - -The TF-A reset code is implemented in BL1 by default. The following high-level -diagram illustrates this: - -|Default reset code flow| - -This diagram shows the default, unoptimised reset flow. Depending on the system -configuration, some of these steps might be unnecessary. The following sections -guide the platform integrator by indicating which build options exclude which -steps, depending on the capability of the platform. - -Note: If BL31 is used as the TF-A entry point instead of BL1, the diagram -above is still relevant, as all these operations will occur in BL31 in -this case. Please refer to section 6 "Using BL31 entrypoint as the reset -address" for more information. - -Programmable CPU reset address ------------------------------- - -By default, TF-A assumes that the CPU reset address is not programmable. -Therefore, all CPUs start at the same address (typically address 0) whenever -they reset. Further logic is then required to identify whether it is a cold or -warm boot to direct CPUs to the right execution path. - -If the reset vector address (reflected in the reset vector base address register -``RVBAR_EL3``) is programmable then it is possible to make each CPU start directly -at the right address, both on a cold and warm reset. Therefore, the boot type -detection can be skipped, resulting in the following boot flow: - -|Reset code flow with programmable reset address| - -To enable this boot flow, compile TF-A with ``PROGRAMMABLE_RESET_ADDRESS=1``. -This option only affects the TF-A reset image, which is BL1 by default or BL31 if -``RESET_TO_BL31=1``. - -On both the FVP and Juno platforms, the reset vector address is not programmable -so both ports use ``PROGRAMMABLE_RESET_ADDRESS=0``. - -Cold boot on a single CPU -------------------------- - -By default, TF-A assumes that several CPUs may be released out of reset. -Therefore, the cold boot code has to arbitrate access to hardware resources -shared amongst CPUs. This is done by nominating one of the CPUs as the primary, -which is responsible for initialising shared hardware and coordinating the boot -flow with the other CPUs. - -If the platform guarantees that only a single CPU will ever be brought up then -no arbitration is required. The notion of primary/secondary CPU itself no longer -applies. This results in the following boot flow: - -|Reset code flow with single CPU released out of reset| - -To enable this boot flow, compile TF-A with ``COLD_BOOT_SINGLE_CPU=1``. This -option only affects the TF-A reset image, which is BL1 by default or BL31 if -``RESET_TO_BL31=1``. - -On both the FVP and Juno platforms, although only one core is powered up by -default, there are platform-specific ways to release any number of cores out of -reset. Therefore, both platform ports use ``COLD_BOOT_SINGLE_CPU=0``. - -Programmable CPU reset address, Cold boot on a single CPU ---------------------------------------------------------- - -It is obviously possible to combine both optimisations on platforms that have -a programmable CPU reset address and which release a single CPU out of reset. -This results in the following boot flow: - - -|Reset code flow with programmable reset address and single CPU released out of reset| - -To enable this boot flow, compile TF-A with both ``COLD_BOOT_SINGLE_CPU=1`` -and ``PROGRAMMABLE_RESET_ADDRESS=1``. These options only affect the TF-A reset -image, which is BL1 by default or BL31 if ``RESET_TO_BL31=1``. - -Using BL31 entrypoint as the reset address ------------------------------------------- - -On some platforms the runtime firmware (BL3x images) for the application -processors are loaded by some firmware running on a secure system processor -on the SoC, rather than by BL1 and BL2 running on the primary application -processor. For this type of SoC it is desirable for the application processor -to always reset to BL31 which eliminates the need for BL1 and BL2. - -TF-A provides a build-time option ``RESET_TO_BL31`` that includes some additional -logic in the BL31 entry point to support this use case. - -In this configuration, the platform's Trusted Boot Firmware must ensure that -BL31 is loaded to its runtime address, which must match the CPU's ``RVBAR_EL3`` -reset vector base address, before the application processor is powered on. -Additionally, platform software is responsible for loading the other BL3x images -required and providing entry point information for them to BL31. Loading these -images might be done by the Trusted Boot Firmware or by platform code in BL31. - -Although the Arm FVP platform does not support programming the reset base -address dynamically at run-time, it is possible to set the initial value of the -``RVBAR_EL3`` register at start-up. This feature is provided on the Base FVP only. -It allows the Arm FVP port to support the ``RESET_TO_BL31`` configuration, in -which case the ``bl31.bin`` image must be loaded to its run address in Trusted -SRAM and all CPU reset vectors be changed from the default ``0x0`` to this run -address. See the `User Guide`_ for details of running the FVP models in this way. - -Although technically it would be possible to program the reset base address with -the right support in the SCP firmware, this is currently not implemented so the -Juno port doesn't support the ``RESET_TO_BL31`` configuration. - -The ``RESET_TO_BL31`` configuration requires some additions and changes in the -BL31 functionality: - -Determination of boot path -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In this configuration, BL31 uses the same reset framework and code as the one -described for BL1 above. Therefore, it is affected by the -``PROGRAMMABLE_RESET_ADDRESS`` and ``COLD_BOOT_SINGLE_CPU`` build options in the -same way. - -In the default, unoptimised BL31 reset flow, on a warm boot a CPU is directed -to the PSCI implementation via a platform defined mechanism. On a cold boot, -the platform must place any secondary CPUs into a safe state while the primary -CPU executes a modified BL31 initialization, as described below. - -Platform initialization -~~~~~~~~~~~~~~~~~~~~~~~ - -In this configuration, when the CPU resets to BL31 there are no parameters that -can be passed in registers by previous boot stages. Instead, the platform code -in BL31 needs to know, or be able to determine, the location of the BL32 (if -required) and BL33 images and provide this information in response to the -``bl31_plat_get_next_image_ep_info()`` function. - -Additionally, platform software is responsible for carrying out any security -initialisation, for example programming a TrustZone address space controller. -This might be done by the Trusted Boot Firmware or by platform code in BL31. - --------------- - -*Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.* - -.. _Firmware Design: firmware-design.rst -.. _User Guide: user-guide.rst - -.. |Default reset code flow| image:: diagrams/default_reset_code.png?raw=true -.. |Reset code flow with programmable reset address| image:: diagrams/reset_code_no_boot_type_check.png?raw=true -.. |Reset code flow with single CPU released out of reset| image:: diagrams/reset_code_no_cpu_check.png?raw=true -.. |Reset code flow with programmable reset address and single CPU released out of reset| image:: diagrams/reset_code_no_checks.png?raw=true diff --git a/docs/romlib-design.rst b/docs/romlib-design.rst deleted file mode 100644 index 4195721..0000000 --- a/docs/romlib-design.rst +++ /dev/null @@ -1,133 +0,0 @@ -Library at ROM -============== - -.. section-numbering:: - :suffix: . - -.. contents:: - -This document provides an overview of the "library at ROM" implementation in -Trusted Firmware-A (TF-A). - -Introduction -~~~~~~~~~~~~ - -The "library at ROM" feature allows platforms to build a library of functions to -be placed in ROM. This reduces SRAM usage by utilising the available space in -ROM. The "library at ROM" contains a jump table with the list of functions that -are placed in ROM. The capabilities of the "library at ROM" are: - -1. Functions can be from one or several libraries. - -2. Functions can be patched after they have been programmed into ROM. - -3. Platform-specific libraries can be placed in ROM. - -4. Functions can be accessed by one or more BL images. - -Index file -~~~~~~~~~~ - -.. image:: diagrams/romlib_design.png - :width: 600 - -Library at ROM is described by an index file with the list of functions to be -placed in ROM. The index file is platform specific and its format is: - -:: - - lib function [patch] - - lib -- Name of the library the function belongs to - function -- Name of the function to be placed in library at ROM - [patch] -- Option to patch the function - -It is also possible to insert reserved spaces in the list by using the keyword -"reserved" rather than the "lib" and "function" names as shown below: - -:: - - reserved reserved - -The reserved spaces can be used to add more functions in the future without -affecting the order and location of functions already existing in the jump -table. Also, for additional flexibility and modularity, the index file can -include other index files. - -For an index file example, refer to ``lib/romlib/jmptbl.i``. - -Wrapper functions -~~~~~~~~~~~~~~~~~ - -.. image:: diagrams/romlib_wrapper.png - :width: 600 - -When invoking a function of the "library at ROM", the calling sequence is as -follows: - -BL image --> wrapper function --> jump table entry --> library at ROM - -The index file is used to create a jump table which is placed in ROM. Then, the -wrappers refer to the jump table to call the "library at ROM" functions. The -wrappers essentially contain a branch instruction to the jump table entry -corresponding to the original function. Finally, the original function in the BL -image(s) is replaced with the wrapper function. - -The "library at ROM" contains a necessary init function that initialises the -global variables defined by the functions inside "library at ROM". - -Scripts -~~~~~~~ - -There are several scripts that generate the necessary files for the "library at -ROM" to work: - -1. ``gentbl.sh`` - Generates the jump table by parsing the index file. - -2. ``genvar.sh`` - Generates the jump table global variable (**not** the jump - table itself) with the absolute address in ROM. This global variable is, - basically, a pointer to the jump table. - -3. ``genwrappers.sh`` - Generates a wrapper function for each entry in the index - file except for the ones that contain the keyword ``patch``. The generated - wrapper file is called ``_.S``. - -Patching of functions in library at ROM -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``genwrappers.sh`` script does not generate wrappers for the entries in the -index file that contain the keyword ``patch``. Thus, it allows calling the -function from the actual library by breaking the link to the "library at ROM" -version of this function. - -The calling sequence for a patched function is as follows: - -BL image --> function - -Build library at ROM -~~~~~~~~~~~~~~~~~~~~~ - -The environment variable ``CROSS_COMPILE`` must be set as per the user guide. -In the below example the usage of ROMLIB together with mbed TLS is demonstrated -to showcase the benefits of library at ROM - it's not mandatory. - -:: - - make PLAT=fvp \ - MBEDTLS_DIR= \ - TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ - ARM_ROTPK_LOCATION=devel_rsa \ - ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ - BL33= \ - USE_ROMLIB=1 \ - all fip - -Known issue ------------ -When building library at ROM, a clean build is always required. This is -necessary when changes are made to the index files, e.g. adding new functions, -patching existing ones etc. - --------------- - -*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/docs/rt-svc-writers-guide.rst b/docs/rt-svc-writers-guide.rst deleted file mode 100644 index 4d4066c..0000000 --- a/docs/rt-svc-writers-guide.rst +++ /dev/null @@ -1,315 +0,0 @@ -Trusted Firmware-A EL3 runtime service writer's guide -===================================================== - - -.. section-numbering:: - :suffix: . - -.. contents:: - --------------- - -Introduction ------------- - -This document describes how to add a runtime service to the EL3 Runtime -Firmware component of Trusted Firmware-A (TF-A), BL31. - -Software executing in the normal world and in the trusted world at exception -levels lower than EL3 will request runtime services using the Secure Monitor -Call (SMC) instruction. These requests will follow the convention described in -the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function -identifiers to each SMC request and describes how arguments are passed and -results are returned. - -SMC Functions are grouped together based on the implementor of the service, for -example a subset of the Function IDs are designated as "OEM Calls" (see `SMCCC`_ -for full details). The EL3 runtime services framework in BL31 enables the -independent implementation of services for each group, which are then compiled -into the BL31 image. This simplifies the integration of common software from -Arm to support `PSCI`_, Secure Monitor for a Trusted OS and SoC specific -software. The common runtime services framework ensures that SMC Functions are -dispatched to their respective service implementation - the `Firmware Design`_ -provides details of how this is achieved. - -The interface and operation of the runtime services depends heavily on the -concepts and definitions described in the `SMCCC`_, in particular SMC Function -IDs, Owning Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and -SMC64 calling conventions. Please refer to that document for a full explanation -of these terms. - -Owning Entities, Call Types and Function IDs --------------------------------------------- - -The SMC Function Identifier includes a OEN field. These values and their -meaning are described in `SMCCC`_ and summarized in table 1 below. Some entities -are allocated a range of of OENs. The OEN must be interpreted in conjunction -with the SMC call type, which is either *Fast* or *Yielding*. Fast calls are -uninterruptible whereas Yielding calls can be pre-empted. The majority of -Owning Entities only have allocated ranges for Fast calls: Yielding calls are -reserved exclusively for Trusted OS providers or for interoperability with -legacy 32-bit software that predates the `SMCCC`_. - -:: - - Type OEN Service - Fast 0 Arm Architecture calls - Fast 1 CPU Service calls - Fast 2 SiP Service calls - Fast 3 OEM Service calls - Fast 4 Standard Service calls - Fast 5-47 Reserved for future use - Fast 48-49 Trusted Application calls - Fast 50-63 Trusted OS calls - - Yielding 0- 1 Reserved for existing Armv7-A calls - Yielding 2-63 Trusted OS Standard Calls - -*Table 1: Service types and their corresponding Owning Entity Numbers* - -Each individual entity can allocate the valid identifiers within the entity -range as they need - it is not necessary to coordinate with other entities of -the same type. For example, two SoC providers can use the same Function ID -within the SiP Service calls OEN range to mean different things - as these -calls should be specific to the SoC. The Standard Runtime Calls OEN is used for -services defined by Arm standards, such as `PSCI`_. - -The SMC Function ID also indicates whether the call has followed the SMC32 -calling convention, where all parameters are 32-bit, or the SMC64 calling -convention, where the parameters are 64-bit. The framework identifies and -rejects invalid calls that use the SMC64 calling convention but that originate -from an AArch32 caller. - -The EL3 runtime services framework uses the call type and OEN to identify a -specific handler for each SMC call, but it is expected that an individual -handler will be responsible for all SMC Functions within a given service type. - -Getting started ---------------- - -TF-A has a `services`_ directory in the source tree under which -each owning entity can place the implementation of its runtime service. The -`PSCI`_ implementation is located here in the `lib/psci`_ directory. - -Runtime service sources will need to include the `runtime_svc.h`_ header file. - -Registering a runtime service ------------------------------ - -A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying -the name of the service, the range of OENs covered, the type of service and -initialization and call handler functions. - -:: - - #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) - -- ``_name`` is used to identify the data structure declared by this macro, and - is also used for diagnostic purposes - -- ``_start`` and ``_end`` values must be based on the ``OEN_*`` values defined in - `smccc.h`_ - -- ``_type`` must be one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` - -- ``_setup`` is the initialization function with the ``rt_svc_init`` signature: - - .. code:: c - - typedef int32_t (*rt_svc_init)(void); - -- ``_smch`` is the SMC handler function with the ``rt_svc_handle`` signature: - - .. code:: c - - typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, - u_register_t x1, u_register_t x2, - u_register_t x3, u_register_t x4, - void *cookie, - void *handle, - u_register_t flags); - -Details of the requirements and behavior of the two callbacks is provided in -the following sections. - -During initialization the services framework validates each declared service -to ensure that the following conditions are met: - -#. The ``_start`` OEN is not greater than the ``_end`` OEN -#. The ``_end`` OEN does not exceed the maximum OEN value (63) -#. The ``_type`` is one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` -#. ``_setup`` and ``_smch`` routines have been specified - -`std_svc_setup.c`_ provides an example of registering a runtime service: - -.. code:: c - - /* Register Standard Service Calls as runtime service */ - DECLARE_RT_SVC( - std_svc, - OEN_STD_START, - OEN_STD_END, - SMC_TYPE_FAST, - std_svc_setup, - std_svc_smc_handler - ); - -Initializing a runtime service ------------------------------- - -Runtime services are initialized once, during cold boot, by the primary CPU -after platform and architectural initialization is complete. The framework -performs basic validation of the declared service before calling -the service initialization function (``_setup`` in the declaration). This -function must carry out any essential EL3 initialization prior to receiving a -SMC Function call via the handler function. - -On success, the initialization function must return ``0``. Any other return value -will cause the framework to issue a diagnostic: - -:: - - Error initializing runtime service - -and then ignore the service - the system will continue to boot but SMC calls -will not be passed to the service handler and instead return the *Unknown SMC -Function ID* result ``0xFFFFFFFF``. - -If the system must not be allowed to proceed without the service, the -initialization function must itself cause the firmware boot to be halted. - -If the service uses per-CPU data this must either be initialized for all CPUs -during this call, or be done lazily when a CPU first issues an SMC call to that -service. - -Handling runtime service requests ---------------------------------- - -SMC calls for a service are forwarded by the framework to the service's SMC -handler function (``_smch`` in the service declaration). This function must have -the following signature: - -.. code:: c - - typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, - u_register_t x1, u_register_t x2, - u_register_t x3, u_register_t x4, - void *cookie, - void *handle, - u_register_t flags); - -The handler is responsible for: - -#. Determining that ``smc_fid`` is a valid and supported SMC Function ID, - otherwise completing the request with the *Unknown SMC Function ID*: - - .. code:: c - - SMC_RET1(handle, SMC_UNK); - -#. Determining if the requested function is valid for the calling security - state. SMC Calls can be made from both the normal and trusted worlds and - the framework will forward all calls to the service handler. - - The ``flags`` parameter to this function indicates the caller security state - in bit[0], where a value of ``1`` indicates a non-secure caller. The - ``is_caller_secure(flags)`` and ``is_caller_non_secure(flags)`` can be used to - test this condition. - - If invalid, the request should be completed with: - - .. code:: c - - SMC_RET1(handle, SMC_UNK); - -#. Truncating parameters for calls made using the SMC32 calling convention. - Such calls can be determined by checking the CC field in bit[30] of the - ``smc_fid`` parameter, for example by using: - - :: - - if (GET_SMC_CC(smc_fid) == SMC_32) ... - - For such calls, the upper bits of the parameters x1-x4 and the saved - parameters X5-X7 are UNDEFINED and must be explicitly ignored by the - handler. This can be done by truncating the values to a suitable 32-bit - integer type before use, for example by ensuring that functions defined - to handle individual SMC Functions use appropriate 32-bit parameters. - -#. Providing the service requested by the SMC Function, utilizing the - immediate parameters x1-x4 and/or the additional saved parameters X5-X7. - The latter can be retrieved using the ``SMC_GET_GP(handle, ref)`` function, - supplying the appropriate ``CTX_GPREG_Xn`` reference, e.g. - - .. code:: c - - uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6); - -#. Implementing the standard SMC32 Functions that provide information about - the implementation of the service. These are the Call Count, Implementor - UID and Revision Details for each service documented in section 6 of the - `SMCCC`_. - - TF-A expects owning entities to follow this recommendation. - -#. Returning the result to the caller. The `SMCCC`_ allows for up to 256 bits - of return value in SMC64 using X0-X3 and 128 bits in SMC32 using W0-W3. The - framework provides a family of macros to set the multi-register return - value and complete the handler: - - .. code:: c - - SMC_RET1(handle, x0); - SMC_RET2(handle, x0, x1); - SMC_RET3(handle, x0, x1, x2); - SMC_RET4(handle, x0, x1, x2, x3); - -The ``cookie`` parameter to the handler is reserved for future use and can be -ignored. The ``handle`` is returned by the SMC handler - completion of the -handler function must always be via one of the ``SMC_RETn()`` macros. - -NOTE: The PSCI and Test Secure-EL1 Payload Dispatcher services do not follow -all of the above requirements yet. - -Services that contain multiple sub-services -------------------------------------------- - -It is possible that a single owning entity implements multiple sub-services. For -example, the Standard calls service handles ``0x84000000``-``0x8400FFFF`` and -``0xC4000000``-``0xC400FFFF`` functions. Within that range, the `PSCI`_ service -handles the ``0x84000000``-``0x8400001F`` and ``0xC4000000``-``0xC400001F`` functions. -In that respect, `PSCI`_ is a 'sub-service' of the Standard calls service. In -future, there could be additional such sub-services in the Standard calls -service which perform independent functions. - -In this situation it may be valuable to introduce a second level framework to -enable independent implementation of sub-services. Such a framework might look -very similar to the current runtime services framework, but using a different -part of the SMC Function ID to identify the sub-service. TF-A does not provide -such a framework at present. - -Secure-EL1 Payload Dispatcher service (SPD) -------------------------------------------- - -Services that handle SMC Functions targeting a Trusted OS, Trusted Application, -or other Secure-EL1 Payload are special. These services need to manage the -Secure-EL1 context, provide the *Secure Monitor* functionality of switching -between the normal and secure worlds, deliver SMC Calls through to Secure-EL1 -and generally manage the Secure-EL1 Payload through CPU power-state transitions. - -TODO: Provide details of the additional work required to implement a SPD and -the BL31 support for these services. Or a reference to the document that will -provide this information.... - --------------- - -*Copyright (c) 2014-2018, Arm Limited and Contributors. All rights reserved.* - -.. _SMCCC: http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html -.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf -.. _Firmware Design: ./firmware-design.rst -.. _services: ../services -.. _lib/psci: ../lib/psci -.. _runtime_svc.h: ../include/common/runtime_svc.h -.. _smccc.h: ../include/lib/smccc.h -.. _std_svc_setup.c: ../services/std_svc/std_svc_setup.c diff --git a/docs/sdei.rst b/docs/sdei.rst deleted file mode 100644 index c524817..0000000 --- a/docs/sdei.rst +++ /dev/null @@ -1,379 +0,0 @@ -Software Delegated Exception Interface -====================================== - - -.. section-numbering:: - :suffix: . - -.. contents:: - :depth: 2 - -This document provides an overview of the SDEI dispatcher implementation in -Trusted Firmware-A (TF-A). - -Introduction ------------- - -`Software Delegated Exception Interface`_ (SDEI) is an Arm specification for -Non-secure world to register handlers with firmware to receive notifications -about system events. Firmware will first receive the system events by way of -asynchronous exceptions and, in response, arranges for the registered handler to -execute in the Non-secure EL. - -Normal world software that interacts with the SDEI dispatcher (makes SDEI -requests and receives notifications) is referred to as the *SDEI Client*. A -client receives the event notification at the registered handler even when it -was executing with exceptions masked. The list of SDEI events available to the -client are specific to the platform [#std-event]_. See also `Determining client -EL`_. - -.. _general SDEI dispatch: - -The following figure depicts a general sequence involving SDEI client executing -at EL2 and an event dispatch resulting from the triggering of a bound interrupt. -A commentary is provided below: - -.. image:: plantuml/sdei_general.svg - -As part of initialisation, the SDEI client binds a Non-secure interrupt [1], and -the SDEI dispatcher returns a platform dynamic event number [2]. The client then -registers a handler for that event [3], enables the event [5], and unmasks all -events on the current PE [7]. This sequence is typical of an SDEI client, but it -may involve additional SDEI calls. - -At a later point in time, when the bound interrupt triggers [9], it's trapped to -EL3. The interrupt is handed over to the SDEI dispatcher, which then arranges to -execute the registered handler [10]. The client terminates its execution with -``SDEI_EVENT_COMPLETE`` [11], following which the dispatcher resumes the -original EL2 execution [13]. Note that the SDEI interrupt remains active until -the client handler completes, at which point EL3 does EOI [12]. - -Other than events bound to interrupts (as depicted in the sequence above, SDEI -events can be explicitly dispatched in response to other exceptions, for -example, upon receiving an *SError* or *Synchronous External Abort*. See -`Explicit dispatch of events`_. - -The remainder of this document only discusses the design and implementation of -SDEI dispatcher in TF-A, and assumes that the reader is familiar with the SDEI -specification, the interfaces, and their requirements. - -.. [#std-event] Except event 0, which is defined by the SDEI specification as a - standard event. - -Defining events ---------------- - -A platform choosing to include the SDEI dispatcher must also define the events -available on the platform, along with their attributes. - -The platform is expected to provide two arrays of event descriptors: one for -private events, and another for shared events. The SDEI dispatcher provides -``SDEI_PRIVATE_EVENT()`` and ``SDEI_SHARED_EVENT()`` macros to populate the -event descriptors. Both macros take 3 arguments: - -- The event number: this must be a positive 32-bit integer. - -- For an event that has a backing interrupt, the interrupt number the event is - bound to: - - - If it's not applicable to an event, this shall be left as ``0``. - - - If the event is dynamic, this should be specified as ``SDEI_DYN_IRQ``. - -- A bit map of `Event flags`_. - -To define event 0, the macro ``SDEI_DEFINE_EVENT_0()`` should be used. This -macro takes only one parameter: an SGI number to signal other PEs. - -To define an event that's meant to be `explicitly dispatched`__ (i.e., not as a -result of receiving an SDEI interrupt), the macro ``SDEI_EXPLICIT_EVENT()`` -should be used. It accepts two parameters: - -.. __: `Explicit dispatch of events`_ - -- The event number (as above); - -- Event priority: ``SDEI_MAPF_CRITICAL`` or ``SDEI_MAPF_NORMAL``, as described - below. - -Once the event descriptor arrays are defined, they should be exported to the -SDEI dispatcher using the ``REGISTER_SDEI_MAP()`` macro, passing it the pointers -to the private and shared event descriptor arrays, respectively. Note that the -``REGISTER_SDEI_MAP()`` macro must be used in the same file where the arrays are -defined. - -Regarding event descriptors: - -- For Event 0: - - - There must be exactly one descriptor in the private array, and none in the - shared array. - - - The event should be defined using ``SDEI_DEFINE_EVENT_0()``. - - - Must be bound to a Secure SGI on the platform. - -- Explicit events should only be used in the private array. - -- Statically bound shared and private interrupts must be bound to shared and - private interrupts on the platform, respectively. See the section on - `interrupt configuration`__. - - .. __: `Configuration within Exception Handling Framework`_ - -- Both arrays should be one-dimensional. The ``REGISTER_SDEI_MAP()`` macro - takes care of replicating private events for each PE on the platform. - -- Both arrays must be sorted in the increasing order of event number. - -The SDEI specification doesn't have provisions for discovery of available events -on the platform. The list of events made available to the client, along with -their semantics, have to be communicated out of band; for example, through -Device Trees or firmware configuration tables. - -See also `Event definition example`_. - -Event flags -~~~~~~~~~~~ - -Event flags describe the properties of the event. They are bit maps that can be -``OR``\ ed to form parameters to macros that `define events`__. - -.. __: `Defining events`_ - -- ``SDEI_MAPF_DYNAMIC``: Marks the event as dynamic. Dynamic events can be - bound to (or released from) any Non-secure interrupt at runtime via the - ``SDEI_INTERRUPT_BIND`` and ``SDEI_INTERRUPT_RELEASE`` calls. - -- ``SDEI_MAPF_BOUND``: Marks the event as statically bound to an interrupt. - These events cannot be re-bound at runtime. - -- ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is - the default priority. - -- ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority. - -Event definition example ------------------------- - -.. code:: c - - static sdei_ev_map_t plat_private_sdei[] = { - /* Event 0 definition */ - SDEI_DEFINE_EVENT_0(8), - - /* PPI */ - SDEI_PRIVATE_EVENT(8, 23, SDEI_MAPF_BOUND), - - /* Dynamic private events */ - SDEI_PRIVATE_EVENT(100, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), - SDEI_PRIVATE_EVENT(101, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) - - /* Events for explicit dispatch */ - SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL); - SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL); - }; - - /* Shared event mappings */ - static sdei_ev_map_t plat_shared_sdei[] = { - SDEI_SHARED_EVENT(804, 0, SDEI_MAPF_DYNAMIC), - - /* Dynamic shared events */ - SDEI_SHARED_EVENT(3000, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), - SDEI_SHARED_EVENT(3001, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) - }; - - /* Export SDEI events */ - REGISTER_SDEI_MAP(plat_private_sdei, plat_shared_sdei); - -Configuration within Exception Handling Framework -------------------------------------------------- - -The SDEI dispatcher functions alongside the Exception Handling Framework. This -means that the platform must assign priorities to both Normal and Critical SDEI -interrupts for the platform: - -- Install priority descriptors for Normal and Critical SDEI interrupts. - -- For those interrupts that are statically bound (i.e. events defined as having - the ``SDEI_MAPF_BOUND`` property), enumerate their properties for the GIC - driver to configure interrupts accordingly. - - The interrupts must be configured to target EL3. This means that they should - be configured as *Group 0*. Additionally, on GICv2 systems, the build option - ``GICV2_G0_FOR_EL3`` must be set to ``1``. - -See also `SDEI porting requirements`_. - -Determining client EL ---------------------- - -The SDEI specification requires that the *physical* SDEI client executes in the -highest Non-secure EL implemented on the system. This means that the dispatcher -will only allow SDEI calls to be made from: - -- EL2, if EL2 is implemented. The Hypervisor is expected to implement a - *virtual* SDEI dispatcher to support SDEI clients in Guest Operating Systems - executing in Non-secure EL1. - -- Non-secure EL1, if EL2 is not implemented or disabled. - -See the function ``sdei_client_el()`` in ``sdei_private.h``. - -Explicit dispatch of events ---------------------------- - -Typically, an SDEI event dispatch is caused by the PE receiving interrupts that -are bound to an SDEI event. However, there are cases where the Secure world -requires dispatch of an SDEI event as a direct or indirect result of a past -activity, such as receiving a Secure interrupt or an exception. - -The SDEI dispatcher implementation provides ``sdei_dispatch_event()`` API for -this purpose. The API has the following signature: - -:: - - int sdei_dispatch_event(int ev_num); - -The parameter ``ev_num`` is the event number to dispatch. The API returns ``0`` -on success, or ``-1`` on failure. - -The following figure depicts a scenario involving explicit dispatch of SDEI -event. A commentary is provided below: - -.. image:: plantuml/sdei_explicit_dispatch.svg - -As part of initialisation, the SDEI client registers a handler for a platform -event [1], enables the event [3], and unmasks the current PE [5]. Note that, -unlike in `general SDEI dispatch`_, this doesn't involve interrupt binding, as -bound or dynamic events can't be explicitly dispatched (see the section below). - -At a later point in time, a critical event [#critical-event]_ is trapped into -EL3 [7]. EL3 performs a first-level triage of the event, and a RAS component -assumes further handling [8]. The dispatch completes, but intends to involve -Non-secure world in further handling, and therefore decides to explicitly -dispatch an event [10] (which the client had already registered for [1]). The -rest of the sequence is similar to that in the `general SDEI dispatch`_: the -requested event is dispatched to the client (assuming all the conditions are -met), and when the handler completes, the preempted execution resumes. - -.. [#critical-event] Examples of critical event are *SError*, *Synchronous - External Abort*, *Fault Handling interrupt*, or *Error - Recovery interrupt* from one of RAS nodes in the system. - -Conditions for event dispatch -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -All of the following requirements must be met for the API to return ``0`` and -event to be dispatched: - -- SDEI events must be unmasked on the PE. I.e. the client must have called - ``PE_UNMASK`` beforehand. - -- Event 0 can't be dispatched. - -- The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro - described above. - -- The event must be private to the PE. - -- The event must have been registered for and enabled. - -- A dispatch for the same event must not be outstanding. I.e. it hasn't already - been dispatched and is yet to be completed. - -- The priority of the event (either Critical or Normal, as configured by the - platform at build-time) shouldn't cause priority inversion. This means: - - - If it's of Normal priority, neither Normal nor Critical priority dispatch - must be outstanding on the PE. - - - If it's of a Critical priority, no Critical priority dispatch must be - outstanding on the PE. - -Further, the caller should be aware of the following assumptions made by the -dispatcher: - -- The caller of the API is a component running in EL3; for example, a RAS - driver. - -- The requested dispatch will be permitted by the Exception Handling Framework. - I.e. the caller must make sure that the requested dispatch has sufficient - priority so as not to cause priority level inversion within Exception - Handling Framework. - -- The caller must be prepared for the SDEI dispatcher to restore the Non-secure - context, and mark that the active context. - -- The call will block until the SDEI client completes the event (i.e. when the - client calls either ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``). - -- The caller must be prepared for this API to return failure and handle - accordingly. - -Porting requirements --------------------- - -The porting requirements of the SDEI dispatcher are outlined in the `porting -guide`__. - -.. __: `SDEI porting requirements`_ - -Note on writing SDEI event handlers ------------------------------------ - -*This section pertains to SDEI event handlers in general, not just when using -the TF-A SDEI dispatcher.* - -The SDEI specification requires that event handlers preserve the contents of all -registers except ``x0`` to ``x17``. This has significance if event handler is -written in C: compilers typically adjust the stack frame at the beginning and -end of C functions. For example, AArch64 GCC typically produces the following -function prologue and epilogue: - -:: - - c_event_handler: - stp x29, x30, [sp,#-32]! - mov x29, sp - - ... - - bl ... - - ... - - ldp x29, x30, [sp],#32 - ret - -The register ``x29`` is used as frame pointer in the prologue. Because neither a -valid ``SDEI_EVENT_COMPLETE`` nor ``SDEI_EVENT_COMPLETE_AND_RESUME`` calls -return to the handler, the epilogue never gets executed, and registers ``x29`` -and ``x30`` (in the case above) are inadvertently corrupted. This violates the -SDEI specification, and the normal execution thereafter will result in -unexpected behaviour. - -To work this around, it's advised that the top-level event handlers are -implemented in assembly, following a similar pattern as below: - -:: - - asm_event_handler: - /* Save link register whilst maintaining stack alignment */ - stp xzr, x30, [sp, #-16]! - bl c_event_handler - - /* Restore link register */ - ldp xzr, x30, [sp], #16 - - /* Complete call */ - ldr x0, =SDEI_EVENT_COMPLETE - smc #0 - b . - ----- - -*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* - -.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf -.. _SDEI porting requirements: porting-guide.rst#sdei-porting-requirements diff --git a/docs/secure-partition-manager-design.rst b/docs/secure-partition-manager-design.rst deleted file mode 100644 index 3c301d0..0000000 --- a/docs/secure-partition-manager-design.rst +++ /dev/null @@ -1,824 +0,0 @@ -******************************* -Secure Partition Manager Design -******************************* - -.. section-numbering:: - :suffix: . - -.. contents:: - -Background -========== - -In some market segments that primarily deal with client-side devices like mobile -phones, tablets, STBs and embedded devices, a Trusted OS instantiates trusted -applications to provide security services like DRM, secure payment and -authentication. The Global Platform TEE Client API specification defines the API -used by Non-secure world applications to access these services. A Trusted OS -fulfils the requirements of a security service as described above. - -Management services are typically implemented at the highest level of privilege -in the system, i.e. EL3 in Trusted Firmware-A (TF-A). The service requirements are -fulfilled by the execution environment provided by TF-A. - -The following diagram illustrates the corresponding software stack: - -|Image 1| - -In other market segments that primarily deal with server-side devices (e.g. data -centres and enterprise servers) the secure software stack typically does not -include a Global Platform Trusted OS. Security functions are accessed through -other interfaces (e.g. ACPI TCG TPM interface, UEFI runtime variable service). - -Placement of management and security functions with diverse requirements in a -privileged Exception Level (i.e. EL3 or S-EL1) makes security auditing of -firmware more difficult and does not allow isolation of unrelated services from -each other either. - -Introduction -============ - -A **Secure Partition** is a software execution environment instantiated in -S-EL0 that can be used to implement simple management and security services. -Since S-EL0 is an unprivileged Exception Level, a Secure Partition relies on -privileged firmware (i.e. TF-A) to be granted access to system and processor -resources. Essentially, it is a software sandbox in the Secure world that runs -under the control of privileged software, provides one or more services and -accesses the following system resources: - -- Memory and device regions in the system address map. - -- PE system registers. - -- A range of synchronous exceptions (e.g. SMC function identifiers). - -Note that currently TF-A only supports handling one Secure Partition. - -A Secure Partition enables TF-A to implement only the essential secure -services in EL3 and instantiate the rest in a partition in S-EL0. -Furthermore, multiple Secure Partitions can be used to isolate unrelated -services from each other. - -The following diagram illustrates the place of a Secure Partition in a typical -Armv8-A software stack. A single or multiple Secure Partitions provide secure -services to software components in the Non-secure world and other Secure -Partitions. - -|Image 2| - -The TF-A build system is responsible for including the Secure Partition image -in the FIP. During boot, BL2 includes support to authenticate and load the -Secure Partition image. A BL31 component called **Secure Partition Manager -(SPM)** is responsible for managing the partition. This is semantically -similar to a hypervisor managing a virtual machine. - -The SPM is responsible for the following actions during boot: - -- Allocate resources requested by the Secure Partition. - -- Perform architectural and system setup required by the Secure Partition to - fulfil a service request. - -- Implement a standard interface that is used for initialising a Secure - Partition. - -The SPM is responsible for the following actions during runtime: - -- Implement a standard interface that is used by a Secure Partition to fulfil - service requests. - -- Implement a standard interface that is used by the Non-secure world for - accessing the services exported by a Secure Partition. A service can be - invoked through a SMC. - -Alternatively, a partition can be viewed as a thread of execution running under -the control of the SPM. Hence common programming concepts described below are -applicable to a partition. - -Description -=========== - -The previous section introduced some general aspects of the software -architecture of a Secure Partition. This section describes the specific choices -made in the current implementation of this software architecture. Subsequent -revisions of the implementation will include a richer set of features that -enable a more flexible architecture. - -Building TF-A with Secure Partition support -------------------------------------------- - -SPM is supported on the Arm FVP exclusively at the moment. The current -implementation supports inclusion of only a single Secure Partition in which a -service always runs to completion (e.g. the requested services cannot be -preempted to give control back to the Normal world). - -It is not currently possible for BL31 to integrate SPM support and a Secure -Payload Dispatcher (SPD) at the same time; they are mutually exclusive. In the -SPM bootflow, a Secure Partition image executing at S-EL0 replaces the Secure -Payload image executing at S-EL1 (e.g. a Trusted OS). Both are referred to as -BL32. - -A working prototype of a SP has been implemented by re-purposing the EDK2 code -and tools, leveraging the concept of the *Standalone Management Mode (MM)* in -the UEFI specification (see the PI v1.6 Volume 4: Management Mode Core -Interface). This will be referred to as the *Standalone MM Secure Partition* in -the rest of this document. - -To enable SPM support in TF-A, the source code must be compiled with the build -flag ``ENABLE_SPM=1``, along with ``EL3_EXCEPTION_HANDLING=1``. On Arm -platforms the build option ``ARM_BL31_IN_DRAM`` must be set to 1. Also, the -location of the binary that contains the BL32 image -(``BL32=path/to/image.bin``) must be specified. - -First, build the Standalone MM Secure Partition. To build it, refer to the -`instructions in the EDK2 repository`_. - -Then build TF-A with SPM support and include the Standalone MM Secure Partition -image in the FIP: - -:: - - BL32=path/to/standalone/mm/sp BL33=path/to/bl33.bin \ - make PLAT=fvp ENABLE_SPM=1 ARM_BL31_IN_DRAM=1 fip all - -Describing Secure Partition resources -------------------------------------- - -TF-A exports a porting interface that enables a platform to specify the system -resources required by the Secure Partition. Some instructions are given below. -However, this interface is under development and it may change as new features -are implemented. - -- A Secure Partition is considered a BL32 image, so the same defines that apply - to BL32 images apply to a Secure Partition: ``BL32_BASE`` and ``BL32_LIMIT``. - -- The following defines are needed to allocate space for the translation tables - used by the Secure Partition: ``PLAT_SP_IMAGE_MMAP_REGIONS`` and - ``PLAT_SP_IMAGE_MAX_XLAT_TABLES``. - -- The functions ``plat_get_secure_partition_mmap()`` and - ``plat_get_secure_partition_boot_info()`` have to be implemented. The file - ``plat/arm/board/fvp/fvp_common.c`` can be used as an example. It uses the - defines in ``include/plat/arm/common/arm_spm_def.h``. - - - ``plat_get_secure_partition_mmap()`` returns an array of mmap regions that - describe the memory regions that the SPM needs to allocate for a Secure - Partition. - - - ``plat_get_secure_partition_boot_info()`` returns a - ``secure_partition_boot_info_t`` struct that is populated by the platform - with information about the memory map of the Secure Partition. - -For an example of all the changes in context, you may refer to commit -``e29efeb1b4``, in which the port for FVP was introduced. - -Accessing Secure Partition services ------------------------------------ - -The `SMC Calling Convention`_ (*Arm DEN 0028B*) describes SMCs as a conduit for -accessing services implemented in the Secure world. The ``MM_COMMUNICATE`` -interface defined in the `Management Mode Interface Specification`_ (*Arm DEN -0060A*) is used to invoke a Secure Partition service as a Fast Call. - -The mechanism used to identify a service within the partition depends on the -service implementation. It is assumed that the caller of the service will be -able to discover this mechanism through standard platform discovery mechanisms -like ACPI and Device Trees. For example, *Volume 4: Platform Initialisation -Specification v1.6. Management Mode Core Interface* specifies that a GUID is -used to identify a management mode service. A client populates the GUID in the -``EFI_MM_COMMUNICATE_HEADER``. The header is populated in the communication -buffer shared with the Secure Partition. - -A Fast Call appears to be atomic from the perspective of the caller and returns -when the requested operation has completed. A service invoked through the -``MM_COMMUNICATE`` SMC will run to completion in the partition on a given CPU. -The SPM is responsible for guaranteeing this behaviour. This means that there -can only be a single outstanding Fast Call in a partition on a given CPU. - -Exchanging data with the Secure Partition ------------------------------------------ - -The exchange of data between the Non-secure world and the partition takes place -through a shared memory region. The location of data in the shared memory area -is passed as a parameter to the ``MM_COMMUNICATE`` SMC. The shared memory area -is statically allocated by the SPM and is expected to be either implicitly known -to the Non-secure world or discovered through a platform discovery mechanism -e.g. ACPI table or device tree. It is possible for the Non-secure world to -exchange data with a partition only if it has been populated in this shared -memory area. The shared memory area is implemented as per the guidelines -specified in Section 3.2.3 of the `Management Mode Interface Specification`_ -(*Arm DEN 0060A*). - -The format of data structures used to encapsulate data in the shared memory is -agreed between the Non-secure world and the Secure Partition. For example, in -the `Management Mode Interface specification`_ (*Arm DEN 0060A*), Section 4 -describes that the communication buffer shared between the Non-secure world and -the Management Mode (MM) in the Secure world must be of the type -``EFI_MM_COMMUNICATE_HEADER``. This data structure is defined in *Volume 4: -Platform Initialisation Specification v1.6. Management Mode Core Interface*. -Any caller of a MM service will have to use the ``EFI_MM_COMMUNICATE_HEADER`` -data structure. - -Runtime model of the Secure Partition -===================================== - -This section describes how the Secure Partition interfaces with the SPM. - -Interface with SPM ------------------- - -In order to instantiate one or more secure services in the Secure Partition in -S-EL0, the SPM should define the following types of interfaces: - -- Interfaces that enable access to privileged operations from S-EL0. These - operations typically require access to system resources that are either shared - amongst multiple software components in the Secure world or cannot be directly - accessed from an unprivileged Exception Level. - -- Interfaces that establish the control path between the SPM and the Secure - Partition. - -This section describes the APIs currently exported by the SPM that enable a -Secure Partition to initialise itself and export its services in S-EL0. These -interfaces are not accessible from the Non-secure world. - -Conduit -^^^^^^^ - -The `SMC Calling Convention`_ (*Arm DEN 0028B*) specification describes the SMC -and HVC conduits for accessing firmware services and their availability -depending on the implemented Exception levels. In S-EL0, the Supervisor Call -exception (SVC) is the only architectural mechanism available for unprivileged -software to make a request for an operation implemented in privileged software. -Hence, the SVC conduit must be used by the Secure Partition to access interfaces -implemented by the SPM. - -A SVC causes an exception to be taken to S-EL1. TF-A assumes ownership of S-EL1 -and installs a simple exception vector table in S-EL1 that relays a SVC request -from a Secure Partition as a SMC request to the SPM in EL3. Upon servicing the -SMC request, Arm Trusted Firmware returns control directly to S-EL0 through an -ERET instruction. - -Calling conventions -^^^^^^^^^^^^^^^^^^^ - -The `SMC Calling Convention`_ (*Arm DEN 0028B*) specification describes the -32-bit and 64-bit calling conventions for the SMC and HVC conduits. The SVC -conduit introduces the concept of SVC32 and SVC64 calling conventions. The SVC32 -and SVC64 calling conventions are equivalent to the 32-bit (SMC32) and the -64-bit (SMC64) calling conventions respectively. - -Communication initiated by SPM -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -A service request is initiated from the SPM through an exception return -instruction (ERET) to S-EL0. Later, the Secure Partition issues an SVC -instruction to signal completion of the request. Some example use cases are -given below: - -- A request to initialise the Secure Partition during system boot. - -- A request to handle a runtime service request. - -Communication initiated by Secure Partition -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -A request is initiated from the Secure Partition by executing a SVC instruction. -An ERET instruction is used by TF-A to return to S-EL0 with the result of the -request. - -For instance, a request to perform privileged operations on behalf of a -partition (e.g. management of memory attributes in the translation tables for -the Secure EL1&0 translation regime). - -Interfaces -^^^^^^^^^^ - -The current implementation reserves function IDs for Fast Calls in the Standard -Secure Service calls range (see `SMC Calling Convention`_ (*Arm DEN 0028B*) -specification) for each API exported by the SPM. This section defines the -function prototypes for each function ID. The function IDs specify whether one -or both of the SVC32 and SVC64 calling conventions can be used to invoke the -corresponding interface. - -Secure Partition Event Management -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The Secure Partition provides an Event Management interface that is used by the -SPM to delegate service requests to the Secure Partition. The interface also -allows the Secure Partition to: - -- Register with the SPM a service that it provides. -- Indicate completion of a service request delegated by the SPM - -Miscellaneous interfaces ------------------------- - -``SPM_VERSION_AARCH32`` -^^^^^^^^^^^^^^^^^^^^^^^ - -- Description - - Returns the version of the interface exported by SPM. - -- Parameters - - - **uint32** - Function ID - - - SVC32 Version: **0x84000060** - -- Return parameters - - - **int32** - Status - - On success, the format of the value is as follows: - - - Bit [31]: Must be 0 - - Bits [30:16]: Major Version. Must be 0 for this revision of the SPM - interface. - - Bits [15:0]: Minor Version. Must be 1 for this revision of the SPM - interface. - - On error, the format of the value is as follows: - - - ``NOT_SUPPORTED``: SPM interface is not supported or not available for the - client. - -- Usage - - This function returns the version of the Secure Partition Manager - implementation. The major version is 0 and the minor version is 1. The version - number is a 31-bit unsigned integer, with the upper 15 bits denoting the major - revision, and the lower 16 bits denoting the minor revision. The following - rules apply to the version numbering: - - - Different major revision values indicate possibly incompatible functions. - - - For two revisions, A and B, for which the major revision values are - identical, if the minor revision value of revision B is greater than the - minor revision value of revision A, then every function in revision A must - work in a compatible way with revision B. However, it is possible for - revision B to have a higher function count than revision A. - -- Implementation responsibilities - - If this function returns a valid version number, all the functions that are - described subsequently must be implemented, unless it is explicitly stated - that a function is optional. - -See `Error Codes`_ for integer values that are associated with each return -code. - -Secure Partition Initialisation -------------------------------- - -The SPM is responsible for initialising the architectural execution context to -enable initialisation of a service in S-EL0. The responsibilities of the SPM are -listed below. At the end of initialisation, the partition issues a -``SP_EVENT_COMPLETE_AARCH64`` call (described later) to signal readiness for -handling requests for services implemented by the Secure Partition. The -initialisation event is executed as a Fast Call. - -Entry point invocation -^^^^^^^^^^^^^^^^^^^^^^ - -The entry point for service requests that should be handled as Fast Calls is -used as the target of the ERET instruction to start initialisation of the Secure -Partition. - -Architectural Setup -^^^^^^^^^^^^^^^^^^^ - -At cold boot, system registers accessible from S-EL0 will be in their reset -state unless otherwise specified. The SPM will perform the following -architectural setup to enable execution in S-EL0 - -MMU setup -^^^^^^^^^ - -The platform port of a Secure Partition specifies to the SPM a list of regions -that it needs access to and their attributes. The SPM validates this resource -description and initialises the Secure EL1&0 translation regime as follows. - -1. Device regions are mapped with nGnRE attributes and Execute Never - instruction access permissions. - -2. Code memory regions are mapped with RO data and Executable instruction access - permissions. - -3. Read Only data memory regions are mapped with RO data and Execute Never - instruction access permissions. - -4. Read Write data memory regions are mapped with RW data and Execute Never - instruction access permissions. - -5. If the resource description does not explicitly describe the type of memory - regions then all memory regions will be marked with Code memory region - attributes. - -6. The ``UXN`` and ``PXN`` bits are set for regions that are not executable by - S-EL0 or S-EL1. - -System Register Setup -^^^^^^^^^^^^^^^^^^^^^ - -System registers that influence software execution in S-EL0 are setup by the SPM -as follows: - -1. ``SCTLR_EL1`` - - - ``UCI=1`` - - ``EOE=0`` - - ``WXN=1`` - - ``nTWE=1`` - - ``nTWI=1`` - - ``UCT=1`` - - ``DZE=1`` - - ``I=1`` - - ``UMA=0`` - - ``SA0=1`` - - ``C=1`` - - ``A=1`` - - ``M=1`` - -2. ``CPACR_EL1`` - - - ``FPEN=b'11`` - -3. ``PSTATE`` - - - ``D,A,I,F=1`` - - ``CurrentEL=0`` (EL0) - - ``SpSel=0`` (Thread mode) - - ``NRW=0`` (AArch64) - -General Purpose Register Setup -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -SPM will invoke the entry point of a service by executing an ERET instruction. -This transition into S-EL0 is special since it is not in response to a previous -request through a SVC instruction. This is the first entry into S-EL0. The -general purpose register usage at the time of entry will be as specified in the -"Return State" column of Table 3-1 in Section 3.1 "Register use in AArch64 SMC -calls" of the `SMC Calling Convention`_ (*Arm DEN 0028B*) specification. In -addition, certain other restrictions will be applied as described below. - -1. ``SP_EL0`` - - A non-zero value will indicate that the SPM has initialised the stack pointer - for the current CPU. - - The value will be 0 otherwise. - -2. ``X4-X30`` - - The values of these registers will be 0. - -3. ``X0-X3`` - - Parameters passed by the SPM. - - - ``X0``: Virtual address of a buffer shared between EL3 and S-EL0. The - buffer will be mapped in the Secure EL1&0 translation regime with read-only - memory attributes described earlier. - - - ``X1``: Size of the buffer in bytes. - - - ``X2``: Cookie value (*IMPLEMENTATION DEFINED*). - - - ``X3``: Cookie value (*IMPLEMENTATION DEFINED*). - -Runtime Event Delegation ------------------------- - -The SPM receives requests for Secure Partition services through a synchronous -invocation (i.e. a SMC from the Non-secure world). These requests are delegated -to the partition by programming a return from the last -``SP_EVENT_COMPLETE_AARCH64`` call received from the partition. The last call -was made to signal either completion of Secure Partition initialisation or -completion of a partition service request. - -``SP_EVENT_COMPLETE_AARCH64`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- Description - - Signal completion of the last SP service request. - -- Parameters - - - **uint32** - Function ID - - - SVC64 Version: **0xC4000061** - - - **int32** - Event Status Code - - Zero or a positive value indicates that the event was handled successfully. - The values depend upon the original event that was delegated to the Secure - partition. They are described as follows. - - - ``SUCCESS`` : Used to indicate that the Secure Partition was initialised - or a runtime request was handled successfully. - - - Any other value greater than 0 is used to pass a specific Event Status - code in response to a runtime event. - - A negative value indicates an error. The values of Event Status code depend - on the original event. - -- Return parameters - - - **int32** - Event ID/Return Code - - Zero or a positive value specifies the unique ID of the event being - delegated to the partition by the SPM. - - In the current implementation, this parameter contains the function ID of - the ``MM_COMMUNICATE`` SMC. This value indicates to the partition that an - event has been delegated to it in response to an ``MM_COMMUNICATE`` request - from the Non-secure world. - - A negative value indicates an error. The format of the value is as follows: - - - ``NOT_SUPPORTED``: Function was called from the Non-secure world. - - See `Error Codes`_ for integer values that are associated with each return - code. - - - **uint32** - Event Context Address - - Address of a buffer shared between the SPM and Secure Partition to pass - event specific information. The format of the data populated in the buffer - is implementation defined. - - The buffer is mapped in the Secure EL1&0 translation regime with read-only - memory attributes described earlier. - - For the SVC64 version, this parameter is a 64-bit Virtual Address (VA). - - For the SVC32 version, this parameter is a 32-bit Virtual Address (VA). - - - **uint32** - Event context size - - Size of the memory starting at Event Address. - - - **uint32/uint64** - Event Cookie - - This is an optional parameter. If unused its value is SBZ. - -- Usage - - This function signals to the SPM that the handling of the last event delegated - to a partition has completed. The partition is ready to handle its next event. - A return from this function is in response to the next event that will be - delegated to the partition. The return parameters describe the next event. - -- Caller responsibilities - - A Secure Partition must only call ``SP_EVENT_COMPLETE_AARCH64`` to signal - completion of a request that was delegated to it by the SPM. - -- Callee responsibilities - - When the SPM receives this call from a Secure Partition, the corresponding - syndrome information can be used to return control through an ERET - instruction, to the instruction immediately after the call in the Secure - Partition context. This syndrome information comprises of general purpose and - system register values when the call was made. - - The SPM must save this syndrome information and use it to delegate the next - event to the Secure Partition. The return parameters of this interface must - specify the properties of the event and be populated in ``X0-X3/W0-W3`` - registers. - -Secure Partition Memory Management ----------------------------------- - -A Secure Partition executes at S-EL0, which is an unprivileged Exception Level. -The SPM is responsible for enabling access to regions of memory in the system -address map from a Secure Partition. This is done by mapping these regions in -the Secure EL1&0 Translation regime with appropriate memory attributes. -Attributes refer to memory type, permission, cacheability and shareability -attributes used in the Translation tables. The definitions of these attributes -and their usage can be found in the `Armv8-A ARM`_ (*Arm DDI 0487*). - -All memory required by the Secure Partition is allocated upfront in the SPM, -even before handing over to the Secure Partition for the first time. The initial -access permissions of the memory regions are statically provided by the platform -port and should allow the Secure Partition to run its initialisation code. - -However, they might not suit the final needs of the Secure Partition because its -final memory layout might not be known until the Secure Partition initialises -itself. As the Secure Partition initialises its runtime environment it might, -for example, load dynamically some modules. For instance, a Secure Partition -could implement a loader for a standard executable file format (e.g. an PE-COFF -loader for loading executable files at runtime). These executable files will be -a part of the Secure Partition image. The location of various sections in an -executable file and their permission attributes (e.g. read-write data, read-only -data and code) will be known only when the file is loaded into memory. - -In this case, the Secure Partition needs a way to change the access permissions -of its memory regions. The SPM provides this feature through the -``SP_MEMORY_ATTRIBUTES_SET_AARCH64`` SVC interface. This interface is available -to the Secure Partition during a specific time window: from the first entry into -the Secure Partition up to the first ``SP_EVENT_COMPLETE`` call that signals the -Secure Partition has finished its initialisation. Once the initialisation is -complete, the SPM does not allow changes to the memory attributes. - -This section describes the standard SVC interface that is implemented by the SPM -to determine and change permission attributes of memory regions that belong to a -Secure Partition. - -``SP_MEMORY_ATTRIBUTES_GET_AARCH64`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- Description - - Request the permission attributes of a memory region from S-EL0. - -- Parameters - - - **uint32** Function ID - - - SVC64 Version: **0xC4000064** - - - **uint64** Base Address - - This parameter is a 64-bit Virtual Address (VA). - - There are no alignment restrictions on the Base Address. The permission - attributes of the translation granule it lies in are returned. - -- Return parameters - - - **int32** - Memory Attributes/Return Code - - On success the format of the Return Code is as follows: - - - Bits[1:0] : Data access permission - - - b'00 : No access - - b'01 : Read-Write access - - b'10 : Reserved - - b'11 : Read-only access - - - Bit[2]: Instruction access permission - - - b'0 : Executable - - b'1 : Non-executable - - - Bit[30:3] : Reserved. SBZ. - - - Bit[31] : Must be 0 - - On failure the following error codes are returned: - - - ``INVALID_PARAMETERS``: The Secure Partition is not allowed to access the - memory region the Base Address lies in. - - - ``NOT_SUPPORTED`` : The SPM does not support retrieval of attributes of - any memory page that is accessible by the Secure Partition, or the - function was called from the Non-secure world. Also returned if it is - used after ``SP_EVENT_COMPLETE_AARCH64``. - - See `Error Codes`_ for integer values that are associated with each return - code. - -- Usage - - This function is used to request the permission attributes for S-EL0 on a - memory region accessible from a Secure Partition. The size of the memory - region is equal to the Translation Granule size used in the Secure EL1&0 - translation regime. Requests to retrieve other memory region attributes are - not currently supported. - -- Caller responsibilities - - The caller must obtain the Translation Granule Size of the Secure EL1&0 - translation regime from the SPM through an implementation defined method. - -- Callee responsibilities - - The SPM must not return the memory access controls for a page of memory that - is not accessible from a Secure Partition. - -``SP_MEMORY_ATTRIBUTES_SET_AARCH64`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- Description - - Set the permission attributes of a memory region from S-EL0. - -- Parameters - - - **uint32** - Function ID - - - SVC64 Version: **0xC4000065** - - - **uint64** - Base Address - - This parameter is a 64-bit Virtual Address (VA). - - The alignment of the Base Address must be greater than or equal to the size - of the Translation Granule Size used in the Secure EL1&0 translation - regime. - - - **uint32** - Page count - - Number of pages starting from the Base Address whose memory attributes - should be changed. The page size is equal to the Translation Granule Size. - - - **uint32** - Memory Access Controls - - - Bits[1:0] : Data access permission - - - b'00 : No access - - b'01 : Read-Write access - - b'10 : Reserved - - b'11 : Read-only access - - - Bit[2] : Instruction access permission - - - b'0 : Executable - - b'1 : Non-executable - - - Bits[31:3] : Reserved. SBZ. - - A combination of attributes that mark the region with RW and Executable - permissions is prohibited. A request to mark a device memory region with - Executable permissions is prohibited. - -- Return parameters - - - **int32** - Return Code - - - ``SUCCESS``: The Memory Access Controls were changed successfully. - - - ``DENIED``: The SPM is servicing a request to change the attributes of a - memory region that overlaps with the region specified in this request. - - - ``INVALID_PARAMETER``: An invalid combination of Memory Access Controls - has been specified. The Base Address is not correctly aligned. The Secure - Partition is not allowed to access part or all of the memory region - specified in the call. - - - ``NO_MEMORY``: The SPM does not have memory resources to change the - attributes of the memory region in the translation tables. - - - ``NOT_SUPPORTED``: The SPM does not permit change of attributes of any - memory region that is accessible by the Secure Partition. Function was - called from the Non-secure world. Also returned if it is used after - ``SP_EVENT_COMPLETE_AARCH64``. - - See `Error Codes`_ for integer values that are associated with each return - code. - -- Usage - - This function is used to change the permission attributes for S-EL0 on a - memory region accessible from a Secure Partition. The size of the memory - region is equal to the Translation Granule size used in the Secure EL1&0 - translation regime. Requests to change other memory region attributes are not - currently supported. - - This function is only available at boot time. This interface is revoked after - the Secure Partition sends the first ``SP_EVENT_COMPLETE_AARCH64`` to signal - that it is initialised and ready to receive run-time requests. - -- Caller responsibilities - - The caller must obtain the Translation Granule Size of the Secure EL1&0 - translation regime from the SPM through an implementation defined method. - -- Callee responsibilities - - The SPM must preserve the original memory access controls of the region of - memory in case of an unsuccessful call.  The SPM must preserve the consistency - of the S-EL1 translation regime if this function is called on different PEs - concurrently and the memory regions specified overlap. - -Error Codes ------------ - -.. csv-table:: - :header: "Name", "Value" - - ``SUCCESS``,0 - ``NOT_SUPPORTED``,-1 - ``INVALID_PARAMETER``,-2 - ``DENIED``,-3 - ``NO_MEMORY``,-5 - ``NOT_PRESENT``,-7 - --------------- - -*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* - -.. _Armv8-A ARM: https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile -.. _instructions in the EDK2 repository: https://github.com/tianocore/edk2-staging/blob/AArch64StandaloneMm/HowtoBuild.MD -.. _Management Mode Interface Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0060a/DEN0060A_ARM_MM_Interface_Specification.pdf -.. _SDEI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf -.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf - -.. |Image 1| image:: diagrams/secure_sw_stack_tos.png -.. |Image 2| image:: diagrams/secure_sw_stack_sp.png diff --git a/docs/security-center.rst b/docs/security-center.rst deleted file mode 100644 index 672c563..0000000 --- a/docs/security-center.rst +++ /dev/null @@ -1,103 +0,0 @@ -Security Center -=============== - -Security Disclosures --------------------- - -We disclose all security vulnerabilities we find or are advised about that are -relevant for ARM Trusted Firmware (TF). We encourage responsible disclosure of -vulnerabilities and inform users as best we can about all possible issues. - -We disclose TF vulnerabilities as Security Advisories. These are listed at the -bottom of this page and announced as issues in the `GitHub issue tracker`_ with -the "security-advisory" tag. You can receive notification emails for these by -watching that project. - -Found a Security Issue? ------------------------ - -Although we try to keep TF secure, we can only do so with the help of the -community of developers and security researchers. - -If you think you have found a security vulnerability, please *do not* report it -in the `GitHub issue tracker`_. Instead send an email to -trusted-firmware-security@arm.com - -Please include: - -* Trusted Firmware version (or commit) affected - -* A description of the concern or vulnerability - -* Details on how to replicate the vulnerability, including: - - - Configuration details - - - Proof of concept exploit code - - - Any additional software or tools required - -We recommend using `this PGP/GPG key`_ for encrypting the information. This key -is also available at http://keyserver.pgp.com and LDAP port 389 of the same -server. The fingerprint for this key is: - -:: - - 1309 2C19 22B4 8E87 F17B FE5C 3AB7 EFCB 45A0 DFD0 - -If you would like replies to be encrypted, please provide your public key. - -Please give us the time to respond to you and fix the vulnerability before going -public. We do our best to respond and fix any issues quickly. We also need to -ensure providers of products that use TF have a chance to consider the -implications of the vulnerability and its remedy. - -Afterwards, we encourage you to write-up your findings about the TF source code. - -Attribution ------------ - -We will name and thank you in the ``change-log.rst`` distributed with the source -code and in any published security advisory. - -Security Advisories -------------------- - -+-----------+------------------------------------------------------------------+ -| ID | Title | -+===========+==================================================================+ -| `TFV-1`_ | Malformed Firmware Update SMC can result in copy of unexpectedly | -| | large data into secure memory | -+-----------+------------------------------------------------------------------+ -| `TFV-2`_ | Enabled secure self-hosted invasive debug interface can allow | -| | normal world to panic secure world | -+-----------+------------------------------------------------------------------+ -| `TFV-3`_ | RO memory is always executable at AArch64 Secure EL1 | -+-----------+------------------------------------------------------------------+ -| `TFV-4`_ | Malformed Firmware Update SMC can result in copy or | -| | authentication of unexpected data in secure memory in AArch32 | -| | state | -+-----------+------------------------------------------------------------------+ -| `TFV-5`_ | Not initializing or saving/restoring PMCR_EL0 can leak secure | -| | world timing information | -+-----------+------------------------------------------------------------------+ -| `TFV-6`_ | Arm Trusted Firmware exposure to speculative processor | -| | vulnerabilities using cache timing side-channels | -+-----------+------------------------------------------------------------------+ -| `TFV-7`_ | Trusted Firmware-A exposure to cache speculation vulnerability | -| | Variant 4 | -+-----------+------------------------------------------------------------------+ -| `TFV-8`_ | Not saving x0 to x3 registers can leak information from one | -| | Normal World SMC client to another | -+-----------+------------------------------------------------------------------+ - -.. _GitHub issue tracker: https://github.com/ARM-software/tf-issues/issues -.. _this PGP/GPG key: security-reporting.asc -.. _TFV-1: ./security_advisories/security-advisory-tfv-1.rst -.. _TFV-2: ./security_advisories/security-advisory-tfv-2.rst -.. _TFV-3: ./security_advisories/security-advisory-tfv-3.rst -.. _TFV-4: ./security_advisories/security-advisory-tfv-4.rst -.. _TFV-5: ./security_advisories/security-advisory-tfv-5.rst -.. _TFV-6: ./security_advisories/security-advisory-tfv-6.rst -.. _TFV-7: ./security_advisories/security-advisory-tfv-7.rst -.. _TFV-8: ./security_advisories/security-advisory-tfv-8.rst diff --git a/docs/security-reporting.asc b/docs/security-reporting.asc deleted file mode 100644 index 8c41f7b..0000000 --- a/docs/security-reporting.asc +++ /dev/null @@ -1,45 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: PGP Desktop 10.2.0 (Build 2317) - -mQENBFey/QMBCACyxJaLsMYU794ZfzLdY172tHXRJfP0X3b34HU35G7kYl1zNiYc -/NoygtQdtDv/aW1B2A/YTNhGge+gX4BWAREd5CYDbdPEoMWC395/qbnmMmez7YNY -PEJ9Iq9e5AayAWwZTL1zgKwdvE+WTwWok/nMbsifJSEdhdrOIHNqRcZgplUUyZ2R -sDqFtSbACO3xj4Psk8KJ23Ax7UZgULouZOJaHOnyq8F9V/U7zWvX4Odf96XaC1Em -cUTsG0kQfa7Y4Hqqjzowq366I4k2o2LAtuLPWNCvq5jjEceLs2+qV4cNLgyL2dzO -wtUL6EdkrGfkxsPHpsVKXig4wjeX9ehCSqRlABEBAAG0PVRydXN0ZWQgRmlybXdh -cmUgU2VjdXJpdHkgPHRydXN0ZWQtZmlybXdhcmUtc2VjdXJpdHlAYXJtLmNvbT6J -AYwEEAECAHYFAley/SEwFIAAAAAAIAAHcHJlZmVycmVkLWVtYWlsLWVuY29kaW5n -QHBncC5jb21wZ3BtaW1lCAsJCAcDAgEKAhkBGRhsZGFwOi8va2V5c2VydmVyLnBn -cC5jb20FGwMAAAAFFgADAgEFHgEAAAAGFQgJCgMCAAoJEDq378tFoN/QFJsH/0ly -H91LYYzKIQrbolQw7Rp47lgzH88uN1rInYpW2GaTbjwPffAhYJ4VsN8RaiFskD9m -DjMg4vY8p0jPTCUX1Acq20Wq0Ybv3HcrtjUp4ie0+rLUi3043yJyKFMWkJC2Kr+p -SobnxSrAie4HDFUgSaPoh9Qf1zXEzOavdgcziMiyS5iVUf6NXYZ9z82OTZ6TdPKS -u+L5zOHTdrV3+hD54w00Xa+EIE7u4v0to6Uwm977508hyGuvpOVq+u7+S3qJQvnY -+JheStbgLsm6CyoRjyrlTE01ujAD6hI6Ef9yMgEljOBEy4phKAJ67SCRLEOiCp5U -YHFCULwhzIyg2y3WmZSJASIEEAECAAwFAlezAnwFAwASdQAACgkQlxC4m8pXrXzd -GAf/T8YEICI9qQt2vnCtCbBvVaTc2sAphVZ51kZVDqCDPB7znDtJYRBpi/9IPELt -mYwIElMx2mqmahVaeUghmbzmcLZe8QHUi8GanO1mh+ook6uyjRojSIq6VUVV5uUf -tuscfhpilOvUclqMqYEIgXfl08YwS40Kmmj0qokwad0co0zGQ8GEhlgMi2yvJfiG -fPS0Xcn1J0980E/VgJQCAKwZvukrbb32WVwuhgepqs/4/62PZNxglcErioFt6P0A -ik4t9Hr0uErqCeEKiYtmEw5e9ioRdX7CV+tJgIk907Tpv6E0iDFRJHmJBvmsz82O -stOazS3wZ5Xck7asTqkvoyo9Z7kBDQRXsv0DAQgAsmL1UUIWyoNmYJWixSPDmclP -0ul3T1FCOsIlWTeVeshnHByYdgZOfce78ETCUoq8G7qvYm4GRrEDpqVbxqTxJioP -4Li05WDdNCKzSoqWd8ADA48gYnnJEu2NhA7ZkEC6u3+Mdbmd3M0J6nsAWeE0BV1p -F5zI600sJuoH2QNWB7Kv5N3GCFE4IgCIH8MwDo4Y4FTZtygx4GjEtSExiOIz+bpX -2+GkFCQGpIyLHLP4FmQmrsNzsIdEyFuG0IdoVuQ2PtNLiw+Wkm7CXWgRmFx/dtPN -eVnOFWdbTtjBWVv/Z6zbANos2knfc75KR4FCQ6pWRvVeJuMuMopUDkfFDMtR8QAR -AQABiQJBBBgBAgErBQJXsv0EBRsMAAAAwF0gBBkBCAAGBQJXsv0DAAoJENaB8ph8 -s9hu/nsH/Rx696ZR+1vZi5qCTUwo6s0Qa15x4OuyJEM85VgMLVY7/MZpp1Y8If6u -A5BynQpy4QIPxIRsRx6twduW9/gb8UVhpMRPyuJ+5sSv0/KeUqkPbKSUGro2zGlR -sjqPrchi6uafWZqOR/y/DNkEvkgZZaP+f9xs2qWKuoF08yTioo76QoroA4DVuVAT -MkDFe9d3natAmfmjO4kvxuthg3y7R+sdXrCHpYYJZdbiR6gyj7e8whlSLwHQT3lz -7QBL/CvVvL/dmhu5pk8fsksbehepMQTkCJ6GGEamOPEhwh7IvlzhEt97U4uzjuMd -BPjqOCes+4QTmn/+lMTySG0kXxnHOEUACgkQOrfvy0Wg39D8Jgf/Uf3epkMOJ9xm -N1l5vW8tQQ6RR055YQxQ9P6JMyCQGEJmGOcvrasCho69wMQDy4AYVtJaZd25LH/3 -LX/lcyDOP4C9VYXM+IxlcaRmjBKqWx9UzQeeioIkfmjMpJFU846ZP1dacge0lPx8 -p6ocPbM0rkv0xuF/dwkDQd4BPSmv4/3/UM8FRoYo8Q7SHkDR98wJ8FCm6k9wRtWC -K/jzmBswY2TewAHom3jLzTM0FZ/n5Sini3EGAI2EvnQrxWRpeE7ZOkHKqLHEOaHl -zeST4U/cUgxhwgnhbGJ7zmrFsHpYnnZYM3mIKfQ3/EhksZ68TF9IB1tfUiQTij4r -9jWa0ybRdQ== -=nZZb ------END PGP PUBLIC KEY BLOCK----- diff --git a/docs/security_advisories/index.rst b/docs/security_advisories/index.rst new file mode 100644 index 0000000..ce2c843 --- /dev/null +++ b/docs/security_advisories/index.rst @@ -0,0 +1,16 @@ +Security Advisories +=================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + security-advisory-tfv-1.rst + security-advisory-tfv-2.rst + security-advisory-tfv-3.rst + security-advisory-tfv-4.rst + security-advisory-tfv-5.rst + security-advisory-tfv-6.rst + security-advisory-tfv-7.rst + security-advisory-tfv-8.rst diff --git a/docs/spd/optee-dispatcher.rst b/docs/spd/optee-dispatcher.rst deleted file mode 100644 index 63baccc..0000000 --- a/docs/spd/optee-dispatcher.rst +++ /dev/null @@ -1,14 +0,0 @@ -OP-TEE Dispatcher -================= - -`OP-TEE OS`_ is a Trusted OS running as Secure EL1. - -To build and execute OP-TEE follow the instructions at -`OP-TEE build.git`_ - --------------- - -*Copyright (c) 2014-2018, Arm Limited and Contributors. All rights reserved.* - -.. _OP-TEE OS: https://github.com/OP-TEE/build -.. _OP-TEE build.git: https://github.com/OP-TEE/build diff --git a/docs/spd/tlk-dispatcher.rst b/docs/spd/tlk-dispatcher.rst deleted file mode 100644 index 90af5fa..0000000 --- a/docs/spd/tlk-dispatcher.rst +++ /dev/null @@ -1,76 +0,0 @@ -Trusted Little Kernel (TLK) Dispatcher -====================================== - -TLK dispatcher (TLK-D) adds support for NVIDIA's Trusted Little Kernel (TLK) -to work with Trusted Firmware-A (TF-A). TLK-D can be compiled by including it -in the platform's makefile. TLK is primarily meant to work with Tegra SoCs, -so while TF-A only supports TLK on Tegra, the dispatcher code can only be -compiled for other platforms. - -In order to compile TLK-D, we need a BL32 image to be present. Since, TLKD -just needs to compile, any BL32 image would do. To use TLK as the BL32, please -refer to the "Build TLK" section. - -Once a BL32 is ready, TLKD can be included in the image by adding "SPD=tlkd" -to the build command. - -Trusted Little Kernel (TLK) -=========================== - -TLK is a Trusted OS running as Secure EL1. It is a Free Open Source Software -(FOSS) release of the NVIDIA® Trusted Little Kernel (TLK) technology, which -extends technology made available with the development of the Little Kernel (LK). -You can download the LK modular embedded preemptive kernel for use on Arm, -x86, and AVR32 systems from https://github.com/travisg/lk - -NVIDIA implemented its Trusted Little Kernel (TLK) technology, designed as a -free and open-source trusted execution environment (OTE). - -TLK features include: - -• Small, pre-emptive kernel -• Supports multi-threading, IPCs, and thread scheduling -• Added TrustZone features -• Added Secure Storage -• Under MIT/FreeBSD license - -NVIDIA extensions to Little Kernel (LK) include: - -• User mode -• Address-space separation for TAs -• TLK Client Application (CA) library -• TLK TA library -• Crypto library (encrypt/decrypt, key handling) via OpenSSL -• Linux kernel driver -• Cortex A9/A15 support -• Power Management -• TrustZone memory carve-out (reconfigurable) -• Page table management -• Debugging support over UART (USB planned) - -TLK is hosted by NVIDIA on http://nv-tegra.nvidia.com under the -3rdparty/ote\_partner/tlk.git repository. Detailed information about -TLK and OTE can be found in the Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf -manual located under the "documentation" directory\_. - -Build TLK -========= - -To build and execute TLK, follow the instructions from "Building a TLK Device" -section from Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf manual. - -Input parameters to TLK -======================= - -TLK expects the TZDRAM size and a structure containing the boot arguments. BL2 -passes this information to the EL3 software as members of the bl32\_ep\_info -struct, where bl32\_ep\_info is part of bl31\_params\_t (passed by BL2 in X0) - -Example: --------- - -:: - - bl32_ep_info->args.arg0 = TZDRAM size available for BL32 - bl32_ep_info->args.arg1 = unused (used only on Armv7-A) - bl32_ep_info->args.arg2 = pointer to boot args diff --git a/docs/spd/trusty-dispatcher.rst b/docs/spd/trusty-dispatcher.rst deleted file mode 100644 index be08570..0000000 --- a/docs/spd/trusty-dispatcher.rst +++ /dev/null @@ -1,32 +0,0 @@ -Trusty Dispatcher -================= - -Trusty is a a set of software components, supporting a Trusted Execution -Environment (TEE) on mobile devices, published and maintained by Google. - -Detailed information and build instructions can be found on the Android -Open Source Project (AOSP) webpage for Trusty hosted at -https://source.android.com/security/trusty - -Boot parameters -=============== - -Custom boot parameters can be passed to Trusty by providing a platform -specific function: - -.. code:: c - - void plat_trusty_set_boot_args(aapcs64_params_t *args) - -If this function is provided ``args->arg0`` must be set to the memory -size allocated to trusty. If the platform does not provide this -function, but defines ``TSP_SEC_MEM_SIZE``, a default implementation -will pass the memory size from ``TSP_SEC_MEM_SIZE``. ``args->arg1`` -can be set to a platform specific parameter block, and ``args->arg2`` -should then be set to the size of that block. - -Supported platforms -=================== - -Out of all the platforms supported by Trusted Firmware-A, Trusty is only -verified and supported by NVIDIA's Tegra SoCs. diff --git a/docs/trusted-board-boot.rst b/docs/trusted-board-boot.rst deleted file mode 100644 index 3ba9636..0000000 --- a/docs/trusted-board-boot.rst +++ /dev/null @@ -1,240 +0,0 @@ -Trusted Board Boot Design Guide -=============================== - - -.. section-numbering:: - :suffix: . - -.. contents:: - -The Trusted Board Boot (TBB) feature prevents malicious firmware from running on -the platform by authenticating all firmware images up to and including the -normal world bootloader. It does this by establishing a Chain of Trust using -Public-Key-Cryptography Standards (PKCS). - -This document describes the design of Trusted Firmware-A (TF-A) TBB, which is an -implementation of the `Trusted Board Boot Requirements (TBBR)`_ specification, -Arm DEN0006D. It should be used in conjunction with the `Firmware Update`_ -design document, which implements a specific aspect of the TBBR. - -Chain of Trust --------------- - -A Chain of Trust (CoT) starts with a set of implicitly trusted components. On -the Arm development platforms, these components are: - -- A SHA-256 hash of the Root of Trust Public Key (ROTPK). It is stored in the - trusted root-key storage registers. - -- The BL1 image, on the assumption that it resides in ROM so cannot be - tampered with. - -The remaining components in the CoT are either certificates or boot loader -images. The certificates follow the `X.509 v3`_ standard. This standard -enables adding custom extensions to the certificates, which are used to store -essential information to establish the CoT. - -In the TBB CoT all certificates are self-signed. There is no need for a -Certificate Authority (CA) because the CoT is not established by verifying the -validity of a certificate's issuer but by the content of the certificate -extensions. To sign the certificates, the PKCS#1 SHA-256 with RSA Encryption -signature scheme is used with a RSA key length of 2048 bits. Future version of -TF-A will support additional cryptographic algorithms. - -The certificates are categorised as "Key" and "Content" certificates. Key -certificates are used to verify public keys which have been used to sign content -certificates. Content certificates are used to store the hash of a boot loader -image. An image can be authenticated by calculating its hash and matching it -with the hash extracted from the content certificate. The SHA-256 function is -used to calculate all hashes. The public keys and hashes are included as -non-standard extension fields in the `X.509 v3`_ certificates. - -The keys used to establish the CoT are: - -- **Root of trust key** - - The private part of this key is used to sign the BL2 content certificate and - the trusted key certificate. The public part is the ROTPK. - -- **Trusted world key** - - The private part is used to sign the key certificates corresponding to the - secure world images (SCP_BL2, BL31 and BL32). The public part is stored in - one of the extension fields in the trusted world certificate. - -- **Non-trusted world key** - - The private part is used to sign the key certificate corresponding to the - non secure world image (BL33). The public part is stored in one of the - extension fields in the trusted world certificate. - -- **BL3-X keys** - - For each of SCP_BL2, BL31, BL32 and BL33, the private part is used to - sign the content certificate for the BL3-X image. The public part is stored - in one of the extension fields in the corresponding key certificate. - -The following images are included in the CoT: - -- BL1 -- BL2 -- SCP_BL2 (optional) -- BL31 -- BL33 -- BL32 (optional) - -The following certificates are used to authenticate the images. - -- **BL2 content certificate** - - It is self-signed with the private part of the ROT key. It contains a hash - of the BL2 image. - -- **Trusted key certificate** - - It is self-signed with the private part of the ROT key. It contains the - public part of the trusted world key and the public part of the non-trusted - world key. - -- **SCP_BL2 key certificate** - - It is self-signed with the trusted world key. It contains the public part of - the SCP_BL2 key. - -- **SCP_BL2 content certificate** - - It is self-signed with the SCP_BL2 key. It contains a hash of the SCP_BL2 - image. - -- **BL31 key certificate** - - It is self-signed with the trusted world key. It contains the public part of - the BL31 key. - -- **BL31 content certificate** - - It is self-signed with the BL31 key. It contains a hash of the BL31 image. - -- **BL32 key certificate** - - It is self-signed with the trusted world key. It contains the public part of - the BL32 key. - -- **BL32 content certificate** - - It is self-signed with the BL32 key. It contains a hash of the BL32 image. - -- **BL33 key certificate** - - It is self-signed with the non-trusted world key. It contains the public - part of the BL33 key. - -- **BL33 content certificate** - - It is self-signed with the BL33 key. It contains a hash of the BL33 image. - -The SCP_BL2 and BL32 certificates are optional, but they must be present if the -corresponding SCP_BL2 or BL32 images are present. - -Trusted Board Boot Sequence ---------------------------- - -The CoT is verified through the following sequence of steps. The system panics -if any of the steps fail. - -- BL1 loads and verifies the BL2 content certificate. The issuer public key is - read from the verified certificate. A hash of that key is calculated and - compared with the hash of the ROTPK read from the trusted root-key storage - registers. If they match, the BL2 hash is read from the certificate. - - Note: the matching operation is platform specific and is currently - unimplemented on the Arm development platforms. - -- BL1 loads the BL2 image. Its hash is calculated and compared with the hash - read from the certificate. Control is transferred to the BL2 image if all - the comparisons succeed. - -- BL2 loads and verifies the trusted key certificate. The issuer public key is - read from the verified certificate. A hash of that key is calculated and - compared with the hash of the ROTPK read from the trusted root-key storage - registers. If the comparison succeeds, BL2 reads and saves the trusted and - non-trusted world public keys from the verified certificate. - -The next two steps are executed for each of the SCP_BL2, BL31 & BL32 images. -The steps for the optional SCP_BL2 and BL32 images are skipped if these images -are not present. - -- BL2 loads and verifies the BL3x key certificate. The certificate signature - is verified using the trusted world public key. If the signature - verification succeeds, BL2 reads and saves the BL3x public key from the - certificate. - -- BL2 loads and verifies the BL3x content certificate. The signature is - verified using the BL3x public key. If the signature verification succeeds, - BL2 reads and saves the BL3x image hash from the certificate. - -The next two steps are executed only for the BL33 image. - -- BL2 loads and verifies the BL33 key certificate. If the signature - verification succeeds, BL2 reads and saves the BL33 public key from the - certificate. - -- BL2 loads and verifies the BL33 content certificate. If the signature - verification succeeds, BL2 reads and saves the BL33 image hash from the - certificate. - -The next step is executed for all the boot loader images. - -- BL2 calculates the hash of each image. It compares it with the hash obtained - from the corresponding content certificate. The image authentication succeeds - if the hashes match. - -The Trusted Board Boot implementation spans both generic and platform-specific -BL1 and BL2 code, and in tool code on the host build machine. The feature is -enabled through use of specific build flags as described in the `User Guide`_. - -On the host machine, a tool generates the certificates, which are included in -the FIP along with the boot loader images. These certificates are loaded in -Trusted SRAM using the IO storage framework. They are then verified by an -Authentication module included in TF-A. - -The mechanism used for generating the FIP and the Authentication module are -described in the following sections. - -Authentication Framework ------------------------- - -The authentication framework included in TF-A provides support to implement -the desired trusted boot sequence. Arm platforms use this framework to -implement the boot requirements specified in the `TBBR-client`_ document. - -More information about the authentication framework can be found in the -`Auth Framework`_ document. - -Certificate Generation Tool ---------------------------- - -The ``cert_create`` tool is built and runs on the host machine as part of the -TF-A build process when ``GENERATE_COT=1``. It takes the boot loader images -and keys as inputs (keys must be in PEM format) and generates the -certificates (in DER format) required to establish the CoT. New keys can be -generated by the tool in case they are not provided. The certificates are then -passed as inputs to the ``fiptool`` utility for creating the FIP. - -The certificates are also stored individually in the in the output build -directory. - -The tool resides in the ``tools/cert_create`` directory. It uses OpenSSL SSL -library version 1.0.1 or later to generate the X.509 certificates. Instructions -for building and using the tool can be found in the `User Guide`_. - --------------- - -*Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.* - -.. _Firmware Update: firmware-update.rst -.. _X.509 v3: https://tools.ietf.org/rfc/rfc5280.txt -.. _User Guide: user-guide.rst -.. _Auth Framework: auth-framework.rst -.. _TBBR-client: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a -.. _Trusted Board Boot Requirements (TBBR): `TBBR-client`_ diff --git a/docs/user-guide.rst b/docs/user-guide.rst deleted file mode 100644 index 0079b1a..0000000 --- a/docs/user-guide.rst +++ /dev/null @@ -1,2143 +0,0 @@ -Trusted Firmware-A User Guide -============================= - - -.. section-numbering:: - :suffix: . - -.. contents:: - -This document describes how to build Trusted Firmware-A (TF-A) and run it with a -tested set of other software components using defined configurations on the Juno -Arm development platform and Arm Fixed Virtual Platform (FVP) models. It is -possible to use other software components, configurations and platforms but that -is outside the scope of this document. - -This document assumes that the reader has previous experience running a fully -bootable Linux software stack on Juno or FVP using the prebuilt binaries and -filesystems provided by `Linaro`_. Further information may be found in the -`Linaro instructions`_. It also assumes that the user understands the role of -the different software components required to boot a Linux system: - -- Specific firmware images required by the platform (e.g. SCP firmware on Juno) -- Normal world bootloader (e.g. UEFI or U-Boot) -- Device tree -- Linux kernel image -- Root filesystem - -This document also assumes that the user is familiar with the `FVP models`_ and -the different command line options available to launch the model. - -This document should be used in conjunction with the `Firmware Design`_. - -Host machine requirements -------------------------- - -The minimum recommended machine specification for building the software and -running the FVP models is a dual-core processor running at 2GHz with 12GB of -RAM. For best performance, use a machine with a quad-core processor running at -2.6GHz with 16GB of RAM. - -The software has been tested on Ubuntu 16.04 LTS (64-bit). Packages used for -building the software were installed from that distribution unless otherwise -specified. - -The software has also been built on Windows 7 Enterprise SP1, using CMD.EXE, -Cygwin, and Msys (MinGW) shells, using version 5.3.1 of the GNU toolchain. - -Tools ------ - -Install the required packages to build TF-A with the following command: - -:: - - sudo apt-get install device-tree-compiler build-essential gcc make git libssl-dev - -TF-A has been tested with Linaro Release 18.04. - -Download and install the AArch32 or AArch64 little-endian GCC cross compiler. If -you would like to use the latest features available, download GCC 8.2-2019.01 -compiler from `arm Developer page`_. Otherwise, the `Linaro Release Notes`_ -documents which version of the compiler to use for a given Linaro Release. Also, -these `Linaro instructions`_ provide further guidance and a script, which can be -used to download Linaro deliverables automatically. - -Optionally, TF-A can be built using clang version 4.0 or newer or Arm -Compiler 6. See instructions below on how to switch the default compiler. - -In addition, the following optional packages and tools may be needed: - -- ``device-tree-compiler`` (dtc) package if you need to rebuild the Flattened Device - Tree (FDT) source files (``.dts`` files) provided with this software. The - version of dtc must be 1.4.6 or above. - -- For debugging, Arm `Development Studio 5 (DS-5)`_. - -- To create and modify the diagram files included in the documentation, `Dia`_. - This tool can be found in most Linux distributions. Inkscape is needed to - generate the actual \*.png files. - -Getting the TF-A source code ----------------------------- - -Clone the repository from the Gerrit server. The project details may be found -on the `arm-trusted-firmware-a project page`_. We recommend the "`Clone with -commit-msg hook`" clone method, which will setup the git commit hook that -automatically generates and inserts appropriate `Change-Id:` lines in your -commit messages. - -Checking source code style -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Trusted Firmware follows the `Linux Coding Style`_ . When making changes to the -source, for submission to the project, the source must be in compliance with -this style guide. - -Additional, project-specific guidelines are defined in the `Trusted Firmware-A -Coding Guidelines`_ document. - -To assist with coding style compliance, the project Makefile contains two -targets which both utilise the `checkpatch.pl` script that ships with the Linux -source tree. The project also defines certain *checkpatch* options in the -``.checkpatch.conf`` file in the top-level directory. - -**Note:** Checkpatch errors will gate upstream merging of pull requests. -Checkpatch warnings will not gate merging but should be reviewed and fixed if -possible. - -To check the entire source tree, you must first download copies of -``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available -in the `Linux master tree`_ *scripts* directory, then set the ``CHECKPATCH`` -environment variable to point to ``checkpatch.pl`` (with the other 2 files in -the same directory) and build the `checkcodebase` target: - -:: - - make CHECKPATCH=/linux/scripts/checkpatch.pl checkcodebase - -To just check the style on the files that differ between your local branch and -the remote master, use: - -:: - - make CHECKPATCH=/linux/scripts/checkpatch.pl checkpatch - -If you wish to check your patch against something other than the remote master, -set the ``BASE_COMMIT`` variable to your desired branch. By default, ``BASE_COMMIT`` -is set to ``origin/master``. - -Building TF-A -------------- - -- Before building TF-A, the environment variable ``CROSS_COMPILE`` must point - to the Linaro cross compiler. - - For AArch64: - - :: - - export CROSS_COMPILE=/bin/aarch64-linux-gnu- - - For AArch32: - - :: - - export CROSS_COMPILE=/bin/arm-linux-gnueabihf- - - It is possible to build TF-A using Clang or Arm Compiler 6. To do so - ``CC`` needs to point to the clang or armclang binary, which will - also select the clang or armclang assembler. Be aware that the - GNU linker is used by default. In case of being needed the linker - can be overridden using the ``LD`` variable. Clang linker version 6 is - known to work with TF-A. - - In both cases ``CROSS_COMPILE`` should be set as described above. - - Arm Compiler 6 will be selected when the base name of the path assigned - to ``CC`` matches the string 'armclang'. - - For AArch64 using Arm Compiler 6: - - :: - - export CROSS_COMPILE=/bin/aarch64-linux-gnu- - make CC=/bin/armclang PLAT= all - - Clang will be selected when the base name of the path assigned to ``CC`` - contains the string 'clang'. This is to allow both clang and clang-X.Y - to work. - - For AArch64 using clang: - - :: - - export CROSS_COMPILE=/bin/aarch64-linux-gnu- - make CC=/bin/clang PLAT= all - -- Change to the root directory of the TF-A source tree and build. - - For AArch64: - - :: - - make PLAT= all - - For AArch32: - - :: - - make PLAT= ARCH=aarch32 AARCH32_SP=sp_min all - - Notes: - - - If ``PLAT`` is not specified, ``fvp`` is assumed by default. See the - `Summary of build options`_ for more information on available build - options. - - - (AArch32 only) Currently only ``PLAT=fvp`` is supported. - - - (AArch32 only) ``AARCH32_SP`` is the AArch32 EL3 Runtime Software and it - corresponds to the BL32 image. A minimal ``AARCH32_SP``, sp_min, is - provided by TF-A to demonstrate how PSCI Library can be integrated with - an AArch32 EL3 Runtime Software. Some AArch32 EL3 Runtime Software may - include other runtime services, for example Trusted OS services. A guide - to integrate PSCI library with AArch32 EL3 Runtime Software can be found - `here`_. - - - (AArch64 only) The TSP (Test Secure Payload), corresponding to the BL32 - image, is not compiled in by default. Refer to the - `Building the Test Secure Payload`_ section below. - - - By default this produces a release version of the build. To produce a - debug version instead, refer to the "Debugging options" section below. - - - The build process creates products in a ``build`` directory tree, building - the objects and binaries for each boot loader stage in separate - sub-directories. The following boot loader binary files are created - from the corresponding ELF files: - - - ``build///bl1.bin`` - - ``build///bl2.bin`` - - ``build///bl31.bin`` (AArch64 only) - - ``build///bl32.bin`` (mandatory for AArch32) - - where ```` is the name of the chosen platform and ```` - is either ``debug`` or ``release``. The actual number of images might differ - depending on the platform. - -- Build products for a specific build variant can be removed using: - - :: - - make DEBUG= PLAT= clean - - ... where ```` is ``0`` or ``1``, as specified when building. - - The build tree can be removed completely using: - - :: - - make realclean - -Summary of build options -~~~~~~~~~~~~~~~~~~~~~~~~ - -The TF-A build system supports the following build options. Unless mentioned -otherwise, these options are expected to be specified at the build command -line and are not to be modified in any component makefiles. Note that the -build system doesn't track dependency for build options. Therefore, if any of -the build options are changed from a previous build, a clean build must be -performed. - -Common build options -^^^^^^^^^^^^^^^^^^^^ - -- ``AARCH32_INSTRUCTION_SET``: Choose the AArch32 instruction set that the - compiler should use. Valid values are T32 and A32. It defaults to T32 due to - code having a smaller resulting size. - -- ``AARCH32_SP`` : Choose the AArch32 Secure Payload component to be built as - as the BL32 image when ``ARCH=aarch32``. The value should be the path to the - directory containing the SP source, relative to the ``bl32/``; the directory - is expected to contain a makefile called ``.mk``. - -- ``ARCH`` : Choose the target build architecture for TF-A. It can take either - ``aarch64`` or ``aarch32`` as values. By default, it is defined to - ``aarch64``. - -- ``ARM_ARCH_MAJOR``: The major version of Arm Architecture to target when - compiling TF-A. Its value must be numeric, and defaults to 8 . See also, - *Armv8 Architecture Extensions* and *Armv7 Architecture Extensions* in - `Firmware Design`_. - -- ``ARM_ARCH_MINOR``: The minor version of Arm Architecture to target when - compiling TF-A. Its value must be a numeric, and defaults to 0. See also, - *Armv8 Architecture Extensions* in `Firmware Design`_. - -- ``BL2``: This is an optional build option which specifies the path to BL2 - image for the ``fip`` target. In this case, the BL2 in the TF-A will not be - built. - -- ``BL2U``: This is an optional build option which specifies the path to - BL2U image. In this case, the BL2U in TF-A will not be built. - -- ``BL2_AT_EL3``: This is an optional build option that enables the use of - BL2 at EL3 execution level. - -- ``BL2_IN_XIP_MEM``: In some use-cases BL2 will be stored in eXecute In Place - (XIP) memory, like BL1. In these use-cases, it is necessary to initialize - the RW sections in RAM, while leaving the RO sections in place. This option - enable this use-case. For now, this option is only supported when BL2_AT_EL3 - is set to '1'. - -- ``BL31``: This is an optional build option which specifies the path to - BL31 image for the ``fip`` target. In this case, the BL31 in TF-A will not - be built. - -- ``BL31_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the - file that contains the BL31 private key in PEM format. If ``SAVE_KEYS=1``, - this file name will be used to save the key. - -- ``BL32``: This is an optional build option which specifies the path to - BL32 image for the ``fip`` target. In this case, the BL32 in TF-A will not - be built. - -- ``BL32_EXTRA1``: This is an optional build option which specifies the path to - Trusted OS Extra1 image for the ``fip`` target. - -- ``BL32_EXTRA2``: This is an optional build option which specifies the path to - Trusted OS Extra2 image for the ``fip`` target. - -- ``BL32_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the - file that contains the BL32 private key in PEM format. If ``SAVE_KEYS=1``, - this file name will be used to save the key. - -- ``BL33``: Path to BL33 image in the host file system. This is mandatory for - ``fip`` target in case TF-A BL2 is used. - -- ``BL33_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the - file that contains the BL33 private key in PEM format. If ``SAVE_KEYS=1``, - this file name will be used to save the key. - -- ``BUILD_MESSAGE_TIMESTAMP``: String used to identify the time and date of the - compilation of each build. It must be set to a C string (including quotes - where applicable). Defaults to a string that contains the time and date of - the compilation. - -- ``BUILD_STRING``: Input string for VERSION_STRING, which allows the TF-A - build to be uniquely identified. Defaults to the current git commit id. - -- ``CFLAGS``: Extra user options appended on the compiler's command line in - addition to the options set by the build system. - -- ``COLD_BOOT_SINGLE_CPU``: This option indicates whether the platform may - release several CPUs out of reset. It can take either 0 (several CPUs may be - brought up) or 1 (only one CPU will ever be brought up during cold reset). - Default is 0. If the platform always brings up a single CPU, there is no - need to distinguish between primary and secondary CPUs and the boot path can - be optimised. The ``plat_is_my_cpu_primary()`` and - ``plat_secondary_cold_boot_setup()`` platform porting interfaces do not need - to be implemented in this case. - -- ``CRASH_REPORTING``: A non-zero value enables a console dump of processor - register state when an unexpected exception occurs during execution of - BL31. This option defaults to the value of ``DEBUG`` - i.e. by default - this is only enabled for a debug build of the firmware. - -- ``CREATE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the - certificate generation tool to create new keys in case no valid keys are - present or specified. Allowed options are '0' or '1'. Default is '1'. - -- ``CTX_INCLUDE_AARCH32_REGS`` : Boolean option that, when set to 1, will cause - the AArch32 system registers to be included when saving and restoring the - CPU context. The option must be set to 0 for AArch64-only platforms (that - is on hardware that does not implement AArch32, or at least not at EL1 and - higher ELs). Default value is 1. - -- ``CTX_INCLUDE_FPREGS``: Boolean option that, when set to 1, will cause the FP - registers to be included when saving and restoring the CPU context. Default - is 0. - -- ``CTX_INCLUDE_PAUTH_REGS``: Boolean option that, when set to 1, allows - Pointer Authentication for **Secure world**. This will cause the - Armv8.3-PAuth registers to be included when saving and restoring the CPU - context as part of a world switch. Default value is 0. Pointer Authentication - is an experimental feature. - - Note that, if the CPU supports it, Pointer Authentication is allowed for - Non-secure world irrespectively of the value of this flag. "Allowed" means - that accesses to PAuth-related registers or execution of PAuth-related - instructions will not be trapped to EL3. As such, usage or not of PAuth in - Non-secure world images, depends on those images themselves. - -- ``DEBUG``: Chooses between a debug and release build. It can take either 0 - (release) or 1 (debug) as values. 0 is the default. - -- ``DISABLE_BIN_GENERATION``: Boolean option to disable the generation - of the binary image. If set to 1, then only the ELF image is built. - 0 is the default. - -- ``DYN_DISABLE_AUTH``: Provides the capability to dynamically disable Trusted - Board Boot authentication at runtime. This option is meant to be enabled only - for development platforms. ``TRUSTED_BOARD_BOOT`` flag must be set if this - flag has to be enabled. 0 is the default. - -- ``EL3_PAYLOAD_BASE``: This option enables booting an EL3 payload instead of - the normal boot flow. It must specify the entry point address of the EL3 - payload. Please refer to the "Booting an EL3 payload" section for more - details. - -- ``ENABLE_AMU``: Boolean option to enable Activity Monitor Unit extensions. - This is an optional architectural feature available on v8.4 onwards. Some - v8.2 implementations also implement an AMU and this option can be used to - enable this feature on those systems as well. Default is 0. - -- ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()`` - are compiled out. For debug builds, this option defaults to 1, and calls to - ``assert()`` are left in place. For release builds, this option defaults to 0 - and calls to ``assert()`` function are compiled out. This option can be set - independently of ``DEBUG``. It can also be used to hide any auxiliary code - that is only required for the assertion and does not fit in the assertion - itself. - -- ``ENABLE_BACKTRACE``: This option controls whether to enables backtrace - dumps or not. It is supported in both AArch64 and AArch32. However, in - AArch32 the format of the frame records are not defined in the AAPCS and they - are defined by the implementation. This implementation of backtrace only - supports the format used by GCC when T32 interworking is disabled. For this - reason enabling this option in AArch32 will force the compiler to only - generate A32 code. This option is enabled by default only in AArch64 debug - builds, but this behaviour can be overridden in each platform's Makefile or - in the build command line. - -- ``ENABLE_MPAM_FOR_LOWER_ELS``: Boolean option to enable lower ELs to use MPAM - feature. MPAM is an optional Armv8.4 extension that enables various memory - system components and resources to define partitions; software running at - various ELs can assign themselves to desired partition to control their - performance aspects. - - When this option is set to ``1``, EL3 allows lower ELs to access their own - MPAM registers without trapping into EL3. This option doesn't make use of - partitioning in EL3, however. Platform initialisation code should configure - and use partitions in EL3 as required. This option defaults to ``0``. - -- ``ENABLE_PAUTH``: Boolean option to enable Armv8.3 Pointer Authentication - for **TF-A BL images themselves**. If enabled, the compiler must support the - ``-msign-return-address`` option. This flag defaults to 0. Pointer - Authentication is an experimental feature. - - If this flag is enabled, ``CTX_INCLUDE_PAUTH_REGS`` must also be enabled. - -- ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE) - support within generic code in TF-A. This option is currently only supported - in BL31. Default is 0. - -- ``ENABLE_PMF``: Boolean option to enable support for optional Performance - Measurement Framework(PMF). Default is 0. - -- ``ENABLE_PSCI_STAT``: Boolean option to enable support for optional PSCI - functions ``PSCI_STAT_RESIDENCY`` and ``PSCI_STAT_COUNT``. Default is 0. - In the absence of an alternate stat collection backend, ``ENABLE_PMF`` must - be enabled. If ``ENABLE_PMF`` is set, the residency statistics are tracked in - software. - -- ``ENABLE_RUNTIME_INSTRUMENTATION``: Boolean option to enable runtime - instrumentation which injects timestamp collection points into TF-A to - allow runtime performance to be measured. Currently, only PSCI is - instrumented. Enabling this option enables the ``ENABLE_PMF`` build option - as well. Default is 0. - -- ``ENABLE_SPE_FOR_LOWER_ELS`` : Boolean option to enable Statistical Profiling - extensions. This is an optional architectural feature for AArch64. - The default is 1 but is automatically disabled when the target architecture - is AArch32. - -- ``ENABLE_SPM`` : Boolean option to enable the Secure Partition Manager (SPM). - Refer to the `Secure Partition Manager Design guide`_ for more details about - this feature. Default is 0. - -- ``ENABLE_SVE_FOR_NS``: Boolean option to enable Scalable Vector Extension - (SVE) for the Non-secure world only. SVE is an optional architectural feature - for AArch64. Note that when SVE is enabled for the Non-secure world, access - to SIMD and floating-point functionality from the Secure world is disabled. - This is to avoid corruption of the Non-secure world data in the Z-registers - which are aliased by the SIMD and FP registers. The build option is not - compatible with the ``CTX_INCLUDE_FPREGS`` build option, and will raise an - assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS`` set to - 1. The default is 1 but is automatically disabled when the target - architecture is AArch32. - -- ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection - checks in GCC. Allowed values are "all", "strong", "default" and "none". The - default value is set to "none". "strong" is the recommended stack protection - level if this feature is desired. "none" disables the stack protection. For - all values other than "none", the ``plat_get_stack_protector_canary()`` - platform hook needs to be implemented. The value is passed as the last - component of the option ``-fstack-protector-$ENABLE_STACK_PROTECTOR``. - -- ``ERROR_DEPRECATED``: This option decides whether to treat the usage of - deprecated platform APIs, helper functions or drivers within Trusted - Firmware as error. It can take the value 1 (flag the use of deprecated - APIs as error) or 0. The default is 0. - -- ``EL3_EXCEPTION_HANDLING``: When set to ``1``, enable handling of exceptions - targeted at EL3. When set ``0`` (default), no exceptions are expected or - handled at EL3, and a panic will result. This is supported only for AArch64 - builds. - -- ``FAULT_INJECTION_SUPPORT``: ARMv8.4 extensions introduced support for fault - injection from lower ELs, and this build option enables lower ELs to use - Error Records accessed via System Registers to inject faults. This is - applicable only to AArch64 builds. - - This feature is intended for testing purposes only, and is advisable to keep - disabled for production images. - -- ``FIP_NAME``: This is an optional build option which specifies the FIP - filename for the ``fip`` target. Default is ``fip.bin``. - -- ``FWU_FIP_NAME``: This is an optional build option which specifies the FWU - FIP filename for the ``fwu_fip`` target. Default is ``fwu_fip.bin``. - -- ``GENERATE_COT``: Boolean flag used to build and execute the ``cert_create`` - tool to create certificates as per the Chain of Trust described in - `Trusted Board Boot`_. The build system then calls ``fiptool`` to - include the certificates in the FIP and FWU_FIP. Default value is '0'. - - Specify both ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=1`` to include support - for the Trusted Board Boot feature in the BL1 and BL2 images, to generate - the corresponding certificates, and to include those certificates in the - FIP and FWU_FIP. - - Note that if ``TRUSTED_BOARD_BOOT=0`` and ``GENERATE_COT=1``, the BL1 and BL2 - images will not include support for Trusted Board Boot. The FIP will still - include the corresponding certificates. This FIP can be used to verify the - Chain of Trust on the host machine through other mechanisms. - - Note that if ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=0``, the BL1 and BL2 - images will include support for Trusted Board Boot, but the FIP and FWU_FIP - will not include the corresponding certificates, causing a boot failure. - -- ``GICV2_G0_FOR_EL3``: Unlike GICv3, the GICv2 architecture doesn't have - inherent support for specific EL3 type interrupts. Setting this build option - to ``1`` assumes GICv2 *Group 0* interrupts are expected to target EL3, both - by `platform abstraction layer`__ and `Interrupt Management Framework`__. - This allows GICv2 platforms to enable features requiring EL3 interrupt type. - This also means that all GICv2 Group 0 interrupts are delivered to EL3, and - the Secure Payload interrupts needs to be synchronously handed over to Secure - EL1 for handling. The default value of this option is ``0``, which means the - Group 0 interrupts are assumed to be handled by Secure EL1. - - .. __: `platform-interrupt-controller-API.rst` - .. __: `interrupt-framework-design.rst` - -- ``HANDLE_EA_EL3_FIRST``: When set to ``1``, External Aborts and SError - Interrupts will be always trapped in EL3 i.e. in BL31 at runtime. When set to - ``0`` (default), these exceptions will be trapped in the current exception - level (or in EL1 if the current exception level is EL0). - -- ``HW_ASSISTED_COHERENCY``: On most Arm systems to-date, platform-specific - software operations are required for CPUs to enter and exit coherency. - However, newer systems exist where CPUs' entry to and exit from coherency - is managed in hardware. Such systems require software to only initiate these - operations, and the rest is managed in hardware, minimizing active software - management. In such systems, this boolean option enables TF-A to carry out - build and run-time optimizations during boot and power management operations. - This option defaults to 0 and if it is enabled, then it implies - ``WARMBOOT_ENABLE_DCACHE_EARLY`` is also enabled. - - If this flag is disabled while the platform which TF-A is compiled for - includes cores that manage coherency in hardware, then a compilation error is - generated. This is based on the fact that a system cannot have, at the same - time, cores that manage coherency in hardware and cores that don't. In other - words, a platform cannot have, at the same time, cores that require - ``HW_ASSISTED_COHERENCY=1`` and cores that require - ``HW_ASSISTED_COHERENCY=0``. - - Note that, when ``HW_ASSISTED_COHERENCY`` is enabled, version 2 of - translation library (xlat tables v2) must be used; version 1 of translation - library is not supported. - -- ``JUNO_AARCH32_EL3_RUNTIME``: This build flag enables you to execute EL3 - runtime software in AArch32 mode, which is required to run AArch32 on Juno. - By default this flag is set to '0'. Enabling this flag builds BL1 and BL2 in - AArch64 and facilitates the loading of ``SP_MIN`` and BL33 as AArch32 executable - images. - -- ``KEY_ALG``: This build flag enables the user to select the algorithm to be - used for generating the PKCS keys and subsequent signing of the certificate. - It accepts 3 values: ``rsa``, ``rsa_1_5`` and ``ecdsa``. The option - ``rsa_1_5`` is the legacy PKCS#1 RSA 1.5 algorithm which is not TBBR - compliant and is retained only for compatibility. The default value of this - flag is ``rsa`` which is the TBBR compliant PKCS#1 RSA 2.1 scheme. - -- ``HASH_ALG``: This build flag enables the user to select the secure hash - algorithm. It accepts 3 values: ``sha256``, ``sha384`` and ``sha512``. - The default value of this flag is ``sha256``. - -- ``LDFLAGS``: Extra user options appended to the linkers' command line in - addition to the one set by the build system. - -- ``LOG_LEVEL``: Chooses the log level, which controls the amount of console log - output compiled into the build. This should be one of the following: - - :: - - 0 (LOG_LEVEL_NONE) - 10 (LOG_LEVEL_ERROR) - 20 (LOG_LEVEL_NOTICE) - 30 (LOG_LEVEL_WARNING) - 40 (LOG_LEVEL_INFO) - 50 (LOG_LEVEL_VERBOSE) - - All log output up to and including the selected log level is compiled into - the build. The default value is 40 in debug builds and 20 in release builds. - -- ``NON_TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It - specifies the file that contains the Non-Trusted World private key in PEM - format. If ``SAVE_KEYS=1``, this file name will be used to save the key. - -- ``NS_BL2U``: Path to NS_BL2U image in the host file system. This image is - optional. It is only needed if the platform makefile specifies that it - is required in order to build the ``fwu_fip`` target. - -- ``NS_TIMER_SWITCH``: Enable save and restore for non-secure timer register - contents upon world switch. It can take either 0 (don't save and restore) or - 1 (do save and restore). 0 is the default. An SPD may set this to 1 if it - wants the timer registers to be saved and restored. - -- ``OVERRIDE_LIBC``: This option allows platforms to override the default libc - for the BL image. It can be either 0 (include) or 1 (remove). The default - value is 0. - -- ``PL011_GENERIC_UART``: Boolean option to indicate the PL011 driver that - the underlying hardware is not a full PL011 UART but a minimally compliant - generic UART, which is a subset of the PL011. The driver will not access - any register that is not part of the SBSA generic UART specification. - Default value is 0 (a full PL011 compliant UART is present). - -- ``PLAT``: Choose a platform to build TF-A for. The chosen platform name - must be subdirectory of any depth under ``plat/``, and must contain a - platform makefile named ``platform.mk``. For example, to build TF-A for the - Arm Juno board, select PLAT=juno. - -- ``PRELOADED_BL33_BASE``: This option enables booting a preloaded BL33 image - instead of the normal boot flow. When defined, it must specify the entry - point address for the preloaded BL33 image. This option is incompatible with - ``EL3_PAYLOAD_BASE``. If both are defined, ``EL3_PAYLOAD_BASE`` has priority - over ``PRELOADED_BL33_BASE``. - -- ``PROGRAMMABLE_RESET_ADDRESS``: This option indicates whether the reset - vector address can be programmed or is fixed on the platform. It can take - either 0 (fixed) or 1 (programmable). Default is 0. If the platform has a - programmable reset address, it is expected that a CPU will start executing - code directly at the right address, both on a cold and warm reset. In this - case, there is no need to identify the entrypoint on boot and the boot path - can be optimised. The ``plat_get_my_entrypoint()`` platform porting interface - does not need to be implemented in this case. - -- ``PSCI_EXTENDED_STATE_ID``: As per PSCI1.0 Specification, there are 2 formats - possible for the PSCI power-state parameter: original and extended State-ID - formats. This flag if set to 1, configures the generic PSCI layer to use the - extended format. The default value of this flag is 0, which means by default - the original power-state format is used by the PSCI implementation. This flag - should be specified by the platform makefile and it governs the return value - of PSCI_FEATURES API for CPU_SUSPEND smc function id. When this option is - enabled on Arm platforms, the option ``ARM_RECOM_STATE_ID_ENC`` needs to be - set to 1 as well. - -- ``RAS_EXTENSION``: When set to ``1``, enable Armv8.2 RAS features. RAS features - are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2 - or later CPUs. - - When ``RAS_EXTENSION`` is set to ``1``, ``HANDLE_EA_EL3_FIRST`` must also be - set to ``1``. - - This option is disabled by default. - -- ``RESET_TO_BL31``: Enable BL31 entrypoint as the CPU reset vector instead - of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1 - entrypoint) or 1 (CPU reset to BL31 entrypoint). - The default value is 0. - -- ``RESET_TO_SP_MIN``: SP_MIN is the minimal AArch32 Secure Payload provided - in TF-A. This flag configures SP_MIN entrypoint as the CPU reset vector - instead of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1 - entrypoint) or 1 (CPU reset to SP_MIN entrypoint). The default value is 0. - -- ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the - file that contains the ROT private key in PEM format. If ``SAVE_KEYS=1``, this - file name will be used to save the key. - -- ``SAVE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the - certificate generation tool to save the keys used to establish the Chain of - Trust. Allowed options are '0' or '1'. Default is '0' (do not save). - -- ``SCP_BL2``: Path to SCP_BL2 image in the host file system. This image is optional. - If a SCP_BL2 image is present then this option must be passed for the ``fip`` - target. - -- ``SCP_BL2_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the - file that contains the SCP_BL2 private key in PEM format. If ``SAVE_KEYS=1``, - this file name will be used to save the key. - -- ``SCP_BL2U``: Path to SCP_BL2U image in the host file system. This image is - optional. It is only needed if the platform makefile specifies that it - is required in order to build the ``fwu_fip`` target. - -- ``SDEI_SUPPORT``: Setting this to ``1`` enables support for Software - Delegated Exception Interface to BL31 image. This defaults to ``0``. - - When set to ``1``, the build option ``EL3_EXCEPTION_HANDLING`` must also be - set to ``1``. - -- ``SEPARATE_CODE_AND_RODATA``: Whether code and read-only data should be - isolated on separate memory pages. This is a trade-off between security and - memory usage. See "Isolating code and read-only data on separate memory - pages" section in `Firmware Design`_. This flag is disabled by default and - affects all BL images. - -- ``SPD``: Choose a Secure Payload Dispatcher component to be built into TF-A. - This build option is only valid if ``ARCH=aarch64``. The value should be - the path to the directory containing the SPD source, relative to - ``services/spd/``; the directory is expected to contain a makefile called - ``.mk``. - -- ``SPIN_ON_BL1_EXIT``: This option introduces an infinite loop in BL1. It can - take either 0 (no loop) or 1 (add a loop). 0 is the default. This loop stops - execution in BL1 just before handing over to BL31. At this point, all - firmware images have been loaded in memory, and the MMU and caches are - turned off. Refer to the "Debugging options" section for more details. - -- ``SP_MIN_WITH_SECURE_FIQ``: Boolean flag to indicate the SP_MIN handles - secure interrupts (caught through the FIQ line). Platforms can enable - this directive if they need to handle such interruption. When enabled, - the FIQ are handled in monitor mode and non secure world is not allowed - to mask these events. Platforms that enable FIQ handling in SP_MIN shall - implement the api ``sp_min_plat_fiq_handler()``. The default value is 0. - -- ``TRUSTED_BOARD_BOOT``: Boolean flag to include support for the Trusted Board - Boot feature. When set to '1', BL1 and BL2 images include support to load - and verify the certificates and images in a FIP, and BL1 includes support - for the Firmware Update. The default value is '0'. Generation and inclusion - of certificates in the FIP and FWU_FIP depends upon the value of the - ``GENERATE_COT`` option. - - Note: This option depends on ``CREATE_KEYS`` to be enabled. If the keys - already exist in disk, they will be overwritten without further notice. - -- ``TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It - specifies the file that contains the Trusted World private key in PEM - format. If ``SAVE_KEYS=1``, this file name will be used to save the key. - -- ``TSP_INIT_ASYNC``: Choose BL32 initialization method as asynchronous or - synchronous, (see "Initializing a BL32 Image" section in - `Firmware Design`_). It can take the value 0 (BL32 is initialized using - synchronous method) or 1 (BL32 is initialized using asynchronous method). - Default is 0. - -- ``TSP_NS_INTR_ASYNC_PREEMPT``: A non zero value enables the interrupt - routing model which routes non-secure interrupts asynchronously from TSP - to EL3 causing immediate preemption of TSP. The EL3 is responsible - for saving and restoring the TSP context in this routing model. The - default routing model (when the value is 0) is to route non-secure - interrupts to TSP allowing it to save its context and hand over - synchronously to EL3 via an SMC. - - Note: when ``EL3_EXCEPTION_HANDLING`` is ``1``, ``TSP_NS_INTR_ASYNC_PREEMPT`` - must also be set to ``1``. - -- ``USE_ARM_LINK``: This flag determines whether to enable support for ARM - linker. When the ``LINKER`` build variable points to the armlink linker, - this flag is enabled automatically. To enable support for armlink, platforms - will have to provide a scatter file for the BL image. Currently, Tegra - platforms use the armlink support to compile BL3-1 images. - -- ``USE_COHERENT_MEM``: This flag determines whether to include the coherent - memory region in the BL memory map or not (see "Use of Coherent memory in - TF-A" section in `Firmware Design`_). It can take the value 1 - (Coherent memory region is included) or 0 (Coherent memory region is - excluded). Default is 1. - -- ``USE_ROMLIB``: This flag determines whether library at ROM will be used. - This feature creates a library of functions to be placed in ROM and thus - reduces SRAM usage. Refer to `Library at ROM`_ for further details. Default - is 0. - -- ``V``: Verbose build. If assigned anything other than 0, the build commands - are printed. Default is 0. - -- ``VERSION_STRING``: String used in the log output for each TF-A image. - Defaults to a string formed by concatenating the version number, build type - and build string. - -- ``WARMBOOT_ENABLE_DCACHE_EARLY`` : Boolean option to enable D-cache early on - the CPU after warm boot. This is applicable for platforms which do not - require interconnect programming to enable cache coherency (eg: single - cluster platforms). If this option is enabled, then warm boot path - enables D-caches immediately after enabling MMU. This option defaults to 0. - -Arm development platform specific build options -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- ``ARM_BL31_IN_DRAM``: Boolean option to select loading of BL31 in TZC secured - DRAM. By default, BL31 is in the secure SRAM. Set this flag to 1 to load - BL31 in TZC secured DRAM. If TSP is present, then setting this option also - sets the TSP location to DRAM and ignores the ``ARM_TSP_RAM_LOCATION`` build - flag. - -- ``ARM_CONFIG_CNTACR``: boolean option to unlock access to the ``CNTBase`` - frame registers by setting the ``CNTCTLBase.CNTACR`` register bits. The - frame number ```` is defined by ``PLAT_ARM_NSTIMER_FRAME_ID``, which should - match the frame used by the Non-Secure image (normally the Linux kernel). - Default is true (access to the frame is allowed). - -- ``ARM_DISABLE_TRUSTED_WDOG``: boolean option to disable the Trusted Watchdog. - By default, Arm platforms use a watchdog to trigger a system reset in case - an error is encountered during the boot process (for example, when an image - could not be loaded or authenticated). The watchdog is enabled in the early - platform setup hook at BL1 and disabled in the BL1 prepare exit hook. The - Trusted Watchdog may be disabled at build time for testing or development - purposes. - -- ``ARM_LINUX_KERNEL_AS_BL33``: The Linux kernel expects registers x0-x3 to - have specific values at boot. This boolean option allows the Trusted Firmware - to have a Linux kernel image as BL33 by preparing the registers to these - values before jumping to BL33. This option defaults to 0 (disabled). For - AArch64 ``RESET_TO_BL31`` and for AArch32 ``RESET_TO_SP_MIN`` must be 1 when - using it. If this option is set to 1, ``ARM_PRELOADED_DTB_BASE`` must be set - to the location of a device tree blob (DTB) already loaded in memory. The - Linux Image address must be specified using the ``PRELOADED_BL33_BASE`` - option. - -- ``ARM_PLAT_MT``: This flag determines whether the Arm platform layer has to - cater for the multi-threading ``MT`` bit when accessing MPIDR. When this flag - is set, the functions which deal with MPIDR assume that the ``MT`` bit in - MPIDR is set and access the bit-fields in MPIDR accordingly. Default value of - this flag is 0. Note that this option is not used on FVP platforms. - -- ``ARM_RECOM_STATE_ID_ENC``: The PSCI1.0 specification recommends an encoding - for the construction of composite state-ID in the power-state parameter. - The existing PSCI clients currently do not support this encoding of - State-ID yet. Hence this flag is used to configure whether to use the - recommended State-ID encoding or not. The default value of this flag is 0, - in which case the platform is configured to expect NULL in the State-ID - field of power-state parameter. - -- ``ARM_ROTPK_LOCATION``: used when ``TRUSTED_BOARD_BOOT=1``. It specifies the - location of the ROTPK hash returned by the function ``plat_get_rotpk_info()`` - for Arm platforms. Depending on the selected option, the proper private key - must be specified using the ``ROT_KEY`` option when building the Trusted - Firmware. This private key will be used by the certificate generation tool - to sign the BL2 and Trusted Key certificates. Available options for - ``ARM_ROTPK_LOCATION`` are: - - - ``regs`` : return the ROTPK hash stored in the Trusted root-key storage - registers. The private key corresponding to this ROTPK hash is not - currently available. - - ``devel_rsa`` : return a development public key hash embedded in the BL1 - and BL2 binaries. This hash has been obtained from the RSA public key - ``arm_rotpk_rsa.der``, located in ``plat/arm/board/common/rotpk``. To use - this option, ``arm_rotprivk_rsa.pem`` must be specified as ``ROT_KEY`` when - creating the certificates. - - ``devel_ecdsa`` : return a development public key hash embedded in the BL1 - and BL2 binaries. This hash has been obtained from the ECDSA public key - ``arm_rotpk_ecdsa.der``, located in ``plat/arm/board/common/rotpk``. To use - this option, ``arm_rotprivk_ecdsa.pem`` must be specified as ``ROT_KEY`` - when creating the certificates. - -- ``ARM_TSP_RAM_LOCATION``: location of the TSP binary. Options: - - - ``tsram`` : Trusted SRAM (default option when TBB is not enabled) - - ``tdram`` : Trusted DRAM (if available) - - ``dram`` : Secure region in DRAM (default option when TBB is enabled, - configured by the TrustZone controller) - -- ``ARM_XLAT_TABLES_LIB_V1``: boolean option to compile TF-A with version 1 - of the translation tables library instead of version 2. It is set to 0 by - default, which selects version 2. - -- ``ARM_CRYPTOCELL_INTEG`` : bool option to enable TF-A to invoke Arm® - TrustZone® CryptoCell functionality for Trusted Board Boot on capable Arm - platforms. If this option is specified, then the path to the CryptoCell - SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag. - -For a better understanding of these options, the Arm development platform memory -map is explained in the `Firmware Design`_. - -Arm CSS platform specific build options -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- ``CSS_DETECT_PRE_1_7_0_SCP``: Boolean flag to detect SCP version - incompatibility. Version 1.7.0 of the SCP firmware made a non-backwards - compatible change to the MTL protocol, used for AP/SCP communication. - TF-A no longer supports earlier SCP versions. If this option is set to 1 - then TF-A will detect if an earlier version is in use. Default is 1. - -- ``CSS_LOAD_SCP_IMAGES``: Boolean flag, which when set, adds SCP_BL2 and - SCP_BL2U to the FIP and FWU_FIP respectively, and enables them to be loaded - during boot. Default is 1. - -- ``CSS_USE_SCMI_SDS_DRIVER``: Boolean flag which selects SCMI/SDS drivers - instead of SCPI/BOM driver for communicating with the SCP during power - management operations and for SCP RAM Firmware transfer. If this option - is set to 1, then SCMI/SDS drivers will be used. Default is 0. - -Arm FVP platform specific build options -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- ``FVP_CLUSTER_COUNT`` : Configures the cluster count to be used to - build the topology tree within TF-A. By default TF-A is configured for dual - cluster topology and this option can be used to override the default value. - -- ``FVP_INTERCONNECT_DRIVER``: Selects the interconnect driver to be built. The - default interconnect driver depends on the value of ``FVP_CLUSTER_COUNT`` as - explained in the options below: - - - ``FVP_CCI`` : The CCI driver is selected. This is the default - if 0 < ``FVP_CLUSTER_COUNT`` <= 2. - - ``FVP_CCN`` : The CCN driver is selected. This is the default - if ``FVP_CLUSTER_COUNT`` > 2. - -- ``FVP_MAX_CPUS_PER_CLUSTER``: Sets the maximum number of CPUs implemented in - a single cluster. This option defaults to 4. - -- ``FVP_MAX_PE_PER_CPU``: Sets the maximum number of PEs implemented on any CPU - in the system. This option defaults to 1. Note that the build option - ``ARM_PLAT_MT`` doesn't have any effect on FVP platforms. - -- ``FVP_USE_GIC_DRIVER`` : Selects the GIC driver to be built. Options: - - - ``FVP_GIC600`` : The GIC600 implementation of GICv3 is selected - - ``FVP_GICV2`` : The GICv2 only driver is selected - - ``FVP_GICV3`` : The GICv3 only driver is selected (default option) - -- ``FVP_USE_SP804_TIMER`` : Use the SP804 timer instead of the Generic Timer - for functions that wait for an arbitrary time length (udelay and mdelay). - The default value is 0. - -- ``FVP_HW_CONFIG_DTS`` : Specify the path to the DTS file to be compiled - to DTB and packaged in FIP as the HW_CONFIG. See `Firmware Design`_ for - details on HW_CONFIG. By default, this is initialized to a sensible DTS - file in ``fdts/`` folder depending on other build options. But some cases, - like shifted affinity format for MPIDR, cannot be detected at build time - and this option is needed to specify the appropriate DTS file. - -- ``FVP_HW_CONFIG`` : Specify the path to the HW_CONFIG blob to be packaged in - FIP. See `Firmware Design`_ for details on HW_CONFIG. This option is - similar to the ``FVP_HW_CONFIG_DTS`` option, but it directly specifies the - HW_CONFIG blob instead of the DTS file. This option is useful to override - the default HW_CONFIG selected by the build system. - -ARM JUNO platform specific build options -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- ``JUNO_TZMP1`` : Boolean option to configure Juno to be used for TrustZone - Media Protection (TZ-MP1). Default value of this flag is 0. - -Debugging options -~~~~~~~~~~~~~~~~~ - -To compile a debug version and make the build more verbose use - -:: - - make PLAT= DEBUG=1 V=1 all - -AArch64 GCC uses DWARF version 4 debugging symbols by default. Some tools (for -example DS-5) might not support this and may need an older version of DWARF -symbols to be emitted by GCC. This can be achieved by using the -``-gdwarf-`` flag, with the version being set to 2 or 3. Setting the -version to 2 is recommended for DS-5 versions older than 5.16. - -When debugging logic problems it might also be useful to disable all compiler -optimizations by using ``-O0``. - -NOTE: Using ``-O0`` could cause output images to be larger and base addresses -might need to be recalculated (see the **Memory layout on Arm development -platforms** section in the `Firmware Design`_). - -Extra debug options can be passed to the build system by setting ``CFLAGS`` or -``LDFLAGS``: - -.. code:: makefile - - CFLAGS='-O0 -gdwarf-2' \ - make PLAT= DEBUG=1 V=1 all - -Note that using ``-Wl,`` style compilation driver options in ``CFLAGS`` will be -ignored as the linker is called directly. - -It is also possible to introduce an infinite loop to help in debugging the -post-BL2 phase of TF-A. This can be done by rebuilding BL1 with the -``SPIN_ON_BL1_EXIT=1`` build flag. Refer to the `Summary of build options`_ -section. In this case, the developer may take control of the target using a -debugger when indicated by the console output. When using DS-5, the following -commands can be used: - -:: - - # Stop target execution - interrupt - - # - # Prepare your debugging environment, e.g. set breakpoints - # - - # Jump over the debug loop - set var $AARCH64::$Core::$PC = $AARCH64::$Core::$PC + 4 - - # Resume execution - continue - -Building the Test Secure Payload -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The TSP is coupled with a companion runtime service in the BL31 firmware, -called the TSPD. Therefore, if you intend to use the TSP, the BL31 image -must be recompiled as well. For more information on SPs and SPDs, see the -`Secure-EL1 Payloads and Dispatchers`_ section in the `Firmware Design`_. - -First clean the TF-A build directory to get rid of any previous BL31 binary. -Then to build the TSP image use: - -:: - - make PLAT= SPD=tspd all - -An additional boot loader binary file is created in the ``build`` directory: - -:: - - build///bl32.bin - - -Building and using the FIP tool -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Firmware Image Package (FIP) is a packaging format used by TF-A to package -firmware images in a single binary. The number and type of images that should -be packed in a FIP is platform specific and may include TF-A images and other -firmware images required by the platform. For example, most platforms require -a BL33 image which corresponds to the normal world bootloader (e.g. UEFI or -U-Boot). - -The TF-A build system provides the make target ``fip`` to create a FIP file -for the specified platform using the FIP creation tool included in the TF-A -project. Examples below show how to build a FIP file for FVP, packaging TF-A -and BL33 images. - -For AArch64: - -:: - - make PLAT=fvp BL33=/bl33.bin fip - -For AArch32: - -:: - - make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33=/bl33.bin fip - -The resulting FIP may be found in: - -:: - - build/fvp//fip.bin - -For advanced operations on FIP files, it is also possible to independently build -the tool and create or modify FIPs using this tool. To do this, follow these -steps: - -It is recommended to remove old artifacts before building the tool: - -:: - - make -C tools/fiptool clean - -Build the tool: - -:: - - make [DEBUG=1] [V=1] fiptool - -The tool binary can be located in: - -:: - - ./tools/fiptool/fiptool - -Invoking the tool with ``help`` will print a help message with all available -options. - -Example 1: create a new Firmware package ``fip.bin`` that contains BL2 and BL31: - -:: - - ./tools/fiptool/fiptool create \ - --tb-fw build///bl2.bin \ - --soc-fw build///bl31.bin \ - fip.bin - -Example 2: view the contents of an existing Firmware package: - -:: - - ./tools/fiptool/fiptool info /fip.bin - -Example 3: update the entries of an existing Firmware package: - -:: - - # Change the BL2 from Debug to Release version - ./tools/fiptool/fiptool update \ - --tb-fw build//release/bl2.bin \ - build//debug/fip.bin - -Example 4: unpack all entries from an existing Firmware package: - -:: - - # Images will be unpacked to the working directory - ./tools/fiptool/fiptool unpack /fip.bin - -Example 5: remove an entry from an existing Firmware package: - -:: - - ./tools/fiptool/fiptool remove \ - --tb-fw build//debug/fip.bin - -Note that if the destination FIP file exists, the create, update and -remove operations will automatically overwrite it. - -The unpack operation will fail if the images already exist at the -destination. In that case, use -f or --force to continue. - -More information about FIP can be found in the `Firmware Design`_ document. - -Building FIP images with support for Trusted Board Boot -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Trusted Board Boot primarily consists of the following two features: - -- Image Authentication, described in `Trusted Board Boot`_, and -- Firmware Update, described in `Firmware Update`_ - -The following steps should be followed to build FIP and (optionally) FWU_FIP -images with support for these features: - -#. Fulfill the dependencies of the ``mbedtls`` cryptographic and image parser - modules by checking out a recent version of the `mbed TLS Repository`_. It - is important to use a version that is compatible with TF-A and fixes any - known security vulnerabilities. See `mbed TLS Security Center`_ for more - information. The latest version of TF-A is tested with tag - ``mbedtls-2.16.0``. - - The ``drivers/auth/mbedtls/mbedtls_*.mk`` files contain the list of mbed TLS - source files the modules depend upon. - ``include/drivers/auth/mbedtls/mbedtls_config.h`` contains the configuration - options required to build the mbed TLS sources. - - Note that the mbed TLS library is licensed under the Apache version 2.0 - license. Using mbed TLS source code will affect the licensing of TF-A - binaries that are built using this library. - -#. To build the FIP image, ensure the following command line variables are set - while invoking ``make`` to build TF-A: - - - ``MBEDTLS_DIR=`` - - ``TRUSTED_BOARD_BOOT=1`` - - ``GENERATE_COT=1`` - - In the case of Arm platforms, the location of the ROTPK hash must also be - specified at build time. Two locations are currently supported (see - ``ARM_ROTPK_LOCATION`` build option): - - - ``ARM_ROTPK_LOCATION=regs``: the ROTPK hash is obtained from the Trusted - root-key storage registers present in the platform. On Juno, this - registers are read-only. On FVP Base and Cortex models, the registers - are read-only, but the value can be specified using the command line - option ``bp.trusted_key_storage.public_key`` when launching the model. - On both Juno and FVP models, the default value corresponds to an - ECDSA-SECP256R1 public key hash, whose private part is not currently - available. - - - ``ARM_ROTPK_LOCATION=devel_rsa``: use the ROTPK hash that is hardcoded - in the Arm platform port. The private/public RSA key pair may be - found in ``plat/arm/board/common/rotpk``. - - - ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the ROTPK hash that is hardcoded - in the Arm platform port. The private/public ECDSA key pair may be - found in ``plat/arm/board/common/rotpk``. - - Example of command line using RSA development keys: - - :: - - MBEDTLS_DIR= \ - make PLAT= TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ - ARM_ROTPK_LOCATION=devel_rsa \ - ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ - BL33=/ \ - all fip - - The result of this build will be the bl1.bin and the fip.bin binaries. This - FIP will include the certificates corresponding to the Chain of Trust - described in the TBBR-client document. These certificates can also be found - in the output build directory. - -#. The optional FWU_FIP contains any additional images to be loaded from - Non-Volatile storage during the `Firmware Update`_ process. To build the - FWU_FIP, any FWU images required by the platform must be specified on the - command line. On Arm development platforms like Juno, these are: - - - NS_BL2U. The AP non-secure Firmware Updater image. - - SCP_BL2U. The SCP Firmware Update Configuration image. - - Example of Juno command line for generating both ``fwu`` and ``fwu_fip`` - targets using RSA development: - - :: - - MBEDTLS_DIR= \ - make PLAT=juno TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ - ARM_ROTPK_LOCATION=devel_rsa \ - ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ - BL33=/ \ - SCP_BL2=/ \ - SCP_BL2U=/ \ - NS_BL2U=/ \ - all fip fwu_fip - - Note: The BL2U image will be built by default and added to the FWU_FIP. - The user may override this by adding ``BL2U=/`` - to the command line above. - - Note: Building and installing the non-secure and SCP FWU images (NS_BL1U, - NS_BL2U and SCP_BL2U) is outside the scope of this document. - - The result of this build will be bl1.bin, fip.bin and fwu_fip.bin binaries. - Both the FIP and FWU_FIP will include the certificates corresponding to the - Chain of Trust described in the TBBR-client document. These certificates - can also be found in the output build directory. - -Building the Certificate Generation Tool -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``cert_create`` tool is built as part of the TF-A build process when the -``fip`` make target is specified and TBB is enabled (as described in the -previous section), but it can also be built separately with the following -command: - -:: - - make PLAT= [DEBUG=1] [V=1] certtool - -For platforms that require their own IDs in certificate files, the generic -'cert_create' tool can be built with the following command. Note that the target -platform must define its IDs within a ``platform_oid.h`` header file for the -build to succeed. - -:: - - make PLAT= USE_TBBR_DEFS=0 [DEBUG=1] [V=1] certtool - -``DEBUG=1`` builds the tool in debug mode. ``V=1`` makes the build process more -verbose. The following command should be used to obtain help about the tool: - -:: - - ./tools/cert_create/cert_create -h - -Building a FIP for Juno and FVP -------------------------------- - -This section provides Juno and FVP specific instructions to build Trusted -Firmware, obtain the additional required firmware, and pack it all together in -a single FIP binary. It assumes that a `Linaro Release`_ has been installed. - -Note: Pre-built binaries for AArch32 are available from Linaro Release 16.12 -onwards. Before that release, pre-built binaries are only available for AArch64. - -Note: Follow the full instructions for one platform before switching to a -different one. Mixing instructions for different platforms may result in -corrupted binaries. - -Note: The uboot image downloaded by the Linaro workspace script does not always -match the uboot image packaged as BL33 in the corresponding fip file. It is -recommended to use the version that is packaged in the fip file using the -instructions below. - -Note: For the FVP, the kernel FDT is packaged in FIP during build and loaded -by the firmware at runtime. See `Obtaining the Flattened Device Trees`_ -section for more info on selecting the right FDT to use. - -#. Clean the working directory - - :: - - make realclean - -#. Obtain SCP_BL2 (Juno) and BL33 (all platforms) - - Use the fiptool to extract the SCP_BL2 and BL33 images from the FIP - package included in the Linaro release: - - :: - - # Build the fiptool - make [DEBUG=1] [V=1] fiptool - - # Unpack firmware images from Linaro FIP - ./tools/fiptool/fiptool unpack /fip.bin - - The unpack operation will result in a set of binary images extracted to the - current working directory. The SCP_BL2 image corresponds to - ``scp-fw.bin`` and BL33 corresponds to ``nt-fw.bin``. - - Note: The fiptool will complain if the images to be unpacked already - exist in the current directory. If that is the case, either delete those - files or use the ``--force`` option to overwrite. - - Note: For AArch32, the instructions below assume that nt-fw.bin is a normal - world boot loader that supports AArch32. - -#. Build TF-A images and create a new FIP for FVP - - :: - - # AArch64 - make PLAT=fvp BL33=nt-fw.bin all fip - - # AArch32 - make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33=nt-fw.bin all fip - -#. Build TF-A images and create a new FIP for Juno - - For AArch64: - - Building for AArch64 on Juno simply requires the addition of ``SCP_BL2`` - as a build parameter. - - :: - - make PLAT=juno BL33=nt-fw.bin SCP_BL2=scp-fw.bin all fip - - For AArch32: - - Hardware restrictions on Juno prevent cold reset into AArch32 execution mode, - therefore BL1 and BL2 must be compiled for AArch64, and BL32 is compiled - separately for AArch32. - - - Before building BL32, the environment variable ``CROSS_COMPILE`` must point - to the AArch32 Linaro cross compiler. - - :: - - export CROSS_COMPILE=/bin/arm-linux-gnueabihf- - - - Build BL32 in AArch32. - - :: - - make ARCH=aarch32 PLAT=juno AARCH32_SP=sp_min \ - RESET_TO_SP_MIN=1 JUNO_AARCH32_EL3_RUNTIME=1 bl32 - - - Save ``bl32.bin`` to a temporary location and clean the build products. - - :: - - cp /bl32.bin - make realclean - - - Before building BL1 and BL2, the environment variable ``CROSS_COMPILE`` - must point to the AArch64 Linaro cross compiler. - - :: - - export CROSS_COMPILE=/bin/aarch64-linux-gnu- - - - The following parameters should be used to build BL1 and BL2 in AArch64 - and point to the BL32 file. - - :: - - make ARCH=aarch64 PLAT=juno JUNO_AARCH32_EL3_RUNTIME=1 \ - BL33=nt-fw.bin SCP_BL2=scp-fw.bin \ - BL32=/bl32.bin all fip - -The resulting BL1 and FIP images may be found in: - -:: - - # Juno - ./build/juno/release/bl1.bin - ./build/juno/release/fip.bin - - # FVP - ./build/fvp/release/bl1.bin - ./build/fvp/release/fip.bin - - -Booting Firmware Update images -------------------------------------- - -When Firmware Update (FWU) is enabled there are at least 2 new images -that have to be loaded, the Non-Secure FWU ROM (NS-BL1U), and the -FWU FIP. - -Juno -~~~~ - -The new images must be programmed in flash memory by adding -an entry in the ``SITE1/HBI0262x/images.txt`` configuration file -on the Juno SD card (where ``x`` depends on the revision of the Juno board). -Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory -programming" for more information. User should ensure these do not -overlap with any other entries in the file. - -:: - - NOR10UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE - NOR10ADDRESS: 0x00400000 ;Image Flash Address [ns_bl2u_base_address] - NOR10FILE: \SOFTWARE\fwu_fip.bin ;Image File Name - NOR10LOAD: 00000000 ;Image Load Address - NOR10ENTRY: 00000000 ;Image Entry Point - - NOR11UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE - NOR11ADDRESS: 0x03EB8000 ;Image Flash Address [ns_bl1u_base_address] - NOR11FILE: \SOFTWARE\ns_bl1u.bin ;Image File Name - NOR11LOAD: 00000000 ;Image Load Address - -The address ns_bl1u_base_address is the value of NS_BL1U_BASE - 0x8000000. -In the same way, the address ns_bl2u_base_address is the value of -NS_BL2U_BASE - 0x8000000. - -FVP -~~~ - -The additional fip images must be loaded with: - -:: - - --data cluster0.cpu0="/ns_bl1u.bin"@0x0beb8000 [ns_bl1u_base_address] - --data cluster0.cpu0="/fwu_fip.bin"@0x08400000 [ns_bl2u_base_address] - -The address ns_bl1u_base_address is the value of NS_BL1U_BASE. -In the same way, the address ns_bl2u_base_address is the value of -NS_BL2U_BASE. - - -EL3 payloads alternative boot flow ----------------------------------- - -On a pre-production system, the ability to execute arbitrary, bare-metal code at -the highest exception level is required. It allows full, direct access to the -hardware, for example to run silicon soak tests. - -Although it is possible to implement some baremetal secure firmware from -scratch, this is a complex task on some platforms, depending on the level of -configuration required to put the system in the expected state. - -Rather than booting a baremetal application, a possible compromise is to boot -``EL3 payloads`` through TF-A instead. This is implemented as an alternative -boot flow, where a modified BL2 boots an EL3 payload, instead of loading the -other BL images and passing control to BL31. It reduces the complexity of -developing EL3 baremetal code by: - -- putting the system into a known architectural state; -- taking care of platform secure world initialization; -- loading the SCP_BL2 image if required by the platform. - -When booting an EL3 payload on Arm standard platforms, the configuration of the -TrustZone controller is simplified such that only region 0 is enabled and is -configured to permit secure access only. This gives full access to the whole -DRAM to the EL3 payload. - -The system is left in the same state as when entering BL31 in the default boot -flow. In particular: - -- Running in EL3; -- Current state is AArch64; -- Little-endian data access; -- All exceptions disabled; -- MMU disabled; -- Caches disabled. - -Booting an EL3 payload -~~~~~~~~~~~~~~~~~~~~~~ - -The EL3 payload image is a standalone image and is not part of the FIP. It is -not loaded by TF-A. Therefore, there are 2 possible scenarios: - -- The EL3 payload may reside in non-volatile memory (NVM) and execute in - place. In this case, booting it is just a matter of specifying the right - address in NVM through ``EL3_PAYLOAD_BASE`` when building TF-A. - -- The EL3 payload needs to be loaded in volatile memory (e.g. DRAM) at - run-time. - -To help in the latter scenario, the ``SPIN_ON_BL1_EXIT=1`` build option can be -used. The infinite loop that it introduces in BL1 stops execution at the right -moment for a debugger to take control of the target and load the payload (for -example, over JTAG). - -It is expected that this loading method will work in most cases, as a debugger -connection is usually available in a pre-production system. The user is free to -use any other platform-specific mechanism to load the EL3 payload, though. - -Booting an EL3 payload on FVP -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The EL3 payloads boot flow requires the CPU's mailbox to be cleared at reset for -the secondary CPUs holding pen to work properly. Unfortunately, its reset value -is undefined on the FVP platform and the FVP platform code doesn't clear it. -Therefore, one must modify the way the model is normally invoked in order to -clear the mailbox at start-up. - -One way to do that is to create an 8-byte file containing all zero bytes using -the following command: - -:: - - dd if=/dev/zero of=mailbox.dat bs=1 count=8 - -and pre-load it into the FVP memory at the mailbox address (i.e. ``0x04000000``) -using the following model parameters: - -:: - - --data cluster0.cpu0=mailbox.dat@0x04000000 [Base FVPs] - --data=mailbox.dat@0x04000000 [Foundation FVP] - -To provide the model with the EL3 payload image, the following methods may be -used: - -#. If the EL3 payload is able to execute in place, it may be programmed into - flash memory. On Base Cortex and AEM FVPs, the following model parameter - loads it at the base address of the NOR FLASH1 (the NOR FLASH0 is already - used for the FIP): - - :: - - -C bp.flashloader1.fname="/" - - On Foundation FVP, there is no flash loader component and the EL3 payload - may be programmed anywhere in flash using method 3 below. - -#. When using the ``SPIN_ON_BL1_EXIT=1`` loading method, the following DS-5 - command may be used to load the EL3 payload ELF image over JTAG: - - :: - - load /el3-payload.elf - -#. The EL3 payload may be pre-loaded in volatile memory using the following - model parameters: - - :: - - --data cluster0.cpu0="/el3-payload>"@address [Base FVPs] - --data="/"@address [Foundation FVP] - - The address provided to the FVP must match the ``EL3_PAYLOAD_BASE`` address - used when building TF-A. - -Booting an EL3 payload on Juno -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If the EL3 payload is able to execute in place, it may be programmed in flash -memory by adding an entry in the ``SITE1/HBI0262x/images.txt`` configuration file -on the Juno SD card (where ``x`` depends on the revision of the Juno board). -Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory -programming" for more information. - -Alternatively, the same DS-5 command mentioned in the FVP section above can -be used to load the EL3 payload's ELF file over JTAG on Juno. - -Preloaded BL33 alternative boot flow ------------------------------------- - -Some platforms have the ability to preload BL33 into memory instead of relying -on TF-A to load it. This may simplify packaging of the normal world code and -improve performance in a development environment. When secure world cold boot -is complete, TF-A simply jumps to a BL33 base address provided at build time. - -For this option to be used, the ``PRELOADED_BL33_BASE`` build option has to be -used when compiling TF-A. For example, the following command will create a FIP -without a BL33 and prepare to jump to a BL33 image loaded at address -0x80000000: - -:: - - make PRELOADED_BL33_BASE=0x80000000 PLAT=fvp all fip - -Boot of a preloaded kernel image on Base FVP -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following example uses a simplified boot flow by directly jumping from the -TF-A to the Linux kernel, which will use a ramdisk as filesystem. This can be -useful if both the kernel and the device tree blob (DTB) are already present in -memory (like in FVP). - -For example, if the kernel is loaded at ``0x80080000`` and the DTB is loaded at -address ``0x82000000``, the firmware can be built like this: - -:: - - CROSS_COMPILE=aarch64-linux-gnu- \ - make PLAT=fvp DEBUG=1 \ - RESET_TO_BL31=1 \ - ARM_LINUX_KERNEL_AS_BL33=1 \ - PRELOADED_BL33_BASE=0x80080000 \ - ARM_PRELOADED_DTB_BASE=0x82000000 \ - all fip - -Now, it is needed to modify the DTB so that the kernel knows the address of the -ramdisk. The following script generates a patched DTB from the provided one, -assuming that the ramdisk is loaded at address ``0x84000000``. Note that this -script assumes that the user is using a ramdisk image prepared for U-Boot, like -the ones provided by Linaro. If using a ramdisk without this header,the ``0x40`` -offset in ``INITRD_START`` has to be removed. - -.. code:: bash - - #!/bin/bash - - # Path to the input DTB - KERNEL_DTB=/ - # Path to the output DTB - PATCHED_KERNEL_DTB=/ - # Base address of the ramdisk - INITRD_BASE=0x84000000 - # Path to the ramdisk - INITRD=/ - - # Skip uboot header (64 bytes) - INITRD_START=$(printf "0x%x" $((${INITRD_BASE} + 0x40)) ) - INITRD_SIZE=$(stat -Lc %s ${INITRD}) - INITRD_END=$(printf "0x%x" $((${INITRD_BASE} + ${INITRD_SIZE})) ) - - CHOSEN_NODE=$(echo \ - "/ { \ - chosen { \ - linux,initrd-start = <${INITRD_START}>; \ - linux,initrd-end = <${INITRD_END}>; \ - }; \ - };") - - echo $(dtc -O dts -I dtb ${KERNEL_DTB}) ${CHOSEN_NODE} | \ - dtc -O dtb -o ${PATCHED_KERNEL_DTB} - - -And the FVP binary can be run with the following command: - -:: - - /FVP_Base_AEMv8A-AEMv8A \ - -C pctl.startup=0.0.0.0 \ - -C bp.secure_memory=1 \ - -C cluster0.NUM_CORES=4 \ - -C cluster1.NUM_CORES=4 \ - -C cache_state_modelled=1 \ - -C cluster0.cpu0.RVBAR=0x04020000 \ - -C cluster0.cpu1.RVBAR=0x04020000 \ - -C cluster0.cpu2.RVBAR=0x04020000 \ - -C cluster0.cpu3.RVBAR=0x04020000 \ - -C cluster1.cpu0.RVBAR=0x04020000 \ - -C cluster1.cpu1.RVBAR=0x04020000 \ - -C cluster1.cpu2.RVBAR=0x04020000 \ - -C cluster1.cpu3.RVBAR=0x04020000 \ - --data cluster0.cpu0="/bl31.bin"@0x04020000 \ - --data cluster0.cpu0="/"@0x82000000 \ - --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 - -Boot of a preloaded kernel image on Juno -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Trusted Firmware must be compiled in a similar way as for FVP explained -above. The process to load binaries to memory is the one explained in -`Booting an EL3 payload on Juno`_. - -Running the software on FVP ---------------------------- - -The latest version of the AArch64 build of TF-A has been tested on the following -Arm FVPs without shifted affinities, and that do not support threaded CPU cores -(64-bit host machine only). - -The FVP models used are Version 11.6 Build 45, unless otherwise stated. - -- ``FVP_Base_AEMv8A-AEMv8A`` -- ``FVP_Base_AEMv8A-AEMv8A-AEMv8A-AEMv8A-CCN502`` -- ``FVP_Base_RevC-2xAEMv8A`` -- ``FVP_Base_Cortex-A32x4`` -- ``FVP_Base_Cortex-A35x4`` -- ``FVP_Base_Cortex-A53x4`` -- ``FVP_Base_Cortex-A55x4+Cortex-A75x4`` -- ``FVP_Base_Cortex-A55x4`` -- ``FVP_Base_Cortex-A57x1-A53x1`` -- ``FVP_Base_Cortex-A57x2-A53x4`` -- ``FVP_Base_Cortex-A57x4-A53x4`` -- ``FVP_Base_Cortex-A57x4`` -- ``FVP_Base_Cortex-A72x4-A53x4`` -- ``FVP_Base_Cortex-A72x4`` -- ``FVP_Base_Cortex-A73x4-A53x4`` -- ``FVP_Base_Cortex-A73x4`` -- ``FVP_Base_Cortex-A75x4`` -- ``FVP_Base_Cortex-A76x4`` -- ``FVP_Base_Cortex-A76AEx4`` -- ``FVP_Base_Cortex-A76AEx8`` -- ``FVP_Base_Neoverse-N1x4`` -- ``FVP_Base_Deimos`` -- ``FVP_CSS_SGI-575`` (Version 11.3 build 42) -- ``FVP_CSS_SGM-775`` (Version 11.3 build 42) -- ``FVP_RD_E1Edge`` (Version 11.3 build 42) -- ``FVP_RD_N1Edge`` -- ``Foundation_Platform`` - -The latest version of the AArch32 build of TF-A has been tested on the following -Arm FVPs without shifted affinities, and that do not support threaded CPU cores -(64-bit host machine only). - -- ``FVP_Base_AEMv8A-AEMv8A`` -- ``FVP_Base_Cortex-A32x4`` - -NOTE: The ``FVP_Base_RevC-2xAEMv8A`` FVP only supports shifted affinities, which -is not compatible with legacy GIC configurations. Therefore this FVP does not -support these legacy GIC configurations. - -NOTE: The build numbers quoted above are those reported by launching the FVP -with the ``--version`` parameter. - -NOTE: Linaro provides a ramdisk image in prebuilt FVP configurations and full -file systems that can be downloaded separately. To run an FVP with a virtio -file system image an additional FVP configuration option -``-C bp.virtioblockdevice.image_path="/`` can be -used. - -NOTE: The software will not work on Version 1.0 of the Foundation FVP. -The commands below would report an ``unhandled argument`` error in this case. - -NOTE: FVPs can be launched with ``--cadi-server`` option such that a -CADI-compliant debugger (for example, Arm DS-5) can connect to and control its -execution. - -NOTE: Since FVP model Version 11.0 Build 11.0.34 and Version 8.5 Build 0.8.5202 -the internal synchronisation timings changed compared to older versions of the -models. The models can be launched with ``-Q 100`` option if they are required -to match the run time characteristics of the older versions. - -The Foundation FVP is a cut down version of the AArch64 Base FVP. It can be -downloaded for free from `Arm's website`_. - -The Cortex-A models listed above are also available to download from -`Arm's website`_. - -Please refer to the FVP documentation for a detailed description of the model -parameter options. A brief description of the important ones that affect TF-A -and normal world software behavior is provided below. - -Obtaining the Flattened Device Trees -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Depending on the FVP configuration and Linux configuration used, different -FDT files are required. FDT source files for the Foundation and Base FVPs can -be found in the TF-A source directory under ``fdts/``. The Foundation FVP has -a subset of the Base FVP components. For example, the Foundation FVP lacks -CLCD and MMC support, and has only one CPU cluster. - -Note: It is not recommended to use the FDTs built along the kernel because not -all FDTs are available from there. - -The dynamic configuration capability is enabled in the firmware for FVPs. -This means that the firmware can authenticate and load the FDT if present in -FIP. A default FDT is packaged into FIP during the build based on -the build configuration. This can be overridden by using the ``FVP_HW_CONFIG`` -or ``FVP_HW_CONFIG_DTS`` build options (refer to the -`Arm FVP platform specific build options`_ section for detail on the options). - -- ``fvp-base-gicv2-psci.dts`` - - For use with models such as the Cortex-A57-A53 Base FVPs without shifted - affinities and with Base memory map configuration. - -- ``fvp-base-gicv2-psci-aarch32.dts`` - - For use with models such as the Cortex-A32 Base FVPs without shifted - affinities and running Linux in AArch32 state with Base memory map - configuration. - -- ``fvp-base-gicv3-psci.dts`` - - For use with models such as the Cortex-A57-A53 Base FVPs without shifted - affinities and with Base memory map configuration and Linux GICv3 support. - -- ``fvp-base-gicv3-psci-1t.dts`` - - For use with models such as the AEMv8-RevC Base FVP with shifted affinities, - single threaded CPUs, Base memory map configuration and Linux GICv3 support. - -- ``fvp-base-gicv3-psci-dynamiq.dts`` - - For use with models as the Cortex-A55-A75 Base FVPs with shifted affinities, - single cluster, single threaded CPUs, Base memory map configuration and Linux - GICv3 support. - -- ``fvp-base-gicv3-psci-aarch32.dts`` - - For use with models such as the Cortex-A32 Base FVPs without shifted - affinities and running Linux in AArch32 state with Base memory map - configuration and Linux GICv3 support. - -- ``fvp-foundation-gicv2-psci.dts`` - - For use with Foundation FVP with Base memory map configuration. - -- ``fvp-foundation-gicv3-psci.dts`` - - (Default) For use with Foundation FVP with Base memory map configuration - and Linux GICv3 support. - -Running on the Foundation FVP with reset to BL1 entrypoint -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following ``Foundation_Platform`` parameters should be used to boot Linux with -4 CPUs using the AArch64 build of TF-A. - -:: - - /Foundation_Platform \ - --cores=4 \ - --arm-v8.0 \ - --secure-memory \ - --visualization \ - --gicv3 \ - --data="/"@0x0 \ - --data="/"@0x08000000 \ - --data="/"@0x80080000 \ - --data="/"@0x84000000 - -Notes: - -- BL1 is loaded at the start of the Trusted ROM. -- The Firmware Image Package is loaded at the start of NOR FLASH0. -- The firmware loads the FDT packaged in FIP to the DRAM. The FDT load address - is specified via the ``hw_config_addr`` property in `TB_FW_CONFIG for FVP`_. -- The default use-case for the Foundation FVP is to use the ``--gicv3`` option - and enable the GICv3 device in the model. Note that without this option, - the Foundation FVP defaults to legacy (Versatile Express) memory map which - is not supported by TF-A. -- In order for TF-A to run correctly on the Foundation FVP, the architecture - versions must match. The Foundation FVP defaults to the highest v8.x - version it supports but the default build for TF-A is for v8.0. To avoid - issues either start the Foundation FVP to use v8.0 architecture using the - ``--arm-v8.0`` option, or build TF-A with an appropriate value for - ``ARM_ARCH_MINOR``. - -Running on the AEMv8 Base FVP with reset to BL1 entrypoint -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following ``FVP_Base_RevC-2xAEMv8A`` parameters should be used to boot Linux -with 8 CPUs using the AArch64 build of TF-A. - -:: - - /FVP_Base_RevC-2xAEMv8A \ - -C pctl.startup=0.0.0.0 \ - -C bp.secure_memory=1 \ - -C bp.tzc_400.diagnostics=1 \ - -C cluster0.NUM_CORES=4 \ - -C cluster1.NUM_CORES=4 \ - -C cache_state_modelled=1 \ - -C bp.secureflashloader.fname="/" \ - -C bp.flashloader0.fname="/" \ - --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 - -Note: The ``FVP_Base_RevC-2xAEMv8A`` has shifted affinities and requires a -specific DTS for all the CPUs to be loaded. - -Running on the AEMv8 Base FVP (AArch32) with reset to BL1 entrypoint -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux -with 8 CPUs using the AArch32 build of TF-A. - -:: - - /FVP_Base_AEMv8A-AEMv8A \ - -C pctl.startup=0.0.0.0 \ - -C bp.secure_memory=1 \ - -C bp.tzc_400.diagnostics=1 \ - -C cluster0.NUM_CORES=4 \ - -C cluster1.NUM_CORES=4 \ - -C cache_state_modelled=1 \ - -C cluster0.cpu0.CONFIG64=0 \ - -C cluster0.cpu1.CONFIG64=0 \ - -C cluster0.cpu2.CONFIG64=0 \ - -C cluster0.cpu3.CONFIG64=0 \ - -C cluster1.cpu0.CONFIG64=0 \ - -C cluster1.cpu1.CONFIG64=0 \ - -C cluster1.cpu2.CONFIG64=0 \ - -C cluster1.cpu3.CONFIG64=0 \ - -C bp.secureflashloader.fname="/" \ - -C bp.flashloader0.fname="/" \ - --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 - -Running on the Cortex-A57-A53 Base FVP with reset to BL1 entrypoint -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to -boot Linux with 8 CPUs using the AArch64 build of TF-A. - -:: - - /FVP_Base_Cortex-A57x4-A53x4 \ - -C pctl.startup=0.0.0.0 \ - -C bp.secure_memory=1 \ - -C bp.tzc_400.diagnostics=1 \ - -C cache_state_modelled=1 \ - -C bp.secureflashloader.fname="/" \ - -C bp.flashloader0.fname="/" \ - --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 - -Running on the Cortex-A32 Base FVP (AArch32) with reset to BL1 entrypoint -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to -boot Linux with 4 CPUs using the AArch32 build of TF-A. - -:: - - /FVP_Base_Cortex-A32x4 \ - -C pctl.startup=0.0.0.0 \ - -C bp.secure_memory=1 \ - -C bp.tzc_400.diagnostics=1 \ - -C cache_state_modelled=1 \ - -C bp.secureflashloader.fname="/" \ - -C bp.flashloader0.fname="/" \ - --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 - -Running on the AEMv8 Base FVP with reset to BL31 entrypoint -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following ``FVP_Base_RevC-2xAEMv8A`` parameters should be used to boot Linux -with 8 CPUs using the AArch64 build of TF-A. - -:: - - /FVP_Base_RevC-2xAEMv8A \ - -C pctl.startup=0.0.0.0 \ - -C bp.secure_memory=1 \ - -C bp.tzc_400.diagnostics=1 \ - -C cluster0.NUM_CORES=4 \ - -C cluster1.NUM_CORES=4 \ - -C cache_state_modelled=1 \ - -C cluster0.cpu0.RVBAR=0x04010000 \ - -C cluster0.cpu1.RVBAR=0x04010000 \ - -C cluster0.cpu2.RVBAR=0x04010000 \ - -C cluster0.cpu3.RVBAR=0x04010000 \ - -C cluster1.cpu0.RVBAR=0x04010000 \ - -C cluster1.cpu1.RVBAR=0x04010000 \ - -C cluster1.cpu2.RVBAR=0x04010000 \ - -C cluster1.cpu3.RVBAR=0x04010000 \ - --data cluster0.cpu0="/"@0x04010000 \ - --data cluster0.cpu0="/"@0xff000000 \ - --data cluster0.cpu0="/"@0x88000000 \ - --data cluster0.cpu0="/"@0x82000000 \ - --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 - -Notes: - -- If Position Independent Executable (PIE) support is enabled for BL31 - in this config, it can be loaded at any valid address for execution. - -- Since a FIP is not loaded when using BL31 as reset entrypoint, the - ``--data=""@`` - parameter is needed to load the individual bootloader images in memory. - BL32 image is only needed if BL31 has been built to expect a Secure-EL1 - Payload. For the same reason, the FDT needs to be compiled from the DT source - and loaded via the ``--data cluster0.cpu0="/"@0x82000000`` - parameter. - -- The ``FVP_Base_RevC-2xAEMv8A`` has shifted affinities and requires a - specific DTS for all the CPUs to be loaded. - -- The ``-C cluster.cpu.RVBAR=@`` parameter, where - X and Y are the cluster and CPU numbers respectively, is used to set the - reset vector for each core. - -- Changing the default value of ``ARM_TSP_RAM_LOCATION`` will also require - changing the value of - ``--data=""@`` to the new value of - ``BL32_BASE``. - -Running on the AEMv8 Base FVP (AArch32) with reset to SP_MIN entrypoint -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux -with 8 CPUs using the AArch32 build of TF-A. - -:: - - /FVP_Base_AEMv8A-AEMv8A \ - -C pctl.startup=0.0.0.0 \ - -C bp.secure_memory=1 \ - -C bp.tzc_400.diagnostics=1 \ - -C cluster0.NUM_CORES=4 \ - -C cluster1.NUM_CORES=4 \ - -C cache_state_modelled=1 \ - -C cluster0.cpu0.CONFIG64=0 \ - -C cluster0.cpu1.CONFIG64=0 \ - -C cluster0.cpu2.CONFIG64=0 \ - -C cluster0.cpu3.CONFIG64=0 \ - -C cluster1.cpu0.CONFIG64=0 \ - -C cluster1.cpu1.CONFIG64=0 \ - -C cluster1.cpu2.CONFIG64=0 \ - -C cluster1.cpu3.CONFIG64=0 \ - -C cluster0.cpu0.RVBAR=0x04002000 \ - -C cluster0.cpu1.RVBAR=0x04002000 \ - -C cluster0.cpu2.RVBAR=0x04002000 \ - -C cluster0.cpu3.RVBAR=0x04002000 \ - -C cluster1.cpu0.RVBAR=0x04002000 \ - -C cluster1.cpu1.RVBAR=0x04002000 \ - -C cluster1.cpu2.RVBAR=0x04002000 \ - -C cluster1.cpu3.RVBAR=0x04002000 \ - --data cluster0.cpu0="/"@0x04002000 \ - --data cluster0.cpu0="/"@0x88000000 \ - --data cluster0.cpu0="/"@0x82000000 \ - --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 - -Note: The load address of ```` depends on the value ``BL32_BASE``. -It should match the address programmed into the RVBAR register as well. - -Running on the Cortex-A57-A53 Base FVP with reset to BL31 entrypoint -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to -boot Linux with 8 CPUs using the AArch64 build of TF-A. - -:: - - /FVP_Base_Cortex-A57x4-A53x4 \ - -C pctl.startup=0.0.0.0 \ - -C bp.secure_memory=1 \ - -C bp.tzc_400.diagnostics=1 \ - -C cache_state_modelled=1 \ - -C cluster0.cpu0.RVBARADDR=0x04010000 \ - -C cluster0.cpu1.RVBARADDR=0x04010000 \ - -C cluster0.cpu2.RVBARADDR=0x04010000 \ - -C cluster0.cpu3.RVBARADDR=0x04010000 \ - -C cluster1.cpu0.RVBARADDR=0x04010000 \ - -C cluster1.cpu1.RVBARADDR=0x04010000 \ - -C cluster1.cpu2.RVBARADDR=0x04010000 \ - -C cluster1.cpu3.RVBARADDR=0x04010000 \ - --data cluster0.cpu0="/"@0x04010000 \ - --data cluster0.cpu0="/"@0xff000000 \ - --data cluster0.cpu0="/"@0x88000000 \ - --data cluster0.cpu0="/"@0x82000000 \ - --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 - -Running on the Cortex-A32 Base FVP (AArch32) with reset to SP_MIN entrypoint -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to -boot Linux with 4 CPUs using the AArch32 build of TF-A. - -:: - - /FVP_Base_Cortex-A32x4 \ - -C pctl.startup=0.0.0.0 \ - -C bp.secure_memory=1 \ - -C bp.tzc_400.diagnostics=1 \ - -C cache_state_modelled=1 \ - -C cluster0.cpu0.RVBARADDR=0x04002000 \ - -C cluster0.cpu1.RVBARADDR=0x04002000 \ - -C cluster0.cpu2.RVBARADDR=0x04002000 \ - -C cluster0.cpu3.RVBARADDR=0x04002000 \ - --data cluster0.cpu0="/"@0x04002000 \ - --data cluster0.cpu0="/"@0x88000000 \ - --data cluster0.cpu0="/"@0x82000000 \ - --data cluster0.cpu0="/"@0x80080000 \ - --data cluster0.cpu0="/"@0x84000000 - -Running the software on Juno ----------------------------- - -This version of TF-A has been tested on variants r0, r1 and r2 of Juno. - -To execute the software stack on Juno, the version of the Juno board recovery -image indicated in the `Linaro Release Notes`_ must be installed. If you have an -earlier version installed or are unsure which version is installed, please -re-install the recovery image by following the -`Instructions for using Linaro's deliverables on Juno`_. - -Preparing TF-A images -~~~~~~~~~~~~~~~~~~~~~ - -After building TF-A, the files ``bl1.bin`` and ``fip.bin`` need copying to the -``SOFTWARE/`` directory of the Juno SD card. - -Other Juno software information -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Please visit the `Arm Platforms Portal`_ to get support and obtain any other Juno -software information. Please also refer to the `Juno Getting Started Guide`_ to -get more detailed information about the Juno Arm development platform and how to -configure it. - -Testing SYSTEM SUSPEND on Juno -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The SYSTEM SUSPEND is a PSCI API which can be used to implement system suspend -to RAM. For more details refer to section 5.16 of `PSCI`_. To test system suspend -on Juno, at the linux shell prompt, issue the following command: - -:: - - echo +10 > /sys/class/rtc/rtc0/wakealarm - echo -n mem > /sys/power/state - -The Juno board should suspend to RAM and then wakeup after 10 seconds due to -wakeup interrupt from RTC. - --------------- - -*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* - -.. _arm Developer page: https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloads -.. _Linaro: `Linaro Release Notes`_ -.. _Linaro Release: `Linaro Release Notes`_ -.. _Linaro Release Notes: https://community.arm.com/dev-platforms/w/docs/226/old-release-notes -.. _Linaro instructions: https://community.arm.com/dev-platforms/w/docs/304/arm-reference-platforms-deliverables -.. _Instructions for using Linaro's deliverables on Juno: https://community.arm.com/dev-platforms/w/docs/303/juno -.. _Arm Platforms Portal: https://community.arm.com/dev-platforms/ -.. _Development Studio 5 (DS-5): https://developer.arm.com/products/software-development-tools/ds-5-development-studio -.. _arm-trusted-firmware-a project page: https://review.trustedfirmware.org/admin/projects/TF-A/trusted-firmware-a -.. _`Linux Coding Style`: https://www.kernel.org/doc/html/latest/process/coding-style.html -.. _Linux master tree: https://github.com/torvalds/linux/tree/master/ -.. _Dia: https://wiki.gnome.org/Apps/Dia/Download -.. _here: psci-lib-integration-guide.rst -.. _Trusted Board Boot: trusted-board-boot.rst -.. _TB_FW_CONFIG for FVP: ../plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts -.. _Secure-EL1 Payloads and Dispatchers: firmware-design.rst#user-content-secure-el1-payloads-and-dispatchers -.. _Firmware Update: firmware-update.rst -.. _Firmware Design: firmware-design.rst -.. _mbed TLS Repository: https://github.com/ARMmbed/mbedtls.git -.. _mbed TLS Security Center: https://tls.mbed.org/security -.. _Arm's website: `FVP models`_ -.. _FVP models: https://developer.arm.com/products/system-design/fixed-virtual-platforms -.. _Juno Getting Started Guide: http://infocenter.arm.com/help/topic/com.arm.doc.dui0928e/DUI0928E_juno_arm_development_platform_gsg.pdf -.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf -.. _Secure Partition Manager Design guide: secure-partition-manager-design.rst -.. _`Trusted Firmware-A Coding Guidelines`: coding-guidelines.rst -.. _`Library at ROM`: romlib-design.rst diff --git a/docs/xlat-tables-lib-v2-design.rst b/docs/xlat-tables-lib-v2-design.rst deleted file mode 100644 index dbed7f8..0000000 --- a/docs/xlat-tables-lib-v2-design.rst +++ /dev/null @@ -1,428 +0,0 @@ -Translation Tables Library Design -================================= - - -.. section-numbering:: - :suffix: . - -.. contents:: - - -This document describes the design of the translation tables library (version 2) -used by Trusted Firmware-A (TF-A). This library provides APIs to create page -tables based on a description of the memory layout, as well as setting up system -registers related to the Memory Management Unit (MMU) and performing the -required Translation Lookaside Buffer (TLB) maintenance operations. - -More specifically, some use cases that this library aims to support are: - -#. Statically allocate translation tables and populate them (at run-time) based - on a description of the memory layout. The memory layout is typically - provided by the platform port as a list of memory regions; - -#. Support for generating translation tables pertaining to a different - translation regime than the exception level the library code is executing at; - -#. Support for dynamic mapping and unmapping of regions, even while the MMU is - on. This can be used to temporarily map some memory regions and unmap them - later on when no longer needed; - -#. Support for non-identity virtual to physical mappings to compress the virtual - address space; - -#. Support for changing memory attributes of memory regions at run-time. - - -About version 1 and version 2 ------------------------------ - -This document focuses on version 2 of the library, whose sources are available -in the `lib/xlat_tables_v2`_ directory. Version 1 of the library can still be -found in `lib/xlat_tables`_ directory but it is less flexible and doesn't -support dynamic mapping. Although potential bug fixes will be applied to both -versions, future features enhancements will focus on version 2 and might not be -back-ported to version 1. Therefore, it is recommended to use version 2, -especially for new platform ports. - -However, please note that version 2 is still in active development and is not -considered stable yet. Hence, compatibility breaks might be introduced. - -From this point onwards, this document will implicitly refer to version 2 of the -library. - - -Design concepts and interfaces ------------------------------- - -This section presents some of the key concepts and data structures used in the -translation tables library. - -`mmap` regions -~~~~~~~~~~~~~~ - -An ``mmap_region`` is an abstract, concise way to represent a memory region to -map. It is one of the key interfaces to the library. It is identified by: - -- its physical base address; -- its virtual base address; -- its size; -- its attributes; -- its mapping granularity (optional). - -See the ``struct mmap_region`` type in `xlat_tables_v2.h`_. - -The user usually provides a list of such mmap regions to map and lets the -library transpose that in a set of translation tables. As a result, the library -might create new translation tables, update or split existing ones. - -The region attributes specify the type of memory (for example device or cached -normal memory) as well as the memory access permissions (read-only or -read-write, executable or not, secure or non-secure, and so on). In the case of -the EL1&0 translation regime, the attributes also specify whether the region is -a User region (EL0) or Privileged region (EL1). See the ``MT_xxx`` definitions -in `xlat_tables_v2.h`_. Note that for the EL1&0 translation regime the Execute -Never attribute is set simultaneously for both EL1 and EL0. - -The granularity controls the translation table level to go down to when mapping -the region. For example, assuming the MMU has been configured to use a 4KB -granule size, the library might map a 2MB memory region using either of the two -following options: - -- using a single level-2 translation table entry; -- using a level-2 intermediate entry to a level-3 translation table (which - contains 512 entries, each mapping 4KB). - -The first solution potentially requires less translation tables, hence -potentially less memory. However, if part of this 2MB region is later remapped -with different memory attributes, the library might need to split the existing -page tables to refine the mappings. If a single level-2 entry has been used -here, a level-3 table will need to be allocated on the fly and the level-2 -modified to point to this new level-3 table. This has a performance cost at -run-time. - -If the user knows upfront that such a remapping operation is likely to happen -then they might enforce a 4KB mapping granularity for this 2MB region from the -beginning; remapping some of these 4KB pages on the fly then becomes a -lightweight operation. - -The region's granularity is an optional field; if it is not specified the -library will choose the mapping granularity for this region as it sees fit (more -details can be found in `The memory mapping algorithm`_ section below). - -Translation Context -~~~~~~~~~~~~~~~~~~~ - -The library can create or modify translation tables pertaining to a different -translation regime than the exception level the library code is executing at. -For example, the library might be used by EL3 software (for instance BL31) to -create translation tables pertaining to the S-EL1&0 translation regime. - -This flexibility comes from the use of *translation contexts*. A *translation -context* constitutes the superset of information used by the library to track -the status of a set of translation tables for a given translation regime. - -The library internally allocates a default translation context, which pertains -to the translation regime of the current exception level. Additional contexts -may be explicitly allocated and initialized using the -``REGISTER_XLAT_CONTEXT()`` macro. Separate APIs are provided to act either on -the default translation context or on an alternative one. - -To register a translation context, the user must provide the library with the -following information: - -* A name. - - The resulting translation context variable will be called after this name, to - which ``_xlat_ctx`` is appended. For example, if the macro name parameter is - ``foo``, the context variable name will be ``foo_xlat_ctx``. - -* The maximum number of `mmap` regions to map. - - Should account for both static and dynamic regions, if applicable. - -* The number of sub-translation tables to allocate. - - Number of translation tables to statically allocate for this context, - excluding the initial lookup level translation table, which is always - allocated. For example, if the initial lookup level is 1, this parameter would - specify the number of level-2 and level-3 translation tables to pre-allocate - for this context. - -* The size of the virtual address space. - - Size in bytes of the virtual address space to map using this context. This - will incidentally determine the number of entries in the initial lookup level - translation table : the library will allocate as many entries as is required - to map the entire virtual address space. - -* The size of the physical address space. - - Size in bytes of the physical address space to map using this context. - -The default translation context is internally initialized using information -coming (for the most part) from platform-specific defines: - -- name: hard-coded to ``tf`` ; hence the name of the default context variable is - ``tf_xlat_ctx``; -- number of `mmap` regions: ``MAX_MMAP_REGIONS``; -- number of sub-translation tables: ``MAX_XLAT_TABLES``; -- size of the virtual address space: ``PLAT_VIRT_ADDR_SPACE_SIZE``; -- size of the physical address space: ``PLAT_PHY_ADDR_SPACE_SIZE``. - -Please refer to the `Porting Guide`_ for more details about these macros. - - -Static and dynamic memory regions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The library optionally supports dynamic memory mapping. This feature may be -enabled using the ``PLAT_XLAT_TABLES_DYNAMIC`` platform build flag. - -When dynamic memory mapping is enabled, the library categorises mmap regions as -*static* or *dynamic*. - -- *Static regions* are fixed for the lifetime of the system. They can only be - added early on, before the translation tables are created and populated. They - cannot be removed afterwards. - -- *Dynamic regions* can be added or removed any time. - -When the dynamic memory mapping feature is disabled, only static regions exist. - -The dynamic memory mapping feature may be used to map and unmap transient memory -areas. This is useful when the user needs to access some memory for a fixed -period of time, after which the memory may be discarded and reclaimed. For -example, a memory region that is only required at boot time while the system is -initializing, or to temporarily share a memory buffer between the normal world -and trusted world. Note that it is up to the caller to ensure that these regions -are not accessed concurrently while the regions are being added or removed. - -Although this feature provides some level of dynamic memory allocation, this -does not allow dynamically allocating an arbitrary amount of memory at an -arbitrary memory location. The user is still required to declare at compile-time -the limits of these allocations ; the library will deny any mapping request that -does not fit within this pre-allocated pool of memory. - - -Library APIs ------------- - -The external APIs exposed by this library are declared and documented in the -`xlat_tables_v2.h`_ header file. This should be the reference point for -getting information about the usage of the different APIs this library -provides. This section just provides some extra details and clarifications. - -Although the ``mmap_region`` structure is a publicly visible type, it is not -recommended to populate these structures by hand. Instead, wherever APIs expect -function arguments of type ``mmap_region_t``, these should be constructed using -the ``MAP_REGION*()`` family of helper macros. This is to limit the risk of -compatibility breaks, should the ``mmap_region`` structure type evolve in the -future. - -The ``MAP_REGION()`` and ``MAP_REGION_FLAT()`` macros do not allow specifying a -mapping granularity, which leaves the library implementation free to choose -it. However, in cases where a specific granularity is required, the -``MAP_REGION2()`` macro might be used instead. - -As explained earlier in this document, when the dynamic mapping feature is -disabled, there is no notion of dynamic regions. Conceptually, there are only -static regions. For this reason (and to retain backward compatibility with the -version 1 of the library), the APIs that map static regions do not embed the -word *static* in their functions names (for example ``mmap_add_region()``), in -contrast with the dynamic regions APIs (for example -``mmap_add_dynamic_region()``). - -Although the definition of static and dynamic regions is not based on the state -of the MMU, the two are still related in some way. Static regions can only be -added before ``init_xlat_tables()`` is called and ``init_xlat_tables()`` must be -called while the MMU is still off. As a result, static regions cannot be added -once the MMU has been enabled. Dynamic regions can be added with the MMU on or -off. In practice, the usual call flow would look like this: - -#. The MMU is initially off. - -#. Add some static regions, add some dynamic regions. - -#. Initialize translation tables based on the list of mmap regions (using one of - the ``init_xlat_tables*()`` APIs). - -#. At this point, it is no longer possible to add static regions. Dynamic - regions can still be added or removed. - -#. Enable the MMU. - -#. Dynamic regions can continue to be added or removed. - -Because static regions are added early on at boot time and are all in the -control of the platform initialization code, the ``mmap_add*()`` family of APIs -are not expected to fail. They do not return any error code. - -Nonetheless, these APIs will check upfront whether the region can be -successfully added before updating the translation context structure. If the -library detects that there is insufficient memory to meet the request, or that -the new region will overlap another one in an invalid way, or if any other -unexpected error is encountered, they will print an error message on the UART. -Additionally, when asserts are enabled (typically in debug builds), an assertion -will be triggered. Otherwise, the function call will just return straight away, -without adding the offending memory region. - - -Library limitations -------------------- - -Dynamic regions are not allowed to overlap each other. Static regions are -allowed to overlap as long as one of them is fully contained inside the other -one. This is allowed for backwards compatibility with the previous behaviour in -the version 1 of the library. - - -Implementation details ----------------------- - -Code structure -~~~~~~~~~~~~~~ - -The library is divided into 4 modules: - -- **Core module** - - Provides the main functionality of the library, such as the initialization of - translation tables contexts and mapping/unmapping memory regions. This module - provides functions such as ``mmap_add_region_ctx`` that let the caller specify - the translation tables context affected by them. - - See `xlat_tables_core.c`_. - -- **Active context module** - - Instantiates the context that is used by the current BL image and provides - helpers to manipulate it, abstracting it from the rest of the code. - This module provides functions such as ``mmap_add_region``, that directly - affect the BL image using them. - - See `xlat_tables_context.c`_. - -- **Utilities module** - - Provides additional functionality like debug print of the current state of the - translation tables and helpers to query memory attributes and to modify them. - - See `xlat_tables_utils.c`_. - -- **Architectural module** - - Provides functions that are dependent on the current execution state - (AArch32/AArch64), such as the functions used for TLB invalidation, setup the - MMU, or calculate the Physical Address Space size. They do not need a - translation context to work on. - - See `aarch32/xlat_tables_arch.c`_ and `aarch64/xlat_tables_arch.c`_. - -From mmap regions to translation tables -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A translation context contains a list of ``mmap_region_t``, which holds the -information of all the regions that are mapped at any given time. Whenever there -is a request to map (resp. unmap) a memory region, it is added to (resp. removed -from) the ``mmap_region_t`` list. - -The mmap regions list is a conceptual way to represent the memory layout. At -some point, the library has to convert this information into actual translation -tables to program into the MMU. - -Before the ``init_xlat_tables()`` API is called, the library only acts on the -mmap regions list. Adding a static or dynamic region at this point through one -of the ``mmap_add*()`` APIs does not affect the translation tables in any way, -they only get registered in the internal mmap region list. It is only when the -user calls the ``init_xlat_tables()`` that the translation tables are populated -in memory based on the list of mmap regions registered so far. This is an -optimization that allows creation of the initial set of translation tables in -one go, rather than having to edit them every time while the MMU is disabled. - -After the ``init_xlat_tables()`` API has been called, only dynamic regions can -be added. Changes to the translation tables (as well as the mmap regions list) -will take effect immediately. - -The memory mapping algorithm -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The mapping function is implemented as a recursive algorithm. It is however -bound by the level of depth of the translation tables (the Armv8-A architecture -allows up to 4 lookup levels). - -By default [#granularity-ref]_, the algorithm will attempt to minimize the -number of translation tables created to satisfy the user's request. It will -favour mapping a region using the biggest possible blocks, only creating a -sub-table if it is strictly necessary. This is to reduce the memory footprint of -the firmware. - -The most common reason for needing a sub-table is when a specific mapping -requires a finer granularity. Misaligned regions also require a finer -granularity than what the user may had originally expected, using a lot more -memory than expected. The reason is that all levels of translation are -restricted to address translations of the same granularity as the size of the -blocks of that level. For example, for a 4 KiB page size, a level 2 block entry -can only translate up to a granularity of 2 MiB. If the Physical Address is not -aligned to 2 MiB then additional level 3 tables are also needed. - -Note that not every translation level allows any type of descriptor. Depending -on the page size, levels 0 and 1 of translation may only allow table -descriptors. If a block entry could be able to describe a translation, but that -level does not allow block descriptors, a table descriptor will have to be used -instead, as well as additional tables at the next level. - -|Alignment Example| - -The mmap regions are sorted in a way that simplifies the code that maps -them. Even though this ordering is only strictly needed for overlapping static -regions, it must also be applied for dynamic regions to maintain a consistent -order of all regions at all times. As each new region is mapped, existing -entries in the translation tables are checked to ensure consistency. Please -refer to the comments in the source code of the core module for more details -about the sorting algorithm in use. - -.. [#granularity-ref] That is, when mmap regions do not enforce their mapping - granularity. - -TLB maintenance operations -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The library takes care of performing TLB maintenance operations when required. -For example, when the user requests removing a dynamic region, the library -invalidates all TLB entries associated to that region to ensure that these -changes are visible to subsequent execution, including speculative execution, -that uses the changed translation table entries. - -A counter-example is the initialization of translation tables. In this case, -explicit TLB maintenance is not required. The Armv8-A architecture guarantees -that all TLBs are disabled from reset and their contents have no effect on -address translation at reset [#tlb-reset-ref]_. Therefore, the TLBs invalidation -is deferred to the ``enable_mmu*()`` family of functions, just before the MMU is -turned on. - -TLB invalidation is not required when adding dynamic regions either. Dynamic -regions are not allowed to overlap existing memory region. Therefore, if the -dynamic mapping request is deemed legitimate, it automatically concerns memory -that was not mapped in this translation regime and the library will have -initialized its corresponding translation table entry to an invalid -descriptor. Given that the TLBs are not architecturally permitted to hold any -invalid translation table entry [#tlb-no-invalid-entry]_, this means that this -mapping cannot be cached in the TLBs. - -.. [#tlb-reset-ref] See section D4.9 `Translation Lookaside Buffers (TLBs)`, subsection `TLB behavior at reset` in Armv8-A, rev C.a. -.. [#tlb-no-invalid-entry] See section D4.10.1 `General TLB maintenance requirements` in Armv8-A, rev C.a. - --------------- - -*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* - -.. _lib/xlat_tables_v2: ../lib/xlat_tables_v2 -.. _lib/xlat_tables: ../lib/xlat_tables -.. _xlat_tables_v2.h: ../include/lib/xlat_tables/xlat_tables_v2.h -.. _xlat_tables_context.c: ../lib/xlat_tables_v2/xlat_tables_context.c -.. _xlat_tables_core.c: ../lib/xlat_tables_v2/xlat_tables_core.c -.. _xlat_tables_utils.c: ../lib/xlat_tables_v2/xlat_tables_utils.c -.. _aarch32/xlat_tables_arch.c: ../lib/xlat_tables_v2/aarch32/xlat_tables_arch.c -.. _aarch64/xlat_tables_arch.c: ../lib/xlat_tables_v2/aarch64/xlat_tables_arch.c -.. _Porting Guide: porting-guide.rst -.. |Alignment Example| image:: ./diagrams/xlat_align.png?raw=true diff --git a/maintainers.rst b/maintainers.rst deleted file mode 100644 index 0fa909f..0000000 --- a/maintainers.rst +++ /dev/null @@ -1,294 +0,0 @@ -Trusted Firmware-A maintainers -============================== - -Trusted Firmware-A (TF-A) is an Arm maintained project. All contributions are -ultimately merged by the maintainers listed below. Technical ownership of some -parts of the codebase is delegated to the sub-maintainers listed below. An -acknowledgement from these sub-maintainers may be required before the -maintainers merge a contribution. - -Main maintainers ----------------- -:M: Dan Handley -:G: `danh-arm`_ -:M: Dimitris Papastamos -:G: `dp-arm`_ -:M: Soby Mathew -:G: `soby-mathew`_ - -Allwinner ARMv8 platform port ------------------------------ -:M: Andre Przywara -:G: `Andre-ARM`_ -:M: Samuel Holland -:G: `smaeul`_ -:F: docs/plat/allwinner.rst -:F: plat/allwinner/ -:F: drivers/allwinner/ - -Amlogic Meson S905 (GXBB) platform port ---------------------------------------- -:M: Andre Przywara -:G: `Andre-ARM`_ -:F: docs/plat/meson-gxbb.rst -:F: drivers/meson/ -:F: plat/meson/gxbb/ - -Amlogic Meson S905x (GXL) platform port ---------------------------------------- -:M: Remi Pommarel -:G: `remi-triplefault`_ -:F: docs/plat/meson-gxl.rst -:F: drivers/meson/gxl -:F: plat/meson/gxl/ - -Armv7-A architecture port -------------------------- -:M: Etienne Carriere -:G: `etienne-lms`_ - -Arm System Guidance for Infrastructure / Mobile FVP platforms -------------------------------------------------------------- -:M: Nariman Poushin -:G: `npoushin`_ -:M: Thomas Abraham -:G: `thomas-arm`_ -:F: plat/arm/css/sgi/ -:F: plat/arm/css/sgm/ -:F: plat/arm/board/sgi575/ -:F: plat/arm/board/sgm775/ - -Console API framework ---------------------- -:M: Julius Werner -:G: `jwerner-chromium`_ -:F: drivers/console/ -:F: include/drivers/console.h -:F: plat/common/aarch64/crash_console_helpers.S - -coreboot support libraries --------------------------- -:M: Julius Werner -:G: `jwerner-chromium`_ -:F: drivers/coreboot/ -:F: include/drivers/coreboot/ -:F: include/lib/coreboot.h -:F: lib/coreboot/ - -eMMC/UFS drivers ----------------- -:M: Haojian Zhuang -:G: `hzhuang1`_ -:F: drivers/partition/ -:F: drivers/synopsys/emmc/ -:F: drivers/synopsys/ufs/ -:F: drivers/ufs/ -:F: include/drivers/dw_ufs.h -:F: include/drivers/ufs.h -:F: include/drivers/synopsys/dw_mmc.h - -HiSilicon HiKey and HiKey960 platform ports -------------------------------------------- -:M: Haojian Zhuang -:G: `hzhuang1`_ -:F: docs/plat/hikey.rst -:F: docs/plat/hikey960.rst -:F: plat/hisilicon/hikey/ -:F: plat/hisilicon/hikey960/ - -HiSilicon Poplar platform port ------------------------------- -:M: Shawn Guo -:G: `shawnguo2`_ -:F: docs/plat/poplar.rst -:F: plat/hisilicon/poplar/ - -Intel SocFPGA platform ports ----------------------------- -:M: Tien Hock Loh -:G: `thloh85-intel` -:F: plat/intel/soc - -MediaTek platform ports ------------------------ -:M: Yidi Lin (林以廸) -:G: `mtk09422`_ -:F: plat/mediatek/ - -Marvell platform ports and SoC drivers --------------------------------------- -:M: Konstantin Porotchkin -:G: `kostapr`_ -:F: docs/marvell/ -:F: plat/marvell/ -:F: drivers/marvell/ -:F: tools/marvell/ - -NVidia platform ports ---------------------- -:M: Varun Wadekar -:G: `vwadekar`_ -:F: docs/plat/nvidia-tegra.rst -:F: include/lib/cpus/aarch64/denver.h -:F: lib/cpus/aarch64/denver.S -:F: plat/nvidia/ - -NXP QorIQ Layerscape platform ports ------------------------------------ -:M: Jiafei Pan -:G: `qoriq-open-source`_ -:F: docs/plat/ls1043a.rst -:F: plat/layerscape/ - -NXP i.MX 7 WaRP7 platform port and SoC drivers ----------------------------------------------- -:M: Bryan O'Donoghue -:G: `bryanodonoghue`_ -:M: Jun Nie -:G: `niej`_ -:F: docs/plat/warp7.rst -:F: plat/imx/common/ -:F: plat/imx/imx7/ -:F: drivers/imx/timer/ -:F: drivers/imx/uart/ -:F: drivers/imx/usdhc/ - -NXP i.MX 8 platform port ------------------------- -:M: Anson Huang -:G: `Anson-Huang`_ -:F: docs/plat/imx8.rst -:F: plat/imx/ - -NXP i.MX8M platform port ------------------------- -:M: Jacky Bai -:G: `JackyBai`_ -:F: doc/plat/imx8m.rst -:F: plat/imx/imx8m/ - -OP-TEE dispatcher ------------------ -:M: Jens Wiklander -:G: `jenswi-linaro`_ -:F: docs/spd/optee-dispatcher.rst -:F: services/spd/opteed/ - -QEMU platform port ------------------- -:M: Jens Wiklander -:G: `jenswi-linaro`_ -:F: docs/plat/qemu.rst -:F: plat/qemu/ - -Raspberry Pi 3 platform port ----------------------------- -:M: Ying-Chun Liu (PaulLiu) -:G: `grandpaul`_ -:F: docs/plat/rpi3.rst -:F: plat/rpi3/ -:F: drivers/rpi3/ -:F: include/drivers/rpi3/ - -Renesas rcar-gen3 platform port -------------------------------- -:M: Jorge Ramirez-Ortiz -:G: `ldts`_ -:M: Marek Vasut -:G: `marex`_ -:F: docs/plat/rcar-gen3.rst -:F: plat/renesas/rcar -:F: drivers/renesas/rcar -:F: tools/renesas/rcar_layout_create - -RockChip platform port ----------------------- -:M: Tony Xie -:G: `TonyXie06`_ -:G: `rockchip-linux`_ -:M: Heiko Stuebner -:G: `mmind`_ -:F: plat/rockchip/ - -STM32MP1 platform port ----------------------- -:M: Yann Gautier -:G: `Yann-lms`_ -:F: docs/plat/stm32mp1.rst -:F: drivers/st/ -:F: fdts/stm32\* -:F: include/drivers/st/ -:F: include/dt-bindings/\*/stm32\* -:F: plat/st/ -:F: tools/stm32image/ - -Synquacer platform port ------------------------ -:M: Sumit Garg -:G: `b49020`_ -:F: docs/plat/synquacer.rst -:F: plat/socionext/synquacer/ - -Texas Instruments platform port -------------------------------- -:M: Andrew F. Davis -:G: `glneo`_ -:F: docs/plat/ti-k3.rst -:F: plat/ti/ - -TLK/Trusty secure payloads --------------------------- -:M: Varun Wadekar -:G: `vwadekar`_ -:F: docs/spd/tlk-dispatcher.rst -:F: docs/spd/trusty-dispatcher.rst -:F: include/bl32/payloads/tlk.h -:F: services/spd/tlkd/ -:F: services/spd/trusty/ - -UniPhier platform port ----------------------- -:M: Masahiro Yamada -:G: `masahir0y`_ -:F: docs/plat/socionext-uniphier.rst -:F: plat/socionext/uniphier/ - -Xilinx platform port --------------------- -:M: Siva Durga Prasad Paladugu -:G: `sivadur`_ -:F: docs/plat/xilinx-zynqmp.rst -:F: plat/xilinx/ - -.. _Andre-ARM: https://github.com/Andre-ARM -.. _Anson-Huang: https://github.com/Anson-Huang -.. _bryanodonoghue: https://github.com/bryanodonoghue -.. _b49020: https://github.com/b49020 -.. _danh-arm: https://github.com/danh-arm -.. _dp-arm: https://github.com/dp-arm -.. _etienne-lms: https://github.com/etienne-lms -.. _glneo: https://github.com/glneo -.. _hzhuang1: https://github.com/hzhuang1 -.. _JackyBai: https://github.com/JackyBai -.. _jenswi-linaro: https://github.com/jenswi-linaro -.. _ldts: https://github.com/ldts -.. _marex: https://github.com/marex -.. _niej: https://github.com/niej -.. _kostapr: https://github.com/kostapr -.. _masahir0y: https://github.com/masahir0y -.. _mmind: https://github.com/mmind -.. _mtk09422: https://github.com/mtk09422 -.. _npoushin: https://github.com/npoushin -.. _qoriq-open-source: https://github.com/qoriq-open-source -.. _remi-triplefault: https://github.com/repk -.. _rockchip-linux: https://github.com/rockchip-linux -.. _shawnguo2: https://github.com/shawnguo2 -.. _sivadur: https://github.com/sivadur -.. _smaeul: https://github.com/smaeul -.. _soby-mathew: https://github.com/soby-mathew -.. _thomas-arm: https://github.com/thomas-arm -.. _TonyXie06: https://github.com/TonyXie06 -.. _vwadekar: https://github.com/vwadekar -.. _Yann-lms: https://github.com/Yann-lms -.. _grandpaul: https://github.com/grandpaul -.. _jwerner-chromium: https://github.com/jwerner-chromium