xref: /optee_os/ldelf/ftrace.c (revision c86f218c5bc8ba0deb6e7c6ff58f8db93c01e32f)
1*c86f218cSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*c86f218cSJens Wiklander /*
3*c86f218cSJens Wiklander  * Copyright (c) 2019, Linaro Limited
4*c86f218cSJens Wiklander  */
5*c86f218cSJens Wiklander 
6*c86f218cSJens Wiklander #include <assert.h>
7*c86f218cSJens Wiklander #include <printk.h>
8*c86f218cSJens Wiklander #include <sys/queue.h>
9*c86f218cSJens Wiklander #include <types_ext.h>
10*c86f218cSJens Wiklander #include <util.h>
11*c86f218cSJens Wiklander #include <user_ta_header.h>
12*c86f218cSJens Wiklander 
13*c86f218cSJens Wiklander #include "ftrace.h"
14*c86f218cSJens Wiklander #include "ta_elf.h"
15*c86f218cSJens Wiklander 
16*c86f218cSJens Wiklander #define MIN_FTRACE_BUF_SIZE	1024
17*c86f218cSJens Wiklander #define MAX_HEADER_STRLEN	128
18*c86f218cSJens Wiklander 
19*c86f218cSJens Wiklander static struct __ftrace_info *finfo;
20*c86f218cSJens Wiklander static struct ftrace_buf *fbuf;
21*c86f218cSJens Wiklander 
22*c86f218cSJens Wiklander bool ftrace_init(void)
23*c86f218cSJens Wiklander {
24*c86f218cSJens Wiklander 	struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue);
25*c86f218cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
26*c86f218cSJens Wiklander 	vaddr_t val = 0;
27*c86f218cSJens Wiklander 	int count = 0;
28*c86f218cSJens Wiklander 	size_t fbuf_size = 0;
29*c86f218cSJens Wiklander 
30*c86f218cSJens Wiklander 	res = ta_elf_resolve_sym("__ftrace_info", &val);
31*c86f218cSJens Wiklander 	if (res)
32*c86f218cSJens Wiklander 		return false;
33*c86f218cSJens Wiklander 
34*c86f218cSJens Wiklander 	finfo = (struct __ftrace_info *)val;
35*c86f218cSJens Wiklander 
36*c86f218cSJens Wiklander 	assert(elf && elf->is_main);
37*c86f218cSJens Wiklander 
38*c86f218cSJens Wiklander 	if (SUB_OVERFLOW(finfo->buf_end, finfo->buf_start, &fbuf_size))
39*c86f218cSJens Wiklander 		return false;
40*c86f218cSJens Wiklander 
41*c86f218cSJens Wiklander 	if (fbuf_size < MIN_FTRACE_BUF_SIZE) {
42*c86f218cSJens Wiklander 		DMSG("ftrace buffer too small");
43*c86f218cSJens Wiklander 		return false;
44*c86f218cSJens Wiklander 	}
45*c86f218cSJens Wiklander 
46*c86f218cSJens Wiklander 	fbuf = (struct ftrace_buf *)finfo->buf_start;
47*c86f218cSJens Wiklander 	fbuf->head_off = sizeof(struct ftrace_buf);
48*c86f218cSJens Wiklander 	count = snprintk((char *)fbuf + fbuf->head_off, MAX_HEADER_STRLEN,
49*c86f218cSJens Wiklander 			 "Function graph for TA: %pUl @ %lx\n",
50*c86f218cSJens Wiklander 			 (void *)&elf->uuid, elf->load_addr);
51*c86f218cSJens Wiklander 	assert(count < MAX_HEADER_STRLEN);
52*c86f218cSJens Wiklander 
53*c86f218cSJens Wiklander 	fbuf->ret_func_ptr = finfo->ret_ptr;
54*c86f218cSJens Wiklander 	fbuf->ret_idx = 0;
55*c86f218cSJens Wiklander 	fbuf->lr_idx = 0;
56*c86f218cSJens Wiklander 	fbuf->buf_off = fbuf->head_off + count;
57*c86f218cSJens Wiklander 	fbuf->curr_size = 0;
58*c86f218cSJens Wiklander 	fbuf->max_size = fbuf_size - sizeof(struct ftrace_buf) - count;
59*c86f218cSJens Wiklander 
60*c86f218cSJens Wiklander 	return true;
61*c86f218cSJens Wiklander }
62*c86f218cSJens Wiklander 
63*c86f218cSJens Wiklander void ftrace_copy_buf(void *pctx, void (*copy_func)(void *pctx, void *b,
64*c86f218cSJens Wiklander 						   size_t bl))
65*c86f218cSJens Wiklander {
66*c86f218cSJens Wiklander 	if (fbuf) {
67*c86f218cSJens Wiklander 		struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue);
68*c86f218cSJens Wiklander 		size_t dump_size = fbuf->buf_off - fbuf->head_off +
69*c86f218cSJens Wiklander 				   fbuf->curr_size;
70*c86f218cSJens Wiklander 
71*c86f218cSJens Wiklander 		assert(elf && elf->is_main);
72*c86f218cSJens Wiklander 		copy_func(pctx, (char *)fbuf + fbuf->head_off, dump_size);
73*c86f218cSJens Wiklander 	}
74*c86f218cSJens Wiklander }
75*c86f218cSJens Wiklander 
76*c86f218cSJens Wiklander void ftrace_map_lr(uint64_t *lr)
77*c86f218cSJens Wiklander {
78*c86f218cSJens Wiklander 	if (fbuf) {
79*c86f218cSJens Wiklander 		if (*lr == fbuf->ret_func_ptr &&
80*c86f218cSJens Wiklander 		    fbuf->lr_idx < fbuf->ret_idx) {
81*c86f218cSJens Wiklander 			fbuf->lr_idx++;
82*c86f218cSJens Wiklander 			*lr = fbuf->ret_stack[fbuf->ret_idx - fbuf->lr_idx];
83*c86f218cSJens Wiklander 		}
84*c86f218cSJens Wiklander 	}
85*c86f218cSJens Wiklander }
86