Merge "feat(libc): add printf support for space padding" into integration
diff --git a/Makefile b/Makefile
index 81143e4..a107785 100644
--- a/Makefile
+++ b/Makefile
@@ -308,6 +308,10 @@
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523
TF_CFLAGS += $(call cc_option, --param=min-pagesize=0)
+ifeq ($(HARDEN_SLS), 1)
+ TF_CFLAGS_aarch64 += $(call cc_option, -mharden-sls=all)
+endif
+
else
# using clang
WARNINGS += -Wshift-overflow -Wshift-sign-overflow \
@@ -1185,6 +1189,7 @@
GENERATE_COT \
GICV2_G0_FOR_EL3 \
HANDLE_EA_EL3_FIRST_NS \
+ HARDEN_SLS \
HW_ASSISTED_COHERENCY \
MEASURED_BOOT \
DRTM_SUPPORT \
diff --git a/changelog.yaml b/changelog.yaml
index 1467ab4..c5e157d 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -569,6 +569,9 @@
- rockchip/rk3399
- rk3399/suspend
+ - title: RK3328
+ scope: rk3328
+
- title: Socionext
scope: socionext
diff --git a/docs/design/auth-framework.rst b/docs/design/auth-framework.rst
index 597f955..281f35f 100644
--- a/docs/design/auth-framework.rst
+++ b/docs/design/auth-framework.rst
@@ -254,8 +254,8 @@
REGISTER_CRYPTO_LIB(_name,
_init,
_verify_signature,
- _calc_hash,
_verify_hash,
+ _calc_hash,
_auth_decrypt,
_convert_pk);
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 8782f18..091456d 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -536,6 +536,14 @@
CPU. This needs to be enabled for revisions r0p0, r0p1 and r0p2. It is still
open.
+- ``ERRATA_V2_2618597``: This applies errata 2618597 workaround to Neoverse-V2
+ CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in
+ r0p2.
+
+- ``ERRATA_V2_2662553``: This applies errata 2662553 workaround to Neoverse-V2
+ CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in
+ r0p2.
+
- ``ERRATA_V2_2719103``: This applies errata 2719103 workaround to Neoverse-V2
CPU, this affects system configurations that do not use and ARM interconnect
IP. This needs to be enabled for revisions r0p0 and r0p1. It has been fixed
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 599aed9..7ca0300 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -671,6 +671,19 @@
MARCH_DIRECTIVE := -march=armv8.5-a
+- ``HARDEN_SLS``: used to pass -mharden-sls=all from the TF-A build
+ options to the compiler currently supporting only of the options.
+ GCC documentation:
+ https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html#index-mharden-sls
+
+ An example usage:
+
+ .. code:: make
+
+ HARDEN_SLS := 1
+
+ This option defaults to 0.
+
- ``NON_TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It
specifies a file that contains the Non-Trusted World private key in PEM
format or a PKCS11 URI. If ``SAVE_KEYS=1``, only a file is accepted and it
diff --git a/include/lib/cpus/aarch64/neoverse_v2.h b/include/lib/cpus/aarch64/neoverse_v2.h
index 68c1558..39a6607 100644
--- a/include/lib/cpus/aarch64/neoverse_v2.h
+++ b/include/lib/cpus/aarch64/neoverse_v2.h
@@ -22,6 +22,10 @@
******************************************************************************/
#define NEOVERSE_V2_CPUPWRCTLR_EL1 S3_0_C15_C2_7
#define NEOVERSE_V2_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1)
+#define NEOVERSE_V2_CPUPWRCTLR_EL1_WFI_RET_CTRL_SHIFT U(4)
+#define NEOVERSE_V2_CPUPWRCTLR_EL1_WFI_RET_CTRL_WIDTH U(3)
+#define NEOVERSE_V2_CPUPWRCTLR_EL1_WFE_RET_CTRL_SHIFT U(7)
+#define NEOVERSE_V2_CPUPWRCTLR_EL1_WFE_RET_CTRL_WIDTH U(3)
/*******************************************************************************
* CPU Extended Control register 2 specific definitions.
@@ -30,6 +34,9 @@
#define NEOVERSE_V2_CPUECTLR2_EL1_PF_MODE_CNSRV ULL(9)
#define NEOVERSE_V2_CPUECTLR2_EL1_PF_MODE_LSB U(11)
#define NEOVERSE_V2_CPUECTLR2_EL1_PF_MODE_WIDTH U(4)
+#define NEOVERSE_V2_CPUECTLR2_EL1_TXREQ_STATIC_FULL ULL(0)
+#define NEOVERSE_V2_CPUECTLR2_EL1_TXREQ_LSB U(0)
+#define NEOVERSE_V2_CPUECTLR2_EL1_TXREQ_WIDTH U(3)
/*******************************************************************************
* CPU Auxiliary Control register 2 specific definitions.
diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h
index de56638..c3a3a7c 100644
--- a/include/services/ffa_svc.h
+++ b/include/services/ffa_svc.h
@@ -117,6 +117,8 @@
#define FFA_FNUM_SPM_ID_GET U(0x85)
#define FFA_FNUM_MSG_SEND2 U(0x86)
#define FFA_FNUM_SECONDARY_EP_REGISTER U(0x87)
+#define FFA_FNUM_MEM_PERM_GET U(0x88)
+#define FFA_FNUM_MEM_PERM_SET U(0x89)
#define FFA_FNUM_PARTITION_INFO_GET_REGS U(0x8B)
#define FFA_FNUM_EL3_INTR_HANDLE U(0x8C)
@@ -165,6 +167,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)
/* FFA SMC64 FIDs */
#define FFA_ERROR_SMC64 FFA_FID(SMC_64, FFA_FNUM_ERROR)
diff --git a/lib/cpus/aarch64/neoverse_v2.S b/lib/cpus/aarch64/neoverse_v2.S
index bfd088d..d4b3a96 100644
--- a/lib/cpus/aarch64/neoverse_v2.S
+++ b/lib/cpus/aarch64/neoverse_v2.S
@@ -29,6 +29,25 @@
check_erratum_ls neoverse_v2, ERRATUM(2331132), CPU_REV(0, 2)
+workaround_reset_start neoverse_v2, ERRATUM(2618597), ERRATA_V2_2618597
+ /* Disable retention control for WFI and WFE. */
+ mrs x0, NEOVERSE_V2_CPUPWRCTLR_EL1
+ bfi x0, xzr, #NEOVERSE_V2_CPUPWRCTLR_EL1_WFI_RET_CTRL_SHIFT, \
+ #NEOVERSE_V2_CPUPWRCTLR_EL1_WFI_RET_CTRL_WIDTH
+ bfi x0, xzr, #NEOVERSE_V2_CPUPWRCTLR_EL1_WFE_RET_CTRL_SHIFT, \
+ #NEOVERSE_V2_CPUPWRCTLR_EL1_WFE_RET_CTRL_WIDTH
+ msr NEOVERSE_V2_CPUPWRCTLR_EL1, x0
+workaround_reset_end neoverse_v2, ERRATUM(2618597)
+
+check_erratum_ls neoverse_v2, ERRATUM(2618597), CPU_REV(0, 1)
+
+workaround_reset_start neoverse_v2, ERRATUM(2662553), ERRATA_V2_2662553
+ sysreg_bitfield_insert NEOVERSE_V2_CPUECTLR2_EL1, NEOVERSE_V2_CPUECTLR2_EL1_TXREQ_STATIC_FULL, \
+ NEOVERSE_V2_CPUECTLR2_EL1_TXREQ_LSB, NEOVERSE_V2_CPUECTLR2_EL1_TXREQ_WIDTH
+workaround_reset_end neoverse_v2, ERRATUM(2662553)
+
+check_erratum_ls neoverse_v2, ERRATUM(2662553), CPU_REV(0, 1)
+
workaround_reset_start neoverse_v2, ERRATUM(2719105), ERRATA_V2_2719105
sysreg_bit_set NEOVERSE_V2_CPUACTLR2_EL1, NEOVERSE_V2_CPUACTLR2_EL1_BIT_0
workaround_reset_end neoverse_v2, ERRATUM(2719105)
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 3901d17..bbf44b4 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -838,6 +838,14 @@
# to revisions r0p0, r0p1 and r0p2. It is still open.
CPU_FLAG_LIST += ERRATA_V2_2331132
+# Flag to apply erratum 2618597 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1. It is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_V2_2618597
+
+# Flag to apply erratum 2662553 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1. It is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_V2_2662553
+
# Flag to apply erratum 2719103 workaround for non-arm interconnect ip. This
# erratum applies to revisions r0p0, rop1. Fixed in r0p2.
CPU_FLAG_LIST += ERRATA_V2_2719103
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 3ff0aaf..8829fcb 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -150,6 +150,10 @@
# Enable Handoff protocol using transfer lists
TRANSFER_LIST := 0
+# Enables support for the gcc compiler option "-mharden-sls=all".
+# By default, disables all SLS hardening.
+HARDEN_SLS := 0
+
# Secure hash algorithm flag, accepts 3 values: sha256, sha384 and sha512.
# The default value is sha256.
HASH_ALG := sha256
diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk
index 95753aa..d8d1293 100644
--- a/plat/arm/board/rdn1edge/platform.mk
+++ b/plat/arm/board/rdn1edge/platform.mk
@@ -73,3 +73,6 @@
endif
override CTX_INCLUDE_AARCH32_REGS := 0
+
+# Enable the flag since RD-N1-EDGE has a system level cache
+NEOVERSE_Nx_EXTERNAL_LLC := 1
diff --git a/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts
index 9c9cefe..d992eac 100644
--- a/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts
+++ b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,6 +18,12 @@
id = <TB_FW_CONFIG_ID>;
};
+ tos_fw-config {
+ load-address = <0x0 0x04001500>;
+ max-size = <0x1000>;
+ id = <TOS_FW_CONFIG_ID>;
+ };
+
nt_fw-config {
load-address = <0x0 0xFEF00000>;
max-size = <0x0100000>;
diff --git a/plat/arm/board/rdn2/fdts/rdn2_stmm_sel0_manifest.dts b/plat/arm/board/rdn2/fdts/rdn2_stmm_sel0_manifest.dts
new file mode 100644
index 0000000..2cf3f75
--- /dev/null
+++ b/plat/arm/board/rdn2/fdts/rdn2_stmm_sel0_manifest.dts
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include <platform_def.h>
+
+/ {
+#define MODE_SEL0 (0x1)
+
+#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
+ * manifest file and fetch the following booting arguments to
+ * pass on to the StandAloneMM(StMM) Secure Partition.
+ */
+ compatible = "arm,ffa-manifest-1.0";
+
+ description = "RDN2 StMM";
+ ffa-version = <0x00010001>; /* 31:16 - Major, 15:0 - Minor */
+ uuid = <0x378daedc 0xf06b4446 0x831440ab 0x933c87a3>;
+ id = <0x8001>;
+ execution-ctx-count = <1>;
+ exception-level = <MODE_SEL0>; /* S-EL0 */
+ execution-state = <0>; /* AArch64 */
+ load-address = <0x0 0xFF200000>;
+ image-size = <0x0 0x280000>;
+ xlat-granule = <0>; /* 4KiB */
+ boot-order = <0>;
+ messaging-method = <0x3>; /* Direct request/response supported. */
+ power-management-messages = <0x1>;
+ gp-register-num = <0>;
+
+ device-regions {
+ compatible = "arm,ffa-manifest-device-regions";
+
+ /*
+ * System registers region for access from S-EL0.
+ * Similar to PLAT_ARM_SECURE_MAP_SYSTEMREG.
+ */
+ sys-regs {
+ base-address = <0x0 0x0C010000>;
+ pages-count = <0x10>;
+ attributes = <SECURE_RW>;
+ };
+
+ rtc {
+ base-address = <0x0 0x0C170000>;
+ pages-count = <0x1>;
+ attributes = <SECURE_RW>;
+ };
+
+ /*
+ * ARM CSS SoC Expansion Peripherals.
+ */
+ soc_components {
+ base-address = <0x0 0x0E000000>;
+ pages-count = <0x2000>;
+ attributes = <SECURE_RW>;
+ };
+
+ cluster_utility {
+ base-address = <0x0 0x20000000>;
+ pages-count = <0x20000>;
+ attributes = <SECURE_RW>;
+ };
+
+ secure_uart {
+ base-address = <0x0 0x2A410000>;
+ pages-count = <0x10>;
+ attributes = <SECURE_RW>;
+ };
+
+ /*
+ * Used for Secure booting.
+ */
+ nor_flash2 {
+ base-address = <0x10 0x54000000>;
+ 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 macro used for defining base of
+ * the SP image.
+ */
+ stmm_region {
+ base-address = <0x0 0xff200000>;
+ pages-count = <0x300>;
+ /* StMM will remap the regions during runtime. */
+ attributes = <SECURE_EXECUTE_RO>;
+ };
+
+ /*
+ * Memory shared between EL3 SPMC and S-EL0.
+ */
+ rx-tx-buffers {
+ description = "shared-buff";
+ base-address = <0x0 0xff500000>;
+ pages-count = <0x100>;
+ attributes = <SECURE_RW>;
+ };
+
+ /*
+ * Memory shared between Normal world and S-EL0.
+ */
+ ns_comm_buffer {
+ /*
+ * Description is needed for StMM to identify
+ * ns-communication buffer.
+ */
+ description = "ns-comm";
+ base-address = <0x0 0xff600000>;
+ pages-count = <0x30>;
+ 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 0xFF630000>;
+ pages-count = <0x5D0>;
+ attributes = <SECURE_RW>;
+ };
+ };
+};
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
index ef8f3d4..beaddef 100644
--- a/plat/arm/board/rdn2/platform.mk
+++ b/plat/arm/board/rdn2/platform.mk
@@ -93,5 +93,15 @@
# Add the NT_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
+STMM_CONFIG_DTS := ${RDN2_BASE}/fdts/${PLAT}_stmm_sel0_manifest.dts
+FDT_SOURCES += ${STMM_CONFIG_DTS}
+TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${STMM_CONFIG_DTS})).dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TOS_FW_CONFIG},--tos-fw-config,${TOS_FW_CONFIG}))
+
override CTX_INCLUDE_AARCH32_REGS := 0
override ENABLE_FEAT_AMU := 1
+
+# Enable the flag since RD-N2 has a system level cache
+NEOVERSE_Nx_EXTERNAL_LLC := 1
diff --git a/plat/arm/board/rdv1/platform.mk b/plat/arm/board/rdv1/platform.mk
index a5fba67..0b059b5 100644
--- a/plat/arm/board/rdv1/platform.mk
+++ b/plat/arm/board/rdv1/platform.mk
@@ -63,3 +63,6 @@
$(error "CSS_SGI_PLATFORM_VARIANT for RD-V1 should always be 0, \
currently set to ${CSS_SGI_PLATFORM_VARIANT}.")
endif
+
+# Enable the flag since RD-V1 has a system level cache
+NEOVERSE_Nx_EXTERNAL_LLC := 1
diff --git a/plat/arm/board/rdv1mc/platform.mk b/plat/arm/board/rdv1mc/platform.mk
index 92f7c10..176e0ef 100644
--- a/plat/arm/board/rdv1mc/platform.mk
+++ b/plat/arm/board/rdv1mc/platform.mk
@@ -74,3 +74,6 @@
$(error "CSS_SGI_PLATFORM_VARIANT for RD-V1-MC should always be 0, \
currently set to ${CSS_SGI_PLATFORM_VARIANT}.")
endif
+
+# Enable the flag since RD-V1-MC has a system level cache
+NEOVERSE_Nx_EXTERNAL_LLC := 1
diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk
index 5b4766d..f96e18b 100644
--- a/plat/rockchip/rk3328/platform.mk
+++ b/plat/rockchip/rk3328/platform.mk
@@ -65,6 +65,7 @@
# Enable workarounds for selected Cortex-A53 errata
ERRATA_A53_855873 := 1
+ERRATA_A53_1530924 := 1
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
$(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER))
diff --git a/services/std_svc/errata_abi/errata_abi_main.c b/services/std_svc/errata_abi/errata_abi_main.c
index cf2e653..13d8361 100644
--- a/services/std_svc/errata_abi/errata_abi_main.c
+++ b/services/std_svc/errata_abi/errata_abi_main.c
@@ -415,13 +415,15 @@
.cpu_partnumber = NEOVERSE_V2_MIDR,
.cpu_errata_list = {
[0] = {2331132, 0x00, 0x02, ERRATA_V2_2331132},
- [1] = {2719103, 0x00, 0x01, ERRATA_V2_2719103, \
+ [1] = {2618597, 0x00, 0x01, ERRATA_V2_2618597},
+ [2] = {2662553, 0x00, 0x01, ERRATA_V2_2662553},
+ [3] = {2719103, 0x00, 0x01, ERRATA_V2_2719103, \
ERRATA_NON_ARM_INTERCONNECT},
- [2] = {2719105, 0x00, 0x01, ERRATA_V2_2719105},
- [3] = {2743011, 0x00, 0x01, ERRATA_V2_2743011},
- [4] = {2779510, 0x00, 0x01, ERRATA_V2_2779510},
- [5] = {2801372, 0x00, 0x01, ERRATA_V2_2801372},
- [6 ... ERRATA_LIST_END] = UNDEF_ERRATA,
+ [4] = {2719105, 0x00, 0x01, ERRATA_V2_2719105},
+ [5] = {2743011, 0x00, 0x01, ERRATA_V2_2743011},
+ [6] = {2779510, 0x00, 0x01, ERRATA_V2_2779510},
+ [7] = {2801372, 0x00, 0x01, ERRATA_V2_2801372},
+ [8 ... ERRATA_LIST_END] = UNDEF_ERRATA,
}
},
#endif /* NEOVERSE_V2_H_INC */
diff --git a/services/std_svc/spm/el3_spmc/spmc.h b/services/std_svc/spm/el3_spmc/spmc.h
index 48644ac..e093a82 100644
--- a/services/std_svc/spm/el3_spmc/spmc.h
+++ b/services/std_svc/spm/el3_spmc/spmc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -168,6 +168,12 @@
/* Mailbox tracking. */
struct mailbox mailbox;
+ /* Lock to protect the runtime state of a S-EL0 SP execution context. */
+ spinlock_t rt_state_lock;
+
+ /* Pointer to translation table context of a S-EL0 SP. */
+ xlat_ctx_t *xlat_ctx_handle;
+
/* Secondary entrypoint. Only valid for a S-EL1 SP. */
uintptr_t secondary_ep;
@@ -224,6 +230,10 @@
entry_point_info_t *ep_info);
void spmc_sp_common_ep_commit(struct secure_partition_desc *sp,
entry_point_info_t *ep_info);
+void spmc_el0_sp_spsr_setup(entry_point_info_t *ep_info);
+void spmc_el0_sp_setup(struct secure_partition_desc *sp,
+ int32_t boot_info_reg,
+ void *sp_manifest);
/*
* Helper function to perform a synchronous entry into a SP.
diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c
index ada6f45..42747bf 100644
--- a/services/std_svc/spm/el3_spmc/spmc_main.c
+++ b/services/std_svc/spm/el3_spmc/spmc_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -30,6 +30,17 @@
#include <platform_def.h>
+/* FFA_MEM_PERM_* helpers */
+#define FFA_MEM_PERM_MASK U(7)
+#define FFA_MEM_PERM_DATA_MASK U(3)
+#define FFA_MEM_PERM_DATA_SHIFT U(0)
+#define FFA_MEM_PERM_DATA_NA U(0)
+#define FFA_MEM_PERM_DATA_RW U(1)
+#define FFA_MEM_PERM_DATA_RES U(2)
+#define FFA_MEM_PERM_DATA_RO U(3)
+#define FFA_MEM_PERM_INST_EXEC (U(0) << 2)
+#define FFA_MEM_PERM_INST_NON_EXEC (U(1) << 2)
+
/* Declare the maximum number of SPs and El3 LPs. */
#define MAX_SP_LP_PARTITIONS SECURE_PARTITION_COUNT + MAX_EL3_LP_DESCS_COUNT
@@ -390,6 +401,11 @@
FFA_ERROR_INVALID_PARAMETER);
}
+ /* 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);
+ }
+
/*
* Check that the target execution context is in a waiting state before
* forwarding the direct request to it.
@@ -398,6 +414,11 @@
if (sp->ec[idx].rt_state != RT_STATE_WAITING) {
VERBOSE("SP context on core%u is not waiting (%u).\n",
idx, sp->ec[idx].rt_model);
+
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
+
return spmc_ffa_error_return(handle, FFA_ERROR_BUSY);
}
@@ -408,6 +429,11 @@
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;
+
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
+
return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
handle, cookie, flags, dst_id);
}
@@ -462,6 +488,10 @@
FFA_ERROR_INVALID_PARAMETER);
}
+ if (sp->runtime_el == S_EL0) {
+ spin_lock(&sp->rt_state_lock);
+ }
+
/* Sanity check state is being tracked correctly in the SPMC. */
idx = get_ec_index(sp);
assert(sp->ec[idx].rt_state == RT_STATE_RUNNING);
@@ -470,12 +500,18 @@
if (sp->ec[idx].rt_model != RT_MODEL_DIR_REQ) {
VERBOSE("SP context on core%u not handling direct req (%u).\n",
idx, sp->ec[idx].rt_model);
+ 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);
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
}
@@ -485,6 +521,10 @@
/* Clear the ongoing direct request ID. */
sp->ec[idx].dir_req_origin_id = INV_SP_ID;
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
+
/*
* If the receiver is not the SPMC then forward the response to the
* Normal world.
@@ -536,9 +576,15 @@
* Get the execution context of the SP that invoked FFA_MSG_WAIT.
*/
idx = get_ec_index(sp);
+ if (sp->runtime_el == S_EL0) {
+ spin_lock(&sp->rt_state_lock);
+ }
/* Ensure SP execution context was in the right runtime model. */
if (sp->ec[idx].rt_model == RT_MODEL_DIR_REQ) {
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
}
@@ -550,6 +596,9 @@
* state is updated after the exit.
*/
if (sp->ec[idx].rt_model == RT_MODEL_INIT) {
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
spmc_sp_synchronous_exit(&sp->ec[idx], x4);
/* Should not get here */
panic();
@@ -567,9 +616,19 @@
cm_el1_sysregs_context_save(secure_state_in);
cm_el1_sysregs_context_restore(secure_state_out);
cm_set_next_eret_context(secure_state_out);
+
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
+
SMC_RET0(cm_get_context(secure_state_out));
}
+ /* Protect the runtime state of a S-EL0 SP with a lock. */
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
+
/* Forward the response to the Normal world. */
return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
handle, cookie, flags, FFA_NWD_ID);
@@ -1343,14 +1402,21 @@
}
idx = get_ec_index(sp);
+
if (idx != vcpu_id) {
ERROR("Cannot run vcpu %d != %d.\n", idx, vcpu_id);
return spmc_ffa_error_return(handle,
FFA_ERROR_INVALID_PARAMETER);
}
+ if (sp->runtime_el == S_EL0) {
+ spin_lock(&sp->rt_state_lock);
+ }
rt_state = &((sp->ec[idx]).rt_state);
rt_model = &((sp->ec[idx]).rt_model);
if (*rt_state == RT_STATE_RUNNING) {
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
ERROR("Partition (0x%x) is already running.\n", target_id);
return spmc_ffa_error_return(handle, FFA_ERROR_BUSY);
}
@@ -1377,6 +1443,10 @@
*/
*rt_state = RT_STATE_RUNNING;
+ if (sp->runtime_el == S_EL0) {
+ spin_unlock(&sp->rt_state_lock);
+ }
+
return spmc_smc_return(smc_fid, secure_origin, x1, 0, 0, 0,
handle, cookie, flags, target_id);
}
@@ -1505,6 +1575,223 @@
}
/*******************************************************************************
+ * Permissions are encoded using a different format in the FFA_MEM_PERM_* ABIs
+ * than in the Trusted Firmware, where the mmap_attr_t enum type is used. This
+ * function converts a permission value from the FF-A format to the mmap_attr_t
+ * format by setting MT_RW/MT_RO, MT_USER/MT_PRIVILEGED and
+ * MT_EXECUTE/MT_EXECUTE_NEVER. The other fields are left as 0 because they are
+ * ignored by the function xlat_change_mem_attributes_ctx().
+ ******************************************************************************/
+static unsigned int ffa_perm_to_mmap_perm(unsigned int perms)
+{
+ unsigned int tf_attr = 0U;
+ unsigned int access;
+
+ /* Deal with data access permissions first. */
+ access = (perms & FFA_MEM_PERM_DATA_MASK) >> FFA_MEM_PERM_DATA_SHIFT;
+
+ switch (access) {
+ case FFA_MEM_PERM_DATA_RW:
+ /* Return 0 if the execute is set with RW. */
+ if ((perms & FFA_MEM_PERM_INST_NON_EXEC) != 0) {
+ tf_attr |= MT_RW | MT_USER | MT_EXECUTE_NEVER;
+ }
+ break;
+
+ case FFA_MEM_PERM_DATA_RO:
+ tf_attr |= MT_RO | MT_USER;
+ /* Deal with the instruction access permissions next. */
+ if ((perms & FFA_MEM_PERM_INST_NON_EXEC) == 0) {
+ tf_attr |= MT_EXECUTE;
+ } else {
+ tf_attr |= MT_EXECUTE_NEVER;
+ }
+ break;
+
+ case FFA_MEM_PERM_DATA_NA:
+ default:
+ return tf_attr;
+ }
+
+ return tf_attr;
+}
+
+/*******************************************************************************
+ * Handler to set the permissions of a set of contiguous pages of a S-EL0 SP
+ ******************************************************************************/
+static uint64_t ffa_mem_perm_set_handler(uint32_t smc_fid,
+ bool secure_origin,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ void *cookie,
+ void *handle,
+ uint64_t flags)
+{
+ struct secure_partition_desc *sp;
+ unsigned int idx;
+ uintptr_t base_va = (uintptr_t) x1;
+ size_t size = (size_t)(x2 * PAGE_SIZE);
+ uint32_t tf_attr;
+ int ret;
+
+ /* This request cannot originate from the Normal world. */
+ if (!secure_origin) {
+ return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
+ }
+
+ if (size == 0) {
+ return spmc_ffa_error_return(handle,
+ FFA_ERROR_INVALID_PARAMETER);
+ }
+
+ /* Get the context of the current SP. */
+ sp = spmc_get_current_sp_ctx();
+ if (sp == NULL) {
+ return spmc_ffa_error_return(handle,
+ FFA_ERROR_INVALID_PARAMETER);
+ }
+
+ /* A S-EL1 SP has no business invoking this ABI. */
+ if (sp->runtime_el == S_EL1) {
+ return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
+ }
+
+ if ((x3 & ~((uint64_t)FFA_MEM_PERM_MASK)) != 0) {
+ return spmc_ffa_error_return(handle,
+ FFA_ERROR_INVALID_PARAMETER);
+ }
+
+ /* Get the execution context of the calling SP. */
+ idx = get_ec_index(sp);
+
+ /*
+ * Ensure that the S-EL0 SP is initialising itself. We do not need to
+ * synchronise this operation through a spinlock since a S-EL0 SP is UP
+ * and can only be initialising on this cpu.
+ */
+ if (sp->ec[idx].rt_model != RT_MODEL_INIT) {
+ return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
+ }
+
+ VERBOSE("Setting memory permissions:\n");
+ VERBOSE(" Start address : 0x%lx\n", base_va);
+ VERBOSE(" Number of pages: %lu (%zu bytes)\n", x2, size);
+ VERBOSE(" Attributes : 0x%x\n", (uint32_t)x3);
+
+ /* Convert inbound permissions to TF-A permission attributes */
+ tf_attr = ffa_perm_to_mmap_perm((unsigned int)x3);
+ if (tf_attr == 0U) {
+ return spmc_ffa_error_return(handle,
+ FFA_ERROR_INVALID_PARAMETER);
+ }
+
+ /* Request the change in permissions */
+ ret = xlat_change_mem_attributes_ctx(sp->xlat_ctx_handle,
+ base_va, size, tf_attr);
+ if (ret != 0) {
+ return spmc_ffa_error_return(handle,
+ FFA_ERROR_INVALID_PARAMETER);
+ }
+
+ SMC_RET1(handle, FFA_SUCCESS_SMC32);
+}
+
+/*******************************************************************************
+ * Permissions are encoded using a different format in the FFA_MEM_PERM_* ABIs
+ * than in the Trusted Firmware, where the mmap_attr_t enum type is used. This
+ * function converts a permission value from the mmap_attr_t format to the FF-A
+ * format.
+ ******************************************************************************/
+static unsigned int mmap_perm_to_ffa_perm(unsigned int attr)
+{
+ unsigned int perms = 0U;
+ unsigned int data_access;
+
+ if ((attr & MT_USER) == 0) {
+ /* No access from EL0. */
+ data_access = FFA_MEM_PERM_DATA_NA;
+ } else {
+ if ((attr & MT_RW) != 0) {
+ data_access = FFA_MEM_PERM_DATA_RW;
+ } else {
+ data_access = FFA_MEM_PERM_DATA_RO;
+ }
+ }
+
+ perms |= (data_access & FFA_MEM_PERM_DATA_MASK)
+ << FFA_MEM_PERM_DATA_SHIFT;
+
+ if ((attr & MT_EXECUTE_NEVER) != 0U) {
+ perms |= FFA_MEM_PERM_INST_NON_EXEC;
+ }
+
+ return perms;
+}
+
+/*******************************************************************************
+ * Handler to get the permissions of a set of contiguous pages of a S-EL0 SP
+ ******************************************************************************/
+static uint64_t ffa_mem_perm_get_handler(uint32_t smc_fid,
+ bool secure_origin,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ void *cookie,
+ void *handle,
+ uint64_t flags)
+{
+ struct secure_partition_desc *sp;
+ unsigned int idx;
+ uintptr_t base_va = (uintptr_t)x1;
+ uint32_t tf_attr = 0;
+ int ret;
+
+ /* This request cannot originate from the Normal world. */
+ if (!secure_origin) {
+ return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
+ }
+
+ /* Get the context of the current SP. */
+ sp = spmc_get_current_sp_ctx();
+ if (sp == NULL) {
+ return spmc_ffa_error_return(handle,
+ FFA_ERROR_INVALID_PARAMETER);
+ }
+
+ /* A S-EL1 SP has no business invoking this ABI. */
+ if (sp->runtime_el == S_EL1) {
+ return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
+ }
+
+ /* Get the execution context of the calling SP. */
+ idx = get_ec_index(sp);
+
+ /*
+ * Ensure that the S-EL0 SP is initialising itself. We do not need to
+ * synchronise this operation through a spinlock since a S-EL0 SP is UP
+ * and can only be initialising on this cpu.
+ */
+ if (sp->ec[idx].rt_model != RT_MODEL_INIT) {
+ return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
+ }
+
+ /* Request the permissions */
+ ret = xlat_get_mem_attributes_ctx(sp->xlat_ctx_handle, base_va, &tf_attr);
+ if (ret != 0) {
+ return spmc_ffa_error_return(handle,
+ FFA_ERROR_INVALID_PARAMETER);
+ }
+
+ /* Convert TF-A permission to FF-A permissions attributes. */
+ x2 = mmap_perm_to_ffa_perm(tf_attr);
+
+ SMC_RET3(handle, FFA_SUCCESS_SMC32, 0, x2);
+}
+
+/*******************************************************************************
* This function will parse the Secure Partition Manifest. From manifest, it
* will fetch details for preparing Secure partition image context and secure
* partition image boot arguments if any.
@@ -1588,7 +1875,7 @@
* since this is currently a hardcoded value for S-EL1 partitions
* we don't need to save it here, just validate.
*/
- if (config_32 != PLATFORM_CORE_COUNT) {
+ if ((sp->runtime_el == S_EL1) && (config_32 != PLATFORM_CORE_COUNT)) {
ERROR("SP Execution Context Count (%u) must be %u.\n",
config_32, PLATFORM_CORE_COUNT);
return -EINVAL;
@@ -1704,7 +1991,8 @@
* the manifest as boot information later.
*/
next_image_ep_info->args.arg1 = fdt_totalsize(sp_manifest);
- INFO("Manifest size = %lu bytes.\n", next_image_ep_info->args.arg1);
+ INFO("Manifest adr = %lx , size = %lu bytes\n", manifest_base,
+ next_image_ep_info->args.arg1);
/*
* Select an SP descriptor for initialising the partition's execution
@@ -1712,6 +2000,11 @@
*/
sp = spmc_get_current_sp_ctx();
+#if SPMC_AT_EL3_SEL0_SP
+ /* Assign translation tables context. */
+ sp_desc->xlat_ctx_handle = spm_get_sp_xlat_context();
+
+#endif /* SPMC_AT_EL3_SEL0_SP */
/* Initialize entry point information for the SP */
SET_PARAM_HEAD(next_image_ep_info, PARAM_EP, VERSION_1,
SECURE | EP_ST_ENABLE);
@@ -1725,7 +2018,7 @@
}
/* Check that the runtime EL in the manifest was correct. */
- if (sp->runtime_el != S_EL1) {
+ if (sp->runtime_el != S_EL0 && sp->runtime_el != S_EL1) {
ERROR("Unexpected runtime EL: %d\n", sp->runtime_el);
return -EINVAL;
}
@@ -1734,11 +2027,29 @@
spmc_sp_common_setup(sp, next_image_ep_info, boot_info_reg);
/* Perform any initialisation specific to S-EL1 SPs. */
- spmc_el1_sp_setup(sp, next_image_ep_info);
+ if (sp->runtime_el == S_EL1) {
+ spmc_el1_sp_setup(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) {
+ 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);
+#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) {
+ spmc_el0_sp_setup(sp, boot_info_reg, sp_manifest);
+ }
+#endif /* SPMC_AT_EL3_SEL0_SP */
return 0;
}
@@ -2051,6 +2362,14 @@
return spmc_ffa_mem_reclaim(smc_fid, secure_origin, x1, x2, x3,
x4, cookie, handle, flags);
+ case FFA_MEM_PERM_GET:
+ return ffa_mem_perm_get_handler(smc_fid, secure_origin, x1, x2,
+ x3, x4, cookie, handle, flags);
+
+ case FFA_MEM_PERM_SET:
+ return ffa_mem_perm_set_handler(smc_fid, secure_origin, x1, x2,
+ x3, x4, cookie, handle, flags);
+
default:
WARN("Unsupported FF-A call 0x%08x.\n", smc_fid);
break;
diff --git a/services/std_svc/spm/el3_spmc/spmc_setup.c b/services/std_svc/spm/el3_spmc/spmc_setup.c
index 6de25f6..609d968 100644
--- a/services/std_svc/spm/el3_spmc/spmc_setup.c
+++ b/services/std_svc/spm/el3_spmc/spmc_setup.c
@@ -20,6 +20,7 @@
#include <plat/common/platform.h>
#include <services/ffa_svc.h>
#include "spm_common.h"
+#include "spm_shim_private.h"
#include "spmc.h"
#include <tools_share/firmware_image_package.h>
@@ -31,6 +32,26 @@
static uint8_t ffa_boot_info_mem[PAGE_SIZE] __aligned(PAGE_SIZE);
/*
+ * We need to choose one execution context from all those available for a S-EL0
+ * SP. This execution context will be used subsequently irrespective of which
+ * physical CPU the SP runs on.
+ */
+#define SEL0_SP_EC_INDEX 0
+#define SP_MEM_READ 0x1
+#define SP_MEM_WRITE 0x2
+#define SP_MEM_EXECUTE 0x4
+#define SP_MEM_NON_SECURE 0x8
+#define SP_MEM_READ_ONLY SP_MEM_READ
+#define SP_MEM_READ_WRITE (SP_MEM_READ | SP_MEM_WRITE)
+
+/* Type of the memory region in SP's manifest. */
+enum sp_memory_region_type {
+ SP_MEM_REGION_DEVICE,
+ SP_MEM_REGION_MEMORY,
+ SP_MEM_REGION_NOT_SPECIFIED
+};
+
+/*
* This function creates a initialization descriptor in the memory reserved
* for passing boot information to an SP. It then copies the partition manifest
* into this region and ensures that its reference in the initialization
@@ -143,14 +164,310 @@
}
/*
- * We are assuming that the index of the execution
- * context used is the linear index of the current physical cpu.
+ * S-EL1 partitions can be assigned with multiple execution contexts, each
+ * pinned to the physical CPU. Each execution context index corresponds to the
+ * respective liner core position.
+ * S-EL0 partitions execute in a single execution context (index 0).
*/
unsigned int get_ec_index(struct secure_partition_desc *sp)
{
+ return (sp->runtime_el == S_EL0) ?
+ SEL0_SP_EC_INDEX : plat_my_core_pos();
+}
+
+#if SPMC_AT_EL3_SEL0_SP
+/* Setup spsr in entry point info for common context management code to use. */
+void spmc_el0_sp_spsr_setup(entry_point_info_t *ep_info)
+{
+ /* Setup Secure Partition SPSR for S-EL0 SP. */
+ ep_info->spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS);
+}
+
+static void read_optional_string(void *manifest, int32_t offset,
+ char *property, char *out, size_t len)
+{
- return plat_my_core_pos();
+ const fdt32_t *prop;
+ int lenp;
+
+ prop = fdt_getprop(manifest, offset, property, &lenp);
+ if (prop == NULL) {
+ out[0] = '\0';
+ } else {
+ memcpy(out, prop, MIN(lenp, (int)len));
+ }
+}
+
+/*******************************************************************************
+ * This function will parse the Secure Partition Manifest for fetching secure
+ * partition specific memory/device region details. It will find base address,
+ * size, memory attributes for each region and then add the respective region
+ * into secure parition's translation context.
+ ******************************************************************************/
+static void populate_sp_regions(struct secure_partition_desc *sp,
+ void *sp_manifest, int node,
+ enum sp_memory_region_type type)
+{
+ uintptr_t base_address;
+ uint32_t mem_attr, mem_region, size;
+ struct mmap_region sp_mem_regions = {0};
+ int32_t offset, ret;
+ char *compatibility[SP_MEM_REGION_NOT_SPECIFIED] = {
+ "arm,ffa-manifest-device-regions",
+ "arm,ffa-manifest-memory-regions"
+ };
+ char description[10];
+ char *property;
+ char *region[SP_MEM_REGION_NOT_SPECIFIED] = {
+ "device regions",
+ "memory regions"
+ };
+
+ if (type >= SP_MEM_REGION_NOT_SPECIFIED) {
+ WARN("Invalid region type\n");
+ return;
+ }
+
+ INFO("Mapping SP's %s\n", region[type]);
+
+ if (fdt_node_check_compatible(sp_manifest, node,
+ compatibility[type]) != 0) {
+ WARN("Incompatible region node in manifest\n");
+ return;
+ }
+
+ for (offset = fdt_first_subnode(sp_manifest, node), mem_region = 0;
+ offset >= 0;
+ offset = fdt_next_subnode(sp_manifest, offset), mem_region++) {
+ read_optional_string(sp_manifest, offset, "description",
+ description, sizeof(description));
+
+ INFO("Mapping: region: %d, %s\n", mem_region, description);
+
+ property = "base-address";
+ ret = fdt_read_uint64(sp_manifest, offset, property,
+ &base_address);
+ if (ret < 0) {
+ WARN("Missing:%s for %s.\n", property, description);
+ continue;
+ }
+
+ property = "pages-count";
+ ret = fdt_read_uint32(sp_manifest, offset, property, &size);
+ if (ret < 0) {
+ WARN("Missing: %s for %s.\n", property, description);
+ continue;
+ }
+ size *= PAGE_SIZE;
+
+ property = "attributes";
+ ret = fdt_read_uint32(sp_manifest, offset, property, &mem_attr);
+ if (ret < 0) {
+ WARN("Missing: %s for %s.\n", property, description);
+ continue;
+ }
+
+ sp_mem_regions.attr = MT_USER;
+ if (type == SP_MEM_REGION_DEVICE) {
+ sp_mem_regions.attr |= MT_EXECUTE_NEVER;
+ } else {
+ sp_mem_regions.attr |= MT_MEMORY;
+ if ((mem_attr & SP_MEM_EXECUTE) == SP_MEM_EXECUTE) {
+ sp_mem_regions.attr &= ~MT_EXECUTE_NEVER;
+ } else {
+ sp_mem_regions.attr |= MT_EXECUTE_NEVER;
+ }
+ }
+
+ if ((mem_attr & SP_MEM_READ_WRITE) == SP_MEM_READ_WRITE) {
+ sp_mem_regions.attr |= MT_RW;
+ }
+
+ if ((mem_attr & SP_MEM_NON_SECURE) == SP_MEM_NON_SECURE) {
+ sp_mem_regions.attr |= MT_NS;
+ } else {
+ sp_mem_regions.attr |= MT_SECURE;
+ }
+
+ sp_mem_regions.base_pa = base_address;
+ 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",
+ sp_mem_regions.base_pa,
+ sp_mem_regions.base_va,
+ sp_mem_regions.size,
+ sp_mem_regions.attr);
+
+ if (type == SP_MEM_REGION_DEVICE) {
+ sp_mem_regions.granularity = XLAT_BLOCK_SIZE(1);
+ } else {
+ sp_mem_regions.granularity = XLAT_BLOCK_SIZE(3);
+ }
+ mmap_add_region_ctx(sp->xlat_ctx_handle, &sp_mem_regions);
+ }
}
+static void spmc_el0_sp_setup_mmu(struct secure_partition_desc *sp,
+ cpu_context_t *ctx)
+{
+ xlat_ctx_t *xlat_ctx;
+ uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
+
+ xlat_ctx = sp->xlat_ctx_handle;
+ init_xlat_tables_ctx(sp->xlat_ctx_handle);
+ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table,
+ xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
+ EL1_EL0_REGIME);
+
+ write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
+ mmu_cfg_params[MMU_CFG_MAIR]);
+
+ write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
+ mmu_cfg_params[MMU_CFG_TCR]);
+
+ write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
+ mmu_cfg_params[MMU_CFG_TTBR0]);
+}
+
+static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx)
+{
+ u_register_t sctlr_el1;
+
+ /* Setup SCTLR_EL1 */
+ sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
+
+ sctlr_el1 |=
+ /*SCTLR_EL1_RES1 |*/
+ /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
+ SCTLR_UCI_BIT |
+ /* RW regions at xlat regime EL1&0 are forced to be XN. */
+ SCTLR_WXN_BIT |
+ /* Don't trap to EL1 execution of WFI or WFE at EL0. */
+ SCTLR_NTWI_BIT | SCTLR_NTWE_BIT |
+ /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */
+ SCTLR_UCT_BIT |
+ /* Don't trap to EL1 execution of DZ ZVA at EL0. */
+ SCTLR_DZE_BIT |
+ /* Enable SP Alignment check for EL0 */
+ SCTLR_SA0_BIT |
+ /* Don't change PSTATE.PAN on taking an exception to EL1 */
+ SCTLR_SPAN_BIT |
+ /* Allow cacheable data and instr. accesses to normal memory. */
+ SCTLR_C_BIT | SCTLR_I_BIT |
+ /* Enable MMU. */
+ SCTLR_M_BIT;
+
+ sctlr_el1 &= ~(
+ /* Explicit data accesses at EL0 are little-endian. */
+ SCTLR_E0E_BIT |
+ /*
+ * Alignment fault checking disabled when at EL1 and EL0 as
+ * the UEFI spec permits unaligned accesses.
+ */
+ SCTLR_A_BIT |
+ /* Accesses to DAIF from EL0 are trapped to EL1. */
+ SCTLR_UMA_BIT
+ );
+
+ write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
+}
+
+static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp,
+ cpu_context_t *ctx)
+{
+
+ spmc_el0_sp_setup_mmu(sp, ctx);
+
+ spmc_el0_sp_setup_sctlr_el1(ctx);
+
+ /* Setup other system registers. */
+
+ /* Shim Exception Vector Base Address */
+ write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
+ SPM_SHIM_EXCEPTIONS_PTR);
+#if NS_TIMER_SWITCH
+ write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
+ EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
+#endif
+
+ /*
+ * FPEN: Allow the Secure Partition to access FP/SIMD registers.
+ * Note that SPM will not do any saving/restoring of these registers on
+ * behalf of the SP. This falls under the SP's responsibility.
+ * TTA: Enable access to trace registers.
+ * ZEN (v8.2): Trap SVE instructions and access to SVE registers.
+ */
+ write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
+ CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
+}
+
+/* Setup context of an EL0 Secure Partition. */
+void spmc_el0_sp_setup(struct secure_partition_desc *sp,
+ int32_t boot_info_reg,
+ void *sp_manifest)
+{
+ mmap_region_t sel1_exception_vectors =
+ MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
+ SPM_SHIM_EXCEPTIONS_SIZE,
+ MT_CODE | MT_SECURE | MT_PRIVILEGED);
+ cpu_context_t *ctx;
+ int node;
+ int offset = 0;
+
+ ctx = &sp->ec[SEL0_SP_EC_INDEX].cpu_ctx;
+
+ sp->xlat_ctx_handle->xlat_regime = EL1_EL0_REGIME;
+
+ /* This region contains the exception vectors used at S-EL1. */
+ mmap_add_region_ctx(sp->xlat_ctx_handle,
+ &sel1_exception_vectors);
+
+ /*
+ * If the SP manifest specified the register to pass the address of the
+ * boot information, then map the memory region to pass boot
+ * information.
+ */
+ if (boot_info_reg >= 0) {
+ mmap_region_t ffa_boot_info_region = MAP_REGION_FLAT(
+ (uintptr_t) ffa_boot_info_mem,
+ PAGE_SIZE,
+ MT_RO_DATA | MT_SECURE | MT_USER);
+ mmap_add_region_ctx(sp->xlat_ctx_handle, &ffa_boot_info_region);
+ }
+
+ /*
+ * Parse the manifest for any device regions that the SP wants to be
+ * mapped in its translation regime.
+ */
+ node = fdt_subnode_offset_namelen(sp_manifest, offset,
+ "device-regions",
+ sizeof("device-regions") - 1);
+ if (node < 0) {
+ WARN("Not found device-region configuration for SP.\n");
+ } else {
+ populate_sp_regions(sp, sp_manifest, node,
+ SP_MEM_REGION_DEVICE);
+ }
+
+ /*
+ * Parse the manifest for any memory regions that the SP wants to be
+ * mapped in its translation regime.
+ */
+ node = fdt_subnode_offset_namelen(sp_manifest, offset,
+ "memory-regions",
+ sizeof("memory-regions") - 1);
+ if (node < 0) {
+ WARN("Not found memory-region configuration for SP.\n");
+ } else {
+ populate_sp_regions(sp, sp_manifest, node,
+ SP_MEM_REGION_MEMORY);
+ }
+
+ spmc_el0_sp_setup_system_registers(sp, ctx);
+
+}
+#endif /* SPMC_AT_EL3_SEL0_SP */
+
/* S-EL1 partition specific initialisation. */
void spmc_el1_sp_setup(struct secure_partition_desc *sp,
entry_point_info_t *ep_info)
@@ -211,12 +528,6 @@
sp->sp_id = sp_id;
}
- /*
- * We currently only support S-EL1 partitions so ensure this is the
- * case.
- */
- assert(sp->runtime_el == S_EL1);
-
/* Check if the SP wants to use the FF-A boot protocol. */
if (boot_info_reg >= 0) {
/*