Merge changes from topic "cot-dt2c" into integration
* changes:
feat(arm): update documentation for cot-dt2c
feat(arm): remove the bl2 static c file
feat(arm): generate tbbr c file CoT dt2c
feat(arm): makefile invoke CoT dt2c
feat(auth): standalone CoT dt2c tool
refactor(auth): separate bl1 and bl2 CoT
refactor(st): align the NV counter naming
refactor(fvp): align the NV counter naming
diff --git a/docs/components/ffa-manifest-binding.rst b/docs/components/ffa-manifest-binding.rst
index ee322ac..29b89b2 100644
--- a/docs/components/ffa-manifest-binding.rst
+++ b/docs/components/ffa-manifest-binding.rst
@@ -1,5 +1,5 @@
FF-A manifest binding to device tree
-========================================
+====================================
This document defines the nodes and properties used to define a partition,
according to the FF-A specification.
@@ -82,7 +82,7 @@
the partition. Absence of this field indicates that the entry point is at
offset 0x0 from the base of the partition's binary.
-- xlat-granule [mandatory]
+- xlat-granule
- value type: <u32>
- Translation granule used with the partition:
@@ -91,10 +91,10 @@
- 0x2: 64k
- boot-order
- - value type: <u16>
+ - value type: <u32>
- A unique number amongst all partitions that specifies if this partition
must be booted before others. The partition with the smaller number will be
- booted first.
+ booted first. Highest vlue allowed for this field is 0xFFFF.
- rx-tx-buffer
- value type: "memory-regions" node
@@ -103,13 +103,15 @@
The "compatible" must be the string "arm,ffa-manifest-rx_tx-buffer".
- messaging-method [mandatory]
- - value type: <u8>
+ - value type: <u32>
- Specifies which messaging methods are supported by the partition, set bit
means the feature is supported, clear bit - not supported:
- - Bit[0]: partition can receive direct requests if set
- - Bit[1]: partition can send direct requests if set
+ - Bit[0]: partition can receive direct requests via FFA_MSG_SEND_DIRECT_REQ ABI if set
+ - Bit[1]: partition can send direct requests via FFA_MSG_SEND_DIRECT_REQ ABI if set
- Bit[2]: partition can send and receive indirect messages
+ - Bit[9]: partition can receive direct requests via FFA_MSG_SEND_DIRECT_REQ2 ABI if set
+ - Bit[10]: partition can send direct requests via FFA_MSG_SEND_DIRECT_REQ2 ABI if set
- managed-exit
- value type: <empty>
@@ -117,6 +119,11 @@
- This field is deprecated in favor of ns-interrupts-action field in the FF-A
v1.1 EAC0 spec.
+- managed-exit-virq
+ - value type: <empty>
+ - Indicates if the partition needs managed exit, if supported, to be signaled
+ through vFIQ signal.
+
- ns-interrupts-action [mandatory]
- value type: <u32>
- Specifies the action that the SPMC must take in response to a Non-secure
@@ -136,6 +143,12 @@
- 0x0: Other-Secure interrupt is queued
- 0x1: Other-Secure interrupt is signaled
+- runtime-model
+ - value type: <u32>
+ - Indicates whether the SP execution can be preempted.
+ - This field is deprecated in favor of other-s-interrupts-action and
+ ns-interrupts-action fields in the FF-A v1.1 spec.
+
- has-primary-scheduler
- value type: <empty>
- Presence of this field indicates that the partition implements the primary
@@ -157,11 +170,6 @@
the FF-A boot information blob to be passed in the specified general purpose
register.
-- stream-endpoint-ids
- - value type: <prop-encoded-array>
- - List of <u32> tuples, identifying the IDs this partition is acting as
- proxy for.
-
- power-management-messages
- value type: <u32>
- Specifies which power management messages a partition subscribes to.
@@ -172,6 +180,17 @@
- Bit[1]: CPU_SUSPEND
- Bit[2]: CPU_SUSPEND_RESUME
+- vm-availability-messages
+ - value type: <u32>
+ - Specifies which VM availability messages a partition subscribes to. A set
+ bit means the partition should be informed of the event, clear bit - should
+ not be informed of event:
+
+ - Bit[0]: VM created
+ - Bit[1]: VM destroyed
+
+.. _memory_region_node:
+
Memory Regions
--------------
@@ -209,6 +228,25 @@
then communicate the region properties (including the base address chosen
by the partition manager) to the partition.
+- stream-ids
+ - value type: <prop-encoded-array>
+ - List of IDs belonging to a DMA capable peripheral device that has access to
+ the memory region represented by current node.
+ - Each ID must have been declared in exactly one device region node.
+
+- smmu-id
+ - value type: <u32>
+ - Identifies the SMMU IP that enforces the access control for the DMA device
+ that owns the above stream-ids.
+
+- stream-ids-access-permissions
+ - value type: <prop-encoded-array>
+ - List of attributes representing the instruction and data access permissions
+ used by the DMA device streams to access the memory region represented by
+ current node.
+
+.. _device_region_node:
+
Device Regions
--------------
@@ -251,11 +289,10 @@
- stream-ids
- value type: <prop-encoded-array>
- - A list of (id, mem-manage) pair, where:
+ - List of IDs where an ID is a unique <u32> value amongst all devices assigned
+ to the partition.
- - id: A unique <u32> value amongst all devices assigned to the partition.
-
-- interrupts [mandatory]
+- interrupts
- value type: <prop-encoded-array>
- A list of (id, attributes) pair describing the device interrupts, where:
@@ -306,4 +343,4 @@
--------------
-*Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index b6f4219..220c3ce 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -10,42 +10,12 @@
========
+--------+--------------------------------------+
-| CoT | Chain of Trust |
-+--------+--------------------------------------+
-| DMA | Direct Memory Access |
-+--------+--------------------------------------+
-| DTB | Device Tree Blob |
-+--------+--------------------------------------+
| DTS | Device Tree Source |
+--------+--------------------------------------+
-| EC | Execution Context |
-+--------+--------------------------------------+
-| FIP | Firmware Image Package |
-+--------+--------------------------------------+
| FF-A | Firmware Framework for Arm A-profile |
+--------+--------------------------------------+
-| IPA | Intermediate Physical Address |
-+--------+--------------------------------------+
-| JOP | Jump-Oriented Programming |
-+--------+--------------------------------------+
| NWd | Normal World |
+--------+--------------------------------------+
-| ODM | Original Design Manufacturer |
-+--------+--------------------------------------+
-| OEM | Original Equipment Manufacturer |
-+--------+--------------------------------------+
-| PA | Physical Address |
-+--------+--------------------------------------+
-| PE | Processing Element |
-+--------+--------------------------------------+
-| PM | Power Management |
-+--------+--------------------------------------+
-| PVM | Primary VM |
-+--------+--------------------------------------+
-| ROP | Return-Oriented Programming |
-+--------+--------------------------------------+
-| SMMU | System Memory Management Unit |
-+--------+--------------------------------------+
| SP | Secure Partition |
+--------+--------------------------------------+
| SPD | Secure Payload Dispatcher |
@@ -56,16 +26,8 @@
+--------+--------------------------------------+
| SPMD | SPM Dispatcher |
+--------+--------------------------------------+
-| SiP | Silicon Provider |
-+--------+--------------------------------------+
| SWd | Secure World |
+--------+--------------------------------------+
-| TLV | Tag-Length-Value |
-+--------+--------------------------------------+
-| TOS | Trusted Operating System |
-+--------+--------------------------------------+
-| VM | Virtual Machine |
-+--------+--------------------------------------+
Foreword
========
@@ -74,34 +36,14 @@
codebase:
#. S-EL2 SPMC based on the FF-A specification `[1]`_, enabling virtualization in
- the secure world, managing multiple S-EL1 or S-EL0 partitions.
+ the secure world, managing multiple S-EL1 or S-EL0 partitions `[5]`_.
#. EL3 SPMC based on the FF-A specification, managing a single S-EL1 partition
- without virtualization in the secure world.
+ without virtualization in the secure world `[6]`_.
#. EL3 SPM based on the MM specification, legacy implementation managing a
single S-EL0 partition `[2]`_.
These implementations differ in their respective SW architecture and only one
-can be selected at build time. This document:
-
-- describes the implementation from bullet 1. when the SPMC resides at S-EL2.
-- is not an architecture specification and it might provide assumptions
- on sections mandated as implementation-defined in the specification.
-- covers the implications to TF-A used as a bootloader, and Hafnium used as a
- reference code base for an S-EL2/SPMC secure firmware on platforms
- implementing the FEAT_SEL2 architecture extension.
-
-Terminology
------------
-
-- The term Hypervisor refers to the NS-EL2 component managing Virtual Machines
- (or partitions) in the normal world.
-- The term SPMC refers to the S-EL2 component managing secure partitions in
- the secure world when the FEAT_SEL2 architecture extension is implemented.
-- Alternatively, SPMC can refer to an S-EL1 component, itself being a secure
- partition and implementing the FF-A ABI on platforms not implementing the
- FEAT_SEL2 architecture extension.
-- The term VM refers to a normal world Virtual Machine managed by an Hypervisor.
-- The term SP refers to a secure world "Virtual Machine" managed by an SPMC.
+can be selected at build time.
Support for legacy platforms
----------------------------
@@ -123,16 +65,6 @@
- S-EL2 SPMC for platforms implementing the FEAT_SEL2 architecture
extension. The SPMD relays the FF-A protocol from EL3 to S-EL2.
-Sample reference stack
-======================
-
-The following diagram illustrates a possible configuration when the
-FEAT_SEL2 architecture extension is implemented, showing the SPMD
-and SPMC, one or multiple secure partitions, with an optional
-Hypervisor:
-
-.. image:: ../resources/diagrams/ff-a-spm-sel2.png
-
TF-A build options
==================
@@ -147,16 +79,15 @@
level to being at S-EL2. It defaults to enabled (value 1) when
SPD=spmd is chosen.
- **SPMC_AT_EL3**: this option adjusts the SPMC exception level to being
- at EL3.
-- If neither ``SPMD_SPM_AT_SEL2`` or ``SPMC_AT_EL3`` are enabled the SPMC
- exception level is set to S-EL1.
+ at EL3. If neither ``SPMD_SPM_AT_SEL2`` or ``SPMC_AT_EL3`` are enabled the
+ SPMC exception level is set to S-EL1.
``SPMD_SPM_AT_SEL2`` is enabled. The context save/restore routine
and exhaustive list of registers is visible at `[4]`_.
- **SPMC_AT_EL3_SEL0_SP**: this option enables the support to load SEL0 SP
when SPMC at EL3 support is enabled.
- **SP_LAYOUT_FILE**: this option specifies a text description file
providing paths to SP binary images and manifests in DTS format
- (see `Describing secure partitions`_). It
+ (see `[3]`_). It
is required when ``SPMD_SPM_AT_SEL2`` is enabled hence when multiple
secure partitions are to be loaded by BL2 on behalf of the SPMC.
@@ -275,1358 +206,28 @@
PLAT=fvp \
all fip
-FVP model invocation
-====================
-
-The FVP command line needs the following options to exercise the S-EL2 SPMC:
-
-+---------------------------------------------------+------------------------------------+
-| - cluster0.has_arm_v8-5=1 | Implements FEAT_SEL2, FEAT_PAuth, |
-| - cluster1.has_arm_v8-5=1 | and FEAT_BTI. |
-+---------------------------------------------------+------------------------------------+
-| - pci.pci_smmuv3.mmu.SMMU_AIDR=2 | Parameters required for the |
-| - pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B | SMMUv3.2 modeling. |
-| - pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 | |
-| - pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 | |
-| - pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 | |
-| - pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 | |
-| - pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 | |
-| - pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 | |
-+---------------------------------------------------+------------------------------------+
-| - cluster0.has_branch_target_exception=1 | Implements FEAT_BTI. |
-| - cluster1.has_branch_target_exception=1 | |
-+---------------------------------------------------+------------------------------------+
-| - cluster0.has_pointer_authentication=2 | Implements FEAT_PAuth |
-| - cluster1.has_pointer_authentication=2 | |
-+---------------------------------------------------+------------------------------------+
-| - cluster0.memory_tagging_support_level=2 | Implements FEAT_MTE2 |
-| - cluster1.memory_tagging_support_level=2 | |
-| - bp.dram_metadata.is_enabled=1 | |
-+---------------------------------------------------+------------------------------------+
-
-Sample FVP command line invocation:
-
-.. code:: shell
-
- <path-to-fvp-model>/FVP_Base_RevC-2xAEMvA -C pctl.startup=0.0.0.0 \
- -C cluster0.NUM_CORES=4 -C cluster1.NUM_CORES=4 -C bp.secure_memory=1 \
- -C bp.secureflashloader.fname=trusted-firmware-a/build/fvp/debug/bl1.bin \
- -C bp.flashloader0.fname=trusted-firmware-a/build/fvp/debug/fip.bin \
- -C bp.pl011_uart0.out_file=fvp-uart0.log -C bp.pl011_uart1.out_file=fvp-uart1.log \
- -C bp.pl011_uart2.out_file=fvp-uart2.log \
- -C cluster0.has_arm_v8-5=1 -C cluster1.has_arm_v8-5=1 \
- -C cluster0.has_pointer_authentication=2 -C cluster1.has_pointer_authentication=2 \
- -C cluster0.has_branch_target_exception=1 -C cluster1.has_branch_target_exception=1 \
- -C cluster0.memory_tagging_support_level=2 -C cluster1.memory_tagging_support_level=2 \
- -C bp.dram_metadata.is_enabled=1 \
- -C pci.pci_smmuv3.mmu.SMMU_AIDR=2 -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B \
- -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 \
- -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 \
- -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0
-
Boot process
============
-Loading Hafnium and secure partitions in the secure world
----------------------------------------------------------
-
-TF-A BL2 is the bootlader for the SPMC and SPs in the secure world.
-
-SPs may be signed by different parties (SiP, OEM/ODM, TOS vendor, etc.).
-Thus they are supplied as distinct signed entities within the FIP flash
-image. The FIP image itself is not signed hence this provides the ability
-to upgrade SPs in the field.
-
-Booting through TF-A
---------------------
-
-SP manifests
-~~~~~~~~~~~~
-
-An SP manifest describes SP attributes as defined in `[1]`_
-(partition manifest at virtual FF-A instance) in DTS format. It is
-represented as a single file associated with the SP. A sample is
-provided by `[5]`_. A binding document is provided by `[6]`_.
-
-Secure Partition packages
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Secure partitions are bundled as independent package files consisting
-of:
-
-- a header
-- a DTB
-- an image payload
-
-The header starts with a magic value and offset values to SP DTB and
-image payload. Each SP package is loaded independently by BL2 loader
-and verified for authenticity and integrity.
-
-The SP package identified by its UUID (matching FF-A uuid property) is
-inserted as a single entry into the FIP at end of the TF-A build flow
-as shown:
-
-.. code:: shell
-
- Trusted Boot Firmware BL2: offset=0x1F0, size=0x8AE1, cmdline="--tb-fw"
- EL3 Runtime Firmware BL31: offset=0x8CD1, size=0x13000, cmdline="--soc-fw"
- Secure Payload BL32 (Trusted OS): offset=0x1BCD1, size=0x15270, cmdline="--tos-fw"
- Non-Trusted Firmware BL33: offset=0x30F41, size=0x92E0, cmdline="--nt-fw"
- HW_CONFIG: offset=0x3A221, size=0x2348, cmdline="--hw-config"
- TB_FW_CONFIG: offset=0x3C569, size=0x37A, cmdline="--tb-fw-config"
- SOC_FW_CONFIG: offset=0x3C8E3, size=0x48, cmdline="--soc-fw-config"
- TOS_FW_CONFIG: offset=0x3C92B, size=0x427, cmdline="--tos-fw-config"
- NT_FW_CONFIG: offset=0x3CD52, size=0x48, cmdline="--nt-fw-config"
- B4B5671E-4A90-4FE1-B81F-FB13DAE1DACB: offset=0x3CD9A, size=0xC168, cmdline="--blob"
- D1582309-F023-47B9-827C-4464F5578FC8: offset=0x48F02, size=0xC168, cmdline="--blob"
-
-.. uml:: ../resources/diagrams/plantuml/fip-secure-partitions.puml
-
-Describing secure partitions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A json-formatted description file is passed to the build flow specifying paths
-to the SP binary image and associated DTS partition manifest file. The latter
-is processed by the dtc compiler to generate a DTB fed into the SP package.
-Optionally, the partition's json description can contain offsets for both
-the image and partition manifest within the SP package. Both offsets need to be
-4KB aligned, because it is the translation granule supported by Hafnium SPMC.
-These fields can be leveraged to support SPs with S1 translation granules that
-differ from 4KB, and to configure the regions allocated within the SP package,
-as well as to comply with the requirements for the implementation of the boot
-information protocol (see `Passing boot data to the SP`_ for more details). In
-case the offsets are absent in their json node, they default to 0x1000 and
-0x4000 for the manifest offset and image offset respectively.
-This file also specifies the SP owner (as an optional field) identifying the
-signing domain in case of dual root CoT.
-The SP owner can either be the silicon or the platform provider. The
-corresponding "owner" field value can either take the value of "SiP" or "Plat".
-In absence of "owner" field, it defaults to "SiP" owner.
-The UUID of the partition can be specified as a field in the description file or
-if it does not exist there the UUID is extracted from the DTS partition
-manifest.
-
-.. code:: shell
-
- {
- "tee1" : {
- "image": "tee1.bin",
- "pm": "tee1.dts",
- "owner": "SiP",
- "uuid": "1b1820fe-48f7-4175-8999-d51da00b7c9f"
- },
-
- "tee2" : {
- "image": "tee2.bin",
- "pm": "tee2.dts",
- "owner": "Plat"
- },
-
- "tee3" : {
- "image": {
- "file": "tee3.bin",
- "offset":"0x2000"
- },
- "pm": {
- "file": "tee3.dts",
- "offset":"0x6000"
- },
- "owner": "Plat"
- },
- }
-
-SPMC manifest
-~~~~~~~~~~~~~
-
-This manifest contains the SPMC *attribute* node consumed by the SPMD at boot
-time. It implements `[1]`_ (SP manifest at physical FF-A instance) and serves
-two different cases:
-
-- The SPMC resides at S-EL1: the SPMC manifest is used by the SPMD to setup a
- SP that co-resides with the SPMC and executes at S-EL1 or Secure Supervisor
- mode.
-- The SPMC resides at S-EL2: the SPMC manifest is used by the SPMD to setup
- the environment required by the SPMC to run at S-EL2. SPs run at S-EL1 or
- S-EL0.
-
-.. code:: shell
-
- attribute {
- spmc_id = <0x8000>;
- maj_ver = <0x1>;
- min_ver = <0x1>;
- exec_state = <0x0>;
- load_address = <0x0 0x6000000>;
- entrypoint = <0x0 0x6000000>;
- binary_size = <0x60000>;
- };
-
-- *spmc_id* defines the endpoint ID value that SPMC can query through
- ``FFA_ID_GET``.
-- *maj_ver/min_ver*. SPMD checks provided version versus its internal
- version and aborts if not matching.
-- *exec_state* defines the SPMC execution state (AArch64 or AArch32).
- Notice Hafnium used as a SPMC only supports AArch64.
-- *load_address* and *binary_size* are mostly used to verify secondary
- entry points fit into the loaded binary image.
-- *entrypoint* defines the cold boot primary core entry point used by
- SPMD (currently matches ``BL32_BASE``) to enter the SPMC.
-
-Other nodes in the manifest are consumed by Hafnium in the secure world.
-A sample can be found at `[7]`_:
-
-- The *hypervisor* node describes SPs. *is_ffa_partition* boolean attribute
- indicates a FF-A compliant SP. The *load_address* field specifies the load
- address at which BL2 loaded the SP package.
-- *cpus* node provide the platform topology and allows MPIDR to VMPIDR mapping.
- Note the primary core is declared first, then secondary cores are declared
- in reverse order.
-- The *memory* nodes provide platform information on the ranges of memory
- available for use by SPs at runtime. These ranges relate to either
- secure or non-secure memory, depending on the *device_type* field.
- If the field specifies "memory" the range is secure, else if it specifies
- "ns-memory" the memory is non-secure. The system integrator must exclude
- the memory used by other components that are not SPs, such as the monitor,
- or the SPMC itself, the OS Kernel/Hypervisor, or other NWd VMs. The SPMC
- limits the SP's address space such that they do not access memory outside
- of those ranges.
+The boot process involving SPMC is highly dependent on the SPMC implementation.
+It is recommended to refer to corresponding SPMC documentation for further
+details. Some aspects of boot process are described here in the greater interest
+of the project.
SPMC boot
-~~~~~~~~~
+---------
-The SPMC is loaded by BL2 as the BL32 image.
+When SPMC resides at a lower EL i.e., S-EL1 or S-EL2, it is loaded by BL2 as the
+BL32 image. The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[7]`_.
-The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[9]`_.
-
-BL2 passes the SPMC manifest address to BL31 through a register.
-
-At boot time, the SPMD in BL31 runs from the primary core, initializes the core
-contexts and launches the SPMC (BL32) passing the following information through
-registers:
+BL2 passes the SPMC manifest address to BL31 through a register. At boot time,
+the SPMD in BL31 runs from the primary core, initializes the core contexts and
+launches the SPMC (BL32) passing the following information through registers:
- X0 holds the ``TOS_FW_CONFIG`` physical address (or SPMC manifest blob).
- X1 holds the ``HW_CONFIG`` physical address.
- X4 holds the currently running core linear id.
-Loading of SPs
-~~~~~~~~~~~~~~
-
-At boot time, BL2 loads SPs sequentially in addition to the SPMC as depicted
-below:
-
-.. uml:: ../resources/diagrams/plantuml/bl2-loading-sp.puml
-
-Note this boot flow is an implementation sample on Arm's FVP platform.
-Platforms not using TF-A's *Firmware CONFiguration* framework would adjust to a
-different boot flow. The flow restricts to a maximum of 8 secure partitions.
-
-Secure boot
-~~~~~~~~~~~
-
-The SP content certificate is inserted as a separate FIP item so that BL2 loads SPMC,
-SPMC manifest, secure partitions and verifies them for authenticity and integrity.
-Refer to TBBR specification `[3]`_.
-
-The multiple-signing domain feature (in current state dual signing domain `[8]`_) allows
-the use of two root keys namely S-ROTPK and NS-ROTPK:
-
-- SPMC (BL32) and SPMC manifest are signed by the SiP using the S-ROTPK.
-- BL33 may be signed by the OEM using NS-ROTPK.
-- An SP may be signed either by SiP (using S-ROTPK) or by OEM (using NS-ROTPK).
-- A maximum of 4 partitions can be signed with the S-ROTPK key and 4 partitions
- signed with the NS-ROTPK key.
-
-Also refer to `Describing secure partitions`_ and `TF-A build options`_ sections.
-
-Hafnium in the secure world
-===========================
-
-General considerations
-----------------------
-
-Build platform for the secure world
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In the Hafnium reference implementation specific code parts are only relevant to
-the secure world. Such portions are isolated in architecture specific files
-and/or enclosed by a ``SECURE_WORLD`` macro.
-
-Secure partitions scheduling
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The FF-A specification `[1]`_ provides two ways to relinquinsh CPU time to
-secure partitions. For this a VM (Hypervisor or OS kernel), or SP invokes one of:
-
-- the FFA_MSG_SEND_DIRECT_REQ interface.
-- the FFA_RUN interface.
-
-Additionally a secure interrupt can pre-empt the normal world execution and give
-CPU cycles by transitioning to EL3 and S-EL2.
-
-Platform topology
-~~~~~~~~~~~~~~~~~
-
-The *execution-ctx-count* SP manifest field can take the value of one or the
-total number of PEs. The FF-A specification `[1]`_ recommends the
-following SP types:
-
-- Pinned MP SPs: an execution context matches a physical PE. MP SPs must
- implement the same number of ECs as the number of PEs in the platform.
-- Migratable UP SPs: a single execution context can run and be migrated on any
- physical PE. Such SP declares a single EC in its SP manifest. An UP SP can
- receive a direct message request originating from any physical core targeting
- the single execution context.
-
-Parsing SP partition manifests
-------------------------------
-
-Hafnium consumes SP manifests as defined in `[1]`_ and `SP manifests`_.
-Note the current implementation may not implement all optional fields.
-
-The SP manifest may contain memory and device regions nodes. In case of
-an S-EL2 SPMC:
-
-- Memory regions are mapped in the SP EL1&0 Stage-2 translation regime at
- load time (or EL1&0 Stage-1 for an S-EL1 SPMC). A memory region node can
- specify RX/TX buffer regions in which case it is not necessary for an SP
- to explicitly invoke the ``FFA_RXTX_MAP`` interface. The memory referred
- shall be contained within the memory ranges defined in SPMC manifest. The
- NS bit in the attributes field should be consistent with the security
- state of the range that it relates to. I.e. non-secure memory shall be
- part of a non-secure memory range, and secure memory shall be contained
- in a secure memory range of a given platform.
-- Device regions are mapped in the SP EL1&0 Stage-2 translation regime (or
- EL1&0 Stage-1 for an S-EL1 SPMC) as peripherals and possibly allocate
- additional resources (e.g. interrupts).
-
-For the S-EL2 SPMC, base addresses for memory and device region nodes are IPAs
-provided the SPMC identity maps IPAs to PAs within SP EL1&0 Stage-2 translation
-regime.
-
-Note: in the current implementation both VTTBR_EL2 and VSTTBR_EL2 point to the
-same set of page tables. It is still open whether two sets of page tables shall
-be provided per SP. The memory region node as defined in the specification
-provides a memory security attribute hinting to map either to the secure or
-non-secure EL1&0 Stage-2 table if it exists.
-
-Passing boot data to the SP
----------------------------
-
-In `[1]`_ , the section "Boot information protocol" defines a method for passing
-data to the SPs at boot time. It specifies the format for the boot information
-descriptor and boot information header structures, which describe the data to be
-exchanged between SPMC and SP.
-The specification also defines the types of data that can be passed.
-The aggregate of both the boot info structures and the data itself is designated
-the boot information blob, and is passed to a Partition as a contiguous memory
-region.
-
-Currently, the SPM implementation supports the FDT type which is used to pass the
-partition's DTB manifest.
-
-The region for the boot information blob is allocated through the SP package.
-
-.. image:: ../resources/diagrams/partition-package.png
-
-To adjust the space allocated for the boot information blob, the json description
-of the SP (see section `Describing secure partitions`_) shall be updated to contain
-the manifest offset. If no offset is provided the manifest offset defaults to 0x1000,
-which is the page size in the Hafnium SPMC.
-
-The configuration of the boot protocol is done in the SPs manifest. As defined by
-the specification, the manifest field 'gp-register-num' configures the GP register
-which shall be used to pass the address to the partitions boot information blob when
-booting the partition.
-In addition, the Hafnium SPMC implementation requires the boot information arguments
-to be listed in a designated DT node:
-
-.. code:: shell
-
- boot-info {
- compatible = "arm,ffa-manifest-boot-info";
- ffa_manifest;
- };
-
-The whole secure partition package image (see `Secure Partition packages`_) is
-mapped to the SP secure EL1&0 Stage-2 translation regime. As such, the SP can
-retrieve the address for the boot information blob in the designated GP register,
-process the boot information header and descriptors, access its own manifest
-DTB blob and extract its partition manifest properties.
-
-SP Boot order
--------------
-
-SP manifests provide an optional boot order attribute meant to resolve
-dependencies such as an SP providing a service required to properly boot
-another SP. SPMC boots the SPs in accordance to the boot order attribute,
-lowest to the highest value. If the boot order attribute is absent from the FF-A
-manifest, the SP is treated as if it had the highest boot order value
-(i.e. lowest booting priority).
-
-It is possible for an SP to call into another SP through a direct request
-provided the latter SP has already been booted.
-
-Boot phases
------------
-
-Primary core boot-up
-~~~~~~~~~~~~~~~~~~~~
-
-Upon boot-up, BL31 hands over to the SPMC (BL32) on the primary boot physical
-core. The SPMC performs its platform initializations and registers the SPMC
-secondary physical core entry point physical address by the use of the
-`FFA_SECONDARY_EP_REGISTER`_ interface (SMC invocation from the SPMC to the SPMD
-at secure physical FF-A instance).
-
-The SPMC then creates secure partitions based on SP packages and manifests. Each
-secure partition is launched in sequence (`SP Boot order`_) on their "primary"
-execution context. If the primary boot physical core linear id is N, an MP SP is
-started using EC[N] on PE[N] (see `Platform topology`_). If the partition is a
-UP SP, it is started using its unique EC0 on PE[N].
-
-The SP primary EC (or the EC used when the partition is booted as described
-above):
-
-- Performs the overall SP boot time initialization, and in case of a MP SP,
- prepares the SP environment for other execution contexts.
-- In the case of a MP SP, it invokes the FFA_SECONDARY_EP_REGISTER at secure
- virtual FF-A instance (SMC invocation from SP to SPMC) to provide the IPA
- entry point for other execution contexts.
-- Exits through ``FFA_MSG_WAIT`` to indicate successful initialization or
- ``FFA_ERROR`` in case of failure.
-
-Secondary cores boot-up
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Once the system is started and NWd brought up, a secondary physical core is
-woken up by the ``PSCI_CPU_ON`` service invocation. The TF-A SPD hook mechanism
-calls into the SPMD on the newly woken up physical core. Then the SPMC is
-entered at the secondary physical core entry point.
-
-In the current implementation, the first SP is resumed on the coresponding EC
-(the virtual CPU which matches the physical core). The implication is that the
-first SP must be a MP SP.
-
-In a linux based system, once secure and normal worlds are booted but prior to
-a NWd FF-A driver has been loaded:
-
-- The first SP has initialized all its ECs in response to primary core boot up
- (at system initialization) and secondary core boot up (as a result of linux
- invoking PSCI_CPU_ON for all secondary cores).
-- Other SPs have their first execution context initialized as a result of secure
- world initialization on the primary boot core. Other ECs for those SPs have to
- be run first through ffa_run to complete their initialization (which results
- in the EC completing with FFA_MSG_WAIT).
-
-Refer to `Power management`_ for further details.
-
-Notifications
--------------
-
-The FF-A v1.1 specification `[1]`_ defines notifications as an asynchronous
-communication mechanism with non-blocking semantics. It allows for one FF-A
-endpoint to signal another for service provision, without hindering its current
-progress.
-
-Hafnium currently supports 64 notifications. The IDs of each notification define
-a position in a 64-bit bitmap.
-
-The signaling of notifications can interchangeably happen between NWd and SWd
-FF-A endpoints.
-
-The SPMC is in charge of managing notifications from SPs to SPs, from SPs to
-VMs, and from VMs to SPs. An hypervisor component would only manage
-notifications from VMs to VMs. Given the SPMC has no visibility of the endpoints
-deployed in NWd, the Hypervisor or OS kernel must invoke the interface
-FFA_NOTIFICATION_BITMAP_CREATE to allocate the notifications bitmap per FF-A
-endpoint in the NWd that supports it.
-
-A sender can signal notifications once the receiver has provided it with
-permissions. Permissions are provided by invoking the interface
-FFA_NOTIFICATION_BIND.
-
-Notifications are signaled by invoking FFA_NOTIFICATION_SET. Henceforth
-they are considered to be in a pending sate. The receiver can retrieve its
-pending notifications invoking FFA_NOTIFICATION_GET, which, from that moment,
-are considered to be handled.
-
-Per the FF-A v1.1 spec, each FF-A endpoint must be associated with a scheduler
-that is in charge of donating CPU cycles for notifications handling. The
-FF-A driver calls FFA_NOTIFICATION_INFO_GET to retrieve the information about
-which FF-A endpoints have pending notifications. The receiver scheduler is
-called and informed by the FF-A driver, and it should allocate CPU cycles to the
-receiver.
-
-There are two types of notifications supported:
-
-- Global, which are targeted to a FF-A endpoint and can be handled within any of
- its execution contexts, as determined by the scheduler of the system.
-- Per-vCPU, which are targeted to a FF-A endpoint and to be handled within a
- a specific execution context, as determined by the sender.
-
-The type of a notification is set when invoking FFA_NOTIFICATION_BIND to give
-permissions to the sender.
-
-Notification signaling resorts to two interrupts:
-
-- Schedule Receiver Interrupt: non-secure physical interrupt to be handled by
- the FF-A driver within the receiver scheduler. At initialization the SPMC
- donates a SGI ID chosen from the secure SGI IDs range and configures it as
- non-secure. The SPMC triggers this SGI on the currently running core when
- there are pending notifications, and the respective receivers need CPU cycles
- to handle them.
-- Notifications Pending Interrupt: virtual interrupt to be handled by the
- receiver of the notification. Set when there are pending notifications for the
- given secure partition. The NPI is pended when the NWd relinquishes CPU cycles
- to an SP.
-
-The notifications receipt support is enabled in the partition FF-A manifest.
-
-Mandatory interfaces
---------------------
-
-The following interfaces are exposed to SPs:
-
-- ``FFA_VERSION``
-- ``FFA_FEATURES``
-- ``FFA_RX_RELEASE``
-- ``FFA_RXTX_MAP``
-- ``FFA_RXTX_UNMAP``
-- ``FFA_PARTITION_INFO_GET``
-- ``FFA_ID_GET``
-- ``FFA_MSG_WAIT``
-- ``FFA_MSG_SEND_DIRECT_REQ``
-- ``FFA_MSG_SEND_DIRECT_RESP``
-- ``FFA_MEM_DONATE``
-- ``FFA_MEM_LEND``
-- ``FFA_MEM_SHARE``
-- ``FFA_MEM_RETRIEVE_REQ``
-- ``FFA_MEM_RETRIEVE_RESP``
-- ``FFA_MEM_RELINQUISH``
-- ``FFA_MEM_FRAG_RX``
-- ``FFA_MEM_FRAG_TX``
-- ``FFA_MEM_RECLAIM``
-- ``FFA_RUN``
-
-As part of the FF-A v1.1 support, the following interfaces were added:
-
- - ``FFA_NOTIFICATION_BITMAP_CREATE``
- - ``FFA_NOTIFICATION_BITMAP_DESTROY``
- - ``FFA_NOTIFICATION_BIND``
- - ``FFA_NOTIFICATION_UNBIND``
- - ``FFA_NOTIFICATION_SET``
- - ``FFA_NOTIFICATION_GET``
- - ``FFA_NOTIFICATION_INFO_GET``
- - ``FFA_SPM_ID_GET``
- - ``FFA_SECONDARY_EP_REGISTER``
- - ``FFA_MEM_PERM_GET``
- - ``FFA_MEM_PERM_SET``
- - ``FFA_MSG_SEND2``
- - ``FFA_RX_ACQUIRE``
-
-FFA_VERSION
-~~~~~~~~~~~
-
-``FFA_VERSION`` requires a *requested_version* parameter from the caller.
-The returned value depends on the caller:
-
-- Hypervisor or OS kernel in NS-EL1/EL2: the SPMD returns the SPMC version
- specified in the SPMC manifest.
-- SP: the SPMC returns its own implemented version.
-- SPMC at S-EL1/S-EL2: the SPMD returns its own implemented version.
-
-FFA_FEATURES
-~~~~~~~~~~~~
-
-FF-A features supported by the SPMC may be discovered by secure partitions at
-boot (that is prior to NWd is booted) or run-time.
-
-The SPMC calling FFA_FEATURES at secure physical FF-A instance always get
-FFA_SUCCESS from the SPMD.
-
-The request made by an Hypervisor or OS kernel is forwarded to the SPMC and
-the response relayed back to the NWd.
-
-FFA_RXTX_MAP/FFA_RXTX_UNMAP
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When invoked from a secure partition FFA_RXTX_MAP maps the provided send and
-receive buffers described by their IPAs to the SP EL1&0 Stage-2 translation
-regime as secure buffers in the MMU descriptors.
-
-When invoked from the Hypervisor or OS kernel, the buffers are mapped into the
-SPMC EL2 Stage-1 translation regime and marked as NS buffers in the MMU
-descriptors. The provided addresses may be owned by a VM in the normal world,
-which is expected to receive messages from the secure world. The SPMC will in
-this case allocate internal state structures to facilitate RX buffer access
-synchronization (through FFA_RX_ACQUIRE interface), and to permit SPs to send
-messages.
-
-The FFA_RXTX_UNMAP unmaps the RX/TX pair from the translation regime of the
-caller, either it being the Hypervisor or OS kernel, as well as a secure
-partition.
-
-FFA_PARTITION_INFO_GET
-~~~~~~~~~~~~~~~~~~~~~~
-
-Partition info get call can originate:
-
-- from SP to SPMC
-- from Hypervisor or OS kernel to SPMC. The request is relayed by the SPMD.
-
-FFA_ID_GET
-~~~~~~~~~~
-
-The FF-A id space is split into a non-secure space and secure space:
-
-- FF-A ID with bit 15 clear relates to VMs.
-- FF-A ID with bit 15 set related to SPs.
-- FF-A IDs 0, 0xffff, 0x8000 are assigned respectively to the Hypervisor, SPMD
- and SPMC.
-
-The SPMD returns:
-
-- The default zero value on invocation from the Hypervisor.
-- The ``spmc_id`` value specified in the SPMC manifest on invocation from
- the SPMC (see `SPMC manifest`_)
-
-This convention helps the SPMC to determine the origin and destination worlds in
-an FF-A ABI invocation. In particular the SPMC shall filter unauthorized
-transactions in its world switch routine. It must not be permitted for a VM to
-use a secure FF-A ID as origin world by spoofing:
-
-- A VM-to-SP direct request/response shall set the origin world to be non-secure
- (FF-A ID bit 15 clear) and destination world to be secure (FF-A ID bit 15
- set).
-- Similarly, an SP-to-SP direct request/response shall set the FF-A ID bit 15
- for both origin and destination IDs.
-
-An incoming direct message request arriving at SPMD from NWd is forwarded to
-SPMC without a specific check. The SPMC is resumed through eret and "knows" the
-message is coming from normal world in this specific code path. Thus the origin
-endpoint ID must be checked by SPMC for being a normal world ID.
-
-An SP sending a direct message request must have bit 15 set in its origin
-endpoint ID and this can be checked by the SPMC when the SP invokes the ABI.
-
-The SPMC shall reject the direct message if the claimed world in origin endpoint
-ID is not consistent:
-
-- It is either forwarded by SPMD and thus origin endpoint ID must be a "normal
- world ID",
-- or initiated by an SP and thus origin endpoint ID must be a "secure world ID".
-
-
-FFA_MSG_SEND_DIRECT_REQ/FFA_MSG_SEND_DIRECT_RESP
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This is a mandatory interface for secure partitions consisting in direct request
-and responses with the following rules:
-
-- An SP can send a direct request to another SP.
-- An SP can receive a direct request from another SP.
-- An SP can send a direct response to another SP.
-- An SP cannot send a direct request to an Hypervisor or OS kernel.
-- An Hypervisor or OS kernel can send a direct request to an SP.
-- An SP can send a direct response to an Hypervisor or OS kernel.
-
-FFA_NOTIFICATION_BITMAP_CREATE/FFA_NOTIFICATION_BITMAP_DESTROY
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The secure partitions notifications bitmap are statically allocated by the SPMC.
-Hence, this interface is not to be issued by secure partitions.
-
-At initialization, the SPMC is not aware of VMs/partitions deployed in the
-normal world. Hence, the Hypervisor or OS kernel must use both ABIs for SPMC
-to be prepared to handle notifications for the provided VM ID.
-
-FFA_NOTIFICATION_BIND/FFA_NOTIFICATION_UNBIND
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Pair of interfaces to manage permissions to signal notifications. Prior to
-handling notifications, an FF-A endpoint must allow a given sender to signal a
-bitmap of notifications.
-
-If the receiver doesn't have notification support enabled in its FF-A manifest,
-it won't be able to bind notifications, hence forbidding it to receive any
-notifications.
-
-FFA_NOTIFICATION_SET/FFA_NOTIFICATION_GET
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-FFA_NOTIFICATION_GET retrieves all pending global notifications and
-per-vCPU notifications targeted to the current vCPU.
-
-Hafnium maintains a global count of pending notifications which gets incremented
-and decremented when handling FFA_NOTIFICATION_SET and FFA_NOTIFICATION_GET
-respectively. A delayed SRI is triggered if the counter is non-zero when the
-SPMC returns to normal world.
-
-FFA_NOTIFICATION_INFO_GET
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Hafnium maintains a global count of pending notifications whose information
-has been retrieved by this interface. The count is incremented and decremented
-when handling FFA_NOTIFICATION_INFO_GET and FFA_NOTIFICATION_GET respectively.
-It also tracks notifications whose information has been retrieved individually,
-such that it avoids duplicating returned information for subsequent calls to
-FFA_NOTIFICATION_INFO_GET. For each notification, this state information is
-reset when receiver called FFA_NOTIFICATION_GET to retrieve them.
-
-FFA_SPM_ID_GET
-~~~~~~~~~~~~~~
-
-Returns the FF-A ID allocated to an SPM component which can be one of SPMD
-or SPMC.
-
-At initialization, the SPMC queries the SPMD for the SPMC ID, using the
-FFA_ID_GET interface, and records it. The SPMC can also query the SPMD ID using
-the FFA_SPM_ID_GET interface at the secure physical FF-A instance.
-
-Secure partitions call this interface at the virtual FF-A instance, to which
-the SPMC returns the priorly retrieved SPMC ID.
-
-The Hypervisor or OS kernel can issue the FFA_SPM_ID_GET call handled by the
-SPMD, which returns the SPMC ID.
-
-FFA_SECONDARY_EP_REGISTER
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When the SPMC boots, all secure partitions are initialized on their primary
-Execution Context.
-
-The FFA_SECONDARY_EP_REGISTER interface is to be used by a secure partition
-from its first execution context, to provide the entry point address for
-secondary execution contexts.
-
-A secondary EC is first resumed either upon invocation of PSCI_CPU_ON from
-the NWd or by invocation of FFA_RUN.
-
-FFA_RX_ACQUIRE/FFA_RX_RELEASE
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The RX buffers can be used to pass information to an FF-A endpoint in the
-following scenarios:
-
- - When it was targetted by a FFA_MSG_SEND2 invokation from another endpoint.
- - Return the result of calling ``FFA_PARTITION_INFO_GET``.
- - In a memory share operation, as part of the ``FFA_MEM_RETRIEVE_RESP``,
- with the memory descriptor of the shared memory.
-
-If a normal world VM is expected to exchange messages with secure world,
-its RX/TX buffer addresses are forwarded to the SPMC via FFA_RXTX_MAP ABI,
-and are from this moment owned by the SPMC.
-The hypervisor must call the FFA_RX_ACQUIRE interface before attempting
-to use the RX buffer, in any of the aforementioned scenarios. A successful
-call to FFA_RX_ACQUIRE transfers ownership of RX buffer to hypervisor, such
-that it can be safely used.
-
-The FFA_RX_RELEASE interface is used after the FF-A endpoint is done with
-processing the data received in its RX buffer. If the RX buffer has been
-acquired by the hypervisor, the FFA_RX_RELEASE call must be forwarded to
-the SPMC to reestablish SPMC's RX ownership.
-
-An attempt from an SP to send a message to a normal world VM whose RX buffer
-was acquired by the hypervisor fails with error code FFA_BUSY, to preserve
-the RX buffer integrity.
-The operation could then be conducted after FFA_RX_RELEASE.
-
-FFA_MSG_SEND2
-~~~~~~~~~~~~~
-
-Hafnium copies a message from the sender TX buffer into receiver's RX buffer.
-For messages from SPs to VMs, operation is only possible if the SPMC owns
-the receiver's RX buffer.
-
-Both receiver and sender need to enable support for indirect messaging,
-in their respective partition manifest. The discovery of support
-of such feature can be done via FFA_PARTITION_INFO_GET.
-
-On a successful message send, Hafnium pends an RX buffer full framework
-notification for the receiver, to inform it about a message in the RX buffer.
-
-The handling of framework notifications is similar to that of
-global notifications. Binding of these is not necessary, as these are
-reserved to be used by the hypervisor or SPMC.
-
-SPMC-SPMD direct requests/responses
------------------------------------
-
-Implementation-defined FF-A IDs are allocated to the SPMC and SPMD.
-Using those IDs in source/destination fields of a direct request/response
-permits SPMD to SPMC communication and either way.
-
-- SPMC to SPMD direct request/response uses SMC conduit.
-- SPMD to SPMC direct request/response uses ERET conduit.
-
-This is used in particular to convey power management messages.
-
-Memory Sharing
---------------
-
-Hafnium implements the following memory sharing interfaces:
-
- - ``FFA_MEM_SHARE`` - for shared access between lender and borrower.
- - ``FFA_MEM_LEND`` - borrower to obtain exclusive access, though lender
- retains ownership of the memory.
- - ``FFA_MEM_DONATE`` - lender permanently relinquishes ownership of memory
- to the borrower.
-
-The ``FFA_MEM_RETRIEVE_REQ`` interface is for the borrower to request the
-memory to be mapped into its address space: for S-EL1 partitions the SPM updates
-their stage 2 translation regime; for S-EL0 partitions the SPM updates their
-stage 1 translation regime. On a successful call, the SPMC responds back with
-``FFA_MEM_RETRIEVE_RESP``.
-
-The ``FFA_MEM_RELINQUISH`` interface is for when the borrower is done with using
-a memory region.
-
-The ``FFA_MEM_RECLAIM`` interface is for the owner of the memory to reestablish
-its ownership and exclusive access to the memory shared.
-
-The memory transaction descriptors are transmitted via RX/TX buffers. In
-situations where the size of the memory transaction descriptor exceeds the
-size of the RX/TX buffers, Hafnium provides support for fragmented transmission
-of the full transaction descriptor. The ``FFA_MEM_FRAG_RX`` and ``FFA_MEM_FRAG_TX``
-interfaces are for receiving and transmitting the next fragment, respectively.
-
-If lender and borrower(s) are SPs, all memory sharing operations are supported.
-
-Hafnium also supports memory sharing operations between the normal world and the
-secure world. If there is an SP involved, the SPMC allocates data to track the
-state of the operation.
-
-The SPMC is also the designated allocator for the memory handle. The hypervisor
-or OS kernel has the possibility to rely on the SPMC to maintain the state
-of the operation, thus saving memory.
-A lender SP can only donate NS memory to a borrower from the normal world.
-
-The SPMC supports the hypervisor retrieve request, as defined by the FF-A
-v1.1 EAC0 specification, in section 16.4.3. The intent is to aid with operations
-that the hypervisor must do for a VM retriever. For example, when handling
-an FFA_MEM_RECLAIM, if the hypervisor relies on SPMC to keep the state
-of the operation, the hypervisor retrieve request can be used to obtain
-that state information, do the necessary validations, and update stage 2
-memory translation.
-
-Hafnium also supports memory lend and share targetting multiple borrowers.
-This is the case for a lender SP to multiple SPs, and for a lender VM to
-multiple endpoints (from both secure world and normal world). If there is
-at least one borrower VM, the hypervisor is in charge of managing its
-stage 2 translation on a successful memory retrieve.
-The semantics of ``FFA_MEM_DONATE`` implies ownership transmission,
-which should target only one partition.
-
-The memory share interfaces are backwards compatible with memory transaction
-descriptors from FF-A v1.0. These get translated to FF-A v1.1 descriptors for
-Hafnium's internal processing of the operation. If the FF-A version of a
-borrower is v1.0, Hafnium provides FF-A v1.0 compliant memory transaction
-descriptors on memory retrieve response.
-
-PE MMU configuration
---------------------
-
-With secure virtualization enabled (``HCR_EL2.VM = 1``) and for S-EL1
-partitions, two IPA spaces (secure and non-secure) are output from the
-secure EL1&0 Stage-1 translation.
-The EL1&0 Stage-2 translation hardware is fed by:
-
-- A secure IPA when the SP EL1&0 Stage-1 MMU is disabled.
-- One of secure or non-secure IPA when the secure EL1&0 Stage-1 MMU is enabled.
-
-``VTCR_EL2`` and ``VSTCR_EL2`` provide configuration bits for controlling the
-NS/S IPA translations. The following controls are set up:
-``VSTCR_EL2.SW = 0`` , ``VSTCR_EL2.SA = 0``, ``VTCR_EL2.NSW = 0``,
-``VTCR_EL2.NSA = 1``:
-
-- Stage-2 translations for the NS IPA space access the NS PA space.
-- Stage-2 translation table walks for the NS IPA space are to the secure PA space.
-
-Secure and non-secure IPA regions (rooted to by ``VTTBR_EL2`` and ``VSTTBR_EL2``)
-use the same set of Stage-2 page tables within a SP.
-
-The ``VTCR_EL2/VSTCR_EL2/VTTBR_EL2/VSTTBR_EL2`` virtual address space
-configuration is made part of a vCPU context.
-
-For S-EL0 partitions with VHE enabled, a single secure EL2&0 Stage-1 translation
-regime is used for both Hafnium and the partition.
-
-Schedule modes and SP Call chains
----------------------------------
-
-An SP execution context is said to be in SPMC scheduled mode if CPU cycles are
-allocated to it by SPMC. Correspondingly, an SP execution context is said to be
-in Normal world scheduled mode if CPU cycles are allocated by the normal world.
-
-A call chain represents all SPs in a sequence of invocations of a direct message
-request. When execution on a PE is in the secure state, only a single call chain
-that runs in the Normal World scheduled mode can exist. FF-A v1.1 spec allows
-any number of call chains to run in the SPMC scheduled mode but the Hafnium
-SPMC restricts the number of call chains in SPMC scheduled mode to only one for
-keeping the implementation simple.
-
-Partition runtime models
-------------------------
-
-The runtime model of an endpoint describes the transitions permitted for an
-execution context between various states. These are the four partition runtime
-models supported (refer to `[1]`_ section 7):
-
- - RTM_FFA_RUN: runtime model presented to an execution context that is
- allocated CPU cycles through FFA_RUN interface.
- - RTM_FFA_DIR_REQ: runtime model presented to an execution context that is
- allocated CPU cycles through FFA_MSG_SEND_DIRECT_REQ interface.
- - RTM_SEC_INTERRUPT: runtime model presented to an execution context that is
- allocated CPU cycles by SPMC to handle a secure interrupt.
- - RTM_SP_INIT: runtime model presented to an execution context that is
- allocated CPU cycles by SPMC to initialize its state.
-
-If an endpoint execution context attempts to make an invalid transition or a
-valid transition that could lead to a loop in the call chain, SPMC denies the
-transition with the help of above runtime models.
-
-Interrupt management
---------------------
-
-GIC ownership
-~~~~~~~~~~~~~
-
-The SPMC owns the GIC configuration. Secure and non-secure interrupts are
-trapped at S-EL2. The SPMC manages interrupt resources and allocates interrupt
-IDs based on SP manifests. The SPMC acknowledges physical interrupts and injects
-virtual interrupts by setting the use of vIRQ/vFIQ bits before resuming a SP.
-
-Abbreviations:
-
- - NS-Int: A non-secure physical interrupt. It requires a switch to the normal
- world to be handled if it triggers while execution is in secure world.
- - Other S-Int: A secure physical interrupt targeted to an SP different from
- the one that is currently running.
- - Self S-Int: A secure physical interrupt targeted to the SP that is currently
- running.
-
-Non-secure interrupt handling
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This section documents the actions supported in SPMC in response to a non-secure
-interrupt as per the guidance provided by FF-A v1.1 EAC0 specification.
-An SP specifies one of the following actions in its partition manifest:
-
- - Non-secure interrupt is signaled.
- - Non-secure interrupt is signaled after a managed exit.
- - Non-secure interrupt is queued.
-
-An SP execution context in a call chain could specify a less permissive action
-than subsequent SP execution contexts in the same call chain. The less
-permissive action takes precedence over the more permissive actions specified
-by the subsequent execution contexts. Please refer to FF-A v1.1 EAC0 section
-8.3.1 for further explanation.
-
-Secure interrupt handling
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This section documents the support implemented for secure interrupt handling in
-SPMC as per the guidance provided by FF-A v1.1 EAC0 specification.
-The following assumptions are made about the system configuration:
-
- - In the current implementation, S-EL1 SPs are expected to use the para
- virtualized ABIs for interrupt management rather than accessing the virtual
- GIC interface.
- - Unless explicitly stated otherwise, this support is applicable only for
- S-EL1 SPs managed by SPMC.
- - Secure interrupts are configured as G1S or G0 interrupts.
- - All physical interrupts are routed to SPMC when running a secure partition
- execution context.
- - All endpoints with multiple execution contexts have their contexts pinned
- to corresponding CPUs. Hence, a secure virtual interrupt cannot be signaled
- to a target vCPU that is currently running or blocked on a different
- physical CPU.
-
-A physical secure interrupt could trigger while CPU is executing in normal world
-or secure world.
-The action of SPMC for a secure interrupt depends on: the state of the target
-execution context of the SP that is responsible for handling the interrupt;
-whether the interrupt triggered while execution was in normal world or secure
-world.
-
-Secure interrupt signaling mechanisms
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Signaling refers to the mechanisms used by SPMC to indicate to the SP execution
-context that it has a pending virtual interrupt and to further run the SP
-execution context, such that it can handle the virtual interrupt. SPMC uses
-either the FFA_INTERRUPT interface with ERET conduit or vIRQ signal for signaling
-to S-EL1 SPs. When normal world execution is preempted by a secure interrupt,
-the SPMD uses the FFA_INTERRUPT ABI with ERET conduit to signal interrupt to SPMC
-running in S-EL2.
-
-+-----------+---------+---------------+---------------------------------------+
-| SP State | Conduit | Interface and | Description |
-| | | parameters | |
-+-----------+---------+---------------+---------------------------------------+
-| WAITING | ERET, | FFA_INTERRUPT,| SPMC signals to SP the ID of pending |
-| | vIRQ | Interrupt ID | interrupt. It pends vIRQ signal and |
-| | | | resumes execution context of SP |
-| | | | through ERET. |
-+-----------+---------+---------------+---------------------------------------+
-| BLOCKED | ERET, | FFA_INTERRUPT | SPMC signals to SP that an interrupt |
-| | vIRQ | | is pending. It pends vIRQ signal and |
-| | | | resumes execution context of SP |
-| | | | through ERET. |
-+-----------+---------+---------------+---------------------------------------+
-| PREEMPTED | vIRQ | NA | SPMC pends the vIRQ signal but does |
-| | | | not resume execution context of SP. |
-+-----------+---------+---------------+---------------------------------------+
-| RUNNING | ERET, | NA | SPMC pends the vIRQ signal and resumes|
-| | vIRQ | | execution context of SP through ERET. |
-+-----------+---------+---------------+---------------------------------------+
-
-Secure interrupt completion mechanisms
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A SP signals secure interrupt handling completion to the SPMC through the
-following mechanisms:
-
- - ``FFA_MSG_WAIT`` ABI if it was in WAITING state.
- - ``FFA_RUN`` ABI if its was in BLOCKED state.
-
-This is a remnant of SPMC implementation based on the FF-A v1.0 specification.
-In the current implementation, S-EL1 SPs use the para-virtualized HVC interface
-implemented by SPMC to perform priority drop and interrupt deactivation (SPMC
-configures EOImode = 0, i.e. priority drop and deactivation are done together).
-The SPMC performs checks to deny the state transition upon invocation of
-either FFA_MSG_WAIT or FFA_RUN interface if the SP didn't perform the
-deactivation of the secure virtual interrupt.
-
-If the current SP execution context was preempted by a secure interrupt to be
-handled by execution context of target SP, SPMC resumes current SP after signal
-completion by target SP execution context.
-
-Actions for a secure interrupt triggered while execution is in normal world
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-+-------------------+----------+-----------------------------------------------+
-| State of target | Action | Description |
-| execution context | | |
-+-------------------+----------+-----------------------------------------------+
-| WAITING | Signaled | This starts a new call chain in SPMC scheduled|
-| | | mode. |
-+-------------------+----------+-----------------------------------------------+
-| PREEMPTED | Queued | The target execution must have been preempted |
-| | | by a non-secure interrupt. SPMC queues the |
-| | | secure virtual interrupt now. It is signaled |
-| | | when the target execution context next enters |
-| | | the RUNNING state. |
-+-------------------+----------+-----------------------------------------------+
-| BLOCKED, RUNNING | NA | The target execution context is blocked or |
-| | | running on a different CPU. This is not |
-| | | supported by current SPMC implementation and |
-| | | execution hits panic. |
-+-------------------+----------+-----------------------------------------------+
-
-If normal world execution was preempted by a secure interrupt, SPMC uses
-FFA_NORMAL_WORLD_RESUME ABI to indicate completion of secure interrupt handling
-and further returns execution to normal world.
-
-The following figure describes interrupt handling flow when a secure interrupt
-triggers while execution is in normal world:
-
-.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-nwd.png
-
-A brief description of the events:
-
- - 1) Secure interrupt triggers while normal world is running.
- - 2) FIQ gets trapped to EL3.
- - 3) SPMD signals secure interrupt to SPMC at S-EL2 using FFA_INTERRUPT ABI.
- - 4) SPMC identifies target vCPU of SP and injects virtual interrupt (pends
- vIRQ).
- - 5) Assuming SP1 vCPU is in WAITING state, SPMC signals virtual interrupt
- using FFA_INTERRUPT with interrupt id as an argument and resumes the SP1
- vCPU using ERET in SPMC scheduled mode.
- - 6) Execution traps to vIRQ handler in SP1 provided that the virtual
- interrupt is not masked i.e., PSTATE.I = 0
- - 7) SP1 queries for the pending virtual interrupt id using a paravirtualized
- HVC call. SPMC clears the pending virtual interrupt state management
- and returns the pending virtual interrupt id.
- - 8) SP1 services the virtual interrupt and invokes the paravirtualized
- de-activation HVC call. SPMC de-activates the physical interrupt,
- clears the fields tracking the secure interrupt and resumes SP1 vCPU.
- - 9) SP1 performs secure interrupt completion through FFA_MSG_WAIT ABI.
- - 10) SPMC returns control to EL3 using FFA_NORMAL_WORLD_RESUME.
- - 11) EL3 resumes normal world execution.
-
-Actions for a secure interrupt triggered while execution is in secure world
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-+-------------------+----------+------------------------------------------------+
-| State of target | Action | Description |
-| execution context | | |
-+-------------------+----------+------------------------------------------------+
-| WAITING | Signaled | This starts a new call chain in SPMC scheduled |
-| | | mode. |
-+-------------------+----------+------------------------------------------------+
-| PREEMPTED by Self | Signaled | The target execution context reenters the |
-| S-Int | | RUNNING state to handle the secure virtual |
-| | | interrupt. |
-+-------------------+----------+------------------------------------------------+
-| PREEMPTED by | Queued | SPMC queues the secure virtual interrupt now. |
-| NS-Int | | It is signaled when the target execution |
-| | | context next enters the RUNNING state. |
-+-------------------+----------+------------------------------------------------+
-| BLOCKED | Signaled | Both preempted and target execution contexts |
-| | | must have been part of the Normal world |
-| | | scheduled call chain. Refer scenario 1 of |
-| | | Table 8.4 in the FF-A v1.1 EAC0 spec. |
-+-------------------+----------+------------------------------------------------+
-| RUNNING | NA | The target execution context is running on a |
-| | | different CPU. This scenario is not supported |
-| | | by current SPMC implementation and execution |
-| | | hits panic. |
-+-------------------+----------+------------------------------------------------+
-
-The following figure describes interrupt handling flow when a secure interrupt
-triggers while execution is in secure world. We assume OS kernel sends a direct
-request message to SP1. Further, SP1 sends a direct request message to SP2. SP1
-enters BLOCKED state and SPMC resumes SP2.
-
-.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-swd.png
-
-A brief description of the events:
-
- - 1) Secure interrupt triggers while SP2 is running.
- - 2) SP2 gets preempted and execution traps to SPMC as IRQ.
- - 3) SPMC finds the target vCPU of secure partition responsible for handling
- this secure interrupt. In this scenario, it is SP1.
- - 4) SPMC pends vIRQ for SP1 and signals through FFA_INTERRUPT interface.
- SPMC further resumes SP1 through ERET conduit. Note that SP1 remains in
- Normal world schedule mode.
- - 6) Execution traps to vIRQ handler in SP1 provided that the virtual
- interrupt is not masked i.e., PSTATE.I = 0
- - 7) SP1 queries for the pending virtual interrupt id using a paravirtualized
- HVC call. SPMC clears the pending virtual interrupt state management
- and returns the pending virtual interrupt id.
- - 8) SP1 services the virtual interrupt and invokes the paravirtualized
- de-activation HVC call. SPMC de-activates the physical interrupt and
- clears the fields tracking the secure interrupt and resumes SP1 vCPU.
- - 9) Since SP1 direct request completed with FFA_INTERRUPT, it resumes the
- direct request to SP2 by invoking FFA_RUN.
- - 9) SPMC resumes the pre-empted vCPU of SP2.
-
-EL3 interrupt handling
-~~~~~~~~~~~~~~~~~~~~~~
-
-In GICv3 based systems, EL3 interrupts are configured as Group0 secure
-interrupts. Execution traps to SPMC when a Group0 interrupt triggers while an
-SP is running. Further, SPMC running at S-EL2 uses FFA_EL3_INTR_HANDLE ABI to
-request EL3 platform firmware to handle a pending Group0 interrupt.
-Similarly, SPMD registers a handler with interrupt management framework to
-delegate handling of Group0 interrupt to the platform if the interrupt triggers
-in normal world.
-
- - Platform hook
-
- - plat_spmd_handle_group0_interrupt
-
- SPMD provides platform hook to handle Group0 secure interrupts. In the
- current design, SPMD expects the platform not to delegate handling to the
- NWd (such as through SDEI) while processing Group0 interrupts.
-
-Power management
-----------------
-
-In platforms with or without secure virtualization:
-
-- The NWd owns the platform PM policy.
-- The Hypervisor or OS kernel is the component initiating PSCI service calls.
-- The EL3 PSCI library is in charge of the PM coordination and control
- (eventually writing to platform registers).
-- While coordinating PM events, the PSCI library calls backs into the Secure
- Payload Dispatcher for events the latter has statically registered to.
-
-When using the SPMD as a Secure Payload Dispatcher:
-
-- A power management event is relayed through the SPD hook to the SPMC.
-- In the current implementation only cpu on (svc_on_finish) and cpu off
- (svc_off) hooks are registered.
-- The behavior for the cpu on event is described in `Secondary cores boot-up`_.
- The SPMC is entered through its secondary physical core entry point.
-- The cpu off event occurs when the NWd calls PSCI_CPU_OFF. The PM event is
- signaled to the SPMC through a power management framework message.
- It consists in a SPMD-to-SPMC direct request/response (`SPMC-SPMD direct
- requests/responses`_) conveying the event details and SPMC response.
- The SPMD performs a synchronous entry into the SPMC. The SPMC is entered and
- updates its internal state to reflect the physical core is being turned off.
- In the current implementation no SP is resumed as a consequence. This behavior
- ensures a minimal support for CPU hotplug e.g. when initiated by the NWd linux
- userspace.
-
-Arm architecture extensions for security hardening
-==================================================
-
-Hafnium supports the following architecture extensions for security hardening:
-
-- Pointer authentication (FEAT_PAuth): the extension permits detection of forged
- pointers used by ROP type of attacks through the signing of the pointer
- value. Hafnium is built with the compiler branch protection option to permit
- generation of a pointer authentication code for return addresses (pointer
- authentication for instructions). The APIA key is used while Hafnium runs.
- A random key is generated at boot time and restored upon entry into Hafnium
- at run-time. APIA and other keys (APIB, APDA, APDB, APGA) are saved/restored
- in vCPU contexts permitting to enable pointer authentication in VMs/SPs.
-- Branch Target Identification (FEAT_BTI): the extension permits detection of
- unexpected indirect branches used by JOP type of attacks. Hafnium is built
- with the compiler branch protection option, inserting land pads at function
- prologues that are reached by indirect branch instructions (BR/BLR).
- Hafnium code pages are marked as guarded in the EL2 Stage-1 MMU descriptors
- such that an indirect branch must always target a landpad. A fault is
- triggered otherwise. VMs/SPs can (independently) mark their code pages as
- guarded in the EL1&0 Stage-1 translation regime.
-- Memory Tagging Extension (FEAT_MTE): the option permits detection of out of
- bound memory array accesses or re-use of an already freed memory region.
- Hafnium enables the compiler option permitting to leverage MTE stack tagging
- applied to core stacks. Core stacks are marked as normal tagged memory in the
- EL2 Stage-1 translation regime. A synchronous data abort is generated upon tag
- check failure on load/stores. A random seed is generated at boot time and
- restored upon entry into Hafnium. MTE system registers are saved/restored in
- vCPU contexts permitting MTE usage from VMs/SPs.
-
-SMMUv3 support in Hafnium
-=========================
-
-An SMMU is analogous to an MMU in a CPU. It performs address translations for
-Direct Memory Access (DMA) requests from system I/O devices.
-The responsibilities of an SMMU include:
-
-- Translation: Incoming DMA requests are translated from bus address space to
- system physical address space using translation tables compliant to
- Armv8/Armv7 VMSA descriptor format.
-- Protection: An I/O device can be prohibited from read, write access to a
- memory region or allowed.
-- Isolation: Traffic from each individial device can be independently managed.
- The devices are differentiated from each other using unique translation
- tables.
-
-The following diagram illustrates a typical SMMU IP integrated in a SoC with
-several I/O devices along with Interconnect and Memory system.
-
-.. image:: ../resources/diagrams/MMU-600.png
-
-SMMU has several versions including SMMUv1, SMMUv2 and SMMUv3. Hafnium provides
-support for SMMUv3 driver in both normal and secure world. A brief introduction
-of SMMUv3 functionality and the corresponding software support in Hafnium is
-provided here.
-
-SMMUv3 features
----------------
-
-- SMMUv3 provides Stage1, Stage2 translation as well as nested (Stage1 + Stage2)
- translation support. It can either bypass or abort incoming translations as
- well.
-- Traffic (memory transactions) from each upstream I/O peripheral device,
- referred to as Stream, can be independently managed using a combination of
- several memory based configuration structures. This allows the SMMUv3 to
- support a large number of streams with each stream assigned to a unique
- translation context.
-- Support for Armv8.1 VMSA where the SMMU shares the translation tables with
- a Processing Element. AArch32(LPAE) and AArch64 translation table format
- are supported by SMMUv3.
-- SMMUv3 offers non-secure stream support with secure stream support being
- optional. Logically, SMMUv3 behaves as if there is an indepdendent SMMU
- instance for secure and non-secure stream support.
-- It also supports sub-streams to differentiate traffic from a virtualized
- peripheral associated with a VM/SP.
-- Additionally, SMMUv3.2 provides support for PEs implementing Armv8.4-A
- extensions. Consequently, SPM depends on Secure EL2 support in SMMUv3.2
- for providing Secure Stage2 translation support to upstream peripheral
- devices.
-
-SMMUv3 Programming Interfaces
------------------------------
-
-SMMUv3 has three software interfaces that are used by the Hafnium driver to
-configure the behaviour of SMMUv3 and manage the streams.
-
-- Memory based data strutures that provide unique translation context for
- each stream.
-- Memory based circular buffers for command queue and event queue.
-- A large number of SMMU configuration registers that are memory mapped during
- boot time by Hafnium driver. Except a few registers, all configuration
- registers have independent secure and non-secure versions to configure the
- behaviour of SMMUv3 for translation of secure and non-secure streams
- respectively.
-
-Peripheral device manifest
---------------------------
-
-Currently, SMMUv3 driver in Hafnium only supports dependent peripheral devices.
-These devices are dependent on PE endpoint to initiate and receive memory
-management transactions on their behalf. The acccess to the MMIO regions of
-any such device is assigned to the endpoint during boot. Moreover, SMMUv3 driver
-uses the same stage 2 translations for the device as those used by partition
-manager on behalf of the PE endpoint. This ensures that the peripheral device
-has the same visibility of the physical address space as the endpoint. The
-device node of the corresponding partition manifest (refer to `[1]`_ section 3.2
-) must specify these additional properties for each peripheral device in the
-system :
-
-- smmu-id: This field helps to identify the SMMU instance that this device is
- upstream of.
-- stream-ids: List of stream IDs assigned to this device.
-
-.. code:: shell
-
- smmuv3-testengine {
- base-address = <0x00000000 0x2bfe0000>;
- pages-count = <32>;
- attributes = <0x3>;
- smmu-id = <0>;
- stream-ids = <0x0 0x1>;
- interrupts = <0x2 0x3>, <0x4 0x5>;
- exclusive-access;
- };
-
-SMMUv3 driver limitations
--------------------------
-
-The primary design goal for the Hafnium SMMU driver is to support secure
-streams.
-
-- Currently, the driver only supports Stage2 translations. No support for
- Stage1 or nested translations.
-- Supports only AArch64 translation format.
-- No support for features such as PCI Express (PASIDs, ATS, PRI), MSI, RAS,
- Fault handling, Performance Monitor Extensions, Event Handling, MPAM.
-- No support for independent peripheral devices.
-
-S-EL0 Partition support
-=======================
-The SPMC (Hafnium) has limited capability to run S-EL0 FF-A partitions using
-FEAT_VHE (mandatory with ARMv8.1 in non-secure state, and in secure world
-with ARMv8.4 and FEAT_SEL2).
-
-S-EL0 partitions are useful for simple partitions that don't require full
-Trusted OS functionality. It is also useful to reduce jitter and cycle
-stealing from normal world since they are more lightweight than VMs.
-
-S-EL0 partitions are presented, loaded and initialized the same as S-EL1 VMs by
-the SPMC. They are differentiated primarily by the 'exception-level' property
-and the 'execution-ctx-count' property in the SP manifest. They are host apps
-under the single EL2&0 Stage-1 translation regime controlled by the SPMC and
-call into the SPMC through SVCs as opposed to HVCs and SMCs. These partitions
-can use FF-A defined services (FFA_MEM_PERM_*) to update or change permissions
-for memory regions.
-
-S-EL0 partitions are required by the FF-A specification to be UP endpoints,
-capable of migrating, and the SPMC enforces this requirement. The SPMC allows
-a S-EL0 partition to accept a direct message from secure world and normal world,
-and generate direct responses to them.
-All S-EL0 partitions must use AArch64. AArch32 S-EL0 partitions are not supported.
-
-Memory sharing, indirect messaging, and notifications functionality with S-EL0
-partitions is supported.
-
-Interrupt handling is not supported with S-EL0 partitions and is work in
-progress.
References
==========
@@ -1641,8 +242,7 @@
.. _[3]:
-[3] `Trusted Boot Board Requirements
-Client <https://developer.arm.com/documentation/den0006/d/>`__
+[3] https://hafnium.readthedocs.io/en/latest/secure-partition-manager/secure-partition-manager.html#secure-partitions-layout-file
.. _[4]:
@@ -1650,23 +250,15 @@
.. _[5]:
-[5] https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+[5] https://hafnium.readthedocs.io/en/latest/secure-partition-manager/index.html
.. _[6]:
-[6] https://trustedfirmware-a.readthedocs.io/en/latest/components/ffa-manifest-binding.html
+[6] :ref:`EL3 Secure Partition Manager<EL3 Secure Partition Manager>`
.. _[7]:
-[7] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
-
-.. _[8]:
-
-[8] https://lists.trustedfirmware.org/archives/list/tf-a@lists.trustedfirmware.org/thread/CFQFGU6H2D5GZYMUYGTGUSXIU3OYZP6U/
-
-.. _[9]:
-
-[9] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot
+[7] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot
--------------
diff --git a/docs/plat/xilinx-versal-net.rst b/docs/plat/xilinx-versal-net.rst
index e9dd772..d22a46d 100644
--- a/docs/plat/xilinx-versal-net.rst
+++ b/docs/plat/xilinx-versal-net.rst
@@ -75,7 +75,7 @@
| 0xc2001000-0xc2001FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx IPI |
+---------------------------+-----------------------------------------------------------+
-PM SMC call ranges
+PM SMC call ranges for SiP SVC version 0.1
--------------------------------------------------------
+---------------------------+---------------------------------------------------------------------------+
@@ -84,6 +84,19 @@
| 0xc2000000-0xc2000FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+---------------------------+---------------------------------------------------------------------------+
+PM SMC call ranges for SiP SVC version 0.2
+--------------------------------------------------------
+
++---------------------------+---------------------------------------------------------------------------+
+| SMC Function Identifier | Service type |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000FFF | Fast SMC64 SiP Service call used for pass-through of AMD-Xilinx Platform |
+| | Management APIs to firmware |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000A00-0xc2000AFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+| | specific TF-A APIs |
++---------------------------+---------------------------------------------------------------------------+
+
SMC function IDs for SiP Service queries
----------------------------------------------
diff --git a/docs/plat/xilinx-versal.rst b/docs/plat/xilinx-versal.rst
index 072329a..7185d91 100644
--- a/docs/plat/xilinx-versal.rst
+++ b/docs/plat/xilinx-versal.rst
@@ -14,11 +14,6 @@
make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31
```
-To build ATF for different platform (supported are "silicon"(default) and "versal_virt")
-```bash
-make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal VERSAL_PLATFORM=versal_virt bl31
-```
-
To build bl32 TSP you have to rebuild bl31 too
```bash
make CROSS_COMPILE=aarch64-none-elf- PLAT=versal SPD=tspd RESET_TO_BL31=1 bl31 bl32
@@ -51,11 +46,6 @@
- `pl011`, `pl011_0`: ARM pl011 UART 0
- `pl011_1` : ARM pl011 UART 1
-* `VERSAL_PLATFORM`: Select the platform. Options:
- - `versal_virt` : Versal Virtual platform
- - `spp_itr6` : SPP ITR6
- - `emu_itr6` : EMU ITR6
-
* `CPU_PWRDWN_SGI`: Select the SGI for triggering CPU power down request to
secondary cores on receiving power down callback from
firmware. Options:
@@ -98,8 +88,8 @@
| 0xc2001000-0xc2001FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx IPI |
+---------------------------+-----------------------------------------------------------+
-PM SMC call ranges
-------------------
+PM SMC call ranges for SiP SVC version 0.1
+--------------------------------------------------------
+---------------------------+---------------------------------------------------------------------------+
| SMC Function Identifier | Service type |
@@ -107,6 +97,19 @@
| 0xc2000000-0xc2000FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+---------------------------+---------------------------------------------------------------------------+
+PM SMC call ranges for SiP SVC version 0.2
+--------------------------------------------------------
+
++---------------------------+---------------------------------------------------------------------------+
+| SMC Function Identifier | Service type |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000FFF | Fast SMC64 SiP Service call used for pass-through of AMD-Xilinx Platform |
+| | Management APIs to firmware |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000A00-0xc2000AFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+| | specific TF-A APIs |
++---------------------------+---------------------------------------------------------------------------+
+
SMC function IDs for SiP Service queries
----------------------------------------
diff --git a/drivers/arm/gic/v3/arm_gicv3_common.c b/drivers/arm/gic/v3/arm_gicv3_common.c
index 4489892..cc82ddb 100644
--- a/drivers/arm/gic/v3/arm_gicv3_common.c
+++ b/drivers/arm/gic/v3/arm_gicv3_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -28,10 +28,13 @@
void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num)
{
uintptr_t gicr_base = 0;
+ unsigned int typer_reg;
assert(gicv3_driver_data);
assert(gicv3_driver_data->rdistif_base_addrs);
+ assert(gicv3_driver_data->gicd_base != 0U);
+ typer_reg = gicd_read_typer(gicv3_driver_data->gicd_base);
/*
* The GICR_WAKER.Sleep bit should be set only when both
* GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on
@@ -60,9 +63,14 @@
*/
gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT);
- /* Wait until the GICR_WAKER.Quiescent bit is set */
- while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
- ;
+ /*
+ * If LPIs are supported, wait until the GICR_WAKER.Quiescent bit is
+ * set.
+ */
+ if ((typer_reg & TYPER_LPIS) != 0U) {
+ while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
+ ;
+ }
}
/*
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 8ea164c..2be19db 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -686,6 +686,8 @@
gicr_write_ctlr(gicr_base,
rdist_ctx->gicr_ctlr & ~(GICR_CTLR_EN_LPIS_BIT));
+ gicr_wait_for_pending_write(gicr_base);
+
/* Restore registers' content */
gicr_write_propbaser(gicr_base, rdist_ctx->gicr_propbaser);
gicr_write_pendbaser(gicr_base, rdist_ctx->gicr_pendbaser);
diff --git a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
index 7205232..d62eed7 100644
--- a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
+++ b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
@@ -9,6 +9,8 @@
#define FXOSC_BASE_ADDR (0x40050000UL)
#define ARMPLL_BASE_ADDR (0x40038000UL)
+#define ARM_DFS_BASE_ADDR (0x40054000UL)
+#define CGM0_BASE_ADDR (0x40030000UL)
#define CGM1_BASE_ADDR (0x40034000UL)
/* FXOSC */
@@ -83,4 +85,25 @@
#define MC_CGM_MUXn_CSS_SWIP BIT_32(16U)
#define MC_CGM_MUXn_CSS_SAFE_SW BIT_32(3U)
+/* DFS */
+#define DFS_PORTSR(DFS_ADDR) ((DFS_ADDR) + 0xCUL)
+#define DFS_PORTOLSR(DFS_ADDR) ((DFS_ADDR) + 0x10UL)
+#define DFS_PORTOLSR_LOL(N) (BIT_32(N) & GENMASK_32(5U, 0U))
+#define DFS_PORTRESET(DFS_ADDR) ((DFS_ADDR) + 0x14UL)
+#define DFS_PORTRESET_MASK GENMASK_32(5U, 0U)
+#define DFS_PORTRESET_SET(VAL) (((VAL) & DFS_PORTRESET_MASK))
+
+#define DFS_CTL(DFS_ADDR) ((DFS_ADDR) + 0x18UL)
+#define DFS_CTL_RESET BIT_32(1U)
+
+#define DFS_DVPORTn(DFS_ADDR, PORT) ((DFS_ADDR) + 0x1CUL + ((PORT) * 0x4UL))
+#define DFS_DVPORTn_MFI_MASK GENMASK_32(15U, 8U)
+#define DFS_DVPORTn_MFI_SHIFT 8U
+#define DFS_DVPORTn_MFN_MASK GENMASK_32(7U, 0U)
+#define DFS_DVPORTn_MFN_SHIFT 0U
+#define DFS_DVPORTn_MFI(MFI) (((MFI) & DFS_DVPORTn_MFI_MASK) >> DFS_DVPORTn_MFI_SHIFT)
+#define DFS_DVPORTn_MFN(MFN) (((MFN) & DFS_DVPORTn_MFN_MASK) >> DFS_DVPORTn_MFN_SHIFT)
+#define DFS_DVPORTn_MFI_SET(VAL) (((VAL) << DFS_DVPORTn_MFI_SHIFT) & DFS_DVPORTn_MFI_MASK)
+#define DFS_DVPORTn_MFN_SET(VAL) (((VAL) << DFS_DVPORTn_MFN_SHIFT) & DFS_DVPORTn_MFN_MASK)
+
#endif /* S32CC_CLK_REGS_H */
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
index 6f18dd3..e23d928 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
@@ -22,6 +22,8 @@
struct s32cc_clk_drv {
uintptr_t fxosc_base;
uintptr_t armpll_base;
+ uintptr_t armdfs_base;
+ uintptr_t cgm0_base;
uintptr_t cgm1_base;
};
@@ -40,6 +42,8 @@
static struct s32cc_clk_drv driver = {
.fxosc_base = FXOSC_BASE_ADDR,
.armpll_base = ARMPLL_BASE_ADDR,
+ .armdfs_base = ARM_DFS_BASE_ADDR,
+ .cgm0_base = CGM0_BASE_ADDR,
.cgm1_base = CGM1_BASE_ADDR,
};
@@ -87,6 +91,12 @@
case S32CC_ARM_PLL:
*base = drv->armpll_base;
break;
+ case S32CC_ARM_DFS:
+ *base = drv->armdfs_base;
+ break;
+ case S32CC_CGM0:
+ *base = drv->cgm0_base;
+ break;
case S32CC_CGM1:
*base = drv->cgm1_base;
break;
@@ -542,6 +552,9 @@
case S32CC_CGM1:
ret = enable_cgm_mux(mux, drv);
break;
+ case S32CC_CGM0:
+ ret = enable_cgm_mux(mux, drv);
+ break;
default:
ERROR("Unknown mux parent type: %d\n", mux->module);
ret = -EINVAL;
@@ -551,6 +564,199 @@
return ret;
}
+static int enable_dfs(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct s32cc_dfs *get_div_dfs(const struct s32cc_dfs_div *dfs_div)
+{
+ const struct s32cc_clk_obj *parent = dfs_div->parent;
+
+ if (parent->type != s32cc_dfs_t) {
+ ERROR("DFS DIV doesn't have a DFS as parent\n");
+ return NULL;
+ }
+
+ return s32cc_obj2dfs(parent);
+}
+
+static struct s32cc_pll *dfsdiv2pll(const struct s32cc_dfs_div *dfs_div)
+{
+ const struct s32cc_clk_obj *parent;
+ const struct s32cc_dfs *dfs;
+
+ dfs = get_div_dfs(dfs_div);
+ if (dfs == NULL) {
+ return NULL;
+ }
+
+ parent = dfs->parent;
+ if (parent->type != s32cc_pll_t) {
+ return NULL;
+ }
+
+ return s32cc_obj2pll(parent);
+}
+
+static int get_dfs_mfi_mfn(unsigned long dfs_freq, const struct s32cc_dfs_div *dfs_div,
+ uint32_t *mfi, uint32_t *mfn)
+{
+ uint64_t factor64, tmp64, ofreq;
+ uint32_t factor32;
+
+ unsigned long in = dfs_freq;
+ unsigned long out = dfs_div->freq;
+
+ /**
+ * factor = (IN / OUT) / 2
+ * MFI = integer(factor)
+ * MFN = (factor - MFI) * 36
+ */
+ factor64 = ((((uint64_t)in) * FP_PRECISION) / ((uint64_t)out)) / 2ULL;
+ tmp64 = factor64 / FP_PRECISION;
+ if (tmp64 > UINT32_MAX) {
+ return -EINVAL;
+ }
+
+ factor32 = (uint32_t)tmp64;
+ *mfi = factor32;
+
+ tmp64 = ((factor64 - ((uint64_t)*mfi * FP_PRECISION)) * 36UL) / FP_PRECISION;
+ if (tmp64 > UINT32_MAX) {
+ return -EINVAL;
+ }
+
+ *mfn = (uint32_t)tmp64;
+
+ /* div_freq = in / (2 * (*mfi + *mfn / 36.0)) */
+ factor64 = (((uint64_t)*mfn) * FP_PRECISION) / 36ULL;
+ factor64 += ((uint64_t)*mfi) * FP_PRECISION;
+ factor64 *= 2ULL;
+ ofreq = (((uint64_t)in) * FP_PRECISION) / factor64;
+
+ if (ofreq != dfs_div->freq) {
+ ERROR("Failed to find MFI and MFN settings for DFS DIV freq %lu\n",
+ dfs_div->freq);
+ ERROR("Nearest freq = %" PRIx64 "\n", ofreq);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int init_dfs_port(uintptr_t dfs_addr, uint32_t port,
+ uint32_t mfi, uint32_t mfn)
+{
+ uint32_t portsr, portolsr;
+ uint32_t mask, old_mfi, old_mfn;
+ uint32_t dvport;
+ bool init_dfs;
+
+ dvport = mmio_read_32(DFS_DVPORTn(dfs_addr, port));
+
+ old_mfi = DFS_DVPORTn_MFI(dvport);
+ old_mfn = DFS_DVPORTn_MFN(dvport);
+
+ portsr = mmio_read_32(DFS_PORTSR(dfs_addr));
+ portolsr = mmio_read_32(DFS_PORTOLSR(dfs_addr));
+
+ /* Skip configuration if it's not needed */
+ if (((portsr & BIT_32(port)) != 0U) &&
+ ((portolsr & BIT_32(port)) == 0U) &&
+ (mfi == old_mfi) && (mfn == old_mfn)) {
+ return 0;
+ }
+
+ init_dfs = (portsr == 0U);
+
+ if (init_dfs) {
+ mask = DFS_PORTRESET_MASK;
+ } else {
+ mask = DFS_PORTRESET_SET(BIT_32(port));
+ }
+
+ mmio_write_32(DFS_PORTOLSR(dfs_addr), mask);
+ mmio_write_32(DFS_PORTRESET(dfs_addr), mask);
+
+ while ((mmio_read_32(DFS_PORTSR(dfs_addr)) & mask) != 0U) {
+ }
+
+ if (init_dfs) {
+ mmio_write_32(DFS_CTL(dfs_addr), DFS_CTL_RESET);
+ }
+
+ mmio_write_32(DFS_DVPORTn(dfs_addr, port),
+ DFS_DVPORTn_MFI_SET(mfi) | DFS_DVPORTn_MFN_SET(mfn));
+
+ if (init_dfs) {
+ /* DFS clk enable programming */
+ mmio_clrbits_32(DFS_CTL(dfs_addr), DFS_CTL_RESET);
+ }
+
+ mmio_clrbits_32(DFS_PORTRESET(dfs_addr), BIT_32(port));
+
+ while ((mmio_read_32(DFS_PORTSR(dfs_addr)) & BIT_32(port)) != BIT_32(port)) {
+ }
+
+ portolsr = mmio_read_32(DFS_PORTOLSR(dfs_addr));
+ if ((portolsr & DFS_PORTOLSR_LOL(port)) != 0U) {
+ ERROR("Failed to lock DFS divider\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int enable_dfs_div(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_dfs_div *dfs_div = s32cc_obj2dfsdiv(module);
+ const struct s32cc_pll *pll;
+ const struct s32cc_dfs *dfs;
+ uintptr_t dfs_addr = 0UL;
+ uint32_t mfi, mfn;
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ dfs = get_div_dfs(dfs_div);
+ if (dfs == NULL) {
+ return -EINVAL;
+ }
+
+ pll = dfsdiv2pll(dfs_div);
+ if (pll == NULL) {
+ ERROR("Failed to identify DFS divider's parent\n");
+ return -EINVAL;
+ }
+
+ ret = get_base_addr(dfs->instance, drv, &dfs_addr);
+ if ((ret != 0) || (dfs_addr == 0UL)) {
+ return -EINVAL;
+ }
+
+ ret = get_dfs_mfi_mfn(pll->vco_freq, dfs_div, &mfi, &mfn);
+ if (ret != 0) {
+ return -EINVAL;
+ }
+
+ return init_dfs_port(dfs_addr, dfs_div->index, mfi, mfn);
+}
+
static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth)
{
const struct s32cc_clk_drv *drv = get_drv();
@@ -587,6 +793,12 @@
case s32cc_fixed_div_t:
ret = -ENOTSUP;
break;
+ case s32cc_dfs_t:
+ ret = enable_dfs(module, drv, depth);
+ break;
+ case s32cc_dfs_div_t:
+ ret = enable_dfs_div(module, drv, depth);
+ break;
default:
ret = -EINVAL;
break;
@@ -793,6 +1005,42 @@
return set_module_rate(&clk->desc, rate, orate, depth);
}
+static int set_dfs_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
+ unsigned long *orate, unsigned int *depth)
+{
+ struct s32cc_dfs_div *dfs_div = s32cc_obj2dfsdiv(module);
+ const struct s32cc_dfs *dfs;
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (dfs_div->parent == NULL) {
+ ERROR("Failed to identify DFS divider's parent\n");
+ return -EINVAL;
+ }
+
+ /* Sanity check */
+ dfs = s32cc_obj2dfs(dfs_div->parent);
+ if (dfs->parent == NULL) {
+ ERROR("Failed to identify DFS's parent\n");
+ return -EINVAL;
+ }
+
+ if ((dfs_div->freq != 0U) && (dfs_div->freq != rate)) {
+ ERROR("DFS DIV frequency was already set to %lu\n",
+ dfs_div->freq);
+ return -EINVAL;
+ }
+
+ dfs_div->freq = rate;
+ *orate = rate;
+
+ return ret;
+}
+
static int set_module_rate(const struct s32cc_clk_obj *module,
unsigned long rate, unsigned long *orate,
unsigned int *depth)
@@ -804,6 +1052,8 @@
return ret;
}
+ ret = -EINVAL;
+
switch (module->type) {
case s32cc_clk_t:
ret = set_clk_freq(module, rate, orate, depth);
@@ -826,8 +1076,13 @@
case s32cc_shared_clkmux_t:
ret = set_mux_freq(module, rate, orate, depth);
break;
+ case s32cc_dfs_t:
+ ERROR("Setting the frequency of a DFS is not allowed!");
+ break;
+ case s32cc_dfs_div_t:
+ ret = set_dfs_div_freq(module, rate, orate, depth);
+ break;
default:
- ret = -EINVAL;
break;
}
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
index 039db2a..c4c73c7 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
@@ -43,6 +43,45 @@
static struct s32cc_clk arm_pll_phi0_clk =
S32CC_FREQ_MODULE_CLK(arm_pll_phi0_div, 0, GHZ);
+/* ARM DFS */
+static struct s32cc_dfs armdfs =
+ S32CC_DFS_INIT(armpll, S32CC_ARM_DFS);
+static struct s32cc_dfs_div arm_dfs1_div =
+ S32CC_DFS_DIV_INIT(armdfs, 0);
+static struct s32cc_clk arm_dfs1_clk =
+ S32CC_FREQ_MODULE_CLK(arm_dfs1_div, 0, 800 * MHZ);
+
+/* MC_CGM0 */
+static struct s32cc_clkmux cgm0_mux0 =
+ S32CC_SHARED_CLKMUX_INIT(S32CC_CGM0, 0, 2,
+ S32CC_CLK_FIRC,
+ S32CC_CLK_ARM_PLL_DFS1, 0, 0, 0);
+static struct s32cc_clk cgm0_mux0_clk = S32CC_MODULE_CLK(cgm0_mux0);
+
+/* XBAR */
+static struct s32cc_clk xbar_2x_clk =
+ S32CC_CHILD_CLK(cgm0_mux0_clk, 48 * MHZ, 800 * MHZ);
+static struct s32cc_fixed_div xbar_div2 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 2);
+static struct s32cc_clk xbar_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div2, 24 * MHZ, 400 * MHZ);
+static struct s32cc_fixed_div xbar_div4 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 4);
+static struct s32cc_clk xbar_div2_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div4, 12 * MHZ, 200 * MHZ);
+static struct s32cc_fixed_div xbar_div6 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 6);
+static struct s32cc_clk xbar_div3_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div6, 8 * MHZ, 133333333);
+static struct s32cc_fixed_div xbar_div8 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 8);
+static struct s32cc_clk xbar_div4_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div8, 6 * MHZ, 100 * MHZ);
+static struct s32cc_fixed_div xbar_div12 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 12);
+static struct s32cc_clk xbar_div6_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div12, 4 * MHZ, 66666666);
+
/* MC_CGM1 */
static struct s32cc_clkmux cgm1_mux0 =
S32CC_SHARED_CLKMUX_INIT(S32CC_CGM1, 0, 3,
@@ -68,13 +107,15 @@
S32CC_FREQ_MODULE_CLK(a53_core_div10, S32CC_A53_MIN_FREQ / 10,
S32CC_A53_MAX_FREQ / 10);
-static struct s32cc_clk *s32cc_hw_clk_list[5] = {
+static struct s32cc_clk *s32cc_hw_clk_list[13] = {
/* Oscillators */
[S32CC_CLK_ID(S32CC_CLK_FIRC)] = &firc_clk,
[S32CC_CLK_ID(S32CC_CLK_SIRC)] = &sirc_clk,
[S32CC_CLK_ID(S32CC_CLK_FXOSC)] = &fxosc_clk,
/* ARM PLL */
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_PHI0)] = &arm_pll_phi0_clk,
+ /* ARM DFS */
+ [S32CC_CLK_ID(S32CC_CLK_ARM_PLL_DFS1)] = &arm_dfs1_clk,
};
static struct s32cc_clk_array s32cc_hw_clocks = {
@@ -83,10 +124,19 @@
.n_clks = ARRAY_SIZE(s32cc_hw_clk_list),
};
-static struct s32cc_clk *s32cc_arch_clk_list[6] = {
+static struct s32cc_clk *s32cc_arch_clk_list[13] = {
/* ARM PLL */
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_MUX)] = &arm_pll_mux_clk,
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_VCO)] = &arm_pll_vco_clk,
+ /* MC_CGM0 */
+ [S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX0)] = &cgm0_mux0_clk,
+ /* XBAR */
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_2X)] = &xbar_2x_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR)] = &xbar_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV2)] = &xbar_div2_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV3)] = &xbar_div3_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV4)] = &xbar_div4_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV6)] = &xbar_div6_clk,
/* MC_CGM1 */
[S32CC_CLK_ID(S32CC_CLK_MC_CGM1_MUX0)] = &cgm1_mux0_clk,
/* A53 */
diff --git a/drivers/nxp/clk/s32cc/s32cc_early_clks.c b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
index 560f8bc..2c256a5 100644
--- a/drivers/nxp/clk/s32cc/s32cc_early_clks.c
+++ b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
@@ -12,24 +12,30 @@
#define S32CC_ARM_PLL_VCO_FREQ (2U * GHZ)
#define S32CC_ARM_PLL_PHI0_FREQ (1U * GHZ)
#define S32CC_A53_FREQ (1U * GHZ)
+#define S32CC_XBAR_2X_FREQ (800U * MHZ)
-int s32cc_init_early_clks(void)
+static int enable_fxosc_clk(void)
{
int ret;
- s32cc_clk_register_drv();
-
- ret = clk_set_parent(S32CC_CLK_ARM_PLL_MUX, S32CC_CLK_FXOSC);
+ ret = clk_set_rate(S32CC_CLK_FXOSC, S32CC_FXOSC_FREQ, NULL);
if (ret != 0) {
return ret;
}
- ret = clk_set_parent(S32CC_CLK_MC_CGM1_MUX0, S32CC_CLK_ARM_PLL_PHI0);
+ ret = clk_enable(S32CC_CLK_FXOSC);
if (ret != 0) {
return ret;
}
- ret = clk_set_rate(S32CC_CLK_FXOSC, S32CC_FXOSC_FREQ, NULL);
+ return ret;
+}
+
+static int enable_arm_pll(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_ARM_PLL_MUX, S32CC_CLK_FXOSC);
if (ret != 0) {
return ret;
}
@@ -44,22 +50,29 @@
return ret;
}
- ret = clk_set_rate(S32CC_CLK_A53_CORE, S32CC_A53_FREQ, NULL);
+ ret = clk_enable(S32CC_CLK_ARM_PLL_VCO);
if (ret != 0) {
return ret;
}
- ret = clk_enable(S32CC_CLK_FXOSC);
+ ret = clk_enable(S32CC_CLK_ARM_PLL_PHI0);
if (ret != 0) {
return ret;
}
- ret = clk_enable(S32CC_CLK_ARM_PLL_VCO);
+ return ret;
+}
+
+static int enable_a53_clk(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_MC_CGM1_MUX0, S32CC_CLK_ARM_PLL_PHI0);
if (ret != 0) {
return ret;
}
- ret = clk_enable(S32CC_CLK_ARM_PLL_PHI0);
+ ret = clk_set_rate(S32CC_CLK_A53_CORE, S32CC_A53_FREQ, NULL);
if (ret != 0) {
return ret;
}
@@ -71,3 +84,59 @@
return ret;
}
+
+static int enable_xbar_clk(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_MC_CGM0_MUX0, S32CC_CLK_ARM_PLL_DFS1);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_set_rate(S32CC_CLK_XBAR_2X, S32CC_XBAR_2X_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_ARM_PLL_DFS1);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_XBAR_2X);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
+
+int s32cc_init_early_clks(void)
+{
+ int ret;
+
+ s32cc_clk_register_drv();
+
+ ret = enable_fxosc_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_arm_pll();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_a53_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_xbar_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index bfda31b..ca46eb1 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -150,6 +150,7 @@
/* GICD_TYPER shifts and masks */
#define TYPER_ESPI U(1 << 8)
#define TYPER_DVIS U(1 << 18)
+#define TYPER_LPIS U(1 << 17)
#define TYPER_ESPI_RANGE_MASK U(0x1f)
#define TYPER_ESPI_RANGE_SHIFT U(27)
#define TYPER_ESPI_RANGE U(TYPER_ESPI_MASK << TYPER_ESPI_SHIFT)
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
index 633f173..b95cd32 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
@@ -78,4 +78,13 @@
#define S32CC_CLK_A53_CORE_DIV2 S32CC_ARCH_CLK(4)
#define S32CC_CLK_A53_CORE_DIV10 S32CC_ARCH_CLK(5)
+/* XBAR clock*/
+#define S32CC_CLK_MC_CGM0_MUX0 S32CC_ARCH_CLK(6)
+#define S32CC_CLK_XBAR_2X S32CC_ARCH_CLK(7)
+#define S32CC_CLK_XBAR S32CC_ARCH_CLK(8)
+#define S32CC_CLK_XBAR_DIV2 S32CC_ARCH_CLK(9)
+#define S32CC_CLK_XBAR_DIV3 S32CC_ARCH_CLK(10)
+#define S32CC_CLK_XBAR_DIV4 S32CC_ARCH_CLK(11)
+#define S32CC_CLK_XBAR_DIV6 S32CC_ARCH_CLK(12)
+
#endif /* S32CC_CLK_IDS_H */
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
index 41fc6f4..703713b 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
@@ -17,6 +17,8 @@
s32cc_clk_t,
s32cc_pll_t,
s32cc_pll_out_div_t,
+ s32cc_dfs_t,
+ s32cc_dfs_div_t,
s32cc_clkmux_t,
s32cc_shared_clkmux_t,
s32cc_fixed_div_t,
@@ -27,6 +29,8 @@
S32CC_FXOSC,
S32CC_SIRC,
S32CC_ARM_PLL,
+ S32CC_ARM_DFS,
+ S32CC_CGM0,
S32CC_CGM1,
};
@@ -122,6 +126,38 @@
.index = (INDEX), \
}
+struct s32cc_dfs {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *parent;
+ enum s32cc_clk_source instance;
+ uintptr_t base;
+};
+
+#define S32CC_DFS_INIT(PARENT, INSTANCE) \
+{ \
+ .desc = { \
+ .type = s32cc_dfs_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .instance = (INSTANCE), \
+}
+
+struct s32cc_dfs_div {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *parent;
+ uint32_t index;
+ unsigned long freq;
+};
+
+#define S32CC_DFS_DIV_INIT(PARENT, INDEX) \
+{ \
+ .desc = { \
+ .type = s32cc_dfs_div_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .index = (INDEX), \
+}
+
struct s32cc_fixed_div {
struct s32cc_clk_obj desc;
struct s32cc_clk_obj *parent;
@@ -151,22 +187,26 @@
size_t n_clks;
};
-#define S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F) \
-{ \
- .desc = { \
- .type = s32cc_clk_t, \
- }, \
- .module = &(PARENT_MODULE).desc, \
- .min_freq = (MIN_F), \
- .max_freq = (MAX_F), \
+#define S32CC_FREQ_CLK(PARENT_MODULE, PARENT, MIN_F, MAX_F) \
+{ \
+ .desc = { \
+ .type = s32cc_clk_t, \
+ }, \
+ .pclock = (PARENT), \
+ .module = (PARENT_MODULE), \
+ .min_freq = (MIN_F), \
+ .max_freq = (MAX_F), \
}
#define S32CC_FREQ_MODULE_CLK(PARENT_MODULE, MIN_F, MAX_F) \
- S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F)
+ S32CC_FREQ_CLK(&(PARENT_MODULE).desc, NULL, MIN_F, MAX_F)
#define S32CC_MODULE_CLK(PARENT_MODULE) \
S32CC_FREQ_MODULE_CLK(PARENT_MODULE, 0, 0)
+#define S32CC_CHILD_CLK(PARENT, MIN_F, MAX_F) \
+ S32CC_FREQ_CLK(NULL, &(PARENT), MIN_F, MAX_F)
+
static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod)
{
uintptr_t osc_addr;
@@ -237,4 +277,20 @@
return (struct s32cc_fixed_div *)fdiv_addr;
}
+static inline struct s32cc_dfs *s32cc_obj2dfs(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t dfs_addr;
+
+ dfs_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs, desc);
+ return (struct s32cc_dfs *)dfs_addr;
+}
+
+static inline struct s32cc_dfs_div *s32cc_obj2dfsdiv(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t dfs_div_addr;
+
+ dfs_div_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs_div, desc);
+ return (struct s32cc_dfs_div *)dfs_div_addr;
+}
+
#endif /* S32CC_CLK_MODULES_H */
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 9f0b190..375cdba 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -182,9 +182,9 @@
}
my_idx = plat_my_core_pos();
-
- for (lvl = PSCI_CPU_PWR_LVL; lvl <= end_pwrlvl; lvl++) {
- parent_idx = psci_cpu_pd_nodes[my_idx].parent_node;
+ parent_idx = psci_cpu_pd_nodes[my_idx].parent_node;
+ for (lvl = PSCI_CPU_PWR_LVL + U(1); lvl < end_pwrlvl; lvl++) {
+ parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
}
cpu_start_idx = psci_non_cpu_pd_nodes[parent_idx].cpu_start_idx;
diff --git a/plat/amd/versal2/include/def.h b/plat/amd/versal2/include/def.h
index a8cbaaf..67244a4 100644
--- a/plat/amd/versal2/include/def.h
+++ b/plat/amd/versal2/include/def.h
@@ -125,6 +125,10 @@
#define APU_CLUSTER_STEP U(0x100000)
#define SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL U(0xF1060504)
+#define PMXC_IOU_SLCR_SRAM_CSR U(0xF106104C)
+#define PMXC_IOU_SLCR_PHY_RESET U(0xF1061050)
+#define PMXC_IOU_SLCR_TX_RX_CONFIG_RDY U(0xF1061054)
+#define PMXC_CRP_RST_UFS U(0xF1260340)
/*******************************************************************************
* IRQ constants
diff --git a/plat/amd/versal2/include/versal2-scmi.h b/plat/amd/versal2/include/versal2-scmi.h
index 4d581e4..c08b4b1 100644
--- a/plat/amd/versal2/include/versal2-scmi.h
+++ b/plat/amd/versal2/include/versal2-scmi.h
@@ -136,5 +136,9 @@
#define RESET_I3C6_0 32
#define RESET_I3C7_0 33
#define RESET_I3C8_0 34
+#define RESET_UFSPHY_0 35
+
+#define PD_USB0 0
+#define PD_USB1 1
#endif /* _VERSAL2_SCMI_H */
diff --git a/plat/amd/versal2/plat_psci.c b/plat/amd/versal2/plat_psci.c
index 4faa434..6f0cbcb 100644
--- a/plat/amd/versal2/plat_psci.c
+++ b/plat/amd/versal2/plat_psci.c
@@ -161,12 +161,29 @@
static int32_t no_pm_ioctl(uint32_t device_id, uint32_t ioctl_id,
uint32_t arg1, uint32_t arg2)
{
+ int32_t ret = 0;
VERBOSE("%s: ioctl_id: %x, arg1: %x\n", __func__, ioctl_id, arg1);
- if (ioctl_id == IOCTL_OSPI_MUX_SELECT) {
+
+ switch (ioctl_id) {
+ case IOCTL_OSPI_MUX_SELECT:
mmio_write_32(SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL, arg1);
- return 0;
+ break;
+ case IOCTL_UFS_TXRX_CFGRDY_GET:
+ ret = (int32_t) mmio_read_32(PMXC_IOU_SLCR_TX_RX_CONFIG_RDY);
+ break;
+ case IOCTL_UFS_SRAM_CSR_SEL:
+ if (arg1 == 1) {
+ ret = (int32_t) mmio_read_32(PMXC_IOU_SLCR_SRAM_CSR);
+ } else if (arg1 == 0) {
+ mmio_write_32(PMXC_IOU_SLCR_SRAM_CSR, arg2);
+ }
+ break;
+ default:
+ ret = PM_RET_ERROR_NOFEATURE;
+ break;
}
- return PM_RET_ERROR_NOFEATURE;
+
+ return ret;
}
static uint64_t no_pm_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
@@ -187,7 +204,13 @@
case PM_IOCTL:
{
ret = no_pm_ioctl(arg[0], arg[1], arg[2], arg[3]);
- SMC_RET1(handle, (uint64_t)ret);
+ /* Firmware driver expects return code in upper 32 bits and
+ * status in lower 32 bits.
+ * status is always SUCCESS(0) for mmio low level register
+ * r/w calls and return value is the value returned from
+ * no_pm_ioctl
+ */
+ SMC_RET1(handle, ((uint64_t)ret << 32));
}
case PM_GET_CHIPID:
{
diff --git a/plat/amd/versal2/scmi.c b/plat/amd/versal2/scmi.c
index c3c517a..7f4b6df 100644
--- a/plat/amd/versal2/scmi.c
+++ b/plat/amd/versal2/scmi.c
@@ -10,6 +10,7 @@
#include <drivers/scmi-msg.h>
#include <drivers/scmi.h>
+#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <platform_def.h>
#include <scmi.h>
@@ -179,14 +180,40 @@
RESET_CELL(RESET_I3C6_0, RESET_I3C6_0, "i3c6"),
RESET_CELL(RESET_I3C7_0, RESET_I3C7_0, "i3c7"),
RESET_CELL(RESET_I3C8_0, RESET_I3C8_0, "i3c8"),
+ RESET_CELL(RESET_UFSPHY_0, RESET_UFSPHY_0, "ufsphy0"),
};
+/**
+ * struct scmi_pd - Data for the exposed power domain controller
+ * @pd_id: pd identifier in RCC reset driver
+ * @name: pd string ID exposed to agent
+ * @state: keep state setting
+ */
+struct scmi_pd {
+ unsigned long pd_id;
+ const char *name;
+ unsigned int state;
+};
+
+#define PD_CELL(_scmi_id, _id, _name, _state) \
+ [_scmi_id] = { \
+ .pd_id = _id, \
+ .name = _name, \
+ .state = _state, \
+ }
+
+static struct scmi_pd scmi0_pd[] = {
+ PD_CELL(PD_USB0, PD_USB0, "usb0", 0),
+ PD_CELL(PD_USB1, PD_USB1, "usb1", 0),
+};
+
struct scmi_resources {
struct scmi_clk *clock;
size_t clock_count;
struct scmi_reset *reset;
size_t reset_count;
-
+ struct scmi_pd *pd;
+ size_t pd_count;
};
static const struct scmi_resources resources[] = {
@@ -195,6 +222,8 @@
.clock_count = ARRAY_SIZE(scmi0_clock),
.reset = scmi0_reset,
.reset_count = ARRAY_SIZE(scmi0_reset),
+ .pd = scmi0_pd,
+ .pd_count = ARRAY_SIZE(scmi0_pd),
},
};
@@ -433,14 +462,122 @@
if (assert_not_deassert) {
NOTICE("SCMI reset %lu/%s set\n",
reset->reset_id, plat_scmi_rstd_get_name(agent_id, scmi_id));
+
+ switch (scmi_id) {
+ case RESET_UFS0_0:
+ mmio_write_32(PMXC_CRP_RST_UFS, 1);
+ break;
+ case RESET_UFSPHY_0:
+ mmio_write_32(PMXC_IOU_SLCR_PHY_RESET, 1);
+ break;
+ default:
+ break;
+ }
} else {
NOTICE("SCMI reset %lu/%s release\n",
reset->reset_id, plat_scmi_rstd_get_name(agent_id, scmi_id));
+
+ switch (scmi_id) {
+ case RESET_UFS0_0:
+ mmio_write_32(PMXC_CRP_RST_UFS, 0);
+ break;
+ case RESET_UFSPHY_0:
+ mmio_write_32(PMXC_IOU_SLCR_PHY_RESET, 0);
+ break;
+ default:
+ break;
+ }
}
return SCMI_SUCCESS;
}
+/*
+ * Platform SCMI reset domains
+ */
+static struct scmi_pd *find_pd(unsigned int agent_id, unsigned int pd_id)
+{
+ const struct scmi_resources *resource = find_resource(agent_id);
+ size_t n;
+
+ if (resource != NULL) {
+ for (n = 0U; n < resource->pd_count; n++) {
+ if (n == pd_id) {
+ return &resource->pd[n];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+size_t plat_scmi_pd_count(unsigned int agent_id)
+{
+ const struct scmi_resources *resource = find_resource(agent_id);
+ size_t ret;
+
+ if (resource == NULL) {
+ ret = 0U;
+ } else {
+ ret = resource->pd_count;
+
+ NOTICE("SCMI: PD: %d\n", (unsigned int)ret);
+ }
+ return ret;
+}
+
+const char *plat_scmi_pd_get_name(unsigned int agent_id, unsigned int pd_id)
+{
+ const struct scmi_pd *pd = find_pd(agent_id, pd_id);
+
+ if (pd == NULL) {
+ return NULL;
+ }
+
+ return pd->name;
+}
+
+unsigned int plat_scmi_pd_statistics(unsigned int agent_id, unsigned long *pd_id)
+{
+ return 0U;
+}
+
+unsigned int plat_scmi_pd_get_attributes(unsigned int agent_id, unsigned int pd_id)
+{
+ return 0U;
+}
+
+unsigned int plat_scmi_pd_get_state(unsigned int agent_id, unsigned int pd_id)
+{
+ const struct scmi_pd *pd = find_pd(agent_id, pd_id);
+
+ if (pd == NULL) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
+ NOTICE("SCMI: PD: get id: %d, state: %x\n", pd_id, pd->state);
+
+ return pd->state;
+}
+
+int32_t plat_scmi_pd_set_state(unsigned int agent_id, unsigned int flags, unsigned int pd_id,
+ unsigned int state)
+{
+ struct scmi_pd *pd = find_pd(agent_id, pd_id);
+
+ if (pd == NULL) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
+ NOTICE("SCMI: PD: set id: %d, orig state: %x, new state: %x, flags: %x\n",
+ pd_id, pd->state, state, flags);
+
+ pd->state = state;
+
+ return 0U;
+}
+
+
/* Currently only one channel is supported. Expectation is that channel 0 is used by NS SW */
static struct scmi_msg_channel scmi_channel[] = {
[0] = {
@@ -475,10 +612,8 @@
SCMI_PROTOCOL_ID_BASE,
SCMI_PROTOCOL_ID_CLOCK,
SCMI_PROTOCOL_ID_RESET_DOMAIN,
- /*
- *SCMI_PROTOCOL_ID_POWER_DOMAIN,
- *SCMI_PROTOCOL_ID_SENSOR,
- */
+ SCMI_PROTOCOL_ID_POWER_DOMAIN,
+ /* SCMI_PROTOCOL_ID_SENSOR, */
0U /* Null termination */
};
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index 9fba4af..bf0e7f3 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -99,12 +99,17 @@
memory@2 {
device_type = "device-memory";
- reg = <0x0 0x1c090000 0x0 0x40000>, /* UART */
+ reg = <0x0 0x1c0b0000 0x0 0x20000>, /* UART 2-3 */
<0x0 0x2bfe0000 0x0 0x20000>, /* SMMUv3TestEngine */
<0x0 0x2a490000 0x0 0x20000>, /* SP805 Trusted Watchdog */
<0x0 0x1c130000 0x0 0x10000>; /* Virtio block device */
};
+ memory@3 {
+ device_type = "ns-device-memory";
+ reg = <0x0 0x1c090000 0x0 0x20000>; /* UART 0-1 */
+ };
+
#if MEASURED_BOOT
#include "event_log.dtsi"
diff --git a/plat/xilinx/common/include/pm_api_sys.h b/plat/xilinx/common/include/pm_api_sys.h
index ffee805..029bb43 100644
--- a/plat/xilinx/common/include/pm_api_sys.h
+++ b/plat/xilinx/common/include/pm_api_sys.h
@@ -64,6 +64,7 @@
uint32_t wake, uint32_t enable,
uint32_t flag);
enum pm_ret_status pm_get_chipid(uint32_t *value);
+enum pm_ret_status eemi_feature_check(uint32_t api_id, uint32_t *ret_payload);
/*
* Assigning of argument values into array elements.
@@ -97,4 +98,9 @@
PM_PACK_PAYLOAD5(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4)); \
}
+#define PM_PACK_PAYLOAD7(pl, mid, flag, arg0, arg1, arg2, arg3, arg4, arg5, arg6) { \
+ pl[6] = (uint32_t)(arg6); \
+ PM_PACK_PAYLOAD6(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4), (arg5)); \
+}
+
#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/common/include/pm_common.h b/plat/xilinx/common/include/pm_common.h
index c0308ab..c38cdef 100644
--- a/plat/xilinx/common/include/pm_common.h
+++ b/plat/xilinx/common/include/pm_common.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,13 +18,15 @@
#if IPI_CRC_CHECK
#define PAYLOAD_ARG_CNT 8U
+#define RET_PAYLOAD_ARG_CNT 7U
#define IPI_W0_TO_W6_SIZE 28U
#define PAYLOAD_CRC_POS 7U
#define CRC_INIT_VALUE 0x4F4EU
#define CRC_ORDER 16U
#define CRC_POLYNOM 0x8005U
#else
-#define PAYLOAD_ARG_CNT 6U
+#define PAYLOAD_ARG_CNT 7U
+#define RET_PAYLOAD_ARG_CNT 6U
#endif
#define PAYLOAD_ARG_SIZE 4U /* size in bytes */
diff --git a/plat/xilinx/common/include/pm_defs.h b/plat/xilinx/common/include/pm_defs.h
index 055fa3d..9920611 100644
--- a/plat/xilinx/common/include/pm_defs.h
+++ b/plat/xilinx/common/include/pm_defs.h
@@ -35,6 +35,7 @@
(uint32_t)XPM_NODESUBCL_DEV_PERIPH, \
(uint32_t)XPM_NODETYPE_DEV_PERIPH, (IDX))
+#define TF_A_FEATURE_CHECK 0xa00U
#define PM_GET_CALLBACK_DATA 0xa01U
#define PM_GET_TRUSTZONE_VERSION 0xa03U
#define TF_A_PM_REGISTER_SGI 0xa04U
@@ -95,6 +96,8 @@
IOCTL_GET_LAST_RESET_REASON = 23,
/* AI engine NPI ISR clear */
IOCTL_AIE_ISR_CLEAR = 24,
+ IOCTL_UFS_TXRX_CFGRDY_GET = 40,
+ IOCTL_UFS_SRAM_CSR_SEL = 41,
};
/**
diff --git a/plat/xilinx/common/include/pm_svc_main.h b/plat/xilinx/common/include/pm_svc_main.h
index 67fbeae..000f198 100644
--- a/plat/xilinx/common/include/pm_svc_main.h
+++ b/plat/xilinx/common/include/pm_svc_main.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,8 @@
extern bool pwrdwn_req_received;
+#define PASS_THROUGH_FW_CMD_ID U(0xfff)
+
/******************************************************************************/
/**
* SECURE_REDUNDANT_CALL() - Adds redundancy to the function call. This is to
diff --git a/plat/xilinx/common/pm_service/pm_api_sys.c b/plat/xilinx/common/pm_service/pm_api_sys.c
index 0a6e810..e9c5f13 100644
--- a/plat/xilinx/common/pm_service/pm_api_sys.c
+++ b/plat/xilinx/common/pm_service/pm_api_sys.c
@@ -122,7 +122,7 @@
}
PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5);
- return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, PAYLOAD_ARG_CNT);
+ return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, RET_PAYLOAD_ARG_CNT);
}
/**
@@ -364,6 +364,37 @@
}
/**
+ * eemi_feature_check() - Returns the supported API version if supported.
+ * @api_id: API ID to check.
+ * @ret_payload: pointer to array of PAYLOAD_ARG_CNT number of
+ * words Returned supported API version
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status eemi_feature_check(uint32_t api_id, uint32_t *ret_payload)
+{
+ enum pm_ret_status ret;
+
+ /* Return version of API which are implemented in TF-A only */
+ switch (api_id) {
+ case PM_GET_CALLBACK_DATA:
+ case PM_GET_TRUSTZONE_VERSION:
+ ret_payload[0] = PM_API_VERSION_2;
+ ret = PM_RET_SUCCESS;
+ break;
+ case TF_A_PM_REGISTER_SGI:
+ case TF_A_FEATURE_CHECK:
+ ret_payload[0] = PM_API_BASE_VERSION;
+ ret = PM_RET_SUCCESS;
+ break;
+ default:
+ ret = PM_RET_ERROR_NO_FEATURE;
+ }
+
+ return ret;
+}
+
+/**
* pm_feature_check() - Returns the supported API version if supported.
* @api_id: API ID to check.
* @flag: 0 - Call from secure source.
@@ -406,7 +437,7 @@
PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
PM_FEATURE_CHECK, api_id);
- return pm_ipi_send_sync(primary_proc, payload, ret_payload, PAYLOAD_ARG_CNT);
+ return pm_ipi_send_sync(primary_proc, payload, ret_payload, RET_PAYLOAD_ARG_CNT);
}
/**
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index 56567dd..205877c 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -164,15 +164,10 @@
*
*/
static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
- uint32_t *value, size_t count)
+ uint32_t value[PAYLOAD_ARG_CNT])
{
size_t i;
enum pm_ret_status ret;
-#if IPI_CRC_CHECK
- uint32_t *payload_ptr = value;
- size_t j;
- uint32_t response_payload[PAYLOAD_ARG_CNT];
-#endif
uintptr_t buffer_base = proc->ipi->buffer_base +
IPI_BUFFER_TARGET_REMOTE_OFFSET +
IPI_BUFFER_RESP_OFFSET;
@@ -184,27 +179,21 @@
* buf-2: unused
* buf-3: unused
*/
- for (i = 1; i <= count; i++) {
- *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
- value++;
+ for (i = 0; i < PAYLOAD_ARG_CNT; i++) {
+ value[i] = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
}
- ret = mmio_read_32(buffer_base);
+ ret = value[0];
#if IPI_CRC_CHECK
- for (j = 0; j < PAYLOAD_ARG_CNT; j++) {
- response_payload[j] = mmio_read_32(buffer_base +
- (j * PAYLOAD_ARG_SIZE));
- }
-
- if (response_payload[PAYLOAD_CRC_POS] !=
- calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) {
+ if (value[PAYLOAD_CRC_POS] !=
+ calculate_crc(value, IPI_W0_TO_W6_SIZE)) {
NOTICE("ERROR in CRC response payload value:0x%x\n",
- response_payload[PAYLOAD_CRC_POS]);
+ value[PAYLOAD_CRC_POS]);
ret = PM_RET_ERROR_INVALID_CRC;
/* Payload data is invalid as CRC validation failed
* Clear the payload to avoid leakage of data to upper layers
*/
- memset(payload_ptr, 0, count);
+ memset(value, 0, PAYLOAD_ARG_CNT);
}
#endif
@@ -240,7 +229,7 @@
count = IPI_BUFFER_MAX_WORDS;
}
- for (i = 0; i <= count; i++) {
+ for (i = 0; i < count; i++) {
*value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
value++;
}
@@ -282,6 +271,7 @@
uint32_t *value, size_t count)
{
enum pm_ret_status ret;
+ uint32_t i, ret_payload[PAYLOAD_ARG_CNT] = {0U};
pm_ipi_lock_get();
@@ -290,7 +280,12 @@
goto unlock;
}
+ ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, ret_payload));
+
- ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count));
+ for (i = 1U; i <= count; i++) {
+ *value = ret_payload[i];
+ value++;
+ }
unlock:
pm_ipi_lock_release();
diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c
index 7ac0ac1..b431a6c 100644
--- a/plat/xilinx/common/pm_service/pm_svc_main.c
+++ b/plat/xilinx/common/pm_service/pm_svc_main.c
@@ -36,6 +36,32 @@
#define EVENT_CPU_PWRDWN (4U)
#define MBOX_SGI_SHARED_IPI (7U)
+/**
+ * upper_32_bits - return bits 32-63 of a number
+ * @n: the number we're accessing
+ */
+#define upper_32_bits(n) ((uint32_t)((n) >> 32U))
+
+/**
+ * lower_32_bits - return bits 0-31 of a number
+ * @n: the number we're accessing
+ */
+#define lower_32_bits(n) ((uint32_t)((n) & 0xffffffffU))
+
+/**
+ * EXTRACT_SMC_ARGS - extracts 32-bit payloads from 64-bit SMC arguments
+ * @pm_arg: array of 32-bit payloads
+ * @x: array of 64-bit SMC arguments
+ */
+#define EXTRACT_ARGS(pm_arg, x) \
+ for (uint32_t i = 0U; i < (PAYLOAD_ARG_CNT - 1U); i++) { \
+ if ((i % 2U) != 0U) { \
+ pm_arg[i] = lower_32_bits(x[(i / 2U) + 1U]); \
+ } else { \
+ pm_arg[i] = upper_32_bits(x[i / 2U]); \
+ } \
+ }
+
/* 1 sec of wait timeout for secondary core down */
#define PWRDWN_WAIT_TIMEOUT (1000U)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
@@ -278,7 +304,7 @@
case (uint32_t)PM_FEATURE_CHECK:
{
- uint32_t result[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t result[RET_PAYLOAD_ARG_CNT] = {0U};
ret = pm_feature_check(pm_arg[0], result, security_flag);
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
@@ -367,6 +393,15 @@
{
switch (api_id) {
+ case TF_A_FEATURE_CHECK:
+ {
+ enum pm_ret_status ret;
+ uint32_t result[PAYLOAD_ARG_CNT] = {0U};
+
+ ret = eemi_feature_check(pm_arg[0], result);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U));
+ }
+
case TF_A_PM_REGISTER_SGI:
{
int32_t ret;
@@ -424,7 +459,7 @@
void *handle, uint32_t security_flag)
{
enum pm_ret_status ret;
- uint32_t buf[PAYLOAD_ARG_CNT] = {0};
+ uint32_t buf[RET_PAYLOAD_ARG_CNT] = {0};
ret = pm_handle_eemi_call(security_flag, api_id, pm_arg[0], pm_arg[1],
pm_arg[2], pm_arg[3], pm_arg[4],
@@ -449,6 +484,45 @@
}
/**
+ * eemi_api_handler() - Prepare EEMI payload and perform IPI transaction.
+ * @api_id: identifier for the API being called.
+ * @pm_arg: pointer to the argument data for the API call.
+ * @handle: Pointer to caller's context structure.
+ * @security_flag: SECURE_FLAG or NON_SECURE_FLAG.
+ *
+ * EEMI - Embedded Energy Management Interface is AMD-Xilinx proprietary
+ * protocol to allow communication between power management controller and
+ * different processing clusters.
+ *
+ * This handler prepares EEMI protocol payload received from kernel and performs
+ * IPI transaction.
+ *
+ * Return: If EEMI API found then, uintptr_t type address, else 0
+ */
+static uintptr_t eemi_api_handler(uint32_t api_id, const uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ enum pm_ret_status ret;
+ uint32_t buf[PAYLOAD_ARG_CNT] = {0};
+ uint32_t payload[PAYLOAD_ARG_CNT] = {0};
+ uint32_t module_id;
+
+ module_id = (api_id & MODULE_ID_MASK) >> 8U;
+
+ PM_PACK_PAYLOAD7(payload, module_id, security_flag, api_id,
+ pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3],
+ pm_arg[4], pm_arg[5]);
+
+ ret = pm_ipi_send_sync(primary_proc, payload, (uint32_t *)buf,
+ PAYLOAD_ARG_CNT);
+
+ SMC_RET4(handle, (uint64_t)ret | ((uint64_t)buf[0] << 32U),
+ (uint64_t)buf[1] | ((uint64_t)buf[2] << 32U),
+ (uint64_t)buf[3] | ((uint64_t)buf[4] << 32U),
+ (uint64_t)buf[5]);
+}
+
+/**
* pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
* @smc_fid: Function Identifier.
* @x1: SMC64 Arguments from kernel.
@@ -477,6 +551,7 @@
uint32_t security_flag = NON_SECURE_FLAG;
uint32_t api_id;
bool status = false, status_tmp = false;
+ uint64_t x[4] = {x1, x2, x3, x4};
/* Handle case where PM wasn't initialized properly */
if (pm_up == false) {
@@ -494,6 +569,14 @@
security_flag = SECURE_FLAG;
}
+ if ((smc_fid & FUNCID_NUM_MASK) == PASS_THROUGH_FW_CMD_ID) {
+ api_id = lower_32_bits(x[0]);
+
+ EXTRACT_ARGS(pm_arg, x);
+
+ return eemi_api_handler(api_id, pm_arg, handle, security_flag);
+ }
+
pm_arg[0] = (uint32_t)x1;
pm_arg[1] = (uint32_t)(x1 >> 32U);
pm_arg[2] = (uint32_t)x2;
diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c
index 772477f..9e8134a 100644
--- a/plat/xilinx/versal/aarch64/versal_common.c
+++ b/plat/xilinx/versal/aarch64/versal_common.c
@@ -1,12 +1,11 @@
/*
* Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
-#include <drivers/generic_delay_timer.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
@@ -18,7 +17,7 @@
#include <versal_def.h>
uint32_t platform_id, platform_version;
-uint32_t cpu_clock = VERSAL_CPU_CLOCK;
+uint32_t cpu_clock;
/*
* Table of regions to map using the MMU.
@@ -39,19 +38,10 @@
return plat_versal_mmap;
}
-static void versal_print_platform_name(void)
-{
- NOTICE("TF-A running on %s\n", PLATFORM_NAME);
-}
-
void versal_config_setup(void)
{
/* Configure IPI data for versal */
versal_ipi_config_table_init();
-
- versal_print_platform_name();
-
- generic_delay_timer_init();
}
void board_detection(void)
@@ -70,7 +60,50 @@
platform_version = FIELD_GET(PLATFORM_VERSION_MASK, plat_info[1]);
}
+const char *board_name_decode(void)
+{
+ const char *platform;
+
+ switch (platform_id) {
+ case VERSAL_SPP:
+ platform = "IPP";
+ break;
+ case VERSAL_EMU:
+ platform = "EMU";
+ break;
+ case VERSAL_QEMU:
+ platform = "QEMU";
+ break;
+ case VERSAL_SILICON:
+ platform = "SILICON";
+ break;
+ default:
+ platform = "unknown";
+ }
+
+ return platform;
+}
+
uint32_t get_uart_clk(void)
{
- return UART_CLOCK;
+ uint32_t uart_clock;
+
+ switch (platform_id) {
+ case VERSAL_SPP:
+ uart_clock = 25000000;
+ break;
+ case VERSAL_EMU:
+ uart_clock = 212000;
+ break;
+ case VERSAL_QEMU:
+ uart_clock = 25000000;
+ break;
+ case VERSAL_SILICON:
+ uart_clock = 100000000;
+ break;
+ default:
+ panic();
+ }
+
+ return uart_clock;
}
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 594784f..0e4ec1c 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,7 @@
#include <bl31/bl31.h>
#include <common/bl_common.h>
#include <common/debug.h>
+#include <drivers/generic_delay_timer.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
@@ -73,22 +74,41 @@
enum pm_ret_status ret_status;
uint64_t addr[HANDOFF_PARAMS_MAX_SIZE];
- set_cnt_freq();
-
- setup_console();
-
- /* Initialize the platform config for future decision making */
- versal_config_setup();
-
- /* Get platform related information */
- board_detection();
-
/*
* Do initial security configuration to allow DRAM/device access. On
* Base VERSAL only DRAM security is programmable (via TrustZone), but
* other platforms might have more programmable security devices
* present.
*/
+ versal_config_setup();
+
+ /* Initialize the platform config for future decision making */
+ board_detection();
+
+ switch (platform_id) {
+ case VERSAL_SPP:
+ cpu_clock = 2720000;
+ break;
+ case VERSAL_EMU:
+ cpu_clock = 212000;
+ break;
+ case VERSAL_QEMU:
+ /* Random values now */
+ cpu_clock = 2720000;
+ break;
+ case VERSAL_SILICON:
+ cpu_clock = 100000000;
+ break;
+ default:
+ panic();
+ }
+ set_cnt_freq();
+
+ generic_delay_timer_init();
+
+ setup_console();
+
+ NOTICE("TF-A running on %s %d\n", board_name_decode(), platform_version);
/* Populate common information for BL32 and BL33 */
SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
diff --git a/plat/xilinx/versal/include/plat_private.h b/plat/xilinx/versal/include/plat_private.h
index 932c6de..4b2b6cf 100644
--- a/plat/xilinx/versal/include/plat_private.h
+++ b/plat/xilinx/versal/include/plat_private.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,6 +25,8 @@
extern uint32_t cpu_clock, platform_id, platform_version;
void board_detection(void);
+const char *board_name_decode(void);
+
void plat_versal_gic_driver_init(void);
void plat_versal_gic_init(void);
void plat_versal_gic_cpuif_enable(void);
diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h
index f21d409..b7691ad 100644
--- a/plat/xilinx/versal/include/versal_def.h
+++ b/plat/xilinx/versal/include/versal_def.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,13 +25,11 @@
#define CONSOLE_IS(con) (VERSAL_CONSOLE_ID_ ## con == VERSAL_CONSOLE)
-/* List all supported platforms */
-#define VERSAL_PLATFORM_ID_versal_virt 1
-#define VERSAL_PLATFORM_ID_spp_itr6 2
-#define VERSAL_PLATFORM_ID_emu_itr6 3
-#define VERSAL_PLATFORM_ID_silicon 4
-
-#define VERSAL_PLATFORM_IS(con) (VERSAL_PLATFORM_ID_ ## con == VERSAL_PLATFORM)
+/* List of platforms */
+#define VERSAL_SILICON U(0)
+#define VERSAL_SPP U(1)
+#define VERSAL_EMU U(2)
+#define VERSAL_QEMU U(3)
/* Firmware Image Package */
#define VERSAL_PRIMARY_CPU 0
@@ -75,27 +73,7 @@
/*******************************************************************************
* Platform related constants
******************************************************************************/
-#if VERSAL_PLATFORM_IS(versal_virt)
-# define PLATFORM_NAME "Versal Virt"
-# define UART_CLOCK 25000000
-# define UART_BAUDRATE 115200
-# define VERSAL_CPU_CLOCK 2720000
-#elif VERSAL_PLATFORM_IS(silicon)
-# define PLATFORM_NAME "Versal Silicon"
-# define UART_CLOCK 100000000
-# define UART_BAUDRATE 115200
-# define VERSAL_CPU_CLOCK 100000000
-#elif VERSAL_PLATFORM_IS(spp_itr6)
-# define PLATFORM_NAME "SPP ITR6"
-# define UART_CLOCK 25000000
-# define UART_BAUDRATE 115200
-# define VERSAL_CPU_CLOCK 2720000
-#elif VERSAL_PLATFORM_IS(emu_itr6)
-# define PLATFORM_NAME "EMU ITR6"
-# define UART_CLOCK 212000
-# define UART_BAUDRATE 9600
-# define VERSAL_CPU_CLOCK 212000
-#endif
+#define UART_BAUDRATE 115200
/* Access control register defines */
#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index 4cf1ed1..74c5bf3 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -197,7 +197,7 @@
*/
static void versal_pwr_domain_off(const psci_power_state_t *target_state)
{
- uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t ret, fw_api_version, version[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index 2f07996..6cc28e1 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -1,5 +1,5 @@
# Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
-# Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -44,8 +44,9 @@
$(eval $(call add_define,IPI_CRC_CHECK))
endif
-VERSAL_PLATFORM ?= silicon
-$(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFORM}))
+ifdef VERSAL_PLATFORM
+ $(warning "VERSAL_PLATFORM has been deprecated")
+endif
ifdef XILINX_OF_BOARD_DTB_ADDR
$(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR))
diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c
index 4441d3e..3c0bd63 100644
--- a/plat/xilinx/versal/sip_svc_setup.c
+++ b/plat/xilinx/versal/sip_svc_setup.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -22,7 +22,7 @@
/* SiP Service Calls version numbers */
#define SIP_SVC_VERSION_MAJOR U(0)
-#define SIP_SVC_VERSION_MINOR U(1)
+#define SIP_SVC_VERSION_MINOR U(2)
/* These macros are used to identify PM calls from the SMC function ID */
#define SIP_FID_MASK GENMASK(23, 16)
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
index e5a5235..fb2005d 100644
--- a/plat/xilinx/versal_net/plat_psci_pm.c
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -59,7 +59,7 @@
*/
static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
{
- uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t ret, fw_api_version, version[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
diff --git a/plat/xilinx/versal_net/sip_svc_setup.c b/plat/xilinx/versal_net/sip_svc_setup.c
index 80d5a53..c974810 100644
--- a/plat/xilinx/versal_net/sip_svc_setup.c
+++ b/plat/xilinx/versal_net/sip_svc_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,7 +25,7 @@
/* SiP Service Calls version numbers */
#define SIP_SVC_VERSION_MAJOR (0U)
-#define SIP_SVC_VERSION_MINOR (1U)
+#define SIP_SVC_VERSION_MINOR (2U)
/* These macros are used to identify PM calls from the SMC function ID */
#define SIP_FID_MASK GENMASK(23, 16)
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
index 3d546b3..66f011a 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
@@ -919,7 +919,7 @@
enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
uint32_t *bit_mask, uint8_t len)
{
- uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t ret_payload[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t status;
/* Get API version implemented in TF-A */
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
index 5a6a9f8..bf17ea4 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
@@ -285,7 +285,7 @@
uint32_t payload[PAYLOAD_ARG_CNT];
uint32_t pm_arg[5];
- uint32_t result[PAYLOAD_ARG_CNT] = {0};
+ uint32_t result[RET_PAYLOAD_ARG_CNT] = {0};
uint32_t api_id;
/* Handle case where PM wasn't initialized properly */
@@ -566,7 +566,7 @@
PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1],
pm_arg[2], pm_arg[3], pm_arg[4]);
ret = pm_ipi_send_sync(primary_proc, payload, result,
- PAYLOAD_ARG_CNT);
+ RET_PAYLOAD_ARG_CNT);
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
(uint64_t)result[1] | ((uint64_t)result[2] << 32U));
}