diff options
Diffstat (limited to 'meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0')
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 |