Merge changes Ided750de,Id3cc887c into integration
* changes:
docs(gxl): add build instructions for booting BL31 from U-Boot SPL
feat(gxl): add support for booting from U-Boot SPL/with standard params
diff --git a/Makefile b/Makefile
index 4d52c31..51c7b2e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -23,7 +23,6 @@
MAKE_HELPERS_DIRECTORY := make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
-include ${MAKE_HELPERS_DIRECTORY}build_env.mk
include ${MAKE_HELPERS_DIRECTORY}build-rules.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
@@ -99,15 +98,15 @@
# Variables for use with Certificate Generation Tool
CRTTOOLPATH ?= tools/cert_create
-CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT}
+CRTTOOL ?= ${CRTTOOLPATH}/cert_create$(.exe)
# Variables for use with Firmware Encryption Tool
ENCTOOLPATH ?= tools/encrypt_fw
-ENCTOOL ?= ${ENCTOOLPATH}/encrypt_fw${BIN_EXT}
+ENCTOOL ?= ${ENCTOOLPATH}/encrypt_fw$(.exe)
# Variables for use with Firmware Image Package
FIPTOOLPATH ?= tools/fiptool
-FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT}
+FIPTOOL ?= ${FIPTOOLPATH}/fiptool$(.exe)
# Variables for use with sptool
SPTOOLPATH ?= tools/sptool
@@ -514,6 +513,12 @@
endif
################################################################################
+# Include the platform specific Makefile after the SPD Makefile (the platform
+# makefile may use all previous definitions in this file)
+################################################################################
+include ${PLAT_MAKEFILE_FULL}
+
+################################################################################
# Process BRANCH_PROTECTION value and set
# Pointer Authentication and Branch Target Identification flags
################################################################################
@@ -558,12 +563,6 @@
endif
################################################################################
-# Include the platform specific Makefile after the SPD Makefile (the platform
-# makefile may use all previous definitions in this file)
-################################################################################
-include ${PLAT_MAKEFILE_FULL}
-
-################################################################################
# Setup arch_features based on ARM_ARCH_MAJOR, ARM_ARCH_MINOR provided from
# platform.
################################################################################
@@ -954,6 +953,14 @@
ifneq (${ENABLE_FEAT_FPMR},0)
$(error "ENABLE_FEAT_FPMR cannot be used with ARCH=aarch32")
endif
+
+ ifeq (${ARCH_FEATURE_AVAILABILITY},1)
+ $(error "ARCH_FEATURE_AVAILABILITY cannot be used with ARCH=aarch32")
+ endif
+ # FEAT_MOPS is only supported on AArch64
+ ifneq (${ENABLE_FEAT_MOPS},0)
+ $(error "ENABLE_FEAT_MOPS cannot be used with ARCH=aarch32")
+ endif
endif #(ARCH=aarch32)
ifneq (${ENABLE_FEAT_FPMR},0)
@@ -1202,6 +1209,7 @@
PROGRAMMABLE_RESET_ADDRESS \
PSCI_EXTENDED_STATE_ID \
PSCI_OS_INIT_MODE \
+ ARCH_FEATURE_AVAILABILITY \
RESET_TO_BL31 \
SAVE_KEYS \
SEPARATE_CODE_AND_RODATA \
@@ -1279,6 +1287,7 @@
ENABLE_FEAT_FPMR \
ENABLE_FEAT_HCX \
ENABLE_FEAT_LS64_ACCDATA \
+ ENABLE_FEAT_MOPS \
ENABLE_FEAT_MTE2 \
ENABLE_FEAT_PAN \
ENABLE_FEAT_RNG \
@@ -1383,6 +1392,7 @@
PROGRAMMABLE_RESET_ADDRESS \
PSCI_EXTENDED_STATE_ID \
PSCI_OS_INIT_MODE \
+ ARCH_FEATURE_AVAILABILITY \
RESET_TO_BL31 \
RME_GPT_BITLOCK_BLOCK \
RME_GPT_MAX_BLOCK \
@@ -1456,6 +1466,7 @@
ENABLE_FEAT_SCTLR2 \
ENABLE_FEAT_D128 \
ENABLE_FEAT_GCS \
+ ENABLE_FEAT_MOPS \
ENABLE_FEAT_MTE2 \
FEATURE_DETECTION \
TWED_DELAY \
@@ -1640,29 +1651,17 @@
clean:
$(s)echo " CLEAN"
- $(call SHELL_REMOVE_DIR,${BUILD_PLAT})
-ifdef UNIX_MK
+ $(q)rm -rf $(BUILD_PLAT)
$(q)${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
-else
-# Clear the MAKEFLAGS as we do not want
-# to pass the gnumake flags to nmake.
- $(q)set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL)) clean
-endif #(UNIX_MK)
$(q)${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
$(q)${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} clean
$(q)${MAKE} --no-print-directory -C ${ROMLIBPATH} clean
realclean distclean:
$(s)echo " REALCLEAN"
- $(call SHELL_REMOVE_DIR,${BUILD_BASE})
- $(call SHELL_DELETE_ALL, ${CURDIR}/cscope.*)
-ifdef UNIX_MK
+ $(q)rm -rf $(BUILD_BASE)
+ $(q)rm -rf $(CURDIR)/cscope.*
$(q)${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
-else
-# Clear the MAKEFLAGS as we do not want
-# to pass the gnumake flags to nmake.
- $(q)set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL)) realclean
-endif #(UNIX_MK)
$(q)${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} realclean
$(q)${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} realclean
$(q)${MAKE} --no-print-directory -C ${ROMLIBPATH} clean
@@ -1747,25 +1746,14 @@
fwu_fip: ${BUILD_PLAT}/${FWU_FIP_NAME}
${FIPTOOL}: FORCE
-ifdef UNIX_MK
$(q)${MAKE} PLAT=${PLAT} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" FIPTOOL=${FIPTOOL} OPENSSL_DIR=${OPENSSL_DIR} DEBUG=${DEBUG} --no-print-directory -C ${FIPTOOLPATH} all
-else
-# Clear the MAKEFLAGS as we do not want
-# to pass the gnumake flags to nmake.
- $(q)set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL))
-endif #(UNIX_MK)
$(BUILD_PLAT)/romlib/romlib.bin $(BUILD_PLAT)/lib/libwrappers.a $&: $(BUILD_PLAT)/lib/libfdt.a $(BUILD_PLAT)/lib/libc.a $(CRYPTO_LIB)
$(q)${MAKE} PLAT_DIR=${PLAT_DIR} BUILD_PLAT=${BUILD_PLAT} ENABLE_BTI=${ENABLE_BTI} CRYPTO_SUPPORT=${CRYPTO_SUPPORT} ARM_ARCH_MINOR=${ARM_ARCH_MINOR} INCLUDES=$(call escape-shell,$(INCLUDES)) DEFINES=$(call escape-shell,$(DEFINES)) --no-print-directory -C ${ROMLIBPATH} all
memmap: all
-ifdef UNIX_MK
$(q)PYTHONPATH=${CURDIR}/tools/memory \
${PYTHON} -m memory.memmap -sr ${BUILD_PLAT}
-else
- $(q)set PYTHONPATH=${CURDIR}/tools/memory && \
- ${PYTHON} -m memory.memmap -sr ${BUILD_PLAT}
-endif
tl: ${BUILD_PLAT}/tl.bin
${BUILD_PLAT}/tl.bin: ${HW_CONFIG}
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 0f6be9f..821ccb8 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -286,6 +286,12 @@
ID_AA64PFR2_EL1_FPMR_MASK);
}
+static unsigned int read_feat_mops_id_field(void)
+{
+ return ISOLATE_FIELD(read_id_aa64isar2_el1(), ID_AA64ISAR2_EL1_MOPS_SHIFT,
+ ID_AA64ISAR2_EL1_MOPS_MASK);
+}
+
/***********************************************************************************
* TF-A supports many Arm architectural features starting from arch version
* (8.0 till 8.7+). These features are mostly enabled through build flags. This
@@ -343,6 +349,8 @@
check_feature(ENABLE_FEAT_DIT, read_feat_dit_id_field(), "DIT", 1, 1);
check_feature(ENABLE_FEAT_AMU, read_feat_amu_id_field(),
"AMUv1", 1, 2);
+ check_feature(ENABLE_FEAT_MOPS, read_feat_mops_id_field(),
+ "MOPS", 1, 1);
check_feature(ENABLE_FEAT_MPAM, read_feat_mpam_version(),
"MPAM", 1, 17);
check_feature(CTX_INCLUDE_NEVE_REGS, read_feat_nv_id_field(),
diff --git a/docs/about/index.rst b/docs/about/index.rst
index 06973ef..7cf2a68 100644
--- a/docs/about/index.rst
+++ b/docs/about/index.rst
@@ -7,6 +7,7 @@
features
release-information
+ lts
maintainers
contact
acknowledgements
diff --git a/docs/about/lts.rst b/docs/about/lts.rst
new file mode 100644
index 0000000..f5e5f8e
--- /dev/null
+++ b/docs/about/lts.rst
@@ -0,0 +1,364 @@
+LTS - Long-Term Support
+=======================
+
+.. table:: Table 1: Document History
+
+ +-------------+--------------------+-------------------------------------------------------+
+ | Date | Author | Description |
+ +=============+====================+=======================================================+
+ | 2022-07-20 | Okash Khawaja, | Initial draft. |
+ | | Varun Wadekar | |
+ +-------------+--------------------+-------------------------------------------------------+
+ | 2022-07-21 | Varun Wadekar | Refine the Maintainership guidelines and planning |
+ | | | sections. Introduce a new section documenting a day |
+ | | | in the life of a LTS branch maintainer |
+ +-------------+--------------------+-------------------------------------------------------+
+ | 2022-08-05 | Okash Khawaja, | Merge two drafts (draft 1 and 2), address comments |
+ | | Varun Wadekar | made by both authors, cosmetic changes to the content |
+ | | | all over the document |
+ +-------------+--------------------+-------------------------------------------------------+
+ | 2022-08-05 | Okash Khawaja | Add note about testing support available from TF.org |
+ +-------------+--------------------+-------------------------------------------------------+
+ | 2022-08-05 | Varun Wadekar | Changed the “Future plans” section to “FAQ” and |
+ | | | answered some of the questions with feedback from |
+ | | | the community. |
+ +-------------+--------------------+-------------------------------------------------------+
+ | 2025-01-07 | Govindraj Raja | Convert from pdf to rst. |
+ +-------------+--------------------+-------------------------------------------------------+
+ | 2025-01-07 | Govindraj Raja | Updates based on learnings and suggestions. |
+ +-------------+--------------------+-------------------------------------------------------+
+
+This document proposes a plan for long-term support (LTS) of the |TF-A| project.
+
+Why is LTS required?
+--------------------
+LTS is needed for commercial reasons. More specifically, on the device side,
+when a product is released, the companies have to support that in-market product
+such that the amount of changes to the firmware are kept to a minimum to avoid
+the risk of regression. At the same time the companies don't want to exclude
+critical patches such as those for security advisories. Similarly on the server side,
+companies want to minimize the churn when deploying fixes during incident
+response, e.g. due to critical security bugs.
+
+Also, the European Cyber Resilience Act (CRA) is a new EU legislation that mandates
+cybersecurity standards for products containing digital elements, aiming to
+protect consumers and businesses by ensuring manufacturers build security into
+their hardware and software throughout their lifecycle, including automatic
+updates and incident reporting; essentially requiring all digital products
+sold in the EU to meet specific cybersecurity requirements.
+
+This means that companies have to maintain and backport critical updates to
+old branches internally. As this effort is duplicated across different companies
+using TF-A, it makes sense to factor out this effort into a community-wide LTS.
+
+What does LTS mean for TF-A?
+----------------------------
+In this section we will define exactly what constitutes LTS for TF-A.
+Specifically, we will define the following characteristics:
+
+- criteria for selecting patches which will be backported to LTS branches
+- lifetime and frequency of LTS branches
+
+**Criteria**
+
+We must have an objective criterion for selecting patches to be backported to
+LTS branches. This will make maintenance easy because:
+
+a. there will be less -- ideally no -- discussion when selecting patches to backport
+b. large parts of the process can be automated
+
+Below is the criteria
+
+#. No features will be backported.
+#. Security advisories: Any patch that makes it into :ref:`Security Advisories`
+ is automatically selected for back porting. This includes patches to external
+ components too, e.g. libfdt.
+#. Workarounds for CPU and other ARM IP errata
+#. Workarounds for non-ARM IP errata, e.g. TI UART
+#. Fixes for platform bugs. These patches must not modify any code outside of
+ the specific platform that the fix applies to.
+#. Patches can only be backported from the master branch. In other words, the
+ master branch will be a superset of all the changes in any LTS branch.
+
+**Lifetime and frequency**
+
+This section approaches three questions: for how long should an LTS release be
+supported, how frequently should LTS releases be made and at which time(s) of
+the year should the releases be made.
+
+1. For how long should an LTS release be supported?
+
+The Linux kernel maintainers supports an LTS branch for 2 years. Since firmware
+tends to have less churn and longer lifetime than a HLOS, TF-A is trying to
+support at-least 7 years for its LTS. Initially it was intended to support
+5 years but there has been no objections to extend LTS support to 7 years.
+There are many challenges that may influence the 7 year support from CI
+infrastructure to availability of maintainers.
+
+2. How frequently should LTS releases be made?
+
+Given that many products that have a release cycle, have a yearly release
+cycle, it would make sense to have yearly TF-A releases.
+
+3. Which time(s) of the year should the releases be made?
+
+TF-A releases are cut twice a year: May and November. Basing LTS release
+on the November TF-A release has a few benefits. First, it aligns with Linux
+LTS releases which happen towards the end of each year. Second, it aligns
+with Android releases which tend to fall in Q3 each year. Since product
+releases are timed with Android release, this gives enough time to harden
+the TF-A LTS release during development so that it's ready for launch in
+Q3 following year. On the other hand, if the May release of TF-A is chosen as
+the basis for LTS then developers will have little time -- about a month,
+taking into account the test-and-debug phase before LTS is cut (see below) --
+before Android release.
+
+To summarize, there will be one LTS release per year. It will be supported for
+5 years and we can discuss extending it to 7 years later on. The LTS release
+will be based on the November release of TF-A.
+
+**Testing Criteria**
+
+Every patch merged to the LTS branch will complete the following tests before
+getting approved.
+
+#. TFTF tests currently running in the testing farm
+#. CI/CD static analysis scans
+#. Coverity scans
+#. Platform tests
+
+Platforms that are not maintained upstream will undergo testing downstream in a
+pre-defined window. The platform maintainer will complete the testing and provide
+a verified score on the patch once testing is completed.
+
+** A note about test coverage from TF.org **
+
+Currently TF.org maintains a CI system to run TF-A automated tests on a
+selection of HW boards donated by TF.org members (a benefit reserved to project
+members, see the project charter for more details). This automated test coverage
+will be extended to cover testing for LTS as well for boards that are part of
+the CI system.
+
+**TFTF Branching**
+
+A note about testing here. After a patch is backported to an LTS branch, that
+branch will need to be regression tested. Since TFTF moves forward with latest
+TF-A changes, newer TFTF tests may not apply to old LTS branches. Therefore
+TFTF will also need to be branched, in-sync with TF-A LTS branches. In other
+words, there will be one TFTF LTS branch corresponding to each TF-A LTS branch.
+The TFTF LTS branch will be used to regression test the corresponding TF-A LTS
+branch.
+
+As we work with the LTS branch of TFTF, we might also need fixes for TFTF
+itself to be ported to LTS. However, decision-making about those patches need
+not be as stringent as for TF-A.
+
+**CI Scripts**
+
+CI Scripts moves forward with TF-A changes, since we need to checkout the
+corresponding release version of CI scripts for LTS.
+
+Though we are unlikely to update CI scripts, but time to time migrating a newer
+FVP version or deprecating certain tests due to unavailability of platforms may
+influence updates to CI Scripts.
+
+**Hafnium / OP-TEE**
+
+Both Hafnium and OP-TEE move forward with TF-A changes so we need to freeze their
+corresponding version from TF-A release for a LTS.
+
+**MbedTLS**
+
+Updates to the version of MbedTLS used with LTS will happen time to time based on
+maintainers call to update them or not.
+
+Release details
+---------------
+This section goes into details of what the LTS release process will look like.
+
+
+**Test-and-debug period**
+
+Since the LTS branch will be used in product releases, it is expected that more
+testing and debugging will be done on the November release of TF-A. Therefore
+it would make sense to leave at least a month after the November release and
+then cut the LTS branch. We recommend two months, given that one of the months
+is December which tends to be slower due to holidays. So, an end-of-November
+TF-A release would result in a beginning-of-February LTS release. Note that
+the LTS branch will be created at the same time as the TF-A November release,
+but it will be officially released at the end of January or early February.
+Going forward we should strive to make the period smaller and smaller until
+ideally it coincides with TF-A November release which means that our test
+and CI/CD infra is good enough to allow that to happen.
+
+**Example timeline**
+
+Below is an example timeline starting from the November 2022 release of TF-A.
+
+.. image:: ../resources/diagrams/lts-timeline-example.png
+
+- Nov 2022: TF-A 2.8 is released towards the end of Nov, 2022. Not shown in the
+ diagram, at the same time LTS release candidate branch is made which is based
+ on TF-A 2.8. This means new features going in 2.8 won’t go in the LTS branch.
+ We can call it `LTS 2.8-rc`.
+- Feb 2023: After testing and debugging LTS 2.8-rc for a couple of months,
+ LTS 2.8.0 is officially released in early Feb 2023.
+- May 2023: TF-A 2.9 is released but since this is not an LTS branch it doesn’t
+ affect LTS.
+- Somewhere between May and Nov of 2023: A security advisory comes up and the
+ related patches go into TF-A master branch. Since these patches fall under
+ LTS criteria, they are backported to LTS 2.8.0 which results in LTS 2.8.1
+ being released. Note that here we don’t allow the extra testing and debugging
+ time that we had between Nov 2022 and early Feb 2023. This is because there
+ isn’t as much to test and debug as an annual LTS release has. Also companies
+ might want to deploy critical patches soon.
+- Nov 2023: TF-A 2.10 is released. Not shown in the diagram, at the same time
+ LTS 2.10-rc is made. It’s tested by partners for a couple of months.
+- Feb 2024: LTS 2.10.1 is released in early Feb. Now there are two LTS
+ branches: 2.8.1 and 2.10.1.
+
+Note that TFTF will follow similar branching model as TF-A LTS, i.e. there will
+be TFTF LTS 2.8.0 in Feb 2023, 2.8.1 (if new TFTF tests need to be added for
+the security advisory) when there is TF-A LTS 2.8.1 and so on.
+
+Maintainership
+--------------
+
+**Guidelines & Responsibilities**
+
+#. Maintainers shall be impartial and strive to work for the benefit of
+ the community
+#. Objective and well-defined merge criteria to avoid confusion and discussions
+ at random points in time when there is a "candidate" patch
+#. The maintainers shall explain the lifecycle of a patch to the community,
+ with a detailed description of the maximum time spent in each step
+#. Automate, automate, automate
+#. Reviewers should not focus too much on "what" and instead focus on "how"
+#. Constantly refine the merge criteria to include more partner use cases
+#. Ensure that all candidate patches flow from the main branch to all LTS branches
+#. Maintainers collaborate in the following discord channel -
+ https://discord.com/channels/1106321706588577904/1162029539761852436
+#. Maintainers discuss and provide updates about upcoming LTS releases in the above
+ mentioned discord channel.
+
+**Options**
+
+These are some options in the order of preference.
+
+#. Current set of :ref:`lts maintainers` from tf.org(or hired contractor) take care of the LTS
+#. From the community, create a set of maintainers focused solely on the LTS branches
+
+A day in the life of a maintainer
+*********************************
+This section documents the daily tasks that a maintainer might perform to
+support the LTS program. It is expected that a maintainer follows clearly laid
+down steps and does not have to make policy level decisions for merge, testing,
+or candidate patch selection.
+
+#. Monitor the main branch to identify candidate patches for the LTS branches
+#. Monitor emails from LTS triage report to choose patches that should be
+ cherry-picked for LTS branches.
+#. Cherry-pick agreed patches to LTS branches co-ordinate review process and Monitor
+ CI results.
+#. Monitor the mailing list for any LTS related issues
+#. Propose or solicit patches to the main branch and tag them as candidates for LTS
+
+Execution Plan
+**************
+This section lists the steps needed to put the LTS system in place. However,
+to kick start LTS in Nov ‘22, only a few steps are needed. The rest can follow
+in the background.
+
+Initial release steps
+*********************
+
+The following steps are necessary to kickstart the project and potentially
+create the first LTS from the Nov’22 release.
+
+#. Create a TF-A LTS release-candidate branch and a TFTF LTS branch immediately
+ after the Nov’22 release
+#. Request all platform-owners to test and debug the RC branch
+#. Gather feedback from the test and debug cycle
+#. Mark the TF-A LTS branch ready by the end of January
+#. Announce the official LTS release availability on the mailing lists
+
+Long term release plan
+**********************
+Above will buy us time to then work on the rest of the execution plan which
+is given below.
+
+#. The review criteria for LTS patches must be the same as TF-A patches
+#. The maintainers shall publish the well-defined merge criteria to allow
+ the community to choose candidate patches
+#. The maintainers shall publish a well-defined test specification for any
+ patch entering the LTS branch
+
+ a. Tests required to pass in the CI/CD flow
+ b. Static analysis scans
+ c. Coverity scans
+
+#. The maintainers shall publish a mechanism to choose candidate patches for
+ the LTS branch
+#. The maintainers shall publish a mechanism to report bugs `[1]`_ seen with
+ an LTS branch
+#. The maintainers shall publish a versioning mechanism for the LTS branch
+
+ a. Bump minor version for any “logical” `[2]`_ fix(es) that gets merged
+
+#. The CI/CD infrastructure shall provide test support for all “live” LTS
+ branches at any given point in time
+#. The CI/CD infrastructure shall provide means to
+
+ a. notify all maintainers that a patch is ready for review
+ b. automatically cherry-pick a patch to a given LTS branch
+ c. get it through the CI/CD testing flow
+ d. gentle ping in LTS discord channel asking for reviews to ensure
+ cherry-picks are merged.
+
+FAQ
+***
+
+In our discussions, in addition to the above points we also considered some
+questions. They have been discussed on the mailing list too.
+
+| Q. What happens when a bug fix applies just to a LTS branch and not to the
+ master branch?
+| A. This will be treated as a special case and the bug, and the fix will be
+ discussed
+
+| Q. When testing a backported patch, what if one of the partners needs more
+ time while the patch fix is time-critical and, hence slowing other
+ partners?
+| A. The maintainers will add more detail to the review and merge process to
+ handle this scenario.
+
+| Q. How do we handle the increasing version numbers for errata fixes?
+| A. Too many CPU errata workarounds resulting in too many LTS releases.
+ We propose bumping the version number for each logical fix as
+ described in the section “Long term release plan” above because
+ that will help accurately track what changes have been deployed in-field.
+
+| Q. What if LTS support duration needs to be extended to longer than 5 years?
+| A. Still under discussion.
+
+These are uncharted waters, and we will face some unseen problems. When they
+become real problems, then we will have concrete data and be better able to
+address them. This means that our LTS definition as presented in this document
+is not the final one. We will constantly be discussing it and deciding how to
+adapt it as we see practical problems.
+
+.. _[1]:
+
+[1] The plan is to create a system where reviewers can tag a patch on mainline which
+gets automatically rebased on LTS and pushed to Gerrit. On seeing this patch,
+the CI/CD starts tests and provides a score. In parallel, the system also sends
+an email to the maintainers announcing the arrival of a candidate patch for the
+LTS branch.
+
+.. _[2]:
+
+[2] Logical will be a patch or patches implementing a certain fix. For example, if a
+security mitigation is fixed with the help of three patches, then all of them are
+considered as one "logical" fix. The version is incremented only after all these
+patches are merged. with the maintainers. If agreed unanimously, the bug fix
+will be merged to the affected LTS branches after completing the review process.
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 12c0f36..210ae7e 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -58,6 +58,8 @@
:|M|: Govindraj Raja <govindraj.raja@arm.com>
:|G|: `govindraj-arm`_
+.. _lts maintainers:
+
LTS Maintainers
---------------
@@ -71,6 +73,10 @@
:|G|: `vwadekar`_
:|M|: Yann Gautier <yann.gautier@st.com>
:|G|: `Yann-lms`_
+:|M|: Chris Palmer <palmer@google.com>
+:|G|: `noncombatant`_
+:|M|: Govindraj Raja <govindraj.raja@arm.com>
+:|G|: `govindraj-arm`_
.. _code owners:
@@ -1098,6 +1104,7 @@
.. _MrVan: https://github.com/MrVan
.. _Neal-liu: https://github.com/neal-liu
.. _niej: https://github.com/niej
+.. _noncombatant: https://github.com/noncombatant
.. _nmenon: https://github.com/nmenon
.. _npoushin: https://github.com/npoushin
.. _odeprez: https://github.com/odeprez
diff --git a/docs/about/release-information.rst b/docs/about/release-information.rst
index 9d6bbf6..dc2b2fd 100644
--- a/docs/about/release-information.rst
+++ b/docs/about/release-information.rst
@@ -35,7 +35,7 @@
For example, TF-A v2.10 has VERSION_MAJOR=2, VERSION_MINOR=10 and VERSION_PATCH=0.
-This VERSION_PATCH macro is only increased for LTS releases.
+This VERSION_PATCH macro is only increased for :ref:`LTS - Long-Term Support` releases.
Upcoming Releases
~~~~~~~~~~~~~~~~~
@@ -120,4 +120,4 @@
--------------
-*Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index d2d2eb5..58321e7 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -378,6 +378,16 @@
flag can take the values 0 to 2, to align with the ``ENABLE_FEAT``
mechanism. Default value is ``0``.
+- ``ENABLE_FEAT_MOPS``: Numeric value to enable FEAT_MOPS (Standardization
+ of memory operations) when INIT_UNUSED_NS_EL2=1.
+ This feature is mandatory from v8.8 and enabling of FEAT_MOPS does not
+ require any settings from EL3 as the controls are present in EL2 registers
+ (HCRX_EL2.{MSCEn,MCE2} and SCTLR_EL2.MSCEn) and in most configurations
+ we expect EL2 to be present. But in case of INIT_UNUSED_NS_EL2=1 ,
+ EL3 should configure the EL2 registers. This flag
+ can take values 0 to 2, to align with the ``ENABLE_FEAT`` mechanism.
+ Default value is ``0``.
+
- ``ENABLE_FEAT_MTE2``: Numeric value to enable Memory Tagging Extension2
if the platform wants to use this feature and MTE2 is enabled at ELX.
This flag can take values 0 to 2, to align with the ``ENABLE_FEAT``
@@ -858,6 +868,11 @@
- ``PSCI_OS_INIT_MODE``: Boolean flag to enable support for optional PSCI
OS-initiated mode. This option defaults to 0.
+- ``ARCH_FEATURE_AVAILABILITY``: Boolean flag to enable support for the
+ optional SMCCC_ARCH_FEATURE_AVAILABILITY call. This option implicitly
+ interacts with IMPDEF_SYSREG_TRAP and software emulation. This option
+ defaults to 0.
+
- ``ENABLE_FEAT_RAS``: Boolean flag to enable Armv8.2 RAS features. RAS features
are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2
or later CPUs. This flag can take the values 0 or 1. The default value is 0.
diff --git a/docs/glossary.rst b/docs/glossary.rst
index f19897c..20ad21c 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -130,6 +130,9 @@
Memory Tagging Extension. An optional Armv8.5 extension that enables
hardware-assisted memory tagging.
+ LTS
+ Long-Term Support
+
OEN
Owning Entity Number
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 5cb20fd..6d03f44 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2454,7 +2454,7 @@
The value should be obtained from a reliable source of randomness.
This function is only needed if ARMv8.3 pointer authentication is used in the
-Trusted Firmware by building with ``BRANCH_PROTECTION`` option set to non-zero.
+Trusted Firmware by building with ``BRANCH_PROTECTION`` option set to 1, 2 or 3.
Function : plat_get_syscnt_freq2() [mandatory]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -3553,7 +3553,10 @@
This function is invoked by BL31's exception handler when there is a synchronous
system register trap caused by access to the implementation defined registers.
It allows platforms enabling ``IMPDEF_SYSREG_TRAP`` to emulate those system
-registers choosing to program bits of their choice.
+registers choosing to program bits of their choice. If using in combination with
+``ARCH_FEATURE_AVAILABILITY``, the macros
+{SCR,MDCR,CPTR}_PLAT_{BITS,IGNORED,FLIPPED} should be defined to report correct
+results.
The first parameter (``uint64_t esr_el3``) contains the content of the ESR_EL3
syndrome register, which encodes the instruction that was trapped.
diff --git a/docs/resources/diagrams/lts-timeline-example.png b/docs/resources/diagrams/lts-timeline-example.png
new file mode 100644
index 0000000..edb1145
--- /dev/null
+++ b/docs/resources/diagrams/lts-timeline-example.png
Binary files differ
diff --git a/drivers/arm/css/scp/css_pm_scmi.c b/drivers/arm/css/scp/css_pm_scmi.c
index 9fe8b37..fbcbdc7 100644
--- a/drivers/arm/css/scp/css_pm_scmi.c
+++ b/drivers/arm/css/scp/css_pm_scmi.c
@@ -312,7 +312,7 @@
/*
* Send powerdown request to online secondary core(s)
*/
- ret = psci_stop_other_cores(0, css_raise_pwr_down_interrupt);
+ ret = psci_stop_other_cores(plat_my_core_pos(), 0, css_raise_pwr_down_interrupt);
if (ret != PSCI_E_SUCCESS) {
ERROR("Failed to powerdown secondary core(s)\n");
}
diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c
index ef04c4d..adca4fd 100644
--- a/drivers/arm/smmu/smmu_v3.c
+++ b/drivers/arm/smmu/smmu_v3.c
@@ -124,22 +124,35 @@
gptbr_el3 << 12);
/*
- * ACCESSEN=1: SMMU- and client-originated accesses are
- * not terminated by this mechanism.
* GPCEN=1: All clients and SMMU-originated accesses,
* except GPT-walks, are subject to GPC.
+ *
+ * It is recommended to set GPCEN and wait for completion
+ * prior to setting ACCESSEN.
+ */
+ mmio_setbits_32(smmu_base + SMMU_ROOT_CR0,
+ SMMU_ROOT_CR0_GPCEN);
+
+ /* Poll for GPCEN ack bit. */
+ if (smmuv3_poll(smmu_base + SMMU_ROOT_CR0ACK,
+ SMMU_ROOT_CR0_GPCEN,
+ SMMU_ROOT_CR0_GPCEN) != 0) {
+ WARN("Failed enabling SMMU GPC.\n");
+ }
+
+ /*
+ * ACCESSEN=1: SMMU- and client-originated accesses are
+ * not terminated by this mechanism.
*/
mmio_setbits_32(smmu_base + SMMU_ROOT_CR0,
SMMU_ROOT_CR0_GPCEN |
SMMU_ROOT_CR0_ACCESSEN);
- /* Poll for ACCESSEN and GPCEN ack bits. */
+ /* Poll for ACCESSEN ack bit. */
if (smmuv3_poll(smmu_base + SMMU_ROOT_CR0ACK,
- SMMU_ROOT_CR0_GPCEN |
SMMU_ROOT_CR0_ACCESSEN,
- SMMU_ROOT_CR0_GPCEN |
SMMU_ROOT_CR0_ACCESSEN) != 0) {
- WARN("Failed enabling SMMU GPC.\n");
+ WARN("Failed enabling SMMU ACCESS.\n");
/*
* Do not return in error, but fall back to
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
index 9b57607..235b988 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
@@ -7,6 +7,7 @@
#include <common/debug.h>
#include <drivers/clk.h>
#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
#include <s32cc-clk-ids.h>
#include <s32cc-clk-modules.h>
#include <s32cc-clk-regs.h>
@@ -1464,7 +1465,39 @@
return 0;
}
-void s32cc_clk_register_drv(void)
+static int s32cc_clk_mmap_regs(const struct s32cc_clk_drv *drv)
+{
+ const uintptr_t base_addrs[11] = {
+ drv->fxosc_base,
+ drv->armpll_base,
+ drv->periphpll_base,
+ drv->armdfs_base,
+ drv->cgm0_base,
+ drv->cgm1_base,
+ drv->cgm5_base,
+ drv->ddrpll_base,
+ drv->mc_me,
+ drv->mc_rgm,
+ drv->rdc,
+ };
+ size_t i;
+ int ret;
+
+ for (i = 0U; i < ARRAY_SIZE(base_addrs); i++) {
+ ret = mmap_add_dynamic_region(base_addrs[i], base_addrs[i],
+ PAGE_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ if (ret != 0) {
+ ERROR("Failed to map clock module 0x%" PRIuPTR "\n",
+ base_addrs[i]);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int s32cc_clk_register_drv(bool mmap_regs)
{
static const struct clk_ops s32cc_clk_ops = {
.enable = s32cc_clk_enable,
@@ -1475,7 +1508,19 @@
.get_parent = s32cc_clk_get_parent,
.set_parent = s32cc_clk_set_parent,
};
+ const struct s32cc_clk_drv *drv;
clk_register(&s32cc_clk_ops);
+
+ drv = get_drv();
+ if (drv == NULL) {
+ return -EINVAL;
+ }
+
+ if (mmap_regs) {
+ return s32cc_clk_mmap_regs(drv);
+ }
+
+ return 0;
}
diff --git a/drivers/nxp/clk/s32cc/s32cc_early_clks.c b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
index 02b9df9..f001568 100644
--- a/drivers/nxp/clk/s32cc/s32cc_early_clks.c
+++ b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
@@ -180,11 +180,14 @@
return ret;
}
-int s32cc_init_early_clks(void)
+int s32cc_init_core_clocks(void)
{
int ret;
- s32cc_clk_register_drv();
+ ret = s32cc_clk_register_drv(false);
+ if (ret != 0) {
+ return ret;
+ }
ret = setup_fxosc();
if (ret != 0) {
@@ -206,6 +209,18 @@
return ret;
}
+ return ret;
+}
+
+int s32cc_init_early_clks(void)
+{
+ int ret;
+
+ ret = s32cc_clk_register_drv(true);
+ if (ret != 0) {
+ return ret;
+ }
+
ret = setup_periph_pll();
if (ret != 0) {
return ret;
diff --git a/fdts/tc-base.dtsi b/fdts/tc-base.dtsi
index e898399..691a3b8 100644
--- a/fdts/tc-base.dtsi
+++ b/fdts/tc-base.dtsi
@@ -387,7 +387,7 @@
soc_uartclk: uartclk {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <UARTCLK_FREQ>;
+ clock-frequency = <TC_UARTCLK>;
clock-output-names = "uartclk";
};
diff --git a/fdts/tc-fpga.dtsi b/fdts/tc-fpga.dtsi
index af140bb..a3feacc 100644
--- a/fdts/tc-fpga.dtsi
+++ b/fdts/tc-fpga.dtsi
@@ -25,7 +25,7 @@
stdout-path = "serial0:38400n8";
};
-#if TC_FPGA_ANDROID_IMG_IN_RAM
+#if TC_FPGA_FS_IMG_IN_RAM
reserved-memory {
phram@0x880000000 {
/*
@@ -36,7 +36,7 @@
no-map;
};
};
-#endif /* TC_FPGA_ANDROID_IMG_IN_RAM */
+#endif /* TC_FPGA_FS_IMG_IN_RAM */
ethernet: ethernet@ETHERNET_ADDR {
compatible = "smsc,lan9115";
diff --git a/fdts/tc2.dts b/fdts/tc2.dts
index c492274..003efdc 100644
--- a/fdts/tc2.dts
+++ b/fdts/tc2.dts
@@ -36,7 +36,6 @@
#define BIG_CPU_PMU_COMPATIBLE "arm,cortex-x4-pmu"
#define MPAM_ADDR 0x1 0x00010000 /* 0x1_0001_0000 */
-#define UARTCLK_FREQ 5000000
#define DPU_ADDR 2cc00000
#define DPU_IRQ 69
diff --git a/fdts/tc3-4-base.dtsi b/fdts/tc3-4-base.dtsi
index c7f3084..049a4c6 100644
--- a/fdts/tc3-4-base.dtsi
+++ b/fdts/tc3-4-base.dtsi
@@ -18,15 +18,12 @@
#define MHU_RX_INT_NAME "combined"
#define MPAM_ADDR 0x0 0x5f010000 /* 0x5f01_0000 */
-#define UARTCLK_FREQ 3750000
#if TARGET_FLAVOUR_FVP
#define DPU_ADDR 4000000000
#define DPU_IRQ 579
-#elif TARGET_FLAVOUR_FPGA
-#define DPU_ADDR 2cc00000
-#define DPU_IRQ 69
#endif
+
#include "tc-base.dtsi"
/ {
diff --git a/fdts/tc3.dts b/fdts/tc3.dts
index b8fe587..22d4d10 100644
--- a/fdts/tc3.dts
+++ b/fdts/tc3.dts
@@ -40,6 +40,11 @@
#define VIRTIO_BLOCK_ADDR 1c130000
#define VIRTIO_BLOCK_INT 204
+#if TARGET_FLAVOUR_FPGA
+#define DPU_ADDR 2cc00000
+#define DPU_IRQ 69
+#endif
+
#include "tc-common.dtsi"
#if TARGET_FLAVOUR_FVP
#include "tc-fvp.dtsi"
diff --git a/fdts/tc4.dts b/fdts/tc4.dts
index 5ab58d5..98cfea1 100644
--- a/fdts/tc4.dts
+++ b/fdts/tc4.dts
@@ -20,14 +20,21 @@
#define RSE_MHU_TX_ADDR 49020000 /* hex */
#define RSE_MHU_RX_ADDR 49030000 /* hex */
+#if TARGET_FLAVOUR_FVP
#define ETHERNET_ADDR 64000000
#define ETHERNET_INT 799
-
#define SYS_REGS_ADDR 60080000
-
#define MMC_ADDR 600b0000
#define MMC_INT_0 778
#define MMC_INT_1 779
+#else /* TARGET_FLAVOUR_FPGA */
+#define ETHERNET_ADDR 18000000
+#define ETHERNET_INT 109
+#define SYS_REGS_ADDR 1c010000
+#define MMC_ADDR 1c050000
+#define MMC_INT_0 107
+#define MMC_INT_1 108
+#endif /* TARGET_FLAVOUR_FVP */
#define RTC_ADDR 600a0000
#define RTC_INT 777
@@ -40,6 +47,11 @@
#define VIRTIO_BLOCK_ADDR 60020000
#define VIRTIO_BLOCK_INT 769
+#if TARGET_FLAVOUR_FPGA
+#define DPU_ADDR 4000000000
+#define DPU_IRQ 579
+#endif
+
#include "tc-common.dtsi"
#if TARGET_FLAVOUR_FVP
#include "tc-fvp.dtsi"
@@ -65,7 +77,8 @@
gpu: gpu@2d000000 {
interrupts = <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "IRQAW";
- iommus = <&smmu_700 0x200>;
+ iommus = <&smmu_700 0x0>;
+ system-coherency = <0x0>;
};
dsu-pmu {
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 3a7e2eb..4d26153 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -317,6 +317,10 @@
/* ID_AA64ISAR2_EL1 definitions */
#define ID_AA64ISAR2_EL1 S3_0_C0_C6_2
+#define ID_AA64ISAR2_EL1_MOPS_SHIFT U(16)
+#define ID_AA64ISAR2_EL1_MOPS_MASK ULL(0xf)
+
+#define MOPS_IMPLEMENTED ULL(0x1)
/* ID_AA64PFR2_EL1 definitions */
#define ID_AA64PFR2_EL1 S3_0_C0_C4_2
@@ -654,15 +658,18 @@
/* MDCR_EL3 definitions */
#define MDCR_EBWE_BIT (ULL(1) << 43)
-#define MDCR_E3BREC (ULL(1) << 38)
-#define MDCR_E3BREW (ULL(1) << 37)
+#define MDCR_E3BREC_BIT (ULL(1) << 38)
+#define MDCR_E3BREW_BIT (ULL(1) << 37)
#define MDCR_EnPMSN_BIT (ULL(1) << 36)
#define MDCR_MPMX_BIT (ULL(1) << 35)
#define MDCR_MCCD_BIT (ULL(1) << 34)
#define MDCR_SBRBE_SHIFT U(32)
-#define MDCR_SBRBE_MASK ULL(0x3)
+#define MDCR_SBRBE(x) ((x) << MDCR_SBRBE_SHIFT)
+#define MDCR_SBRBE_ALL ULL(0x3)
+#define MDCR_SBRBE_NS ULL(0x1)
#define MDCR_NSTB(x) ((x) << 24)
#define MDCR_NSTB_EL1 ULL(0x3)
+#define MDCR_NSTB_EL3 ULL(0x2)
#define MDCR_NSTBE_BIT (ULL(1) << 26)
#define MDCR_MTPME_BIT (ULL(1) << 28)
#define MDCR_TDCC_BIT (ULL(1) << 27)
@@ -679,6 +686,7 @@
#define MDCR_SPD32_ENABLE ULL(0x3)
#define MDCR_NSPB(x) ((x) << 12)
#define MDCR_NSPB_EL1 ULL(0x3)
+#define MDCR_NSPB_EL3 ULL(0x2)
#define MDCR_NSPBE_BIT (ULL(1) << 11)
#define MDCR_TDOSA_BIT (ULL(1) << 10)
#define MDCR_TDA_BIT (ULL(1) << 9)
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 8bdc13c..1d0a2e0 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -144,6 +144,8 @@
* +----------------------------+
* | FEAT_FPMR |
* +----------------------------+
+ * | FEAT_MOPS |
+ * +----------------------------+
*/
__attribute__((always_inline))
@@ -290,7 +292,10 @@
CREATE_FEATURE_FUNCS(feat_fpmr, id_aa64pfr2_el1, ID_AA64PFR2_EL1_FPMR_SHIFT,
ID_AA64PFR2_EL1_FPMR_MASK, FPMR_IMPLEMENTED,
ENABLE_FEAT_FPMR)
-
+/* FEAT_MOPS */
+CREATE_FEATURE_FUNCS(feat_mops, id_aa64isar2_el1, ID_AA64ISAR2_EL1_MOPS_SHIFT,
+ ID_AA64ISAR2_EL1_MOPS_MASK, MOPS_IMPLEMENTED,
+ ENABLE_FEAT_MOPS)
__attribute__((always_inline))
static inline bool is_feat_sxpie_supported(void)
@@ -353,8 +358,8 @@
ID_AA64MMFR1_EL1_HCX_MASK, 1U, ENABLE_FEAT_HCX)
/* FEAT_RNG_TRAP: Trapping support */
-CREATE_FEATURE_PRESENT(feat_rng_trap, id_aa64pfr1_el1, ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT,
- ID_AA64PFR1_EL1_RNDR_TRAP_MASK, RNG_TRAP_IMPLEMENTED)
+CREATE_FEATURE_FUNCS(feat_rng_trap, id_aa64pfr1_el1, ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT,
+ ID_AA64PFR1_EL1_RNDR_TRAP_MASK, RNG_TRAP_IMPLEMENTED, ENABLE_FEAT_RNG_TRAP)
/* Return the RME version, zero if not supported. */
CREATE_FEATURE_FUNCS(feat_rme, id_aa64pfr0_el1, ID_AA64PFR0_FEAT_RME_SHIFT,
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-drv.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-drv.h
index d879f5b..632b82f 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-drv.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-drv.h
@@ -6,6 +6,7 @@
#ifndef S32CC_CLK_DRV_H
#define S32CC_CLK_DRV_H
+int s32cc_init_core_clocks(void);
int s32cc_init_early_clks(void);
#endif
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-utils.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-utils.h
index e6adecc..c6e90f0 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-utils.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-utils.h
@@ -5,6 +5,7 @@
#ifndef S32CC_CLK_UTILS_H
#define S32CC_CLK_UTILS_H
+#include <stdbool.h>
#include <s32cc-clk-modules.h>
struct s32cc_clk *s32cc_get_clk_from_table(const struct s32cc_clk_array *const *clk_arr,
@@ -18,6 +19,6 @@
struct s32cc_clk *s32cc_get_arch_clk(unsigned long id);
int s32cc_get_clk_id(const struct s32cc_clk *clk, unsigned long *id);
-void s32cc_clk_register_drv(void);
+int s32cc_clk_register_drv(bool mmap_regs);
#endif /* S32CC_CLK_UTILS_H */
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index c40f955..f12a4d6 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -302,7 +302,7 @@
/*
* Highest power level which takes part in a power management
- * operation.
+ * operation. May be lower while the core is in suspend state.
*/
unsigned int target_pwrlvl;
diff --git a/include/lib/psci/psci_lib.h b/include/lib/psci/psci_lib.h
index c50f8cb..9950a6e 100644
--- a/include/lib/psci/psci_lib.h
+++ b/include/lib/psci/psci_lib.h
@@ -89,10 +89,10 @@
void psci_register_spd_pm_hook(const spd_pm_ops_t *pm);
void psci_prepare_next_non_secure_ctx(
entry_point_info_t *next_image_info);
-int psci_stop_other_cores(unsigned int wait_ms,
+int psci_stop_other_cores(unsigned int this_cpu_idx, unsigned int wait_ms,
void (*stop_func)(u_register_t mpidr));
-bool psci_is_last_on_cpu_safe(void);
-bool psci_are_all_cpus_on_safe(void);
+bool psci_is_last_on_cpu_safe(unsigned int this_core);
+bool psci_are_all_cpus_on_safe(unsigned int this_core);
void psci_pwrdown_cpu(unsigned int power_level);
void psci_do_manage_extensions(void);
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
index 7b66a5e..bcf9fc9 100644
--- a/include/lib/transfer_list.h
+++ b/include/lib/transfer_list.h
@@ -56,6 +56,7 @@
TL_TAG_HOB_BLOCK = 2,
TL_TAG_HOB_LIST = 3,
TL_TAG_ACPI_TABLE_AGGREGATE = 4,
+ TL_TAG_TPM_EVLOG = 5,
TL_TAG_OPTEE_PAGABLE_PART = 0x100,
TL_TAG_DT_SPMC_MANIFEST = 0x101,
TL_TAG_EXEC_EP_INFO64 = 0x102,
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 118b537..b43f131 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -299,6 +299,16 @@
#if (MEASURED_BOOT || DICE_PROTECTION_ENVIRONMENT)
void bl2_plat_mboot_init(void);
void bl2_plat_mboot_finish(void);
+#if TRANSFER_LIST
+int plat_handoff_mboot(const void *data, uint32_t data_size, void *tl_base);
+#else
+static inline int
+plat_handoff_mboot(__unused const void *data, __unused uint32_t data_size,
+ __unused void *tl_base)
+{
+ return -1;
+}
+#endif
#else
static inline void bl2_plat_mboot_init(void)
{
diff --git a/include/services/arm_arch_svc.h b/include/services/arm_arch_svc.h
index 645b388..c2b1f41 100644
--- a/include/services/arm_arch_svc.h
+++ b/include/services/arm_arch_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,8 +13,310 @@
#define SMCCC_ARCH_WORKAROUND_1 U(0x80008000)
#define SMCCC_ARCH_WORKAROUND_2 U(0x80007FFF)
#define SMCCC_ARCH_WORKAROUND_3 U(0x80003FFF)
+#define SMCCC_ARCH_FEATURE_AVAILABILITY U(0x80000003)
#define SMCCC_GET_SOC_VERSION U(0)
#define SMCCC_GET_SOC_REVISION U(1)
+#ifndef __ASSEMBLER__
+#if ARCH_FEATURE_AVAILABILITY
+#include <lib/cassert.h>
+
+#if ENABLE_FEAT_FGT2
+#define SCR_FEAT_FGT2 SCR_FGTEN2_BIT
+#else
+#define SCR_FEAT_FGT2 (0)
+#endif
+
+#if ENABLE_FEAT_FPMR
+#define SCR_FEAT_FPMR SCR_EnFPM_BIT
+#else
+#define SCR_FEAT_FPMR
+#endif
+
+#if ENABLE_FEAT_D128
+#define SCR_FEAT_D128 SCR_D128En_BIT
+#else
+#define SCR_FEAT_D128 (0)
+#endif
+
+#if ENABLE_FEAT_S1PIE
+#define SCR_FEAT_S1PIE SCR_PIEN_BIT
+#else
+#define SCR_FEAT_S1PIE (0)
+#endif
+
+#if ENABLE_FEAT_SCTLR2
+#define SCR_FEAT_SCTLR2 SCR_SCTLR2En_BIT
+#else
+#define SCR_FEAT_SCTLR2 (0)
+#endif
+
+#if ENABLE_FEAT_TCR2
+#define SCR_FEAT_TCR2 SCR_TCR2EN_BIT
+#else
+#define SCR_FEAT_TCR2 (0)
+#endif
+
+#if ENABLE_FEAT_THE
+#define SCR_FEAT_THE SCR_RCWMASKEn_BIT
+#else
+#define SCR_FEAT_THE (0)
+#endif
+
+#if ENABLE_SME_FOR_NS
+#define SCR_FEAT_SME SCR_ENTP2_BIT
+#else
+#define SCR_FEAT_SME (0)
+#endif
+
+#if ENABLE_FEAT_GCS
+#define SCR_FEAT_GCS SCR_GCSEn_BIT
+#else
+#define SCR_FEAT_GCS (0)
+#endif
+
+#if ENABLE_FEAT_HCX
+#define SCR_FEAT_HCX SCR_HXEn_BIT
+#else
+#define SCR_FEAT_HCX (0)
+#endif
+
+#if ENABLE_FEAT_LS64_ACCDATA
+#define SCR_FEAT_LS64_ACCDATA (SCR_ADEn_BIT | SCR_EnAS0_BIT)
+#else
+#define SCR_FEAT_LS64_ACCDATA (0)
+#endif
+
+#if ENABLE_FEAT_AMUv1p1
+#define SCR_FEAT_AMUv1p1 SCR_AMVOFFEN_BIT
+#else
+#define SCR_FEAT_AMUv1p1 (0)
+#endif
+
+#if ENABLE_FEAT_ECV
+#define SCR_FEAT_ECV SCR_ECVEN_BIT
+#else
+#define SCR_FEAT_ECV (0)
+#endif
+
+#if ENABLE_FEAT_FGT
+#define SCR_FEAT_FGT SCR_FGTEN_BIT
+#else
+#define SCR_FEAT_FGT (0)
+#endif
+
+#if ENABLE_FEAT_MTE2
+#define SCR_FEAT_MTE2 SCR_ATA_BIT
+#else
+#define SCR_FEAT_MTE2 (0)
+#endif
+
+#if ENABLE_FEAT_CSV2_2
+#define SCR_FEAT_CSV2_2 SCR_EnSCXT_BIT
+#else
+#define SCR_FEAT_CSV2_2 (0)
+#endif
+
+#if ENABLE_FEAT_RAS
+#define SCR_FEAT_RAS SCR_TERR_BIT
+#else
+#define SCR_FEAT_RAS (0)
+#endif
+
+#ifndef SCR_PLAT_FEATS
+#define SCR_PLAT_FEATS (0)
+#endif
+#ifndef SCR_PLAT_FLIPPED
+#define SCR_PLAT_FLIPPED (0)
+#endif
+#ifndef SCR_PLAT_IGNORED
+#define SCR_PLAT_IGNORED (0)
+#endif
+
+#ifndef CPTR_PLAT_FEATS
+#define CPTR_PLAT_FEATS (0)
+#endif
+#ifndef CPTR_PLAT_FLIPPED
+#define CPTR_PLAT_FLIPPED (0)
+#endif
+
+#ifndef MDCR_PLAT_FEATS
+#define MDCR_PLAT_FEATS (0)
+#endif
+#ifndef MDCR_PLAT_FLIPPED
+#define MDCR_PLAT_FLIPPED (0)
+#endif
+#ifndef MDCR_PLAT_IGNORED
+#define MDCR_PLAT_IGNORED (0)
+#endif
+/*
+ * XYZ_EL3_FEATS - list all bits that are relevant for feature enablement. It's
+ * a constant list based on what features are expected. This relies on the fact
+ * that if the feature is in any way disabled, then the relevant bit will not be
+ * written by context management.
+ *
+ * XYZ_EL3_FLIPPED - bits with an active 0, rather than the usual active 1. The
+ * spec always uses active 1 to mean that the feature will not trap.
+ *
+ * XYZ_EL3_IGNORED - list of all bits that are not relevant for feature
+ * enablement and should not be reported to lower ELs
+ */
+#define SCR_EL3_FEATS ( \
+ SCR_FEAT_FGT2 | \
+ SCR_FEAT_FPMR | \
+ SCR_FEAT_D128 | \
+ SCR_FEAT_S1PIE | \
+ SCR_FEAT_SCTLR2 | \
+ SCR_FEAT_TCR2 | \
+ SCR_FEAT_THE | \
+ SCR_FEAT_SME | \
+ SCR_FEAT_GCS | \
+ SCR_FEAT_HCX | \
+ SCR_FEAT_LS64_ACCDATA | \
+ SCR_FEAT_AMUv1p1 | \
+ SCR_FEAT_ECV | \
+ SCR_FEAT_FGT | \
+ SCR_FEAT_MTE2 | \
+ SCR_FEAT_CSV2_2 | \
+ SCR_APK_BIT | /* FEAT_Pauth */ \
+ SCR_FEAT_RAS | \
+ SCR_PLAT_FEATS)
+#define SCR_EL3_FLIPPED ( \
+ SCR_FEAT_RAS | \
+ SCR_PLAT_FLIPPED)
+#define SCR_EL3_IGNORED ( \
+ SCR_API_BIT | \
+ SCR_RW_BIT | \
+ SCR_SIF_BIT | \
+ SCR_HCE_BIT | \
+ SCR_FIQ_BIT | \
+ SCR_IRQ_BIT | \
+ SCR_NS_BIT | \
+ SCR_RES1_BITS | \
+ SCR_PLAT_IGNORED)
+CASSERT((SCR_EL3_FEATS & SCR_EL3_IGNORED) == 0, scr_feat_is_ignored);
+CASSERT((SCR_EL3_FLIPPED & SCR_EL3_FEATS) == SCR_EL3_FLIPPED, scr_flipped_not_a_feat);
+
+#if ENABLE_SYS_REG_TRACE_FOR_NS
+#define CPTR_SYS_REG_TRACE (TCPAC_BIT | TTA_BIT)
+#else
+#define CPTR_SYS_REG_TRACE (0)
+#endif
+
+#if ENABLE_FEAT_AMU
+#define CPTR_FEAT_AMU TAM_BIT
+#else
+#define CPTR_FEAT_AMU (0)
+#endif
+
+#if ENABLE_SME_FOR_NS
+#define CPTR_FEAT_SME ESM_BIT
+#else
+#define CPTR_FEAT_SME (0)
+#endif
+
+#if ENABLE_SVE_FOR_NS
+#define CPTR_FEAT_SVE CPTR_EZ_BIT
+#else
+#define CPTR_FEAT_SVE (0)
+#endif
+
+#define CPTR_EL3_FEATS ( \
+ CPTR_SYS_REG_TRACE | \
+ CPTR_FEAT_AMU | \
+ CPTR_FEAT_SME | \
+ TFP_BIT | \
+ CPTR_FEAT_SVE | \
+ CPTR_PLAT_FEATS)
+#define CPTR_EL3_FLIPPED ( \
+ CPTR_SYS_REG_TRACE | \
+ CPTR_FEAT_AMU | \
+ TFP_BIT | \
+ CPTR_PLAT_FLIPPED)
+CASSERT((CPTR_EL3_FLIPPED & CPTR_EL3_FEATS) == CPTR_EL3_FLIPPED, cptr_flipped_not_a_feat);
+
+/*
+ * Some features enables are expressed with more than 1 bit in order to cater
+ * for multi world enablement. In those cases (BRB, TRB, SPE) only the last bit
+ * is used and reported. This (ab)uses the convenient fact that the last bit
+ * always means "enabled for this world" when context switched correctly.
+ * The per-world values have been adjusted such that this is always true.
+ */
+#if ENABLE_BRBE_FOR_NS
+#define MDCR_FEAT_BRBE MDCR_SBRBE(1UL)
+#else
+#define MDCR_FEAT_BRBE (0)
+#endif
+
+#if ENABLE_FEAT_FGT
+#define MDCR_FEAT_FGT MDCR_TDCC_BIT
+#else
+#define MDCR_FEAT_FGT (0)
+#endif
+
+#if ENABLE_TRBE_FOR_NS
+#define MDCR_FEAT_TRBE MDCR_NSTB(1UL)
+#else
+#define MDCR_FEAT_TRBE (0)
+#endif
+
+#if ENABLE_TRF_FOR_NS
+#define MDCR_FEAT_TRF MDCR_TTRF_BIT
+#else
+#define MDCR_FEAT_TRF (0)
+#endif
+
+#if ENABLE_SPE_FOR_NS
+#define MDCR_FEAT_SPE MDCR_NSPB(1UL)
+#else
+#define MDCR_FEAT_SPE (0)
+#endif
+
+#define MDCR_EL3_FEATS ( \
+ MDCR_FEAT_BRBE | \
+ MDCR_FEAT_FGT | \
+ MDCR_FEAT_TRBE | \
+ MDCR_FEAT_TRF | \
+ MDCR_FEAT_SPE | \
+ MDCR_TDOSA_BIT | \
+ MDCR_TDA_BIT | \
+ MDCR_TPM_BIT | /* FEAT_PMUv3 */ \
+ MDCR_PLAT_FEATS)
+#define MDCR_EL3_FLIPPED ( \
+ MDCR_FEAT_FGT | \
+ MDCR_FEAT_TRF | \
+ MDCR_TDOSA_BIT | \
+ MDCR_TDA_BIT | \
+ MDCR_TPM_BIT | \
+ MDCR_PLAT_FLIPPED)
+#define MDCR_EL3_IGNORED ( \
+ MDCR_EBWE_BIT | \
+ MDCR_EnPMSN_BIT | \
+ MDCR_SBRBE(2UL) | \
+ MDCR_MTPME_BIT | \
+ MDCR_NSTBE_BIT | \
+ MDCR_NSTB(2UL) | \
+ MDCR_SDD_BIT | \
+ MDCR_SPD32(3UL) | \
+ MDCR_NSPB(2UL) | \
+ MDCR_NSPBE_BIT | \
+ MDCR_PLAT_IGNORED)
+CASSERT((MDCR_EL3_FEATS & MDCR_EL3_IGNORED) == 0, mdcr_feat_is_ignored);
+CASSERT((MDCR_EL3_FLIPPED & MDCR_EL3_FEATS) == MDCR_EL3_FLIPPED, mdcr_flipped_not_a_feat);
+
+#define MPAM3_EL3_FEATS (MPAM3_EL3_TRAPLOWER_BIT)
+#define MPAM3_EL3_FLIPPED (MPAM3_EL3_TRAPLOWER_BIT)
+#define MPAM3_EL3_IGNORED (MPAM3_EL3_MPAMEN_BIT)
+CASSERT((MPAM3_EL3_FEATS & MPAM3_EL3_IGNORED) == 0, mpam3_feat_is_ignored);
+CASSERT((MPAM3_EL3_FLIPPED & MPAM3_EL3_FEATS) == MPAM3_EL3_FLIPPED, mpam3_flipped_not_a_feat);
+
+/* The hex representations of these registers' S3 encoding */
+#define SCR_EL3_OPCODE U(0x1E1100)
+#define CPTR_EL3_OPCODE U(0x1E1140)
+#define MDCR_EL3_OPCODE U(0x1E1320)
+#define MPAM3_EL3_OPCODE U(0x1EA500)
+
+#endif /* ARCH_FEATURE_AVAILABILITY */
+#endif /* __ASSEMBLER__ */
#endif /* ARM_ARCH_SVC_H */
diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h
index 01dbea9..f5a9a2d 100644
--- a/include/services/ffa_svc.h
+++ b/include/services/ffa_svc.h
@@ -173,8 +173,8 @@
#define FFA_SPM_ID_GET FFA_FID(SMC_32, FFA_FNUM_SPM_ID_GET)
#define FFA_NORMAL_WORLD_RESUME FFA_FID(SMC_32, FFA_FNUM_NORMAL_WORLD_RESUME)
#define FFA_EL3_INTR_HANDLE FFA_FID(SMC_32, FFA_FNUM_EL3_INTR_HANDLE)
-#define FFA_MEM_PERM_GET FFA_FID(SMC_32, FFA_FNUM_MEM_PERM_GET)
-#define FFA_MEM_PERM_SET FFA_FID(SMC_32, FFA_FNUM_MEM_PERM_SET)
+#define FFA_MEM_PERM_GET_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_PERM_GET)
+#define FFA_MEM_PERM_SET_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_PERM_SET)
#define FFA_CONSOLE_LOG_SMC32 FFA_FID(SMC_32, FFA_FNUM_CONSOLE_LOG)
/* FFA SMC64 FIDs */
@@ -201,6 +201,8 @@
FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_REQ2)
#define FFA_MSG_SEND_DIRECT_RESP2_SMC64 \
FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_RESP2)
+#define FFA_MEM_PERM_GET_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_PERM_GET)
+#define FFA_MEM_PERM_SET_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_PERM_SET)
/*
* FF-A partition properties values.
@@ -208,6 +210,8 @@
#define FFA_PARTITION_DIRECT_REQ_RECV U(1 << 0)
#define FFA_PARTITION_DIRECT_REQ_SEND U(1 << 1)
#define FFA_PARTITION_INDIRECT_MSG U(1 << 2)
+#define FFA_PARTITION_DIRECT_REQ2_RECV U(1 << 9)
+#define FFA_PARTITION_DIRECT_REQ2_SEND U(1 << 10)
/*
* Reserve a special value for traffic targeted to the Hypervisor or SPM.
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index ca5e047..9b97685 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -49,7 +49,6 @@
per_world_context_t per_world_context[CPU_DATA_CONTEXT_NUM];
static bool has_secure_perworld_init;
-static void manage_extensions_common(cpu_context_t *ctx);
static void manage_extensions_nonsecure(cpu_context_t *ctx);
static void manage_extensions_secure(cpu_context_t *ctx);
static void manage_extensions_secure_per_world(void);
@@ -236,8 +235,9 @@
* SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
* than EL3
*/
- scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
-
+ if (is_armv8_3_pauth_present()) {
+ scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+ }
#endif /* CTX_INCLUDE_PAUTH_REGS */
#if HANDLE_EA_EL3_FIRST_NS
@@ -251,7 +251,6 @@
* and RAS ERX registers from EL1 and EL2(from any security state)
* are trapped to EL3.
* Set here to trap only for NS EL1/EL2
- *
*/
scr_el3 |= SCR_TERR_BIT;
#endif
@@ -447,9 +446,9 @@
* If FEAT_RNG_TRAP is enabled, all reads of the RNDR and RNDRRS
* registers are trapped to EL3.
*/
-#if ENABLE_FEAT_RNG_TRAP
- scr_el3 |= SCR_TRNDR_BIT;
-#endif
+ if (is_feat_rng_trap_supported()) {
+ scr_el3 |= SCR_TRNDR_BIT;
+ }
#if FAULT_INJECTION_SUPPORT
/* Enable fault injection from lower ELs */
@@ -466,7 +465,9 @@
* SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
* than EL3
*/
- scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+ if (is_armv8_3_pauth_present()) {
+ scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+ }
#endif /* CTX_INCLUDE_PAUTH_REGS */
/*
@@ -567,11 +568,12 @@
& ~(MDCR_TDA_BIT | MDCR_TDOSA_BIT)) ;
write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3);
- /*
- * Configure MDCR_EL3 register as applicable for each world
- * (NS/Secure/Realm) context.
- */
- manage_extensions_common(ctx);
+#if IMAGE_BL31
+ /* Enable FEAT_TRF for Non-Secure and prohibit for Secure state. */
+ if (is_feat_trf_supported()) {
+ trf_enable(ctx);
+ }
+#endif /* IMAGE_BL31 */
/*
* Store the X0-X7 value from the entrypoint into the context
@@ -781,41 +783,6 @@
}
/*******************************************************************************
- * Enable architecture extensions on first entry to Non-secure world only
- * and disable for secure world.
- *
- * NOTE: Arch features which have been provided with the capability of getting
- * enabled only for non-secure world and being disabled for secure world are
- * grouped here, as the MDCR_EL3 context value remains same across the worlds.
- ******************************************************************************/
-static void manage_extensions_common(cpu_context_t *ctx)
-{
-#if IMAGE_BL31
- if (is_feat_spe_supported()) {
- /*
- * Enable FEAT_SPE for Non-Secure and prohibit for Secure state.
- */
- spe_enable(ctx);
- }
-
- if (is_feat_trbe_supported()) {
- /*
- * Enable FEAT_TRBE for Non-Secure and prohibit for Secure and
- * Realm state.
- */
- trbe_enable(ctx);
- }
-
- if (is_feat_trf_supported()) {
- /*
- * Enable FEAT_TRF for Non-Secure and prohibit for Secure state.
- */
- trf_enable(ctx);
- }
-#endif /* IMAGE_BL31 */
-}
-
-/*******************************************************************************
* Enable architecture extensions on first entry to Non-secure world.
******************************************************************************/
static void manage_extensions_nonsecure(cpu_context_t *ctx)
@@ -837,6 +804,21 @@
debugv8p9_extended_bp_wp_enable(ctx);
}
+ /*
+ * SPE, TRBE, and BRBE have multi-field enables that affect which world
+ * they apply to. Despite this, it is useful to ignore these for
+ * simplicity in determining the feature's per world enablement status.
+ * This is only possible when context is written per-world. Relied on
+ * by SMCCC_ARCH_FEATURE_AVAILABILITY
+ */
+ if (is_feat_spe_supported()) {
+ spe_enable(ctx);
+ }
+
+ if (is_feat_trbe_supported()) {
+ trbe_enable(ctx);
+ }
+
if (is_feat_brbe_supported()) {
brbe_enable(ctx);
}
@@ -901,6 +883,10 @@
sme_init_el2_unused();
}
+ if (is_feat_mops_supported()) {
+ write_hcrx_el2(read_hcrx_el2() | HCRX_EL2_MSCEn_BIT);
+ }
+
#if ENABLE_PAUTH
enable_pauth_el2();
#endif /* ENABLE_PAUTH */
@@ -930,6 +916,20 @@
sme_disable(ctx);
}
}
+
+ /*
+ * SPE and TRBE cannot be fully disabled from EL3 registers alone, only
+ * sysreg access can. In case the EL1 controls leave them active on
+ * context switch, we want the owning security state to be NS so Secure
+ * can't be DOSed.
+ */
+ if (is_feat_spe_supported()) {
+ spe_disable(ctx);
+ }
+
+ if (is_feat_trbe_supported()) {
+ trbe_disable(ctx);
+ }
#endif /* IMAGE_BL31 */
}
diff --git a/lib/extensions/brbe/brbe.c b/lib/extensions/brbe/brbe.c
index fef6647..f951654 100644
--- a/lib/extensions/brbe/brbe.c
+++ b/lib/extensions/brbe/brbe.c
@@ -22,7 +22,7 @@
* MDCR_EL3.{E3BREW, E3BREC} = 0b00
* Branch recording at EL3 is disabled
*/
- mdcr_el3_val &= ~((MDCR_SBRBE_MASK << MDCR_SBRBE_SHIFT) | MDCR_E3BREW | MDCR_E3BREC);
- mdcr_el3_val |= (0x1UL << MDCR_SBRBE_SHIFT);
+ mdcr_el3_val &= ~((MDCR_SBRBE(MDCR_SBRBE_ALL)) | MDCR_E3BREW_BIT | MDCR_E3BREC_BIT);
+ mdcr_el3_val |= (MDCR_SBRBE(MDCR_SBRBE_NS));
write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
}
diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c
index a8d42ab..d7df267 100644
--- a/lib/extensions/spe/spe.c
+++ b/lib/extensions/spe/spe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -42,18 +42,14 @@
u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
/*
- * MDCR_EL3.NSPB: Clear these bits to disable SPE feature, as it was enabled
- * for Non-secure state only. After clearing these bits Secure state owns
- * the Profiling Buffer and accesses to Statistical Profiling and Profiling
- * Buffer control registers at EL2 and EL1 generate Trap exceptions to EL3
- *
- * MDCR_EL3.NSPBE: Don't care as it was cleared during spe_enable and setting
- * this to 1 does not make sense as NSPBE{1} and NSPB{0b0x} is RESERVED.
+ * MDCR_EL3.{NSPB,NSPBE} = 0b00, 0b0
+ * Disable access of profiling buffer control registers from lower ELs
+ * in any security state. Secure state owns the buffer.
*
* MDCR_EL3.EnPMSN (ARM v8.7): Clear the bit to trap access of PMSNEVFR_EL1
* from EL2/EL1 to EL3.
*/
- mdcr_el3_val &= ~(MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT);
+ mdcr_el3_val &= ~(MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_NSPBE_BIT | MDCR_EnPMSN_BIT);
write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
}
diff --git a/lib/extensions/trbe/trbe.c b/lib/extensions/trbe/trbe.c
index 8775e40..24d88ae 100644
--- a/lib/extensions/trbe/trbe.c
+++ b/lib/extensions/trbe/trbe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -35,13 +35,9 @@
u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
/*
- * MDCR_EL3.NSTBE = 0b0
- * Trace Buffer owning Security state is secure state. If FEAT_RME
- * is not implemented, this field is RES0.
- *
- * MDCR_EL3.NSTB = 0b00
- * Clear these bits to disable access of trace buffer control registers
- * from lower ELs in any security state.
+ * MDCR_EL3.{NSTBE,NSTB} = 0b0, 0b00
+ * Disable access of trace buffer control registers from lower ELs in
+ * any security state. Secure state owns the buffer.
*/
mdcr_el3_val &= ~(MDCR_NSTB(MDCR_NSTB_EL1));
mdcr_el3_val &= ~(MDCR_NSTBE_BIT);
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 5418666..93d71b8 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -16,6 +16,8 @@
#include <drivers/delay_timer.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/extensions/spe.h>
+#include <lib/pmf/pmf.h>
+#include <lib/runtime_instr.h>
#include <lib/utils.h>
#include <plat/common/platform.h>
@@ -170,9 +172,9 @@
* Returns 1 (true) if the current CPU is the last ON CPU or 0 (false)
* otherwise.
******************************************************************************/
-static bool psci_is_last_cpu_to_idle_at_pwrlvl(unsigned int end_pwrlvl)
+static bool psci_is_last_cpu_to_idle_at_pwrlvl(unsigned int my_idx, unsigned int end_pwrlvl)
{
- unsigned int my_idx, lvl;
+ unsigned int lvl;
unsigned int parent_idx = 0;
unsigned int cpu_start_idx, ncpus, cpu_idx;
plat_local_state_t local_state;
@@ -181,7 +183,6 @@
return true;
}
- my_idx = plat_my_core_pos();
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;
@@ -212,11 +213,9 @@
* turned OFF and the current CPU is the last running CPU in the system.
* Returns true, if the current CPU is the last ON CPU or false otherwise.
******************************************************************************/
-bool psci_is_last_on_cpu(void)
+bool psci_is_last_on_cpu(unsigned int my_idx)
{
- unsigned int cpu_idx, my_idx = plat_my_core_pos();
-
- for (cpu_idx = 0; cpu_idx < psci_plat_core_count; cpu_idx++) {
+ for (unsigned int cpu_idx = 0; cpu_idx < psci_plat_core_count; cpu_idx++) {
if (cpu_idx == my_idx) {
assert(psci_get_aff_info_state() == AFF_STATE_ON);
continue;
@@ -260,13 +259,9 @@
/*
* Assume that this cpu was suspended and retrieve its target power
- * level. If it is invalid then it could only have been turned off
- * earlier. PLAT_MAX_PWR_LVL will be the highest power level a
- * cpu can be turned off to.
+ * level. If it wasn't, the cpu is off so this will be PLAT_MAX_PWR_LVL.
*/
pwrlvl = psci_get_suspend_pwrlvl();
- if (pwrlvl == PSCI_INVALID_PWR_LVL)
- pwrlvl = PLAT_MAX_PWR_LVL;
assert(pwrlvl < PSCI_INVALID_PWR_LVL);
return pwrlvl;
}
@@ -428,14 +423,14 @@
* function will be called after a cpu is powered on to find the local state
* each power domain has emerged from.
*****************************************************************************/
-void psci_get_target_local_pwr_states(unsigned int end_pwrlvl,
+void psci_get_target_local_pwr_states(unsigned int cpu_idx, unsigned int end_pwrlvl,
psci_power_state_t *target_state)
{
unsigned int parent_idx, lvl;
plat_local_state_t *pd_state = target_state->pwr_domain_state;
pd_state[PSCI_CPU_PWR_LVL] = psci_get_cpu_local_state();
- parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node;
+ parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
/* Copy the local power state from node to state_info */
for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) {
@@ -454,7 +449,7 @@
* enter. This function will be called after coordination of requested power
* states has been done for each power level.
*****************************************************************************/
-void psci_set_target_local_pwr_states(unsigned int end_pwrlvl,
+void psci_set_target_local_pwr_states(unsigned int cpu_idx, unsigned int end_pwrlvl,
const psci_power_state_t *target_state)
{
unsigned int parent_idx, lvl;
@@ -468,7 +463,7 @@
*/
psci_flush_cpu_data(psci_svc_cpu_data.local_state);
- parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node;
+ parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
/* Copy the local_state from state_info */
for (lvl = 1U; lvl <= end_pwrlvl; lvl++) {
@@ -500,9 +495,9 @@
* affinity info state, target power state and requested power state for the
* current CPU and all its ancestor power domains to RUN.
*****************************************************************************/
-void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl)
+void psci_set_pwr_domains_to_run(unsigned int cpu_idx, unsigned int end_pwrlvl)
{
- unsigned int parent_idx, cpu_idx = plat_my_core_pos(), lvl;
+ unsigned int parent_idx, lvl;
parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
/* Reset the local_state to RUN for the non cpu power domains. */
@@ -544,10 +539,10 @@
* This function will only be invoked with data cache enabled and while
* powering down a core.
*****************************************************************************/
-void psci_do_state_coordination(unsigned int end_pwrlvl,
+void psci_do_state_coordination(unsigned int cpu_idx, unsigned int end_pwrlvl,
psci_power_state_t *state_info)
{
- unsigned int lvl, parent_idx, cpu_idx = plat_my_core_pos();
+ unsigned int lvl, parent_idx;
unsigned int start_idx;
unsigned int ncpus;
plat_local_state_t target_state, *req_states;
@@ -620,11 +615,11 @@
* This function will only be invoked with data cache enabled and while
* powering down a core.
*****************************************************************************/
-int psci_validate_state_coordination(unsigned int end_pwrlvl,
+int psci_validate_state_coordination(unsigned int cpu_idx, unsigned int end_pwrlvl,
psci_power_state_t *state_info)
{
int rc = PSCI_E_SUCCESS;
- unsigned int lvl, parent_idx, cpu_idx = plat_my_core_pos();
+ unsigned int lvl, parent_idx;
unsigned int start_idx;
unsigned int ncpus;
plat_local_state_t target_state, *req_states;
@@ -674,7 +669,7 @@
* specified power level.
*/
lvl = state_info->last_at_pwrlvl;
- if (!psci_is_last_cpu_to_idle_at_pwrlvl(lvl)) {
+ if (!psci_is_last_cpu_to_idle_at_pwrlvl(cpu_idx, lvl)) {
rc = PSCI_E_DENIED;
}
@@ -1004,7 +999,7 @@
*/
psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes);
- psci_get_target_local_pwr_states(end_pwrlvl, &state_info);
+ psci_get_target_local_pwr_states(cpu_idx, end_pwrlvl, &state_info);
#if ENABLE_PSCI_STAT
plat_psci_stat_accounting_stop(&state_info);
@@ -1025,7 +1020,7 @@
if (psci_get_aff_info_state() == AFF_STATE_ON_PENDING)
psci_cpu_on_finish(cpu_idx, &state_info);
else
- psci_cpu_suspend_finish(cpu_idx, &state_info);
+ psci_cpu_suspend_to_powerdown_finish(cpu_idx, &state_info);
/*
* Generic management: Now we just need to retrieve the
@@ -1038,16 +1033,10 @@
* Set the requested and target state of this CPU and all the higher
* power domains which are ancestors of this CPU to run.
*/
- psci_set_pwr_domains_to_run(end_pwrlvl);
+ psci_set_pwr_domains_to_run(cpu_idx, end_pwrlvl);
#if ENABLE_PSCI_STAT
- /*
- * Update PSCI stats.
- * Caches are off when writing stats data on the power down path.
- * Since caches are now enabled, it's necessary to do cache
- * maintenance before reading that same data.
- */
- psci_stats_update_pwr_up(end_pwrlvl, &state_info);
+ psci_stats_update_pwr_up(cpu_idx, end_pwrlvl, &state_info);
#endif
/*
@@ -1169,6 +1158,17 @@
******************************************************************************/
void psci_pwrdown_cpu(unsigned int power_level)
{
+#if ENABLE_RUNTIME_INSTRUMENTATION
+
+ /*
+ * Flush cache line so that even if CPU power down happens
+ * the timestamp update is reflected in memory.
+ */
+ PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
+ RT_INSTR_ENTER_CFLUSH,
+ PMF_CACHE_MAINT);
+#endif
+
#if HW_ASSISTED_COHERENCY
/*
* With hardware-assisted coherency, the CPU drivers only initiate the
@@ -1188,6 +1188,12 @@
*/
psci_do_pwrdown_cache_maintenance(power_level);
#endif
+
+#if ENABLE_RUNTIME_INSTRUMENTATION
+ PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
+ RT_INSTR_EXIT_CFLUSH,
+ PMF_NO_CACHE_MAINT);
+#endif
}
/*******************************************************************************
@@ -1200,15 +1206,11 @@
* The function returns 'PSCI_E_DENIED' if some cores failed to stop within the
* given timeout.
******************************************************************************/
-int psci_stop_other_cores(unsigned int wait_ms,
+int psci_stop_other_cores(unsigned int this_cpu_idx, unsigned int wait_ms,
void (*stop_func)(u_register_t mpidr))
{
- unsigned int idx, this_cpu_idx;
-
- this_cpu_idx = plat_my_core_pos();
-
/* Invoke stop_func for each core */
- for (idx = 0U; idx < psci_plat_core_count; idx++) {
+ for (unsigned int idx = 0U; idx < psci_plat_core_count; idx++) {
/* skip current CPU */
if (idx == this_cpu_idx) {
continue;
@@ -1222,11 +1224,11 @@
/* Need to wait for other cores to shutdown */
if (wait_ms != 0U) {
- while ((wait_ms-- != 0U) && (!psci_is_last_on_cpu())) {
+ while ((wait_ms-- != 0U) && (!psci_is_last_on_cpu(this_cpu_idx))) {
mdelay(1U);
}
- if (!psci_is_last_on_cpu()) {
+ if (!psci_is_last_on_cpu(this_cpu_idx)) {
WARN("Failed to stop all cores!\n");
psci_print_power_domain_map();
return PSCI_E_DENIED;
@@ -1244,16 +1246,15 @@
* This API has following differences with psci_is_last_on_cpu
* 1. PSCI states are locked
******************************************************************************/
-bool psci_is_last_on_cpu_safe(void)
+bool psci_is_last_on_cpu_safe(unsigned int this_core)
{
- unsigned int this_core = plat_my_core_pos();
unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
psci_get_parent_pwr_domain_nodes(this_core, PLAT_MAX_PWR_LVL, parent_nodes);
psci_acquire_pwr_domain_locks(PLAT_MAX_PWR_LVL, parent_nodes);
- if (!psci_is_last_on_cpu()) {
+ if (!psci_is_last_on_cpu(this_core)) {
psci_release_pwr_domain_locks(PLAT_MAX_PWR_LVL, parent_nodes);
return false;
}
@@ -1270,9 +1271,8 @@
* This API has following differences with psci_are_all_cpus_on
* 1. PSCI states are locked
******************************************************************************/
-bool psci_are_all_cpus_on_safe(void)
+bool psci_are_all_cpus_on_safe(unsigned int this_core)
{
- unsigned int this_core = plat_my_core_pos();
unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
psci_get_parent_pwr_domain_nodes(this_core, PLAT_MAX_PWR_LVL, parent_nodes);
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index a015531..7ac0e02 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -59,8 +59,8 @@
entry_point_info_t ep;
psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
plat_local_state_t cpu_pd_state;
-#if PSCI_OS_INIT_MODE
unsigned int cpu_idx = plat_my_core_pos();
+#if PSCI_OS_INIT_MODE
plat_local_state_t prev[PLAT_MAX_PWR_LVL];
#endif
@@ -145,7 +145,7 @@
plat_psci_stat_accounting_stop(&state_info);
/* Update PSCI stats */
- psci_stats_update_pwr_up(PSCI_CPU_PWR_LVL, &state_info);
+ psci_stats_update_pwr_up(cpu_idx, PSCI_CPU_PWR_LVL, &state_info);
#endif
return PSCI_E_SUCCESS;
@@ -167,7 +167,8 @@
* might return if the power down was abandoned for any reason, e.g.
* arrival of an interrupt
*/
- rc = psci_cpu_suspend_start(&ep,
+ rc = psci_cpu_suspend_start(cpu_idx,
+ &ep,
target_pwrlvl,
&state_info,
is_power_down_state);
@@ -181,9 +182,10 @@
int rc;
psci_power_state_t state_info;
entry_point_info_t ep;
+ unsigned int cpu_idx = plat_my_core_pos();
/* Check if the current CPU is the last ON CPU in the system */
- if (!psci_is_last_on_cpu())
+ if (!psci_is_last_on_cpu(cpu_idx))
return PSCI_E_DENIED;
/* Validate the entry point and get the entry_point_info */
@@ -212,7 +214,8 @@
* might return if the power down was abandoned for any reason, e.g.
* arrival of an interrupt
*/
- rc = psci_cpu_suspend_start(&ep,
+ rc = psci_cpu_suspend_start(cpu_idx,
+ &ep,
PLAT_MAX_PWR_LVL,
&state_info,
PSTATE_TYPE_POWERDOWN);
@@ -399,9 +402,11 @@
return PSCI_E_SUCCESS;
}
+ unsigned int this_core = plat_my_core_pos();
+
if (mode == PLAT_COORD) {
/* Check if the current CPU is the last ON CPU in the system */
- if (!psci_is_last_on_cpu_safe()) {
+ if (!psci_is_last_on_cpu_safe(this_core)) {
return PSCI_E_DENIED;
}
}
@@ -411,8 +416,8 @@
* Check if all CPUs in the system are ON or if the current
* CPU is the last ON CPU in the system.
*/
- if (!(psci_are_all_cpus_on_safe() ||
- psci_is_last_on_cpu_safe())) {
+ if (!(psci_are_all_cpus_on_safe(this_core) ||
+ psci_is_last_on_cpu_safe(this_core))) {
return PSCI_E_DENIED;
}
}
diff --git a/lib/psci/psci_off.c b/lib/psci/psci_off.c
index f83753f..d40ee3f 100644
--- a/lib/psci/psci_off.c
+++ b/lib/psci/psci_off.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -102,25 +102,14 @@
* it returns the negotiated state info for each power level upto
* the end level specified.
*/
- psci_do_state_coordination(end_pwrlvl, &state_info);
+ psci_do_state_coordination(idx, end_pwrlvl, &state_info);
/* Update the target state in the power domain nodes */
- psci_set_target_local_pwr_states(end_pwrlvl, &state_info);
+ psci_set_target_local_pwr_states(idx, end_pwrlvl, &state_info);
#if ENABLE_PSCI_STAT
/* Update the last cpu for each level till end_pwrlvl */
- psci_stats_update_pwr_down(end_pwrlvl, &state_info);
-#endif
-
-#if ENABLE_RUNTIME_INSTRUMENTATION
-
- /*
- * Flush cache line so that even if CPU power down happens
- * the timestamp update is reflected in memory.
- */
- PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
- RT_INSTR_ENTER_CFLUSH,
- PMF_CACHE_MAINT);
+ psci_stats_update_pwr_down(idx, end_pwrlvl, &state_info);
#endif
/*
@@ -128,12 +117,6 @@
*/
psci_pwrdown_cpu(psci_find_max_off_lvl(&state_info));
-#if ENABLE_RUNTIME_INSTRUMENTATION
- PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
- RT_INSTR_EXIT_CFLUSH,
- PMF_NO_CACHE_MAINT);
-#endif
-
/*
* Plat. management: Perform platform specific actions to turn this
* cpu off e.g. exit cpu coherency, program the power controller etc.
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index 2eb4a9b..6622755 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -295,19 +295,19 @@
void psci_restore_req_local_pwr_states(unsigned int cpu_idx,
plat_local_state_t *prev);
#endif
-void psci_get_target_local_pwr_states(unsigned int end_pwrlvl,
+void psci_get_target_local_pwr_states(unsigned int cpu_idx, unsigned int end_pwrlvl,
psci_power_state_t *target_state);
-void psci_set_target_local_pwr_states(unsigned int end_pwrlvl,
+void psci_set_target_local_pwr_states(unsigned int cpu_idx, unsigned int end_pwrlvl,
const psci_power_state_t *target_state);
int psci_validate_entry_point(entry_point_info_t *ep,
uintptr_t entrypoint, u_register_t context_id);
void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx,
unsigned int end_lvl,
unsigned int *node_index);
-void psci_do_state_coordination(unsigned int end_pwrlvl,
+void psci_do_state_coordination(unsigned int cpu_idx, unsigned int end_pwrlvl,
psci_power_state_t *state_info);
#if PSCI_OS_INIT_MODE
-int psci_validate_state_coordination(unsigned int end_pwrlvl,
+int psci_validate_state_coordination(unsigned int cpu_idx, unsigned int end_pwrlvl,
psci_power_state_t *state_info);
#endif
void psci_acquire_pwr_domain_locks(unsigned int end_pwrlvl,
@@ -318,9 +318,9 @@
unsigned int is_power_down_state);
unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info);
unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info);
-void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl);
+void psci_set_pwr_domains_to_run(unsigned int cpu_idx, unsigned int end_pwrlvl);
void psci_print_power_domain_map(void);
-bool psci_is_last_on_cpu(void);
+bool psci_is_last_on_cpu(unsigned int my_idx);
int psci_spd_migrate_info(u_register_t *mpidr);
/*
@@ -343,12 +343,13 @@
int psci_do_cpu_off(unsigned int end_pwrlvl);
/* Private exported functions from psci_suspend.c */
-int psci_cpu_suspend_start(const entry_point_info_t *ep,
+int psci_cpu_suspend_start(unsigned int idx,
+ const entry_point_info_t *ep,
unsigned int end_pwrlvl,
psci_power_state_t *state_info,
unsigned int is_power_down_state);
-void psci_cpu_suspend_finish(unsigned int cpu_idx, const psci_power_state_t *state_info);
+void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx, const psci_power_state_t *state_info);
/* Private exported functions from psci_helpers.S */
void psci_do_pwrdown_cache_maintenance(unsigned int pwr_level);
@@ -360,9 +361,9 @@
u_register_t psci_system_reset2(uint32_t reset_type, u_register_t cookie);
/* Private exported functions from psci_stat.c */
-void psci_stats_update_pwr_down(unsigned int end_pwrlvl,
+void psci_stats_update_pwr_down(unsigned int cpu_idx, unsigned int end_pwrlvl,
const psci_power_state_t *state_info);
-void psci_stats_update_pwr_up(unsigned int end_pwrlvl,
+void psci_stats_update_pwr_up(unsigned int cpu_idx, unsigned int end_pwrlvl,
const psci_power_state_t *state_info);
u_register_t psci_stat_residency(u_register_t target_cpu,
unsigned int power_state);
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index 6bf1ff4..a81ba4a 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -68,8 +68,8 @@
/* Set the Affinity Info for the cores as OFF */
svc_cpu_data->aff_info_state = AFF_STATE_OFF;
- /* Invalidate the suspend level for the cpu */
- svc_cpu_data->target_pwrlvl = PSCI_INVALID_PWR_LVL;
+ /* Default to the highest power level when the cpu is not suspending */
+ svc_cpu_data->target_pwrlvl = PLAT_MAX_PWR_LVL;
/* Set the power state to OFF state */
svc_cpu_data->local_state = PLAT_MAX_OFF_STATE;
@@ -202,6 +202,7 @@
int __init psci_setup(const psci_lib_args_t *lib_args)
{
const unsigned char *topology_tree;
+ unsigned int cpu_idx = plat_my_core_pos();
assert(VERIFY_PSCI_LIB_ARGS_V1(lib_args));
@@ -218,7 +219,7 @@
psci_update_pwrlvl_limits();
/* Populate the mpidr field of cpu node for this CPU */
- psci_cpu_pd_nodes[plat_my_core_pos()].mpidr =
+ psci_cpu_pd_nodes[cpu_idx].mpidr =
read_mpidr() & MPIDR_AFFINITY_MASK;
psci_init_req_local_pwr_states();
@@ -227,7 +228,7 @@
* Set the requested and target state of this CPU and all the higher
* power domain levels for this CPU to run.
*/
- psci_set_pwr_domains_to_run(PLAT_MAX_PWR_LVL);
+ psci_set_pwr_domains_to_run(cpu_idx, PLAT_MAX_PWR_LVL);
(void) plat_setup_psci_ops((uintptr_t)lib_args->mailbox_ep,
&psci_plat_pm_ops);
diff --git a/lib/psci/psci_stat.c b/lib/psci/psci_stat.c
index bedb816..1225557 100644
--- a/lib/psci/psci_stat.c
+++ b/lib/psci/psci_stat.c
@@ -73,11 +73,10 @@
* This function will only be invoked with data cache enabled and while
* powering down a core.
******************************************************************************/
-void psci_stats_update_pwr_down(unsigned int end_pwrlvl,
+void psci_stats_update_pwr_down(unsigned int cpu_idx, unsigned int end_pwrlvl,
const psci_power_state_t *state_info)
{
unsigned int lvl, parent_idx;
- unsigned int cpu_idx = plat_my_core_pos();
assert(end_pwrlvl <= PLAT_MAX_PWR_LVL);
assert(state_info != NULL);
@@ -106,11 +105,10 @@
* and NON-CPU power domains.
* It is called with caches enabled and locks acquired(for NON-CPU domain)
******************************************************************************/
-void psci_stats_update_pwr_up(unsigned int end_pwrlvl,
+void psci_stats_update_pwr_up(unsigned int cpu_idx, unsigned int end_pwrlvl,
const psci_power_state_t *state_info)
{
unsigned int lvl, parent_idx;
- unsigned int cpu_idx = plat_my_core_pos();
int stat_idx;
plat_local_state_t local_state;
u_register_t residency;
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index cb12b83..2aadbfd 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,42 +25,18 @@
* This function does generic and platform specific operations after a wake-up
* from standby/retention states at multiple power levels.
******************************************************************************/
-static void psci_suspend_to_standby_finisher(unsigned int cpu_idx,
- unsigned int end_pwrlvl)
+static void psci_cpu_suspend_to_standby_finish(unsigned int cpu_idx,
+ unsigned int end_pwrlvl,
+ psci_power_state_t *state_info)
{
- unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
- psci_power_state_t state_info;
-
- /* Get the parent nodes */
- psci_get_parent_pwr_domain_nodes(cpu_idx, end_pwrlvl, parent_nodes);
-
- psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes);
-
- /*
- * Find out which retention states this CPU has exited from until the
- * 'end_pwrlvl'. The exit retention state could be deeper than the entry
- * state as a result of state coordination amongst other CPUs post wfi.
- */
- psci_get_target_local_pwr_states(end_pwrlvl, &state_info);
-
-#if ENABLE_PSCI_STAT
- plat_psci_stat_accounting_stop(&state_info);
- psci_stats_update_pwr_up(end_pwrlvl, &state_info);
-#endif
-
/*
* Plat. management: Allow the platform to do operations
* on waking up from retention.
*/
- psci_plat_pm_ops->pwr_domain_suspend_finish(&state_info);
+ psci_plat_pm_ops->pwr_domain_suspend_finish(state_info);
- /*
- * Set the requested and target state of this CPU and all the higher
- * power domain levels for this CPU to run.
- */
- psci_set_pwr_domains_to_run(end_pwrlvl);
-
- psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes);
+ /* This loses its meaning when not suspending, reset so it's correct for OFF */
+ psci_set_suspend_pwrlvl(PLAT_MAX_PWR_LVL);
}
/*******************************************************************************
@@ -116,29 +92,12 @@
*/
cm_init_my_context(ep);
-#if ENABLE_RUNTIME_INSTRUMENTATION
-
- /*
- * Flush cache line so that even if CPU power down happens
- * the timestamp update is reflected in memory.
- */
- PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
- RT_INSTR_ENTER_CFLUSH,
- PMF_CACHE_MAINT);
-#endif
-
/*
* Arch. management. Initiate power down sequence.
* TODO : Introduce a mechanism to query the cache level to flush
* and the cpu-ops power down to perform from the platform.
*/
psci_pwrdown_cpu(max_off_lvl);
-
-#if ENABLE_RUNTIME_INSTRUMENTATION
- PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
- RT_INSTR_EXIT_CFLUSH,
- PMF_NO_CACHE_MAINT);
-#endif
}
/*******************************************************************************
@@ -159,14 +118,14 @@
* the state transition has been done, no further error is expected and it is
* not possible to undo any of the actions taken beyond that point.
******************************************************************************/
-int psci_cpu_suspend_start(const entry_point_info_t *ep,
+int psci_cpu_suspend_start(unsigned int idx,
+ const entry_point_info_t *ep,
unsigned int end_pwrlvl,
psci_power_state_t *state_info,
unsigned int is_power_down_state)
{
int rc = PSCI_E_SUCCESS;
bool skip_wfi = false;
- unsigned int idx = plat_my_core_pos();
unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
/*
@@ -202,7 +161,7 @@
* This function validates the requested state info for
* OS-initiated mode.
*/
- rc = psci_validate_state_coordination(end_pwrlvl, state_info);
+ rc = psci_validate_state_coordination(idx, end_pwrlvl, state_info);
if (rc != PSCI_E_SUCCESS) {
skip_wfi = true;
goto exit;
@@ -214,7 +173,7 @@
* it returns the negotiated state info for each power level upto
* the end level specified.
*/
- psci_do_state_coordination(end_pwrlvl, state_info);
+ psci_do_state_coordination(idx, end_pwrlvl, state_info);
#if PSCI_OS_INIT_MODE
}
#endif
@@ -230,11 +189,11 @@
#endif
/* Update the target state in the power domain nodes */
- psci_set_target_local_pwr_states(end_pwrlvl, state_info);
+ psci_set_target_local_pwr_states(idx, end_pwrlvl, state_info);
#if ENABLE_PSCI_STAT
/* Update the last cpu for each level till end_pwrlvl */
- psci_stats_update_pwr_down(end_pwrlvl, state_info);
+ psci_stats_update_pwr_down(idx, end_pwrlvl, state_info);
#endif
if (is_power_down_state != 0U)
@@ -304,11 +263,32 @@
PMF_NO_CACHE_MAINT);
#endif
+ psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes);
+ /*
+ * Find out which retention states this CPU has exited from until the
+ * 'end_pwrlvl'. The exit retention state could be deeper than the entry
+ * state as a result of state coordination amongst other CPUs post wfi.
+ */
+ psci_get_target_local_pwr_states(idx, end_pwrlvl, state_info);
+
+#if ENABLE_PSCI_STAT
+ plat_psci_stat_accounting_stop(state_info);
+ psci_stats_update_pwr_up(idx, end_pwrlvl, state_info);
+#endif
+
/*
* After we wake up from context retaining suspend, call the
* context retaining suspend finisher.
*/
- psci_suspend_to_standby_finisher(idx, end_pwrlvl);
+ psci_cpu_suspend_to_standby_finish(idx, end_pwrlvl, state_info);
+
+ /*
+ * Set the requested and target state of this CPU and all the higher
+ * power domain levels for this CPU to run.
+ */
+ psci_set_pwr_domains_to_run(idx, end_pwrlvl);
+
+ psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes);
return rc;
}
@@ -318,7 +298,7 @@
* are called by the common finisher routine in psci_common.c. The `state_info`
* is the psci_power_state from which this CPU has woken up from.
******************************************************************************/
-void psci_cpu_suspend_finish(unsigned int cpu_idx, const psci_power_state_t *state_info)
+void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx, const psci_power_state_t *state_info)
{
unsigned int counter_freq;
unsigned int max_off_lvl;
@@ -363,8 +343,8 @@
psci_spd_pm->svc_suspend_finish(max_off_lvl);
}
- /* Invalidate the suspend level for the cpu */
- psci_set_suspend_pwrlvl(PSCI_INVALID_PWR_LVL);
+ /* This loses its meaning when not suspending, reset so it's correct for OFF */
+ psci_set_suspend_pwrlvl(PLAT_MAX_PWR_LVL);
PUBLISH_EVENT(psci_suspend_pwrdown_finish);
}
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index a1db0b8..3c9e136 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -83,6 +83,7 @@
# Enable the features which are mandatory from ARCH version 8.8 and upwards.
ifeq "8.8" "$(word 1, $(sort 8.8 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
+armv8-8-a-feats := ENABLE_FEAT_MOPS
# 8.7 Compliant
armv8-8-a-feats += ${armv8-7-a-feats}
FEAT_LIST := ${armv8-8-a-feats}
@@ -213,6 +214,14 @@
ENABLE_FEAT_HCX ?= 0
#----
+# 8.8
+#----
+
+# Flag to enable FEAT_MOPS (Standardization of Memory operations)
+# when INIT_UNUSED_NS_EL2 = 1
+ENABLE_FEAT_MOPS ?= 0
+
+#----
# 8.9
#----
diff --git a/make_helpers/build_env.mk b/make_helpers/build_env.mk
deleted file mode 100644
index 13acaae..0000000
--- a/make_helpers/build_env.mk
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# This file contains the logic to identify and include any relevant
-# build environment specific make include files.
-
-ifndef BUILD_ENV_MK
- BUILD_ENV_MK := $(lastword $(MAKEFILE_LIST))
-
- # Block possible built-in command definitions that are not fully portable.
- # This traps occurences that need replacing with our OS portable macros
- COPY := $$(error "Replace COPY with call to SHELL_COPY or SHELL_COPY_TREE.")
- CP := $$(error "Replace CP with call to SHELL_COPY or SHELL_COPY_TREE.")
- DEL := $$(error "Replace DEL with call to SHELL_DELETE.")
- RD := $$(error "Replace RD with call to SHELL_REMOVE_DIR.")
- RM := $$(error "Replace RM with call to SHELL_DELETE.")
- RMDIR := $$(error "Replace RMDIR with call to SHELL_REMOVE_DIR.")
-
- ENV_FILE_TO_INCLUDE := unix.mk
- ifdef OSTYPE
- ifneq ($(findstring ${OSTYPE}, cygwin),)
- ENV_FILE_TO_INCLUDE := cygwin.mk
- else
- ifneq ($(findstring ${OSTYPE}, MINGW32 mingw msys),)
- ENV_FILE_TO_INCLUDE := msys.mk
- endif
- endif
- else
- ifdef MSYSTEM
- # Although the MINGW MSYS shell sets OSTYPE as msys in its environment,
- # it does not appear in the GNU make view of environment variables.
- # We use MSYSTEM as an alternative, as that is seen by make
- ifneq ($(findstring ${MSYSTEM}, MINGW32 mingw msys),)
- OSTYPE ?= msys
- ENV_FILE_TO_INCLUDE := msys.mk
- endif
- else
- ifdef OS
- ifneq ($(findstring ${OS}, Windows_NT),)
- ENV_FILE_TO_INCLUDE := windows.mk
- endif
- endif
- endif
- endif
- include $(dir $(lastword $(MAKEFILE_LIST)))${ENV_FILE_TO_INCLUDE}
- ENV_FILE_TO_INCLUDE :=
-
- ifndef SHELL_COPY
- $(error "SHELL_COPY not defined for build environment.")
- endif
- ifndef SHELL_COPY_TREE
- $(error "SHELL_COPY_TREE not defined for build environment.")
- endif
- ifndef SHELL_DELETE_ALL
- $(error "SHELL_DELETE_ALL not defined for build environment.")
- endif
- ifndef SHELL_DELETE
- $(error "SHELL_DELETE not defined for build environment.")
- endif
- ifndef SHELL_REMOVE_DIR
- $(error "SHELL_REMOVE_DIR not defined for build environment.")
- endif
-
-endif
diff --git a/make_helpers/common.mk b/make_helpers/common.mk
index 848e4e9..a4b69c7 100644
--- a/make_helpers/common.mk
+++ b/make_helpers/common.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -14,4 +14,6 @@
s := @$(if $(or $(verbose),$(silent)),: )
q := $(if $(verbose),,@)
+
+ .exe := $(if $(filter Windows_NT,$(OS)),.exe)
endif
diff --git a/make_helpers/cygwin.mk b/make_helpers/cygwin.mk
deleted file mode 100644
index 04a963f..0000000
--- a/make_helpers/cygwin.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-#
-
-# OS specific definitions for builds in a Cygwin environment.
-# Cygwin allows us to use unix style commands on a windows platform.
-
-ifndef CYGWIN_MK
- CYGWIN_MK := $(lastword $(MAKEFILE_LIST))
-
- include ${MAKE_HELPERS_DIRECTORY}unix.mk
-
- # In cygwin executable files have the Windows .exe extension type.
- BIN_EXT := .exe
-
-endif
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 8a0975b..4985c0c 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -210,6 +210,9 @@
# Enable PSCI OS-initiated mode support
PSCI_OS_INIT_MODE := 0
+# SMCCC_ARCH_FEATURE_AVAILABILITY support
+ARCH_FEATURE_AVAILABILITY := 0
+
# By default, BL1 acts as the reset handler, not BL31
RESET_TO_BL31 := 0
diff --git a/make_helpers/msys.mk b/make_helpers/msys.mk
deleted file mode 100644
index 7e60d57..0000000
--- a/make_helpers/msys.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-#
-
-# OS specific definitions for builds in a Mingw32 MSYS environment.
-# Mingw32 allows us to use some unix style commands on a windows platform.
-
-ifndef MSYS_MK
- MSYS_MK := $(lastword $(MAKEFILE_LIST))
-
- include ${MAKE_HELPERS_DIRECTORY}unix.mk
-
- # In MSYS executable files have the Windows .exe extension type.
- BIN_EXT := .exe
-
-endif
-
diff --git a/make_helpers/toolchain.mk b/make_helpers/toolchain.mk
index 2ab577c..3b9d984 100644
--- a/make_helpers/toolchain.mk
+++ b/make_helpers/toolchain.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -18,7 +18,6 @@
ifndef toolchain-mk
toolchain-mk := $(lastword $(MAKEFILE_LIST))
- include $(dir $(toolchain-mk))build_env.mk
include $(dir $(toolchain-mk))utilities.mk
#
@@ -242,28 +241,28 @@
#
# Arm Compiler for Embedded
- toolchain-guess-tool-arm-clang = $(shell $(1) --version 2>&1 <$(nul) | grep -o "Tool: armclang")
- toolchain-guess-tool-arm-link = $(shell $(1) --help 2>&1 <$(nul) | grep -o "Tool: armlink")
- toolchain-guess-tool-arm-fromelf = $(shell $(1) --help 2>&1 <$(nul) | grep -o "Tool: fromelf")
- toolchain-guess-tool-arm-ar = $(shell $(1) --version 2>&1 <$(nul) | grep -o "Tool: armar")
+ toolchain-guess-tool-arm-clang = $(shell $(1) --version 2>&1 </dev/null | grep -o "Tool: armclang")
+ toolchain-guess-tool-arm-link = $(shell $(1) --help 2>&1 </dev/null | grep -o "Tool: armlink")
+ toolchain-guess-tool-arm-fromelf = $(shell $(1) --help 2>&1 </dev/null | grep -o "Tool: fromelf")
+ toolchain-guess-tool-arm-ar = $(shell $(1) --version 2>&1 </dev/null | grep -o "Tool: armar")
# LLVM Project
- toolchain-guess-tool-llvm-clang = $(shell $(1) -v 2>&1 <$(nul) | grep -o "clang version")
- toolchain-guess-tool-llvm-lld = $(shell $(1) --help 2>&1 <$(nul) | grep -o "OVERVIEW: lld")
- toolchain-guess-tool-llvm-objcopy = $(shell $(1) --help 2>&1 <$(nul) | grep -o "llvm-objcopy tool")
- toolchain-guess-tool-llvm-objdump = $(shell $(1) --help 2>&1 <$(nul) | grep -o "llvm object file dumper")
- toolchain-guess-tool-llvm-ar = $(shell $(1) --help 2>&1 <$(nul) | grep -o "LLVM Archiver")
+ toolchain-guess-tool-llvm-clang = $(shell $(1) -v 2>&1 </dev/null | grep -o "clang version")
+ toolchain-guess-tool-llvm-lld = $(shell $(1) --help 2>&1 </dev/null | grep -o "OVERVIEW: lld")
+ toolchain-guess-tool-llvm-objcopy = $(shell $(1) --help 2>&1 </dev/null | grep -o "llvm-objcopy tool")
+ toolchain-guess-tool-llvm-objdump = $(shell $(1) --help 2>&1 </dev/null | grep -o "llvm object file dumper")
+ toolchain-guess-tool-llvm-ar = $(shell $(1) --help 2>&1 </dev/null | grep -o "LLVM Archiver")
# GNU Compiler Collection & GNU Binary Utilities
- toolchain-guess-tool-gnu-gcc = $(shell $(1) -v 2>&1 <$(nul) | grep -o "gcc version")
- toolchain-guess-tool-gnu-ld = $(shell $(1) -v 2>&1 <$(nul) | grep -o "GNU ld")
- toolchain-guess-tool-gnu-objcopy = $(shell $(1) --version 2>&1 <$(nul) | grep -o "GNU objcopy")
- toolchain-guess-tool-gnu-objdump = $(shell $(1) --version 2>&1 <$(nul) | grep -o "GNU objdump")
- toolchain-guess-tool-gnu-ar = $(shell $(1) --version 2>&1 <$(nul) | grep -o "GNU ar")
+ toolchain-guess-tool-gnu-gcc = $(shell $(1) -v 2>&1 </dev/null | grep -o "gcc version")
+ toolchain-guess-tool-gnu-ld = $(shell $(1) -v 2>&1 </dev/null | grep -o "GNU ld")
+ toolchain-guess-tool-gnu-objcopy = $(shell $(1) --version 2>&1 </dev/null | grep -o "GNU objcopy")
+ toolchain-guess-tool-gnu-objdump = $(shell $(1) --version 2>&1 </dev/null | grep -o "GNU objdump")
+ toolchain-guess-tool-gnu-ar = $(shell $(1) --version 2>&1 </dev/null | grep -o "GNU ar")
# Other tools
- toolchain-guess-tool-generic-dtc = $(shell $(1) --version 2>&1 <$(nul) | grep -o "Version: DTC")
- toolchain-guess-tool-generic-poetry = $(shell $(1) --version 2>&1 <$(nul))
+ toolchain-guess-tool-generic-dtc = $(shell $(1) --version 2>&1 </dev/null | grep -o "Version: DTC")
+ toolchain-guess-tool-generic-poetry = $(shell $(1) --version 2>&1 </dev/null)
toolchain-guess-tool = $(if $(2),$(firstword $(foreach candidate,$(1),$\
$(if $(call toolchain-guess-tool-$(candidate),$(2)),$(candidate)))))
@@ -330,17 +329,17 @@
toolchain-derive-llvm-clang-cpp = $(1)
toolchain-derive-llvm-clang-as = $(1)
- toolchain-derive-llvm-clang-ld = $(shell $(1) --print-prog-name ld.lld 2>$(nul))
- toolchain-derive-llvm-clang-oc = $(shell $(1) --print-prog-name llvm-objcopy 2>$(nul))
- toolchain-derive-llvm-clang-od = $(shell $(1) --print-prog-name llvm-objdump 2>$(nul))
- toolchain-derive-llvm-clang-ar = $(shell $(1) --print-prog-name llvm-ar 2>$(nul))
+ toolchain-derive-llvm-clang-ld = $(shell $(1) --print-prog-name ld.lld 2>/dev/null)
+ toolchain-derive-llvm-clang-oc = $(shell $(1) --print-prog-name llvm-objcopy 2>/dev/null)
+ toolchain-derive-llvm-clang-od = $(shell $(1) --print-prog-name llvm-objdump 2>/dev/null)
+ toolchain-derive-llvm-clang-ar = $(shell $(1) --print-prog-name llvm-ar 2>/dev/null)
toolchain-derive-gnu-gcc-cpp = $(1)
toolchain-derive-gnu-gcc-as = $(1)
toolchain-derive-gnu-gcc-ld = $(1)
- toolchain-derive-gnu-gcc-oc = $(shell $(1) --print-prog-name objcopy 2>$(nul))
- toolchain-derive-gnu-gcc-od = $(shell $(1) --print-prog-name objdump 2>$(nul))
- toolchain-derive-gnu-gcc-ar = $(shell $(1) --print-prog-name ar 2>$(nul))
+ toolchain-derive-gnu-gcc-oc = $(shell $(1) --print-prog-name objcopy 2>/dev/null)
+ toolchain-derive-gnu-gcc-od = $(shell $(1) --print-prog-name objdump 2>/dev/null)
+ toolchain-derive-gnu-gcc-ar = $(shell $(1) --print-prog-name ar 2>/dev/null)
toolchain-derive = $(if $3,$(call toolchain-derive-$1-$2,$3))
diff --git a/make_helpers/unix.mk b/make_helpers/unix.mk
deleted file mode 100644
index fa7722a..0000000
--- a/make_helpers/unix.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# Trusted Firmware shell command definitions for a Unix style environment.
-
-ifndef UNIX_MK
- UNIX_MK := $(lastword $(MAKEFILE_LIST))
-
- DIR_DELIM := /
- PATH_SEP := :
-
- # These defines provide Unix style equivalents of the shell commands
- # required by the Trusted Firmware build environment.
-
- # ${1} is the file to be copied.
- # ${2} is the destination file name.
- define SHELL_COPY
- $(q)cp -f "${1}" "${2}"
- endef
-
- # ${1} is the directory to be copied.
- # ${2} is the destination directory path.
- define SHELL_COPY_TREE
- $(q)cp -rf "${1}" "${2}"
- endef
-
- # ${1} is the file to be deleted.
- define SHELL_DELETE
- -$(q)rm -f "${1}"
- endef
-
- # ${1} is a space delimited list of files to be deleted.
- # Note that we do not quote ${1}, as multiple parameters may be passed.
- define SHELL_DELETE_ALL
- -$(q)rm -rf ${1}
- endef
-
- define SHELL_REMOVE_DIR
- -$(q)rm -rf "${1}"
- endef
-
- nul := /dev/null
-
- which = $(shell command -v $(call escape-shell,$(1)) 2>$(nul))
-endif
diff --git a/make_helpers/utilities.mk b/make_helpers/utilities.mk
index fcccd24..10645bf 100644
--- a/make_helpers/utilities.mk
+++ b/make_helpers/utilities.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -127,3 +127,17 @@
#
defined = $(call bool,$(filter-out undefined,$(origin $(1))))
+
+#
+# Determine the path to a program.
+#
+# Parameters:
+#
+# - $(1): The program to search for.
+#
+# Example usage:
+#
+# path-to-gcc := $(call which,gcc) # "/usr/bin/gcc"
+#
+
+which = $(shell command -v $(call escape-shell,$(1)) 2>/dev/null)
diff --git a/make_helpers/windows.mk b/make_helpers/windows.mk
deleted file mode 100644
index c24aa08..0000000
--- a/make_helpers/windows.mk
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# OS specific parts for builds in a Windows_NT environment. The
-# environment variable OS is set to Windows_NT on all modern Windows platforms
-
-# Include generic windows command definitions.
-
-ifndef WINDOWS_MK
- WINDOWS_MK := $(lastword $(MAKEFILE_LIST))
-
- DIR_DELIM := $(strip \)
- BIN_EXT := .exe
- PATH_SEP := ;
-
- # For some Windows native commands there is a problem with the directory delimiter.
- # Make uses / (slash) and the commands expect \ (backslash)
- # We have to provide a means of translating these, so we define local functions.
-
- # ${1} is the file to be copied.
- # ${2} is the destination file name.
- define SHELL_COPY
- $(eval tmp_from_file:=$(subst /,\,${1}))
- $(eval tmp_to_file:=$(subst /,\,${2}))
- copy "${tmp_from_file}" "${tmp_to_file}"
- endef
-
- # ${1} is the directory to be copied.
- # ${2} is the destination directory path.
- define SHELL_COPY_TREE
- $(eval tmp_from_dir:=$(subst /,\,${1}))
- $(eval tmp_to_dir:=$(subst /,\,${2}))
- xcopy /HIVE "${tmp_from_dir}" "${tmp_to_dir}"
- endef
-
- # ${1} is the file to be deleted.
- define SHELL_DELETE
- $(eval tmp_del_file:=$(subst /,\,${*}))
- -@if exist $(tmp_del_file) del /Q $(tmp_del_file)
- endef
-
- # ${1} is a space delimited list of files to be deleted.
- define SHELL_DELETE_ALL
- $(eval $(foreach filename,$(wildcard ${1}),$(call DELETE_IF_THERE,${filename})))
- endef
-
- # ${1} is the directory to be removed.
- define SHELL_REMOVE_DIR
- $(eval tmp_dir:=$(subst /,\,${1}))
- -@if exist "$(tmp_dir)" rd /Q /S "$(tmp_dir)"
- endef
-
- nul := nul
-
- which = $(shell where "$(1)" 2>$(nul))
-endif
-
-# Because git is not available from CMD.EXE, we need to avoid
-# the BUILD_STRING generation which uses git.
-# For now we use "development build".
-# This can be overridden from the command line or environment.
-BUILD_STRING ?= development build
-
-MSVC_NMAKE := nmake.exe
diff --git a/plat/amd/versal2/bl31_setup.c b/plat/amd/versal2/bl31_setup.c
index 6e7fffe..05e4c96 100644
--- a/plat/amd/versal2/bl31_setup.c
+++ b/plat/amd/versal2/bl31_setup.c
@@ -127,14 +127,14 @@
uart_clock = get_uart_clk();
+ /* Initialize the platform config for future decision making */
+ config_setup();
+
setup_console();
NOTICE("TF-A running on %s %d.%d\n", board_name_decode(),
platform_version / 10U, platform_version % 10U);
- /* Initialize the platform config for future decision making */
- config_setup();
-
/*
* Do initial security configuration to allow DRAM/device access. On
* Base only DRAM security is programmable (via TrustZone), but
@@ -170,16 +170,19 @@
{
static uint32_t index;
uint32_t i;
+ int32_t ret = 0;
/* Validate 'handler' and 'id' parameters */
if ((handler == NULL) || (index >= MAX_INTR_EL3)) {
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit_label;
}
/* Check if a handler has already been registered */
for (i = 0; i < index; i++) {
if (id == type_el3_interrupt_table[i].id) {
- return -EALREADY;
+ ret = -EALREADY;
+ goto exit_label;
}
}
@@ -188,7 +191,8 @@
index++;
- return 0;
+exit_label:
+ return ret;
}
static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
diff --git a/plat/amd/versal2/include/platform_def.h b/plat/amd/versal2/include/platform_def.h
index 42c9b08..be1e351 100644
--- a/plat/amd/versal2/include/platform_def.h
+++ b/plat/amd/versal2/include/platform_def.h
@@ -24,6 +24,9 @@
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * PLATFORM_CORE_COUNT_PER_CLUSTER)
+#define E_INVALID_CORE_COUNT -1
+#define E_INVALID_CLUSTER_COUNT -3
+
#define PLAT_MAX_PWR_LVL U(2)
#define PLAT_MAX_RET_STATE U(1)
#define PLAT_MAX_OFF_STATE U(2)
diff --git a/plat/amd/versal2/plat_psci.c b/plat/amd/versal2/plat_psci.c
index e8dc5d3..55842cc 100644
--- a/plat/amd/versal2/plat_psci.c
+++ b/plat/amd/versal2/plat_psci.c
@@ -40,12 +40,14 @@
int32_t cluster = cpu_id / PLATFORM_CORE_COUNT_PER_CLUSTER;
uintptr_t apu_cluster_base = 0, apu_pcli_base, apu_pcli_cluster = 0;
uintptr_t rst_apu_cluster = PSX_CRF + RST_APU0_OFFSET + ((uint64_t)cluster * 0x4U);
+ int32_t ret = PSCI_E_SUCCESS;
VERBOSE("%s: mpidr: 0x%lx, cpuid: %x, cpu: %x, cluster: %x\n",
__func__, mpidr, cpu_id, cpu, cluster);
if (cpu_id == -1) {
- return PSCI_E_INTERN_FAIL;
+ ret = PSCI_E_INTERN_FAIL;
+ goto exit_label;
}
if (cluster > 3U) {
@@ -84,7 +86,8 @@
mmio_write_32(apu_pcli_base + PCLI_PSTATE_OFFSET, PCLI_PSTATE_VAL_CLEAR);
mmio_write_32(apu_pcli_base + PCLI_PREQ_OFFSET, PREQ_CHANGE_REQUEST);
- return PSCI_E_SUCCESS;
+exit_label:
+ return ret;
}
static void zynqmp_nopmu_pwr_domain_off(const psci_power_state_t *target_state)
@@ -101,13 +104,15 @@
static int32_t zynqmp_validate_ns_entrypoint(uint64_t ns_entrypoint)
{
+ int32_t ret = PSCI_E_INVALID_ADDRESS;
+
VERBOSE("Validate ns_entry point %lx\n", ns_entrypoint);
if ((ns_entrypoint) != 0U) {
- return PSCI_E_SUCCESS;
- } else {
- return PSCI_E_INVALID_ADDRESS;
+ ret = PSCI_E_SUCCESS;
}
+
+ return ret;
}
static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state)
diff --git a/plat/amd/versal2/plat_topology.c b/plat/amd/versal2/plat_topology.c
index 0763139..434e08a 100644
--- a/plat/amd/versal2/plat_topology.c
+++ b/plat/amd/versal2/plat_topology.c
@@ -41,6 +41,7 @@
int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
{
uint32_t cluster_id, cpu_id;
+ int32_t ret = 0;
mpidr &= MPIDR_AFFINITY_MASK;
@@ -48,7 +49,8 @@
cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
- return -3;
+ ret = E_INVALID_CLUSTER_COUNT;
+ goto exit_label;
}
/*
@@ -56,8 +58,11 @@
* one of the two clusters present on the platform.
*/
if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER) {
- return -1;
+ ret = E_INVALID_CORE_COUNT;
+ } else {
+ ret = (cpu_id + (cluster_id * PLATFORM_CORE_COUNT_PER_CLUSTER));
}
- return (cpu_id + (cluster_id * PLATFORM_CORE_COUNT_PER_CLUSTER));
+exit_label:
+ return ret;
}
diff --git a/plat/amd/versal2/scmi.c b/plat/amd/versal2/scmi.c
index eec8205..0d384a5 100644
--- a/plat/amd/versal2/scmi.c
+++ b/plat/amd/versal2/scmi.c
@@ -288,13 +288,16 @@
uint32_t start_idx)
{
const struct scmi_clk *clock = clk_find(agent_id, scmi_id);
+ int32_t ret = SCMI_SUCCESS;
if (clock == NULL) {
- return SCMI_NOT_FOUND;
+ ret = SCMI_NOT_FOUND;
+ goto exit_label;
}
if (start_idx > 0U) {
- return SCMI_OUT_OF_RANGE;
+ ret = SCMI_OUT_OF_RANGE;
+ goto exit_label;
}
if (array == NULL) {
@@ -304,10 +307,11 @@
VERBOSE("SCMI: CLK: id: %d, clk_name: %s, get_rate %lu\n",
scmi_id, clock->name, *array);
} else {
- return SCMI_GENERIC_ERROR;
+ ret = SCMI_GENERIC_ERROR;
}
- return SCMI_SUCCESS;
+exit_label:
+ return ret;
}
unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, unsigned int scmi_id)
@@ -529,12 +533,13 @@
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);
+ const char *ret = NULL;
- if (pd == NULL) {
- return NULL;
+ if (pd != NULL) {
+ ret = pd->name;
}
- return pd->name;
+ return ret;
}
unsigned int plat_scmi_pd_statistics(unsigned int agent_id, unsigned long *pd_id)
@@ -550,14 +555,15 @@
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);
+ uint32_t ret = SCMI_NOT_SUPPORTED;
- if (pd == NULL) {
- return SCMI_NOT_SUPPORTED;
+ if (pd != NULL) {
+ NOTICE("SCMI: PD: get id: %d, state: %x\n", pd_id, pd->state);
+
+ ret = pd->state;
}
- NOTICE("SCMI: PD: get id: %d, state: %x\n", pd_id, pd->state);
-
- return pd->state;
+ return ret;
}
int32_t plat_scmi_pd_set_state(unsigned int agent_id, unsigned int flags, unsigned int pd_id,
@@ -568,14 +574,15 @@
if (pd == NULL) {
ret = SCMI_NOT_SUPPORTED;
- } else {
-
- NOTICE("SCMI: PD: set id: %d, orig state: %x, new state: %x, flags: %x\n",
- pd_id, pd->state, state, flags);
-
- pd->state = state;
+ goto exit_label;
}
+ NOTICE("SCMI: PD: set id: %d, orig state: %x, new state: %x, flags: %x\n",
+ pd_id, pd->state, state, flags);
+
+ pd->state = state;
+
+exit_label:
return ret;
}
@@ -638,8 +645,9 @@
size_t i;
int32_t ret;
- for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++)
+ for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) {
scmi_smt_init_agent_channel(&scmi_channel[i]);
+ }
INFO("SCMI: Server initialized\n");
@@ -649,12 +657,14 @@
for (i = 0U; i < ARRAY_SIZE(scmi0_clock); i++) {
/* Keep i2c on 100MHz to calculate rates properly */
- if ((i >= CLK_I2C0_0) && (i <= CLK_I2C7_0))
+ if ((i >= CLK_I2C0_0) && (i <= CLK_I2C7_0)) {
continue;
+ }
/* Keep UFS clocks to default values to get the expected rates */
- if (i >= CLK_UFS0_0 && i <= CLK_UFS0_2)
+ if ((i >= CLK_UFS0_0) && (i <= CLK_UFS0_2)) {
continue;
+ }
/*
* SPP supports multiple versions.
diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
index dd82a10..6d60cbe 100644
--- a/plat/arm/board/a5ds/platform.mk
+++ b/plat/arm/board/a5ds/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -75,9 +75,7 @@
${DYN_CFG_SOURCES} \
${A5DS_SECURITY_SOURCES}
-# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
-ifdef UNIX_MK
-
+# Add the FDT_SOURCES and options for Dynamic Config
FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
TB_FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_tb_fw_config.dtb
@@ -94,7 +92,6 @@
FDT_SOURCES += plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \
plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \
${FVP_HW_CONFIG_DTS}
-endif
NEED_BL32 := yes
diff --git a/plat/arm/board/fvp/fdts/fvp_stmm_manifest.dts b/plat/arm/board/fvp/fdts/fvp_stmm_manifest.dts
new file mode 100644
index 0000000..df6810f
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_stmm_manifest.dts
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include <platform_def.h>
+
+/ {
+#define MODE_SEL0 (0x1)
+#define MODE_SEL1 (0x2)
+
+#define SECURE_RO 0x1
+#define SECURE_RW 0x3
+#define SECURE_EXECUTE_RO 0x5
+#define SECURE_EXECUTE_RW 0x7
+#define NON_SECURE_RO 0x9
+#define NON_SECURE_RW 0xB
+#define NON_SECURE_EXECUTE_RO 0xD
+#define NON_SECURE_EXECUTE_RW 0xF
+ /*
+ * FF-A compatible Secure Partition Manager parses the
+ * config file and fetch the following booting arguments to
+ * pass on to the StandAloneMM(StMM) Secure Partition.
+ */
+ compatible = "arm,ffa-manifest-1.0";
+
+ description = "FVP Base StandaloneMm";
+ ffa-version = <0x00010002>; /* 31:16 - Major, 15:0 - Minor */
+ uuid = <0xdcae8d37 0x46446bf0 0xab401483 0xa3873c93>;
+ id = <0x8001>;
+ execution-ctx-count = <PLATFORM_CORE_COUNT>;
+ exception-level = <MODE_SEL0>; /* SEL0*/
+ execution-state = <0>; /* AArch64*/
+ load-address = <0x0 0xff200000>;
+ image-size = <0x0 0x00300000>;
+ xlat-granule = <0>; /* 4KiB */
+ boot-order = <0>;
+ messaging-method = <0x603>; /* Direct req/resp/req2/resp2 supported. */
+ gp-register-num = <0>;
+
+ device-regions {
+ compatible = "arm,ffa-manifest-device-regions";
+
+ /**
+ * System registers, rtc, uart and etc regions for access from S-EL0.
+ */
+ io_fpga {
+ base-address = <0x0 0x1C000000>;
+ pages-count = <0x3000>;
+ attributes = <SECURE_RW>;
+ };
+
+ system_reg_el0 {
+ base-address = <0x0 0x1C010000>;
+ pages-count = <0x10>;
+ attributes = <SECURE_RW>;
+ };
+
+ /**
+ * ARM CSS SoC Peripherals area.
+ * Similar to SOC_CSS_MAP_DEVICE.
+ */
+ soc_components {
+ base-address = <0x0 0x20000000>;
+ pages-count = <0xc200>;
+ attributes = <SECURE_RO>;
+ };
+
+ /**
+ * NOR0 Flash region, used for Firmware Image Update.
+ */
+ nor_flash0 {
+ base-address = <0x0 0x08000000>;
+ pages-count = <0x4000>;
+ attributes = <SECURE_RW>;
+ };
+
+ /**
+ * NOR1 Flash region, used for Secure booting.
+ */
+ nor_flash1 {
+ base-address = <0x0 0x0c000000>;
+ pages-count = <0x4000>;
+ attributes = <SECURE_RW>;
+ };
+ };
+
+ memory-regions {
+ compatible = "arm,ffa-manifest-memory-regions";
+
+ /*
+ * SPM Payload memory. Mapped as code region for S-EL0
+ * Similar to ARM_SP_IMAGE_MMAP.
+ */
+ stmm_region {
+ description = "image";
+ base-address = <0x0 0xff200000>;
+ pages-count = <0x300>;
+ /* StMM will remap the regions during runtime */
+ attributes = <SECURE_EXECUTE_RO>;
+ };
+
+ /*
+ * Memory shared between EL3 and S-EL0.
+ * Similar to ARM_SPM_BUF_EL0_MMAP.
+ */
+ rx-tx-buffers {
+ description = "shared-buff";
+ base-address = <0x0 0xff500000>;
+ pages-count = <0x100>;
+ attributes = <SECURE_RW>;
+ };
+
+ /*
+ * Memory shared between Normal world and S-EL0.
+ * Similar to ARM_SP_IMAGE_NS_BUF_MMAP.
+ */
+ ns_comm_buffer {
+ /*
+ * Description is needed for StMM to identify
+ * ns-communication buffer.
+ */
+ description = "ns-comm";
+ base-address = <0x0 0xff600000>;
+ pages-count = <0x10>;
+ attributes = <NON_SECURE_RW>;
+ };
+
+ /*
+ * Heap used by SP to allocate memory for DMA.
+ */
+ heap {
+ /*
+ * Description is needed for StMM to identify
+ * heap buffer.
+ */
+ description = "heap";
+ base-address = <0x0 0xFF610000>;
+ pages-count = <0x7F0>;
+ attributes = <SECURE_RW>;
+ };
+ };
+};
diff --git a/plat/arm/board/fvp/fvp_security.c b/plat/arm/board/fvp/fvp_security.c
index 573d92e..5b97034 100644
--- a/plat/arm/board/fvp/fvp_security.c
+++ b/plat/arm/board/fvp/fvp_security.c
@@ -24,7 +24,7 @@
const arm_tzc_regions_info_t fvp_tzc_regions[] = {
ARM_TZC_REGIONS_DEF,
-#if !SPM_MM && !ENABLE_RME
+#if !SPM_MM && !ENABLE_RME && !(SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP)
{FVP_DRAM3_BASE, FVP_DRAM3_END,
ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS},
{FVP_DRAM4_BASE, FVP_DRAM4_END,
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index e0c9725..df4be8f 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -170,6 +170,8 @@
# elif SPMC_AT_EL3
# define PLAT_ARM_MMAP_ENTRIES 13
# define MAX_XLAT_TABLES 11
+# define PLAT_SP_IMAGE_MMAP_REGIONS 30
+# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10
# else
# define PLAT_ARM_MMAP_ENTRIES 9
# if USE_DEBUGFS
@@ -220,7 +222,8 @@
* In case of PSA Crypto API, few algorithms like ECDSA needs bigger BL1 RW
* area.
*/
-#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA || PSA_CRYPTO
+#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA || PSA_CRYPTO || \
+FVP_TRUSTED_SRAM_SIZE == 512
#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xC000)
#else
#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000)
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 08fbfee..8793840 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -22,7 +22,12 @@
# only; enable redistributor frames of all CPU cores by default.
FVP_GICR_REGION_PROTECTION := 0
+ifeq (${HW_ASSISTED_COHERENCY}, 0)
FVP_DT_PREFIX := fvp-base-gicv3-psci
+else
+FVP_DT_PREFIX := fvp-base-gicv3-psci-dynamiq
+endif
+# fdts is wrong otherwise
# Size (in kilobytes) of the Trusted SRAM region to utilize when building for
# the FVP platform. This option defaults to 256.
@@ -58,6 +63,7 @@
ENABLE_TRBE_FOR_NS := 2
ENABLE_FEAT_D128 := 2
ENABLE_FEAT_FPMR := 2
+ ENABLE_FEAT_MOPS := 2
endif
ENABLE_SYS_REG_TRACE_FOR_NS := 2
@@ -338,7 +344,6 @@
endif
# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
-ifdef UNIX_MK
FVP_HW_CONFIG_DTS := fdts/${FVP_DT_PREFIX}.dts
FDT_SOURCES += ${FVP_HW_CONFIG_DTS}
@@ -390,7 +395,6 @@
# Add the HW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG}))
-endif
ifeq (${TRANSFER_LIST}, 1)
include lib/transfer_list/transfer_list.mk
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index 5a22628..71f7bb3 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -259,7 +259,7 @@
#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000)
#elif TARGET_PLATFORM >= 3
-#if TC_FPGA_ANDROID_IMG_IN_RAM
+#if TC_FPGA_FS_IMG_IN_RAM
/* 10GB reserved for system+userdata+vendor images */
#define SYSTEM_IMAGE_SIZE 0xC0000000 /* 3GB */
#define USERDATA_IMAGE_SIZE 0x140000000 /* 5GB */
@@ -273,8 +273,8 @@
#define PLAT_ARM_DRAM2_SIZE ULL(0x380000000) - ANDROID_FS_SIZE
#else
#define PLAT_ARM_DRAM2_BASE ULL(0x880000000)
-#define PLAT_ARM_DRAM2_SIZE ULL(0x380000000)
-#endif /* TC_FPGA_ANDROID_IMG_IN_RAM */
+#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000)
+#endif /* TC_FPGA_FS_IMG_IN_RAM */
#endif /* TARGET_VERSION >= 3 */
@@ -443,18 +443,22 @@
#undef PLAT_ARM_BOOT_UART_CLK_IN_HZ
#undef PLAT_ARM_RUN_UART_CLK_IN_HZ
-#if TARGET_FLAVOUR_FVP
-#define PLAT_ARM_BOOT_UART_BASE TC_UART1
-#define TC_UARTCLK 7372800
-#else /* TARGET_FLAVOUR_FPGA */
-#define PLAT_ARM_BOOT_UART_BASE TC_UART0
-#if TARGET_PLATFORM <= 2
-#define TC_UARTCLK 5000000
-#elif TARGET_PLATFORM >= 3
-#define TC_UARTCLK 3750000
-#endif /* TARGET_PLATFORM >= 3 */
#undef ARM_CONSOLE_BAUDRATE
#define ARM_CONSOLE_BAUDRATE 38400
+
+#if TARGET_PLATFORM <= 2
+#define TC_UARTCLK 5000000
+#elif TARGET_PLATFORM == 3
+#define TC_UARTCLK 3750000
+#elif TARGET_PLATFORM == 4
+#define TC_UARTCLK 4000000
+#endif /* TARGET_PLATFORM <=2 */
+
+
+#if TARGET_FLAVOUR_FVP
+#define PLAT_ARM_BOOT_UART_BASE TC_UART1
+#else /* TARGET_FLAVOUR_FPGA */
+#define PLAT_ARM_BOOT_UART_BASE TC_UART0
#endif /* TARGET_FLAVOUR_FPGA */
#define PLAT_ARM_RUN_UART_BASE TC_UART0
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 759c85d..1ec7c44 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -77,8 +77,8 @@
$(error TARGET_FLAVOUR must be fvp or fpga)
endif
-# Support for loading Android Image to DRAM
-TC_FPGA_ANDROID_IMG_IN_RAM := 0
+# Support for loading FS Image to DRAM
+TC_FPGA_FS_IMG_IN_RAM := 0
# Support Loading of FIP image to DRAM
TC_FPGA_FIP_IMG_IN_RAM := 0
@@ -92,7 +92,7 @@
TC_RESOLUTION_$(call uppercase,${TC_RESOLUTION}) \
TC_DPU_USE_SCMI_CLK \
TC_SCMI_PD_CTRL_EN \
- TC_FPGA_ANDROID_IMG_IN_RAM \
+ TC_FPGA_FS_IMG_IN_RAM \
TC_FPGA_FIP_IMG_IN_RAM \
TC_DPU_USE_SIMPLE_PANEL \
))
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 07b3b62..17dc0ed 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -52,17 +52,10 @@
#pragma weak bl2_plat_arch_setup
#pragma weak bl2_plat_sec_mem_layout
-#if ENABLE_RME
#define MAP_BL2_TOTAL MAP_REGION_FLAT( \
bl2_tzram_layout.total_base, \
bl2_tzram_layout.total_size, \
- MT_MEMORY | MT_RW | MT_ROOT)
-#else
-#define MAP_BL2_TOTAL MAP_REGION_FLAT( \
- bl2_tzram_layout.total_base, \
- bl2_tzram_layout.total_size, \
- MT_MEMORY | MT_RW | MT_SECURE)
-#endif /* ENABLE_RME */
+ MT_MEMORY | MT_RW | EL3_PAS)
#pragma weak arm_bl2_plat_handle_post_image_load
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 73d96c5..580ef5f 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -363,7 +363,7 @@
endif
# Pointer Authentication sources
-ifeq (${ENABLE_PAUTH}, 1)
+ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3))
PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c
endif
diff --git a/plat/arm/common/arm_ni.c b/plat/arm/common/arm_ni.c
index b3ad8b3..9c105f7 100644
--- a/plat/arm/common/arm_ni.c
+++ b/plat/arm/common/arm_ni.c
@@ -144,19 +144,33 @@
for (uint32_t i = 0U; i < vd_count; i++) {
vd_addr = global_cfg + mmio_read_32(global_cfg + NI_CHILD_POINTER(i));
+
+ VERBOSE("Voltage domain %u at 0x%lx node info: 0x%x\n",
+ i, vd_addr, mmio_read_32(vd_addr));
+
pd_count = mmio_read_32(vd_addr + NI_CHILD_NODE_COUNT);
for (uint32_t j = 0U; j < pd_count; j++) {
pd_addr = global_cfg + mmio_read_32(vd_addr + NI_CHILD_POINTER(j));
cd_count = mmio_read_32(pd_addr + NI_CHILD_NODE_COUNT);
+ VERBOSE("Power domain %u at 0x%lx node info: 0x%x\n",
+ j, pd_addr, mmio_read_32(pd_addr));
+
for (uint32_t k = 0U; k < cd_count; k++) {
cd_addr = global_cfg + mmio_read_32(pd_addr + NI_CHILD_POINTER(k));
comp_count = mmio_read_32(cd_addr + NI_CHILD_NODE_COUNT);
+ VERBOSE("Clock domain %u at 0x%lx node info: 0x%x\n",
+ k, cd_addr, mmio_read_32(cd_addr));
+
for (uint32_t l = 0U; l < comp_count; l++) {
comp_addr = global_cfg +
mmio_read_32(cd_addr + NI_CHILD_POINTER(l));
+
+ VERBOSE("Component %u at 0x%lx node info: 0x%x\n",
+ l, comp_addr, mmio_read_32(comp_addr));
+
ni_setup_component(comp_addr);
}
}
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index a603f2b..dbb6f81 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -9,6 +9,7 @@
#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
+#include <lib/transfer_list.h>
#include <lib/xlat_tables/xlat_tables_compat.h>
#include <plat/common/platform.h>
#include <services/arm_arch_svc.h>
@@ -129,3 +130,13 @@
/* Create the page tables to reflect the above mappings */
init_xlat_tables();
}
+
+#if ((MEASURED_BOOT || DICE_PROTECTION_ENVIRONMENT) && TRANSFER_LIST)
+int plat_handoff_mboot(const void *data, uint32_t data_size, void *tl_base)
+{
+ if (!transfer_list_add(tl_base, TL_TAG_TPM_EVLOG, data_size, data))
+ return -1;
+
+ return 0;
+}
+#endif
diff --git a/plat/intel/soc/agilex5/bl31_plat_setup.c b/plat/intel/soc/agilex5/bl31_plat_setup.c
index c090117..ab03928 100644
--- a/plat/intel/soc/agilex5/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl31_plat_setup.c
@@ -196,6 +196,9 @@
NOTICE("BL31: CPU ID = %x\n", cpuid);
INFO("BL31: Invalidate Data cache\n");
invalidate_dcache_all();
+
+ /* Invalidate for NS EL2 and EL1 */
+ invalidate_cache_low_el();
}
/* Get non-secure image entrypoint for BL33. Zephyr and Linux */
diff --git a/plat/intel/soc/agilex5/soc/agilex5_cache.S b/plat/intel/soc/agilex5/soc/agilex5_cache.S
index 52ed5d3..f8c6a2d 100644
--- a/plat/intel/soc/agilex5/soc/agilex5_cache.S
+++ b/plat/intel/soc/agilex5/soc/agilex5_cache.S
@@ -15,14 +15,16 @@
* --------------------------------------------------------
*/
func invalidate_cache_low_el
- mrs x0,SCR_EL3
- orr x1,x0,#SCR_NS_BIT
+ mrs x0, SCR_EL3
+ orr x1, x0, #SCR_NS_BIT
msr SCR_EL3, x1
isb
tlbi ALLE2
dsb sy
tlbi ALLE1
dsb sy
+ msr SCR_EL3, x0
+ isb
endfunc invalidate_cache_low_el
.pushsection .text.asm_dcache_level, "ax"
diff --git a/plat/mediatek/build_helpers/mtk_build_helpers.mk b/plat/mediatek/build_helpers/mtk_build_helpers.mk
index 0cb2014..a095ba9 100644
--- a/plat/mediatek/build_helpers/mtk_build_helpers.mk
+++ b/plat/mediatek/build_helpers/mtk_build_helpers.mk
@@ -71,8 +71,9 @@
$(eval SOURCES := $(2))
$(eval OBJS_TEMP := $(addprefix $(BUILD_DIR)/$(MODULE)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
$(eval MODULE_OBJS += $(OBJS_TEMP))
+ $(eval BL := $(call uppercase,$(3)))
-$(eval $(call MAKE_OBJS,$(BUILD_DIR)/$(MODULE),$(SOURCES),${3}))
+$(eval $(call MAKE_OBJS,$(BUILD_DIR)/$(MODULE),$(SOURCES),${3},$(BL)))
libraries: $(OBJS_TEMP)
endef
diff --git a/plat/mediatek/drivers/emi/common/emi.h b/plat/mediatek/drivers/emi/common/emi.h
new file mode 100644
index 0000000..eb2a0d3
--- /dev/null
+++ b/plat/mediatek/drivers/emi/common/emi.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2025, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_H
+#define EMI_H
+
+#include <stdint.h>
+
+#define EMI_MPU_ALIGN_BITS 12
+
+uint64_t sip_emi_mpu_set_protection(u_register_t start, u_register_t end, u_register_t region);
+
+#endif /* EMI_H */
diff --git a/plat/mediatek/drivers/emi/emi_stub.c b/plat/mediatek/drivers/emi/emi_stub.c
new file mode 100644
index 0000000..3682bf7
--- /dev/null
+++ b/plat/mediatek/drivers/emi/emi_stub.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2025, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <common/debug.h>
+
+#include "common/emi.h"
+#include <mtk_sip_svc.h>
+
+uint64_t sip_emi_mpu_set_protection(u_register_t start, u_register_t end,
+ u_register_t region)
+{
+ return MTK_SIP_E_NOT_SUPPORTED;
+}
diff --git a/plat/mediatek/drivers/emi/rules.mk b/plat/mediatek/drivers/emi/rules.mk
new file mode 100644
index 0000000..9f462bb
--- /dev/null
+++ b/plat/mediatek/drivers/emi/rules.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2025, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := emi
+
+ifeq ($(MTKLIB_PATH),)
+LOCAL_SRCS-y := $(LOCAL_DIR)/emi_stub.c
+endif
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/include/mtk_sip_def.h b/plat/mediatek/include/mtk_sip_def.h
index ff12408..6f496d2 100644
--- a/plat/mediatek/include/mtk_sip_def.h
+++ b/plat/mediatek/include/mtk_sip_def.h
@@ -13,6 +13,7 @@
_func(MTK_SIP_KERNEL_DFD, 0x205) \
_func(MTK_SIP_KERNEL_MSDC, 0x273) \
_func(MTK_SIP_VCORE_CONTROL, 0x506) \
+ _func(MTK_SIP_EMIDBG_CONTROL, 0x50B) \
_func(MTK_SIP_IOMMU_CONTROL, 0x514) \
_func(MTK_SIP_AUDIO_CONTROL, 0x517) \
_func(MTK_SIP_APUSYS_CONTROL, 0x51E) \
@@ -21,9 +22,11 @@
_func(MTK_SIP_KERNEL_VCP_CONTROL, 0x52C)
#define MTK_SIP_SMC_FROM_S_EL1_TABLE(_func) \
- _func(MTK_SIP_TEE_MPU_PERM_SET, 0x031)
+ _func(MTK_SIP_TEE_MPU_PERM_SET, 0x031) \
+ _func(MTK_SIP_TEE_EMI_MPU_CONTROL, 0x048)
#define MTK_SIP_SMC_FROM_BL33_TABLE(_func) \
- _func(MTK_SIP_KERNEL_BOOT, 0x115)
+ _func(MTK_SIP_KERNEL_BOOT, 0x115) \
+ _func(MTK_SIP_BL_EMIMPU_CONTROL, 0x415)
#endif /* MTK_SIP_DEF_H */
diff --git a/plat/mediatek/mt8196/include/platform_def.h b/plat/mediatek/mt8196/include/platform_def.h
index 4f40890..6b6416a 100644
--- a/plat/mediatek/mt8196/include/platform_def.h
+++ b/plat/mediatek/mt8196/include/platform_def.h
@@ -169,8 +169,21 @@
/*******************************************************************************
* EMI MPU related constants
*******************************************************************************/
-#define EMI_MPU_BASE (IO_PHYS + 0x00428000)
-#define SUB_EMI_MPU_BASE (IO_PHYS + 0x00528000)
+#define EMI_MPU_BASE (IO_PHYS + 0x00428000)
+#define SUB_EMI_MPU_BASE (IO_PHYS + 0x00528000)
+#define EMI_SLB_BASE (IO_PHYS + 0x0042e000)
+#define SUB_EMI_SLB_BASE (IO_PHYS + 0x0052e000)
+#define CHN0_EMI_APB_BASE (IO_PHYS + 0x00201000)
+#define CHN1_EMI_APB_BASE (IO_PHYS + 0x00205000)
+#define CHN2_EMI_APB_BASE (IO_PHYS + 0x00209000)
+#define CHN3_EMI_APB_BASE (IO_PHYS + 0x0020D000)
+#define EMI_APB_BASE (IO_PHYS + 0x00429000)
+#define INFRA_EMI_DEBUG_CFG_BASE (IO_PHYS + 0x00425000)
+#define NEMI_SMPU_BASE (IO_PHYS + 0x0042f000)
+#define SEMI_SMPU_BASE (IO_PHYS + 0x0052f000)
+#define SUB_EMI_APB_BASE (IO_PHYS + 0x00529000)
+#define SUB_INFRA_EMI_DEBUG_CFG_BASE (IO_PHYS + 0x00525000)
+#define SUB_INFRACFG_AO_MEM_BASE (IO_PHYS + 0x00504000)
/*******************************************************************************
* System counter frequency related constants
diff --git a/plat/mediatek/mt8196/platform.mk b/plat/mediatek/mt8196/platform.mk
index 3c827c9..8ae8e28 100644
--- a/plat/mediatek/mt8196/platform.mk
+++ b/plat/mediatek/mt8196/platform.mk
@@ -27,12 +27,18 @@
MODULES-y += $(MTK_PLAT)/lib/pm
MODULES-y += $(MTK_PLAT)/drivers/apusys
MODULES-y += $(MTK_PLAT)/drivers/dp
+MODULES-y += $(MTK_PLAT)/drivers/emi
MODULES-y += $(MTK_PLAT)/drivers/mcusys
MODULES-y += $(MTK_PLAT)/drivers/timer
MODULES-y += $(MTK_PLAT)/drivers/vcp
MODULES-y += $(MTK_PLAT)/helpers
MODULES-y += $(MTK_PLAT)/topology
+ifneq ($(MTKLIB_PATH),)
+LDFLAGS += -L $(dir $(MTKLIB_PATH))
+LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(MTKLIB_PATH)))
+endif
+
PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \
drivers/ti/uart/aarch64/16550_console.S \
lib/bl_aux_params/bl_aux_params.c
diff --git a/plat/nuvoton/npcm845x/platform.mk b/plat/nuvoton/npcm845x/platform.mk
index 1959aac..d73756c 100644
--- a/plat/nuvoton/npcm845x/platform.mk
+++ b/plat/nuvoton/npcm845x/platform.mk
@@ -318,9 +318,8 @@
endif
# Pointer Authentication sources
-ifeq (${ENABLE_PAUTH}, 1)
-PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c \
- lib/extensions/pauth/pauth_helpers.S
+ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3))
+PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c
endif
ifeq (${SPD},spmd)
diff --git a/plat/nxp/s32/s32g274ardb2/include/platform_def.h b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
index 1a4c495..cb16658 100644
--- a/plat/nxp/s32/s32g274ardb2/include/platform_def.h
+++ b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
@@ -48,7 +48,7 @@
/* We'll be doing a 1:1 mapping anyway */
#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 36)
-#define MAX_MMAP_REGIONS U(8)
+#define MAX_MMAP_REGIONS U(18)
#define MAX_XLAT_TABLES U(32)
/* Console settings */
diff --git a/plat/nxp/s32/s32g274ardb2/include/s32cc-bl-common.h b/plat/nxp/s32/s32g274ardb2/include/s32cc-bl-common.h
new file mode 100644
index 0000000..0f0c804
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/include/s32cc-bl-common.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef S32CC_BL_COMMON_H
+#define S32CC_BL_COMMON_H
+
+int s32cc_bl_mmu_setup(void);
+
+#endif /* S32CC_BL_COMMON_H */
diff --git a/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
index 4645f01..0929f9d 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
+++ b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
@@ -4,15 +4,21 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <errno.h>
+
#include <common/debug.h>
#include <common/desc_image_load.h>
#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <plat_console.h>
#include <s32cc-clk-drv.h>
+
#include <plat_io_storage.h>
+#include <s32cc-bl-common.h>
#include <s32cc-ncore.h>
+#define SIUL20_BASE UL(0x4009C000)
#define SIUL2_PC09_MSCR UL(0x4009C2E4)
#define SIUL2_PC10_MSCR UL(0x4009C2E8)
#define SIUL2_PC10_LIN0_IMCR UL(0x4009CA40)
@@ -38,6 +44,20 @@
void bl2_platform_setup(void)
{
+ int ret;
+
+ ret = mmap_add_dynamic_region(S32G_FIP_BASE, S32G_FIP_BASE,
+ S32G_FIP_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ if (ret != 0) {
+ panic();
+ }
+}
+
+static int s32g_mmap_siul2(void)
+{
+ return mmap_add_dynamic_region(SIUL20_BASE, SIUL20_BASE, PAGE_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE);
}
static void linflex_config_pinctrl(void)
@@ -55,14 +75,6 @@
{
int ret;
- ret = s32cc_init_early_clks();
- if (ret != 0) {
- panic();
- }
-
- linflex_config_pinctrl();
- console_s32g2_register();
-
/* Restore (clear) the CAIUTC[IsolEn] bit for the primary cluster, which
* we have manually set during early BL2 boot.
*/
@@ -71,6 +83,29 @@
ncore_init();
ncore_caiu_online(A53_CLUSTER0_CAIU);
+ ret = s32cc_init_core_clocks();
+ if (ret != 0) {
+ panic();
+ }
+
+ ret = s32cc_bl_mmu_setup();
+ if (ret != 0) {
+ panic();
+ }
+
+ ret = s32cc_init_early_clks();
+ if (ret != 0) {
+ panic();
+ }
+
+ ret = s32g_mmap_siul2();
+ if (ret != 0) {
+ panic();
+ }
+
+ linflex_config_pinctrl();
+ console_s32g2_register();
+
plat_s32g2_io_setup();
}
@@ -78,3 +113,26 @@
{
}
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+ const struct bl_mem_params_node *desc = get_bl_mem_params_node(image_id);
+ const struct image_info *img_info;
+ size_t size;
+
+ if (desc == NULL) {
+ return -EINVAL;
+ }
+
+ img_info = &desc->image_info;
+
+ if ((img_info == NULL) || (img_info->image_max_size == 0U)) {
+ return -EINVAL;
+ }
+
+ size = page_align(img_info->image_max_size, UP);
+
+ return mmap_add_dynamic_region(img_info->image_base,
+ img_info->image_base,
+ size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+}
diff --git a/plat/nxp/s32/s32g274ardb2/plat_bl31_setup.c b/plat/nxp/s32/s32g274ardb2/plat_bl31_setup.c
index 03bf35c..22c66b0 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_bl31_setup.c
+++ b/plat/nxp/s32/s32g274ardb2/plat_bl31_setup.c
@@ -4,10 +4,14 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <common/debug.h>
#include <drivers/arm/gicv3.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <plat_console.h>
+#include <s32cc-bl-common.h>
+
static entry_point_info_t bl33_image_ep_info;
static unsigned int s32g2_mpidr_to_core_pos(unsigned long mpidr);
@@ -25,8 +29,6 @@
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
- console_s32g2_register();
-
SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
bl33_image_ep_info.pc = BL33_BASE;
bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
@@ -35,6 +37,14 @@
void bl31_plat_arch_setup(void)
{
+ int ret;
+
+ ret = s32cc_bl_mmu_setup();
+ if (ret != 0) {
+ panic();
+ }
+
+ console_s32g2_register();
}
struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
@@ -42,6 +52,31 @@
return &bl33_image_ep_info;
}
+static int mmap_gic(const gicv3_driver_data_t *gic_data)
+{
+ size_t gicr_size;
+ int ret;
+
+ ret = mmap_add_dynamic_region(gic_data->gicd_base,
+ gic_data->gicd_base,
+ PAGE_SIZE_64KB,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ if (ret != 0) {
+ return ret;
+ }
+
+ gicr_size = gicv3_redist_size(0x0U);
+ ret = mmap_add_dynamic_region(gic_data->gicr_base,
+ gic_data->gicr_base,
+ gicr_size * gic_data->rdistif_num,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
void bl31_platform_setup(void)
{
static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
@@ -52,8 +87,13 @@
.rdistif_base_addrs = rdistif_base_addrs,
.mpidr_to_core_pos = s32g2_mpidr_to_core_pos,
};
-
unsigned int pos = plat_my_core_pos();
+ int ret;
+
+ ret = mmap_gic(&plat_gic_data);
+ if (ret != 0) {
+ panic();
+ }
gicv3_driver_init(&plat_gic_data);
gicv3_distif_init();
diff --git a/plat/nxp/s32/s32g274ardb2/plat_console.c b/plat/nxp/s32/s32g274ardb2/plat_console.c
index 542fa7b..e65e439 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_console.c
+++ b/plat/nxp/s32/s32g274ardb2/plat_console.c
@@ -5,6 +5,7 @@
*/
#include <common/debug.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
#include <linflex.h>
#include <plat_console.h>
#include <platform_def.h>
@@ -17,6 +18,12 @@
};
int ret;
+ ret = mmap_add_dynamic_region(UART_BASE, UART_BASE, PAGE_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ if (ret != 0) {
+ panic();
+ }
+
ret = console_linflex_register(UART_BASE, UART_CLOCK_HZ,
UART_BAUDRATE, &s32g2_console);
if (ret == 0) {
diff --git a/plat/nxp/s32/s32g274ardb2/platform.mk b/plat/nxp/s32/s32g274ardb2/platform.mk
index 7d6e960..4ec7cd0 100644
--- a/plat/nxp/s32/s32g274ardb2/platform.mk
+++ b/plat/nxp/s32/s32g274ardb2/platform.mk
@@ -38,6 +38,9 @@
ERRATA_SPECULATIVE_AT := 1
ERRATA_S32_051700 := 1
+PLAT_XLAT_TABLES_DYNAMIC := 1
+$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
+
# Selecting Drivers for SoC
$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
$(eval $(call SET_NXP_MAKE_FLAG,CLK_NEEDED,BL_COMM))
@@ -47,6 +50,8 @@
BL_COMMON_SOURCES += \
${PLAT_S32G274ARDB2}/plat_console.c \
${PLAT_S32G274ARDB2}/plat_helpers.S \
+ ${PLAT_S32G274ARDB2}/s32cc_bl_common.c \
+ ${XLAT_TABLES_LIB_SRCS} \
BL2_SOURCES += \
${BL_COMMON_SOURCES} \
diff --git a/plat/nxp/s32/s32g274ardb2/s32cc_bl_common.c b/plat/nxp/s32/s32g274ardb2/s32cc_bl_common.c
new file mode 100644
index 0000000..4664438
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/s32cc_bl_common.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <errno.h>
+
+#include <common/bl_common.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <s32cc-bl-common.h>
+
+int s32cc_bl_mmu_setup(void)
+{
+ const unsigned long code_start = BL_CODE_BASE;
+ const unsigned long rw_start = BL_CODE_END;
+ unsigned long code_size;
+ unsigned long rw_size;
+
+ if (code_start > BL_CODE_END) {
+ return -EINVAL;
+ }
+
+ if (rw_start > BL_END) {
+ return -EINVAL;
+ }
+
+ code_size = BL_CODE_END - code_start;
+ rw_size = BL_END - rw_start;
+
+ mmap_add_region(code_start, code_start, code_size,
+ MT_RO | MT_MEMORY | MT_SECURE);
+ mmap_add_region(rw_start, rw_start, rw_size,
+ MT_RW | MT_MEMORY | MT_SECURE);
+
+ init_xlat_tables();
+ enable_mmu_el3(0);
+
+ return 0;
+}
diff --git a/plat/nxp/soc-lx2160a/ddr_fip.mk b/plat/nxp/soc-lx2160a/ddr_fip.mk
index c303ced..c1f14dc 100644
--- a/plat/nxp/soc-lx2160a/ddr_fip.mk
+++ b/plat/nxp/soc-lx2160a/ddr_fip.mk
@@ -1,5 +1,6 @@
#
# Copyright 2020 NXP
+# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -67,7 +68,7 @@
# Variables for use with Certificate Generation Tool
CRTTOOLPATH ?= tools/cert_create
-CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT}
+CRTTOOL ?= ${CRTTOOLPATH}/cert_create$(.exe)
ifneq (${GENERATE_COT},0)
ddr_certificates: ${DDR_CRT_DEPS} ${CRTTOOL}
@@ -82,7 +83,7 @@
# Variables for use with Firmware Image Package
FIPTOOLPATH ?= tools/fiptool
-FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT}
+FIPTOOL ?= ${FIPTOOLPATH}/fiptool$(.exe)
${BUILD_PLAT}/${DDR_FIP_NAME}: ${DDR_FIP_DEPS} ${FIPTOOL}
$(eval ${CHECK_DDR_FIP_CMD})
diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
index 51497bd..5e3a61a 100644
--- a/plat/qemu/common/common.mk
+++ b/plat/qemu/common/common.mk
@@ -149,9 +149,8 @@
endif
# Pointer Authentication sources
-ifeq (${ENABLE_PAUTH}, 1)
+ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3))
PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c
-CTX_INCLUDE_PAUTH_REGS := 1
endif
endif
diff --git a/plat/qemu/common/qemu_bl31_setup.c b/plat/qemu/common/qemu_bl31_setup.c
index e502e7b..81ce102 100644
--- a/plat/qemu/common/qemu_bl31_setup.c
+++ b/plat/qemu/common/qemu_bl31_setup.c
@@ -68,6 +68,9 @@
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
+ bool is64 = false;
+ uint64_t hval;
+
/* Initialize the console to provide early debug support */
qemu_console_init();
@@ -92,6 +95,11 @@
* They are stored in Secure RAM, in BL2's address space.
*/
while (bl_params) {
+#ifdef __aarch64__
+ if (bl_params->image_id == BL31_IMAGE_ID &&
+ GET_RW(bl_params->ep_info->spsr) == MODE_RW_64)
+ is64 = true;
+#endif
if (bl_params->image_id == BL32_IMAGE_ID)
bl32_image_ep_info = *bl_params->ep_info;
@@ -113,11 +121,19 @@
panic();
#endif
- if (TRANSFER_LIST && arg1 == (TRANSFER_LIST_SIGNATURE |
- REGISTER_CONVENTION_VERSION_MASK) &&
- transfer_list_check_header((void *)arg3) != TL_OPS_NON) {
- bl31_tl = (void *)arg3; /* saved TL address from BL2 */
- }
+ if (!TRANSFER_LIST ||
+ !transfer_list_check_header((void *)arg3))
+ return;
+
+ if (is64)
+ hval = TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
+ else
+ hval = TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION);
+
+ if (arg1 != hval)
+ return;
+
+ bl31_tl = (void *)arg3; /* saved TL address from BL2 */
}
#if ENABLE_RME
@@ -309,10 +325,12 @@
#if TRANSFER_LIST
if (bl31_tl) {
/*
- * update the TL from S to NS memory before jump to BL33
+ * Relocate the TL from S to NS memory before EL3 exit
* to reflect all changes in TL done by BL32
*/
- memcpy((void *)FW_NS_HANDOFF_BASE, bl31_tl, bl31_tl->max_size);
+ if (!transfer_list_relocate(bl31_tl, (void *)FW_NS_HANDOFF_BASE,
+ bl31_tl->max_size))
+ ERROR("Relocate TL to NS memory failed\n");
}
#endif
diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c
index 0bfb126..5dc39a1 100644
--- a/plat/qemu/common/qemu_common.c
+++ b/plat/qemu/common/qemu_common.c
@@ -258,6 +258,23 @@
}
#endif /* PLAT_qemu */
+/*
+ * Calculate checksum of 64-bit words @buffer, of @size bytes
+ */
+static uint64_t checksum_calc(uint64_t *buffer, size_t size)
+{
+ uint64_t sum = 0UL;
+
+ assert(((uintptr_t)buffer & (sizeof(uint64_t) - 1UL)) == 0UL);
+ assert((size & (sizeof(uint64_t) - 1UL)) == 0UL);
+
+ for (unsigned long i = 0UL; i < (size / sizeof(uint64_t)); i++) {
+ sum += buffer[i];
+ }
+
+ return sum;
+}
+
int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
{
int i, last;
@@ -352,10 +369,12 @@
last = num_banks - 1;
for (i = 0; i < num_banks; i++) {
plat_get_memory_node(i, &bank_ptr[last]);
- checksum += bank_ptr[last].base + bank_ptr[last].size;
last--;
}
+ checksum += checksum_calc((uint64_t *)bank_ptr,
+ num_banks * sizeof(*bank_ptr));
+
/* Checksum must be 0 */
manifest->plat_dram.checksum = ~checksum + 1UL;
@@ -373,8 +392,8 @@
strlcpy(console_ptr[0].name, "pl011", sizeof(console_ptr[0].name));
/* Update checksum */
- checksum += console_ptr[0].base + console_ptr[0].map_pages +
- console_ptr[0].clk_in_hz + console_ptr[0].baud_rate;
+ checksum += checksum_calc((uint64_t *)console_ptr,
+ num_consoles * sizeof(*console_ptr));
/* Checksum must be 0 */
manifest->plat_console.checksum = ~checksum + 1UL;
diff --git a/plat/qemu/qemu/qemu_measured_boot.c b/plat/qemu/qemu/qemu_measured_boot.c
index 76a4da1..54a4156 100644
--- a/plat/qemu/qemu/qemu_measured_boot.c
+++ b/plat/qemu/qemu/qemu_measured_boot.c
@@ -65,6 +65,14 @@
event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
+ dump_event_log((uint8_t *)event_log_base, event_log_cur_size);
+
+#if TRANSFER_LIST
+ if (!plat_handoff_mboot((void *)event_log_base, event_log_cur_size,
+ (void *)(uintptr_t)FW_HANDOFF_BASE))
+ return;
+#endif
+
rc = qemu_set_nt_fw_info(
#ifdef SPD_opteed
(uintptr_t)event_log_base,
@@ -101,7 +109,6 @@
}
#endif /* defined(SPD_tspd) || defined(SPD_spmd) */
- dump_event_log((uint8_t *)event_log_base, event_log_cur_size);
}
int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
diff --git a/plat/socionext/synquacer/platform.mk b/plat/socionext/synquacer/platform.mk
index e4ae87b..7a5a03c 100644
--- a/plat/socionext/synquacer/platform.mk
+++ b/plat/socionext/synquacer/platform.mk
@@ -25,6 +25,14 @@
# Libraries
include lib/xlat_tables_v2/xlat_tables.mk
+ifeq (${TRANSFER_LIST}, 1)
+include lib/transfer_list/transfer_list.mk
+endif
+
+ifeq (${HOB_LIST}, 1)
+include lib/hob/hob.mk
+endif
+
PLAT_PATH := plat/socionext/synquacer
PLAT_INCLUDES := -I$(PLAT_PATH)/include \
-I$(PLAT_PATH)/drivers/scpi \
diff --git a/plat/st/common/common.mk b/plat/st/common/common.mk
index 7395a36..dc753a0 100644
--- a/plat/st/common/common.mk
+++ b/plat/st/common/common.mk
@@ -1,5 +1,6 @@
#
# Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
+# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -76,7 +77,7 @@
# Variables for use with stm32image
STM32IMAGEPATH ?= tools/stm32image
-STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
+STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image$(.exe)
STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c
STM32_DEPS += ${STM32IMAGE}
diff --git a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
index cdff3c8..1882669 100644
--- a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
+++ b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
@@ -110,8 +110,9 @@
disable_interrupt = ((x3 & IPI_SMC_ENQUIRY_DIRQ_MASK) != 0U);
ret = ipi_mb_enquire_status(ipi_local_id, ipi_remote_id);
- if ((((uint32_t)ret & IPI_MB_STATUS_RECV_PENDING) > 0U) && disable_interrupt)
+ if ((((uint32_t)ret & IPI_MB_STATUS_RECV_PENDING) > 0U) && disable_interrupt) {
ipi_mb_disable_irq(ipi_local_id, ipi_remote_id);
+ }
SMC_RET1(handle, ret);
}
case IPI_MAILBOX_NOTIFY:
@@ -128,8 +129,9 @@
enable_interrupt = ((x3 & IPI_SMC_ACK_EIRQ_MASK) != 0U);
ipi_mb_ack(ipi_local_id, ipi_remote_id);
- if (enable_interrupt != 0)
+ if (enable_interrupt != 0) {
ipi_mb_enable_irq(ipi_local_id, ipi_remote_id);
+ }
SMC_RET1(handle, 0);
}
case IPI_MAILBOX_ENABLE_IRQ:
diff --git a/plat/xilinx/common/plat_startup.c b/plat/xilinx/common/plat_startup.c
index 9f829c9..c5c52a8 100644
--- a/plat/xilinx/common/plat_startup.c
+++ b/plat/xilinx/common/plat_startup.c
@@ -123,14 +123,17 @@
static uint32_t get_xbl_endian(const struct xbl_partition *partition)
{
uint64_t flags = partition->flags & XBL_FLAGS_ENDIAN_MASK;
+ uint32_t spsr_value = 0U;
flags >>= XBL_FLAGS_ENDIAN_SHIFT;
if (flags == XBL_FLAGS_ENDIAN_BE) {
- return SPSR_E_BIG;
+ spsr_value = SPSR_E_BIG;
} else {
- return SPSR_E_LITTLE;
+ spsr_value = SPSR_E_LITTLE;
}
+
+ return spsr_value;
}
/**
@@ -182,10 +185,12 @@
uint64_t handoff_addr)
{
const struct xbl_handoff_params *HandoffParams;
+ enum xbl_handoff xbl_status = XBL_HANDOFF_SUCCESS;
if (handoff_addr == 0U) {
WARN("BL31: No handoff structure passed\n");
- return XBL_HANDOFF_NO_STRUCT;
+ xbl_status = XBL_HANDOFF_NO_STRUCT;
+ goto exit_label;
}
HandoffParams = (struct xbl_handoff_params *)handoff_addr;
@@ -194,7 +199,8 @@
(HandoffParams->magic[2] != (uint8_t)'N') ||
(HandoffParams->magic[3] != (uint8_t)'X')) {
ERROR("BL31: invalid handoff structure at %" PRIx64 "\n", handoff_addr);
- return XBL_HANDOFF_INVAL_STRUCT;
+ xbl_status = XBL_HANDOFF_INVAL_STRUCT;
+ goto exit_label;
}
VERBOSE("BL31: TF-A handoff params at:0x%" PRIx64 ", entries:%u\n",
@@ -202,7 +208,8 @@
if (HandoffParams->num_entries > XBL_MAX_PARTITIONS) {
ERROR("BL31: TF-A handoff params: too many partitions (%u/%u)\n",
HandoffParams->num_entries, XBL_MAX_PARTITIONS);
- return XBL_HANDOFF_TOO_MANY_PARTS;
+ xbl_status = XBL_HANDOFF_TOO_MANY_PARTS;
+ goto exit_label;
}
/*
@@ -304,5 +311,6 @@
}
}
- return XBL_HANDOFF_SUCCESS;
+exit_label:
+ return xbl_status;
}
diff --git a/plat/xilinx/common/pm_service/pm_api_sys.c b/plat/xilinx/common/pm_service/pm_api_sys.c
index 627266d..9af8bb2 100644
--- a/plat/xilinx/common/pm_service/pm_api_sys.c
+++ b/plat/xilinx/common/pm_service/pm_api_sys.c
@@ -149,10 +149,11 @@
uint32_t payload[PAYLOAD_ARG_CNT];
uint32_t cpuid = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpuid);
+ enum pm_ret_status ret = PM_RET_ERROR_INTERNAL;
if (proc == NULL) {
WARN("Failed to get proc %d\n", cpuid);
- return PM_RET_ERROR_INTERNAL;
+ goto exit_label;
}
/*
@@ -165,7 +166,10 @@
PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, flag, PM_SELF_SUSPEND,
proc->node_id, latency, state, address,
(address >> 32));
- return pm_ipi_send_sync(proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(proc, payload, NULL, 0);
+
+exit_label:
+ return ret;
}
/**
@@ -215,15 +219,18 @@
uint32_t flag)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* Send request to the PMU */
PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target,
latency, state);
if (ack == (uint32_t)IPI_BLOCKING) {
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
} else {
- return pm_ipi_send(primary_proc, payload);
+ ret = pm_ipi_send(primary_proc, payload);
}
+
+ return ret;
}
/**
@@ -273,15 +280,15 @@
enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack)
{
enum pm_ret_status ret = PM_RET_SUCCESS;
+
/* Return if interrupt is not from PMU */
- if (pm_ipi_irq_status(primary_proc) == 0U) {
- return ret;
- }
+ if (pm_ipi_irq_status(primary_proc) != 0U) {
- ret = pm_ipi_buff_read_callb(data, count);
+ ret = pm_ipi_buff_read_callb(data, count);
- if (ack != 0U) {
- pm_ipi_irq_clear(primary_proc);
+ if (ack != 0U) {
+ pm_ipi_irq_clear(primary_proc);
+ }
}
return ret;
@@ -302,16 +309,19 @@
uint32_t flag)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* Send request to the PMC */
PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN,
target, ack);
if (ack == (uint32_t)IPI_BLOCKING) {
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
} else {
- return pm_ipi_send(primary_proc, payload);
+ ret = pm_ipi_send(primary_proc, payload);
}
+
+ return ret;
}
/**
@@ -328,18 +338,22 @@
uint32_t flag)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
/* Setting scope for subsequent PSCI reboot or shutdown */
pm_shutdown_scope = subtype;
- return PM_RET_SUCCESS;
+ goto exit_label;
}
/* Send request to the PMC */
PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SYSTEM_SHUTDOWN,
type, subtype);
- return pm_ipi_send_non_blocking(primary_proc, payload);
+ ret = pm_ipi_send_non_blocking(primary_proc, payload);
+
+exit_label:
+ return ret;
}
/**
@@ -412,16 +426,19 @@
{
uint32_t payload[PAYLOAD_ARG_CNT];
uint32_t module_id;
+ 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;
- return PM_RET_SUCCESS;
+ ret = PM_RET_SUCCESS;
+ goto exit_label;
case TF_A_PM_REGISTER_SGI:
ret_payload[0] = PM_API_BASE_VERSION;
- return PM_RET_SUCCESS;
+ ret = PM_RET_SUCCESS;
+ goto exit_label;
default:
break;
}
@@ -433,12 +450,17 @@
* If module_id is 0, then we consider it LIBPM module as default id
*/
if ((module_id > 0U) && (module_id != LIBPM_MODULE_ID)) {
- return PM_RET_SUCCESS;
+ ret = PM_RET_SUCCESS;
+ goto exit_label;
}
PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
- PM_FEATURE_CHECK, api_id);
- return pm_ipi_send_sync(primary_proc, payload, ret_payload, RET_PAYLOAD_ARG_CNT);
+ PM_FEATURE_CHECK, api_id);
+ ret = pm_ipi_send_sync(primary_proc, payload, ret_payload, RET_PAYLOAD_ARG_CNT);
+
+exit_label:
+ return ret;
+
}
/**
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index e12e74d..bf1fd55 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -294,14 +294,17 @@
uint32_t pm_ipi_irq_status(const struct pm_proc *proc)
{
int32_t ret;
+ int32_t result = 0;
ret = ipi_mb_enquire_status(proc->ipi->local_ipi_id,
proc->ipi->remote_ipi_id);
if (((uint32_t)ret & IPI_MB_STATUS_RECV_PENDING) != 0U) {
- return 1;
+ result = 1;
} else {
- return 0;
+ result = 0;
}
+
+ return result;
}
#if IPI_CRC_CHECK
diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c
index fe496f3..237761a 100644
--- a/plat/xilinx/common/pm_service/pm_svc_main.c
+++ b/plat/xilinx/common/pm_service/pm_svc_main.c
@@ -112,7 +112,8 @@
VERBOSE("CPU power down request received\n");
/* Send powerdown request to online secondary core(s) */
- ret = psci_stop_other_cores(PWRDWN_WAIT_TIMEOUT, raise_pwr_down_interrupt);
+ ret = psci_stop_other_cores(plat_my_core_pos(), PWRDWN_WAIT_TIMEOUT,
+ raise_pwr_down_interrupt);
if (ret != (uint32_t)PSCI_E_SUCCESS) {
ERROR("Failed to powerdown secondary core(s)\n");
}
@@ -154,7 +155,7 @@
ipi_status = ipi_mb_enquire_status(IPI_ID_APU, IPI_ID_PMC);
if (((uint32_t)ipi_status & IPI_MB_STATUS_RECV_PENDING) == 0U) {
plat_ic_end_of_interrupt(id);
- return 0;
+ goto exit_label;
}
/* Handle PMC case */
@@ -201,6 +202,7 @@
/* Clear FIQ */
plat_ic_end_of_interrupt(id);
+exit_label:
return 0;
}
@@ -218,21 +220,19 @@
*/
int32_t pm_register_sgi(uint32_t sgi_num, uint32_t reset)
{
+ int32_t ret = 0;
+
if (reset == 1U) {
sgi = INVALID_SGI;
- return 0;
+ } else if (sgi != INVALID_SGI) {
+ ret = -EBUSY;
+ } else if (sgi_num >= GICV3_MAX_SGI_TARGETS) {
+ ret = -EINVAL;
+ } else {
+ sgi = (uint32_t)sgi_num;
}
- if (sgi != INVALID_SGI) {
- return -EBUSY;
- }
-
- if (sgi_num >= GICV3_MAX_SGI_TARGETS) {
- return -EINVAL;
- }
-
- sgi = (uint32_t)sgi_num;
- return 0;
+ return ret;
}
/**
diff --git a/plat/xilinx/common/versal.c b/plat/xilinx/common/versal.c
index 7c29bae..dc0ae10 100644
--- a/plat/xilinx/common/versal.c
+++ b/plat/xilinx/common/versal.c
@@ -25,12 +25,17 @@
*/
int32_t plat_is_smccc_feature_available(u_register_t fid)
{
+ int32_t ret = 0;
+
switch (fid) {
case SMCCC_ARCH_SOC_ID:
- return SMC_ARCH_CALL_SUCCESS;
+ ret = SMC_ARCH_CALL_SUCCESS;
+ break;
default:
- return SMC_ARCH_CALL_NOT_SUPPORTED;
+ ret = SMC_ARCH_CALL_NOT_SUPPORTED;
}
+
+ return ret;
}
/**
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 54badf5..befe36c 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -151,16 +151,19 @@
{
static uint32_t index;
uint32_t i;
+ int32_t ret = 0;
/* Validate 'handler' and 'id' parameters */
if ((handler == NULL) || (index >= MAX_INTR_EL3)) {
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit_label;
}
/* Check if a handler has already been registered */
for (i = 0; i < index; i++) {
if (id == type_el3_interrupt_table[i].id) {
- return -EALREADY;
+ ret = -EALREADY;
+ goto exit_label;
}
}
@@ -169,7 +172,8 @@
index++;
- return 0;
+exit_label:
+ return ret;
}
static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
@@ -178,6 +182,7 @@
(void)id;
uint32_t intr_id;
uint32_t i;
+ uint64_t ret = 0;
interrupt_type_handler_t handler = NULL;
intr_id = plat_ic_get_pending_interrupt_id();
@@ -189,10 +194,10 @@
}
if (handler != NULL) {
- return handler(intr_id, flags, handle, cookie);
+ ret = handler(intr_id, flags, handle, cookie);
}
- return 0;
+ return ret;
}
void bl31_platform_setup(void)
diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h
index f7149c7..c5bcc95 100644
--- a/plat/xilinx/versal/include/versal_def.h
+++ b/plat/xilinx/versal/include/versal_def.h
@@ -49,10 +49,10 @@
/*******************************************************************************
* memory map related constants
******************************************************************************/
-#define DEVICE0_BASE 0xFF000000
-#define DEVICE0_SIZE 0x00E00000
-#define DEVICE1_BASE 0xF9000000
-#define DEVICE1_SIZE 0x00800000
+#define DEVICE0_BASE U(0xFF000000)
+#define DEVICE0_SIZE U(0x00E00000)
+#define DEVICE1_BASE U(0xF9000000)
+#define DEVICE1_SIZE U(0x00800000)
/*******************************************************************************
* IRQ constants
@@ -63,16 +63,16 @@
/*******************************************************************************
* CCI-400 related constants
******************************************************************************/
-#define PLAT_ARM_CCI_BASE 0xFD000000
-#define PLAT_ARM_CCI_SIZE 0x00100000
+#define PLAT_ARM_CCI_BASE U(0xFD000000)
+#define PLAT_ARM_CCI_SIZE U(0x00100000)
#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 4
#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 5
/*******************************************************************************
* UART related constants
******************************************************************************/
-#define VERSAL_UART0_BASE 0xFF000000
-#define VERSAL_UART1_BASE 0xFF010000
+#define VERSAL_UART0_BASE U(0xFF000000)
+#define VERSAL_UART1_BASE U(0xFF010000)
#if CONSOLE_IS(pl011) || CONSOLE_IS(dtb)
# define UART_BASE VERSAL_UART0_BASE
@@ -115,8 +115,8 @@
#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/
-#define CRF_BASE 0xFD1A0000
-#define CRF_SIZE 0x00600000
+#define CRF_BASE U(0xFD1A0000)
+#define CRF_SIZE U(0x00600000)
/* CRF registers and bitfields */
#define CRF_RST_APU (CRF_BASE + 0X00000300)
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index f160563..b976267 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -28,16 +28,17 @@
{
int32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
const struct pm_proc *proc;
+ int32_t ret = PSCI_E_INTERN_FAIL;
VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
if (cpu_id == -1) {
- return PSCI_E_INTERN_FAIL;
+ goto exit_label;
}
proc = pm_get_proc((uint32_t)cpu_id);
if (proc == NULL) {
- return PSCI_E_INTERN_FAIL;
+ goto exit_label;
}
/* Send request to PMC to wake up selected ACPU core */
@@ -47,7 +48,10 @@
/* Clear power down request */
pm_client_wakeup(proc);
- return PSCI_E_SUCCESS;
+ ret = PSCI_E_SUCCESS;
+
+exit_label:
+ return ret;
}
/**
@@ -246,6 +250,7 @@
static int32_t versal_validate_power_state(uint32_t power_state,
psci_power_state_t *req_state)
{
+ int32_t ret = PSCI_E_SUCCESS;
VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
uint32_t pstate = psci_get_pstate_type(power_state);
@@ -261,10 +266,10 @@
/* We expect the 'state id' to be zero */
if (psci_get_pstate_id(power_state) != 0U) {
- return PSCI_E_INVALID_PARAMS;
+ ret = PSCI_E_INVALID_PARAMS;
}
- return PSCI_E_SUCCESS;
+ return ret;
}
/**
diff --git a/plat/xilinx/versal/plat_versal.c b/plat/xilinx/versal/plat_versal.c
index ba17b1d..6e0b2d6 100644
--- a/plat/xilinx/versal/plat_versal.c
+++ b/plat/xilinx/versal/plat_versal.c
@@ -10,13 +10,12 @@
int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
{
- if ((mpidr & MPIDR_CLUSTER_MASK) != 0U) {
- return -1;
+ int32_t ret = -1;
+
+ if (((mpidr & MPIDR_CLUSTER_MASK) == 0U) &&
+ ((mpidr & MPIDR_CPU_MASK) < PLATFORM_CORE_COUNT)) {
+ ret = versal_calc_core_pos(mpidr);
}
- if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) {
- return -1;
- }
-
- return (int32_t)versal_calc_core_pos(mpidr);
+ return ret;
}
diff --git a/plat/xilinx/versal_net/aarch64/versal_net_common.c b/plat/xilinx/versal_net/aarch64/versal_net_common.c
index 0dd0194..7365818 100644
--- a/plat/xilinx/versal_net/aarch64/versal_net_common.c
+++ b/plat/xilinx/versal_net/aarch64/versal_net_common.c
@@ -42,20 +42,28 @@
/* For saving cpu clock for certain platform */
uint32_t cpu_clock;
-char *board_name_decode(void)
+const char *board_name_decode(void)
{
+ const char *platform;
+
switch (platform_id) {
case VERSAL_NET_SPP:
- return "IPP";
+ platform = "IPP";
+ break;
case VERSAL_NET_EMU:
- return "EMU";
+ platform = "EMU";
+ break;
case VERSAL_NET_SILICON:
- return "Silicon";
+ platform = "Silicon";
+ break;
case VERSAL_NET_QEMU:
- return "QEMU";
+ platform = "QEMU";
+ break;
default:
- return "Unknown";
+ platform = "Unknown";
}
+
+ return platform;
}
void board_detection(void)
diff --git a/plat/xilinx/versal_net/bl31_versal_net_setup.c b/plat/xilinx/versal_net/bl31_versal_net_setup.c
index faeeda0..d131a92 100644
--- a/plat/xilinx/versal_net/bl31_versal_net_setup.c
+++ b/plat/xilinx/versal_net/bl31_versal_net_setup.c
@@ -117,6 +117,9 @@
set_cnt_freq();
+ /* Initialize the platform config for future decision making */
+ versal_net_config_setup();
+
setup_console();
NOTICE("TF-A running on %s %d.%d\n", board_name_decode(),
@@ -124,8 +127,6 @@
versal_net_setup_qos();
- /* Initialize the platform config for future decision making */
- versal_net_config_setup();
/*
* Do initial security configuration to allow DRAM/device access. On
@@ -177,16 +178,19 @@
{
static uint32_t index;
uint32_t i;
+ int32_t ret = 0;
/* Validate 'handler' and 'id' parameters */
if ((handler == NULL) || (index >= MAX_INTR_EL3)) {
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit_label;
}
/* Check if a handler has already been registered */
for (i = 0; i < index; i++) {
if (id == type_el3_interrupt_table[i].id) {
- return -EALREADY;
+ ret = -EALREADY;
+ goto exit_label;
}
}
@@ -195,7 +199,8 @@
index++;
- return 0;
+exit_label:
+ return ret;
}
static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
diff --git a/plat/xilinx/versal_net/include/plat_private.h b/plat/xilinx/versal_net/include/plat_private.h
index 0b82ca7..8b4020e 100644
--- a/plat/xilinx/versal_net/include/plat_private.h
+++ b/plat/xilinx/versal_net/include/plat_private.h
@@ -35,7 +35,7 @@
extern uint32_t cpu_clock, platform_id, platform_version;
void board_detection(void);
-char *board_name_decode(void);
+const char *board_name_decode(void);
uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
uint64_t x4, void *cookie, void *handle, uint64_t flags);
int32_t sip_svc_setup_init(void);
diff --git a/plat/xilinx/versal_net/include/platform_def.h b/plat/xilinx/versal_net/include/platform_def.h
index 8cb7deb..a7ff84e 100644
--- a/plat/xilinx/versal_net/include/platform_def.h
+++ b/plat/xilinx/versal_net/include/platform_def.h
@@ -25,6 +25,9 @@
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * PLATFORM_CORE_COUNT_PER_CLUSTER)
+#define E_INVALID_CORE_COUNT -1
+#define E_INVALID_CLUSTER_COUNT -3
+
#define PLAT_MAX_PWR_LVL U(2)
#define PLAT_MAX_RET_STATE U(1)
#define PLAT_MAX_OFF_STATE U(2)
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
index 9f95574..a76832e 100644
--- a/plat/xilinx/versal_net/plat_psci_pm.c
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -29,17 +29,18 @@
{
int32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
const struct pm_proc *proc;
+ int32_t ret = PSCI_E_INTERN_FAIL;
VERBOSE("%s: mpidr: 0x%lx, cpuid: %x\n",
__func__, mpidr, cpu_id);
if (cpu_id == -1) {
- return PSCI_E_INTERN_FAIL;
+ goto exit_label;
}
proc = pm_get_proc(cpu_id);
if (proc == NULL) {
- return PSCI_E_INTERN_FAIL;
+ goto exit_label;
}
(void)pm_req_wakeup(proc->node_id, (versal_net_sec_entry & 0xFFFFFFFFU) | 0x1U,
@@ -48,7 +49,10 @@
/* Clear power down request */
pm_client_wakeup(proc);
- return PSCI_E_SUCCESS;
+ ret = PSCI_E_SUCCESS;
+
+exit_label:
+ return ret;
}
/**
@@ -64,7 +68,7 @@
const struct pm_proc *proc = pm_get_proc(cpu_id);
if (proc == NULL) {
- return;
+ goto exit_label;
}
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
@@ -94,6 +98,9 @@
SECURE_FLAG);
}
}
+
+exit_label:
+ return;
}
/**
@@ -148,7 +155,7 @@
const struct pm_proc *proc = pm_get_proc(cpu_id);
if (proc == NULL) {
- return;
+ goto exit_label;
}
for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
@@ -170,6 +177,9 @@
SECURE_FLAG);
/* TODO: disable coherency */
+
+exit_label:
+ return;
}
static void versal_net_pwr_domain_on_finish(const psci_power_state_t *target_state)
@@ -195,12 +205,13 @@
const struct pm_proc *proc = pm_get_proc(cpu_id);
if (proc == NULL) {
- return;
+ goto exit_label;
}
- for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
__func__, i, target_state->pwr_domain_state[i]);
+ }
/* Clear the APU power control register for this cpu */
pm_client_wakeup(proc);
@@ -213,6 +224,9 @@
}
plat_arm_gic_cpuif_enable();
+
+exit_label:
+ return;
}
/**
@@ -243,6 +257,8 @@
static int32_t versal_net_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
+ int32_t ret = PSCI_E_INVALID_PARAMS;
+
VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
uint32_t pstate = psci_get_pstate_type(power_state);
@@ -257,11 +273,11 @@
}
/* We expect the 'state id' to be zero */
- if (psci_get_pstate_id(power_state) != 0U) {
- return PSCI_E_INVALID_PARAMS;
+ if (psci_get_pstate_id(power_state) == 0U) {
+ ret = PSCI_E_SUCCESS;
}
- return PSCI_E_SUCCESS;
+ return ret;
}
/**
@@ -274,8 +290,9 @@
{
uint64_t i;
- for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) {
req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+ }
}
static const struct plat_psci_ops versal_net_nopmc_psci_ops = {
diff --git a/plat/xilinx/versal_net/plat_topology.c b/plat/xilinx/versal_net/plat_topology.c
index 4e2d36e..ef5c426 100644
--- a/plat/xilinx/versal_net/plat_topology.c
+++ b/plat/xilinx/versal_net/plat_topology.c
@@ -41,6 +41,7 @@
int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
{
uint32_t cluster_id, cpu_id;
+ int32_t ret;
mpidr &= MPIDR_AFFINITY_MASK;
@@ -48,7 +49,8 @@
cpu_id = (uint32_t)MPIDR_AFFLVL1_VAL(mpidr);
if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
- return -3;
+ ret = E_INVALID_CLUSTER_COUNT;
+ goto exit_label;
}
/*
@@ -56,8 +58,11 @@
* one of the two clusters present on the platform.
*/
if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER) {
- return -1;
+ ret = E_INVALID_CORE_COUNT;
+ } else {
+ ret = (int32_t)(cpu_id + (cluster_id * PLATFORM_CORE_COUNT_PER_CLUSTER));
}
- return (int32_t)(cpu_id + (cluster_id * PLATFORM_CORE_COUNT_PER_CLUSTER));
+exit_label:
+ return ret;
}
diff --git a/plat/xilinx/versal_net/sip_svc_setup.c b/plat/xilinx/versal_net/sip_svc_setup.c
index bf06e2c..21657ab 100644
--- a/plat/xilinx/versal_net/sip_svc_setup.c
+++ b/plat/xilinx/versal_net/sip_svc_setup.c
@@ -37,7 +37,7 @@
/* SiP Service UUID */
DEFINE_SVC_UUID2(versal_net_sip_uuid,
- 0x80d4c25a, 0xebaf, 0x11eb, 0x94, 0x68,
+ 0x80d4c25au, 0xebaf, 0x11eb, 0x94, 0x68,
0x0b, 0x4e, 0x3b, 0x8f, 0xc3, 0x60);
/**
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
index 1361eda..412238d 100644
--- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
@@ -9,7 +9,6 @@
#include <string.h>
#include <common/debug.h>
-#include <drivers/generic_delay_timer.h>
#include <lib/mmio.h>
#include <lib/smccc.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
@@ -57,12 +56,15 @@
uint32_t get_uart_clk(void)
{
unsigned int ver = zynqmp_get_silicon_ver();
+ uint32_t uart_clk = 0U;
if (ver == ZYNQMP_CSU_VERSION_QEMU) {
- return 133000000;
+ uart_clk = 133000000U;
} else {
- return 100000000;
+ uart_clk = 100000000U;
}
+
+ return uart_clk;
}
#if LOG_LEVEL >= LOG_LEVEL_NOTICE
@@ -312,14 +314,17 @@
int32_t plat_is_smccc_feature_available(u_register_t fid)
{
+ int32_t ret = SMC_ARCH_CALL_NOT_SUPPORTED;
+
switch (fid) {
case SMCCC_ARCH_SOC_ID:
- return SMC_ARCH_CALL_SUCCESS;
+ ret = SMC_ARCH_CALL_SUCCESS;
+ break;
default:
- return SMC_ARCH_CALL_NOT_SUPPORTED;
+ break;
}
- return SMC_ARCH_CALL_NOT_SUPPORTED;
+ return ret;
}
int32_t plat_get_soc_version(void)
@@ -389,29 +394,22 @@
void zynqmp_config_setup(void)
{
- uint64_t counter_freq;
-
/* Configure IPI data for ZynqMP */
zynqmp_ipi_config_table_init();
zynqmp_print_platform_name();
-
- /* Configure counter frequency */
- counter_freq = read_cntfrq_el0();
- if (counter_freq == ZYNQMP_DEFAULT_COUNTER_FREQ) {
- write_cntfrq_el0(plat_get_syscnt_freq2());
- }
-
- generic_delay_timer_init();
}
uint32_t plat_get_syscnt_freq2(void)
{
uint32_t ver = zynqmp_get_silicon_ver();
+ uint32_t ret = 0U;
if (ver == ZYNQMP_CSU_VERSION_QEMU) {
- return 65000000;
+ ret = 65000000U;
} else {
- return mmio_read_32((uint64_t)IOU_SCNTRS_BASEFREQ);
+ ret = mmio_read_32((uint64_t)IOU_SCNTRS_BASEFREQ);
}
+
+ return ret;
}
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index 77fbb58..b29e1c6 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -13,6 +13,7 @@
#include <common/debug.h>
#include <common/fdt_fixup.h>
#include <common/fdt_wrappers.h>
+#include <drivers/generic_delay_timer.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <libfdt.h>
@@ -77,6 +78,15 @@
(void)arg2;
(void)arg3;
uint64_t tfa_handoff_addr;
+ uint64_t counter_freq;
+
+ /* Configure counter frequency */
+ counter_freq = read_cntfrq_el0();
+ if (counter_freq == ZYNQMP_DEFAULT_COUNTER_FREQ) {
+ write_cntfrq_el0(plat_get_syscnt_freq2());
+ }
+
+ generic_delay_timer_init();
setup_console();
diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c
index a619359..3fae407 100644
--- a/plat/xilinx/zynqmp/plat_psci.c
+++ b/plat/xilinx/zynqmp/plat_psci.c
@@ -36,22 +36,23 @@
const struct pm_proc *proc;
uint32_t buff[3];
enum pm_ret_status ret;
+ int32_t result = PSCI_E_INTERN_FAIL;
VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
if (cpu_id == -1) {
- return PSCI_E_INTERN_FAIL;
+ goto exit_label;
}
proc = pm_get_proc(cpu_id);
if (proc == NULL) {
- return PSCI_E_INTERN_FAIL;
+ goto exit_label;
}
/* Check the APU proc status before wakeup */
ret = pm_get_node_status(proc->node_id, buff);
if ((ret != PM_RET_SUCCESS) || (buff[0] == PM_PROC_STATE_SUSPENDING)) {
- return PSCI_E_INTERN_FAIL;
+ goto exit_label;
}
/* Clear power down request */
@@ -60,7 +61,10 @@
/* Send request to PMU to wake up selected APU CPU core */
(void)pm_req_wakeup(proc->node_id, 1, zynqmp_sec_entry, REQ_ACK_BLOCKING);
- return PSCI_E_SUCCESS;
+ result = PSCI_E_SUCCESS;
+
+exit_label:
+ return result;
}
static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state)
@@ -101,9 +105,10 @@
return;
}
- for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
__func__, i, target_state->pwr_domain_state[i]);
+ }
state = (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) ?
PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
@@ -194,6 +199,7 @@
VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
uint32_t pstate = psci_get_pstate_type(power_state);
+ int32_t result = PSCI_E_INVALID_PARAMS;
assert(req_state);
@@ -204,11 +210,11 @@
req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
}
/* We expect the 'state id' to be zero */
- if (psci_get_pstate_id(power_state) != 0U) {
- return PSCI_E_INVALID_PARAMS;
+ if (psci_get_pstate_id(power_state) == 0U) {
+ result = PSCI_E_SUCCESS;
}
- return PSCI_E_SUCCESS;
+ return result;
}
static void zynqmp_get_sys_suspend_power_state(psci_power_state_t *req_state)
diff --git a/plat/xilinx/zynqmp/plat_zynqmp.c b/plat/xilinx/zynqmp/plat_zynqmp.c
index e7c0378..3a4c172 100644
--- a/plat/xilinx/zynqmp/plat_zynqmp.c
+++ b/plat/xilinx/zynqmp/plat_zynqmp.c
@@ -10,13 +10,12 @@
int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
{
- if ((mpidr & MPIDR_CLUSTER_MASK) != 0U) {
- return -1;
+ int32_t core_pos = -1;
+
+ if (((mpidr & MPIDR_CLUSTER_MASK) == 0U) &&
+ ((mpidr & MPIDR_CPU_MASK) < PLATFORM_CORE_COUNT)) {
+ core_pos = (int32_t)zynqmp_calc_core_pos(mpidr);
}
- if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) {
- return -1;
- }
-
- return (int32_t)zynqmp_calc_core_pos(mpidr);
+ return core_pos;
}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
index dbc5f13..aad3114 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -2405,12 +2405,16 @@
static bool pm_clock_valid(uint32_t clock_id)
{
unsigned int i;
+ bool valid = true;
- for (i = 0U; i < ARRAY_SIZE(pm_clk_invalid_list); i++)
- if (pm_clk_invalid_list[i] == clock_id)
- return 0;
+ for (i = 0U; i < ARRAY_SIZE(pm_clk_invalid_list); i++) {
+ if (pm_clk_invalid_list[i] == clock_id) {
+ valid = false;
+ break;
+ }
+ }
- return 1;
+ return valid;
}
/**
@@ -2492,13 +2496,15 @@
uint8_t num_nodes;
uint32_t i;
uint16_t typeflags;
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
if (!pm_clock_valid(clock_id)) {
- return PM_RET_ERROR_ARGS;
+ goto exit_label;
}
if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) {
- return PM_RET_ERROR_NOTSUPPORTED;
+ status = PM_RET_ERROR_NOTSUPPORTED;
+ goto exit_label;
}
(void)memset(topology, 0, CLK_TOPOLOGY_PAYLOAD_LEN);
@@ -2507,7 +2513,8 @@
/* Skip parent till index */
if (index >= num_nodes) {
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
+ goto exit_label;
}
for (i = 0; i < 3U; i++) {
@@ -2525,7 +2532,10 @@
(CLK_TYPEFLAGS_BITS - CLK_TYPEFLAGS2_SHIFT));
}
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
+
+exit_label:
+ return status;
}
/**
@@ -2548,13 +2558,15 @@
const struct pm_clock_node *clock_nodes;
uint8_t num_nodes;
uint32_t type, i;
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
if (!pm_clock_valid(clock_id)) {
- return PM_RET_ERROR_ARGS;
+ goto exit_label;
}
if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) {
- return PM_RET_ERROR_NOTSUPPORTED;
+ status = PM_RET_ERROR_NOTSUPPORTED;
+ goto exit_label;
}
clock_nodes = *clocks[clock_id].nodes;
@@ -2570,11 +2582,12 @@
}
/* Clock is not fixed clock */
- if (i == num_nodes) {
- return PM_RET_ERROR_ARGS;
+ if (i != num_nodes) {
+ status = PM_RET_SUCCESS;
}
- return PM_RET_SUCCESS;
+exit_label:
+ return status;
}
/**
@@ -2601,18 +2614,20 @@
{
uint32_t i;
const int32_t *clk_parents;
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
if (!pm_clock_valid(clock_id)) {
- return PM_RET_ERROR_ARGS;
+ goto exit_label;
}
if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) {
- return PM_RET_ERROR_NOTSUPPORTED;
+ status = PM_RET_ERROR_NOTSUPPORTED;
+ goto exit_label;
}
clk_parents = *clocks[clock_id].parents;
if (clk_parents == NULL) {
- return PM_RET_ERROR_ARGS;
+ goto exit_label;
}
(void)memset(parents, 0, CLK_PARENTS_PAYLOAD_LEN);
@@ -2620,7 +2635,8 @@
/* Skip parent till index */
for (i = 0; i < index; i++) {
if (clk_parents[i] == CLK_NA_PARENT) {
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
+ goto exit_label;
}
}
@@ -2631,7 +2647,10 @@
}
}
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
+
+exit_label:
+ return status;
}
/**
@@ -2648,8 +2667,10 @@
enum pm_ret_status pm_api_clock_get_attributes(uint32_t clock_id,
uint32_t *attr)
{
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
+
if (clock_id >= (uint32_t)CLK_MAX) {
- return PM_RET_ERROR_ARGS;
+ goto exit_label;
}
/* Clock valid bit */
@@ -2658,7 +2679,10 @@
/* Clock type (Output/External) */
*attr |= (pm_clock_type(clock_id) << CLK_TYPE_SHIFT);
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
+
+exit_label:
+ return status;
}
/**
@@ -2678,9 +2702,10 @@
{
uint32_t i;
const struct pm_clock_node *nodes;
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
if (clock_id >= CLK_MAX_OUTPUT_CLK) {
- return PM_RET_ERROR_ARGS;
+ goto exit_label;
}
nodes = *clocks[clock_id].nodes;
@@ -2693,11 +2718,13 @@
} else {
*max_div = (uint32_t)BIT(nodes[i].width) - (uint32_t)1U;
}
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
+ break;
}
}
- return PM_RET_ERROR_ARGS;
+exit_label:
+ return status;
}
/**
@@ -2771,14 +2798,16 @@
struct pm_pll *pm_clock_get_pll(enum clock_id clock_id)
{
uint32_t i;
+ struct pm_pll *pll = NULL;
for (i = 0; i < ARRAY_SIZE(pm_plls); i++) {
if (pm_plls[i].cid == clock_id) {
- return &pm_plls[i];
+ pll = &pm_plls[i];
+ break;
}
}
- return NULL;
+ return pll;
}
/**
@@ -2793,13 +2822,14 @@
enum pm_node_id *node_id)
{
const struct pm_pll *pll = pm_clock_get_pll(clock_id);
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
if (pll != NULL) {
*node_id = pll->nid;
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
}
- return PM_RET_ERROR_ARGS;
+ return status;
}
/**
@@ -2813,17 +2843,19 @@
struct pm_pll *pm_clock_get_pll_by_related_clk(enum clock_id clock_id)
{
uint32_t i;
+ struct pm_pll *pll = NULL;
for (i = 0; i < ARRAY_SIZE(pm_plls); i++) {
if ((pm_plls[i].pre_src == clock_id) ||
(pm_plls[i].post_src == clock_id) ||
(pm_plls[i].div2 == clock_id) ||
(pm_plls[i].bypass == clock_id)) {
- return &pm_plls[i];
+ pll = &pm_plls[i];
+ break;
}
}
- return NULL;
+ return pll;
}
/**
@@ -2838,16 +2870,18 @@
*/
enum pm_ret_status pm_clock_pll_enable(struct pm_pll *pll)
{
- if (pll == NULL) {
- return PM_RET_ERROR_ARGS;
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
+
+ if (pll != NULL) {
+ /* Set the PLL mode according to the buffered mode value */
+ if (pll->mode == PLL_FRAC_MODE) {
+ status = pm_pll_set_mode(pll->nid, PM_PLL_MODE_FRACTIONAL);
+ } else {
+ status = pm_pll_set_mode(pll->nid, PM_PLL_MODE_INTEGER);
+ }
}
- /* Set the PLL mode according to the buffered mode value */
- if (pll->mode == PLL_FRAC_MODE) {
- return pm_pll_set_mode(pll->nid, PM_PLL_MODE_FRACTIONAL);
- }
-
- return pm_pll_set_mode(pll->nid, PM_PLL_MODE_INTEGER);
+ return status;
}
/**
@@ -2862,11 +2896,13 @@
*/
enum pm_ret_status pm_clock_pll_disable(struct pm_pll *pll)
{
- if (pll == NULL) {
- return PM_RET_ERROR_ARGS;
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
+
+ if (pll != NULL) {
+ status = pm_pll_set_mode(pll->nid, PM_PLL_MODE_RESET);
}
- return pm_pll_set_mode(pll->nid, PM_PLL_MODE_RESET);
+ return status;
}
/**
@@ -2883,16 +2919,16 @@
enum pm_ret_status pm_clock_pll_get_state(struct pm_pll *pll,
uint32_t *state)
{
- enum pm_ret_status status;
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
enum pm_pll_mode mode;
if ((pll == NULL) || (state == NULL)) {
- return PM_RET_ERROR_ARGS;
+ goto exit_label;
}
status = pm_pll_get_mode(pll->nid, &mode);
if (status != PM_RET_SUCCESS) {
- return status;
+ goto exit_label;
}
if (mode == PM_PLL_MODE_RESET) {
@@ -2901,7 +2937,10 @@
*state = 1;
}
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
+
+exit_label:
+ return status;
}
/**
@@ -2921,23 +2960,25 @@
enum clock_id clock_id,
uint32_t parent_index)
{
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
+
if (pll == NULL) {
- return PM_RET_ERROR_ARGS;
+ goto exit_label;
}
if (pll->pre_src == clock_id) {
- return pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_PRE_SRC,
- parent_index);
+ status = pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_PRE_SRC, parent_index);
+ goto exit_label;
}
if (pll->post_src == clock_id) {
- return pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_POST_SRC,
- parent_index);
+ status = pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_POST_SRC, parent_index);
+ goto exit_label;
}
if (pll->div2 == clock_id) {
- return pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_DIV2,
- parent_index);
+ status = pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_DIV2, parent_index);
}
- return PM_RET_ERROR_ARGS;
+exit_label:
+ return status;
}
/**
@@ -2955,27 +2996,33 @@
enum clock_id clock_id,
uint32_t *parent_index)
{
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
+
if (pll == NULL) {
- return PM_RET_ERROR_ARGS;
+ goto exit_label;
}
if (pll->pre_src == clock_id) {
- return pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_PRE_SRC,
- parent_index);
+ status = pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_PRE_SRC,
+ parent_index);
+ goto exit_label;
}
if (pll->post_src == clock_id) {
- return pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_POST_SRC,
- parent_index);
+ status = pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_POST_SRC,
+ parent_index);
+ goto exit_label;
}
if (pll->div2 == clock_id) {
- return pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_DIV2,
- parent_index);
+ status = pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_DIV2,
+ parent_index);
+ goto exit_label;
}
if (pll->bypass == clock_id) {
*parent_index = 0;
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
}
- return PM_RET_ERROR_ARGS;
+exit_label:
+ return status;
}
/**
@@ -2992,13 +3039,14 @@
uint32_t mode)
{
struct pm_pll *pll = pm_clock_get_pll(clock_id);
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
- if ((pll == NULL) || ((mode != PLL_FRAC_MODE) && (mode != PLL_INT_MODE))) {
- return PM_RET_ERROR_ARGS;
+ if (!((pll == NULL) || ((mode != PLL_FRAC_MODE) && (mode != PLL_INT_MODE)))) {
+ pll->mode = (uint8_t)mode;
+ status = PM_RET_SUCCESS;
}
- pll->mode = (uint8_t)mode;
- return PM_RET_SUCCESS;
+ return status;
}
/**
@@ -3015,13 +3063,14 @@
uint32_t *mode)
{
const struct pm_pll *pll = pm_clock_get_pll(clock_id);
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
- if ((pll == NULL) || (mode == NULL)) {
- return PM_RET_ERROR_ARGS;
+ if ((pll != NULL) && (mode != NULL)) {
+ *mode = pll->mode;
+ status = PM_RET_SUCCESS;
}
- *mode = pll->mode;
- return PM_RET_SUCCESS;
+ return status;
}
/**
@@ -3033,15 +3082,17 @@
*/
enum pm_ret_status pm_clock_id_is_valid(uint32_t clock_id)
{
- if (!pm_clock_valid(clock_id)) {
- return PM_RET_ERROR_ARGS;
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
+
+ if (pm_clock_valid(clock_id)) {
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) {
+ status = PM_RET_ERROR_NOTSUPPORTED;
+ } else {
+ status = PM_RET_SUCCESS;
+ }
}
- if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) {
- return PM_RET_ERROR_NOTSUPPORTED;
- }
-
- return PM_RET_SUCCESS;
+ return status;
}
/**
@@ -3056,23 +3107,29 @@
{
uint32_t i;
const struct pm_clock_node *nodes;
+ uint8_t status = 0U;
if (clock_id >= (uint32_t)CLK_MAX_OUTPUT_CLK) {
- return 0;
+ goto exit_label;
}
nodes = *clocks[clock_id].nodes;
for (i = 0; i < clocks[clock_id].num_nodes; i++) {
if (nodes[i].type == TYPE_DIV1) {
- if (div_id == PM_CLOCK_DIV0_ID)
- return 1;
+ if (div_id == PM_CLOCK_DIV0_ID) {
+ status = 1U;
+ break;
+ }
} else if (nodes[i].type == TYPE_DIV2) {
- if (div_id == PM_CLOCK_DIV1_ID)
- return 1;
+ if (div_id == PM_CLOCK_DIV1_ID) {
+ status = 1U;
+ break;
+ }
} else {
/* To fix the misra 15.7 warning */
}
}
- return 0;
+exit_label:
+ return status;
}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
index a8404ba..fd3992c 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -61,9 +61,11 @@
static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(uint32_t mode)
{
uint32_t val;
+ enum pm_ret_status status = PM_RET_SUCCESS;
if ((mmio_read_32(CRL_APB_RST_LPD_TOP) & CRL_APB_RPU_AMBA_RESET) != 0U) {
- return PM_RET_ERROR_ACCESS;
+ status = PM_RET_ERROR_ACCESS;
+ goto exit_label;
}
val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
@@ -77,12 +79,14 @@
val |= ZYNQMP_TCM_COMB_MASK;
val |= ZYNQMP_SLCLAMP_MASK;
} else {
- return PM_RET_ERROR_ARGS;
+ status = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
- return PM_RET_SUCCESS;
+exit_label:
+ return status;
}
/**
@@ -136,6 +140,7 @@
static enum pm_ret_status pm_ioctl_config_tcm_comb(uint32_t value)
{
uint32_t val;
+ enum pm_ret_status status = PM_RET_SUCCESS;
val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
@@ -144,12 +149,14 @@
} else if (value == PM_RPU_TCM_COMB) {
val |= ZYNQMP_TCM_COMB_MASK;
} else {
- return PM_RET_ERROR_ARGS;
+ status = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
- return PM_RET_SUCCESS;
+exit_label:
+ return status;
}
/**
@@ -165,12 +172,16 @@
static enum pm_ret_status pm_ioctl_set_tapdelay_bypass(uint32_t type,
uint32_t value)
{
+ enum pm_ret_status status = PM_RET_SUCCESS;
+
if ((((value != PM_TAPDELAY_BYPASS_ENABLE) &&
(value != PM_TAPDELAY_BYPASS_DISABLE)) || (type >= PM_TAPDELAY_MAX))) {
- return PM_RET_ERROR_ARGS;
+ status = PM_RET_ERROR_ARGS;
+ } else {
+ status = pm_mmio_write(IOU_TAPDLY_BYPASS, TAP_DELAY_MASK, value << type);
}
- return pm_mmio_write(IOU_TAPDLY_BYPASS, TAP_DELAY_MASK, value << type);
+ return status;
}
/**
@@ -372,11 +383,11 @@
/* Get PLL node ID using PLL clock ID */
status = pm_clock_get_pll_node_id(pll, &pll_nid);
- if (status != PM_RET_SUCCESS) {
- return status;
+ if (status == PM_RET_SUCCESS) {
+ status = pm_pll_set_parameter(pll_nid, PM_PLL_PARAM_DATA, data);
}
- return pm_pll_set_parameter(pll_nid, PM_PLL_PARAM_DATA, data);
+ return status;
}
/**
@@ -397,11 +408,11 @@
/* Get PLL node ID using PLL clock ID */
status = pm_clock_get_pll_node_id(pll, &pll_nid);
- if (status != PM_RET_SUCCESS) {
- return status;
+ if (status == PM_RET_SUCCESS) {
+ status = pm_pll_get_parameter(pll_nid, PM_PLL_PARAM_DATA, data);
}
- return pm_pll_get_parameter(pll_nid, PM_PLL_PARAM_DATA, data);
+ return status;
}
/**
@@ -418,12 +429,16 @@
static enum pm_ret_status pm_ioctl_write_ggs(uint32_t index,
uint32_t value)
{
+ enum pm_ret_status ret_status = PM_RET_SUCCESS;
+
if (index >= GGS_NUM_REGS) {
- return PM_RET_ERROR_ARGS;
+ ret_status = PM_RET_ERROR_ARGS;
+ } else {
+ ret_status = pm_mmio_write((uint64_t)GGS_BASEADDR + (index << 2),
+ 0xFFFFFFFFU, value);
}
- return pm_mmio_write((uint64_t)(GGS_BASEADDR + (index << 2)),
- 0xFFFFFFFFU, value);
+ return ret_status;
}
/**
@@ -440,11 +455,15 @@
static enum pm_ret_status pm_ioctl_read_ggs(uint32_t index,
uint32_t *value)
{
+ enum pm_ret_status ret_status = PM_RET_SUCCESS;
+
if (index >= GGS_NUM_REGS) {
- return PM_RET_ERROR_ARGS;
+ ret_status = PM_RET_ERROR_ARGS;
+ } else {
+ ret_status = pm_mmio_read((uint64_t)GGS_BASEADDR + (index << 2), value);
}
- return pm_mmio_read((uint64_t)(GGS_BASEADDR + (index << 2)), value);
+ return ret_status;
}
/**
@@ -461,12 +480,16 @@
static enum pm_ret_status pm_ioctl_write_pggs(uint32_t index,
uint32_t value)
{
+ enum pm_ret_status ret_status = PM_RET_SUCCESS;
+
if (index >= PGGS_NUM_REGS) {
- return PM_RET_ERROR_ARGS;
+ ret_status = PM_RET_ERROR_ARGS;
+ } else {
+ ret_status = pm_mmio_write((uint64_t)PGGS_BASEADDR + (index << 2),
+ 0xFFFFFFFFU, value);
}
- return pm_mmio_write((uint64_t)(PGGS_BASEADDR + (index << 2)),
- 0xFFFFFFFFU, value);
+ return ret_status;
}
/**
@@ -481,6 +504,7 @@
uint32_t value)
{
uint32_t mask;
+ enum pm_ret_status status = PM_RET_ERROR_ARGS;
const uint32_t regarr[] = {0xFD360000U,
0xFD360014U,
0xFD370000U,
@@ -499,17 +523,16 @@
0xFF419000U,
};
- if (index >= ARRAY_SIZE(regarr)) {
- return PM_RET_ERROR_ARGS;
+ if (index < ARRAY_SIZE(regarr)) {
+ if (index <= AFIFM6_WRCTRL) {
+ mask = FABRIC_WIDTH;
+ } else {
+ mask = 0xf00;
+ }
+ status = pm_mmio_write(regarr[index], mask, value);
}
- if (index <= AFIFM6_WRCTRL) {
- mask = FABRIC_WIDTH;
- } else {
- mask = 0xf00;
- }
-
- return pm_mmio_write(regarr[index], mask, value);
+ return status;
}
/**
@@ -526,11 +549,15 @@
static enum pm_ret_status pm_ioctl_read_pggs(uint32_t index,
uint32_t *value)
{
+ enum pm_ret_status status = 0;
+
if (index >= PGGS_NUM_REGS) {
- return PM_RET_ERROR_ARGS;
+ status = PM_RET_ERROR_ARGS;
+ } else {
+ status = pm_mmio_read((uint64_t)PGGS_BASEADDR + (index << 2), value);
}
- return pm_mmio_read((uint64_t)(PGGS_BASEADDR + (index << 2)), value);
+ return status;
}
/**
@@ -548,7 +575,7 @@
ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
ZYNQMP_ULPI_RESET_VAL_HIGH);
if (ret != PM_RET_SUCCESS) {
- return ret;
+ goto exit_label;
}
/* Drive ULPI assert for atleast 1ms */
@@ -557,7 +584,7 @@
ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
ZYNQMP_ULPI_RESET_VAL_LOW);
if (ret != PM_RET_SUCCESS) {
- return ret;
+ goto exit_label;
}
/* Drive ULPI de-assert for atleast 1ms */
@@ -566,6 +593,7 @@
ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
ZYNQMP_ULPI_RESET_VAL_HIGH);
+exit_label:
return ret;
}
@@ -703,12 +731,13 @@
IOCTL_AFI,
};
uint8_t i, ioctl_id;
- enum pm_ret_status ret;
+ enum pm_ret_status ret = PM_RET_SUCCESS;
for (i = 0U; i < ARRAY_SIZE(supported_ids); i++) {
ioctl_id = supported_ids[i];
if (ioctl_id >= 64U) {
- return PM_RET_ERROR_NOTSUPPORTED;
+ ret = PM_RET_ERROR_NOTSUPPORTED;
+ break;
}
ret = check_api_dependency(ioctl_id);
if (ret == PM_RET_SUCCESS) {
@@ -716,5 +745,5 @@
}
}
- return PM_RET_SUCCESS;
+ return ret;
}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
index 763d9fa..5ffd9ef 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
@@ -1991,13 +1991,16 @@
enum pm_ret_status pm_api_pinctrl_get_num_func_groups(uint32_t fid,
uint32_t *ngroups)
{
+ enum pm_ret_status status = PM_RET_SUCCESS;
+
if (fid >= (uint32_t)MAX_FUNCTION) {
- return PM_RET_ERROR_ARGS;
+ status = PM_RET_ERROR_ARGS;
+ } else {
+
+ *ngroups = pinctrl_functions[fid].group_size;
}
- *ngroups = pinctrl_functions[fid].group_size;
-
- return PM_RET_SUCCESS;
+ return status;
}
/**
@@ -2044,9 +2047,11 @@
uint16_t grps;
uint16_t end_of_grp_offset;
uint16_t i;
+ enum pm_ret_status status = PM_RET_SUCCESS;
if (fid >= (uint32_t)MAX_FUNCTION) {
- return PM_RET_ERROR_ARGS;
+ status = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
(void)memset(groups, END_OF_GROUPS, GROUPS_PAYLOAD_LEN);
@@ -2061,7 +2066,8 @@
groups[i] = (uint16_t)(grps + index + i);
}
- return PM_RET_SUCCESS;
+exit_label:
+ return status;
}
/**
@@ -2089,22 +2095,26 @@
{
uint32_t i;
const uint16_t *grps;
+ enum pm_ret_status status = PM_RET_SUCCESS;
if (pin >= (uint32_t)MAX_PIN) {
- return PM_RET_ERROR_ARGS;
+ status = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
(void)memset(groups, END_OF_GROUPS, GROUPS_PAYLOAD_LEN);
grps = *zynqmp_pin_groups[pin].groups;
if (grps == NULL) {
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
+ goto exit_label;
}
/* Skip groups till index */
for (i = 0; i < index; i++) {
if (grps[i] == (uint16_t)END_OF_GROUPS) {
- return PM_RET_SUCCESS;
+ status = PM_RET_SUCCESS;
+ goto exit_label;
}
}
@@ -2115,5 +2125,6 @@
}
}
- return PM_RET_SUCCESS;
+exit_label:
+ return status;
}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.c b/plat/xilinx/zynqmp/pm_service/pm_client.c
index 9882e30..cadde9a 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_client.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_client.c
@@ -238,11 +238,13 @@
*/
const struct pm_proc *pm_get_proc(uint32_t cpuid)
{
+ const struct pm_proc *ret = NULL;
+
if (cpuid < ARRAY_SIZE(pm_procs_all)) {
- return &pm_procs_all[cpuid];
+ ret = &pm_procs_all[cpuid];
}
- return NULL;
+ return ret;
}
/**
@@ -254,12 +256,16 @@
*/
static uint32_t pm_get_cpuid(enum pm_node_id nid)
{
+ uint32_t ret = UNDEFINED_CPUID;
+
for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
if (pm_procs_all[i].node_id == nid) {
- return i;
+ ret = i;
+ break;
}
}
- return UNDEFINED_CPUID;
+
+ return ret;
}
const struct pm_proc *primary_proc = &pm_procs_all[0];
@@ -321,28 +327,30 @@
void pm_client_wakeup(const struct pm_proc *proc)
{
uint32_t cpuid = pm_get_cpuid(proc->node_id);
+ uint32_t val;
- if (cpuid == UNDEFINED_CPUID) {
- return;
+ if (cpuid != UNDEFINED_CPUID) {
+ bakery_lock_get(&pm_client_secure_lock);
+
+ /* clear powerdown bit for affected cpu */
+ val = mmio_read_32(APU_PWRCTL);
+
+ val &= ~(proc->pwrdn_mask);
+ mmio_write_32(APU_PWRCTL, val);
+
+ bakery_lock_release(&pm_client_secure_lock);
}
-
- bakery_lock_get(&pm_client_secure_lock);
-
- /* clear powerdown bit for affected cpu */
- uint32_t val = mmio_read_32(APU_PWRCTL);
- val &= ~(proc->pwrdn_mask);
- mmio_write_32(APU_PWRCTL, val);
-
- bakery_lock_release(&pm_client_secure_lock);
}
enum pm_ret_status pm_set_suspend_mode(uint32_t mode)
{
- if ((mode != PM_SUSPEND_MODE_STD) &&
- (mode != PM_SUSPEND_MODE_POWER_OFF)) {
- return PM_RET_ERROR_ARGS;
+ enum pm_ret_status suspend_mode_status = PM_RET_ERROR_ARGS;
+
+ if ((mode == PM_SUSPEND_MODE_STD) ||
+ (mode == PM_SUSPEND_MODE_POWER_OFF)) {
+ suspend_mode = mode;
+ suspend_mode_status = PM_RET_SUCCESS;
}
- suspend_mode = mode;
- return PM_RET_SUCCESS;
+ return suspend_mode_status;
}
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 215bf30..81f681f 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
@@ -305,14 +305,17 @@
uint32_t latency, uint32_t state)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* Send request to the PMU */
PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
if (ack == REQ_ACK_BLOCKING) {
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
} else {
- return pm_ipi_send(primary_proc, payload);
+ ret = pm_ipi_send(primary_proc, payload);
}
+
+ return ret;
}
/**
@@ -339,7 +342,7 @@
{
uint32_t payload[PAYLOAD_ARG_CNT];
uint64_t encoded_address;
-
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* encode set Address into 1st bit of address */
encoded_address = address;
@@ -350,10 +353,12 @@
encoded_address >> 32, ack);
if (ack == REQ_ACK_BLOCKING) {
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
} else {
- return pm_ipi_send(primary_proc, payload);
+ ret = pm_ipi_send(primary_proc, payload);
}
+
+ return ret;
}
/**
@@ -369,15 +374,18 @@
enum pm_request_ack ack)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* Send request to the PMU */
PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
if (ack == REQ_ACK_BLOCKING) {
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
} else {
- return pm_ipi_send(primary_proc, payload);
+ ret = pm_ipi_send(primary_proc, payload);
}
+
+ return ret;
}
/**
@@ -439,15 +447,17 @@
enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
if (type == (uint32_t)PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
/* Setting scope for subsequent PSCI reboot or shutdown */
pm_shutdown_scope = subtype;
- return PM_RET_SUCCESS;
+ } else {
+ PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
+ ret = pm_ipi_send_non_blocking(primary_proc, payload);
}
- PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
- return pm_ipi_send_non_blocking(primary_proc, payload);
+ return ret;
}
/* APIs for managing PM slaves: */
@@ -468,14 +478,17 @@
enum pm_request_ack ack)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
if (ack == REQ_ACK_BLOCKING) {
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
} else {
- return pm_ipi_send(primary_proc, payload);
+ ret = pm_ipi_send(primary_proc, payload);
}
+
+ return ret;
}
/**
@@ -496,15 +509,18 @@
enum pm_request_ack ack)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
ack);
if (ack == REQ_ACK_BLOCKING) {
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
} else {
- return pm_ipi_send(primary_proc, payload);
+ ret = pm_ipi_send(primary_proc, payload);
}
+
+ return ret;
}
/* Miscellaneous API functions */
@@ -709,13 +725,16 @@
enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count)
{
enum pm_ret_status ret = PM_RET_SUCCESS;
+
/* Return if interrupt is not from PMU */
if ((pm_ipi_irq_status(primary_proc) == 0U)) {
- return ret;
+ goto exit_label;
}
ret = pm_ipi_buff_read_callb(data, count);
pm_ipi_irq_clear(primary_proc);
+
+exit_label:
return ret;
}
@@ -770,7 +789,7 @@
{
uint8_t i;
uint32_t version_type;
- enum pm_ret_status ret;
+ enum pm_ret_status ret = PM_RET_SUCCESS;
for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
if (api_dep_table[i].id == id) {
@@ -780,18 +799,20 @@
ret = fw_api_version(api_dep_table[i].api_id,
&version_type, 1);
- if (ret != (uint32_t)PM_RET_SUCCESS) {
- return ret;
+ if (ret != PM_RET_SUCCESS) {
+ goto exit_label;
}
/* Check if fw version matches TF-A expected version */
if (version_type != tfa_expected_ver_id[api_dep_table[i].api_id]) {
- return PM_RET_ERROR_NOTSUPPORTED;
+ ret = PM_RET_ERROR_NOTSUPPORTED;
+ goto exit_label;
}
}
}
- return PM_RET_SUCCESS;
+exit_label:
+ return ret;
}
/**
@@ -806,20 +827,26 @@
static enum pm_ret_status feature_check_tfa(uint32_t api_id, uint32_t *version,
uint32_t *bit_mask)
{
+ enum pm_ret_status ret = PM_RET_ERROR_NO_FEATURE;
+
switch (api_id) {
case PM_QUERY_DATA:
*version = TFA_API_QUERY_DATA_VERSION;
bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
- return PM_RET_SUCCESS;
+ ret = PM_RET_SUCCESS;
+ break;
case PM_GET_CALLBACK_DATA:
case PM_GET_TRUSTZONE_VERSION:
case PM_SET_SUSPEND_MODE:
*version = TFA_API_BASE_VERSION;
- return PM_RET_SUCCESS;
+ ret = PM_RET_SUCCESS;
+ break;
default:
- return PM_RET_ERROR_NO_FEATURE;
+ break;
}
+
+ return ret;
}
/**
@@ -834,6 +861,8 @@
static enum pm_ret_status get_tfa_version_for_partial_apis(uint32_t api_id,
uint32_t *version)
{
+ enum pm_ret_status ret = PM_RET_ERROR_ARGS;
+
switch (api_id) {
case PM_SELF_SUSPEND:
case PM_REQ_WAKEUP:
@@ -854,13 +883,17 @@
case PM_PLL_GET_MODE:
case PM_REGISTER_ACCESS:
*version = TFA_API_BASE_VERSION;
- return PM_RET_SUCCESS;
+ ret = PM_RET_SUCCESS;
+ break;
case PM_FEATURE_CHECK:
*version = FW_API_VERSION_2;
- return PM_RET_SUCCESS;
+ ret = PM_RET_SUCCESS;
+ break;
default:
- return PM_RET_ERROR_ARGS;
+ break;
}
+
+ return ret;
}
/**
@@ -876,6 +909,7 @@
uint32_t *version)
{
uint32_t status;
+ uint32_t ret = PM_RET_ERROR_NO_FEATURE;
switch (api_id) {
case PM_SELF_SUSPEND:
@@ -898,13 +932,17 @@
case PM_REGISTER_ACCESS:
case PM_FEATURE_CHECK:
status = check_api_dependency(api_id);
- if (status != (uint32_t)PM_RET_SUCCESS) {
- return status;
+ if (status != PM_RET_SUCCESS) {
+ ret = status;
+ } else {
+ ret = get_tfa_version_for_partial_apis(api_id, version);
}
- return get_tfa_version_for_partial_apis(api_id, version);
+ break;
default:
- return PM_RET_ERROR_NO_FEATURE;
+ break;
}
+
+ return ret;
}
/**
@@ -921,18 +959,18 @@
uint32_t *bit_mask, uint8_t len)
{
uint32_t ret_payload[RET_PAYLOAD_ARG_CNT] = {0U};
- uint32_t status;
+ enum pm_ret_status status;
/* Get API version implemented in TF-A */
status = feature_check_tfa(api_id, version, bit_mask);
- if (status != (uint32_t)PM_RET_ERROR_NO_FEATURE) {
- return status;
+ if (status != PM_RET_ERROR_NO_FEATURE) {
+ goto exit_label;
}
/* Get API version implemented by firmware and TF-A both */
status = feature_check_partial(api_id, version);
- if (status != (uint32_t)PM_RET_ERROR_NO_FEATURE) {
- return status;
+ if (status != PM_RET_ERROR_NO_FEATURE) {
+ goto exit_label;
}
/* Get API version implemented by firmware */
@@ -941,7 +979,7 @@
* firmware but implemented in TF-A
*/
if ((api_id != (uint32_t)PM_IOCTL) && (status != PM_RET_SUCCESS)) {
- return status;
+ goto exit_label;
}
*version = ret_payload[0];
@@ -949,7 +987,8 @@
/* Update IOCTL bit mask which are implemented in TF-A */
if ((api_id == (uint32_t)PM_IOCTL) || (api_id == (uint32_t)PM_GET_OP_CHARACTERISTIC)) {
if (len < 2U) {
- return PM_RET_ERROR_ARGS;
+ status = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
bit_mask[0] = ret_payload[1];
bit_mask[1] = ret_payload[2];
@@ -961,6 +1000,7 @@
/* Requires for MISRA */
}
+exit_label:
return status;
}
@@ -1112,7 +1152,7 @@
/* Check if clock ID is valid and return an error if it is not */
status = pm_clock_id_is_valid(clock_id);
if (status != PM_RET_SUCCESS) {
- return status;
+ goto exit_label;
}
if (enable != 0U) {
@@ -1130,6 +1170,7 @@
status = PM_RET_SUCCESS;
}
+exit_label:
return status;
}
@@ -1147,15 +1188,19 @@
enum pm_ret_status pm_clock_enable(uint32_t clock_id)
{
struct pm_pll *pll;
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* First try to handle it as a PLL */
pll = pm_clock_get_pll(clock_id);
if (pll != NULL) {
- return pm_clock_pll_enable(pll);
+ ret = pm_clock_pll_enable(pll);
+ } else {
+
+ /* It's an on-chip clock, PMU should configure clock's gate */
+ ret = pm_clock_gate(clock_id, 1);
}
- /* It's an on-chip clock, PMU should configure clock's gate */
- return pm_clock_gate(clock_id, 1);
+ return ret;
}
/**
@@ -1172,15 +1217,19 @@
enum pm_ret_status pm_clock_disable(uint32_t clock_id)
{
struct pm_pll *pll;
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* First try to handle it as a PLL */
pll = pm_clock_get_pll(clock_id);
if (pll != NULL) {
- return pm_clock_pll_disable(pll);
+ ret = pm_clock_pll_disable(pll);
+ } else {
+
+ /* It's an on-chip clock, PMU should configure clock's gate */
+ ret = pm_clock_gate(clock_id, 0);
}
- /* It's an on-chip clock, PMU should configure clock's gate */
- return pm_clock_gate(clock_id, 0);
+ return ret;
}
/**
@@ -1204,17 +1253,21 @@
/* First try to handle it as a PLL */
pll = pm_clock_get_pll(clock_id);
if (pll != NULL) {
- return pm_clock_pll_get_state(pll, state);
+ status = pm_clock_pll_get_state(pll, state);
+ goto exit_label;
}
/* Check if clock ID is a valid on-chip clock */
status = pm_clock_id_is_valid(clock_id);
if (status != PM_RET_SUCCESS) {
- return status;
+ goto exit_label;
}
/* Send request to the PMU */
PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
- return pm_ipi_send_sync(primary_proc, payload, state, 1);
+ status = pm_ipi_send_sync(primary_proc, payload, state, 1);
+
+exit_label:
+ return status;
}
/**
@@ -1242,13 +1295,14 @@
/* Get PLL node ID using PLL clock ID */
status = pm_clock_get_pll_node_id(clock_id, &nid);
if (status == PM_RET_SUCCESS) {
- return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
+ status = pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
+ goto exit_label;
}
/* Check if clock ID is a valid on-chip clock */
status = pm_clock_id_is_valid(clock_id);
if (status != PM_RET_SUCCESS) {
- return status;
+ goto exit_label;
}
if (div0 == (divider & div0)) {
@@ -1258,12 +1312,16 @@
div_id = PM_CLOCK_DIV1_ID;
val = (divider & ~div1) >> 16;
} else {
- return PM_RET_ERROR_ARGS;
+ status = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
/* Send request to the PMU */
PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+
+exit_label:
+ return status;
}
/**
@@ -1280,7 +1338,7 @@
enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
uint32_t *divider)
{
- enum pm_ret_status status;
+ enum pm_ret_status status = PM_RET_SUCCESS;
enum pm_node_id nid;
uint32_t payload[PAYLOAD_ARG_CNT];
uint32_t val;
@@ -1288,22 +1346,23 @@
/* Get PLL node ID using PLL clock ID */
status = pm_clock_get_pll_node_id(clock_id, &nid);
if (status == PM_RET_SUCCESS) {
- return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
+ status = pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
+ goto exit_label;
}
/* Check if clock ID is a valid on-chip clock */
status = pm_clock_id_is_valid(clock_id);
if (status != PM_RET_SUCCESS) {
- return status;
+ goto exit_label;
}
if ((pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) != 0U) {
/* Send request to the PMU to get div0 */
PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
- PM_CLOCK_DIV0_ID);
+ PM_CLOCK_DIV0_ID);
status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
if (status != PM_RET_SUCCESS) {
- return status;
+ goto exit_label;
}
*divider = val;
}
@@ -1311,14 +1370,14 @@
if ((pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) != 0U) {
/* Send request to the PMU to get div1 */
PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
- PM_CLOCK_DIV1_ID);
+ PM_CLOCK_DIV1_ID);
status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
if (status != PM_RET_SUCCESS) {
- return status;
+ goto exit_label;
}
*divider |= val << 16;
}
-
+exit_label:
return status;
}
@@ -1342,18 +1401,22 @@
/* First try to handle it as a PLL */
pll = pm_clock_get_pll_by_related_clk(clock_id);
if (pll != NULL) {
- return pm_clock_pll_set_parent(pll, clock_id, parent_index);
+ status = pm_clock_pll_set_parent(pll, clock_id, parent_index);
+ goto exit_label;
}
/* Check if clock ID is a valid on-chip clock */
status = pm_clock_id_is_valid(clock_id);
if (status != PM_RET_SUCCESS) {
- return status;
+ goto exit_label;
}
/* Send request to the PMU */
PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+
+exit_label:
+ return status;
}
/**
@@ -1377,18 +1440,22 @@
/* First try to handle it as a PLL */
pll = pm_clock_get_pll_by_related_clk(clock_id);
if (pll != NULL) {
- return pm_clock_pll_get_parent(pll, clock_id, parent_index);
+ status = pm_clock_pll_get_parent(pll, clock_id, parent_index);
+ goto exit_label;
}
/* Check if clock ID is a valid on-chip clock */
status = pm_clock_id_is_valid(clock_id);
if (status != PM_RET_SUCCESS) {
- return status;
+ goto exit_label;
}
/* Send request to the PMU */
PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
- return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
+ status = pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
+
+exit_label:
+ return status;
}
/**
@@ -1655,20 +1722,26 @@
uint32_t value)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = 0;
/* Check if given node ID is a PLL node */
if ((nid < NODE_APLL) || (nid > NODE_IOPLL)) {
- return PM_RET_ERROR_ARGS;
+ ret = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
/* Check if parameter ID is valid and return an error if it's not */
if (param_id >= PM_PLL_PARAM_MAX) {
- return PM_RET_ERROR_ARGS;
+ ret = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
/* Send request to the PMU */
PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+
+exit_label:
+ return ret;
}
/**
@@ -1686,20 +1759,26 @@
uint32_t *value)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* Check if given node ID is a PLL node */
if ((nid < NODE_APLL) || (nid > NODE_IOPLL)) {
- return PM_RET_ERROR_ARGS;
+ ret = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
/* Check if parameter ID is valid and return an error if it's not */
if (param_id >= PM_PLL_PARAM_MAX) {
- return PM_RET_ERROR_ARGS;
+ ret = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
/* Send request to the PMU */
PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
- return pm_ipi_send_sync(primary_proc, payload, value, 1);
+ ret = pm_ipi_send_sync(primary_proc, payload, value, 1);
+
+exit_label:
+ return ret;
}
/**
@@ -1719,20 +1798,26 @@
enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* Check if given node ID is a PLL node */
if ((nid < NODE_APLL) || (nid > NODE_IOPLL)) {
- return PM_RET_ERROR_ARGS;
+ ret = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
/* Check if PLL mode is valid */
if (mode >= PM_PLL_MODE_MAX) {
- return PM_RET_ERROR_ARGS;
+ ret = PM_RET_ERROR_ARGS;
+ goto exit_label;
}
/* Send request to the PMU */
PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
- return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ ret = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+
+exit_label:
+ return ret;
}
/**
@@ -1747,15 +1832,18 @@
enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
{
uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* Check if given node ID is a PLL node */
if ((nid < NODE_APLL) || (nid > NODE_IOPLL)) {
- return PM_RET_ERROR_ARGS;
+ ret = PM_RET_ERROR_ARGS;
+ } else {
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
+ ret = pm_ipi_send_sync(primary_proc, payload, mode, 1);
}
- /* Send request to the PMU */
- PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
- return pm_ipi_send_sync(primary_proc, payload, mode, 1);
+ return ret;
}
/**
@@ -1783,7 +1871,8 @@
((CSUDMA_BASE & address) != CSUDMA_BASE) &&
((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) {
- return PM_RET_ERROR_ACCESS;
+ ret = PM_RET_ERROR_ACCESS;
+ goto exit_label;
}
switch (register_access_id) {
@@ -1798,6 +1887,8 @@
WARN("Unimplemented register_access call\n\r");
break;
}
+
+exit_label:
return ret;
}
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 21435c6..81db58b 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
@@ -220,6 +220,7 @@
int32_t pm_setup(void)
{
enum pm_ret_status err;
+ int32_t ret = -EINVAL;
pm_ipi_init(primary_proc);
@@ -227,17 +228,17 @@
if (err != PM_RET_SUCCESS) {
ERROR("BL31: Failed to read Platform Management API version. "
"Return: %d\n", err);
- return -EINVAL;
+ goto exit_label;
}
if (pm_ctx.api_version < PM_VERSION) {
ERROR("BL31: Platform Management API version error. Expected: "
"v%d.%d - Found: v%d.%d\n", PM_VERSION_MAJOR,
PM_VERSION_MINOR, pm_ctx.api_version >> 16,
pm_ctx.api_version & 0xFFFFU);
- return -EINVAL;
+ goto exit_label;
}
- int32_t status = 0, ret = 0;
+ int32_t status = 0;
#if ZYNQMP_WDT_RESTART
status = pm_wdt_restart_setup();
if (status)
@@ -255,6 +256,7 @@
pm_up = (status == 0);
+exit_label:
return ret;
}
diff --git a/poetry.lock b/poetry.lock
index 0349943..4127bcd 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1247,13 +1247,13 @@
[[package]]
name = "virtualenv"
-version = "20.26.4"
+version = "20.26.6"
description = "Virtual Python Environment builder"
optional = false
python-versions = ">=3.7"
files = [
- {file = "virtualenv-20.26.4-py3-none-any.whl", hash = "sha256:48f2695d9809277003f30776d155615ffc11328e6a0a8c1f0ec80188d7874a55"},
- {file = "virtualenv-20.26.4.tar.gz", hash = "sha256:c17f4e0f3e6036e9f26700446f85c76ab11df65ff6d8a9cbfad9f71aabfcf23c"},
+ {file = "virtualenv-20.26.6-py3-none-any.whl", hash = "sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2"},
+ {file = "virtualenv-20.26.6.tar.gz", hash = "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48"},
]
[package.dependencies]
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 5456164..6acd1b6 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -14,6 +14,9 @@
#include <services/arm_arch_svc.h>
#include <smccc_helpers.h>
#include <plat/common/platform.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <lib/el3_runtime/context_mgmt.h>
static int32_t smccc_version(void)
{
@@ -90,6 +93,12 @@
}
return 0; /* ERRATA_APPLIES || ERRATA_MISSING */
#endif
+
+#if ARCH_FEATURE_AVAILABILITY
+ case SMCCC_ARCH_FEATURE_AVAILABILITY:
+ return SMC_ARCH_CALL_SUCCESS;
+#endif /* ARCH_FEATURE_AVAILABILITY */
+
#endif /* __aarch64__ */
/* Fallthrough */
@@ -113,6 +122,91 @@
}
/*
+ * Reads a system register, sanitises its value, and returns a bitmask
+ * representing which feature in that sysreg has been enabled by firmware. The
+ * bitmask is a 1:1 mapping to the register's fields.
+ */
+#if ARCH_FEATURE_AVAILABILITY
+static uintptr_t smccc_arch_feature_availability(u_register_t reg,
+ void *handle,
+ u_register_t flags)
+{
+ cpu_context_t *caller_context;
+ per_world_context_t *caller_per_world_context;
+ el3_state_t *state;
+ u_register_t bitmask, check;
+
+ /* check the caller security state */
+ if (is_caller_secure(flags)) {
+ caller_context = cm_get_context(SECURE);
+ caller_per_world_context = &per_world_context[CPU_CONTEXT_SECURE];
+ } else if (is_caller_non_secure(flags)) {
+ caller_context = cm_get_context(NON_SECURE);
+ caller_per_world_context = &per_world_context[CPU_CONTEXT_NS];
+ } else {
+#if ENABLE_RME
+ caller_context = cm_get_context(REALM);
+ caller_per_world_context = &per_world_context[CPU_CONTEXT_REALM];
+#else /* !ENABLE_RME */
+ assert(0); /* shouldn't be possible */
+#endif /* ENABLE_RME */
+ }
+
+ state = get_el3state_ctx(caller_context);
+
+ switch (reg) {
+ case SCR_EL3_OPCODE:
+ bitmask = read_ctx_reg(state, CTX_SCR_EL3);
+ bitmask &= ~SCR_EL3_IGNORED;
+ check = bitmask & ~SCR_EL3_FEATS;
+ bitmask &= SCR_EL3_FEATS;
+ bitmask ^= SCR_EL3_FLIPPED;
+ /* will only report 0 if neither is implemented */
+ if (is_feat_rng_trap_supported() || is_feat_rng_present())
+ bitmask |= SCR_TRNDR_BIT;
+ break;
+ case CPTR_EL3_OPCODE:
+ bitmask = caller_per_world_context->ctx_cptr_el3;
+ check = bitmask & ~CPTR_EL3_FEATS;
+ bitmask &= CPTR_EL3_FEATS;
+ bitmask ^= CPTR_EL3_FLIPPED;
+ break;
+ case MDCR_EL3_OPCODE:
+ bitmask = read_ctx_reg(state, CTX_MDCR_EL3);
+ bitmask &= ~MDCR_EL3_IGNORED;
+ check = bitmask & ~MDCR_EL3_FEATS;
+ bitmask &= MDCR_EL3_FEATS;
+ bitmask ^= MDCR_EL3_FLIPPED;
+ break;
+#if ENABLE_FEAT_MPAM
+ case MPAM3_EL3_OPCODE:
+ bitmask = caller_per_world_context->ctx_mpam3_el3;
+ bitmask &= ~MPAM3_EL3_IGNORED;
+ check = bitmask & ~MPAM3_EL3_FEATS;
+ bitmask &= MPAM3_EL3_FEATS;
+ bitmask ^= MPAM3_EL3_FLIPPED;
+ break;
+#endif /* ENABLE_FEAT_MPAM */
+ default:
+ SMC_RET2(handle, SMC_INVALID_PARAM, ULL(0));
+ }
+
+ /*
+ * failing this means that the requested register has a bit set that
+ * hasn't been declared as a known feature bit or an ignore bit. This is
+ * likely to happen when support for a new feature is added but the
+ * bitmask macros are not updated.
+ */
+ if (ENABLE_ASSERTIONS && check != 0) {
+ ERROR("Unexpected bits 0x%lx were set in register %lx!\n", check, reg);
+ assert(0);
+ }
+
+ SMC_RET2(handle, SMC_ARCH_CALL_SUCCESS, bitmask);
+}
+#endif /* ARCH_FEATURE_AVAILABILITY */
+
+/*
* Top-level Arm Architectural Service SMC handler.
*/
static uintptr_t arm_arch_svc_smc_handler(uint32_t smc_fid,
@@ -161,6 +255,11 @@
SMC_RET0(handle);
#endif
#endif /* __aarch64__ */
+#if ARCH_FEATURE_AVAILABILITY
+ /* return is 64 bit so only reply on SMC64 requests */
+ case SMCCC_ARCH_FEATURE_AVAILABILITY | (SMC_64 << FUNCID_CC_SHIFT):
+ return smccc_arch_feature_availability(x1, handle, flags);
+#endif /* ARCH_FEATURE_AVAILABILITY */
default:
WARN("Unimplemented Arm Architecture Service Call: 0x%x \n",
smc_fid);
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index 9e83848..8910ec6 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -190,24 +190,28 @@
if (!optee_ep_info->pc)
return 1;
- if (TRANSFER_LIST &&
- optee_ep_info->args.arg1 == (TRANSFER_LIST_SIGNATURE |
- REGISTER_CONVENTION_VERSION_MASK)) {
- tl = (void *)optee_ep_info->args.arg3;
- if (transfer_list_check_header(tl) == TL_OPS_NON) {
- return 1;
- }
-
- opteed_rw = GET_RW(optee_ep_info->spsr);
+ tl = (void *)optee_ep_info->args.arg3;
+ if (TRANSFER_LIST && transfer_list_check_header(tl)) {
te = transfer_list_find(tl, TL_TAG_FDT);
dt = transfer_list_entry_data(te);
+ opteed_rw = GET_RW(optee_ep_info->spsr);
if (opteed_rw == OPTEE_AARCH64) {
+ if (optee_ep_info->args.arg1 !=
+ TRANSFER_LIST_HANDOFF_X1_VALUE(
+ REGISTER_CONVENTION_VERSION))
+ return 1;
+
arg0 = (uint64_t)dt;
arg2 = 0;
} else {
- arg2 = (uint64_t)dt;
+ if (optee_ep_info->args.arg1 !=
+ TRANSFER_LIST_HANDOFF_R1_VALUE(
+ REGISTER_CONVENTION_VERSION))
+ return 1;
+
arg0 = 0;
+ arg2 = (uint64_t)dt;
}
arg1 = optee_ep_info->args.arg1;
diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c
index f2b423a..f58f615 100644
--- a/services/std_svc/drtm/drtm_main.c
+++ b/services/std_svc/drtm/drtm_main.c
@@ -208,7 +208,7 @@
return DENIED;
}
- running_on_single_core = psci_is_last_on_cpu_safe();
+ running_on_single_core = psci_is_last_on_cpu_safe(plat_my_core_pos());
if (!running_on_single_core) {
ERROR("DRTM: invalid launch due to non-boot PE not being turned off\n");
return SECONDARY_PE_NOT_OFF;
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index d063ea3..13ea5db 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -33,6 +33,8 @@
#include <smccc_helpers.h>
#include <lib/extensions/sme.h>
#include <lib/extensions/sve.h>
+#include <lib/extensions/spe.h>
+#include <lib/extensions/trbe.h>
#include "rmmd_initial_context.h"
#include "rmmd_private.h"
@@ -127,6 +129,20 @@
if (is_feat_sme_supported()) {
sme_enable(ctx);
}
+
+ /*
+ * SPE and TRBE cannot be fully disabled from EL3 registers alone, only
+ * sysreg access can. In case the EL1 controls leave them active on
+ * context switch, we want the owning security state to be NS so Realm
+ * can't be DOSed.
+ */
+ if (is_feat_spe_supported()) {
+ spe_disable(ctx);
+ }
+
+ if (is_feat_trbe_supported()) {
+ trbe_disable(ctx);
+ }
}
static void manage_extensions_realm_per_world(void)
diff --git a/services/std_svc/spm/el3_spmc/spmc.h b/services/std_svc/spm/el3_spmc/spmc.h
index e093a82..6fd0f2b 100644
--- a/services/std_svc/spm/el3_spmc/spmc.h
+++ b/services/std_svc/spm/el3_spmc/spmc.h
@@ -134,6 +134,9 @@
/* Track the source partition ID to validate a direct response. */
uint16_t dir_req_origin_id;
+
+ /* Track direct message function id to validate a direct response. */
+ uint16_t dir_req_funcid;
};
/*
diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c
index c6ec30c..b0d6ba6 100644
--- a/services/std_svc/spm/el3_spmc/spmc_main.c
+++ b/services/std_svc/spm/el3_spmc/spmc_main.c
@@ -304,6 +304,7 @@
void *handle)
{
/* Retrieve populated Direct Response Arguments. */
+ uint64_t smc_fid = SMC_GET_GP(handle, CTX_GPREG_X0);
uint64_t x1 = SMC_GET_GP(handle, CTX_GPREG_X1);
uint64_t x2 = SMC_GET_GP(handle, CTX_GPREG_X2);
uint16_t src_id = ffa_endpoint_source(x1);
@@ -323,7 +324,8 @@
return false;
}
- if (!direct_msg_validate_arg2(x2)) {
+ if ((smc_fid != FFA_MSG_SEND_DIRECT_RESP2_SMC64) &&
+ !direct_msg_validate_arg2(x2)) {
ERROR("Invalid EL3 LP message encoding.\n");
return false;
}
@@ -331,6 +333,21 @@
}
/*******************************************************************************
+ * Helper function to check that partition can receive direct msg or not.
+ ******************************************************************************/
+static bool direct_msg_receivable(uint32_t properties, uint16_t dir_req_fnum)
+{
+ if ((dir_req_fnum == FFA_FNUM_MSG_SEND_DIRECT_REQ &&
+ ((properties & FFA_PARTITION_DIRECT_REQ_RECV) == 0U)) ||
+ (dir_req_fnum == FFA_FNUM_MSG_SEND_DIRECT_REQ2 &&
+ ((properties & FFA_PARTITION_DIRECT_REQ2_RECV) == 0U))) {
+ return false;
+ }
+
+ return true;
+}
+
+/*******************************************************************************
* Handle direct request messages and route to the appropriate destination.
******************************************************************************/
static uint64_t direct_req_smc_handler(uint32_t smc_fid,
@@ -345,14 +362,21 @@
{
uint16_t src_id = ffa_endpoint_source(x1);
uint16_t dst_id = ffa_endpoint_destination(x1);
+ uint16_t dir_req_funcid;
struct el3_lp_desc *el3_lp_descs;
struct secure_partition_desc *sp;
unsigned int idx;
- /* Check if arg2 has been populated correctly based on message type. */
- if (!direct_msg_validate_arg2(x2)) {
- return spmc_ffa_error_return(handle,
- FFA_ERROR_INVALID_PARAMETER);
+ dir_req_funcid = (smc_fid != FFA_MSG_SEND_DIRECT_REQ2_SMC64) ?
+ FFA_FNUM_MSG_SEND_DIRECT_REQ : FFA_FNUM_MSG_SEND_DIRECT_REQ2;
+
+ /*
+ * Sanity check for DIRECT_REQ:
+ * Check if arg2 has been populated correctly based on message type
+ */
+ if ((dir_req_funcid == FFA_FNUM_MSG_SEND_DIRECT_REQ) &&
+ !direct_msg_validate_arg2(x2)) {
+ return spmc_ffa_error_return(handle, FFA_ERROR_INVALID_PARAMETER);
}
/* Validate Sender is either the current SP or from the normal world. */
@@ -368,6 +392,10 @@
/* Check if the request is destined for a Logical Partition. */
for (unsigned int i = 0U; i < MAX_EL3_LP_DESCS_COUNT; i++) {
if (el3_lp_descs[i].sp_id == dst_id) {
+ if (!direct_msg_receivable(el3_lp_descs[i].properties, dir_req_funcid)) {
+ return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
+ }
+
uint64_t ret = el3_lp_descs[i].direct_req(
smc_fid, secure_origin, x1, x2,
x3, x4, cookie, handle, flags);
@@ -402,6 +430,10 @@
FFA_ERROR_INVALID_PARAMETER);
}
+ if (!direct_msg_receivable(sp->properties, dir_req_funcid)) {
+ return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
+ }
+
/* Protect the runtime state of a UP S-EL0 SP with a lock. */
if (sp->runtime_el == S_EL0) {
spin_lock(&sp->rt_state_lock);
@@ -430,6 +462,7 @@
sp->ec[idx].rt_state = RT_STATE_RUNNING;
sp->ec[idx].rt_model = RT_MODEL_DIR_REQ;
sp->ec[idx].dir_req_origin_id = src_id;
+ sp->ec[idx].dir_req_funcid = dir_req_funcid;
if (sp->runtime_el == S_EL0) {
spin_unlock(&sp->rt_state_lock);
@@ -453,9 +486,13 @@
uint64_t flags)
{
uint16_t dst_id = ffa_endpoint_destination(x1);
+ uint16_t dir_req_funcid;
struct secure_partition_desc *sp;
unsigned int idx;
+ dir_req_funcid = (smc_fid != FFA_MSG_SEND_DIRECT_RESP2_SMC64) ?
+ FFA_FNUM_MSG_SEND_DIRECT_REQ : FFA_FNUM_MSG_SEND_DIRECT_REQ2;
+
/* Check if arg2 has been populated correctly based on message type. */
if (!direct_msg_validate_arg2(x2)) {
return spmc_ffa_error_return(handle,
@@ -507,6 +544,15 @@
return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
}
+ if (dir_req_funcid != sp->ec[idx].dir_req_funcid) {
+ WARN("Unmatched direct req/resp func id. req:%x, resp:%x on core%u.\n",
+ sp->ec[idx].dir_req_funcid, (smc_fid & FUNCID_NUM_MASK), idx);
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
+ return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
+ }
+
if (sp->ec[idx].dir_req_origin_id != dst_id) {
WARN("Invalid direct resp partition ID 0x%x != 0x%x on core%u.\n",
dst_id, sp->ec[idx].dir_req_origin_id, idx);
@@ -522,6 +568,9 @@
/* Clear the ongoing direct request ID. */
sp->ec[idx].dir_req_origin_id = INV_SP_ID;
+ /* Clear the ongoing direct request message version. */
+ sp->ec[idx].dir_req_funcid = 0U;
+
if (sp->runtime_el == S_EL0) {
spin_unlock(&sp->rt_state_lock);
}
@@ -647,6 +696,8 @@
{
struct secure_partition_desc *sp;
unsigned int idx;
+ uint16_t dst_id = ffa_endpoint_destination(x1);
+ bool cancel_dir_req = false;
/* Check that the response did not originate from the Normal world. */
if (!secure_origin) {
@@ -674,6 +725,32 @@
panic();
}
+ if (sp->runtime_el == S_EL0) {
+ spin_lock(&sp->rt_state_lock);
+ }
+
+ if (sp->ec[idx].rt_state == RT_STATE_RUNNING &&
+ sp->ec[idx].rt_model == RT_MODEL_DIR_REQ) {
+ sp->ec[idx].rt_state = RT_STATE_WAITING;
+ sp->ec[idx].dir_req_origin_id = INV_SP_ID;
+ sp->ec[idx].dir_req_funcid = 0x00;
+ cancel_dir_req = true;
+ }
+
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
+
+ if (cancel_dir_req) {
+ if (dst_id == FFA_SPMC_ID) {
+ spmc_sp_synchronous_exit(&sp->ec[idx], x4);
+ /* Should not get here. */
+ panic();
+ } else
+ return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
+ handle, cookie, flags, dst_id);
+ }
+
return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
}
@@ -1267,6 +1344,7 @@
case FFA_RX_RELEASE:
case FFA_MSG_SEND_DIRECT_REQ_SMC32:
case FFA_MSG_SEND_DIRECT_REQ_SMC64:
+ case FFA_MSG_SEND_DIRECT_REQ2_SMC64:
case FFA_PARTITION_INFO_GET:
case FFA_RXTX_MAP_SMC32:
case FFA_RXTX_MAP_SMC64:
@@ -1289,6 +1367,7 @@
case FFA_SECONDARY_EP_REGISTER_SMC64:
case FFA_MSG_SEND_DIRECT_RESP_SMC32:
case FFA_MSG_SEND_DIRECT_RESP_SMC64:
+ case FFA_MSG_SEND_DIRECT_RESP2_SMC64:
case FFA_MEM_RELINQUISH:
case FFA_MSG_WAIT:
case FFA_CONSOLE_LOG_SMC32:
@@ -1909,7 +1988,9 @@
/* Validate this entry, we currently only support direct messaging. */
if ((config_32 & ~(FFA_PARTITION_DIRECT_REQ_RECV |
- FFA_PARTITION_DIRECT_REQ_SEND)) != 0U) {
+ FFA_PARTITION_DIRECT_REQ_SEND |
+ FFA_PARTITION_DIRECT_REQ2_RECV |
+ FFA_PARTITION_DIRECT_REQ2_SEND)) != 0U) {
WARN("Invalid Secure Partition messaging method (0x%x)\n",
config_32);
return -EINVAL;
@@ -2077,39 +2158,34 @@
return ret;
}
- /* Check that the runtime EL in the manifest was correct. */
- if (sp->runtime_el != S_EL0 && sp->runtime_el != S_EL1) {
- ERROR("Unexpected runtime EL: %d\n", sp->runtime_el);
- return -EINVAL;
- }
-
/* Perform any common initialisation. */
spmc_sp_common_setup(sp, next_image_ep_info, boot_info_reg);
/* Perform any initialisation specific to S-EL1 SPs. */
if (sp->runtime_el == S_EL1) {
spmc_el1_sp_setup(sp, next_image_ep_info);
+ spmc_sp_common_ep_commit(sp, next_image_ep_info);
}
-
#if SPMC_AT_EL3_SEL0_SP
- /* Setup spsr in endpoint info for common context management routine. */
- if (sp->runtime_el == S_EL0) {
+ /* Perform any initialisation specific to S-EL0 SPs. */
+ else if (sp->runtime_el == S_EL0) {
+ /* Setup spsr in endpoint info for common context management routine. */
spmc_el0_sp_spsr_setup(next_image_ep_info);
- }
-#endif /* SPMC_AT_EL3_SEL0_SP */
- /* Initialize the SP context with the required ep info. */
- spmc_sp_common_ep_commit(sp, next_image_ep_info);
+ spmc_sp_common_ep_commit(sp, next_image_ep_info);
-#if SPMC_AT_EL3_SEL0_SP
- /*
- * Perform any initialisation specific to S-EL0 not set by common
- * context management routine.
- */
- if (sp->runtime_el == S_EL0) {
+ /*
+ * Perform any initialisation specific to S-EL0 not set by common
+ * context management routine.
+ */
spmc_el0_sp_setup(sp, boot_info_reg, sp_manifest);
}
#endif /* SPMC_AT_EL3_SEL0_SP */
+ else {
+ ERROR("Unexpected runtime EL: %u\n", sp->runtime_el);
+ return -EINVAL;
+ }
+
return 0;
}
@@ -2356,11 +2432,13 @@
case FFA_MSG_SEND_DIRECT_REQ_SMC32:
case FFA_MSG_SEND_DIRECT_REQ_SMC64:
+ case FFA_MSG_SEND_DIRECT_REQ2_SMC64:
return direct_req_smc_handler(smc_fid, secure_origin, x1, x2,
x3, x4, cookie, handle, flags);
case FFA_MSG_SEND_DIRECT_RESP_SMC32:
case FFA_MSG_SEND_DIRECT_RESP_SMC64:
+ case FFA_MSG_SEND_DIRECT_RESP2_SMC64:
return direct_resp_smc_handler(smc_fid, secure_origin, x1, x2,
x3, x4, cookie, handle, flags);
@@ -2426,11 +2504,13 @@
return spmc_ffa_console_log(smc_fid, secure_origin, x1, x2, x3,
x4, cookie, handle, flags);
- case FFA_MEM_PERM_GET:
+ case FFA_MEM_PERM_GET_SMC32:
+ case FFA_MEM_PERM_GET_SMC64:
return ffa_mem_perm_get_handler(smc_fid, secure_origin, x1, x2,
x3, x4, cookie, handle, flags);
- case FFA_MEM_PERM_SET:
+ case FFA_MEM_PERM_SET_SMC32:
+ case FFA_MEM_PERM_SET_SMC64:
return ffa_mem_perm_set_handler(smc_fid, secure_origin, x1, x2,
x3, x4, cookie, handle, flags);
diff --git a/services/std_svc/spm/el3_spmc/spmc_pm.c b/services/std_svc/spm/el3_spmc/spmc_pm.c
index 517d6d5..0a6215c 100644
--- a/services/std_svc/spm/el3_spmc/spmc_pm.c
+++ b/services/std_svc/spm/el3_spmc/spmc_pm.c
@@ -147,6 +147,8 @@
ec->rt_model = RT_MODEL_DIR_REQ;
ec->rt_state = RT_STATE_RUNNING;
ec->dir_req_origin_id = FFA_SPMC_ID;
+ /* Expect a direct message response from the SP. */
+ ec->dir_req_funcid = FFA_FNUM_MSG_SEND_DIRECT_REQ;
rc = spmc_sp_synchronous_entry(ec);
if (rc != 0ULL) {
diff --git a/services/std_svc/spm/el3_spmc/spmc_setup.c b/services/std_svc/spm/el3_spmc/spmc_setup.c
index f7357f1..d42115d 100644
--- a/services/std_svc/spm/el3_spmc/spmc_setup.c
+++ b/services/std_svc/spm/el3_spmc/spmc_setup.c
@@ -5,14 +5,22 @@
*/
#include <assert.h>
+#include <errno.h>
#include <string.h>
#include <arch.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <common/fdt_wrappers.h>
+
#include <context.h>
#include <lib/el3_runtime/context_mgmt.h>
+#if HOB_LIST
+#include <lib/hob/hob.h>
+#include <lib/hob/hob_guid.h>
+#include <lib/hob/mmram.h>
+#include <lib/hob/mpinfo.h>
+#endif
#include <lib/utils.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <libfdt.h>
@@ -51,6 +59,199 @@
SP_MEM_REGION_NOT_SPECIFIED
};
+
+#if HOB_LIST
+static int get_memory_region_info(void *sp_manifest, int mem_region_node,
+ const char *name, uint32_t granularity,
+ uint64_t *base_address, uint32_t *size)
+{
+ char *property;
+ int node, ret;
+
+ if (name != NULL) {
+ node = fdt_subnode_offset_namelen(sp_manifest, mem_region_node,
+ name, strlen(name));
+ if (node < 0) {
+ ERROR("Not found '%s' region in memory regions configuration for SP.\n",
+ name);
+ return -ENOENT;
+ }
+ } else {
+ node = mem_region_node;
+ }
+
+ property = "base-address";
+ ret = fdt_read_uint64(sp_manifest, node, property, base_address);
+ if (ret < 0) {
+ ERROR("Not found property(%s) in memory region(%s).\n",
+ property, name);
+ return -ENOENT;
+ }
+
+ property = "pages-count";
+ ret = fdt_read_uint32(sp_manifest, node, property, size);
+ if (ret < 0) {
+ ERROR("Not found property(%s) in memory region(%s).\n",
+ property, name);
+ return -ENOENT;
+ }
+
+ *size = ((*size) << (PAGE_SIZE_SHIFT + (granularity << 1)));
+
+ return 0;
+}
+
+static struct efi_hob_handoff_info_table *build_sp_boot_hob_list(
+ void *sp_manifest, uintptr_t hob_table_start, size_t *hob_table_size)
+{
+ struct efi_hob_handoff_info_table *hob_table;
+ uintptr_t base_address;
+ int mem_region_node;
+ int32_t node, ret;
+ const char *name;
+ uint32_t granularity, size;
+ uint32_t mem_region_num;
+ struct efi_guid ns_buf_guid = MM_NS_BUFFER_GUID;
+ struct efi_guid mmram_resv_guid = MM_PEI_MMRAM_MEMORY_RESERVE_GUID;
+ struct efi_mmram_descriptor *mmram_desc_data;
+ struct efi_mmram_hob_descriptor_block *mmram_hob_desc_data;
+
+ if (sp_manifest == NULL || hob_table_size == NULL || *hob_table_size == 0) {
+ return NULL;
+ }
+
+ node = fdt_path_offset(sp_manifest, "/");
+ if (node < 0) {
+ ERROR("Failed to get root in sp_manifest.\n");
+ return NULL;
+ }
+
+ ret = fdt_read_uint32(sp_manifest, node, "xlat-granule", &granularity);
+ if (ret < 0) {
+ ERROR("Not found property(xlat-granule) in sp_manifest.\n");
+ return NULL;
+ }
+
+ if (granularity > 0x02) {
+ ERROR("Invalid granularity value: 0x%x\n", granularity);
+ return NULL;
+ }
+
+ mem_region_node = fdt_subnode_offset_namelen(sp_manifest, 0, "memory-regions",
+ sizeof("memory-regions") - 1);
+ if (node < 0) {
+ ERROR("Not found memory-region configuration for SP.\n");
+ return NULL;
+ }
+
+ INFO("Generating PHIT_HOB...\n");
+
+ hob_table = create_hob_list(BL32_BASE, BL32_LIMIT,
+ hob_table_start, *hob_table_size);
+ if (hob_table == NULL) {
+ ERROR("Failed to create Hob Table.\n");
+ return NULL;
+ }
+
+ /*
+ * Create fv hob.
+ */
+ ret = get_memory_region_info(sp_manifest, mem_region_node,
+ "stmm_region", granularity, &base_address, &size);
+ if (ret < 0) {
+ return NULL;
+ }
+
+ if (base_address != BL32_BASE &&
+ base_address + size > BL32_LIMIT) {
+ ERROR("Image is ouf of bound(0x%lx/0x%x), should be in (0x%llx/0x%llx)\n",
+ base_address, size, BL32_BASE, BL32_LIMIT - BL32_BASE);
+ return NULL;
+ }
+
+ ret = create_fv_hob(hob_table, base_address, size);
+ if (ret < 0) {
+ ERROR("Failed to create fv hob... ret:%d\n", ret);
+ return NULL;
+ }
+
+ INFO("Success to create FV hob(0x%lx/0x%x).\n", base_address, size);
+
+ /*
+ * Create Ns Buffer hob.
+ */
+ ret = get_memory_region_info(sp_manifest, mem_region_node,
+ "ns_comm_buffer", granularity, &base_address, &size);
+ if (ret < 0) {
+ return NULL;
+ }
+
+ ret = create_guid_hob(hob_table, &ns_buf_guid,
+ sizeof(struct efi_mmram_descriptor), (void **) &mmram_desc_data);
+ if (ret < 0) {
+ ERROR("Failed to create ns buffer hob\n");
+ return NULL;
+ }
+
+ mmram_desc_data->physical_start = base_address;
+ mmram_desc_data->physical_size = size;
+ mmram_desc_data->cpu_start = base_address;
+ mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED;
+
+ /*
+ * Create mmram_resv hob.
+ */
+ for (node = fdt_first_subnode(sp_manifest, mem_region_node), mem_region_num = 0;
+ node >= 0;
+ node = fdt_next_subnode(sp_manifest, node), mem_region_num++) {
+ ret = get_memory_region_info(sp_manifest, node, NULL, granularity,
+ &base_address, &size);
+ if (ret < 0) {
+ name = fdt_get_name(sp_manifest, node, NULL);
+ ERROR("Invalid memory region(%s) found!\n", name);
+ return NULL;
+ }
+ }
+
+ ret = create_guid_hob(hob_table, &mmram_resv_guid,
+ (sizeof(struct efi_mmram_hob_descriptor_block) +
+ (sizeof(struct efi_mmram_descriptor) * mem_region_num)),
+ (void **) &mmram_hob_desc_data);
+ if (ret < 0) {
+ ERROR("Failed to create mmram_resv hob. ret: %d\n", ret);
+ return NULL;
+ }
+
+ mmram_hob_desc_data->number_of_mm_reserved_regions = mem_region_num;
+
+ for (node = fdt_first_subnode(sp_manifest, mem_region_node), mem_region_num = 0;
+ node >= 0;
+ node = fdt_next_subnode(sp_manifest, node), mem_region_num++) {
+ get_memory_region_info(sp_manifest, node, NULL, granularity,
+ &base_address, &size);
+ name = fdt_get_name(sp_manifest, node, NULL);
+
+ mmram_desc_data = &mmram_hob_desc_data->descriptor[mem_region_num];
+ mmram_desc_data->physical_start = base_address;
+ mmram_desc_data->physical_size = size;
+ mmram_desc_data->cpu_start = base_address;
+
+ if (!strcmp(name, "heap")) {
+ mmram_desc_data->region_state = EFI_CACHEABLE;
+ } else {
+ mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED;
+ }
+ }
+
+ *hob_table_size = hob_table->efi_free_memory_bottom -
+ (efi_physical_address_t) hob_table;
+
+ return hob_table;
+}
+#endif
+
+
+
/*
* This function creates a initialization descriptor in the memory reserved
* for passing boot information to an SP. It then copies the partition manifest
@@ -62,14 +263,13 @@
{
struct ffa_boot_info_header *boot_header;
struct ffa_boot_info_desc *boot_descriptor;
- uintptr_t manifest_addr;
+ uintptr_t content_addr;
/*
* Calculate the maximum size of the manifest that can be accommodated
* in the boot information memory region.
*/
- const unsigned int
- max_manifest_sz = sizeof(ffa_boot_info_mem) -
+ size_t max_sz = sizeof(ffa_boot_info_mem) -
(sizeof(struct ffa_boot_info_header) +
sizeof(struct ffa_boot_info_desc));
@@ -83,17 +283,6 @@
return;
}
- /*
- * Check if the manifest will fit into the boot info memory region else
- * bail.
- */
- if (ep_info->args.arg1 > max_manifest_sz) {
- WARN("Unable to copy manifest into boot information. ");
- WARN("Max sz = %u bytes. Manifest sz = %lu bytes\n",
- max_manifest_sz, ep_info->args.arg1);
- return;
- }
-
/* Zero the memory region before populating. */
memset(ffa_boot_info_mem, 0, PAGE_SIZE);
@@ -125,29 +314,58 @@
/* Set the count. Currently 1 since only the manifest is specified. */
boot_header->count_boot_info_desc = 1;
+ boot_descriptor->flags =
+ FFA_BOOT_INFO_FLAG_NAME(FFA_BOOT_INFO_FLAG_NAME_UUID) |
+ FFA_BOOT_INFO_FLAG_CONTENT(FFA_BOOT_INFO_FLAG_CONTENT_ADR);
+
+ content_addr = (uintptr_t) (ffa_boot_info_mem +
+ boot_header->offset_boot_info_desc +
+ boot_header->size_boot_info_desc);
+
+#if HOB_LIST
+ /* Populate the boot information descriptor for the hob_list. */
+ boot_descriptor->type =
+ FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) |
+ FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_HOB);
+
+ content_addr = (uintptr_t) build_sp_boot_hob_list(
+ (void *) ep_info->args.arg0, content_addr, &max_sz);
+ if (content_addr == (uintptr_t) NULL) {
+ WARN("Unable to create phit hob properly.");
+ return;
+ }
+
+ boot_descriptor->size_boot_info = max_sz;
+ boot_descriptor->content = content_addr;
+#else
+ /*
+ * Check if the manifest will fit into the boot info memory region else
+ * bail.
+ */
+ if (ep_info->args.arg1 > max_sz) {
+ WARN("Unable to copy manifest into boot information. ");
+ WARN("Max sz = %lu bytes. Manifest sz = %lu bytes\n",
+ max_sz, ep_info->args.arg1);
+ return;
+ }
+
/* Populate the boot information descriptor for the manifest. */
boot_descriptor->type =
FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) |
FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_FDT);
- boot_descriptor->flags =
- FFA_BOOT_INFO_FLAG_NAME(FFA_BOOT_INFO_FLAG_NAME_UUID) |
- FFA_BOOT_INFO_FLAG_CONTENT(FFA_BOOT_INFO_FLAG_CONTENT_ADR);
-
/*
* Copy the manifest into boot info region after the boot information
* descriptor.
*/
boot_descriptor->size_boot_info = (uint32_t) ep_info->args.arg1;
- manifest_addr = (uintptr_t) (ffa_boot_info_mem +
- boot_header->offset_boot_info_desc +
- boot_header->size_boot_info_desc);
- memcpy((void *) manifest_addr, (void *) ep_info->args.arg0,
+ memcpy((void *) content_addr, (void *) ep_info->args.arg0,
boot_descriptor->size_boot_info);
- boot_descriptor->content = manifest_addr;
+ boot_descriptor->content = content_addr;
+#endif
/* Calculate the size of the total boot info blob. */
boot_header->size_boot_info_blob = boot_header->offset_boot_info_desc +
@@ -158,7 +376,7 @@
INFO("SP boot info @ 0x%lx, size: %u bytes.\n",
(uintptr_t) ffa_boot_info_mem,
boot_header->size_boot_info_blob);
- INFO("SP manifest @ 0x%lx, size: %u bytes.\n",
+ INFO("SP content @ 0x%lx, size: %u bytes.\n",
boot_descriptor->content,
boot_descriptor->size_boot_info);
}
@@ -194,6 +412,7 @@
out[0] = '\0';
} else {
memcpy(out, prop, MIN(lenp, (int)len));
+ out[MIN(lenp, (int)len) - 1] = '\0';
}
}
@@ -292,10 +511,11 @@
sp_mem_regions.base_va = base_address;
sp_mem_regions.size = size;
- INFO("Adding PA: 0x%llx VA: 0x%lx Size: 0x%lx attr:0x%x\n",
+ INFO("Adding PA: 0x%llx VA: 0x%lx Size: 0x%lx mem_attr: 0x%x, attr:0x%x\n",
sp_mem_regions.base_pa,
sp_mem_regions.base_va,
sp_mem_regions.size,
+ mem_attr,
sp_mem_regions.attr);
if (type == SP_MEM_REGION_DEVICE) {
@@ -464,7 +684,6 @@
}
spmc_el0_sp_setup_system_registers(sp, ctx);
-
}
#endif /* SPMC_AT_EL3_SEL0_SP */
diff --git a/services/std_svc/spm/spm_mm/spm_mm_setup.c b/services/std_svc/spm/spm_mm/spm_mm_setup.c
index de05459..66ce84c 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_setup.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_setup.c
@@ -13,6 +13,15 @@
#include <context.h>
#include <common/debug.h>
#include <lib/el3_runtime/context_mgmt.h>
+#if HOB_LIST
+#include <lib/hob/hob.h>
+#include <lib/hob/hob_guid.h>
+#include <lib/hob/mmram.h>
+#include <lib/hob/mpinfo.h>
+#endif
+#if TRANSFER_LIST
+#include <lib/transfer_list.h>
+#endif
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <platform_def.h>
#include <plat/common/common_def.h>
@@ -23,6 +32,92 @@
#include "spm_mm_private.h"
#include "spm_shim_private.h"
+#if HOB_LIST && TRANSFER_LIST
+static struct efi_hob_handoff_info_table *build_sp_boot_hob_list(
+ const spm_mm_boot_info_t *sp_boot_info, uint16_t *hob_table_size)
+{
+ int ret;
+ struct efi_hob_handoff_info_table *hob_table;
+ struct efi_guid ns_buf_guid = MM_NS_BUFFER_GUID;
+ struct efi_guid mmram_resv_guid = MM_PEI_MMRAM_MEMORY_RESERVE_GUID;
+ struct efi_mmram_descriptor *mmram_desc_data;
+ uint16_t mmram_resv_data_size;
+ struct efi_mmram_hob_descriptor_block *mmram_hob_desc_data;
+ uint64_t hob_table_offset;
+
+ hob_table_offset = sizeof(struct transfer_list_header) +
+ sizeof(struct transfer_list_entry);
+
+ *hob_table_size = 0U;
+
+ hob_table = create_hob_list(sp_boot_info->sp_mem_base,
+ sp_boot_info->sp_mem_limit - sp_boot_info->sp_mem_base,
+ sp_boot_info->sp_shared_buf_base + hob_table_offset,
+ sp_boot_info->sp_shared_buf_size);
+ if (hob_table == NULL) {
+ return NULL;
+ }
+
+ ret = create_fv_hob(hob_table, sp_boot_info->sp_image_base,
+ sp_boot_info->sp_image_size);
+ if (ret) {
+ return NULL;
+ }
+
+ ret = create_guid_hob(hob_table, &ns_buf_guid,
+ sizeof(struct efi_mmram_descriptor), (void **) &mmram_desc_data);
+ if (ret) {
+ return NULL;
+ }
+
+ mmram_desc_data->physical_start = sp_boot_info->sp_ns_comm_buf_base;
+ mmram_desc_data->physical_size = sp_boot_info->sp_ns_comm_buf_size;
+ mmram_desc_data->cpu_start = sp_boot_info->sp_ns_comm_buf_base;
+ mmram_desc_data->region_state = EFI_CACHEABLE | EFI_ALLOCATED;
+
+ mmram_resv_data_size = sizeof(struct efi_mmram_hob_descriptor_block) +
+ sizeof(struct efi_mmram_descriptor) * sp_boot_info->num_sp_mem_regions;
+
+ ret = create_guid_hob(hob_table, &mmram_resv_guid,
+ mmram_resv_data_size, (void **) &mmram_hob_desc_data);
+ if (ret) {
+ return NULL;
+ }
+
+ *hob_table_size = hob_table->efi_free_memory_bottom -
+ (efi_physical_address_t) hob_table;
+
+ mmram_hob_desc_data->number_of_mm_reserved_regions = 4U;
+ mmram_desc_data = &mmram_hob_desc_data->descriptor[0];
+
+ /* First, should be image mm range. */
+ mmram_desc_data[0].physical_start = sp_boot_info->sp_image_base;
+ mmram_desc_data[0].physical_size = sp_boot_info->sp_image_size;
+ mmram_desc_data[0].cpu_start = sp_boot_info->sp_image_base;
+ mmram_desc_data[0].region_state = EFI_CACHEABLE | EFI_ALLOCATED;
+
+ /* Second, should be shared buffer mm range. */
+ mmram_desc_data[1].physical_start = sp_boot_info->sp_shared_buf_base;
+ mmram_desc_data[1].physical_size = sp_boot_info->sp_shared_buf_size;
+ mmram_desc_data[1].cpu_start = sp_boot_info->sp_shared_buf_base;
+ mmram_desc_data[1].region_state = EFI_CACHEABLE | EFI_ALLOCATED;
+
+ /* Ns Buffer mm range */
+ mmram_desc_data[2].physical_start = sp_boot_info->sp_ns_comm_buf_base;
+ mmram_desc_data[2].physical_size = sp_boot_info->sp_ns_comm_buf_size;
+ mmram_desc_data[2].cpu_start = sp_boot_info->sp_ns_comm_buf_base;
+ mmram_desc_data[2].region_state = EFI_CACHEABLE | EFI_ALLOCATED;
+
+ /* Heap mm range */
+ mmram_desc_data[3].physical_start = sp_boot_info->sp_heap_base;
+ mmram_desc_data[3].physical_size = sp_boot_info->sp_heap_size;
+ mmram_desc_data[3].cpu_start = sp_boot_info->sp_heap_base;
+ mmram_desc_data[3].region_state = EFI_CACHEABLE;
+
+ return hob_table;
+}
+#endif
+
/* Setup context of the Secure Partition */
void spm_sp_setup(sp_context_t *sp_ctx)
{
@@ -32,6 +127,15 @@
const spm_mm_boot_info_t *sp_boot_info =
plat_get_secure_partition_boot_info(NULL);
+#if HOB_LIST && TRANSFER_LIST
+ struct efi_hob_handoff_info_table *hob_table;
+ struct transfer_list_header *sp_boot_tl;
+ struct transfer_list_entry *sp_boot_te;
+ uint16_t hob_table_size;
+#endif
+
+ assert(sp_boot_info != NULL);
+
/*
* Initialize CPU context
* ----------------------
@@ -195,7 +299,35 @@
* Prepare information in buffer shared between EL3 and S-EL0
* ----------------------------------------------------------
*/
+#if HOB_LIST && TRANSFER_LIST
+ sp_boot_tl = transfer_list_init((void *) sp_boot_info->sp_shared_buf_base,
+ sp_boot_info->sp_shared_buf_size);
+ assert(sp_boot_tl != NULL);
+ hob_table = build_sp_boot_hob_list(sp_boot_info, &hob_table_size);
+ assert(hob_table != NULL);
+
+ transfer_list_update_checksum(sp_boot_tl);
+
+ sp_boot_te = transfer_list_add(sp_boot_tl, TL_TAG_HOB_LIST,
+ hob_table_size, hob_table);
+ if (sp_boot_te == NULL) {
+ ERROR("Failed to add HOB list to xfer list\n");
+ }
+
+ transfer_list_set_handoff_args(sp_boot_tl, &ep_info);
+
+ transfer_list_dump(sp_boot_tl);
+
+ write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0,
+ ep_info.args.arg0);
+ write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1,
+ ep_info.args.arg1);
+ write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2,
+ ep_info.args.arg2);
+ write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3,
+ ep_info.args.arg3);
+#else
void *shared_buf_ptr = (void *) sp_boot_info->sp_shared_buf_base;
/* Copy the boot information into the shared buffer with the SP. */
@@ -205,7 +337,6 @@
assert(sp_boot_info->sp_shared_buf_base <=
(UINTPTR_MAX - sp_boot_info->sp_shared_buf_size + 1));
- assert(sp_boot_info != NULL);
memcpy((void *) shared_buf_ptr, (const void *) sp_boot_info,
sizeof(spm_mm_boot_info_t));
@@ -256,4 +387,5 @@
if (plat_my_core_pos() == sp_mp_info[index].linear_id)
sp_mp_info[index].flags |= MP_INFO_FLAG_PRIMARY_CPU;
}
+#endif
}
diff --git a/tools/amlogic/Makefile b/tools/amlogic/Makefile
index 7bfee7d..cdaf7e7 100644
--- a/tools/amlogic/Makefile
+++ b/tools/amlogic/Makefile
@@ -1,5 +1,6 @@
#
# Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
+# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# https://spdx.org/licenses
@@ -7,11 +8,10 @@
MAKE_HELPERS_DIRECTORY := ../../make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
-include ${MAKE_HELPERS_DIRECTORY}build_env.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
-PROJECT := doimage${BIN_EXT}
+PROJECT := doimage$(.exe)
OBJECTS := doimage.o
HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 -D_GNU_SOURCE
@@ -38,6 +38,6 @@
$(q)$(host-cc) -c ${HOSTCCFLAGS} $< -o $@
clean:
- $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
+ $(q)rm -rf $(PROJECT) $(OBJECTS)
distclean: clean
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index ce12a66..e403b2d 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -1,18 +1,17 @@
#
-# Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
PLAT := none
DEBUG := 0
-CRTTOOL ?= cert_create${BIN_EXT}
+CRTTOOL ?= cert_create$(.exe)
BINARY := $(notdir ${CRTTOOL})
COT := tbbr
MAKE_HELPERS_DIRECTORY := ../../make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
-include ${MAKE_HELPERS_DIRECTORY}build_env.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
include ${MAKE_HELPERS_DIRECTORY}defaults.mk
include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
@@ -95,7 +94,7 @@
endif
clean:
- $(call SHELL_DELETE_ALL,${OBJECTS})
+ $(q)rm -rf $(OBJECTS)
realclean: clean
- $(call SHELL_DELETE,${BINARY})
+ $(q)rm -f $(BINARY)
diff --git a/tools/encrypt_fw/Makefile b/tools/encrypt_fw/Makefile
index 50b0fa2..14def1d 100644
--- a/tools/encrypt_fw/Makefile
+++ b/tools/encrypt_fw/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2024, Arm Limited. All rights reserved.
+# Copyright (c) 2024-2025, Arm Limited. All rights reserved.
# Copyright (c) 2019-2022, Linaro Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -7,13 +7,12 @@
BUILD_INFO ?= 1
DEBUG := 0
-ENCTOOL ?= encrypt_fw${BIN_EXT}
+ENCTOOL ?= encrypt_fw$(.exe)
BINARY := $(notdir ${ENCTOOL})
OPENSSL_DIR := /usr
MAKE_HELPERS_DIRECTORY := ../../make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
-include ${MAKE_HELPERS_DIRECTORY}build_env.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
include ${MAKE_HELPERS_DIRECTORY}defaults.mk
include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
@@ -75,7 +74,7 @@
endif
clean:
- $(call SHELL_DELETE_ALL,${OBJECTS})
+ $(q)rm -rf $(OBJECTS)
realclean: clean
- $(call SHELL_DELETE,${BINARY})
+ $(q)rm -f $(BINARY)
diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile
index 54dee87..a660a50 100644
--- a/tools/fiptool/Makefile
+++ b/tools/fiptool/Makefile
@@ -1,17 +1,16 @@
#
-# Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
MAKE_HELPERS_DIRECTORY := ../../make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
-include ${MAKE_HELPERS_DIRECTORY}build_env.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
include ${MAKE_HELPERS_DIRECTORY}defaults.mk
include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
-FIPTOOL ?= fiptool${BIN_EXT}
+FIPTOOL ?= fiptool$(.exe)
PROJECT := $(notdir ${FIPTOOL})
OBJECTS := fiptool.o tbbr_config.o
STATIC ?= 0
@@ -93,4 +92,4 @@
endif # STATIC
clean:
- $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS} $(DEPS))
+ $(q)rm -rf $(PROJECT) $(OBJECTS) $(DEPS)
diff --git a/tools/fiptool/Makefile.msvc b/tools/fiptool/Makefile.msvc
deleted file mode 100644
index 9081bc6..0000000
--- a/tools/fiptool/Makefile.msvc
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-CC = cl.exe
-LD = link.exe
-
-# FIPTOOLPATH and FIPTOOL are passed from the main makefile.
-
-OBJECTS = $(FIPTOOLPATH)\fiptool.obj \
- $(FIPTOOLPATH)\tbbr_config.obj \
- $(FIPTOOLPATH)\win_posix.obj
-
-INC = -I$(FIPTOOLPATH) -Iinclude\tools_share
-
-CFLAGS = $(CFLAGS) /nologo /Za /Zi /c /O2 /MT
-
-all: $(FIPTOOL)
-
-$(FIPTOOL): $(OBJECTS)
- $(LD) /nologo /INCREMENTAL:NO /debug /nodefaultlib:libc.lib /out:$@ $(LIBS) $**
-
-.PHONY: clean realclean
-
-clean:
- -@del /f /q $(OBJECTS) > nul
- -@del /f /q $(FIPTOOLPATH)\*.pdb > nul
-
-realclean:
- -@del /f /q $(OBJECTS) > nul
- -@del /f /q $(FIPTOOLPATH)\*.pdb > nul
- -@del /f /q $(FIPTOOL) > nul
-
-.c.obj:
- $(CC) -c $(CFLAGS) $(INC) $< -Fo$@
diff --git a/tools/nxp/create_pbl/Makefile b/tools/nxp/create_pbl/Makefile
index 22aa921..965cc51 100644
--- a/tools/nxp/create_pbl/Makefile
+++ b/tools/nxp/create_pbl/Makefile
@@ -1,18 +1,18 @@
#
# Copyright 2018-2020 NXP
+# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
MAKE_HELPERS_DIRECTORY := ../../../make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
-include ${MAKE_HELPERS_DIRECTORY}build_env.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
-PROJECT_1 := create_pbl${BIN_EXT}
+PROJECT_1 := create_pbl$(.exe)
OBJECTS_1 := create_pbl.o
-PROJECT_2 := byte_swap${BIN_EXT}
+PROJECT_2 := byte_swap$(.exe)
OBJECTS_2 := byte_swap.o
override CPPFLAGS += -D_GNU_SOURCE -D_XOPEN_SOURCE=700
@@ -49,5 +49,5 @@
$(q)$(host-cc) -c ${CPPFLAGS} ${CFLAGS} ${INCLUDE_PATHS} $< -o $@
clean:
- $(call SHELL_DELETE_ALL, ${PROJECT_1} ${OBJECTS_1})
- $(call SHELL_DELETE_ALL, ${PROJECT_2} ${OBJECTS_2})
+ $(q)rm -rf $(PROJECT_1) $(OBJECTS_1)
+ $(q)rm -rf $(PROJECT_2) $(OBJECTS_2)
diff --git a/tools/nxp/create_pbl/create_pbl.mk b/tools/nxp/create_pbl/create_pbl.mk
index 305c049..81f6d13 100644
--- a/tools/nxp/create_pbl/create_pbl.mk
+++ b/tools/nxp/create_pbl/create_pbl.mk
@@ -1,12 +1,13 @@
#
# Copyright 2018-2020 NXP
+# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#
-CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl${BIN_EXT}
-BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap${BIN_EXT}
+CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl$(.exe)
+BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap$(.exe)
HOST_GCC := gcc
diff --git a/tools/nxp/create_pbl/pbl_ch2.mk b/tools/nxp/create_pbl/pbl_ch2.mk
index bf05a12..47ff892 100644
--- a/tools/nxp/create_pbl/pbl_ch2.mk
+++ b/tools/nxp/create_pbl/pbl_ch2.mk
@@ -1,12 +1,13 @@
#
# Copyright 2020 NXP
+# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#
-CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl${BIN_EXT}
-BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap${BIN_EXT}
+CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl$(.exe)
+BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap$(.exe)
HOST_GCC := gcc
diff --git a/tools/nxp/create_pbl/pbl_ch3.mk b/tools/nxp/create_pbl/pbl_ch3.mk
index 15129e4..f5d42cd 100644
--- a/tools/nxp/create_pbl/pbl_ch3.mk
+++ b/tools/nxp/create_pbl/pbl_ch3.mk
@@ -1,13 +1,14 @@
#
# Copyright 2018-2022 NXP
+# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#
SHELL=/bin/bash
-CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl${BIN_EXT}
-BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap${BIN_EXT}
+CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl$(.exe)
+BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap$(.exe)
HOST_GCC := gcc
diff --git a/tools/sptool/Makefile b/tools/sptool/Makefile
index 0da5c09..f579a42 100644
--- a/tools/sptool/Makefile
+++ b/tools/sptool/Makefile
@@ -1,16 +1,15 @@
#
-# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
MAKE_HELPERS_DIRECTORY := ../../make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
-include ${MAKE_HELPERS_DIRECTORY}build_env.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
-SPTOOL ?= sptool${BIN_EXT}
+SPTOOL ?= sptool$(.exe)
PROJECT := $(notdir ${SPTOOL})
OBJECTS := sptool.o
@@ -40,4 +39,4 @@
$(q)$(host-cc) -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
clean:
- $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
+ $(q)rm -rf $(PROJECT) $(OBJECTS)
diff --git a/tools/stm32image/Makefile b/tools/stm32image/Makefile
index 453daae..64b6ccf 100644
--- a/tools/stm32image/Makefile
+++ b/tools/stm32image/Makefile
@@ -1,16 +1,15 @@
#
-# Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
MAKE_HELPERS_DIRECTORY := ../../make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
-include ${MAKE_HELPERS_DIRECTORY}build_env.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
include ${MAKE_HELPERS_DIRECTORY}toolchain.mk
-PROJECT := stm32image${BIN_EXT}
+PROJECT := stm32image$(.exe)
OBJECTS := stm32image.o
HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 -D_GNU_SOURCE
@@ -37,6 +36,6 @@
$(q)$(host-cc) -c ${HOSTCCFLAGS} $< -o $@
clean:
- $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})
+ $(q)rm -rf $(PROJECT) $(OBJECTS)
distclean: clean
diff --git a/tools/tlc/poetry.lock b/tools/tlc/poetry.lock
index 3c0cdf8..ea1b750 100644
--- a/tools/tlc/poetry.lock
+++ b/tools/tlc/poetry.lock
@@ -1331,13 +1331,13 @@
[[package]]
name = "virtualenv"
-version = "20.26.5"
+version = "20.26.6"
description = "Virtual Python Environment builder"
optional = false
python-versions = ">=3.7"
files = [
- {file = "virtualenv-20.26.5-py3-none-any.whl", hash = "sha256:4f3ac17b81fba3ce3bd6f4ead2749a72da5929c01774948e243db9ba41df4ff6"},
- {file = "virtualenv-20.26.5.tar.gz", hash = "sha256:ce489cac131aa58f4b25e321d6d186171f78e6cb13fafbf32a840cee67733ff4"},
+ {file = "virtualenv-20.26.6-py3-none-any.whl", hash = "sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2"},
+ {file = "virtualenv-20.26.6.tar.gz", hash = "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48"},
]
[package.dependencies]