xref: /aosp_15_r20/trusty/kernel/services/smc/smc_service.c (revision 344aa361028b423587d4ef3fa52a23d194628137)
1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker  * Copyright (c) 2019, Google Inc. All rights reserved
3*344aa361SAndroid Build Coastguard Worker  *
4*344aa361SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker  * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker  * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker  * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker  * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker  * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker  * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker  *
12*344aa361SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker  * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker  *
15*344aa361SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker  */
23*344aa361SAndroid Build Coastguard Worker 
24*344aa361SAndroid Build Coastguard Worker #include <err.h>
25*344aa361SAndroid Build Coastguard Worker #include <interface/smc/smc.h>
26*344aa361SAndroid Build Coastguard Worker #include <kernel/thread.h>
27*344aa361SAndroid Build Coastguard Worker #include <lib/ktipc/ktipc.h>
28*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/handle_set.h>
29*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/ipc.h>
30*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/ipc_msg.h>
31*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
32*344aa361SAndroid Build Coastguard Worker #include <lk/trace.h>
33*344aa361SAndroid Build Coastguard Worker #include <services/smc/acl.h>
34*344aa361SAndroid Build Coastguard Worker #include <string.h>
35*344aa361SAndroid Build Coastguard Worker 
36*344aa361SAndroid Build Coastguard Worker #define LOCAL_TRACE (0)
37*344aa361SAndroid Build Coastguard Worker 
38*344aa361SAndroid Build Coastguard Worker struct smc_channel_ctx {
39*344aa361SAndroid Build Coastguard Worker     struct smc_access_policy policy;
40*344aa361SAndroid Build Coastguard Worker     struct uuid uuid;
41*344aa361SAndroid Build Coastguard Worker };
42*344aa361SAndroid Build Coastguard Worker 
43*344aa361SAndroid Build Coastguard Worker /**
44*344aa361SAndroid Build Coastguard Worker  * struct smc_regs - Struct representing input/output registers of an SMC
45*344aa361SAndroid Build Coastguard Worker  * @r0-3: registers r0-3/x0-3 for 32/64 bit respectively
46*344aa361SAndroid Build Coastguard Worker  */
47*344aa361SAndroid Build Coastguard Worker struct smc_regs {
48*344aa361SAndroid Build Coastguard Worker     ulong r0;
49*344aa361SAndroid Build Coastguard Worker     ulong r1;
50*344aa361SAndroid Build Coastguard Worker     ulong r2;
51*344aa361SAndroid Build Coastguard Worker     ulong r3;
52*344aa361SAndroid Build Coastguard Worker };
53*344aa361SAndroid Build Coastguard Worker 
54*344aa361SAndroid Build Coastguard Worker #if ARCH_ARM64
55*344aa361SAndroid Build Coastguard Worker #define SMC_ARG0 "x0"
56*344aa361SAndroid Build Coastguard Worker #define SMC_ARG1 "x1"
57*344aa361SAndroid Build Coastguard Worker #define SMC_ARG2 "x2"
58*344aa361SAndroid Build Coastguard Worker #define SMC_ARG3 "x3"
59*344aa361SAndroid Build Coastguard Worker #define SMC_ARCH_EXTENSION ""
60*344aa361SAndroid Build Coastguard Worker #define SMC_REGISTERS_TRASHED                                              \
61*344aa361SAndroid Build Coastguard Worker     "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", \
62*344aa361SAndroid Build Coastguard Worker             "x15", "x16", "x17"
63*344aa361SAndroid Build Coastguard Worker #else
64*344aa361SAndroid Build Coastguard Worker #define SMC_ARG0 "r0"
65*344aa361SAndroid Build Coastguard Worker #define SMC_ARG1 "r1"
66*344aa361SAndroid Build Coastguard Worker #define SMC_ARG2 "r2"
67*344aa361SAndroid Build Coastguard Worker #define SMC_ARG3 "r3"
68*344aa361SAndroid Build Coastguard Worker #define SMC_ARCH_EXTENSION ".arch_extension sec\n"
69*344aa361SAndroid Build Coastguard Worker #define SMC_REGISTERS_TRASHED "ip"
70*344aa361SAndroid Build Coastguard Worker #endif
71*344aa361SAndroid Build Coastguard Worker 
72*344aa361SAndroid Build Coastguard Worker /* Perform a secure manager call with up to 4 inputs and 4 outputs */
smc(struct smc_regs * regs)73*344aa361SAndroid Build Coastguard Worker static struct smc_regs smc(struct smc_regs* regs) {
74*344aa361SAndroid Build Coastguard Worker     register ulong _r0 __asm__(SMC_ARG0) = regs->r0;
75*344aa361SAndroid Build Coastguard Worker     register ulong _r1 __asm__(SMC_ARG1) = regs->r1;
76*344aa361SAndroid Build Coastguard Worker     register ulong _r2 __asm__(SMC_ARG2) = regs->r2;
77*344aa361SAndroid Build Coastguard Worker     register ulong _r3 __asm__(SMC_ARG3) = regs->r3;
78*344aa361SAndroid Build Coastguard Worker     __asm__ volatile(SMC_ARCH_EXTENSION "smc #0"
79*344aa361SAndroid Build Coastguard Worker                      : "=r"(_r0), "=r"(_r1), "=r"(_r2), "=r"(_r3)
80*344aa361SAndroid Build Coastguard Worker                      : "r"(_r0), "r"(_r1), "r"(_r2), "r"(_r3)
81*344aa361SAndroid Build Coastguard Worker                      : SMC_REGISTERS_TRASHED);
82*344aa361SAndroid Build Coastguard Worker     return (struct smc_regs){
83*344aa361SAndroid Build Coastguard Worker             .r0 = _r0,
84*344aa361SAndroid Build Coastguard Worker             .r1 = _r1,
85*344aa361SAndroid Build Coastguard Worker             .r2 = _r2,
86*344aa361SAndroid Build Coastguard Worker             .r3 = _r3,
87*344aa361SAndroid Build Coastguard Worker     };
88*344aa361SAndroid Build Coastguard Worker }
89*344aa361SAndroid Build Coastguard Worker 
smc_service_handle_msg(const struct ktipc_port * port,struct handle * channel,void * ctx)90*344aa361SAndroid Build Coastguard Worker static int smc_service_handle_msg(const struct ktipc_port* port,
91*344aa361SAndroid Build Coastguard Worker                                   struct handle* channel,
92*344aa361SAndroid Build Coastguard Worker                                   void* ctx) {
93*344aa361SAndroid Build Coastguard Worker     struct smc_channel_ctx* channel_ctx = ctx;
94*344aa361SAndroid Build Coastguard Worker     int rc;
95*344aa361SAndroid Build Coastguard Worker     struct smc_msg request;
96*344aa361SAndroid Build Coastguard Worker     struct smc_response response = {0};
97*344aa361SAndroid Build Coastguard Worker     struct smc_regs ret;
98*344aa361SAndroid Build Coastguard Worker     uint32_t smc_nr;
99*344aa361SAndroid Build Coastguard Worker 
100*344aa361SAndroid Build Coastguard Worker     rc = ktipc_recv(channel, sizeof(request), &request, sizeof(request));
101*344aa361SAndroid Build Coastguard Worker     if ((size_t)rc != sizeof(request)) {
102*344aa361SAndroid Build Coastguard Worker         TRACEF("%s: failed (%d) to read SMC request\n", __func__, rc);
103*344aa361SAndroid Build Coastguard Worker         goto err;
104*344aa361SAndroid Build Coastguard Worker     }
105*344aa361SAndroid Build Coastguard Worker 
106*344aa361SAndroid Build Coastguard Worker     smc_nr = (uint32_t)request.params[0];
107*344aa361SAndroid Build Coastguard Worker     rc = channel_ctx->policy.check_access(smc_nr);
108*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
109*344aa361SAndroid Build Coastguard Worker         TRACEF("%s: failed (%d) client not allowed to call SMC number %x\n",
110*344aa361SAndroid Build Coastguard Worker                __func__, rc, smc_nr);
111*344aa361SAndroid Build Coastguard Worker         /*
112*344aa361SAndroid Build Coastguard Worker          * callers of smc_read_response should not consume the struct smc_msg
113*344aa361SAndroid Build Coastguard Worker          * out parameter if the status code is negative but we write the error
114*344aa361SAndroid Build Coastguard Worker          * code into the message anyway out of an over-abundance of caution.
115*344aa361SAndroid Build Coastguard Worker          */
116*344aa361SAndroid Build Coastguard Worker         response.msg.params[0] = (ulong)ERR_ACCESS_DENIED;
117*344aa361SAndroid Build Coastguard Worker         response.rc = ERR_ACCESS_DENIED;
118*344aa361SAndroid Build Coastguard Worker         goto send_response;
119*344aa361SAndroid Build Coastguard Worker     }
120*344aa361SAndroid Build Coastguard Worker 
121*344aa361SAndroid Build Coastguard Worker     rc = channel_ctx->policy.check_request(smc_nr, &channel_ctx->uuid,
122*344aa361SAndroid Build Coastguard Worker                                            &request);
123*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
124*344aa361SAndroid Build Coastguard Worker         TRACEF("%s: failed (%d) invalid request for SMC number %x\n", __func__,
125*344aa361SAndroid Build Coastguard Worker                rc, smc_nr);
126*344aa361SAndroid Build Coastguard Worker         /* same reasoning as the ERR_ACCESS_DENIED case above */
127*344aa361SAndroid Build Coastguard Worker         response.msg.params[0] = (ulong)ERR_INVALID_ARGS;
128*344aa361SAndroid Build Coastguard Worker         response.rc = ERR_INVALID_ARGS;
129*344aa361SAndroid Build Coastguard Worker         goto send_response;
130*344aa361SAndroid Build Coastguard Worker     }
131*344aa361SAndroid Build Coastguard Worker 
132*344aa361SAndroid Build Coastguard Worker     struct smc_regs args = {
133*344aa361SAndroid Build Coastguard Worker             .r0 = (ulong)request.params[0],
134*344aa361SAndroid Build Coastguard Worker             .r1 = (ulong)request.params[1],
135*344aa361SAndroid Build Coastguard Worker             .r2 = (ulong)request.params[2],
136*344aa361SAndroid Build Coastguard Worker             .r3 = (ulong)request.params[3],
137*344aa361SAndroid Build Coastguard Worker     };
138*344aa361SAndroid Build Coastguard Worker     ret = smc(&args);
139*344aa361SAndroid Build Coastguard Worker 
140*344aa361SAndroid Build Coastguard Worker     response.msg.params[0] = ret.r0;
141*344aa361SAndroid Build Coastguard Worker     response.msg.params[1] = ret.r1;
142*344aa361SAndroid Build Coastguard Worker     response.msg.params[2] = ret.r2;
143*344aa361SAndroid Build Coastguard Worker     response.msg.params[3] = ret.r3;
144*344aa361SAndroid Build Coastguard Worker 
145*344aa361SAndroid Build Coastguard Worker     if ((int32_t)ret.r0 == SM_ERR_UNDEFINED_SMC) {
146*344aa361SAndroid Build Coastguard Worker         TRACEF("%s: unknown or failed smcall: %x\n", __func__, smc_nr);
147*344aa361SAndroid Build Coastguard Worker         response.rc = ERR_GENERIC;
148*344aa361SAndroid Build Coastguard Worker     }
149*344aa361SAndroid Build Coastguard Worker 
150*344aa361SAndroid Build Coastguard Worker send_response:
151*344aa361SAndroid Build Coastguard Worker     rc = ktipc_send(channel, &response, sizeof(response));
152*344aa361SAndroid Build Coastguard Worker     if ((size_t)rc != sizeof(response)) {
153*344aa361SAndroid Build Coastguard Worker         TRACEF("%s: failed (%d) to send response\n", __func__, rc);
154*344aa361SAndroid Build Coastguard Worker     }
155*344aa361SAndroid Build Coastguard Worker 
156*344aa361SAndroid Build Coastguard Worker err:
157*344aa361SAndroid Build Coastguard Worker     return rc;
158*344aa361SAndroid Build Coastguard Worker }
159*344aa361SAndroid Build Coastguard Worker 
smc_service_handle_connect(const struct ktipc_port * port,struct handle * chan,const struct uuid * peer_uuid,void ** ctx_p)160*344aa361SAndroid Build Coastguard Worker static int smc_service_handle_connect(const struct ktipc_port* port,
161*344aa361SAndroid Build Coastguard Worker                                       struct handle* chan,
162*344aa361SAndroid Build Coastguard Worker                                       const struct uuid* peer_uuid,
163*344aa361SAndroid Build Coastguard Worker                                       void** ctx_p) {
164*344aa361SAndroid Build Coastguard Worker     struct smc_channel_ctx* channel_ctx = calloc(1, sizeof(*channel_ctx));
165*344aa361SAndroid Build Coastguard Worker     if (!channel_ctx) {
166*344aa361SAndroid Build Coastguard Worker         TRACEF("%s: failed to allocate smc_channel_ctx\n", __func__);
167*344aa361SAndroid Build Coastguard Worker         return ERR_NO_MEMORY;
168*344aa361SAndroid Build Coastguard Worker     }
169*344aa361SAndroid Build Coastguard Worker 
170*344aa361SAndroid Build Coastguard Worker     smc_load_access_policy(peer_uuid, &channel_ctx->policy);
171*344aa361SAndroid Build Coastguard Worker     channel_ctx->uuid = *peer_uuid;
172*344aa361SAndroid Build Coastguard Worker 
173*344aa361SAndroid Build Coastguard Worker     *ctx_p = channel_ctx;
174*344aa361SAndroid Build Coastguard Worker 
175*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
176*344aa361SAndroid Build Coastguard Worker }
177*344aa361SAndroid Build Coastguard Worker 
smc_service_handle_channel_cleanup(void * ctx)178*344aa361SAndroid Build Coastguard Worker static void smc_service_handle_channel_cleanup(void* ctx) {
179*344aa361SAndroid Build Coastguard Worker     struct smc_channel_ctx* channel_ctx = ctx;
180*344aa361SAndroid Build Coastguard Worker     free(channel_ctx);
181*344aa361SAndroid Build Coastguard Worker }
182*344aa361SAndroid Build Coastguard Worker 
183*344aa361SAndroid Build Coastguard Worker const static struct ktipc_srv_ops smc_service_ops = {
184*344aa361SAndroid Build Coastguard Worker         .on_connect = smc_service_handle_connect,
185*344aa361SAndroid Build Coastguard Worker         .on_message = smc_service_handle_msg,
186*344aa361SAndroid Build Coastguard Worker         .on_channel_cleanup = smc_service_handle_channel_cleanup,
187*344aa361SAndroid Build Coastguard Worker };
188*344aa361SAndroid Build Coastguard Worker 
189*344aa361SAndroid Build Coastguard Worker const static struct ktipc_port_acl smc_service_port_acl = {
190*344aa361SAndroid Build Coastguard Worker         .flags = IPC_PORT_ALLOW_TA_CONNECT,
191*344aa361SAndroid Build Coastguard Worker         .uuids = NULL,
192*344aa361SAndroid Build Coastguard Worker         .uuid_num = 0,
193*344aa361SAndroid Build Coastguard Worker         .extra_data = NULL,
194*344aa361SAndroid Build Coastguard Worker };
195*344aa361SAndroid Build Coastguard Worker 
196*344aa361SAndroid Build Coastguard Worker const static struct ktipc_port smc_service_port = {
197*344aa361SAndroid Build Coastguard Worker         .name = SMC_SERVICE_PORT,
198*344aa361SAndroid Build Coastguard Worker         .uuid = &kernel_uuid,
199*344aa361SAndroid Build Coastguard Worker         .msg_max_size = sizeof(struct smc_response),
200*344aa361SAndroid Build Coastguard Worker         .msg_queue_len = 1,
201*344aa361SAndroid Build Coastguard Worker         .acl = &smc_service_port_acl,
202*344aa361SAndroid Build Coastguard Worker         .priv = NULL,
203*344aa361SAndroid Build Coastguard Worker };
204*344aa361SAndroid Build Coastguard Worker 
205*344aa361SAndroid Build Coastguard Worker static struct ktipc_server smc_ktipc_server =
206*344aa361SAndroid Build Coastguard Worker         KTIPC_SERVER_INITIAL_VALUE(smc_ktipc_server, "smc_ktipc_server");
207*344aa361SAndroid Build Coastguard Worker 
smc_service_init(uint level)208*344aa361SAndroid Build Coastguard Worker static void smc_service_init(uint level) {
209*344aa361SAndroid Build Coastguard Worker     int rc;
210*344aa361SAndroid Build Coastguard Worker 
211*344aa361SAndroid Build Coastguard Worker     rc = ktipc_server_start(&smc_ktipc_server);
212*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
213*344aa361SAndroid Build Coastguard Worker         panic("Failed (%d) to start smc server\n", rc);
214*344aa361SAndroid Build Coastguard Worker     }
215*344aa361SAndroid Build Coastguard Worker 
216*344aa361SAndroid Build Coastguard Worker     rc = ktipc_server_add_port(&smc_ktipc_server, &smc_service_port,
217*344aa361SAndroid Build Coastguard Worker                                &smc_service_ops);
218*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
219*344aa361SAndroid Build Coastguard Worker         panic("Failed (%d) to create smc port\n", rc);
220*344aa361SAndroid Build Coastguard Worker     }
221*344aa361SAndroid Build Coastguard Worker }
222*344aa361SAndroid Build Coastguard Worker 
223*344aa361SAndroid Build Coastguard Worker LK_INIT_HOOK(smc, smc_service_init, LK_INIT_LEVEL_APPS);
224