Initial commit

This commit is contained in:
Your Name
2026-04-23 17:07:55 +08:00
commit b7e39e063b
16725 changed files with 1625565 additions and 0 deletions
@@ -0,0 +1,34 @@
From 843eb2ef918d5ae3d09de088110cb026ca25306b Mon Sep 17 00:00:00 2001
From: Ross Burton <ross.burton@arm.com>
Date: Tue, 26 May 2020 14:38:02 -0500
Subject: [PATCH] allow setting sysroot for libgcc lookup
Explicitly pass the new variable LIBGCC_LOCATE_CFLAGS variable when searching
for the compiler libraries as there's no easy way to reliably pass --sysroot
otherwise.
Upstream-Status: Pending [https://github.com/OP-TEE/optee_os/issues/4188]
Signed-off-by: Ross Burton <ross.burton@arm.com>
---
mk/gcc.mk | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/mk/gcc.mk b/mk/gcc.mk
index adc77a24f25e..81bfa78ad8d7 100644
--- a/mk/gcc.mk
+++ b/mk/gcc.mk
@@ -13,11 +13,11 @@ nostdinc$(sm) := -nostdinc -isystem $(shell $(CC$(sm)) \
-print-file-name=include 2> /dev/null)
# Get location of libgcc from gcc
-libgcc$(sm) := $(shell $(CC$(sm)) $(CFLAGS$(arch-bits-$(sm))) \
+libgcc$(sm) := $(shell $(CC$(sm)) $(LIBGCC_LOCATE_CFLAGS) $(CFLAGS$(arch-bits-$(sm))) \
-print-libgcc-file-name 2> /dev/null)
-libstdc++$(sm) := $(shell $(CXX$(sm)) $(CXXFLAGS$(arch-bits-$(sm))) $(comp-cxxflags$(sm)) \
+libstdc++$(sm) := $(shell $(CXX$(sm)) $(LIBGCC_LOCATE_CFLAGS) $(CXXFLAGS$(arch-bits-$(sm))) $(comp-cxxflags$(sm)) \
-print-file-name=libstdc++.a 2> /dev/null)
-libgcc_eh$(sm) := $(shell $(CXX$(sm)) $(CXXFLAGS$(arch-bits-$(sm))) $(comp-cxxflags$(sm)) \
+libgcc_eh$(sm) := $(shell $(CXX$(sm)) $(LIBGCC_LOCATE_CFLAGS) $(CXXFLAGS$(arch-bits-$(sm))) $(comp-cxxflags$(sm)) \
-print-file-name=libgcc_eh.a 2> /dev/null)
# Define these to something to discover accidental use
@@ -0,0 +1,29 @@
From 0ca5ef7c8256dbd9690a01a82397bc16a123e179 Mon Sep 17 00:00:00 2001
From: Brett Warren <brett.warren@arm.com>
Date: Wed, 23 Sep 2020 09:27:34 +0100
Subject: [PATCH] optee: enable clang support
When compiling with clang, the LIBGCC_LOCATE_CFLAG variable used
to provide a sysroot wasn't included, which results in not locating
compiler-rt. This is mitigated by including the variable as ammended.
Upstream-Status: Pending
ChangeId: 8ba69a4b2eb8ebaa047cb266c9aa6c2c3da45701
Signed-off-by: Brett Warren <brett.warren@arm.com>
---
mk/clang.mk | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mk/clang.mk b/mk/clang.mk
index a045beee8482..1ebe2f702dcd 100644
--- a/mk/clang.mk
+++ b/mk/clang.mk
@@ -30,7 +30,7 @@ comp-cflags-warns-clang := -Wno-language-extension-token \
# Note, use the compiler runtime library (libclang_rt.builtins.*.a) instead of
# libgcc for clang
-libgcc$(sm) := $(shell $(CC$(sm)) $(CFLAGS$(arch-bits-$(sm))) \
+libgcc$(sm) := $(shell $(CC$(sm)) $(LIBGCC_LOCATE_CFLAGS) $(CFLAGS$(arch-bits-$(sm))) \
-rtlib=compiler-rt -print-libgcc-file-name 2> /dev/null)
# Core ASLR relies on the executable being ready to run from its preferred load
@@ -0,0 +1,62 @@
From 741df4df0ec7b69b0573cff265dc1ae7cb70b55c Mon Sep 17 00:00:00 2001
From: Jerome Forissier <jerome.forissier@linaro.org>
Date: Fri, 5 Aug 2022 09:48:03 +0200
Subject: [PATCH] core: link: add --no-warn-rwx-segments
Signed-off-by: Anton Antonov <Anton.Antonov@arm.com>
Upstream-Status: Backport [https://github.com/OP-TEE/optee_os/pull/5474]
binutils ld.bfd generates one RWX LOAD segment by merging several sections
with mixed R/W/X attributes (.text, .rodata, .data). After version 2.38 it
also warns by default when that happens [1], which breaks the build due to
--fatal-warnings. The RWX segment is not a problem for the TEE core, since
that information is not used to set memory permissions. Therefore, silence
the warning.
Link: [1] https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=ba951afb99912da01a6e8434126b8fac7aa75107
Link: https://sourceware.org/bugzilla/show_bug.cgi?id=29448
Reported-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
---
core/arch/arm/kernel/link.mk | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/core/arch/arm/kernel/link.mk b/core/arch/arm/kernel/link.mk
index 0e96e606cd9d..3fbcb6804c6f 100644
--- a/core/arch/arm/kernel/link.mk
+++ b/core/arch/arm/kernel/link.mk
@@ -37,6 +37,7 @@ link-ldflags += --sort-section=alignment
link-ldflags += --fatal-warnings
link-ldflags += --gc-sections
link-ldflags += $(link-ldflags-common)
+link-ldflags += $(call ld-option,--no-warn-rwx-segments)
link-ldadd = $(LDADD)
link-ldadd += $(ldflags-external)
@@ -61,6 +62,7 @@ link-script-cppflags := \
$(cppflagscore))
ldargs-all_objs := -T $(link-script-dummy) --no-check-sections \
+ $(call ld-option,--no-warn-rwx-segments) \
$(link-ldflags-common) \
$(link-objs) $(link-ldadd) $(libgcccore)
cleanfiles += $(link-out-dir)/all_objs.o
@@ -75,7 +77,7 @@ $(link-out-dir)/unpaged_entries.txt: $(link-out-dir)/all_objs.o
$(AWK) '/ ____keep_pager/ { printf "-u%s ", $$3 }' > $@
unpaged-ldargs := -T $(link-script-dummy) --no-check-sections --gc-sections \
- $(link-ldflags-common)
+ $(link-ldflags-common) $(call ld-option,--no-warn-rwx-segments)
unpaged-ldadd := $(objs) $(link-ldadd) $(libgcccore)
cleanfiles += $(link-out-dir)/unpaged.o
$(link-out-dir)/unpaged.o: $(link-out-dir)/unpaged_entries.txt
@@ -104,7 +106,7 @@ $(link-out-dir)/init_entries.txt: $(link-out-dir)/all_objs.o
$(AWK) '/ ____keep_init/ { printf "-u%s ", $$3 }' > $@
init-ldargs := -T $(link-script-dummy) --no-check-sections --gc-sections \
- $(link-ldflags-common)
+ $(link-ldflags-common) $(call ld-option,--no-warn-rwx-segments)
init-ldadd := $(link-objs-init) $(link-out-dir)/version.o $(link-ldadd) \
$(libgcccore)
cleanfiles += $(link-out-dir)/init.o
@@ -0,0 +1,240 @@
From 162493e5b212b9d7391669a55be09b69b97a9cf8 Mon Sep 17 00:00:00 2001
From: Emekcan Aras <emekcan.aras@arm.com>
Date: Wed, 21 Dec 2022 10:55:58 +0000
Subject: [PATCH] core: Define section attributes for clang
Clang's attribute section is not same as gcc, here we need to add flags
to sections so they can be eventually collected by linker into final
output segments. Only way to do so with clang is to use
pragma clang section ...
The behavious is described here [1], this allows us to define names bss
sections. This was not an issue until clang-15 where LLD linker starts
to detect the section flags before merging them and throws the following
errors
| ld.lld: error: section type mismatch for .nozi.kdata_page
| >>> /mnt/b/yoe/master/build/tmp/work/qemuarm64-yoe-linux/optee-os-tadevkit/3.17.0-r0/build/core/arch/arm/kernel/thread.o:(.nozi.kdata_page): SHT_PROGBITS
| >>> output section .nozi: SHT_NOBITS
|
| ld.lld: error: section type mismatch for .nozi.mmu.l2
| >>> /mnt/b/yoe/master/build/tmp/work/qemuarm64-yoe-linux/optee-os-tadevkit/3.17.0-r0/build/core/arch/arm/mm/core_mmu_lpae.o:(.nozi.mmu.l2): SHT_PROGBITS
| >>> output section .nozi: SHT_NOBITS
These sections should be carrying SHT_NOBITS but so far it was not
possible to do so, this patch tries to use clangs pragma to get this
going and match the functionality with gcc.
[1] https://intel.github.io/llvm-docs/clang/LanguageExtensions.html#specifying-section-names-for-global-objects-pragma-clang-section
Upstream-Status: Pending
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
core/arch/arm/kernel/thread.c | 19 +++++++++++++++--
core/arch/arm/mm/core_mmu_lpae.c | 35 +++++++++++++++++++++++++++----
core/arch/arm/mm/core_mmu_v7.c | 36 +++++++++++++++++++++++++++++---
core/arch/arm/mm/pgt_cache.c | 12 ++++++++++-
core/kernel/thread.c | 13 +++++++++++-
5 files changed, 104 insertions(+), 11 deletions(-)
diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c
index 1cf76a0ca690..1e7f9f96b558 100644
--- a/core/arch/arm/kernel/thread.c
+++ b/core/arch/arm/kernel/thread.c
@@ -44,15 +44,30 @@ static size_t thread_user_kcode_size __nex_bss;
#if defined(CFG_CORE_UNMAP_CORE_AT_EL0) && \
defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) && defined(ARM64)
long thread_user_kdata_sp_offset __nex_bss;
+#ifdef __clang__
+#ifndef CFG_VIRTUALIZATION
+#pragma clang section bss=".nozi.kdata_page"
+#else
+#pragma clang section bss=".nex_nozi.kdata_page"
+#endif
+#endif
static uint8_t thread_user_kdata_page[
ROUNDUP(sizeof(struct thread_core_local) * CFG_TEE_CORE_NB_CORE,
SMALL_PAGE_SIZE)]
__aligned(SMALL_PAGE_SIZE)
+#ifndef __clang__
#ifndef CFG_VIRTUALIZATION
- __section(".nozi.kdata_page");
+ __section(".nozi.kdata_page")
#else
- __section(".nex_nozi.kdata_page");
+ __section(".nex_nozi.kdata_page")
#endif
+#endif
+ ;
+#endif
+
+/* reset BSS section to default ( .bss ) */
+#ifdef __clang__
+#pragma clang section bss=""
#endif
#ifdef ARM32
diff --git a/core/arch/arm/mm/core_mmu_lpae.c b/core/arch/arm/mm/core_mmu_lpae.c
index 3f08eec623f3..e6dc9261c41e 100644
--- a/core/arch/arm/mm/core_mmu_lpae.c
+++ b/core/arch/arm/mm/core_mmu_lpae.c
@@ -233,19 +233,46 @@ typedef uint16_t l1_idx_t;
typedef uint64_t base_xlat_tbls_t[CFG_TEE_CORE_NB_CORE][NUM_BASE_LEVEL_ENTRIES];
typedef uint64_t xlat_tbl_t[XLAT_TABLE_ENTRIES];
+#ifdef __clang__
+#pragma clang section bss=".nozi.mmu.base_table"
+#endif
static base_xlat_tbls_t base_xlation_table[NUM_BASE_TABLES]
__aligned(NUM_BASE_LEVEL_ENTRIES * XLAT_ENTRY_SIZE)
- __section(".nozi.mmu.base_table");
+#ifndef __clang__
+ __section(".nozi.mmu.base_table")
+#endif
+;
+#ifdef __clang__
+#pragma clang section bss=""
+#endif
+#ifdef __clang__
+#pragma clang section bss=".nozi.mmu.l2"
+#endif
static xlat_tbl_t xlat_tables[MAX_XLAT_TABLES]
- __aligned(XLAT_TABLE_SIZE) __section(".nozi.mmu.l2");
+ __aligned(XLAT_TABLE_SIZE)
+#ifndef __clang__
+ __section(".nozi.mmu.l2")
+#endif
+;
+#ifdef __clang__
+#pragma clang section bss=""
+#endif
#define XLAT_TABLES_SIZE (sizeof(xlat_tbl_t) * MAX_XLAT_TABLES)
+#ifdef __clang__
+#pragma clang section bss=".nozi.mmu.l2"
+#endif
/* MMU L2 table for TAs, one for each thread */
static xlat_tbl_t xlat_tables_ul1[CFG_NUM_THREADS]
- __aligned(XLAT_TABLE_SIZE) __section(".nozi.mmu.l2");
-
+#ifndef __clang__
+ __aligned(XLAT_TABLE_SIZE) __section(".nozi.mmu.l2")
+#endif
+;
+#ifdef __clang__
+#pragma clang section bss=""
+#endif
/*
* TAs page table entry inside a level 1 page table.
*
diff --git a/core/arch/arm/mm/core_mmu_v7.c b/core/arch/arm/mm/core_mmu_v7.c
index cd85bd22d385..3e18f54f6cf8 100644
--- a/core/arch/arm/mm/core_mmu_v7.c
+++ b/core/arch/arm/mm/core_mmu_v7.c
@@ -204,16 +204,46 @@ typedef uint32_t l1_xlat_tbl_t[NUM_L1_ENTRIES];
typedef uint32_t l2_xlat_tbl_t[NUM_L2_ENTRIES];
typedef uint32_t ul1_xlat_tbl_t[NUM_UL1_ENTRIES];
+#ifdef __clang__
+#pragma clang section bss=".nozi.mmu.l1"
+#endif
static l1_xlat_tbl_t main_mmu_l1_ttb
- __aligned(L1_ALIGNMENT) __section(".nozi.mmu.l1");
+ __aligned(L1_ALIGNMENT)
+#ifndef __clang__
+ __section(".nozi.mmu.l1")
+#endif
+;
+#ifdef __clang__
+#pragma clang section bss=""
+#endif
/* L2 MMU tables */
+#ifdef __clang__
+#pragma clang section bss=".nozi.mmu.l2"
+#endif
static l2_xlat_tbl_t main_mmu_l2_ttb[MAX_XLAT_TABLES]
- __aligned(L2_ALIGNMENT) __section(".nozi.mmu.l2");
+ __aligned(L2_ALIGNMENT)
+#ifndef __clang__
+ __section(".nozi.mmu.l2")
+#endif
+;
+#ifdef __clang__
+#pragma clang section bss=""
+#endif
/* MMU L1 table for TAs, one for each thread */
+#ifdef __clang__
+#pragma clang section bss=".nozi.mmu.ul1"
+#endif
static ul1_xlat_tbl_t main_mmu_ul1_ttb[CFG_NUM_THREADS]
- __aligned(UL1_ALIGNMENT) __section(".nozi.mmu.ul1");
+ __aligned(UL1_ALIGNMENT)
+#ifndef __clang__
+ __section(".nozi.mmu.ul1")
+#endif
+;
+#ifdef __clang__
+#pragma clang section bss=""
+#endif
struct mmu_partition {
l1_xlat_tbl_t *l1_table;
diff --git a/core/arch/arm/mm/pgt_cache.c b/core/arch/arm/mm/pgt_cache.c
index 79553c6d2183..b9efdf42780b 100644
--- a/core/arch/arm/mm/pgt_cache.c
+++ b/core/arch/arm/mm/pgt_cache.c
@@ -410,8 +410,18 @@ void pgt_init(void)
* has a large alignment, while .bss has a small alignment. The current
* link script is optimized for small alignment in .bss
*/
+#ifdef __clang__
+#pragma clang section bss=".nozi.mmu.l2"
+#endif
static uint8_t pgt_tables[PGT_CACHE_SIZE][PGT_SIZE]
- __aligned(PGT_SIZE) __section(".nozi.pgt_cache");
+ __aligned(PGT_SIZE)
+#ifndef __clang__
+ __section(".nozi.pgt_cache")
+#endif
+ ;
+#ifdef __clang__
+#pragma clang section bss=""
+#endif
size_t n;
for (n = 0; n < ARRAY_SIZE(pgt_tables); n++) {
diff --git a/core/kernel/thread.c b/core/kernel/thread.c
index d1f2f3823be7..8de124ae5357 100644
--- a/core/kernel/thread.c
+++ b/core/kernel/thread.c
@@ -38,13 +38,24 @@ struct thread_core_local thread_core_local[CFG_TEE_CORE_NB_CORE] __nex_bss;
name[stack_num][sizeof(name[stack_num]) / sizeof(uint32_t) - 1]
#endif
+#define DO_PRAGMA(x) _Pragma (#x)
+
+#ifdef __clang__
+#define DECLARE_STACK(name, num_stacks, stack_size, linkage) \
+DO_PRAGMA (clang section bss=".nozi_stack." #name) \
+linkage uint32_t name[num_stacks] \
+ [ROUNDUP(stack_size + STACK_CANARY_SIZE + STACK_CHECK_EXTRA, \
+ STACK_ALIGNMENT) / sizeof(uint32_t)] \
+ __attribute__((aligned(STACK_ALIGNMENT))); \
+DO_PRAGMA(clang section bss="")
+#else
#define DECLARE_STACK(name, num_stacks, stack_size, linkage) \
linkage uint32_t name[num_stacks] \
[ROUNDUP(stack_size + STACK_CANARY_SIZE + STACK_CHECK_EXTRA, \
STACK_ALIGNMENT) / sizeof(uint32_t)] \
__attribute__((section(".nozi_stack." # name), \
aligned(STACK_ALIGNMENT)))
-
+#endif
#define GET_STACK(stack) ((vaddr_t)(stack) + STACK_SIZE(stack))
DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE, STACK_TMP_SIZE,
@@ -0,0 +1,88 @@
From d0e32b6e202cde672c2b38dc568122a52be716b4 Mon Sep 17 00:00:00 2001
From: Jens Wiklander <jens.wiklander@linaro.org>
Date: Mon, 21 Nov 2022 18:17:33 +0100
Subject: [PATCH] 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 dd34173e838d..e02c02b6097d 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 4c6e9d75ca45..047ae1f25cc9 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
@@ -0,0 +1,246 @@
From 9da324001fd93e1b3d9bca076e4afddbb5cac289 Mon Sep 17 00:00:00 2001
From: Balint Dobszay <balint.dobszay@arm.com>
Date: Fri, 10 Feb 2023 11:07:27 +0100
Subject: [PATCH] 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 e02c02b6097d..98e13c072d8e 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 0f14ca2f6ad9..3758fd8b7674 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 047ae1f25cc9..fa76437fb73c 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 3b8287e06a11..023a5f3f558b 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 1d36e90b1cf7..d386f1e4d211 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 260854473b8b..941e093b29a1 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
@@ -0,0 +1,275 @@
From 18ad0cce24addd45271edf3172ab9ce873186d7a 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: Submitted [https://github.com/OP-TEE/optee_os/pull/6002]
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 5a19fb0c7ff3..b3d1d354735d 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 f5bda7bfe7d0..30c1e4691273 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 d386f1e4d211..740be6d22e47 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 46a15646ecf0..12681151a796 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 1e7f9f96b558..8cd4dc961b02 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 3b4ac0b4e35c..bc4e7687d618 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 21cb62513a42..7297005a6038 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
@@ -0,0 +1,148 @@
From e7835c526aabd8e5b6db335619a0d86165c587ed 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: Submitted [https://github.com/OP-TEE/optee_os/pull/6002]
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 24b0a8cc07d2..51f6b697e5eb 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 740be6d22e47..b644e1c72e6a 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;