blob: 6b502d78853af63654e41fc82266ea430c9bc6d0 [file] [log] [blame]
Patrick Williamsb542dec2023-06-09 01:26:37 -05001From cad33cffb5be17fc0654aaf03c4d5227ae682e7a Mon Sep 17 00:00:00 2001
2From: Imre Kis <imre.kis@arm.com>
3Date: Tue, 25 Apr 2023 14:19:14 +0200
4Subject: [PATCH] core: spmc: configure SP's NS interrupt action based on
5 the manifest
6
7Used mandatory ns-interrupts-action SP manifest property to configure
8signaled or queued non-secure interrupt handling.
9
10Upstream-Status: Submitted [https://github.com/OP-TEE/optee_os/pull/6002]
11
12Signed-off-by: Imre Kis <imre.kis@arm.com>
13Change-Id: I843e69e5dbb9613ecd8b95654e8ca1730a594ca6
14---
15 .../arm/include/kernel/secure_partition.h | 2 +
16 core/arch/arm/kernel/secure_partition.c | 66 +++++++++++++++++--
17 2 files changed, 63 insertions(+), 5 deletions(-)
18
19diff --git a/core/arch/arm/include/kernel/secure_partition.h b/core/arch/arm/include/kernel/secure_partition.h
20index 290750936..3bf339d3c 100644
21--- a/core/arch/arm/include/kernel/secure_partition.h
22+++ b/core/arch/arm/include/kernel/secure_partition.h
23@@ -43,6 +43,8 @@ struct sp_session {
24 unsigned int spinlock;
25 const void *fdt;
26 bool is_initialized;
27+ uint32_t ns_interrupts_action;
28+ uint32_t ns_interrupts_action_inherited;
29 TAILQ_ENTRY(sp_session) link;
30 };
31
32diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c
33index 52365553b..e54069c17 100644
34--- a/core/arch/arm/kernel/secure_partition.c
35+++ b/core/arch/arm/kernel/secure_partition.c
36@@ -46,6 +46,10 @@
37 SP_MANIFEST_ATTR_WRITE | \
38 SP_MANIFEST_ATTR_EXEC)
39
40+#define SP_MANIFEST_NS_INT_QUEUED (0x0)
41+#define SP_MANIFEST_NS_INT_MANAGED_EXIT (0x1)
42+#define SP_MANIFEST_NS_INT_SIGNALED (0x2)
43+
44 #define SP_PKG_HEADER_MAGIC (0x474b5053)
45 #define SP_PKG_HEADER_VERSION_V1 (0x1)
46 #define SP_PKG_HEADER_VERSION_V2 (0x2)
47@@ -907,6 +911,30 @@ static TEE_Result sp_init_uuid(const TEE_UUID *uuid, const void * const fdt)
48 return res;
49 DMSG("endpoint is 0x%"PRIx16, sess->endpoint_id);
50
51+ res = sp_dt_get_u32(fdt, 0, "ns-interrupts-action",
52+ &sess->ns_interrupts_action);
53+
54+ if (res) {
55+ EMSG("Mandatory property is missing: ns-interrupts-action");
56+ return res;
57+ }
58+
59+ switch (sess->ns_interrupts_action) {
60+ case SP_MANIFEST_NS_INT_QUEUED:
61+ case SP_MANIFEST_NS_INT_SIGNALED:
62+ /* OK */
63+ break;
64+
65+ case SP_MANIFEST_NS_INT_MANAGED_EXIT:
66+ EMSG("Managed exit is not implemented");
67+ return TEE_ERROR_NOT_IMPLEMENTED;
68+
69+ default:
70+ EMSG("Invalid ns-interrupts-action value: %d",
71+ sess->ns_interrupts_action);
72+ return TEE_ERROR_BAD_PARAMETERS;
73+ }
74+
75 return TEE_SUCCESS;
76 }
77
78@@ -989,17 +1017,45 @@ TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp)
79 return res;
80 }
81
82+/*
83+ * According to FF-A v1.1 section 8.3.1.4 if a caller requires less permissive
84+ * active on NS interrupt than the callee, the callee must inherit the caller's
85+ * configuration.
86+ * Each SP's own NS action setting is stored in ns_interrupts_action. The
87+ * effective action will be MIN([self action], [caller's action]) which is
88+ * stored in the ns_interrupts_action_inherited field.
89+ */
90+static void sp_cpsr_configure_foreing_interrupts(struct sp_session *s,
91+ struct ts_session *caller,
92+ uint64_t *cpsr)
93+{
94+ if (caller) {
95+ struct sp_session *caller_sp = to_sp_session(caller);
96+
97+ s->ns_interrupts_action_inherited =
98+ MIN(caller_sp->ns_interrupts_action_inherited,
99+ s->ns_interrupts_action);
100+ } else {
101+ s->ns_interrupts_action_inherited = s->ns_interrupts_action;
102+ }
103+
104+ if (s->ns_interrupts_action_inherited == SP_MANIFEST_NS_INT_QUEUED)
105+ *cpsr |= (THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT);
106+ else
107+ *cpsr &= ~(THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT);
108+}
109+
110 static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
111 uint32_t cmd __unused)
112 {
113 struct sp_ctx *ctx = to_sp_ctx(s->ctx);
114 TEE_Result res = TEE_SUCCESS;
115 uint32_t exceptions = 0;
116- uint64_t cpsr = 0;
117 struct sp_session *sp_s = to_sp_session(s);
118 struct ts_session *sess = NULL;
119 struct thread_ctx_regs *sp_regs = NULL;
120 uint32_t thread_id = THREAD_ID_INVALID;
121+ struct ts_session *caller = NULL;
122 uint32_t rpc_target_info = 0;
123 uint32_t panicked = false;
124 uint32_t panic_code = 0;
125@@ -1009,11 +1065,12 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
126 sp_regs = &ctx->sp_regs;
127 ts_push_current_session(s);
128
129- cpsr = sp_regs->cpsr;
130- sp_regs->cpsr = read_daif() & (SPSR_64_DAIF_MASK << SPSR_64_DAIF_SHIFT);
131-
132 exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
133
134+ /* Enable/disable foreign interrupts in CPSR/SPSR */
135+ caller = ts_get_calling_session();
136+ sp_cpsr_configure_foreing_interrupts(sp_s, caller, &sp_regs->cpsr);
137+
138 /*
139 * Store endpoint ID and thread ID in rpc_target_info. This will be used
140 * as w1 in FFA_INTERRUPT in case of a NWd interrupt.
141@@ -1026,7 +1083,6 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
142
143 __thread_enter_user_mode(sp_regs, &panicked, &panic_code);
144
145- sp_regs->cpsr = cpsr;
146 /* Restore rpc_target_info */
147 thread_get_tsd()->rpc_target_info = rpc_target_info;
148
149--
1502.17.1