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