xref: /aosp_15_r20/trusty/kernel/lib/metrics/metrics.c (revision 344aa361028b423587d4ef3fa52a23d194628137)
1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker  * Copyright (c) 2021, 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 <assert.h>
25*344aa361SAndroid Build Coastguard Worker #include <err.h>
26*344aa361SAndroid Build Coastguard Worker #include <interface/metrics/consumer.h>
27*344aa361SAndroid Build Coastguard Worker #include <kernel/mutex.h>
28*344aa361SAndroid Build Coastguard Worker #include <lib/dpc.h>
29*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/handle.h>
30*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/ipc.h>
31*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/ipc_msg.h>
32*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/trusty_app.h>
33*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
34*344aa361SAndroid Build Coastguard Worker #include <lk/trace.h>
35*344aa361SAndroid Build Coastguard Worker #include <string.h>
36*344aa361SAndroid Build Coastguard Worker #include <trusty/uuid.h>
37*344aa361SAndroid Build Coastguard Worker 
38*344aa361SAndroid Build Coastguard Worker #define LOCAL_TRACE (0)
39*344aa361SAndroid Build Coastguard Worker 
40*344aa361SAndroid Build Coastguard Worker /*
41*344aa361SAndroid Build Coastguard Worker  * Format of the payload is "<UUID>:<app name>", with neither UUID nor app name
42*344aa361SAndroid Build Coastguard Worker  * being null-terminated. However, unlike APP_NAME_MAX_SIZE, UUID_STR_SIZE
43*344aa361SAndroid Build Coastguard Worker  * counts the null character. Hence, the maximum size of an app name is
44*344aa361SAndroid Build Coastguard Worker  * METRICS_MAX_APP_ID_LEN - UUID_STR_SIZE.
45*344aa361SAndroid Build Coastguard Worker  */
46*344aa361SAndroid Build Coastguard Worker static_assert(UUID_STR_SIZE <= METRICS_MAX_APP_ID_LEN);
47*344aa361SAndroid Build Coastguard Worker #define APP_NAME_MAX_SIZE (METRICS_MAX_APP_ID_LEN - UUID_STR_SIZE)
48*344aa361SAndroid Build Coastguard Worker 
49*344aa361SAndroid Build Coastguard Worker /**
50*344aa361SAndroid Build Coastguard Worker  * enum chan_state - states of the metrics consumer channel event handler
51*344aa361SAndroid Build Coastguard Worker  * CHAN_STATE_WAITING_CHAN_READY:
52*344aa361SAndroid Build Coastguard Worker  *      Inital state of the channel handler. At this point we are waiting for an
53*344aa361SAndroid Build Coastguard Worker  *      IPC_HANDLE_POLL_READY channel event that signifies that metrics consumer
54*344aa361SAndroid Build Coastguard Worker  *      connection is ready for use. After consuming this event, we transition
55*344aa361SAndroid Build Coastguard Worker  *      to %CHAN_STATE_IDLE state.
56*344aa361SAndroid Build Coastguard Worker  * CHAN_STATE_IDLE:
57*344aa361SAndroid Build Coastguard Worker  *      While in this state we (2) can not consume any events from the channel
58*344aa361SAndroid Build Coastguard Worker  *      (1) can only send one message over the channel. Once a message is sent,
59*344aa361SAndroid Build Coastguard Worker  *      we transition to either %CHAN_STATE_WAITING_CRASH_RESP or
60*344aa361SAndroid Build Coastguard Worker  *      %CHAN_STATE_WAITING_EXIT_RESP or %CHAN_STATE_WAITING_EVENT_DROP_RESP
61*344aa361SAndroid Build Coastguard Worker  *      depending on what message was sent.
62*344aa361SAndroid Build Coastguard Worker  * CHAN_STATE_WAITING_CRASH_RESP:
63*344aa361SAndroid Build Coastguard Worker  *      In this state we are waiting for a response to a message about an app
64*344aa361SAndroid Build Coastguard Worker  *      crash.  After receiving the response message, we transition to
65*344aa361SAndroid Build Coastguard Worker  *      %CHAN_STATE_IDLE state.
66*344aa361SAndroid Build Coastguard Worker  * CHAN_STATE_WAITING_EXIT_RESP:
67*344aa361SAndroid Build Coastguard Worker  *      In this state we are waiting for a response to a message about an app
68*344aa361SAndroid Build Coastguard Worker  *      crash.  After receiving the response message, we transition to
69*344aa361SAndroid Build Coastguard Worker  *      %CHAN_STATE_IDLE state.
70*344aa361SAndroid Build Coastguard Worker  * CHAN_STATE_WAITING_EVENT_DROP_RESP:
71*344aa361SAndroid Build Coastguard Worker  *      In this state we are waiting for a response to a message about an event
72*344aa361SAndroid Build Coastguard Worker  *      drop. After receiving the response message, we transition to
73*344aa361SAndroid Build Coastguard Worker  *      %CHAN_STATE_IDLE state.
74*344aa361SAndroid Build Coastguard Worker  */
75*344aa361SAndroid Build Coastguard Worker enum chan_state {
76*344aa361SAndroid Build Coastguard Worker     CHAN_STATE_WAITING_CHAN_READY = 0,
77*344aa361SAndroid Build Coastguard Worker     CHAN_STATE_IDLE = 1,
78*344aa361SAndroid Build Coastguard Worker     CHAN_STATE_WAITING_CRASH_RESP = 2,
79*344aa361SAndroid Build Coastguard Worker     CHAN_STATE_WAITING_EXIT_RESP = 3,
80*344aa361SAndroid Build Coastguard Worker     CHAN_STATE_WAITING_EVENT_DROP_RESP = 4,
81*344aa361SAndroid Build Coastguard Worker };
82*344aa361SAndroid Build Coastguard Worker 
83*344aa361SAndroid Build Coastguard Worker struct metrics_ctx {
84*344aa361SAndroid Build Coastguard Worker     struct handle* chan;
85*344aa361SAndroid Build Coastguard Worker     enum chan_state chan_state;
86*344aa361SAndroid Build Coastguard Worker     bool event_dropped;
87*344aa361SAndroid Build Coastguard Worker };
88*344aa361SAndroid Build Coastguard Worker 
89*344aa361SAndroid Build Coastguard Worker static struct metrics_ctx ctx;
90*344aa361SAndroid Build Coastguard Worker static mutex_t ctx_lock = MUTEX_INITIAL_VALUE(ctx_lock);
91*344aa361SAndroid Build Coastguard Worker 
recv_resp(struct handle * chan,uint32_t cmd)92*344aa361SAndroid Build Coastguard Worker static int recv_resp(struct handle* chan, uint32_t cmd) {
93*344aa361SAndroid Build Coastguard Worker     int rc;
94*344aa361SAndroid Build Coastguard Worker     struct ipc_msg_info msg_info;
95*344aa361SAndroid Build Coastguard Worker     struct metrics_resp resp;
96*344aa361SAndroid Build Coastguard Worker 
97*344aa361SAndroid Build Coastguard Worker     rc = ipc_get_msg(chan, &msg_info);
98*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
99*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) to get message\n", rc);
100*344aa361SAndroid Build Coastguard Worker         return rc;
101*344aa361SAndroid Build Coastguard Worker     }
102*344aa361SAndroid Build Coastguard Worker 
103*344aa361SAndroid Build Coastguard Worker     struct iovec_kern iov = {
104*344aa361SAndroid Build Coastguard Worker             .iov_base = &resp,
105*344aa361SAndroid Build Coastguard Worker             .iov_len = sizeof(resp),
106*344aa361SAndroid Build Coastguard Worker     };
107*344aa361SAndroid Build Coastguard Worker     struct ipc_msg_kern ipc_msg = {
108*344aa361SAndroid Build Coastguard Worker             .num_iov = 1,
109*344aa361SAndroid Build Coastguard Worker             .iov = &iov,
110*344aa361SAndroid Build Coastguard Worker             .num_handles = 0,
111*344aa361SAndroid Build Coastguard Worker             .handles = NULL,
112*344aa361SAndroid Build Coastguard Worker     };
113*344aa361SAndroid Build Coastguard Worker     rc = ipc_read_msg(chan, msg_info.id, 0, &ipc_msg);
114*344aa361SAndroid Build Coastguard Worker     ipc_put_msg(chan, msg_info.id);
115*344aa361SAndroid Build Coastguard Worker 
116*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
117*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) ipc_read_msg().\n", rc);
118*344aa361SAndroid Build Coastguard Worker         return rc;
119*344aa361SAndroid Build Coastguard Worker     }
120*344aa361SAndroid Build Coastguard Worker 
121*344aa361SAndroid Build Coastguard Worker     if (rc != sizeof(resp)) {
122*344aa361SAndroid Build Coastguard Worker         TRACEF("unexpected number of bytes received: %d.\n", rc);
123*344aa361SAndroid Build Coastguard Worker         return ERR_BAD_LEN;
124*344aa361SAndroid Build Coastguard Worker     }
125*344aa361SAndroid Build Coastguard Worker 
126*344aa361SAndroid Build Coastguard Worker     if (resp.cmd != (cmd | METRICS_CMD_RESP_BIT)) {
127*344aa361SAndroid Build Coastguard Worker         TRACEF("unknown command received: %u %u.\n", resp.cmd, cmd);
128*344aa361SAndroid Build Coastguard Worker         return ERR_CMD_UNKNOWN;
129*344aa361SAndroid Build Coastguard Worker     }
130*344aa361SAndroid Build Coastguard Worker 
131*344aa361SAndroid Build Coastguard Worker     if (resp.status != METRICS_NO_ERROR) {
132*344aa361SAndroid Build Coastguard Worker         TRACEF("event report failure: %d.\n", resp.status);
133*344aa361SAndroid Build Coastguard Worker         /* This error is not severe enough to close the connection. */
134*344aa361SAndroid Build Coastguard Worker     }
135*344aa361SAndroid Build Coastguard Worker 
136*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
137*344aa361SAndroid Build Coastguard Worker }
138*344aa361SAndroid Build Coastguard Worker 
send_req(struct handle * chan,struct ipc_msg_kern * ipc_msg,size_t total_len)139*344aa361SAndroid Build Coastguard Worker static int send_req(struct handle* chan,
140*344aa361SAndroid Build Coastguard Worker                     struct ipc_msg_kern* ipc_msg,
141*344aa361SAndroid Build Coastguard Worker                     size_t total_len) {
142*344aa361SAndroid Build Coastguard Worker     int rc = ipc_send_msg(chan, ipc_msg);
143*344aa361SAndroid Build Coastguard Worker     if (rc < 0) {
144*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) to send message\n", rc);
145*344aa361SAndroid Build Coastguard Worker         return rc;
146*344aa361SAndroid Build Coastguard Worker     }
147*344aa361SAndroid Build Coastguard Worker 
148*344aa361SAndroid Build Coastguard Worker     if (rc != (int)total_len) {
149*344aa361SAndroid Build Coastguard Worker         TRACEF("unexpected number of bytes sent: %d\n", rc);
150*344aa361SAndroid Build Coastguard Worker         return ERR_BAD_LEN;
151*344aa361SAndroid Build Coastguard Worker     }
152*344aa361SAndroid Build Coastguard Worker 
153*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
154*344aa361SAndroid Build Coastguard Worker }
155*344aa361SAndroid Build Coastguard Worker 
report_crash(struct handle * chan,struct trusty_app * app,const struct trusty_error_args * error_args)156*344aa361SAndroid Build Coastguard Worker static int report_crash(struct handle* chan,
157*344aa361SAndroid Build Coastguard Worker                         struct trusty_app* app,
158*344aa361SAndroid Build Coastguard Worker                         const struct trusty_error_args* error_args) {
159*344aa361SAndroid Build Coastguard Worker     int rc;
160*344aa361SAndroid Build Coastguard Worker     struct metrics_req req = {};
161*344aa361SAndroid Build Coastguard Worker     struct metrics_report_crash_req args = {};
162*344aa361SAndroid Build Coastguard Worker     size_t total_len;
163*344aa361SAndroid Build Coastguard Worker 
164*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(is_mutex_held(&ctx_lock));
165*344aa361SAndroid Build Coastguard Worker 
166*344aa361SAndroid Build Coastguard Worker     uuid_to_str(&app->props.uuid, args.app_id);
167*344aa361SAndroid Build Coastguard Worker 
168*344aa361SAndroid Build Coastguard Worker     req.cmd = METRICS_CMD_REPORT_CRASH;
169*344aa361SAndroid Build Coastguard Worker     args.crash_reason = error_args->reason;
170*344aa361SAndroid Build Coastguard Worker     args.far = error_args->far;
171*344aa361SAndroid Build Coastguard Worker     memcpy(args.far_hash, error_args->far_hash, sizeof(args.far_hash));
172*344aa361SAndroid Build Coastguard Worker     args.elr = error_args->elr;
173*344aa361SAndroid Build Coastguard Worker     memcpy(args.elr_hash, error_args->elr_hash, sizeof(args.elr_hash));
174*344aa361SAndroid Build Coastguard Worker     args.is_hash = error_args->is_hash;
175*344aa361SAndroid Build Coastguard Worker 
176*344aa361SAndroid Build Coastguard Worker     struct iovec_kern iovs[] = {
177*344aa361SAndroid Build Coastguard Worker             {
178*344aa361SAndroid Build Coastguard Worker                     .iov_base = &req,
179*344aa361SAndroid Build Coastguard Worker                     .iov_len = sizeof(req),
180*344aa361SAndroid Build Coastguard Worker             },
181*344aa361SAndroid Build Coastguard Worker             {
182*344aa361SAndroid Build Coastguard Worker                     .iov_base = &args,
183*344aa361SAndroid Build Coastguard Worker                     .iov_len = sizeof(args),
184*344aa361SAndroid Build Coastguard Worker             },
185*344aa361SAndroid Build Coastguard Worker     };
186*344aa361SAndroid Build Coastguard Worker     struct ipc_msg_kern ipc_msg = {
187*344aa361SAndroid Build Coastguard Worker             .num_iov = countof(iovs),
188*344aa361SAndroid Build Coastguard Worker             .iov = iovs,
189*344aa361SAndroid Build Coastguard Worker     };
190*344aa361SAndroid Build Coastguard Worker 
191*344aa361SAndroid Build Coastguard Worker     total_len = sizeof(req) + sizeof(args);
192*344aa361SAndroid Build Coastguard Worker     rc = send_req(chan, &ipc_msg, total_len);
193*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
194*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) report app crash\n", rc);
195*344aa361SAndroid Build Coastguard Worker         return rc;
196*344aa361SAndroid Build Coastguard Worker     }
197*344aa361SAndroid Build Coastguard Worker 
198*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
199*344aa361SAndroid Build Coastguard Worker }
200*344aa361SAndroid Build Coastguard Worker 
report_exit(struct handle * chan,struct trusty_app * app,const struct trusty_error_args * error_args)201*344aa361SAndroid Build Coastguard Worker static int report_exit(struct handle* chan,
202*344aa361SAndroid Build Coastguard Worker                         struct trusty_app* app,
203*344aa361SAndroid Build Coastguard Worker                         const struct trusty_error_args* error_args) {
204*344aa361SAndroid Build Coastguard Worker     int rc;
205*344aa361SAndroid Build Coastguard Worker     struct metrics_req req = {};
206*344aa361SAndroid Build Coastguard Worker     struct metrics_report_exit_req args = {};
207*344aa361SAndroid Build Coastguard Worker     size_t total_len;
208*344aa361SAndroid Build Coastguard Worker 
209*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(is_mutex_held(&ctx_lock));
210*344aa361SAndroid Build Coastguard Worker 
211*344aa361SAndroid Build Coastguard Worker     uuid_to_str(&app->props.uuid, args.app_id);
212*344aa361SAndroid Build Coastguard Worker 
213*344aa361SAndroid Build Coastguard Worker     req.cmd = METRICS_CMD_REPORT_EXIT;
214*344aa361SAndroid Build Coastguard Worker     args.exit_code = error_args->reason;
215*344aa361SAndroid Build Coastguard Worker 
216*344aa361SAndroid Build Coastguard Worker     struct iovec_kern iovs[] = {
217*344aa361SAndroid Build Coastguard Worker             {
218*344aa361SAndroid Build Coastguard Worker                     .iov_base = &req,
219*344aa361SAndroid Build Coastguard Worker                     .iov_len = sizeof(req),
220*344aa361SAndroid Build Coastguard Worker             },
221*344aa361SAndroid Build Coastguard Worker             {
222*344aa361SAndroid Build Coastguard Worker                     .iov_base = &args,
223*344aa361SAndroid Build Coastguard Worker                     .iov_len = sizeof(args),
224*344aa361SAndroid Build Coastguard Worker             },
225*344aa361SAndroid Build Coastguard Worker     };
226*344aa361SAndroid Build Coastguard Worker     struct ipc_msg_kern ipc_msg = {
227*344aa361SAndroid Build Coastguard Worker             .num_iov = countof(iovs),
228*344aa361SAndroid Build Coastguard Worker             .iov = iovs,
229*344aa361SAndroid Build Coastguard Worker     };
230*344aa361SAndroid Build Coastguard Worker 
231*344aa361SAndroid Build Coastguard Worker     total_len = sizeof(req) + sizeof(args);
232*344aa361SAndroid Build Coastguard Worker     rc = send_req(chan, &ipc_msg, total_len);
233*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
234*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) report app exit\n", rc);
235*344aa361SAndroid Build Coastguard Worker         return rc;
236*344aa361SAndroid Build Coastguard Worker     }
237*344aa361SAndroid Build Coastguard Worker 
238*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
239*344aa361SAndroid Build Coastguard Worker }
240*344aa361SAndroid Build Coastguard Worker 
report_event_drop(struct handle * chan)241*344aa361SAndroid Build Coastguard Worker static int report_event_drop(struct handle* chan) {
242*344aa361SAndroid Build Coastguard Worker     int rc;
243*344aa361SAndroid Build Coastguard Worker     struct metrics_req req;
244*344aa361SAndroid Build Coastguard Worker 
245*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(is_mutex_held(&ctx_lock));
246*344aa361SAndroid Build Coastguard Worker 
247*344aa361SAndroid Build Coastguard Worker     req.cmd = METRICS_CMD_REPORT_EVENT_DROP;
248*344aa361SAndroid Build Coastguard Worker     req.reserved = 0;
249*344aa361SAndroid Build Coastguard Worker 
250*344aa361SAndroid Build Coastguard Worker     struct iovec_kern iov = {
251*344aa361SAndroid Build Coastguard Worker             .iov_base = &req,
252*344aa361SAndroid Build Coastguard Worker             .iov_len = sizeof(req),
253*344aa361SAndroid Build Coastguard Worker     };
254*344aa361SAndroid Build Coastguard Worker     struct ipc_msg_kern ipc_msg = {
255*344aa361SAndroid Build Coastguard Worker             .num_iov = 1,
256*344aa361SAndroid Build Coastguard Worker             .iov = &iov,
257*344aa361SAndroid Build Coastguard Worker     };
258*344aa361SAndroid Build Coastguard Worker 
259*344aa361SAndroid Build Coastguard Worker     rc = send_req(chan, &ipc_msg, sizeof(req));
260*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
261*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) report event drop\n", rc);
262*344aa361SAndroid Build Coastguard Worker         return rc;
263*344aa361SAndroid Build Coastguard Worker     }
264*344aa361SAndroid Build Coastguard Worker 
265*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
266*344aa361SAndroid Build Coastguard Worker }
267*344aa361SAndroid Build Coastguard Worker 
on_ta_crash(struct trusty_app * app,const struct trusty_error_args * error_args)268*344aa361SAndroid Build Coastguard Worker static int on_ta_crash(struct trusty_app* app, const struct trusty_error_args* error_args) {
269*344aa361SAndroid Build Coastguard Worker     int rc;
270*344aa361SAndroid Build Coastguard Worker 
271*344aa361SAndroid Build Coastguard Worker     mutex_acquire(&ctx_lock);
272*344aa361SAndroid Build Coastguard Worker 
273*344aa361SAndroid Build Coastguard Worker     if (ctx.chan_state != CHAN_STATE_IDLE) {
274*344aa361SAndroid Build Coastguard Worker         TRACEF("there is a metrics event still in progress or metrics TA "
275*344aa361SAndroid Build Coastguard Worker                "is unavailable\n");
276*344aa361SAndroid Build Coastguard Worker         ctx.event_dropped = true;
277*344aa361SAndroid Build Coastguard Worker         goto out;
278*344aa361SAndroid Build Coastguard Worker     }
279*344aa361SAndroid Build Coastguard Worker 
280*344aa361SAndroid Build Coastguard Worker     if (!ctx.chan) {
281*344aa361SAndroid Build Coastguard Worker         TRACEF("failed get metrics consumer channel\n");
282*344aa361SAndroid Build Coastguard Worker         goto out;
283*344aa361SAndroid Build Coastguard Worker     }
284*344aa361SAndroid Build Coastguard Worker 
285*344aa361SAndroid Build Coastguard Worker     if(error_args->is_crash) {
286*344aa361SAndroid Build Coastguard Worker         rc = report_crash(ctx.chan, app, error_args);
287*344aa361SAndroid Build Coastguard Worker         ctx.chan_state = CHAN_STATE_WAITING_CRASH_RESP;
288*344aa361SAndroid Build Coastguard Worker     }
289*344aa361SAndroid Build Coastguard Worker     else {
290*344aa361SAndroid Build Coastguard Worker         rc = report_exit(ctx.chan, app, error_args);
291*344aa361SAndroid Build Coastguard Worker         ctx.chan_state = CHAN_STATE_WAITING_EXIT_RESP;
292*344aa361SAndroid Build Coastguard Worker     }
293*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
294*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) report app crash\n", rc);
295*344aa361SAndroid Build Coastguard Worker         goto err;
296*344aa361SAndroid Build Coastguard Worker     }
297*344aa361SAndroid Build Coastguard Worker 
298*344aa361SAndroid Build Coastguard Worker     goto out;
299*344aa361SAndroid Build Coastguard Worker 
300*344aa361SAndroid Build Coastguard Worker err:
301*344aa361SAndroid Build Coastguard Worker     handle_close(ctx.chan);
302*344aa361SAndroid Build Coastguard Worker     ctx.chan = NULL;
303*344aa361SAndroid Build Coastguard Worker out:
304*344aa361SAndroid Build Coastguard Worker     mutex_release(&ctx_lock);
305*344aa361SAndroid Build Coastguard Worker     /*
306*344aa361SAndroid Build Coastguard Worker      * Returning an error here will bring down the kernel. Metrics reporting
307*344aa361SAndroid Build Coastguard Worker      * isn't critical. So, we always return NO_ERROR. If something goes wrong,
308*344aa361SAndroid Build Coastguard Worker      * printing an error should suffice.
309*344aa361SAndroid Build Coastguard Worker      */
310*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
311*344aa361SAndroid Build Coastguard Worker }
312*344aa361SAndroid Build Coastguard Worker 
313*344aa361SAndroid Build Coastguard Worker static struct trusty_app_notifier notifier = {
314*344aa361SAndroid Build Coastguard Worker         .crash = on_ta_crash,
315*344aa361SAndroid Build Coastguard Worker };
316*344aa361SAndroid Build Coastguard Worker 
handle_chan(struct dpc * work)317*344aa361SAndroid Build Coastguard Worker static void handle_chan(struct dpc* work) {
318*344aa361SAndroid Build Coastguard Worker     int rc;
319*344aa361SAndroid Build Coastguard Worker     uint32_t event;
320*344aa361SAndroid Build Coastguard Worker 
321*344aa361SAndroid Build Coastguard Worker     mutex_acquire(&ctx_lock);
322*344aa361SAndroid Build Coastguard Worker 
323*344aa361SAndroid Build Coastguard Worker     event = ctx.chan->ops->poll(ctx.chan, ~0U, true);
324*344aa361SAndroid Build Coastguard Worker     if (event & IPC_HANDLE_POLL_HUP) {
325*344aa361SAndroid Build Coastguard Worker         TRACEF("received IPC_HANDLE_POLL_HUP, closing channel\n");
326*344aa361SAndroid Build Coastguard Worker         goto err;
327*344aa361SAndroid Build Coastguard Worker     }
328*344aa361SAndroid Build Coastguard Worker 
329*344aa361SAndroid Build Coastguard Worker     switch (ctx.chan_state) {
330*344aa361SAndroid Build Coastguard Worker     case CHAN_STATE_WAITING_CHAN_READY:
331*344aa361SAndroid Build Coastguard Worker         if (!(event & IPC_HANDLE_POLL_READY)) {
332*344aa361SAndroid Build Coastguard Worker             TRACEF("unexpected channel event: 0x%x\n", event);
333*344aa361SAndroid Build Coastguard Worker             goto err;
334*344aa361SAndroid Build Coastguard Worker         }
335*344aa361SAndroid Build Coastguard Worker 
336*344aa361SAndroid Build Coastguard Worker         ctx.chan_state = CHAN_STATE_IDLE;
337*344aa361SAndroid Build Coastguard Worker         goto out;
338*344aa361SAndroid Build Coastguard Worker 
339*344aa361SAndroid Build Coastguard Worker     case CHAN_STATE_IDLE:
340*344aa361SAndroid Build Coastguard Worker         TRACEF("unexpected channel event: 0x%x\n", event);
341*344aa361SAndroid Build Coastguard Worker         goto err;
342*344aa361SAndroid Build Coastguard Worker 
343*344aa361SAndroid Build Coastguard Worker     case CHAN_STATE_WAITING_CRASH_RESP:
344*344aa361SAndroid Build Coastguard Worker         if (!(event & IPC_HANDLE_POLL_MSG)) {
345*344aa361SAndroid Build Coastguard Worker             TRACEF("unexpected channel event: 0x%x\n", event);
346*344aa361SAndroid Build Coastguard Worker             goto err;
347*344aa361SAndroid Build Coastguard Worker         }
348*344aa361SAndroid Build Coastguard Worker 
349*344aa361SAndroid Build Coastguard Worker         rc = recv_resp(ctx.chan, METRICS_CMD_REPORT_CRASH);
350*344aa361SAndroid Build Coastguard Worker         if (rc != NO_ERROR) {
351*344aa361SAndroid Build Coastguard Worker             TRACEF("failed (%d) receive response\n", rc);
352*344aa361SAndroid Build Coastguard Worker             goto err;
353*344aa361SAndroid Build Coastguard Worker         }
354*344aa361SAndroid Build Coastguard Worker 
355*344aa361SAndroid Build Coastguard Worker         ctx.chan_state = CHAN_STATE_IDLE;
356*344aa361SAndroid Build Coastguard Worker 
357*344aa361SAndroid Build Coastguard Worker         if (ctx.event_dropped) {
358*344aa361SAndroid Build Coastguard Worker             rc = report_event_drop(ctx.chan);
359*344aa361SAndroid Build Coastguard Worker             if (rc != NO_ERROR) {
360*344aa361SAndroid Build Coastguard Worker                 TRACEF("failed (%d) report event drop\n", rc);
361*344aa361SAndroid Build Coastguard Worker                 goto err;
362*344aa361SAndroid Build Coastguard Worker             }
363*344aa361SAndroid Build Coastguard Worker             ctx.chan_state = CHAN_STATE_WAITING_EVENT_DROP_RESP;
364*344aa361SAndroid Build Coastguard Worker             goto out;
365*344aa361SAndroid Build Coastguard Worker         }
366*344aa361SAndroid Build Coastguard Worker 
367*344aa361SAndroid Build Coastguard Worker         goto out;
368*344aa361SAndroid Build Coastguard Worker 
369*344aa361SAndroid Build Coastguard Worker     case CHAN_STATE_WAITING_EXIT_RESP:
370*344aa361SAndroid Build Coastguard Worker         if (!(event & IPC_HANDLE_POLL_MSG)) {
371*344aa361SAndroid Build Coastguard Worker             TRACEF("unexpected channel event: 0x%x\n", event);
372*344aa361SAndroid Build Coastguard Worker             goto err;
373*344aa361SAndroid Build Coastguard Worker         }
374*344aa361SAndroid Build Coastguard Worker 
375*344aa361SAndroid Build Coastguard Worker         rc = recv_resp(ctx.chan, METRICS_CMD_REPORT_EXIT);
376*344aa361SAndroid Build Coastguard Worker         if (rc != NO_ERROR) {
377*344aa361SAndroid Build Coastguard Worker             TRACEF("failed (%d) receive response\n", rc);
378*344aa361SAndroid Build Coastguard Worker             goto err;
379*344aa361SAndroid Build Coastguard Worker         }
380*344aa361SAndroid Build Coastguard Worker 
381*344aa361SAndroid Build Coastguard Worker         ctx.chan_state = CHAN_STATE_IDLE;
382*344aa361SAndroid Build Coastguard Worker 
383*344aa361SAndroid Build Coastguard Worker         if (ctx.event_dropped) {
384*344aa361SAndroid Build Coastguard Worker             rc = report_event_drop(ctx.chan);
385*344aa361SAndroid Build Coastguard Worker             if (rc != NO_ERROR) {
386*344aa361SAndroid Build Coastguard Worker                 TRACEF("failed (%d) report event drop\n", rc);
387*344aa361SAndroid Build Coastguard Worker                 goto err;
388*344aa361SAndroid Build Coastguard Worker             }
389*344aa361SAndroid Build Coastguard Worker             ctx.chan_state = CHAN_STATE_WAITING_EVENT_DROP_RESP;
390*344aa361SAndroid Build Coastguard Worker             goto out;
391*344aa361SAndroid Build Coastguard Worker         }
392*344aa361SAndroid Build Coastguard Worker 
393*344aa361SAndroid Build Coastguard Worker         goto out;
394*344aa361SAndroid Build Coastguard Worker 
395*344aa361SAndroid Build Coastguard Worker     case CHAN_STATE_WAITING_EVENT_DROP_RESP:
396*344aa361SAndroid Build Coastguard Worker         if (!(event & IPC_HANDLE_POLL_MSG)) {
397*344aa361SAndroid Build Coastguard Worker             TRACEF("unexpected channel event: 0x%x\n", event);
398*344aa361SAndroid Build Coastguard Worker             goto err;
399*344aa361SAndroid Build Coastguard Worker         }
400*344aa361SAndroid Build Coastguard Worker 
401*344aa361SAndroid Build Coastguard Worker         rc = recv_resp(ctx.chan, METRICS_CMD_REPORT_EVENT_DROP);
402*344aa361SAndroid Build Coastguard Worker         if (rc != NO_ERROR) {
403*344aa361SAndroid Build Coastguard Worker             TRACEF("failed (%d) receive response\n", rc);
404*344aa361SAndroid Build Coastguard Worker             goto err;
405*344aa361SAndroid Build Coastguard Worker         }
406*344aa361SAndroid Build Coastguard Worker 
407*344aa361SAndroid Build Coastguard Worker         ctx.chan_state = CHAN_STATE_IDLE;
408*344aa361SAndroid Build Coastguard Worker         ctx.event_dropped = false;
409*344aa361SAndroid Build Coastguard Worker         goto out;
410*344aa361SAndroid Build Coastguard Worker     }
411*344aa361SAndroid Build Coastguard Worker 
412*344aa361SAndroid Build Coastguard Worker err:
413*344aa361SAndroid Build Coastguard Worker     handle_close(ctx.chan);
414*344aa361SAndroid Build Coastguard Worker     ctx.chan = NULL;
415*344aa361SAndroid Build Coastguard Worker out:
416*344aa361SAndroid Build Coastguard Worker     mutex_release(&ctx_lock);
417*344aa361SAndroid Build Coastguard Worker }
418*344aa361SAndroid Build Coastguard Worker 
419*344aa361SAndroid Build Coastguard Worker static struct dpc chan_event_work = {
420*344aa361SAndroid Build Coastguard Worker         .node = LIST_INITIAL_CLEARED_VALUE,
421*344aa361SAndroid Build Coastguard Worker         .cb = handle_chan,
422*344aa361SAndroid Build Coastguard Worker };
423*344aa361SAndroid Build Coastguard Worker 
on_handle_event(struct handle_waiter * waiter)424*344aa361SAndroid Build Coastguard Worker static void on_handle_event(struct handle_waiter* waiter) {
425*344aa361SAndroid Build Coastguard Worker     int rc = dpc_enqueue_work(NULL, &chan_event_work, false);
426*344aa361SAndroid Build Coastguard Worker     if (rc != NO_ERROR) {
427*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) to enqueue dpc work\n", rc);
428*344aa361SAndroid Build Coastguard Worker     }
429*344aa361SAndroid Build Coastguard Worker }
430*344aa361SAndroid Build Coastguard Worker 
431*344aa361SAndroid Build Coastguard Worker static struct handle_waiter waiter = {
432*344aa361SAndroid Build Coastguard Worker         .node = LIST_INITIAL_CLEARED_VALUE,
433*344aa361SAndroid Build Coastguard Worker         .notify_proc = on_handle_event,
434*344aa361SAndroid Build Coastguard Worker };
435*344aa361SAndroid Build Coastguard Worker 
metrics_init(uint level)436*344aa361SAndroid Build Coastguard Worker static void metrics_init(uint level) {
437*344aa361SAndroid Build Coastguard Worker     int rc = ipc_port_connect_async(&kernel_uuid, METRICS_CONSUMER_PORT,
438*344aa361SAndroid Build Coastguard Worker                                     IPC_PORT_PATH_MAX,
439*344aa361SAndroid Build Coastguard Worker                                     IPC_CONNECT_WAIT_FOR_PORT, &ctx.chan);
440*344aa361SAndroid Build Coastguard Worker     if (rc) {
441*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) to connect to port\n", rc);
442*344aa361SAndroid Build Coastguard Worker         goto err_port_connect;
443*344aa361SAndroid Build Coastguard Worker     }
444*344aa361SAndroid Build Coastguard Worker 
445*344aa361SAndroid Build Coastguard Worker     rc = trusty_register_app_notifier(&notifier);
446*344aa361SAndroid Build Coastguard Worker     if (rc) {
447*344aa361SAndroid Build Coastguard Worker         TRACEF("failed (%d) to register app notifier\n", rc);
448*344aa361SAndroid Build Coastguard Worker         goto err_app_notifier;
449*344aa361SAndroid Build Coastguard Worker     }
450*344aa361SAndroid Build Coastguard Worker 
451*344aa361SAndroid Build Coastguard Worker     ctx.chan_state = CHAN_STATE_WAITING_CHAN_READY;
452*344aa361SAndroid Build Coastguard Worker     handle_add_waiter(ctx.chan, &waiter);
453*344aa361SAndroid Build Coastguard Worker 
454*344aa361SAndroid Build Coastguard Worker     return;
455*344aa361SAndroid Build Coastguard Worker 
456*344aa361SAndroid Build Coastguard Worker err_app_notifier:
457*344aa361SAndroid Build Coastguard Worker     handle_close(ctx.chan);
458*344aa361SAndroid Build Coastguard Worker     ctx.chan = NULL;
459*344aa361SAndroid Build Coastguard Worker err_port_connect:
460*344aa361SAndroid Build Coastguard Worker     return;
461*344aa361SAndroid Build Coastguard Worker }
462*344aa361SAndroid Build Coastguard Worker 
463*344aa361SAndroid Build Coastguard Worker /* Need to init before (LK_INIT_LEVEL_APPS - 1) to register an app notifier. */
464*344aa361SAndroid Build Coastguard Worker LK_INIT_HOOK(metrics, metrics_init, LK_INIT_LEVEL_APPS - 2);
465