summaryrefslogtreecommitdiff
path: root/meta-arm/meta-arm/recipes-security/optee/optee-os-3.20.0/0008-core-spmc-configure-SP-s-NS-interrupt-action-based-o.patch
blob: 32e560689fde8cde81f0462e5482eabda94bd93d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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