| Platform Fault Detection Interface (PFDI) |
| ***************************************** |
| |
| This document describes the Trusted Firmware-A (TF-A) support for the Platform |
| Fault Detection Interface (PFDI). |
| |
| PFDI provides a standard EL3 interface for running platform or PE fault-detection |
| tests, reporting their result to the non-secure world, and coordinating |
| out-of-reset (OoR) self-tests during CPU bring-up. |
| |
| PFDI is intended for platforms that integrate a processor or platform |
| self-test library and need a standard firmware interface for diagnostics. |
| Non-secure software can use it to discover the available test library, request |
| online tests, and read the last recorded test result, while TF-A can use it to |
| run OoR tests before a PE is released for normal execution. |
| |
| For the architectural definition of PFDI, refer to the `PFDI Supplement`_. |
| This document focuses on the TF-A implementation and on the platform code that |
| must be provided to make it usable. |
| |
| SMC Interface |
| ============= |
| |
| The following SMC function IDs are implemented: |
| |
| - ``PFDI_VERSION`` |
| - ``PFDI_FEATURES`` |
| - ``PFDI_PE_TEST_ID`` |
| - ``PFDI_PE_TEST_PART_COUNT`` |
| - ``PFDI_PE_TEST_RUN`` |
| - ``PFDI_PE_TEST_RESULT`` |
| - ``PFDI_FW_CHECK`` |
| - ``PFDI_FORCE_ERROR`` |
| |
| Execution Model |
| =============== |
| |
| - PFDI operations are **PE-local**. ``PFDI_PE_TEST_RUN`` and |
| ``PFDI_PE_TEST_RESULT`` operate on the calling PE. |
| - ``PFDI_FORCE_ERROR`` is also PE-local and applies to the next invocation of |
| the targeted PFDI ABI from that same PE, even if that invocation would |
| otherwise fail normal parameter validation. |
| - ``PFDI_PE_TEST_RUN`` is executed in one of two modes: |
| |
| - **OoR mode** (``PFDI_OOR_MODE``): used by TF-A during PE bring-up. |
| - **Online mode** (``PFDI_ONL_MODE``): used by non-secure callers after boot. |
| |
| - For OoR execution, TF-A stores the per-PE result and uses it later to decide |
| whether a PE is allowed to continue boot. |
| - ``start`` and ``end`` may be passed as ``-1`` together to request the |
| full test range. Any other mixed use of ``-1`` is rejected. |
| - Pending injected errors, stored results, and any other PFDI state are not |
| persistent across reset or firmware update. |
| |
| Required Platform Functions |
| =========================== |
| |
| The core PFDI service requires exactly one registered test library descriptor: |
| |
| .. code-block:: c |
| |
| REGISTER_PFDI_FUNC(name, run, count, result); |
| |
| All three callbacks must be implemented. |
| |
| ``run(start, end, mode, ft_id)`` |
| -------------------------------- |
| |
| This callback executes the requested test range on the current PE. |
| |
| - ``start`` and ``end`` are the test-case indices to execute. |
| - ``mode`` is either ``PFDI_OOR_MODE`` or ``PFDI_ONL_MODE``. |
| - ``ft_id`` must be updated with the failing test identifier when returning |
| ``PFDI_RET_FAULT_FOUND``. |
| - Return ``PFDI_SMCC_RET_SUCCESS`` on success, or a ``pfdi_status_t`` error |
| code on failure. |
| |
| ``count(tc_size)`` |
| ------------------ |
| |
| This callback returns the total number of available test cases. |
| |
| - ``tc_size`` must be populated with the number of test parts. |
| - Return ``PFDI_RET_TEST_COUNT_ZERO`` if no tests are available. |
| |
| ``result(cpu_num, ft_id)`` |
| -------------------------- |
| |
| This callback returns the stored result for the requested PE. |
| |
| - ``cpu_num`` is the logical CPU number supplied by TF-A. |
| - ``ft_id`` should be updated with the failing test identifier when the stored |
| result is ``PFDI_RET_FAULT_FOUND``. |
| - Return ``PFDI_RET_NOT_RUN`` until OoR testing has completed for that PE. |
| |
| Optional Platform-Specific Functions |
| ==================================== |
| |
| Platforms may also register an optional descriptor: |
| |
| .. code-block:: c |
| |
| static const struct plat_pfdi_func_desc plat_pfdi_func_desc = { |
| .name = "my-platform", |
| .force_plat_err = force_plat_err, |
| .check_plat_err = check_plat_err, |
| .post_run = post_run, |
| }; |
| |
| pfdi_register_plat_func_desc(&plat_pfdi_func_desc); |
| |
| All callbacks are optional and may be ``NULL``. The platform must register the |
| descriptor during BL31 platform setup, before ``pfdi_init()`` runs. |
| Registrations are merged by callback slot, which allows separate components to |
| install disjoint hooks such as ``check_plat_err()`` and ``post_run()``. |
| |
| ``force_plat_err(fid, error_id)`` |
| --------------------------------- |
| |
| This hook runs when ``PFDI_FORCE_ERROR`` is used to inject a failure for a given |
| SMC function. |
| |
| Use it when error injection must also modify platform state, for example: |
| |
| - programming a hardware fault-status register, |
| - forcing an SBIST/BIST failure indication, |
| - priming a platform monitor so that the next request observes the injected |
| error. |
| |
| If this hook returns non-zero, the PFDI service rejects the injection request. |
| |
| ``check_plat_err(fid, error_id)`` |
| --------------------------------- |
| |
| This hook runs when an injected error is consumed by a later PFDI operation. |
| |
| Use it to validate a generic injected error against platform state. |
| Typical uses are: |
| |
| - checking whether the expected hardware condition was actually latched before |
| returning the error to the caller. |
| |
| If no platform hook is registered, the PFDI service returns the injected |
| ``error_id`` directly. When a hook is present, TF-A still returns the original |
| injected ABI error to the caller, so the hook must not depend on rewriting the |
| reported ``x0`` value. |
| |
| ``post_run(status, start, end, mode, ft_id)`` |
| --------------------------------------------- |
| |
| This hook runs after every ``pfdi_pe_test_run()`` attempt, regardless of whether |
| the test run succeeded or failed. |
| |
| Use it for follow-up actions such as: |
| |
| - clearing temporary hardware state, |
| - recording telemetry, |
| - updating platform result storage, |
| - triggering additional housekeeping after an OoR or online run. |
| |
| Platform Integration Steps |
| ========================== |
| |
| To enable PFDI on a platform: |
| |
| 1. Select the ``PFDI_SUPPORT`` option in the platform build. |
| 2. Define ``PFDI_TEST_LIB_VERSION`` to the implemented test library version, |
| either in ``platform_def.h`` or on the build command line. |
| 3. Compile the PFDI service code and the platform test implementation into BL31. |
| 4. Provide one ``REGISTER_PFDI_FUNC()`` instance with working ``run()``, |
| ``count()`` and ``result()`` callbacks. |
| 5. If OoR tests must run when a secondary PE is powered on through a |
| platform-specific path, implement ``pfdi_enable()`` and |
| ``plat_pfdi_mpidr_by_core_pos()``. The latter maps the linear core position |
| to the MPIDR expected by the platform's PSCI ``pwr_domain_on()`` callback, |
| and returns ``INVALID_MPID`` for an invalid position. |
| 6. Optionally provide ``struct plat_pfdi_func_desc`` when platform-specific |
| error injection, validation, or post-run processing is needed. |
| |
| Configuration |
| ============= |
| |
| ``PFDI_SUPPORT`` |
| ---------------- |
| |
| Enables the EL3 PFDI service. |
| |
| ``PFDI_TEST_LIB_VERSION`` |
| ------------------------- |
| |
| This value is optional. If it is not defined, TF-A uses zero and |
| ``PFDI_PE_TEST_ID`` returns ``PFDI_RET_UNKNOWN``. Platforms can define it in |
| ``platform_def.h`` or pass it on the build command line. |
| |
| PFDI_TEST_LIB_VERSION encoding (uint64_t) |
| As per Platform Fault Detection Interface Specification v1.0BET0, the test |
| library version returned by ``PFDI_PE_TEST_ID`` in the following format: |
| |
| :: |
| |
| Bits [63:32] : Reserved, must be 0 |
| Bits [31:24] : Vendor ID |
| Bits [23:20] : Reserved, must be 0 |
| Bits [19:16] : Implementation ID |
| Bits [15:8] : Major version |
| Bits [7:0] : Minor version |
| |
| # Vendor IDs |
| _____________________________________________________________________________ |
| | Vendor ID | Vendor name | |
| |____________________________________|______________________________________| |
| | 0 | Arm Limited | |
| |____________________________________|______________________________________| |
| | Others | Reserved | |
| |____________________________________|______________________________________| |
| |
| PFDI Test Library Implementation IDs |
| _____________________________________________________________________________ |
| | Implementation ID | Library name | |
| |____________________________________|______________________________________| |
| | 0 | Reserved | |
| |____________________________________|______________________________________| |
| | 1 | Arm STL | |
| |____________________________________|______________________________________| |
| | Others | Reserved | |
| |____________________________________|______________________________________| |
| |
| Notes: |
| - A value of 0 means no test engine metadata is available, and |
| ``PFDI_PE_TEST_ID`` returns ``PFDI_RET_UNKNOWN``. |
| - Currently only Vendor ID 0 is valid. |
| - For Arm vendor, Implementation ID 1 identifies Arm STL. |
| - On error, the encoded value must be zero. |
| |
| Example:: |
| |
| PFDI_TEST_LIB_VERSION := 0x0000000000010100 |
| |
| Vendor ID = 0x00 (Arm Limited) |
| Implementation ID = 0x01 (Arm STL) |
| Major version = 0x01 |
| Minor version = 0x00 |
| |
| Limitations |
| =========== |
| |
| - ``PFDI_FW_CHECK`` currently has no firmware-specific checks behind it and |
| returns success unless an injected error is configured. |
| - ``PFDI_FORCE_ERROR`` is one-shot per PE and per ABI function. The next |
| invocation of the targeted function consumes the pending injected error and |
| returns it in ``x0`` with ``x1``-``x4`` cleared. |
| - The platform must provide result storage semantics that match the TF-A flow, |
| especially for OoR execution on secondary PEs. |
| - The current implementation assumes that PFDI tests are safe to run on the |
| target PE in the requested execution mode. |
| |
| -------------- |
| |
| *Copyright (c) 2026, Arm Limited and Contributors. All rights reserved.* |
| |
| .. _PFDI Supplement: https://support.arm.com/documentation/110468/latest/ |