summaryrefslogtreecommitdiff
path: root/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0
diff options
context:
space:
mode:
Diffstat (limited to 'meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0')
-rw-r--r--meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0005-core-arm-S-EL1-SPMC-boot-ABI-update.patch91
-rw-r--r--meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0006-core-ffa-add-TOS_FW_CONFIG-handling.patch249
-rw-r--r--meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0007-core-spmc-handle-non-secure-interrupts.patch279
-rw-r--r--meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0008-core-spmc-configure-SP-s-NS-interrupt-action-based-o.patch150
4 files changed, 769 insertions, 0 deletions
diff --git a/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0005-core-arm-S-EL1-SPMC-boot-ABI-update.patch b/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0005-core-arm-S-EL1-SPMC-boot-ABI-update.patch
new file mode 100644
index 0000000000..4313a829ac
--- /dev/null
+++ b/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0005-core-arm-S-EL1-SPMC-boot-ABI-update.patch
@@ -0,0 +1,91 @@
+From 11f4ea86579bc1a58e4adde2849326f4213694f2 Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Mon, 21 Nov 2022 18:17:33 +0100
+Subject: core: arm: S-EL1 SPMC: boot ABI update
+
+Updates the boot ABI for S-EL1 SPMC to align better with other SPMCs,
+like Hafnium, but also with the non-FF-A configuration.
+
+Register usage:
+X0 - TOS FW config [1] address, if not NULL
+X2 - System DTB, if not NULL
+
+Adds check in the default get_aslr_seed() to see if the system DTB is
+present before trying to read kaslr-seed from secure-chosen.
+
+Note that this is an incompatible change and requires corresponding
+change in TF-A ("feat(qemu): update abi between spmd and spmc") [2].
+
+[1] A TF-A concept: TOS_FW_CONFIG - Trusted OS Firmware configuration
+ file. Used by Trusted OS (BL32), that is, OP-TEE in this case
+Link: [2] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=25ae7ad1878244f78206cc7c91f7bdbd267331a1
+
+Upstream-Status: Accepted
+
+Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+---
+ core/arch/arm/kernel/boot.c | 8 +++++++-
+ core/arch/arm/kernel/entry_a64.S | 17 ++++++++---------
+ 2 files changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/core/arch/arm/kernel/boot.c b/core/arch/arm/kernel/boot.c
+index dd34173e8..e02c02b60 100644
+--- a/core/arch/arm/kernel/boot.c
++++ b/core/arch/arm/kernel/boot.c
+@@ -1502,11 +1502,17 @@ struct ns_entry_context *boot_core_hpen(void)
+ #if defined(CFG_DT)
+ unsigned long __weak get_aslr_seed(void *fdt)
+ {
+- int rc = fdt_check_header(fdt);
++ int rc = 0;
+ const uint64_t *seed = NULL;
+ int offs = 0;
+ int len = 0;
+
++ if (!fdt) {
++ DMSG("No fdt");
++ goto err;
++ }
++
++ rc = fdt_check_header(fdt);
+ if (rc) {
+ DMSG("Bad fdt: %d", rc);
+ goto err;
+diff --git a/core/arch/arm/kernel/entry_a64.S b/core/arch/arm/kernel/entry_a64.S
+index 4c6e9d75c..047ae1f25 100644
+--- a/core/arch/arm/kernel/entry_a64.S
++++ b/core/arch/arm/kernel/entry_a64.S
+@@ -143,21 +143,20 @@
+ .endm
+
+ FUNC _start , :
+-#if defined(CFG_CORE_SEL1_SPMC)
+ /*
+- * With OP-TEE as SPMC at S-EL1 the SPMD (SPD_spmd) in TF-A passes
+- * the DTB in x0, pagaeble part in x1 and the rest of the registers
+- * are unused
++ * If CFG_CORE_FFA is enabled, then x0 if non-NULL holds the TOS FW
++ * config [1] address, else x0 if non-NULL holds the pagable part
++ * address.
++ *
++ * [1] A TF-A concept: TOS_FW_CONFIG - Trusted OS Firmware
++ * configuration file. Used by Trusted OS (BL32), that is, OP-TEE
++ * here.
+ */
+- mov x19, x1 /* Save pagable part */
+- mov x20, x0 /* Save DT address */
+-#else
+- mov x19, x0 /* Save pagable part address */
++ mov x19, x0
+ #if defined(CFG_DT_ADDR)
+ ldr x20, =CFG_DT_ADDR
+ #else
+ mov x20, x2 /* Save DT address */
+-#endif
+ #endif
+
+ adr x0, reset_vect_table
+--
+2.39.1.windows.1
+
diff --git a/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0006-core-ffa-add-TOS_FW_CONFIG-handling.patch b/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0006-core-ffa-add-TOS_FW_CONFIG-handling.patch
new file mode 100644
index 0000000000..add39076fd
--- /dev/null
+++ b/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0006-core-ffa-add-TOS_FW_CONFIG-handling.patch
@@ -0,0 +1,249 @@
+From 84f4ef4c4f2f45e2f54597f1afe80d8f8396cc57 Mon Sep 17 00:00:00 2001
+From: Balint Dobszay <balint.dobszay@arm.com>
+Date: Fri, 10 Feb 2023 11:07:27 +0100
+Subject: core: ffa: add TOS_FW_CONFIG handling
+
+At boot TF-A passes two DT addresses (HW_CONFIG and TOS_FW_CONFIG), but
+currently only the HW_CONFIG address is saved, the other one is dropped.
+This commit adds functionality to save the TOS_FW_CONFIG too, so we can
+retrieve it later. This is necessary for the CFG_CORE_SEL1_SPMC use
+case, because the SPMC manifest is passed in this DT.
+
+Upstream-Status: Accepted
+
+Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
+---
+ core/arch/arm/kernel/boot.c | 60 ++++++++++++++++++++++-
+ core/arch/arm/kernel/entry_a32.S | 3 +-
+ core/arch/arm/kernel/entry_a64.S | 13 ++++-
+ core/arch/arm/kernel/link_dummies_paged.c | 4 +-
+ core/arch/arm/kernel/secure_partition.c | 2 +-
+ core/include/kernel/boot.h | 7 ++-
+ 6 files changed, 81 insertions(+), 8 deletions(-)
+
+diff --git a/core/arch/arm/kernel/boot.c b/core/arch/arm/kernel/boot.c
+index e02c02b60..98e13c072 100644
+--- a/core/arch/arm/kernel/boot.c
++++ b/core/arch/arm/kernel/boot.c
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: BSD-2-Clause
+ /*
+ * Copyright (c) 2015-2022, Linaro Limited
++ * Copyright (c) 2023, Arm Limited
+ */
+
+ #include <arm.h>
+@@ -83,6 +84,9 @@ struct dt_descriptor {
+ };
+
+ static struct dt_descriptor external_dt __nex_bss;
++#ifdef CFG_CORE_SEL1_SPMC
++static struct dt_descriptor tos_fw_config_dt __nex_bss;
++#endif
+ #endif
+
+ #ifdef CFG_SECONDARY_INIT_CNTFRQ
+@@ -1224,6 +1228,54 @@ static struct core_mmu_phys_mem *get_nsec_memory(void *fdt __unused,
+ #endif /*CFG_CORE_DYN_SHM*/
+ #endif /*!CFG_DT*/
+
++#if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_DT)
++void *get_tos_fw_config_dt(void)
++{
++ if (!IS_ENABLED(CFG_MAP_EXT_DT_SECURE))
++ return NULL;
++
++ assert(cpu_mmu_enabled());
++
++ return tos_fw_config_dt.blob;
++}
++
++static void init_tos_fw_config_dt(unsigned long pa)
++{
++ struct dt_descriptor *dt = &tos_fw_config_dt;
++ void *fdt = NULL;
++ int ret = 0;
++
++ if (!IS_ENABLED(CFG_MAP_EXT_DT_SECURE))
++ return;
++
++ if (!pa)
++ panic("No TOS_FW_CONFIG DT found");
++
++ fdt = core_mmu_add_mapping(MEM_AREA_EXT_DT, pa, CFG_DTB_MAX_SIZE);
++ if (!fdt)
++ panic("Failed to map TOS_FW_CONFIG DT");
++
++ dt->blob = fdt;
++
++ ret = fdt_open_into(fdt, fdt, CFG_DTB_MAX_SIZE);
++ if (ret < 0) {
++ EMSG("Invalid Device Tree at %#lx: error %d", pa, ret);
++ panic();
++ }
++
++ IMSG("TOS_FW_CONFIG DT found");
++}
++#else
++void *get_tos_fw_config_dt(void)
++{
++ return NULL;
++}
++
++static void init_tos_fw_config_dt(unsigned long pa __unused)
++{
++}
++#endif /*CFG_CORE_SEL1_SPMC && CFG_DT*/
++
+ #ifdef CFG_CORE_DYN_SHM
+ static void discover_nsec_memory(void)
+ {
+@@ -1361,10 +1413,16 @@ static bool cpu_nmfi_enabled(void)
+ * Note: this function is weak just to make it possible to exclude it from
+ * the unpaged area.
+ */
+-void __weak boot_init_primary_late(unsigned long fdt)
++void __weak boot_init_primary_late(unsigned long fdt,
++ unsigned long tos_fw_config)
+ {
+ init_external_dt(fdt);
++ init_tos_fw_config_dt(tos_fw_config);
++#ifdef CFG_CORE_SEL1_SPMC
++ tpm_map_log_area(get_tos_fw_config_dt());
++#else
+ tpm_map_log_area(get_external_dt());
++#endif
+ discover_nsec_memory();
+ update_external_dt();
+ configure_console_from_dt();
+diff --git a/core/arch/arm/kernel/entry_a32.S b/core/arch/arm/kernel/entry_a32.S
+index 0f14ca2f6..3758fd8b7 100644
+--- a/core/arch/arm/kernel/entry_a32.S
++++ b/core/arch/arm/kernel/entry_a32.S
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: BSD-2-Clause */
+ /*
+ * Copyright (c) 2014, Linaro Limited
+- * Copyright (c) 2021, Arm Limited
++ * Copyright (c) 2021-2023, Arm Limited
+ */
+
+ #include <arm32_macros.S>
+@@ -560,6 +560,7 @@ shadow_stack_access_ok:
+ str r0, [r8, #THREAD_CORE_LOCAL_FLAGS]
+ #endif
+ mov r0, r6 /* DT address */
++ mov r1, #0 /* unused */
+ bl boot_init_primary_late
+ #ifndef CFG_VIRTUALIZATION
+ mov r0, #THREAD_CLF_TMP
+diff --git a/core/arch/arm/kernel/entry_a64.S b/core/arch/arm/kernel/entry_a64.S
+index 047ae1f25..fa76437fb 100644
+--- a/core/arch/arm/kernel/entry_a64.S
++++ b/core/arch/arm/kernel/entry_a64.S
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: BSD-2-Clause */
+ /*
+ * Copyright (c) 2015-2022, Linaro Limited
+- * Copyright (c) 2021, Arm Limited
++ * Copyright (c) 2021-2023, Arm Limited
+ */
+
+ #include <platform_config.h>
+@@ -320,7 +320,11 @@ clear_nex_bss:
+ bl core_mmu_set_default_prtn_tbl
+ #endif
+
++#ifdef CFG_CORE_SEL1_SPMC
++ mov x0, xzr /* pager not used */
++#else
+ mov x0, x19 /* pagable part address */
++#endif
+ mov x1, #-1
+ bl boot_init_primary_early
+
+@@ -337,7 +341,12 @@ clear_nex_bss:
+ mov x22, x0
+ str wzr, [x22, #THREAD_CORE_LOCAL_FLAGS]
+ #endif
+- mov x0, x20 /* DT address */
++ mov x0, x20 /* DT address also known as HW_CONFIG */
++#ifdef CFG_CORE_SEL1_SPMC
++ mov x1, x19 /* TOS_FW_CONFIG DT address */
++#else
++ mov x1, xzr /* unused */
++#endif
+ bl boot_init_primary_late
+ #ifdef CFG_CORE_PAUTH
+ init_pauth_per_cpu
+diff --git a/core/arch/arm/kernel/link_dummies_paged.c b/core/arch/arm/kernel/link_dummies_paged.c
+index 3b8287e06..023a5f3f5 100644
+--- a/core/arch/arm/kernel/link_dummies_paged.c
++++ b/core/arch/arm/kernel/link_dummies_paged.c
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: BSD-2-Clause
+ /*
+ * Copyright (c) 2017-2021, Linaro Limited
++ * Copyright (c) 2023, Arm Limited
+ */
+ #include <compiler.h>
+ #include <initcall.h>
+@@ -27,7 +28,8 @@ void __section(".text.dummy.call_finalcalls") call_finalcalls(void)
+ }
+
+ void __section(".text.dummy.boot_init_primary_late")
+-boot_init_primary_late(unsigned long fdt __unused)
++boot_init_primary_late(unsigned long fdt __unused,
++ unsigned long tos_fw_config __unused)
+ {
+ }
+
+diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c
+index 1d36e90b1..d386f1e4d 100644
+--- a/core/arch/arm/kernel/secure_partition.c
++++ b/core/arch/arm/kernel/secure_partition.c
+@@ -1212,7 +1212,7 @@ static TEE_Result fip_sp_map_all(void)
+ int subnode = 0;
+ int root = 0;
+
+- fdt = get_external_dt();
++ fdt = get_tos_fw_config_dt();
+ if (!fdt) {
+ EMSG("No SPMC manifest found");
+ return TEE_ERROR_GENERIC;
+diff --git a/core/include/kernel/boot.h b/core/include/kernel/boot.h
+index 260854473..941e093b2 100644
+--- a/core/include/kernel/boot.h
++++ b/core/include/kernel/boot.h
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: BSD-2-Clause */
+ /*
+ * Copyright (c) 2015-2020, Linaro Limited
+- * Copyright (c) 2021, Arm Limited
++ * Copyright (c) 2021-2023, Arm Limited
+ */
+ #ifndef __KERNEL_BOOT_H
+ #define __KERNEL_BOOT_H
+@@ -46,7 +46,7 @@ extern const struct core_mmu_config boot_mmu_config;
+ /* @nsec_entry is unused if using CFG_WITH_ARM_TRUSTED_FW */
+ void boot_init_primary_early(unsigned long pageable_part,
+ unsigned long nsec_entry);
+-void boot_init_primary_late(unsigned long fdt);
++void boot_init_primary_late(unsigned long fdt, unsigned long tos_fw_config);
+ void boot_init_memtag(void);
+
+ void __panic_at_smc_return(void) __noreturn;
+@@ -103,6 +103,9 @@ void *get_embedded_dt(void);
+ /* Returns external DTB if present, otherwise NULL */
+ void *get_external_dt(void);
+
++/* Returns TOS_FW_CONFIG DTB if present, otherwise NULL */
++void *get_tos_fw_config_dt(void);
++
+ /*
+ * get_aslr_seed() - return a random seed for core ASLR
+ * @fdt: Pointer to a device tree if CFG_DT_ADDR=y
+--
+2.39.1.windows.1
+
diff --git a/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0007-core-spmc-handle-non-secure-interrupts.patch b/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0007-core-spmc-handle-non-secure-interrupts.patch
new file mode 100644
index 0000000000..a0377abafe
--- /dev/null
+++ b/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0007-core-spmc-handle-non-secure-interrupts.patch
@@ -0,0 +1,279 @@
+From f4b4f5bccc1be9a709008cc8e6107302745796c8 Mon Sep 17 00:00:00 2001
+From: Imre Kis <imre.kis@arm.com>
+Date: Tue, 18 Apr 2023 16:41:51 +0200
+Subject: [PATCH] core: spmc: handle non-secure interrupts
+
+Add FFA_INTERRUPT and FFA_RUN support for signaling non-secure
+interrupts and for resuming to the secure world. If a secure partition
+is preempted by a non-secure interrupt OP-TEE saves the SP's state and
+sends an FFA_INTERRUPT to the normal world. After handling the interrupt
+the normal world should send an FFA_RUN to OP-TEE so it can continue
+running the SP.
+If OP-TEE is the active FF-A endpoint (i.e. it is running TAs) the
+non-secure interrupts are signaled by the existing
+OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT message instead of
+FFA_INTERRUPT.
+
+Upstream-Status: Pending
+
+Signed-off-by: Imre Kis <imre.kis@arm.com>
+Change-Id: I577ebe86d416ee494963216a66a3bfc8206921b4
+
+---
+ core/arch/arm/include/ffa.h | 2 +-
+ .../arch/arm/include/kernel/spmc_sp_handler.h | 11 +++++++
+ core/arch/arm/kernel/secure_partition.c | 17 ++++++++++
+ core/arch/arm/kernel/spmc_sp_handler.c | 26 ++++++++++++++++
+ core/arch/arm/kernel/thread.c | 7 +++++
+ core/arch/arm/kernel/thread_spmc.c | 31 ++++++++++++++++++-
+ core/arch/arm/kernel/thread_spmc_a64.S | 30 ++++++++++++++++++
+ 7 files changed, 122 insertions(+), 2 deletions(-)
+
+diff --git a/core/arch/arm/include/ffa.h b/core/arch/arm/include/ffa.h
+index 5a19fb0c..b3d1d354 100644
+--- a/core/arch/arm/include/ffa.h
++++ b/core/arch/arm/include/ffa.h
+@@ -50,7 +50,7 @@
+ #define FFA_ID_GET U(0x84000069)
+ #define FFA_MSG_WAIT U(0x8400006B)
+ #define FFA_MSG_YIELD U(0x8400006C)
+-#define FFA_MSG_RUN U(0x8400006D)
++#define FFA_RUN U(0x8400006D)
+ #define FFA_MSG_SEND U(0x8400006E)
+ #define FFA_MSG_SEND_DIRECT_REQ_32 U(0x8400006F)
+ #define FFA_MSG_SEND_DIRECT_REQ_64 U(0xC400006F)
+diff --git a/core/arch/arm/include/kernel/spmc_sp_handler.h b/core/arch/arm/include/kernel/spmc_sp_handler.h
+index f5bda7bf..30c1e469 100644
+--- a/core/arch/arm/include/kernel/spmc_sp_handler.h
++++ b/core/arch/arm/include/kernel/spmc_sp_handler.h
+@@ -25,6 +25,8 @@ void spmc_sp_start_thread(struct thread_smc_args *args);
+ int spmc_sp_add_share(struct ffa_rxtx *rxtx,
+ size_t blen, uint64_t *global_handle,
+ struct sp_session *owner_sp);
++void spmc_sp_set_to_preempted(struct ts_session *ts_sess);
++int spmc_sp_resume_from_preempted(uint16_t endpoint_id);
+ #else
+ static inline void spmc_sp_start_thread(struct thread_smc_args *args __unused)
+ {
+@@ -37,6 +39,15 @@ static inline int spmc_sp_add_share(struct ffa_rxtx *rxtx __unused,
+ {
+ return FFA_NOT_SUPPORTED;
+ }
++
++static inline void spmc_sp_set_to_preempted(struct ts_session *ts_sess __unused)
++{
++}
++
++static inline int spmc_sp_resume_from_preempted(uint16_t endpoint_id __unused)
++{
++ return FFA_NOT_SUPPORTED;
++}
+ #endif
+
+ #endif /* __KERNEL_SPMC_SP_HANDLER_H */
+diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c
+index 1d36e90b..6e351e43 100644
+--- a/core/arch/arm/kernel/secure_partition.c
++++ b/core/arch/arm/kernel/secure_partition.c
+@@ -999,6 +999,8 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
+ struct sp_session *sp_s = to_sp_session(s);
+ struct ts_session *sess = NULL;
+ struct thread_ctx_regs *sp_regs = NULL;
++ uint32_t thread_id = THREAD_ID_INVALID;
++ uint32_t rpc_target_info = 0;
+ uint32_t panicked = false;
+ uint32_t panic_code = 0;
+
+@@ -1011,8 +1013,23 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
+ sp_regs->cpsr = read_daif() & (SPSR_64_DAIF_MASK << SPSR_64_DAIF_SHIFT);
+
+ exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
++
++ /*
++ * Store endpoint ID and thread ID in rpc_target_info. This will be used
++ * as w1 in FFA_INTERRUPT in case of a NWd interrupt.
++ */
++ rpc_target_info = thread_get_tsd()->rpc_target_info;
++ thread_id = thread_get_id();
++ assert((thread_id & ~0xffff) == 0);
++ thread_get_tsd()->rpc_target_info = (sp_s->endpoint_id << 16) |
++ (thread_id & 0xffff);
++
+ __thread_enter_user_mode(sp_regs, &panicked, &panic_code);
++
+ sp_regs->cpsr = cpsr;
++ /* Restore rpc_target_info */
++ thread_get_tsd()->rpc_target_info = rpc_target_info;
++
+ thread_unmask_exceptions(exceptions);
+
+ thread_user_clear_vfp(&ctx->uctx);
+diff --git a/core/arch/arm/kernel/spmc_sp_handler.c b/core/arch/arm/kernel/spmc_sp_handler.c
+index 5d3326fc..f4c7ff81 100644
+--- a/core/arch/arm/kernel/spmc_sp_handler.c
++++ b/core/arch/arm/kernel/spmc_sp_handler.c
+@@ -366,6 +366,32 @@ cleanup:
+ return res;
+ }
+
++void spmc_sp_set_to_preempted(struct ts_session *ts_sess)
++{
++ if (ts_sess && is_sp_ctx(ts_sess->ctx)) {
++ struct sp_session *sp_sess = to_sp_session(ts_sess);
++
++ assert(sp_sess->state == sp_busy);
++
++ sp_sess->state = sp_preempted;
++ }
++}
++
++int spmc_sp_resume_from_preempted(uint16_t endpoint_id)
++{
++ struct sp_session *sp_sess = sp_get_session(endpoint_id);
++
++ if (!sp_sess)
++ return FFA_INVALID_PARAMETERS;
++
++ if (sp_sess->state != sp_preempted)
++ return FFA_DENIED;
++
++ sp_sess->state = sp_busy;
++
++ return FFA_OK;
++}
++
+ static bool check_rxtx(struct ffa_rxtx *rxtx)
+ {
+ return rxtx && rxtx->rx && rxtx->tx && rxtx->size > 0;
+diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c
+index 1e7f9f96..8cd4dc96 100644
+--- a/core/arch/arm/kernel/thread.c
++++ b/core/arch/arm/kernel/thread.c
+@@ -531,6 +531,13 @@ int thread_state_suspend(uint32_t flags, uint32_t cpsr, vaddr_t pc)
+ core_mmu_set_user_map(NULL);
+ }
+
++ if (IS_ENABLED(CFG_SECURE_PARTITION)) {
++ struct ts_session *ts_sess =
++ TAILQ_FIRST(&threads[ct].tsd.sess_stack);
++
++ spmc_sp_set_to_preempted(ts_sess);
++ }
++
+ l->curr_thread = THREAD_ID_INVALID;
+
+ if (IS_ENABLED(CFG_VIRTUALIZATION))
+diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
+index 3b4ac0b4..bc4e7687 100644
+--- a/core/arch/arm/kernel/thread_spmc.c
++++ b/core/arch/arm/kernel/thread_spmc.c
+@@ -45,7 +45,7 @@ struct mem_frag_state {
+ #endif
+
+ /* Initialized in spmc_init() below */
+-static uint16_t my_endpoint_id;
++uint16_t my_endpoint_id;
+
+ /*
+ * If struct ffa_rxtx::size is 0 RX/TX buffers are not mapped or initialized.
+@@ -437,6 +437,32 @@ out:
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+ cpu_spin_unlock(&rxtx->spinlock);
+ }
++
++static void spmc_handle_run(struct thread_smc_args *args)
++{
++ uint16_t endpoint = (args->a1 >> 16) & 0xffff;
++ uint16_t thread_id = (args->a1 & 0xffff);
++ uint32_t rc = 0;
++
++ if (endpoint != my_endpoint_id) {
++ /*
++ * The endpoint should be an SP, try to resume the SP from
++ * preempted into busy state.
++ */
++ rc = spmc_sp_resume_from_preempted(endpoint);
++ if (rc)
++ goto out;
++ }
++
++ thread_resume_from_rpc(thread_id, 0, 0, 0, 0);
++
++ /* thread_resume_from_rpc return only of the thread_id is invalid */
++ rc = FFA_INVALID_PARAMETERS;
++
++out:
++ spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ,
++ FFA_PARAM_MBZ, FFA_PARAM_MBZ);
++}
+ #endif /*CFG_CORE_SEL1_SPMC*/
+
+ static void handle_yielding_call(struct thread_smc_args *args)
+@@ -970,6 +996,9 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
+ case FFA_PARTITION_INFO_GET:
+ spmc_handle_partition_info_get(args, &nw_rxtx);
+ break;
++ case FFA_RUN:
++ spmc_handle_run(args);
++ break;
+ #endif /*CFG_CORE_SEL1_SPMC*/
+ case FFA_INTERRUPT:
+ itr_core_handler();
+diff --git a/core/arch/arm/kernel/thread_spmc_a64.S b/core/arch/arm/kernel/thread_spmc_a64.S
+index 21cb6251..7297005a 100644
+--- a/core/arch/arm/kernel/thread_spmc_a64.S
++++ b/core/arch/arm/kernel/thread_spmc_a64.S
+@@ -14,6 +14,20 @@
+ #include <kernel/thread.h>
+ #include <optee_ffa.h>
+
++#if CFG_SECURE_PARTITION
++LOCAL_FUNC thread_ffa_interrupt , :
++ mov_imm x0, FFA_INTERRUPT /* FID */
++ /* X1: Endpoint/vCPU IDs is set by caller */
++ mov x2, #FFA_PARAM_MBZ /* Param MBZ */
++ mov x3, #FFA_PARAM_MBZ /* Param MBZ */
++ mov x4, #FFA_PARAM_MBZ /* Param MBZ */
++ mov x5, #FFA_PARAM_MBZ /* Param MBZ */
++ mov x6, #FFA_PARAM_MBZ /* Param MBZ */
++ mov x7, #FFA_PARAM_MBZ /* Param MBZ */
++ b .ffa_msg_loop
++END_FUNC thread_ffa_msg_wait
++#endif /* CFG_SECURE_PARTITION */
++
+ FUNC thread_ffa_msg_wait , :
+ mov_imm x0, FFA_MSG_WAIT /* FID */
+ mov x1, #FFA_TARGET_INFO_MBZ /* Target info MBZ */
+@@ -171,6 +185,14 @@ END_FUNC thread_rpc
+ * The current thread as indicated by @thread_index has just been
+ * suspended. The job here is just to inform normal world the thread id to
+ * resume when returning.
++ * If the active FF-A endpoint is OP-TEE (or a TA) then an this function send an
++ * OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT message to the normal world via the
++ * FFA_MSG_SEND_DIRECT_RESP interface. This is handled by the OP-TEE
++ * driver in Linux so it can schedule task to the thread.
++ * If the active endpoint is an SP the function sends an FFA_INTERRUPT. This is
++ * handled by the FF-A driver and after taking care of the NWd interrupts it
++ * returns via an FFA_RUN call.
++ * The active endpoint is determined by the upper 16 bits of rpc_target_info.
+ */
+ FUNC thread_foreign_intr_exit , :
+ /* load threads[w0].tsd.rpc_target_info into w1 */
+@@ -178,6 +200,14 @@ FUNC thread_foreign_intr_exit , :
+ adr_l x2, threads
+ madd x1, x1, x0, x2
+ ldr w1, [x1, #THREAD_CTX_TSD_RPC_TARGET_INFO]
++#if CFG_SECURE_PARTITION
++ adr_l x2, my_endpoint_id
++ ldrh w2, [x2]
++ lsr w3, w1, #16
++ cmp w2, w3
++ /* (threads[w0].tsd.rpc_target_info >> 16) != my_endpoint_id */
++ bne thread_ffa_interrupt
++#endif /* CFG_SECURE_PARTITION */
+ mov x2, #FFA_PARAM_MBZ
+ mov w3, #FFA_PARAM_MBZ
+ mov w4, #OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT
+
+--
+2.17.1
diff --git a/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0008-core-spmc-configure-SP-s-NS-interrupt-action-based-o.patch b/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0008-core-spmc-configure-SP-s-NS-interrupt-action-based-o.patch
new file mode 100644
index 0000000000..32e560689f
--- /dev/null
+++ b/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0008-core-spmc-configure-SP-s-NS-interrupt-action-based-o.patch
@@ -0,0 +1,150 @@
+From cad33cffb5be17fc0654aaf03c4d5227ae682e7a Mon Sep 17 00:00:00 2001
+From: Imre Kis <imre.kis@arm.com>
+Date: Tue, 25 Apr 2023 14:19:14 +0200
+Subject: [PATCH] core: spmc: configure SP's NS interrupt action based on
+ the manifest
+
+Used mandatory ns-interrupts-action SP manifest property to configure
+signaled or queued non-secure interrupt handling.
+
+Upstream-Status: Pending
+
+Signed-off-by: Imre Kis <imre.kis@arm.com>
+Change-Id: I843e69e5dbb9613ecd8b95654e8ca1730a594ca6
+---
+ .../arm/include/kernel/secure_partition.h | 2 +
+ core/arch/arm/kernel/secure_partition.c | 66 +++++++++++++++++--
+ 2 files changed, 63 insertions(+), 5 deletions(-)
+
+diff --git a/core/arch/arm/include/kernel/secure_partition.h b/core/arch/arm/include/kernel/secure_partition.h
+index 290750936..3bf339d3c 100644
+--- a/core/arch/arm/include/kernel/secure_partition.h
++++ b/core/arch/arm/include/kernel/secure_partition.h
+@@ -43,6 +43,8 @@ struct sp_session {
+ unsigned int spinlock;
+ const void *fdt;
+ bool is_initialized;
++ uint32_t ns_interrupts_action;
++ uint32_t ns_interrupts_action_inherited;
+ TAILQ_ENTRY(sp_session) link;
+ };
+
+diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c
+index 52365553b..e54069c17 100644
+--- a/core/arch/arm/kernel/secure_partition.c
++++ b/core/arch/arm/kernel/secure_partition.c
+@@ -46,6 +46,10 @@
+ SP_MANIFEST_ATTR_WRITE | \
+ SP_MANIFEST_ATTR_EXEC)
+
++#define SP_MANIFEST_NS_INT_QUEUED (0x0)
++#define SP_MANIFEST_NS_INT_MANAGED_EXIT (0x1)
++#define SP_MANIFEST_NS_INT_SIGNALED (0x2)
++
+ #define SP_PKG_HEADER_MAGIC (0x474b5053)
+ #define SP_PKG_HEADER_VERSION_V1 (0x1)
+ #define SP_PKG_HEADER_VERSION_V2 (0x2)
+@@ -907,6 +911,30 @@ static TEE_Result sp_init_uuid(const TEE_UUID *uuid, const void * const fdt)
+ return res;
+ DMSG("endpoint is 0x%"PRIx16, sess->endpoint_id);
+
++ res = sp_dt_get_u32(fdt, 0, "ns-interrupts-action",
++ &sess->ns_interrupts_action);
++
++ if (res) {
++ EMSG("Mandatory property is missing: ns-interrupts-action");
++ return res;
++ }
++
++ switch (sess->ns_interrupts_action) {
++ case SP_MANIFEST_NS_INT_QUEUED:
++ case SP_MANIFEST_NS_INT_SIGNALED:
++ /* OK */
++ break;
++
++ case SP_MANIFEST_NS_INT_MANAGED_EXIT:
++ EMSG("Managed exit is not implemented");
++ return TEE_ERROR_NOT_IMPLEMENTED;
++
++ default:
++ EMSG("Invalid ns-interrupts-action value: %d",
++ sess->ns_interrupts_action);
++ return TEE_ERROR_BAD_PARAMETERS;
++ }
++
+ return TEE_SUCCESS;
+ }
+
+@@ -989,17 +1017,45 @@ TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp)
+ return res;
+ }
+
++/*
++ * According to FF-A v1.1 section 8.3.1.4 if a caller requires less permissive
++ * active on NS interrupt than the callee, the callee must inherit the caller's
++ * configuration.
++ * Each SP's own NS action setting is stored in ns_interrupts_action. The
++ * effective action will be MIN([self action], [caller's action]) which is
++ * stored in the ns_interrupts_action_inherited field.
++ */
++static void sp_cpsr_configure_foreing_interrupts(struct sp_session *s,
++ struct ts_session *caller,
++ uint64_t *cpsr)
++{
++ if (caller) {
++ struct sp_session *caller_sp = to_sp_session(caller);
++
++ s->ns_interrupts_action_inherited =
++ MIN(caller_sp->ns_interrupts_action_inherited,
++ s->ns_interrupts_action);
++ } else {
++ s->ns_interrupts_action_inherited = s->ns_interrupts_action;
++ }
++
++ if (s->ns_interrupts_action_inherited == SP_MANIFEST_NS_INT_QUEUED)
++ *cpsr |= (THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT);
++ else
++ *cpsr &= ~(THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT);
++}
++
+ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
+ uint32_t cmd __unused)
+ {
+ struct sp_ctx *ctx = to_sp_ctx(s->ctx);
+ TEE_Result res = TEE_SUCCESS;
+ uint32_t exceptions = 0;
+- uint64_t cpsr = 0;
+ struct sp_session *sp_s = to_sp_session(s);
+ struct ts_session *sess = NULL;
+ struct thread_ctx_regs *sp_regs = NULL;
+ uint32_t thread_id = THREAD_ID_INVALID;
++ struct ts_session *caller = NULL;
+ uint32_t rpc_target_info = 0;
+ uint32_t panicked = false;
+ uint32_t panic_code = 0;
+@@ -1009,11 +1065,12 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
+ sp_regs = &ctx->sp_regs;
+ ts_push_current_session(s);
+
+- cpsr = sp_regs->cpsr;
+- sp_regs->cpsr = read_daif() & (SPSR_64_DAIF_MASK << SPSR_64_DAIF_SHIFT);
+-
+ exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
+
++ /* Enable/disable foreign interrupts in CPSR/SPSR */
++ caller = ts_get_calling_session();
++ sp_cpsr_configure_foreing_interrupts(sp_s, caller, &sp_regs->cpsr);
++
+ /*
+ * Store endpoint ID and thread ID in rpc_target_info. This will be used
+ * as w1 in FFA_INTERRUPT in case of a NWd interrupt.
+@@ -1026,7 +1083,6 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
+
+ __thread_enter_user_mode(sp_regs, &panicked, &panic_code);
+
+- sp_regs->cpsr = cpsr;
+ /* Restore rpc_target_info */
+ thread_get_tsd()->rpc_target_info = rpc_target_info;
+
+--
+2.17.1