Skip to content

Commit c2ce7aa

Browse files
etienne-lmsLionel Debieve
authored andcommitted
core: pta: scmi: ocall threaded context
Using Ocall (CFG_CORE_OCALL=y), the SCMI agent and PTA can provision a secure thread for SCMI message passing/processing. The channel exchange protocol using OP-TEE Ocall is described in the PTA API header file pta_scmi_client.h Note: this change was originally posted to OP-TEE through pull request OP-TEE#4535. Change-Id: I995192c660cd837fa7ccc025f5c95363e3b01937 Signed-off-by: Etienne Carriere <[email protected]> Reviewed-on: https://gerrit.st.com/c/mpu/oe/optee/optee_os/+/202484 Tested-by: Etienne CARRIERE <[email protected]> Reviewed-by: Etienne CARRIERE <[email protected]> Reviewed-by: Lionel DEBIEVE <[email protected]>
1 parent 5b86d56 commit c2ce7aa

File tree

3 files changed

+200
-2
lines changed

3 files changed

+200
-2
lines changed

core/pta/scmi.c

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,17 @@
77
#include <config.h>
88
#include <drivers/scmi-msg.h>
99
#include <kernel/pseudo_ta.h>
10+
#include <optee_rpc_cmd.h>
1011
#include <pta_scmi_client.h>
1112
#include <stdint.h>
1213
#include <string.h>
14+
#include <tee/uuid.h>
15+
#include <util.h>
16+
17+
static bool valid_caps(unsigned int caps)
18+
{
19+
return (caps & ~PTA_SCMI_CAPS_VALID_MASK) == 0;
20+
}
1321

1422
static TEE_Result cmd_capabilities(uint32_t ptypes,
1523
TEE_Param param[TEE_NUM_PARAMS])
@@ -25,6 +33,8 @@ static TEE_Result cmd_capabilities(uint32_t ptypes,
2533

2634
if (IS_ENABLED(CFG_SCMI_MSG_SMT))
2735
caps |= PTA_SCMI_CAPS_SMT_HEADER;
36+
if (IS_ENABLED(CFG_CORE_OCALL))
37+
caps |= PTA_SCMI_CAPS_OCALL_THREAD;
2838

2939
param[0].value.a = caps;
3040
param[0].value.b = 0;
@@ -97,6 +107,116 @@ static TEE_Result cmd_process_smt_message(uint32_t ptypes,
97107
return TEE_ERROR_NOT_SUPPORTED;
98108
}
99109

110+
/* Process an OCALL RPC to client and report status */
111+
static enum optee_scmi_ocall_reply pta_scmi_ocall(uint32_t channel_id)
112+
{
113+
static const TEE_UUID uuid = PTA_SCMI_UUID;
114+
static uint64_t uuid_octet[2];
115+
static bool uuid_ready;
116+
struct thread_param params[THREAD_RPC_MAX_NUM_PARAMS] = {
117+
/* Ocall command, sub command */
118+
THREAD_PARAM_VALUE(INOUT, 0, 0, 0),
119+
/* UUID of Ocall initiator */
120+
THREAD_PARAM_VALUE(IN, 0, 0, 0),
121+
/* Output value argument to get REE feedback */
122+
THREAD_PARAM_VALUE(OUT, 0, 0, 0),
123+
};
124+
uint64_t ocall_res = 0;
125+
uint64_t __maybe_unused ocall_ori = 0;
126+
enum optee_scmi_ocall_reply agent_request = PTA_SCMI_OCALL_ERROR;
127+
TEE_Result res = TEE_ERROR_GENERIC;
128+
129+
if (!IS_ENABLED(CFG_CORE_OCALL))
130+
return PTA_SCMI_OCALL_ERROR;
131+
132+
if (!uuid_ready) {
133+
tee_uuid_to_octets((uint8_t *)uuid_octet, &uuid);
134+
uuid_ready = true;
135+
}
136+
137+
params[0].u.value.a = PTA_SCMI_OCALL_CMD_THREAD_READY;
138+
params[1].u.value.a = uuid_octet[0];
139+
params[1].u.value.b = uuid_octet[1];
140+
141+
params[0] = THREAD_PARAM_VALUE(INOUT, PTA_SCMI_OCALL_CMD_THREAD_READY,
142+
0, 0);
143+
params[1] = THREAD_PARAM_VALUE(IN, uuid_octet[0], uuid_octet[1], 0);
144+
params[2] = THREAD_PARAM_VALUE(OUT, 0, 0, 0);
145+
146+
res = thread_rpc_cmd(OPTEE_RPC_CMD_OCALL, ARRAY_SIZE(params), params);
147+
if (res) {
148+
DMSG("Close thread on RPC error %#"PRIx32, res);
149+
return PTA_SCMI_OCALL_ERROR;
150+
}
151+
152+
ocall_res = params[0].u.value.b;
153+
ocall_ori = params[0].u.value.c;
154+
if (ocall_res) {
155+
DMSG("SCMI RPC thread failed %#"PRIx64" from %#"PRIx64,
156+
ocall_res, ocall_ori);
157+
return PTA_SCMI_OCALL_ERROR;
158+
}
159+
160+
agent_request = (enum optee_scmi_ocall_reply)params[2].u.value.a;
161+
162+
switch (agent_request) {
163+
case PTA_SCMI_OCALL_PROCESS_SMT_CHANNEL:
164+
FMSG("Posting message on channel %u"PRIu32, channel_id);
165+
if (IS_ENABLED(CFG_SCMI_MSG_SMT))
166+
scmi_smt_threaded_entry(channel_id);
167+
else
168+
panic();
169+
break;
170+
case PTA_SCMI_OCALL_CLOSE_THREAD:
171+
FMSG("Closing channel %u"PRIu32, channel_id);
172+
break;
173+
case PTA_SCMI_OCALL_ERROR:
174+
FMSG("Error on channel %u"PRIu32, channel_id);
175+
break;
176+
default:
177+
DMSG("Invalid Ocall cmd %#x on channel %u"PRIu32,
178+
agent_request, channel_id);
179+
return PTA_SCMI_OCALL_CLOSE_THREAD;
180+
}
181+
182+
return agent_request;
183+
}
184+
185+
static TEE_Result cmd_scmi_ocall_thread(uint32_t ptypes,
186+
TEE_Param params[TEE_NUM_PARAMS])
187+
{
188+
const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
189+
TEE_PARAM_TYPE_NONE,
190+
TEE_PARAM_TYPE_NONE,
191+
TEE_PARAM_TYPE_NONE);
192+
193+
uint32_t channel_id = (int)params[0].value.a;
194+
struct scmi_msg_channel *channel = NULL;
195+
196+
if (ptypes != exp_ptypes)
197+
return TEE_ERROR_BAD_PARAMETERS;
198+
199+
if (IS_ENABLED(CFG_SCMI_MSG_SMT))
200+
channel = plat_scmi_get_channel(channel_id);
201+
else
202+
return TEE_ERROR_NOT_SUPPORTED;
203+
204+
if (!channel)
205+
return TEE_ERROR_BAD_PARAMETERS;
206+
207+
FMSG("Enter Ocall thread on channel %u"PRIu32, channel_id);
208+
while (1) {
209+
switch (pta_scmi_ocall(channel_id)) {
210+
case PTA_SCMI_OCALL_PROCESS_SMT_CHANNEL:
211+
continue;
212+
case PTA_SCMI_OCALL_CLOSE_THREAD:
213+
return TEE_SUCCESS;
214+
default:
215+
return TEE_ERROR_GENERIC;
216+
}
217+
}
218+
}
219+
100220
static TEE_Result cmd_get_channel_handle(uint32_t ptypes,
101221
TEE_Param params[TEE_NUM_PARAMS])
102222
{
@@ -107,13 +227,13 @@ static TEE_Result cmd_get_channel_handle(uint32_t ptypes,
107227
unsigned int channel_id = params[0].value.a;
108228
unsigned int caps = params[0].value.b;
109229

110-
if (ptypes != exp_ptypes)
230+
if (ptypes != exp_ptypes || !valid_caps(caps))
111231
return TEE_ERROR_BAD_PARAMETERS;
112232

113233
if (IS_ENABLED(CFG_SCMI_MSG_SMT)) {
114234
struct scmi_msg_channel *channel = NULL;
115235

116-
if (caps != PTA_SCMI_CAPS_SMT_HEADER)
236+
if (!(caps & PTA_SCMI_CAPS_SMT_HEADER))
117237
return TEE_ERROR_NOT_SUPPORTED;
118238

119239
channel = plat_scmi_get_channel(channel_id);
@@ -163,6 +283,8 @@ static TEE_Result pta_scmi_invoke_command(void *session __unused, uint32_t cmd,
163283
return cmd_process_smt_message(ptypes, params);
164284
case PTA_SCMI_CMD_GET_CHANNEL_HANDLE:
165285
return cmd_get_channel_handle(ptypes, params);
286+
case PTA_SCMI_CMD_OCALL_THREAD:
287+
return cmd_scmi_ocall_thread(ptypes, params);
166288
default:
167289
return TEE_ERROR_NOT_SUPPORTED;
168290
}

lib/libutee/include/pta_scmi_client.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,80 @@
5858
*/
5959
#define PTA_SCMI_CMD_GET_CHANNEL_HANDLE 3
6060

61+
/*
62+
* PTA_SCMI_CMD_OCALL_THREAD - Allocate a threaded path using OCALL
63+
*
64+
* [in] value[0].a: channel handle
65+
*
66+
* Use Ocall support to create a provisioned OP-TEE thread context for
67+
* the channel. Successful creation of the thread makes this command to
68+
* return with Ocall command PTA_SCMI_OCALL_CMD_THREAD_READY.
69+
*/
70+
#define PTA_SCMI_CMD_OCALL_THREAD 4
71+
6172
/*
6273
* Capabilities
6374
*/
6475

6576
/* Channel supports shared memory using the SMT header protocol */
6677
#define PTA_SCMI_CAPS_SMT_HEADER BIT32(0)
6778

79+
/*
80+
* Channel can use command PTA_SCMI_CMD_OCALL_THREAD to provision a
81+
* TEE thread for SCMI message passing.
82+
*/
83+
#define PTA_SCMI_CAPS_OCALL_THREAD BIT32(1)
84+
85+
#define PTA_SCMI_CAPS_VALID_MASK (PTA_SCMI_CAPS_SMT_HEADER | \
86+
PTA_SCMI_CAPS_OCALL_THREAD)
87+
88+
/*
89+
* enum optee_scmi_ocall_cmd
90+
* enum optee_scmi_ocall_reply
91+
*
92+
* These enumerates define the IDs used by REE/TEE to communicate in the
93+
* established REE/TEE Ocall thread context.
94+
*
95+
* At channel setup, we start from the REE: caller requests an Ocall context.
96+
*
97+
* 0. REE opens a session toward PTA SCMI. REE invokes PTA command
98+
* PTA_SCMI_CMD_GET_CHANNEL to get a channel handler.
99+
*
100+
* 1. REE invokes command PTA_SCMI_CAPS_OCALL_THREAD with an Ocall context.
101+
* This is the initial invocation of the Ocall thread context. Any further
102+
* error in the thread communication will make Core to return to REE from
103+
* this command invocation with an TEE_Result error code.
104+
*
105+
* 2. Upon support of Ocall the PTA creates an Ocall context and returns to
106+
* REE with Ocall command PTA_SCMI_OCALL_CMD_THREAD_READY.
107+
*
108+
* 3. REE returns to the PTA, from the Ocall, with output param[0].value.a
109+
* set to PTA_SCMI_OCALL_PROCESS_SMT_CHANNEL to post an SCMI message.
110+
* In such case, OP-TEE processes the message and returns to REE with
111+
* Ocall command PTA_SCMI_OCALL_CMD_THREAD_READY. The SCMI response is in
112+
* the shared memory buffer.
113+
*
114+
* 4. Alternatively REE can return from the Ocall with output param[0].value.a
115+
* set to PTA_SCMI_OCALL_CLOSE_THREAD. This requests OP-TEE to terminate the
116+
* Ocall, release resources and return from initial command invocation at 1.
117+
* as if REE closes the SCMI communication.
118+
*
119+
* At anytime, if an error is reported by Ocall commands or replies, SCMI PTA
120+
* release the Ocall thread context and return from initial invocation at 1.
121+
* PTA_SCMI_OCALL_ERROR is used in Ocall return to force an error report.
122+
*
123+
* REE channel initialization completes when returning from step 2.
124+
* REE agent posts an SCMI message through step 3.
125+
* At channel release, REE driver executes step 4.
126+
*/
127+
128+
enum optee_scmi_ocall_cmd {
129+
PTA_SCMI_OCALL_CMD_THREAD_READY = 0,
130+
};
131+
132+
enum optee_scmi_ocall_reply {
133+
PTA_SCMI_OCALL_ERROR = 0,
134+
PTA_SCMI_OCALL_CLOSE_THREAD = 1,
135+
PTA_SCMI_OCALL_PROCESS_SMT_CHANNEL = 2,
136+
};
68137
#endif /* SCMI_PTA_SCMI_CLIENT_H */

mk/config.mk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,13 @@ CFG_SCMI_MSG_VOLTAGE_DOMAIN ?= n
678678
# Enable SCMI PTA interface for REE SCMI agents
679679
CFG_SCMI_PTA ?= n
680680

681+
# Enable SCMI server (SCP-firmware-scmi library)
682+
CFG_SCMI_SERVER ?= n
683+
ifeq ($(CFG_SCMI_SERVER),y)
684+
$(call force,CFG_SCMI_PTA,y,Mandated by CFG_SCMI_SERVER)
685+
$(call force,CFG_CORE_OCALL,y,Mandated by CFG_SCMI_SERVER)
686+
endif
687+
681688
ifneq ($(CFG_STMM_PATH),)
682689
$(call force,CFG_WITH_STMM_SP,y)
683690
else

0 commit comments

Comments
 (0)