aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile81
-rw-r--r--branch_protection.mk52
-rw-r--r--defaults.mk5
-rw-r--r--docs/Makefile12
-rw-r--r--docs/getting_started/build-options.rst36
-rw-r--r--docs/getting_started/docs-build.rst29
-rw-r--r--drivers/arm/gic/gic_v2.c12
-rw-r--r--fwu/ns_bl1u/ns_bl1u.mk6
-rw-r--r--fwu/ns_bl2u/ns_bl2u.mk6
-rw-r--r--include/common/aarch64/asm_macros.S24
-rw-r--r--include/common/asm_macros_common.S8
-rw-r--r--include/drivers/arm/gic_v2.h5
-rw-r--r--include/lib/aarch64/arch.h5
-rw-r--r--include/lib/aarch64/arch_features.h6
-rw-r--r--include/lib/xlat_tables/xlat_tables_defs.h7
-rw-r--r--include/runtime_services/ffa_helpers.h2
-rw-r--r--lib/aarch32/misc_helpers.S40
-rw-r--r--lib/aarch64/cache_helpers.S12
-rw-r--r--lib/extensions/amu/aarch64/amu_helpers.S90
-rw-r--r--lib/xlat_tables_v2/xlat_tables_core.c12
-rw-r--r--lib/xlat_tables_v2/xlat_tables_utils.c9
-rw-r--r--spm/cactus/aarch64/cactus_entrypoint.S6
-rw-r--r--spm/cactus/cactus-secondary.dts6
-rw-r--r--spm/cactus/cactus-tertiary.dts63
-rw-r--r--spm/cactus/cactus.dts6
-rw-r--r--spm/cactus/cactus.mk14
-rw-r--r--spm/cactus/cactus_def.h12
-rw-r--r--spm/cactus/cactus_ffa_tests.c13
-rw-r--r--spm/cactus/cactus_main.c63
-rw-r--r--spm/cactus_mm/cactus_mm.mk6
-rw-r--r--spm/common/sp_helpers.c16
-rw-r--r--spm/common/sp_helpers.h12
-rw-r--r--spm/ivy/ivy.mk5
-rw-r--r--spm/quark/quark.mk5
-rw-r--r--tftf/tests/plat/nvidia/tegra194/include/tegra194_ras.h290
-rw-r--r--tftf/tests/plat/nvidia/tegra194/serror_handler.S23
-rw-r--r--tftf/tests/plat/nvidia/tegra194/test_ras_corrected.c403
-rw-r--r--tftf/tests/plat/nvidia/tegra194/test_ras_uncorrectable.c388
-rw-r--r--tftf/tests/runtime_services/secure_service/ffa_helpers.c17
-rw-r--r--tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c17
-rw-r--r--tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c9
-rw-r--r--tftf/tests/tests-tegra194.mk11
-rw-r--r--tftf/tests/tests-tegra194.xml15
-rwxr-xr-xtools/generate_json/generate_json.sh13
44 files changed, 1658 insertions, 214 deletions
diff --git a/Makefile b/Makefile
index fea13db..b09e749 100644
--- a/Makefile
+++ b/Makefile
@@ -149,13 +149,20 @@ include ${PLAT_MAKEFILE_FULL}
################################################################################
$(eval $(call assert_boolean,DEBUG))
$(eval $(call assert_boolean,ENABLE_ASSERTIONS))
-$(eval $(call assert_boolean,ENABLE_PAUTH))
$(eval $(call assert_boolean,FIRMWARE_UPDATE))
$(eval $(call assert_boolean,FWU_BL_TEST))
$(eval $(call assert_boolean,NEW_TEST_SESSION))
$(eval $(call assert_boolean,USE_NVM))
################################################################################
+# Process build options
+################################################################################
+
+# Process BRANCH_PROTECTION value and set
+# Pointer Authentication and Branch Target Identification flags
+include branch_protection.mk
+
+################################################################################
# Add definitions to the cpp preprocessor based on the current build options.
# This is done after including the platform specific makefile to allow the
# platform to overwrite the default options
@@ -164,6 +171,7 @@ $(eval $(call add_define,TFTF_DEFINES,ARM_ARCH_MAJOR))
$(eval $(call add_define,TFTF_DEFINES,ARM_ARCH_MINOR))
$(eval $(call add_define,TFTF_DEFINES,DEBUG))
$(eval $(call add_define,TFTF_DEFINES,ENABLE_ASSERTIONS))
+$(eval $(call add_define,TFTF_DEFINES,ENABLE_BTI))
$(eval $(call add_define,TFTF_DEFINES,ENABLE_PAUTH))
$(eval $(call add_define,TFTF_DEFINES,LOG_LEVEL))
$(eval $(call add_define,TFTF_DEFINES,NEW_TEST_SESSION))
@@ -230,10 +238,14 @@ TFTF_CFLAGS += ${COMMON_CFLAGS}
TFTF_ASFLAGS += ${COMMON_ASFLAGS}
TFTF_LDFLAGS += ${COMMON_LDFLAGS}
-ifeq (${ENABLE_PAUTH},1)
-TFTF_CFLAGS += -mbranch-protection=pac-ret
-NS_BL1U_CFLAGS += -mbranch-protection=pac-ret
-NS_BL2U_CFLAGS += -mbranch-protection=pac-ret
+ifneq (${BP_OPTION},none)
+TFTF_CFLAGS += -mbranch-protection=${BP_OPTION}
+NS_BL1U_CFLAGS += -mbranch-protection=${BP_OPTION}
+NS_BL2U_CFLAGS += -mbranch-protection=${BP_OPTION}
+CACTUS_MM_CFLAGS += -mbranch-protection=${BP_OPTION}
+CACTUS_CFLAGS += -mbranch-protection=${BP_OPTION}
+IVY_CFLAGS += -mbranch-protection=${BP_OPTION}
+QUARK_CFLAGS += -mbranch-protection=${BP_OPTION}
endif
#####################################################################################
@@ -514,32 +526,35 @@ cscope:
${Q}cscope -b -q -k
.PHONY: help
+.SILENT: help
help:
- @echo "usage: ${MAKE} PLAT=<${PLATFORMS}> <all|tftf|ns_bl1u|ns_bl2u|cactus|ivy|quark|el3_payload|distclean|clean|checkcodebase|checkpatch>"
- @echo ""
- @echo "PLAT is used to specify which platform you wish to build."
- @echo "If no platform is specified, PLAT defaults to: ${DEFAULT_PLAT}"
- @echo ""
- @echo "Supported Targets:"
- @echo " all Build all supported binaries for this platform"
- @echo " (i.e. TFTF and FWU images)"
- @echo " tftf Build the TFTF image"
- @echo " ns_bl1u Build the NS_BL1U image"
- @echo " ns_bl2u Build the NS_BL2U image"
- @echo " cactus Build the Cactus image (Test S-EL0 payload) and resource description."
- @echo " cactus_mm Build the Cactus-MM image (Test S-EL0 payload)."
- @echo " ivy Build the Ivy image (Test S-EL0 payload) and resource description."
- @echo " quark Build the Quark image (Test S-EL0 payload) and resource description."
- @echo " el3_payload Build the EL3 test payload"
- @echo " checkcodebase Check the coding style of the entire source tree"
- @echo " checkpatch Check the coding style on changes in the current"
- @echo " branch against BASE_COMMIT (default origin/master)"
- @echo " doc Build html based documentation using Sphinx tool"
- @echo " clean Clean the build for the selected platform"
- @echo " cscope Generate cscope index"
- @echo " distclean Remove all build artifacts for all platforms"
- @echo ""
- @echo "note: most build targets require PLAT to be set to a specific platform."
- @echo ""
- @echo "example: build all targets for the FVP platform:"
- @echo " CROSS_COMPILE=aarch64-none-elf- make PLAT=fvp all"
+ echo "usage: ${MAKE} PLAT=<${PLATFORMS}> \
+<all|tftf|ns_bl1u|ns_bl2u|cactus|ivy|quark|el3_payload|distclean|clean|checkcodebase|checkpatch|help_tests>"
+ echo ""
+ echo "PLAT is used to specify which platform you wish to build."
+ echo "If no platform is specified, PLAT defaults to: ${DEFAULT_PLAT}"
+ echo ""
+ echo "Supported Targets:"
+ echo " all Build all supported binaries for this platform"
+ echo " (i.e. TFTF and FWU images)"
+ echo " tftf Build the TFTF image"
+ echo " ns_bl1u Build the NS_BL1U image"
+ echo " ns_bl2u Build the NS_BL2U image"
+ echo " cactus Build the Cactus image (Test S-EL0 payload) and resource description."
+ echo " cactus_mm Build the Cactus-MM image (Test S-EL0 payload)."
+ echo " ivy Build the Ivy image (Test S-EL0 payload) and resource description."
+ echo " quark Build the Quark image (Test S-EL0 payload) and resource description."
+ echo " el3_payload Build the EL3 test payload"
+ echo " checkcodebase Check the coding style of the entire source tree"
+ echo " checkpatch Check the coding style on changes in the current"
+ echo " branch against BASE_COMMIT (default origin/master)"
+ echo " doc Build html based documentation using Sphinx tool"
+ echo " clean Clean the build for the selected platform"
+ echo " cscope Generate cscope index"
+ echo " distclean Remove all build artifacts for all platforms"
+ echo " help_tests List all possible sets of tests"
+ echo ""
+ echo "note: most build targets require PLAT to be set to a specific platform."
+ echo ""
+ echo "example: build all targets for the FVP platform:"
+ echo " CROSS_COMPILE=aarch64-none-elf- make PLAT=fvp all"
diff --git a/branch_protection.mk b/branch_protection.mk
new file mode 100644
index 0000000..c16cdad
--- /dev/null
+++ b/branch_protection.mk
@@ -0,0 +1,52 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Default, static values for build variables, listed in alphabetic order.
+# Dependencies between build options, if any, are handled in the top-level
+# Makefile, after this file is included. This ensures that the former is better
+# poised to handle dependencies, as all build variables would have a default
+# value by then.
+
+# Select the branch protection features to use.
+BRANCH_PROTECTION := 0
+
+# Flag to enable Branch Target Identification in the TFTF.
+# Internal flag not meant for direct setting.
+# Use BRANCH_PROTECTION to enable BTI.
+ENABLE_BTI := 0
+
+# Enable Pointer Authentication support in the TFTF.
+# Internal flag not meant for direct setting.
+# Use BRANCH_PROTECTION to enable PAUTH.
+ENABLE_PAUTH := 0
+
+# Process BRANCH_PROTECTION value and set
+# Pointer Authentication and Branch Target Identification flags
+ifeq (${BRANCH_PROTECTION},0)
+ # Default value turns off all types of branch protection
+ BP_OPTION := none
+else ifneq (${ARCH},aarch64)
+ $(error BRANCH_PROTECTION requires AArch64)
+else ifeq (${BRANCH_PROTECTION},1)
+ # Enables all types of branch protection features
+ BP_OPTION := standard
+ ENABLE_BTI := 1
+ ENABLE_PAUTH := 1
+else ifeq (${BRANCH_PROTECTION},2)
+ # Return address signing to its standard level
+ BP_OPTION := pac-ret
+ ENABLE_PAUTH := 1
+else ifeq (${BRANCH_PROTECTION},3)
+ # Extend the signing to include leaf functions
+ BP_OPTION := pac-ret+leaf
+ ENABLE_PAUTH := 1
+else ifeq (${BRANCH_PROTECTION},4)
+ # Turn on branch target identification mechanism
+ BP_OPTION := bti
+ ENABLE_BTI := 1
+else
+ $(error Unknown BRANCH_PROTECTION value ${BRANCH_PROTECTION})
+endif
diff --git a/defaults.mk b/defaults.mk
index cf90aaf..ca44b47 100644
--- a/defaults.mk
+++ b/defaults.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2020, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -26,9 +26,6 @@ DEBUG := 0
# Build platform
DEFAULT_PLAT := fvp
-# Enable Pointer Authentication support in the TFTF
-ENABLE_PAUTH := 0
-
# Whether the Firmware Update images (i.e. NS_BL1U and NS_BL2U images) should be
# built. The platform makefile is free to override this value.
FIRMWARE_UPDATE := 0
diff --git a/docs/Makefile b/docs/Makefile
index a7083fb..5691e6c 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2019, ARM Limited. All rights reserved.
+# Copyright (c) 2019-2020, ARM Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -7,11 +7,11 @@
#
# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-SPHINXPROJ = TrustedFirmware-A Tests
-SOURCEDIR = .
-BUILDDIR = build
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SPHINXPROJ ?= TrustedFirmware-A Tests
+SOURCEDIR ?= $(CURDIR)
+BUILDDIR ?= build
# Put it first so that "make" without argument is like "make help".
help:
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 95724e7..8815466 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -30,6 +30,37 @@ payload, whose simplistic build system is mostly independent.
- ``ARM_ARCH_MINOR``: The minor version of Arm Architecture to target when
compiling TF-A Tests. Its value must be a numeric, and defaults to 0.
+- ``BRANCH_PROTECTION``: Numeric value to enable ARMv8.3 Pointer Authentication
+ (``ARMv8.3-PAuth``) and ARMv8.5 Branch Target Identification (``ARMv8.5-BTI``)
+ support in the Trusted Firmware-A Test Framework itself.
+ If enabled, it is needed to use a compiler that supports the option
+ ``-mbranch-protection`` (GCC 9 and later).
+ Selects the branch protection features to use:
+- 0: Default value turns off all types of branch protection
+- 1: Enables all types of branch protection features
+- 2: Return address signing to its standard level
+- 3: Extend the signing to include leaf functions
+- 4: Turn on branch target identification mechanism
+
+ The table below summarizes ``BRANCH_PROTECTION`` values, GCC compilation
+ options and resulting PAuth/BTI features.
+
+ +-------+--------------+-------+-----+
+ | Value | GCC option | PAuth | BTI |
+ +=======+==============+=======+=====+
+ | 0 | none | N | N |
+ +-------+--------------+-------+-----+
+ | 1 | standard | Y | Y |
+ +-------+--------------+-------+-----+
+ | 2 | pac-ret | Y | N |
+ +-------+--------------+-------+-----+
+ | 3 | pac-ret+leaf | Y | N |
+ +-------+--------------+-------+-----+
+ | 4 | bti | N | Y |
+ +-------+--------------+-------+-----+
+
+ This option defaults to 0 and this is an experimental feature.
+
- ``DEBUG``: Chooses between a debug and a release build. A debug build
typically embeds assertions checking the validity of some assumptions and its
output is more verbose. The option can take either 0 (release) or 1 (debug)
@@ -90,11 +121,6 @@ Arm FVP Platform Specific Build Options
TFTF-specific Build Options
---------------------------
-- ``ENABLE_PAUTH``: Boolean option to enable ARMv8.3 Pointer Authentication
- (``ARMv8.3-PAuth``) support in the Trusted Firmware-A Test Framework itself.
- If enabled, it is needed to use a compiler that supports the option
- ``-mbranch-protection`` (GCC 9 and later). It defaults to 0.
-
- ``NEW_TEST_SESSION``: Choose whether a new test session should be started
every time or whether the framework should determine whether a previous
session was interrupted and resume it. It can take either 1 (always
diff --git a/docs/getting_started/docs-build.rst b/docs/getting_started/docs-build.rst
index 6a6992b..1b8c1eb 100644
--- a/docs/getting_started/docs-build.rst
+++ b/docs/getting_started/docs-build.rst
@@ -64,7 +64,7 @@ Output from the build process will be placed in:
::
- docs/build/html/
+ docs/build/html
We also support building documentation in other formats. From the ``docs``
directory of the project, run the following command to see the supported
@@ -76,9 +76,36 @@ top-level Makefile for TF-A Tests themselves.
make help
+Building rendered documentation from a container
+------------------------------------------------
+
+There may be cases where you can not either install or upgrade required
+dependencies to generate the documents, so in this case, one way to
+create the documentation is through a docker container. The first step is
+to check if `docker`_ is installed in your host, otherwise check main docker
+page for installation instructions. Once installed, run the following script
+from project root directory
+
+.. code:: shell
+
+ docker run --rm -v $PWD:/TF sphinxdoc/sphinx \
+ bash -c 'cd /TF && \
+ pip3 install plantuml -r ./docs/requirements.txt && make doc'
+
+The above command fetches the ``sphinxdoc/sphinx`` container from `docker
+hub`_, launches the container, installs documentation requirements and finally
+creates the documentation. Once done, exit the container and output from the
+build process will be placed in:
+
+::
+
+ docs/build/html
+
--------------
*Copyright (c) 2020, Arm Limited. All rights reserved.*
.. _Sphinx: http://www.sphinx-doc.org/en/master/
.. _pip homepage: https://pip.pypa.io/en/stable/
+.. _docker: https://www.docker.com/
+.. _docker hub: https://hub.docker.com/repository/docker/sphinxdoc/sphinx
diff --git a/drivers/arm/gic/gic_v2.c b/drivers/arm/gic/gic_v2.c
index 7904ed1..ef93007 100644
--- a/drivers/arm/gic/gic_v2.c
+++ b/drivers/arm/gic/gic_v2.c
@@ -44,6 +44,11 @@ static unsigned int core_pos_to_gic_id(unsigned int core_pos)
/*******************************************************************************
* GIC Distributor interface accessors for reading entire registers
******************************************************************************/
+uint8_t gicd_read_itargetsr_byte(unsigned int base, unsigned int interrupt_id)
+{
+ return mmio_read_8(base + GICD_ITARGETSR + interrupt_id);
+}
+
unsigned int gicd_read_itargetsr(unsigned int base, unsigned int interrupt_id)
{
unsigned n = interrupt_id >> ITARGETSR_SHIFT;
@@ -266,12 +271,19 @@ void gicv2_set_itargetsr(unsigned int num, unsigned int core_pos)
gicd_set_itargetsr(gicd_base_addr, num, gic_cpu_id);
}
+uint8_t gicv2_read_itargetsr_value(unsigned int num)
+{
+ return gicd_read_itargetsr_byte(gicd_base_addr, num);
+}
+
void gicv2_set_itargetsr_value(unsigned int num, unsigned int val)
{
assert(gicd_base_addr);
assert(IS_SPI(num));
gicd_write_itargetsr_byte(gicd_base_addr, num, val);
+
+ assert(gicv2_read_itargetsr_value(num) == val);
}
unsigned int gicv2_gicd_get_isenabler(unsigned int num)
diff --git a/fwu/ns_bl1u/ns_bl1u.mk b/fwu/ns_bl1u/ns_bl1u.mk
index 7e0e767..2b45b8d 100644
--- a/fwu/ns_bl1u/ns_bl1u.mk
+++ b/fwu/ns_bl1u/ns_bl1u.mk
@@ -4,6 +4,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include branch_protection.mk
include lib/xlat_tables_v2/xlat_tables.mk
include lib/compiler-rt/compiler-rt.mk
@@ -67,9 +68,8 @@ $(eval $(call add_define,NS_BL1U_DEFINES,ARM_ARCH_MAJOR))
$(eval $(call add_define,NS_BL1U_DEFINES,ARM_ARCH_MINOR))
$(eval $(call add_define,NS_BL1U_DEFINES,DEBUG))
$(eval $(call add_define,NS_BL1U_DEFINES,ENABLE_ASSERTIONS))
+$(eval $(call add_define,NS_BL1U_DEFINES,ENABLE_BTI))
+$(eval $(call add_define,NS_BL1U_DEFINES,ENABLE_PAUTH))
$(eval $(call add_define,NS_BL1U_DEFINES,FWU_BL_TEST))
$(eval $(call add_define,NS_BL1U_DEFINES,LOG_LEVEL))
$(eval $(call add_define,NS_BL1U_DEFINES,PLAT_${PLAT}))
-ifeq (${ARCH},aarch64)
- $(eval $(call add_define,NS_BL1U_DEFINES,ENABLE_PAUTH))
-endif
diff --git a/fwu/ns_bl2u/ns_bl2u.mk b/fwu/ns_bl2u/ns_bl2u.mk
index b6e616e..0864313 100644
--- a/fwu/ns_bl2u/ns_bl2u.mk
+++ b/fwu/ns_bl2u/ns_bl2u.mk
@@ -4,6 +4,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include branch_protection.mk
include lib/xlat_tables_v2/xlat_tables.mk
include lib/compiler-rt/compiler-rt.mk
@@ -62,9 +63,8 @@ $(eval $(call add_define,NS_BL2U_DEFINES,ARM_ARCH_MAJOR))
$(eval $(call add_define,NS_BL2U_DEFINES,ARM_ARCH_MINOR))
$(eval $(call add_define,NS_BL2U_DEFINES,DEBUG))
$(eval $(call add_define,NS_BL2U_DEFINES,ENABLE_ASSERTIONS))
+$(eval $(call add_define,NS_BL2U_DEFINES,ENABLE_BTI))
+$(eval $(call add_define,NS_BL2U_DEFINES,ENABLE_PAUTH))
$(eval $(call add_define,NS_BL2U_DEFINES,FWU_BL_TEST))
$(eval $(call add_define,NS_BL2U_DEFINES,LOG_LEVEL))
$(eval $(call add_define,NS_BL2U_DEFINES,PLAT_${PLAT}))
-ifeq (${ARCH},aarch64)
- $(eval $(call add_define,NS_BL2U_DEFINES,ENABLE_PAUTH))
-endif
diff --git a/include/common/aarch64/asm_macros.S b/include/common/aarch64/asm_macros.S
index 5298ae0..d829133 100644
--- a/include/common/aarch64/asm_macros.S
+++ b/include/common/aarch64/asm_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -192,4 +192,26 @@
b \label_error
.endm
+ /*
+ * Helper macro to read system register value into x0
+ */
+ .macro read reg:req
+#if ENABLE_BTI
+ bti j
+#endif
+ mrs x0, \reg
+ ret
+ .endm
+
+ /*
+ * Helper macro to write value from x1 to system register
+ */
+ .macro write reg:req
+#if ENABLE_BTI
+ bti j
+#endif
+ msr \reg, x1
+ ret
+ .endm
+
#endif /* __ASM_MACROS_S__ */
diff --git a/include/common/asm_macros_common.S b/include/common/asm_macros_common.S
index d38dcce..1cf94f4 100644
--- a/include/common/asm_macros_common.S
+++ b/include/common/asm_macros_common.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,6 +7,12 @@
#ifndef __ASM_MACROS_COMMON_S__
#define __ASM_MACROS_COMMON_S__
+#include <lib/utils_def.h>
+
+#if ENABLE_BTI && !ARM_ARCH_AT_LEAST(8, 5)
+#error Branch Target Identification requires ARM_ARCH_MINOR >= 5
+#endif
+
/*
* This macro is used to create a function label and place the
* code into a separate text section based on the function name
diff --git a/include/drivers/arm/gic_v2.h b/include/drivers/arm/gic_v2.h
index 8432a3f..6e7b764 100644
--- a/include/drivers/arm/gic_v2.h
+++ b/include/drivers/arm/gic_v2.h
@@ -242,6 +242,11 @@ unsigned int gicv2_gicd_get_ispendr(unsigned int interrupt_id);
unsigned int gicv2_gicc_read_iar(void);
/*
+ * Read and return the target core mask of interrupt ID `num`.
+ */
+uint8_t gicv2_read_itargetsr_value(unsigned int num);
+
+/*
* Set the bit corresponding to `num` in the GICD ICENABLER register.
*/
void gicv2_gicd_set_icenabler(unsigned int num);
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 718964e..2d2a892 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -235,6 +235,11 @@
#define SSBS_UNAVAILABLE ULL(0) /* No architectural SSBS support */
+#define ID_AA64PFR1_EL1_BT_SHIFT U(0)
+#define ID_AA64PFR1_EL1_BT_MASK ULL(0xf)
+
+#define BTI_IMPLEMENTED ULL(1) /* The BTI mechanism is implemented */
+
#define ID_AA64PFR1_EL1_MTE_SHIFT U(8)
#define ID_AA64PFR1_EL1_MTE_MASK ULL(0xf)
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index fc9e8d4..15eb784 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -62,6 +62,12 @@ static inline bool is_armv8_4_ttst_present(void)
ID_AA64MMFR2_EL1_ST_MASK) == 1U;
}
+static inline bool is_armv8_5_bti_present(void)
+{
+ return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_BT_SHIFT) &
+ ID_AA64PFR1_EL1_BT_MASK) == BTI_IMPLEMENTED;
+}
+
static inline unsigned int get_armv8_5_mte_support(void)
{
return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) &
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 8a5ce53..1fd3c83 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -62,6 +62,11 @@
#define OSH (U(0x2) << 6)
#define ISH (U(0x3) << 6)
+#ifdef __aarch64__
+/* Guarded Page bit */
+#define GP (ULL(1) << 50)
+#endif
+
#define TABLE_ADDR_MASK ULL(0x0000FFFFFFFFF000)
/*
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 0692aa9..2cc2c46 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -23,6 +23,7 @@
typedef unsigned short ffa_vm_id_t;
typedef unsigned short ffa_vm_count_t;
typedef unsigned short ffa_vcpu_count_t;
+typedef uint32_t ffa_int_id_t;
#ifndef __ASSEMBLY__
@@ -59,6 +60,7 @@ smc_ret_values ffa_error(int32_t error_code);
smc_ret_values ffa_features(uint32_t feature);
smc_ret_values ffa_partition_info_get(const uint32_t uuid[4]);
smc_ret_values ffa_rx_release(void);
+smc_ret_values ffa_rxtx_map(uintptr_t send, uintptr_t recv, uint32_t pages);
#endif /* __ASSEMBLY__ */
diff --git a/lib/aarch32/misc_helpers.S b/lib/aarch32/misc_helpers.S
index ab37be9..6cabea2 100644
--- a/lib/aarch32/misc_helpers.S
+++ b/lib/aarch32/misc_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -16,24 +16,29 @@
* void zeromem(void *mem, unsigned int length);
*
* Initialise a memory region to 0.
- * The memory address and length must be 4-byte aligned.
+ * The memory address must be 4-byte aligned.
* -----------------------------------------------------------------------
*/
func zeromem
#if ENABLE_ASSERTIONS
tst r0, #0x3
ASM_ASSERT(eq)
- tst r1, #0x3
- ASM_ASSERT(eq)
#endif
- add r2, r0, r1
- mov r1, #0
-z_loop:
- cmp r2, r0
- beq z_end
- str r1, [r0], #4
- b z_loop
-z_end:
+ mov r2, #0
+/* zero 4 bytes at a time */
+z_loop4:
+ cmp r1, #4
+ blo z_loop1
+ str r2, [r0], #4
+ subs r1, r1, #4
+ bne z_loop4
+ bx lr
+
+/* zero byte per byte */
+z_loop1:
+ strb r2, [r0], #1
+ subs r1, r1, #1
+ bne z_loop1
bx lr
endfunc zeromem
@@ -54,20 +59,19 @@ func memcpy4
/* copy 4 bytes at a time */
m_loop4:
cmp r2, #4
- blt m_loop1
+ blo m_loop1
ldr r3, [r1], #4
str r3, [r0], #4
- sub r2, r2, #4
- b m_loop4
+ subs r2, r2, #4
+ bne m_loop4
+ bx lr
+
/* copy byte per byte */
m_loop1:
- cmp r2,#0
- beq m_end
ldrb r3, [r1], #1
strb r3, [r0], #1
subs r2, r2, #1
bne m_loop1
-m_end:
bx lr
endfunc memcpy4
diff --git a/lib/aarch64/cache_helpers.S b/lib/aarch64/cache_helpers.S
index 9c40b9d..de9c8e4 100644
--- a/lib/aarch64/cache_helpers.S
+++ b/lib/aarch64/cache_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -30,7 +30,7 @@ loop_\op:
dc \op, x0
add x0, x0, x2
cmp x0, x1
- b.lo loop_\op
+ b.lo loop_\op
dsb sy
exit_loop_\op:
ret
@@ -91,6 +91,9 @@ func do_dcsw_op
cbz x3, exit
adr x14, dcsw_loop_table // compute inner loop address
add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions
+#if ENABLE_BTI
+ add x14, x14, x0, lsl #2 // inner loop is + "bti j" instruction
+#endif
mov x0, x9
mov w8, #1
loop1:
@@ -116,6 +119,9 @@ loop1:
br x14 // jump to DC operation specific loop
.macro dcsw_loop _op
+#if ENABLE_BTI
+ bti j
+#endif
loop2_\_op:
lsl w7, w6, w2 // w7 = aligned max set number
@@ -134,7 +140,7 @@ loop3_\_op:
level_done:
add x10, x10, #2 // increment cache number
cmp x3, x10
- b.hi loop1
+ b.hi loop1
msr csselr_el1, xzr // select cache level 0 in csselr
dsb sy // barrier to complete final cache operation
isb
diff --git a/lib/extensions/amu/aarch64/amu_helpers.S b/lib/extensions/amu/aarch64/amu_helpers.S
index 862a713..061f3fd 100644
--- a/lib/extensions/amu/aarch64/amu_helpers.S
+++ b/lib/extensions/amu/aarch64/amu_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,35 +18,29 @@
* and return it in `x0`.
*/
func amu_group0_cnt_read_internal
+ adr x1, 1f
#if ENABLE_ASSERTIONS
/*
* It can be dangerous to call this function with an
* out of bounds index. Ensure `idx` is valid.
*/
- mov x1, x0
- lsr x1, x1, #2
- cmp x1, #0
+ tst x0, #~3
ASM_ASSERT(eq)
#endif
-
/*
* Given `idx` calculate address of mrs/ret instruction pair
* in the table below.
*/
- adr x1, 1f
- lsl x0, x0, #3 /* each mrs/ret sequence is 8 bytes */
- add x1, x1, x0
+ add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */
+#if ENABLE_BTI
+ add x1, x1, x0, lsl #2 /* + "bti j" instruction */
+#endif
br x1
-1:
- mrs x0, AMEVCNTR00_EL0 /* index 0 */
- ret
- mrs x0, AMEVCNTR01_EL0 /* index 1 */
- ret
- mrs x0, AMEVCNTR02_EL0 /* index 2 */
- ret
- mrs x0, AMEVCNTR03_EL0 /* index 3 */
- ret
+1: read AMEVCNTR00_EL0 /* index 0 */
+ read AMEVCNTR01_EL0 /* index 1 */
+ read AMEVCNTR02_EL0 /* index 2 */
+ read AMEVCNTR03_EL0 /* index 3 */
endfunc amu_group0_cnt_read_internal
/*
@@ -56,57 +50,39 @@ endfunc amu_group0_cnt_read_internal
* and return it in `x0`.
*/
func amu_group1_cnt_read_internal
+ adr x1, 1f
#if ENABLE_ASSERTIONS
/*
* It can be dangerous to call this function with an
* out of bounds index. Ensure `idx` is valid.
*/
- mov x1, x0
- lsr x1, x1, #4
- cmp x1, #0
+ tst x0, #~0xF
ASM_ASSERT(eq)
#endif
-
/*
* Given `idx` calculate address of mrs/ret instruction pair
* in the table below.
*/
- adr x1, 1f
- lsl x0, x0, #3 /* each mrs/ret sequence is 8 bytes */
- add x1, x1, x0
+ add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */
+#if ENABLE_BTI
+ add x1, x1, x0, lsl #2 /* + "bti j" instruction */
+#endif
br x1
-1:
- mrs x0, AMEVCNTR10_EL0 /* index 0 */
- ret
- mrs x0, AMEVCNTR11_EL0 /* index 1 */
- ret
- mrs x0, AMEVCNTR12_EL0 /* index 2 */
- ret
- mrs x0, AMEVCNTR13_EL0 /* index 3 */
- ret
- mrs x0, AMEVCNTR14_EL0 /* index 4 */
- ret
- mrs x0, AMEVCNTR15_EL0 /* index 5 */
- ret
- mrs x0, AMEVCNTR16_EL0 /* index 6 */
- ret
- mrs x0, AMEVCNTR17_EL0 /* index 7 */
- ret
- mrs x0, AMEVCNTR18_EL0 /* index 8 */
- ret
- mrs x0, AMEVCNTR19_EL0 /* index 9 */
- ret
- mrs x0, AMEVCNTR1A_EL0 /* index 10 */
- ret
- mrs x0, AMEVCNTR1B_EL0 /* index 11 */
- ret
- mrs x0, AMEVCNTR1C_EL0 /* index 12 */
- ret
- mrs x0, AMEVCNTR1D_EL0 /* index 13 */
- ret
- mrs x0, AMEVCNTR1E_EL0 /* index 14 */
- ret
- mrs x0, AMEVCNTR1F_EL0 /* index 15 */
- ret
+1: read AMEVCNTR10_EL0 /* index 0 */
+ read AMEVCNTR11_EL0 /* index 1 */
+ read AMEVCNTR12_EL0 /* index 2 */
+ read AMEVCNTR13_EL0 /* index 3 */
+ read AMEVCNTR14_EL0 /* index 4 */
+ read AMEVCNTR15_EL0 /* index 5 */
+ read AMEVCNTR16_EL0 /* index 6 */
+ read AMEVCNTR17_EL0 /* index 7 */
+ read AMEVCNTR18_EL0 /* index 8 */
+ read AMEVCNTR19_EL0 /* index 9 */
+ read AMEVCNTR1A_EL0 /* index 10 */
+ read AMEVCNTR1B_EL0 /* index 11 */
+ read AMEVCNTR1C_EL0 /* index 12 */
+ read AMEVCNTR1D_EL0 /* index 13 */
+ read AMEVCNTR1E_EL0 /* index 14 */
+ read AMEVCNTR1F_EL0 /* index 15 */
endfunc amu_group1_cnt_read_internal
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index 933b17a..c3dd445 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -1,9 +1,10 @@
/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <arch_features.h>
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
@@ -193,6 +194,15 @@ uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr,
if (mem_type == MT_MEMORY) {
desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);
+#if ENABLE_BTI
+ /* Check if Branch Target Identification is implemented */
+ if (is_armv8_5_bti_present() &&
+ ((attr & (MT_TYPE_MASK | MT_RW |
+ MT_EXECUTE_NEVER)) == MT_CODE)) {
+ /* Set GP bit for block and page code entries */
+ desc |= GP;
+ }
+#endif
} else {
assert(mem_type == MT_NON_CACHEABLE);
desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH);
diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c
index 41c01ae..168d492 100644
--- a/lib/xlat_tables_v2/xlat_tables_utils.c
+++ b/lib/xlat_tables_v2/xlat_tables_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -94,6 +94,13 @@ static void xlat_desc_print(const xlat_ctx_t *ctx, uint64_t desc)
}
printf(((LOWER_ATTRS(NS) & desc) != 0ULL) ? "-NS" : "-S");
+
+#ifdef __aarch64__
+ /* Check Guarded Page bit */
+ if ((desc & GP) != 0ULL) {
+ printf("-GP");
+ }
+#endif
}
static const char * const level_spacers[] = {
diff --git a/spm/cactus/aarch64/cactus_entrypoint.S b/spm/cactus/aarch64/cactus_entrypoint.S
index 4fe17e3..383c319 100644
--- a/spm/cactus/aarch64/cactus_entrypoint.S
+++ b/spm/cactus/aarch64/cactus_entrypoint.S
@@ -35,6 +35,12 @@ pie_fixup:
add x1, x1, x0
bl fixup_gdt_reloc
+ /* Set up exceptions vector table */
+ adrp x0, tftf_vector
+ add x0, x0, :lo12:tftf_vector
+ msr vbar_el1, x0
+ isb
+
/* And jump to the C entrypoint. */
b cactus_main
diff --git a/spm/cactus/cactus-secondary.dts b/spm/cactus/cactus-secondary.dts
index 8a140a9..661684b 100644
--- a/spm/cactus/cactus-secondary.dts
+++ b/spm/cactus/cactus-secondary.dts
@@ -20,7 +20,7 @@
id = <2>;
auxiliary-id = <0xae>;
stream-endpoint-ids = <0 1 2 3>;
- execution-ctx-count = <1>;
+ execution-ctx-count = <8>;
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0x7100000>;
@@ -45,14 +45,14 @@
rxbuffer: rx-buffer {
description = "rx-buffer";
pages-count = <1>;
- base-address = <0x00000000 0x7202000>;
+ base-address = <0x00000000 0x7302000>;
attributes = <0x1>; /* read-only */
};
txbuffer: tx-buffer {
description = "tx-buffer";
pages-count = <1>;
- base-address = <0x00000000 0x7203000>;
+ base-address = <0x00000000 0x7303000>;
attributes = <0x3>; /* read-write */
};
diff --git a/spm/cactus/cactus-tertiary.dts b/spm/cactus/cactus-tertiary.dts
new file mode 100644
index 0000000..ea7d5d6
--- /dev/null
+++ b/spm/cactus/cactus-tertiary.dts
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP)
+ * that has additional optional properties defined.
+ *
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-manifest-1.0";
+
+ /* Properties */
+ description = "Base-1";
+ ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+ uuid = <0x79b55c73 0x1d8c44b9 0x859361e1 0x770ad8d2>;
+ id = <3>;
+ auxiliary-id = <0xae>;
+ stream-endpoint-ids = <0 1 2 3>;
+ execution-ctx-count = <8>;
+ exception-level = <2>; /* S-EL1 */
+ execution-state = <0>; /* AARCH64 */
+ load-address = <0x7200000>;
+ entrypoint-offset = <0x00001000>;
+ xlat-granule = <0>; /* 4KiB */
+ boot-order = <0>;
+ messaging-method = <0>; /* Direct messaging only */
+ run-time-model = <0>; /* Run to completion */
+
+ /* Boot protocol */
+ gp-register-num = <0x0>;
+
+ memory-regions {
+ compatible = "arm,ffa-manifest-memory-regions";
+
+ /* Without optional base-address */
+ test-memory {
+ description = "test-memory";
+ pages-count = <4>;
+ attributes = <0x7>; /* read-write-execute */
+ };
+ };
+
+ device-regions {
+ compatible = "arm,ffa-manifest-device-regions";
+
+ test-reg {
+ /* Dummy values */
+ base-address = <0x00000000 0x25000000>;
+ pages-count = <16>;
+ attributes = <0x3>; /* read-write */
+ reg = <0x10000008 0x00000001 1>;
+ smmu-id = <1>;
+ stream-ids = <0x0 0x1>;
+ interrupts = <0x2 0x3>,
+ <0x4 0x5>;
+ };
+ };
+
+};
diff --git a/spm/cactus/cactus.dts b/spm/cactus/cactus.dts
index 2e30db4..e64d3a8 100644
--- a/spm/cactus/cactus.dts
+++ b/spm/cactus/cactus.dts
@@ -20,7 +20,7 @@
id = <1>;
auxiliary-id = <0xae>;
stream-endpoint-ids = <0 1 2 3>;
- execution-ctx-count = <1>;
+ execution-ctx-count = <8>;
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0x7000000>;
@@ -45,14 +45,14 @@
rxbuffer: rx-buffer {
description = "rx-buffer";
pages-count = <1>;
- base-address = <0x00000000 0x7200000>;
+ base-address = <0x00000000 0x7300000>;
attributes = <0x1>; /* read-only */
};
txbuffer: tx-buffer {
description = "tx-buffer";
pages-count = <1>;
- base-address = <0x00000000 0x7201000>;
+ base-address = <0x00000000 0x7301000>;
attributes = <0x3>; /* read-write */
};
diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk
index d98cd2a..e6577c3 100644
--- a/spm/cactus/cactus.mk
+++ b/spm/cactus/cactus.mk
@@ -4,6 +4,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include branch_protection.mk
include lib/xlat_tables_v2/xlat_tables.mk
CACTUS_DTB := $(BUILD_PLAT)/cactus.dtb
@@ -17,9 +18,10 @@ CACTUS_INCLUDES := \
-Iinclude/lib/${ARCH} \
-Iinclude/lib/utils \
-Iinclude/lib/xlat_tables \
+ -Iinclude/plat/common \
-Iinclude/runtime_services \
-Ispm/cactus \
- -Ispm/common \
+ -Ispm/common
CACTUS_SOURCES := \
$(addprefix spm/cactus/, \
@@ -37,7 +39,9 @@ CACTUS_SOURCES := \
CACTUS_SOURCES += \
tftf/framework/debug.c \
tftf/framework/${ARCH}/asm_debug.S \
- tftf/tests/runtime_services/secure_service/ffa_helpers.c
+ tftf/tests/runtime_services/secure_service/ffa_helpers.c \
+ tftf/framework/${ARCH}/exceptions.S \
+ tftf/framework/${ARCH}/exception_report.c
CACTUS_SOURCES += drivers/arm/pl011/${ARCH}/pl011_console.S \
lib/${ARCH}/cache_helpers.S \
@@ -53,11 +57,15 @@ CACTUS_LINKERFILE := spm/cactus/cactus.ld.S
CACTUS_DEFINES :=
+$(eval $(call add_define,CACTUS_DEFINES,ARM_ARCH_MAJOR))
+$(eval $(call add_define,CACTUS_DEFINES,ARM_ARCH_MINOR))
$(eval $(call add_define,CACTUS_DEFINES,DEBUG))
+$(eval $(call add_define,CACTUS_DEFINES,ENABLE_ASSERTIONS))
+$(eval $(call add_define,CACTUS_DEFINES,ENABLE_BTI))
+$(eval $(call add_define,CACTUS_DEFINES,ENABLE_PAUTH))
$(eval $(call add_define,CACTUS_DEFINES,FVP_CLUSTER_COUNT))
$(eval $(call add_define,CACTUS_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
$(eval $(call add_define,CACTUS_DEFINES,FVP_MAX_PE_PER_CPU))
-$(eval $(call add_define,CACTUS_DEFINES,ENABLE_ASSERTIONS))
$(eval $(call add_define,CACTUS_DEFINES,LOG_LEVEL))
$(eval $(call add_define,CACTUS_DEFINES,PLAT_${PLAT}))
diff --git a/spm/cactus/cactus_def.h b/spm/cactus/cactus_def.h
index 0d3df2e..be6f06a 100644
--- a/spm/cactus/cactus_def.h
+++ b/spm/cactus/cactus_def.h
@@ -24,22 +24,24 @@
* RX/TX buffer used by VM's in SPM for memory sharing
* Each VM allocated 2 pages, one for RX and one for TX buffer.
*/
-#define CACTUS_RX_BASE ULL(0x7200000)
+#define CACTUS_RX_BASE ULL(0x7300000)
#define CACTUS_TX_BASE CACTUS_RX_BASE + PAGE_SIZE
#define CACTUS_RX_TX_SIZE PAGE_SIZE * 2
/*
* RX/TX buffer helpers.
*/
-#define get_sp_rx_start(sp_id) (CACTUS_RX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE))
-#define get_sp_rx_end(sp_id) (CACTUS_RX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE) + PAGE_SIZE)
-#define get_sp_tx_start(sp_id) (CACTUS_TX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE))
-#define get_sp_tx_end(sp_id) (CACTUS_TX_BASE + ((sp_id - 1) * CACTUS_RX_TX_SIZE) + PAGE_SIZE)
+#define get_sp_rx_start(sp_id) (CACTUS_RX_BASE + (((sp_id & 0x7FFFU) - 1U) * CACTUS_RX_TX_SIZE))
+#define get_sp_rx_end(sp_id) (CACTUS_RX_BASE + (((sp_id & 0x7FFFU) - 1U) * CACTUS_RX_TX_SIZE) + PAGE_SIZE)
+#define get_sp_tx_start(sp_id) (CACTUS_TX_BASE + (((sp_id & 0x7FFFU) - 1U) * CACTUS_RX_TX_SIZE))
+#define get_sp_tx_end(sp_id) (CACTUS_TX_BASE + (((sp_id & 0x7FFFU) - 1U) * CACTUS_RX_TX_SIZE) + PAGE_SIZE)
/*
* UUID of secure partition as defined in the respective manifests.
*/
#define PRIMARY_UUID {0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb}
#define SECONDARY_UUID {0xd1582309, 0xf02347b9, 0x827c4464, 0xf5578fc8}
+#define TERTIARY_UUID {0x79b55c73, 0x1d8c44b9, 0x859361e1, 0x770ad8d2}
+
#endif /* CACTUS_DEF_H */
diff --git a/spm/cactus/cactus_ffa_tests.c b/spm/cactus/cactus_ffa_tests.c
index 25c20b0..a242e41 100644
--- a/spm/cactus/cactus_ffa_tests.c
+++ b/spm/cactus/cactus_ffa_tests.c
@@ -16,6 +16,7 @@
static const uint32_t primary_uuid[4] = PRIMARY_UUID;
static const uint32_t secondary_uuid[4] = SECONDARY_UUID;
+static const uint32_t tertiary_uuid[4] = TERTIARY_UUID;
static const uint32_t null_uuid[4] = {0};
struct feature_test {
@@ -116,15 +117,21 @@ static void ffa_partition_info_get_test(struct mailbox_buffers *mb)
const char *test_partition_info = "FFA Partition info interface";
const char *test_primary = "Get primary partition info";
const char *test_secondary = "Get secondary partition info";
+ const char *test_tertiary = "Get tertiary partition info";
const char *test_all = "Get all partitions info";
const struct ffa_partition_info expected_info[] = {
- {.id = SPM_VM_ID_FIRST, .exec_context = 8, .properties = 0}, /* Primary partition info */
- {.id = 2, .exec_context = 2, .properties = 0} /* Secondary partition info */
+ {.id = SPM_VM_ID_FIRST, .exec_context = 8U, .properties = 0U}, /* Primary partition info */
+ {.id = SPM_VM_ID_FIRST + 1U, .exec_context = 8U, .properties = 0U}, /* Secondary partition info */
+ {.id = SPM_VM_ID_FIRST + 2U, .exec_context = 8U, .properties = 0U} /* Tertiary partition info */
};
announce_test_section_start(test_partition_info);
+ announce_test_start(test_tertiary);
+ ffa_partition_info_helper(mb, tertiary_uuid, &expected_info[2], 1);
+ announce_test_end(test_tertiary);
+
announce_test_start(test_secondary);
ffa_partition_info_helper(mb, secondary_uuid, &expected_info[1], 1);
announce_test_end(test_secondary);
@@ -134,7 +141,7 @@ static void ffa_partition_info_get_test(struct mailbox_buffers *mb)
announce_test_end(test_primary);
announce_test_start(test_all);
- ffa_partition_info_helper(mb, null_uuid, expected_info, 2);
+ ffa_partition_info_helper(mb, null_uuid, expected_info, 3);
announce_test_end(test_all);
ffa_partition_info_wrong_test();
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 31906d5..0809716 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -50,18 +50,21 @@ static void __dead2 message_loop(ffa_vm_id_t vm_id)
for (;;) {
if (ffa_ret.ret0 != FFA_MSG_SEND_DIRECT_REQ_SMC32) {
- ffa_ret = ffa_error(-1);
- continue;
+ ERROR("%s(%u) unknown func id 0x%lx\n",
+ __func__, vm_id, ffa_ret.ret0);
+ break;
}
- if (ffa_ret.ret1 != SP_ID(vm_id)) {
- ffa_ret = ffa_error(-2);
- continue;
+ if (ffa_ret.ret1 != vm_id) {
+ ERROR("%s(%u) invalid vm id 0x%lx\n",
+ __func__, vm_id, ffa_ret.ret1);
+ break;
}
if (ffa_ret.ret2 != HYP_ID) {
- ffa_ret = ffa_error(-3);
- continue;
+ ERROR("%s(%u) invalid hyp id 0x%lx\n",
+ __func__, vm_id, ffa_ret.ret2);
+ break;
}
/*
@@ -74,9 +77,10 @@ static void __dead2 message_loop(ffa_vm_id_t vm_id)
* Send a response through direct messaging then block
* until receiving a new message request.
*/
- ffa_ret = ffa_msg_send_direct_resp(SP_ID(vm_id),
- HYP_ID, sp_response);
+ ffa_ret = ffa_msg_send_direct_resp(vm_id, HYP_ID, sp_response);
}
+
+ panic();
}
static const mmap_region_t cactus_mmap[] __attribute__((used)) = {
@@ -143,6 +147,13 @@ static void cactus_plat_configure_mmu(unsigned int vm_id)
init_xlat_tables();
}
+int tftf_irq_handler_dispatcher(void)
+{
+ ERROR("%s\n", __func__);
+
+ return 0;
+}
+
void __dead2 cactus_main(void)
{
assert(IS_IN_EL1() != 0);
@@ -176,17 +187,35 @@ void __dead2 cactus_main(void)
NOTICE("Booting Primary Cactus Secure Partition\n%s\n%s\n",
build_message, version_string);
-
- /* Get number of VMs */
- NOTICE("VM count: %u\n", spm_vm_get_count());
-
- /* Get virtual CPU count for current VM */
- NOTICE("vCPU count: %u\n", spm_vcpu_get_count(ffa_id));
} else {
set_putc_impl(HVC_CALL_AS_STDOUT);
- NOTICE("Booting Secondary Cactus Secure Partition\n%s\n%s\n",
- build_message, version_string);
+ NOTICE("Booting Secondary Cactus Secure Partition (ID: %u)\n%s\n%s\n",
+ ffa_id, build_message, version_string);
+
+ if (ffa_id == (SPM_VM_ID_FIRST + 2)) {
+ NOTICE("Mapping RXTX Region\n");
+
+ /* Declare RX/TX buffers at virtual FF-A instance */
+ static struct {
+ uint8_t rx[PAGE_SIZE];
+ uint8_t tx[PAGE_SIZE];
+ } __aligned(PAGE_SIZE) ffa_buffers;
+
+ /* Map RX/TX buffers */
+ smc_ret_values ret = ffa_rxtx_map((uintptr_t) &ffa_buffers.tx,
+ (uintptr_t) &ffa_buffers.rx,
+ sizeof(ffa_buffers.rx) / PAGE_SIZE);
+
+ if (ret.ret0 != FFA_SUCCESS_SMC32) {
+ ERROR("ffa_rxtx_map error (%lu)\n", ret.ret2);
+ panic();
+ }
+
+ /* Update mailbox with RX/TX buffer */
+ mb.send = (void *) &ffa_buffers.tx;
+ mb.recv = (void *) &ffa_buffers.rx;
+ }
}
NOTICE("FFA id: %u\n", ffa_id);
diff --git a/spm/cactus_mm/cactus_mm.mk b/spm/cactus_mm/cactus_mm.mk
index 6d69061..3156c1c 100644
--- a/spm/cactus_mm/cactus_mm.mk
+++ b/spm/cactus_mm/cactus_mm.mk
@@ -4,6 +4,8 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include branch_protection.mk
+
CACTUS_MM_INCLUDES := \
-Iinclude \
-Iinclude/common \
@@ -52,7 +54,11 @@ CACTUS_MM_DEFINES :=
# that is done.
CACTUS_MM_DEFINES += -DENABLE_ASSERTIONS=0
+$(eval $(call add_define,CACTUS_MM_DEFINES,ARM_ARCH_MAJOR))
+$(eval $(call add_define,CACTUS_MM_DEFINES,ARM_ARCH_MINOR))
$(eval $(call add_define,CACTUS_MM_DEFINES,DEBUG))
+$(eval $(call add_define,CACTUS_MM_DEFINES,ENABLE_BTI))
+$(eval $(call add_define,CACTUS_MM_DEFINES,ENABLE_PAUTH))
$(eval $(call add_define,CACTUS_MM_DEFINES,FVP_CLUSTER_COUNT))
$(eval $(call add_define,CACTUS_MM_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
$(eval $(call add_define,CACTUS_MM_DEFINES,FVP_MAX_PE_PER_CPU))
diff --git a/spm/common/sp_helpers.c b/spm/common/sp_helpers.c
index 7dc1648..1b650d3 100644
--- a/spm/common/sp_helpers.c
+++ b/spm/common/sp_helpers.c
@@ -75,22 +75,10 @@ void sp_sleep(uint32_t ms)
* Hypervisor Calls Wrappers
******************************************************************************/
-ffa_vcpu_count_t spm_vcpu_get_count(ffa_vm_id_t vm_id)
+ffa_int_id_t spm_interrupt_get(void)
{
hvc_args args = {
- .fid = SPM_VCPU_GET_COUNT,
- .arg1 = vm_id
- };
-
- hvc_ret_values ret = tftf_hvc(&args);
-
- return ret.ret0;
-}
-
-ffa_vm_count_t spm_vm_get_count(void)
-{
- hvc_args args = {
- .fid = SPM_VM_GET_COUNT
+ .fid = SPM_INTERRUPT_GET
};
hvc_ret_values ret = tftf_hvc(&args);
diff --git a/spm/common/sp_helpers.h b/spm/common/sp_helpers.h
index 2b9cc2e..ec92227 100644
--- a/spm/common/sp_helpers.h
+++ b/spm/common/sp_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,10 +11,10 @@
#include <tftf_lib.h>
#include <ffa_helpers.h>
-#define SPM_VM_ID_FIRST (1)
+#define SPM_VM_ID_FIRST SP_ID(1)
-#define SPM_VM_GET_COUNT (0xFF01)
-#define SPM_VCPU_GET_COUNT (0xFF02)
+/* Should match with IDs defined in SPM/Hafnium */
+#define SPM_INTERRUPT_GET (0xFF04)
#define SPM_DEBUG_LOG (0xBD000000)
typedef struct {
@@ -69,9 +69,7 @@ void sp_sleep(uint32_t ms);
* Hypervisor Calls Wrappers
*/
-ffa_vcpu_count_t spm_vcpu_get_count(ffa_vm_id_t vm_id);
-
-ffa_vm_count_t spm_vm_get_count(void);
+ffa_int_id_t spm_interrupt_get(void);
void spm_debug_log(char c);
diff --git a/spm/ivy/ivy.mk b/spm/ivy/ivy.mk
index afc89f4..a500049 100644
--- a/spm/ivy/ivy.mk
+++ b/spm/ivy/ivy.mk
@@ -4,6 +4,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include branch_protection.mk
include lib/sprt/sprt_client.mk
IVY_DTB := $(BUILD_PLAT)/ivy.dtb
@@ -50,8 +51,12 @@ IVY_LINKERFILE := spm/ivy/ivy.ld.S
IVY_DEFINES :=
+$(eval $(call add_define,IVY_DEFINES,ARM_ARCH_MAJOR))
+$(eval $(call add_define,IVY_DEFINES,ARM_ARCH_MINOR))
$(eval $(call add_define,IVY_DEFINES,DEBUG))
$(eval $(call add_define,IVY_DEFINES,ENABLE_ASSERTIONS))
+$(eval $(call add_define,IVY_DEFINES,ENABLE_BTI))
+$(eval $(call add_define,IVY_DEFINES,ENABLE_PAUTH))
$(eval $(call add_define,IVY_DEFINES,FVP_CLUSTER_COUNT))
$(eval $(call add_define,IVY_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
$(eval $(call add_define,IVY_DEFINES,FVP_MAX_PE_PER_CPU))
diff --git a/spm/quark/quark.mk b/spm/quark/quark.mk
index ec4a3ed..0fe1646 100644
--- a/spm/quark/quark.mk
+++ b/spm/quark/quark.mk
@@ -4,6 +4,7 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+include branch_protection.mk
include lib/sprt/sprt_client.mk
QUARK_DTB := $(BUILD_PLAT)/quark.dtb
@@ -47,8 +48,12 @@ QUARK_LINKERFILE := spm/quark/quark.ld.S
QUARK_DEFINES :=
+$(eval $(call add_define,QUARK_DEFINES,ARM_ARCH_MAJOR))
+$(eval $(call add_define,QUARK_DEFINES,ARM_ARCH_MINOR))
$(eval $(call add_define,QUARK_DEFINES,DEBUG))
$(eval $(call add_define,QUARK_DEFINES,ENABLE_ASSERTIONS))
+$(eval $(call add_define,QUARK_DEFINES,ENABLE_BTI))
+$(eval $(call add_define,QUARK_DEFINES,ENABLE_PAUTH))
$(eval $(call add_define,QUARK_DEFINES,FVP_CLUSTER_COUNT))
$(eval $(call add_define,QUARK_DEFINES,FVP_MAX_CPUS_PER_CLUSTER))
$(eval $(call add_define,QUARK_DEFINES,FVP_MAX_PE_PER_CPU))
diff --git a/tftf/tests/plat/nvidia/tegra194/include/tegra194_ras.h b/tftf/tests/plat/nvidia/tegra194/include/tegra194_ras.h
new file mode 100644
index 0000000..9bbd261
--- /dev/null
+++ b/tftf/tests/plat/nvidia/tegra194/include/tegra194_ras.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA194_RAS_H
+#define TEGRA194_RAS_H
+
+/* Error record information */
+struct err_record_info {
+ /* Opaque group-specific data */
+ void *aux_data;
+ struct {
+ /*
+ * For error records accessed via. system register, index of
+ * the error record.
+ */
+ unsigned int idx_start;
+ unsigned int num_idx;
+ } sysreg;
+};
+
+struct err_record_mapping {
+ struct err_record_info *err_records;
+ size_t num_err_records;
+};
+
+/* Implementation defined RAS error and corresponding error message */
+struct ras_error_rec {
+ const char *error_msg;
+ /* IERR(bits[15:8]) from ERR<n>STATUS */
+ uint8_t error_code;
+};
+
+/* RAS error node-specific auxiliary data */
+struct ras_aux_data {
+ /* point to null-terminated ras_error array to convert error code to msg. */
+ const struct ras_error_rec *error_records;
+ /* function to return a value which needs to be programmed into ERXCTLR_EL1
+ * to enable all specified RAS errors for current node.
+ */
+ uint64_t (*err_ctrl)(void);
+};
+
+/* Architecturally-defined primary error code SERR, bits[7:0] from ERR<n>STATUS */
+#define ERR_STATUS_SERR(X) \
+ /* SERR, message */ \
+ X(0, "No error") \
+ X(1, "IMPLEMENTATION DEFINED error") \
+ X(2, "Data value from (non-associative) internal memory") \
+ X(3, "IMPLEMENTATION DEFINED pin") \
+ X(4, "Assertion failure") \
+ X(5, "Error detected on internal data path") \
+ X(6, "Data value from associative memory") \
+ X(7, "Address/control value from associative memory") \
+ X(8, "Data value from a TLB") \
+ X(9, "Address/control value from a TLB") \
+ X(10, "Data value from producer") \
+ X(11, "Address/control value from producer") \
+ X(12, "Data value from (non-associative) external memory") \
+ X(13, "Illegal address (software fault)") \
+ X(14, "Illegal access (software fault)") \
+ X(15, "Illegal state (software fault)") \
+ X(16, "Internal data register") \
+ X(17, "Internal control register") \
+ X(18, "Error response from slave") \
+ X(19, "External timeout") \
+ X(20, "Internal timeout") \
+ X(21, "Deferred error from slave not supported at master")
+
+/* IFU Uncorrectable RAS ERROR */
+#define IFU_UNCORR_RAS_ERROR_LIST(X)
+
+/* JSR_RET Uncorrectable RAS ERROR */
+#define JSR_RET_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(JSR_RET, 35, 0x13, "Floating Point Register File Parity Error") \
+ X(JSR_RET, 34, 0x12, "Integer Register File Parity Error") \
+ X(JSR_RET, 33, 0x11, "Garbage Bundle") \
+ X(JSR_RET, 32, 0x10, "Bundle Completion Timeout")
+
+/* JSR_MTS Uncorrectable RAS ERROR */
+#define JSR_MTS_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(JSR_MTS, 40, 0x28, "CoreSight Access Error") \
+ X(JSR_MTS, 39, 0x27, "Dual Execution Uncorrectable Error") \
+ X(JSR_MTS, 37, 0x25, "CTU MMIO Region") \
+ X(JSR_MTS, 36, 0x24, "MTS MMCRAB Region Access") \
+ X(JSR_MTS, 35, 0x23, "MTS_CARVEOUT Access from ARM SW")
+
+/* LSD_STQ Uncorrectable RAS ERROR */
+#define LSD_STQ_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(LSD_STQ, 41, 0x39, "Coherent Cache Data Store Multi-Line ECC Error") \
+ X(LSD_STQ, 40, 0x38, "Coherent Cache Data Store Uncorrectable ECC Error") \
+ X(LSD_STQ, 38, 0x36, "Coherent Cache Data Load Uncorrectable ECC Error") \
+ X(LSD_STQ, 33, 0x31, "Coherent Cache Tag Store Parity Error") \
+ X(LSD_STQ, 32, 0x30, "Coherent Cache Tag Load Parity Error")
+
+/* LSD_DCC Uncorrectable RAS ERROR */
+#define LSD_DCC_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(LSD_DCC, 41, 0x49, "BTU Copy Mini-Cache PPN Multi-Hit Error") \
+ X(LSD_DCC, 39, 0x47, "Coherent Cache Data Uncorrectable ECC Error") \
+ X(LSD_DCC, 37, 0x45, "Version Cache Byte-Enable Parity Error") \
+ X(LSD_DCC, 36, 0x44, "Version Cache Data Uncorrectable ECC Error") \
+ X(LSD_DCC, 33, 0x41, "BTU Copy Coherent Cache PPN Parity Error") \
+ X(LSD_DCC, 32, 0x40, "BTU Copy Coherent Cache VPN Parity Error")
+
+/* LSD_L1HPF Uncorrectable RAS ERROR */
+#define LSD_L1HPF_UNCORR_RAS_ERROR_LIST(X)
+
+/* L2 Uncorrectable RAS ERROR */
+#define L2_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(L2, 56, 0x68, "URT Timeout") \
+ X(L2, 55, 0x67, "L2 Protocol Violation") \
+ X(L2, 54, 0x66, "SCF to L2 Slave Error Read") \
+ X(L2, 53, 0x65, "SCF to L2 Slave Error Write") \
+ X(L2, 52, 0x64, "SCF to L2 Decode Error Read") \
+ X(L2, 51, 0x63, "SCF to L2 Decode Error Write") \
+ X(L2, 50, 0x62, "SCF to L2 Request Response Interface Parity Errors") \
+ X(L2, 49, 0x61, "SCF to L2 Advance notice interface parity errors") \
+ X(L2, 48, 0x60, "SCF to L2 Filldata Parity Errors") \
+ X(L2, 47, 0x5F, "SCF to L2 UnCorrectable ECC Data Error on interface") \
+ X(L2, 45, 0x5D, "Core 1 to L2 Parity Error") \
+ X(L2, 44, 0x5C, "Core 0 to L2 Parity Error") \
+ X(L2, 43, 0x5B, "L2 Multi-Hit") \
+ X(L2, 42, 0x5A, "L2 URT Tag Parity Error") \
+ X(L2, 41, 0x59, "L2 NTT Tag Parity Error") \
+ X(L2, 40, 0x58, "L2 MLT Tag Parity Error") \
+ X(L2, 39, 0x57, "L2 URD Data") \
+ X(L2, 38, 0x56, "L2 NTP Data") \
+ X(L2, 36, 0x54, "L2 MLC Uncorrectable Clean") \
+ X(L2, 35, 0x53, "L2 URD Uncorrectable Dirty") \
+ X(L2, 34, 0x52, "L2 MLC Uncorrectable Dirty")
+
+/* CLUSTER_CLOCKS Uncorrectable RAS ERROR */
+#define CLUSTER_CLOCKS_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(CLUSTER_CLOCKS, 32, 0xE4, "Frequency Monitor Error")
+
+/* MMU Uncorrectable RAS ERROR */
+#define MMU_UNCORR_RAS_ERROR_LIST(X)
+
+/* L3 Uncorrectable RAS ERROR */
+#define L3_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(L3, 43, 0x7B, "SNOC Interface Parity Error") \
+ X(L3, 42, 0x7A, "MCF Interface Parity Error") \
+ X(L3, 41, 0x79, "L3 Tag Parity Error") \
+ X(L3, 40, 0x78, "L3 Dir Parity Error") \
+ X(L3, 39, 0x77, "L3 Uncorrectable ECC Error") \
+ X(L3, 37, 0x75, "Multi-Hit CAM Error") \
+ X(L3, 36, 0x74, "Multi-Hit Tag Error") \
+ X(L3, 35, 0x73, "Unrecognized Command Error") \
+ X(L3, 34, 0x72, "L3 Protocol Error")
+
+/* CCPMU Uncorrectable RAS ERROR */
+#define CCPMU_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(CCPMU, 33, 0x81, "CRAB Access Error")
+
+/* SCF_IOB Uncorrectable RAS ERROR */
+#define SCF_IOB_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(SCF_IOB, 41, 0x99, "Request parity error") \
+ X(SCF_IOB, 40, 0x98, "Putdata parity error") \
+ X(SCF_IOB, 39, 0x97, "Uncorrectable ECC on Putdata") \
+ X(SCF_IOB, 38, 0x96, "CBB Interface Error") \
+ X(SCF_IOB, 37, 0x95, "MMCRAB Error") \
+ X(SCF_IOB, 36, 0x94, "IHI Interface Error") \
+ X(SCF_IOB, 35, 0x93, "CRI Error") \
+ X(SCF_IOB, 34, 0x92, "TBX Interface Error") \
+ X(SCF_IOB, 33, 0x91, "EVP Interface Error")
+
+/* SCF_SNOC Uncorrectable RAS ERROR */
+#define SCF_SNOC_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(SCF_SNOC, 42, 0xAA, "Misc Client Parity Error") \
+ X(SCF_SNOC, 41, 0xA9, "Misc Filldata Parity Error") \
+ X(SCF_SNOC, 40, 0xA8, "Uncorrectable ECC Misc Client") \
+ X(SCF_SNOC, 39, 0xA7, "DVMU Interface Parity Error") \
+ X(SCF_SNOC, 38, 0xA6, "DVMU Interface Timeout Error") \
+ X(SCF_SNOC, 37, 0xA5, "CPE Request Error") \
+ X(SCF_SNOC, 36, 0xA4, "CPE Response Error") \
+ X(SCF_SNOC, 35, 0xA3, "CPE Timeout Error") \
+ X(SCF_SNOC, 34, 0xA2, "Uncorrectable Carveout Error")
+
+/* SCF_CTU Uncorrectable RAS ERROR */
+#define SCF_CTU_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(SCF_CTU, 39, 0xB7, "Timeout error for TRC_DMA request") \
+ X(SCF_CTU, 38, 0xB6, "Timeout error for CTU Snp") \
+ X(SCF_CTU, 37, 0xB5, "Parity error in CTU TAG RAM") \
+ X(SCF_CTU, 36, 0xB3, "Parity error in CTU DATA RAM") \
+ X(SCF_CTU, 35, 0xB4, "Parity error for Cluster Rsp") \
+ X(SCF_CTU, 34, 0xB2, "Parity error for TRL requests from 9 agents") \
+ X(SCF_CTU, 33, 0xB1, "Parity error for MCF request") \
+ X(SCF_CTU, 32, 0xB0, "TRC DMA fillsnoop parity error")
+
+/* CMU_CLOCKS Uncorrectable RAS ERROR */
+#define CMU_CLOCKS_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(CMU_CLOCKS, 39, 0xC7, "Cluster 3 frequency monitor error") \
+ X(CMU_CLOCKS, 38, 0xC6, "Cluster 2 frequency monitor error") \
+ X(CMU_CLOCKS, 37, 0xC5, "Cluster 1 frequency monitor error") \
+ X(CMU_CLOCKS, 36, 0xC3, "Cluster 0 frequency monitor error") \
+ X(CMU_CLOCKS, 35, 0xC4, "Voltage error on ADC1 Monitored Logic") \
+ X(CMU_CLOCKS, 34, 0xC2, "Voltage error on ADC0 Monitored Logic") \
+ X(CMU_CLOCKS, 33, 0xC1, "Lookup Table 1 Parity Error") \
+ X(CMU_CLOCKS, 32, 0xC0, "Lookup Table 0 Parity Error")
+
+/*
+ * Define one ras_error entry.
+ * This macro wille be used to to generate ras_error records for each node
+ * defined by <NODE_NAME>_UNCORR_RAS_ERROR_LIST macro.
+ */
+#define DEFINE_ONE_RAS_ERROR_MSG(unit, ras_bit, ierr, msg) \
+ { \
+ .error_msg = (msg), \
+ .error_code = (ierr) \
+ },
+
+/*
+ * Set one implementation defined bit in ERR<n>CTLR
+ * This macro will be used to collect all defined ERR_CTRL bits for each node
+ * defined by <NODE_NAME>_UNCORR_RAS_ERROR_LIST macro.
+ */
+#define DEFINE_ENABLE_RAS_BIT(unit, ras_bit, ierr, msg) \
+ do { \
+ val |= (1ULL << ras_bit##U); \
+ } while (0);
+
+/* Represent one RAS node with 0 or more error bits(ERR_CTLR) enabled */
+#define DEFINE_ONE_RAS_NODE(node) \
+static const struct ras_error_rec node##_uncorr_ras_errors[] = { \
+ node##_UNCORR_RAS_ERROR_LIST(DEFINE_ONE_RAS_ERROR_MSG) \
+ {NULL, 0U}, \
+}; \
+static inline uint64_t node##_err_ctrl(void) \
+{ \
+ uint64_t val = 0ULL; \
+ node##_UNCORR_RAS_ERROR_LIST(DEFINE_ENABLE_RAS_BIT) \
+ return val; \
+}
+
+#define DEFINE_ONE_RAS_AUX_DATA(node) \
+ { \
+ .error_records = node##_uncorr_ras_errors, \
+ .err_ctrl = &node##_err_ctrl \
+ },
+
+#define PER_CORE_RAS_NODE_LIST(X) \
+ X(IFU) \
+ X(JSR_RET) \
+ X(JSR_MTS) \
+ X(LSD_STQ) \
+ X(LSD_DCC) \
+ X(LSD_L1HPF)
+
+#define PER_CORE_RAS_GROUP_NODES PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#define PER_CLUSTER_RAS_NODE_LIST(X) \
+ X(L2) \
+ X(CLUSTER_CLOCKS) \
+ X(MMU)
+
+#define PER_CLUSTER_RAS_GROUP_NODES PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#define SCF_L3_BANK_RAS_NODE_LIST(X) X(L3)
+
+/* we have 4 SCF_L3 nodes:3*256 + L3_Bank_ID(0-3) */
+#define SCF_L3_BANK_RAS_GROUP_NODES \
+ SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) \
+ SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) \
+ SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) \
+ SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#define CCPLEX_RAS_NODE_LIST(X) \
+ X(CCPMU) \
+ X(SCF_IOB) \
+ X(SCF_SNOC) \
+ X(SCF_CTU) \
+ X(CMU_CLOCKS)
+
+#define CCPLEX_RAS_GROUP_NODES CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#endif /* TEGRA194_RAS_H */
diff --git a/tftf/tests/plat/nvidia/tegra194/serror_handler.S b/tftf/tests/plat/nvidia/tegra194/serror_handler.S
new file mode 100644
index 0000000..f040e5d
--- /dev/null
+++ b/tftf/tests/plat/nvidia/tegra194/serror_handler.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <sdei.h>
+
+ .globl serror_sdei_event_handler
+/*
+ * SDEI event handler for SErrors.
+ */
+func serror_sdei_event_handler
+ stp x29, x30, [sp, #-16]!
+ bl sdei_handler
+ ldp x29, x30, [sp], #16
+ mov_imm x0, SDEI_EVENT_COMPLETE
+ mov x1, xzr
+ smc #0
+ b .
+endfunc serror_sdei_event_handler
diff --git a/tftf/tests/plat/nvidia/tegra194/test_ras_corrected.c b/tftf/tests/plat/nvidia/tegra194/test_ras_corrected.c
new file mode 100644
index 0000000..a7be1a7
--- /dev/null
+++ b/tftf/tests/plat/nvidia/tegra194/test_ras_corrected.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <drivers/arm/arm_gic.h>
+#include <events.h>
+#include <lib/irq.h>
+#include <power_management.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+#include <platform.h>
+
+#include "include/tegra194_ras.h"
+
+/* Macro to indicate CPU to start an action */
+#define START U(0xAA55)
+
+/* Global flag to indicate that a fault was received */
+static volatile uint64_t irq_received;
+
+/* NVIDIA Pseudo fault generation registers */
+#define T194_ERXPFGCTL_EL1 S3_0_C15_C1_4
+#define T194_ERXPFGCDN_EL1 S3_0_C15_C1_6
+DEFINE_RENAME_SYSREG_RW_FUNCS(erxpfgctl_el1, T194_ERXPFGCTL_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(erxpfgcdn_el1, T194_ERXPFGCDN_EL1)
+
+/* Instantiate RAS nodes */
+PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE);
+PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE);
+SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE);
+CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE);
+
+/* Instantiate RAS node groups */
+static __unused struct ras_aux_data per_core_ras_group[] = {
+ PER_CORE_RAS_GROUP_NODES
+};
+
+static __unused struct ras_aux_data per_cluster_ras_group[] = {
+ PER_CLUSTER_RAS_GROUP_NODES
+};
+
+static __unused struct ras_aux_data scf_l3_ras_group[] = {
+ SCF_L3_BANK_RAS_GROUP_NODES
+};
+
+static __unused struct ras_aux_data ccplex_ras_group[] = {
+ CCPLEX_RAS_GROUP_NODES
+};
+
+/*
+ * we have same probe and handler for each error record group, use a macro to
+ * simply the record definition.
+ */
+#define ADD_ONE_ERR_GROUP(errselr_start, group) \
+ { \
+ .sysreg.idx_start = (errselr_start), \
+ .sysreg.num_idx = ARRAY_SIZE((group)), \
+ .aux_data = (group) \
+ }
+
+/* RAS error record group information */
+static struct err_record_info tegra194_ras_records[] = {
+ /*
+ * Per core ras error records
+ *
+ * ERRSELR starts from (0*256 + Logical_CPU_ID*16 + 0) to
+ * (0*256 + Logical_CPU_ID*16 + 5) for each group.
+ * 8 cores/groups, 6 * 8 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x000, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x010, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x020, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x030, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x040, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x050, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x060, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x070, per_core_ras_group),
+
+ /*
+ * Per cluster ras error records
+ *
+ * ERRSELR starts from 2*256 + Logical_Cluster_ID*16 + 0 to
+ * 2*256 + Logical_Cluster_ID*16 + 3.
+ * 4 clusters/groups, 3 * 4 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x200, per_cluster_ras_group),
+ ADD_ONE_ERR_GROUP(0x210, per_cluster_ras_group),
+ ADD_ONE_ERR_GROUP(0x220, per_cluster_ras_group),
+ ADD_ONE_ERR_GROUP(0x230, per_cluster_ras_group),
+
+ /*
+ * SCF L3_Bank ras error records
+ *
+ * ERRSELR: 3*256 + L3_Bank_ID, L3_Bank_ID: 0-3
+ * 1 groups, 4 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x300, scf_l3_ras_group),
+
+ /*
+ * CCPLEX ras error records
+ *
+ * ERRSELR: 4*256 + Unit_ID, Unit_ID: 0 - 4
+ * 1 groups, 5 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x400, ccplex_ras_group),
+};
+
+static void test_ras_inject_error(uint32_t errselr_el1, unsigned int errctlr_bit)
+{
+ uint64_t pfg_ctlr = BIT_64(errctlr_bit);
+
+ INFO("Injecting on 0x%lx:\n\terrctlr_el1=%d\n\terrselr_el1=0x%x\n\tpfg_ctlr=0x%llx\n",
+ read_mpidr_el1(), errctlr_bit, errselr_el1, pfg_ctlr);
+
+ /* clear the flag before we inject error */
+ irq_received = 0;
+ dccvac((uint64_t)&irq_received);
+ dmbish();
+
+ /* Choose error record */
+ write_errselr_el1(errselr_el1);
+
+ /* Program count down timer to 1 */
+ write_erxpfgcdn_el1(1);
+
+ /* Start count down to generate error on expiry */
+ write_erxpfgctl_el1(3 << 6 | ERXPFGCTL_CDEN_BIT | pfg_ctlr);
+ waitms(5);
+
+ /* Wait until IRQ fires */
+ do {
+ /*
+ * clean+invalidate cache lines before reading the global
+ * flag populated by another CPU
+ */
+ dccivac((uint64_t)&irq_received);
+ dmbish();
+ } while (irq_received == 0);
+
+ /* write 1-to-clear */
+ write_erxstatus_el1(read_erxstatus_el1() | (3 << 24));
+}
+
+static void generate_corrected_faults(void)
+{
+ unsigned int i;
+ unsigned int j;
+ unsigned int k;
+ unsigned int total = 0;
+
+ for (i = 0; i < ARRAY_SIZE(tegra194_ras_records); i++)
+ total += tegra194_ras_records[i].sysreg.num_idx;
+
+ VERBOSE("Total Nodes:%u\n", total);
+
+ for (i = 0; i < ARRAY_SIZE(tegra194_ras_records); i++) {
+
+ const struct err_record_info *info = &tegra194_ras_records[i];
+ uint32_t idx_start = info->sysreg.idx_start;
+ uint32_t num_idx = info->sysreg.num_idx;
+ const struct ras_aux_data *aux_data =
+ (const struct ras_aux_data *)info->aux_data;
+
+ /* No corrected errors for this node */
+ if (idx_start == 0x400) {
+ VERBOSE("0x%lx skipping errselr_el1=0x%x\n",
+ read_mpidr_el1(), idx_start);
+ continue;
+ }
+
+ for (j = 0; j < num_idx; j++) {
+ uint32_t errselr_el1 = idx_start + j;
+ uint64_t __unused err_fr;
+ uint64_t uncorr_errs, corr_errs;
+
+ /* Write to ERRSELR_EL1 to select the error record */
+ write_errselr_el1(errselr_el1);
+
+ /*
+ * all supported errors for this node exist in the
+ * top 32 bits
+ */
+ err_fr = read_erxfr_el1();
+ err_fr >>= 32;
+ err_fr <<= 32;
+
+ /*
+ * Mask the corrected errors that are disabled
+ * in the ERXFR register
+ */
+ uncorr_errs = aux_data[j].err_ctrl();
+ corr_errs = ~uncorr_errs & err_fr;
+
+ for (k = 32; k < 64; k++) {
+ /*
+ * JSR_MTS node, errctlr_bit = 32 or 34
+ * are uncorrected errors and should be
+ * skipped
+ */
+ if ((idx_start < 0x200) && ((errselr_el1 & 0xF) == 2) && (k == 32 || k == 34)) {
+ VERBOSE("0x%lx skipping errselr_el1=0x%x\n",
+ read_mpidr_el1(), errselr_el1);
+ continue;
+ }
+
+ if (corr_errs & BIT_64(k))
+ test_ras_inject_error(errselr_el1, k);
+ }
+ }
+ }
+}
+
+static int ce_irq_handler(void *data)
+{
+ unsigned int __unused irq_num = *(unsigned int *)data;
+
+ /* write 1-to-clear */
+ write_erxstatus_el1(read_erxstatus_el1() | (3 << 24));
+
+ irq_received = 1;
+
+ /*
+ * clean cache lines after writing the global flag so that
+ * latest value is visible to other CPUs
+ */
+ dccvac((uint64_t)&irq_received);
+ dsbish();
+
+ /* Return value doesn't matter */
+ return 0;
+}
+
+static event_t cpu_booted[PLATFORM_CORE_COUNT];
+static volatile uint64_t cpu_powerdown[PLATFORM_CORE_COUNT];
+static volatile uint64_t cpu_start_test[PLATFORM_CORE_COUNT];
+static volatile uint64_t cpu_test_completed[PLATFORM_CORE_COUNT];
+
+static test_result_t test_corrected_errors(void)
+{
+ unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos = platform_get_core_pos(mpid);
+
+ VERBOSE("Hello from core 0x%x\n", mpid);
+
+ /* Tell the lead CPU that the calling CPU has entered the test */
+ tftf_send_event(&cpu_booted[core_pos]);
+
+ /* Wait until lead CPU asks us to start the test */
+ do {
+ /*
+ * clean+invalidate cache lines before reading the global
+ * flag populated by another CPU
+ */
+ dccivac((uintptr_t)&cpu_start_test[core_pos]);
+ dmbish();
+ } while (!cpu_start_test[core_pos]);
+
+ generate_corrected_faults();
+
+ VERBOSE("0x%lx: test complete\n", read_mpidr_el1());
+
+ /* Inform lead CPU of test completion */
+ cpu_test_completed[core_pos] = true;
+ dccvac((uintptr_t)&cpu_test_completed[core_pos]);
+ dsbish();
+
+ /* Wait until lead CPU asks us to power down */
+ do {
+ /*
+ * clean+invalidate cache lines before reading the global
+ * flag populated by another CPU
+ */
+ dccivac((uintptr_t)&cpu_powerdown[core_pos]);
+ dmbish();
+ } while (!cpu_powerdown[core_pos]);
+
+ return TEST_RESULT_SUCCESS;
+}
+
+test_result_t test_ras_corrected(void)
+{
+ int64_t __unused ret = 0;
+ unsigned int cpu_node, cpu_mpid;
+ unsigned int lead_mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos;
+
+ tftf_testcase_printf("Tegra194 corrected RAS error verification\n");
+
+ /* long execution test; reset watchdog */
+ tftf_platform_watchdog_reset();
+
+ /* register IRQ handler */
+ for (uint32_t irq = 424; irq <= 431; irq++) {
+
+ ret = tftf_irq_register_handler(irq, ce_irq_handler);
+ if (ret < 0)
+ return TEST_RESULT_FAIL;
+
+ /* enable the IRQ */
+ tftf_irq_enable(irq, GIC_HIGHEST_NS_PRIORITY);
+ }
+
+ /* Power on all CPUs */
+ for_each_cpu(cpu_node) {
+
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /* Skip lead CPU, it is already powered on */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ ret = tftf_cpu_on(cpu_mpid,
+ (uintptr_t) test_corrected_errors,
+ 0);
+ if (ret != PSCI_E_SUCCESS)
+ return TEST_RESULT_FAIL;
+ }
+
+ /*
+ * The lead CPU needs to wait for all other CPUs to enter the test.
+ * This is because the test framework declares the end of a test when no
+ * CPU is in the test. Therefore, if the lead CPU goes ahead and exits
+ * the test then potentially there could be no CPU executing the test at
+ * this time because none of them have entered the test yet, hence the
+ * framework will be misled in thinking the test is finished.
+ */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /* Skip lead CPU */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ core_pos = platform_get_core_pos(cpu_mpid);
+ tftf_wait_for_event(&cpu_booted[core_pos]);
+ }
+
+ /* Ask all CPUs to start the test */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /*
+ * Except lead CPU, Wait for all cores to be powered off
+ * by framework
+ */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ /* Allow the CPU to start the test */
+ core_pos = platform_get_core_pos(cpu_mpid);
+ cpu_start_test[core_pos] = START;
+
+ /*
+ * clean cache lines after writing the global flag so that
+ * latest value is visible to other CPUs
+ */
+ dccvac((uintptr_t)&cpu_start_test[core_pos]);
+ dsbish();
+
+ /* Wait for the CPU to complete the test */
+ do {
+ /*
+ * clean+invalidate cache lines before reading the global
+ * flag populated by another CPU
+ */
+ dccivac((uintptr_t)&cpu_test_completed[core_pos]);
+ dmbish();
+ } while (!cpu_test_completed[core_pos]);
+ }
+
+ /* run through all supported corrected faults */
+ generate_corrected_faults();
+
+ /* Wait for all CPUs to power off */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /*
+ * Except lead CPU, Wait for all cores to be powered off
+ * by framework
+ */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ /* Allow other CPUs to power down */
+ core_pos = platform_get_core_pos(cpu_mpid);
+ cpu_powerdown[core_pos] = START;
+
+ /*
+ * clean cache lines after writing the global flag so that
+ * latest value is visible to other CPUs
+ */
+ dccvac((uintptr_t)&cpu_powerdown[core_pos]);
+ dsbish();
+
+ /* Wait for the CPU to actually power off */
+ while (tftf_psci_affinity_info(cpu_mpid, MPIDR_AFFLVL0) != PSCI_STATE_OFF)
+ dsbsy();
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/plat/nvidia/tegra194/test_ras_uncorrectable.c b/tftf/tests/plat/nvidia/tegra194/test_ras_uncorrectable.c
new file mode 100644
index 0000000..b52a35c
--- /dev/null
+++ b/tftf/tests/plat/nvidia/tegra194/test_ras_uncorrectable.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <events.h>
+#include <lib/irq.h>
+#include <power_management.h>
+#include <sdei.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+#include <platform.h>
+
+#include "include/tegra194_ras.h"
+
+/* Macro to indicate CPU to start an action */
+#define START U(0xAA55)
+
+/* Global flag to indicate that a fault was received */
+static volatile uint64_t fault_received;
+
+/* SDEI handler to receive RAS UC errors */
+extern int serror_sdei_event_handler(int ev, uint64_t arg);
+
+/* NVIDIA Pseudo fault generation registers */
+#define T194_ERXPFGCTL_EL1 S3_0_C15_C1_4
+#define T194_ERXPFGCDN_EL1 S3_0_C15_C1_6
+DEFINE_RENAME_SYSREG_RW_FUNCS(erxpfgctl_el1, T194_ERXPFGCTL_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(erxpfgcdn_el1, T194_ERXPFGCDN_EL1)
+
+/* Instantiate RAS nodes */
+PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE);
+PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE);
+SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE);
+CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE);
+
+/* Instantiate RAS node groups */
+static __unused struct ras_aux_data per_core_ras_group[] = {
+ PER_CORE_RAS_GROUP_NODES
+};
+
+static __unused struct ras_aux_data per_cluster_ras_group[] = {
+ PER_CLUSTER_RAS_GROUP_NODES
+};
+
+static __unused struct ras_aux_data scf_l3_ras_group[] = {
+ SCF_L3_BANK_RAS_GROUP_NODES
+};
+
+static __unused struct ras_aux_data ccplex_ras_group[] = {
+ CCPLEX_RAS_GROUP_NODES
+};
+
+/*
+ * we have same probe and handler for each error record group, use a macro to
+ * simply the record definition.
+ */
+#define ADD_ONE_ERR_GROUP(errselr_start, group) \
+ { \
+ .sysreg.idx_start = (errselr_start), \
+ .sysreg.num_idx = ARRAY_SIZE((group)), \
+ .aux_data = (group) \
+ }
+
+/* RAS error record group information */
+static struct err_record_info tegra194_ras_records[] = {
+ /*
+ * Per core RAS error records
+ *
+ * ERRSELR starts from (0*256 + Logical_CPU_ID*16 + 0) to
+ * (0*256 + Logical_CPU_ID*16 + 5) for each group.
+ * 8 cores/groups, 6 * 8 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x000, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x010, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x020, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x030, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x040, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x050, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x060, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x070, per_core_ras_group),
+
+ /*
+ * Per cluster ras error records
+ *
+ * ERRSELR starts from 2*256 + Logical_Cluster_ID*16 + 0 to
+ * 2*256 + Logical_Cluster_ID*16 + 3.
+ * 4 clusters/groups, 3 * 4 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x200, per_cluster_ras_group),
+ ADD_ONE_ERR_GROUP(0x210, per_cluster_ras_group),
+ ADD_ONE_ERR_GROUP(0x220, per_cluster_ras_group),
+ ADD_ONE_ERR_GROUP(0x230, per_cluster_ras_group),
+
+ /*
+ * SCF L3_Bank ras error records
+ *
+ * ERRSELR: 3*256 + L3_Bank_ID, L3_Bank_ID: 0-3
+ * 1 groups, 4 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x300, scf_l3_ras_group),
+
+ /*
+ * CCPLEX ras error records
+ *
+ * ERRSELR: 4*256 + Unit_ID, Unit_ID: 0 - 4
+ * 1 groups, 5 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x400, ccplex_ras_group),
+};
+
+static void test_ras_inject_serror(uint32_t errselr_el1, uint64_t pfg_ctlr)
+{
+ unsigned int core_pos = platform_get_core_pos(read_mpidr_el1() & MPID_MASK);
+
+ /*
+ * The per-cluster frequency monitoring nodes should be accessed from
+ * CPUs in the cluster that the node belongs to. e.g. nodes 0x200 and
+ * 0x201 should be accessed from CPUs in cluster 0, nodes 0x210 and
+ * 0x211 should be accessed from CPUs in cluster 1 and so on.
+ */
+ if (((errselr_el1 & 0xF00) == 0x200) && ((errselr_el1 >> 4) & 0xF) != (core_pos >> 1)) {
+ return;
+ }
+
+ /* clear the flag before we inject SError */
+ fault_received = 0;
+ dccvac((uint64_t)&fault_received);
+ dmbish();
+
+ INFO("mpidr=0x%lx, errselr_el1=0x%x, pfg_ctlr=0x%llx\n",
+ read_mpidr_el1(), errselr_el1, pfg_ctlr);
+
+ /* Choose error record */
+ write_errselr_el1(errselr_el1);
+
+ /* Program count down timer to 1 */
+ write_erxpfgcdn_el1(1);
+
+ /* Start count down to generate error on expiry */
+ write_erxpfgctl_el1(ERXPFGCTL_UC_BIT | ERXPFGCTL_CDEN_BIT | pfg_ctlr);
+
+ /* wait until the SError fires */
+ do {
+ dccivac((uint64_t)&fault_received);
+ dmbish();
+ } while (fault_received == 0);
+
+ /*
+ * ACLR_EL1, Bit13 = RESET_RAS_FMON
+ *
+ * A write of 1 to this write-only bit re-enables checking for RAS
+ * frequency monitoring errors which are temporarily disabled when
+ * detected.
+ */
+ if (((errselr_el1 & 0xF00) == 0x200) && ((errselr_el1 >> 4) & 0xF) == (core_pos >> 1))
+ write_actlr_el1(read_actlr_el1() | BIT_32(13));
+ else if ((errselr_el1 == 0x404))
+ write_actlr_el1(read_actlr_el1() | BIT_32(13));
+}
+
+static void generate_uncorrectable_faults(void)
+{
+ unsigned int i;
+ unsigned int j;
+ unsigned int k;
+ unsigned int total = 0;
+
+ for (i = 0; i < ARRAY_SIZE(tegra194_ras_records); i++)
+ total += tegra194_ras_records[i].sysreg.num_idx;
+
+ VERBOSE("Total Nodes:%u\n", total);
+
+ for (i = 0; i < ARRAY_SIZE(tegra194_ras_records); i++) {
+
+ const struct err_record_info *info = &tegra194_ras_records[i];
+ uint32_t idx_start = info->sysreg.idx_start;
+ uint32_t num_idx = info->sysreg.num_idx;
+ const struct ras_aux_data *aux_data =
+ (const struct ras_aux_data *)info->aux_data;
+
+ for (j = 0; j < num_idx; j++) {
+ uint32_t errselr_el1 = idx_start + j;
+ uint64_t __unused err_fr;
+ uint64_t uncorr_errs;
+
+ /* Write to ERRSELR_EL1 to select the error record */
+ write_errselr_el1(errselr_el1);
+
+ /*
+ * all supported errors for this node exist in the
+ * top 32 bits
+ */
+ err_fr = read_erxfr_el1();
+ err_fr >>= 32;
+ err_fr <<= 32;
+
+ /*
+ * Mask the uncorrectable errors that are disabled
+ * in the ERXFR register
+ */
+ uncorr_errs = aux_data[j].err_ctrl();
+ uncorr_errs &= err_fr;
+
+ for (k = 32; k < 64; k++) {
+ if (uncorr_errs & BIT_64(k)) {
+ VERBOSE("ERR<x>CTLR bit%d\n", k);
+ test_ras_inject_serror(errselr_el1, BIT_64(k));
+ }
+ }
+ }
+ }
+}
+
+int __unused sdei_handler(int ev, uint64_t arg)
+{
+ fault_received = 1;
+ dccvac((uint64_t)&fault_received);
+ dsbish();
+ VERBOSE("SError SDEI event received.\n");
+ return 0;
+}
+
+static event_t cpu_booted[PLATFORM_CORE_COUNT];
+static volatile uint64_t cpu_powerdown[PLATFORM_CORE_COUNT];
+static volatile uint64_t cpu_start_test[PLATFORM_CORE_COUNT];
+static volatile uint64_t cpu_test_completed[PLATFORM_CORE_COUNT];
+
+static void sdei_register_for_event(int event_id)
+{
+ int64_t ret = 0;
+
+ /* Register SDEI handler */
+ ret = sdei_event_register(event_id, serror_sdei_event_handler, 0,
+ SDEI_REGF_RM_PE, read_mpidr_el1());
+ if (ret < 0)
+ tftf_testcase_printf("SDEI event register failed: 0x%llx\n",
+ ret);
+
+ ret = sdei_event_enable(event_id);
+ if (ret < 0)
+ tftf_testcase_printf("SDEI event enable failed: 0x%llx\n", ret);
+
+ ret = sdei_pe_unmask();
+ if (ret < 0)
+ tftf_testcase_printf("SDEI pe unmask failed: 0x%llx\n", ret);
+}
+
+static test_result_t test_cpu_serrors(void)
+{
+ unsigned int mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos = platform_get_core_pos(mpid);
+
+ VERBOSE("Hello from core 0x%x\n", mpid);
+
+ /* register for the SDEI event ID */
+ sdei_register_for_event(300 + core_pos);
+
+ /* Tell the lead CPU that the calling CPU has entered the test */
+ tftf_send_event(&cpu_booted[core_pos]);
+
+ /* Wait until lead CPU asks us to start the test */
+ do {
+ dccivac((uintptr_t)&cpu_start_test[core_pos]);
+ dmbish();
+ } while (!cpu_start_test[core_pos]);
+
+ generate_uncorrectable_faults();
+
+ VERBOSE("0x%lx: test complete\n", read_mpidr_el1());
+
+ /* Inform lead CPU of test completion */
+ cpu_test_completed[core_pos] = true;
+ dccvac((uintptr_t)&cpu_test_completed[core_pos]);
+ dsbish();
+
+ /* Wait until lead CPU asks us to power down */
+ do {
+ dccivac((uintptr_t)&cpu_powerdown[core_pos]);
+ dmbish();
+ } while (!cpu_powerdown[core_pos]);
+
+ return TEST_RESULT_SUCCESS;
+}
+
+test_result_t test_ras_uncorrectable(void)
+{
+ const int __unused event_id = 300;
+ int64_t __unused ret = 0;
+ unsigned int cpu_node, cpu_mpid;
+ unsigned int lead_mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos;
+
+ tftf_testcase_printf("Tegra194 uncorrectable RAS errors.\n");
+
+ /* long execution test; reset watchdog */
+ tftf_platform_watchdog_reset();
+
+ /* Power on all CPUs */
+ for_each_cpu(cpu_node) {
+
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /* Skip lead CPU, it is already powered on */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ ret = tftf_cpu_on(cpu_mpid,
+ (uintptr_t) test_cpu_serrors,
+ 0);
+ if (ret != PSCI_E_SUCCESS)
+ ret = TEST_RESULT_FAIL;
+ }
+
+ /*
+ * The lead CPU needs to wait for all other CPUs to enter the test.
+ * This is because the test framework declares the end of a test when no
+ * CPU is in the test. Therefore, if the lead CPU goes ahead and exits
+ * the test then potentially there could be no CPU executing the test at
+ * this time because none of them have entered the test yet, hence the
+ * framework will be misled in thinking the test is finished.
+ */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /* Skip lead CPU */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ core_pos = platform_get_core_pos(cpu_mpid);
+ tftf_wait_for_event(&cpu_booted[core_pos]);
+ }
+
+ /* register for the SDEI event ID */
+ sdei_register_for_event(300);
+
+ /* Ask all CPUs to start the test */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /*
+ * Except lead CPU, Wait for all cores to be powered off
+ * by framework
+ */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ /* Allow the CPU to start the test */
+ core_pos = platform_get_core_pos(cpu_mpid);
+ cpu_start_test[core_pos] = START;
+ dccvac((uintptr_t)&cpu_start_test[core_pos]);
+ dsbish();
+
+ /* Wait for the CPU to complete the test */
+ do {
+ dccivac((uintptr_t)&cpu_test_completed[core_pos]);
+ dmbish();
+ } while (!cpu_test_completed[core_pos]);
+ }
+
+ /* run through all supported uncorrectable faults */
+ generate_uncorrectable_faults();
+
+ VERBOSE("0x%lx: test complete\n", read_mpidr_el1());
+
+ /* Wait for all CPUs to power off */
+ for_each_cpu(cpu_node) {
+ cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
+ /*
+ * Except lead CPU, Wait for all cores to be powered off
+ * by framework
+ */
+ if (cpu_mpid == lead_mpid)
+ continue;
+
+ /* Allow other CPUs to start power down sequence */
+ core_pos = platform_get_core_pos(cpu_mpid);
+ cpu_powerdown[core_pos] = START;
+ dccvac((uintptr_t)&cpu_powerdown[core_pos]);
+ dsbish();
+
+ /* Wait for the CPU to actually power off */
+ while (tftf_psci_affinity_info(cpu_mpid, MPIDR_AFFLVL0) != PSCI_STATE_OFF)
+ dsbsy();
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index c90cac8..bda47c9 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -134,7 +134,7 @@ bool check_spmc_execution_level(void)
*
*/
ret_values = ffa_msg_send_direct_req(HYP_ID, SP_ID(1),
- OPTEE_FFA_GET_API_VERSION);
+ OPTEE_FFA_GET_API_VERSION);
if ((ret_values.ret3 == FFA_VERSION_MAJOR) &&
(ret_values.ret4 == FFA_VERSION_MINOR)) {
is_optee_spmc_criteria++;
@@ -146,7 +146,7 @@ bool check_spmc_execution_level(void)
*
*/
ret_values = ffa_msg_send_direct_req(HYP_ID, SP_ID(1),
- OPTEE_FFA_GET_OS_VERSION);
+ OPTEE_FFA_GET_OS_VERSION);
if ((ret_values.ret3 == OPTEE_FFA_GET_OS_VERSION_MAJOR) &&
(ret_values.ret4 == OPTEE_FFA_GET_OS_VERSION_MINOR)) {
is_optee_spmc_criteria++;
@@ -247,3 +247,16 @@ smc_ret_values ffa_rx_release(void)
return tftf_smc(&args);
}
+
+/* Map the RXTX buffer */
+smc_ret_values ffa_rxtx_map(uintptr_t send, uintptr_t recv, uint32_t pages)
+{
+ smc_args args = {
+ .fid = FFA_RXTX_MAP_SMC64,
+ .arg1 = send,
+ .arg2 = recv,
+ .arg3 = pages
+ };
+
+ return tftf_smc(&args);
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
index 6008b78..d00793a 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
@@ -22,8 +22,7 @@ static test_result_t send_receive_direct_msg(unsigned int sp_id,
smc_ret_values ret_values;
/* Send a message to SP through direct messaging */
- ret_values = ffa_msg_send_direct_req(HYP_ID, SP_ID(sp_id),
- test_pattern);
+ ret_values = ffa_msg_send_direct_req(HYP_ID, sp_id, test_pattern);
/*
* Return responses may be FFA_MSG_SEND_DIRECT_RESP or FFA_INTERRUPT,
@@ -70,7 +69,7 @@ test_result_t test_ffa_direct_messaging(void)
/**********************************************************************
* Send a message to SP1 through direct messaging
**********************************************************************/
- result = send_receive_direct_msg(1, DIRECT_MSG_TEST_PATTERN1);
+ result = send_receive_direct_msg(SP_ID(1), DIRECT_MSG_TEST_PATTERN1);
if (result != TEST_RESULT_SUCCESS) {
return result;
}
@@ -78,7 +77,7 @@ test_result_t test_ffa_direct_messaging(void)
/**********************************************************************
* Send a message to SP2 through direct messaging
**********************************************************************/
- result = send_receive_direct_msg(2, DIRECT_MSG_TEST_PATTERN2);
+ result = send_receive_direct_msg(SP_ID(2), DIRECT_MSG_TEST_PATTERN2);
if (result != TEST_RESULT_SUCCESS) {
return result;
}
@@ -86,13 +85,7 @@ test_result_t test_ffa_direct_messaging(void)
/**********************************************************************
* Send a message to SP1 through direct messaging
**********************************************************************/
- result = send_receive_direct_msg(1, DIRECT_MSG_TEST_PATTERN3);
- if (result != TEST_RESULT_SUCCESS) {
- return result;
- }
+ result = send_receive_direct_msg(SP_ID(1), DIRECT_MSG_TEST_PATTERN3);
- /**********************************************************************
- * All tests passed.
- **********************************************************************/
- return TEST_RESULT_SUCCESS;
+ return result;
}
diff --git a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c
index 16ed371..eae5ccd 100644
--- a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c
+++ b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c
@@ -22,7 +22,8 @@
#define TEST_SPURIOUS_ITERATIONS_COUNT 1000000
-#define TEST_SPI_ID (MIN_SPI_ID + 2)
+#define TEST_SPI_ID (MIN_SPI_ID + 2)
+#define CPU_TARGET_FIELD ((1 << PLATFORM_CORE_COUNT) - 1)
static event_t cpu_ready[PLATFORM_CORE_COUNT];
static volatile int requested_irq_received[PLATFORM_CORE_COUNT];
@@ -47,7 +48,8 @@ static int test_handler(void *data)
/* Dummy handler that increases a variable to check if it has been called. */
static int test_spurious_handler(void *data)
{
- unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
+ u_register_t core_mpid = read_mpidr_el1() & MPID_MASK;
+ unsigned int core_pos = platform_get_core_pos(core_mpid);
spurious_count[core_pos]++;
@@ -194,6 +196,7 @@ test_result_t test_multicore_spurious_interrupt(void)
test_finished_flag = 1;
return TEST_RESULT_SKIPPED;
}
+ mp_printf("CPU 0x%x powered on\n", (unsigned int)cpu_mpid);
}
/* Wait for non-lead CPUs to enter the test */
@@ -226,7 +229,7 @@ test_result_t test_multicore_spurious_interrupt(void)
tftf_irq_enable(TEST_SPI_ID, GIC_HIGHEST_NS_PRIORITY);
/* Route interrupts to all CPUs */
- gicv2_set_itargetsr_value(TEST_SPI_ID, 0xFF);
+ gicv2_set_itargetsr_value(TEST_SPI_ID, CPU_TARGET_FIELD);
for (j = 0; j < TEST_SPURIOUS_ITERATIONS_COUNT; j++) {
diff --git a/tftf/tests/tests-tegra194.mk b/tftf/tests/tests-tegra194.mk
new file mode 100644
index 0000000..890c840
--- /dev/null
+++ b/tftf/tests/tests-tegra194.mk
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES += $(addprefix tftf/tests/plat/nvidia/tegra194/, \
+ test_ras_corrected.c \
+ test_ras_uncorrectable.c \
+ serror_handler.S \
+)
diff --git a/tftf/tests/tests-tegra194.xml b/tftf/tests/tests-tegra194.xml
new file mode 100644
index 0000000..49f6f9e
--- /dev/null
+++ b/tftf/tests/tests-tegra194.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+ <testsuite name="Tegra194 platform tests" description="Tests for Tegra194 platforms">
+ <testcase name="RAS corrected error test" function="test_ras_corrected" />
+ <testcase name="RAS uncorrectable error test" function="test_ras_uncorrectable" />
+ </testsuite>
+
+</testsuites>
diff --git a/tools/generate_json/generate_json.sh b/tools/generate_json/generate_json.sh
index 8dd2630..449733c 100755
--- a/tools/generate_json/generate_json.sh
+++ b/tools/generate_json/generate_json.sh
@@ -17,14 +17,19 @@
GENERATED_JSON=build/$2/$3/sp_layout.json
# To demonstrate communication between SP's, two cactus S-EL1 instances used.
-# cactus-primary and cactus-secondary has same binary but different
-# partition manifest.
+# To also test mapping of the RXTX region a third cactus S-EL1 instance is used.
+# cactus-primary, cactus-secondary and cactus-tertiary have same binary but
+# different partition manifests.
if [ "$1" == "cactus" ]; then
echo -e "{\n\t\"$1-primary\" : {\n \
\t\"image\": \"$1.bin\",\n \
- \t\"pm\": \"../../../spm/$1/$1.dts\"\n\t},\n\n\t\"$1-secondary\" : {\n \
+ \t\"pm\": \"../../../spm/$1/$1.dts\",\n \
+ \t\"owner\": \"SiP\"\n\t},\n\n\t\"$1-secondary\" : {\n \
\t\"image\": \"$1.bin\",\n \
- \t\"pm\": \"../../../spm/$1/$1-secondary.dts\" \n \
+ \t\"pm\": \"../../../spm/$1/$1-secondary.dts\",\n \
+ \t\"owner\": \"Plat\"\n\t},\n\n\t\"$1-tertiary\" : {\n \
+ \t\"image\": \"$1.bin\",\n \
+ \t\"pm\": \"../../../spm/$1/$1-tertiary.dts\" \n \
}\n}" \
> "$GENERATED_JSON"
else