12e192b24SSimon Glass /* 22e192b24SSimon Glass * Copyright (c) 2011 The Chromium OS Authors. 32e192b24SSimon Glass * 42e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 52e192b24SSimon Glass */ 62e192b24SSimon Glass 72e192b24SSimon Glass #include <common.h> 82e192b24SSimon Glass #include <command.h> 92e192b24SSimon Glass #include <mapmem.h> 102e192b24SSimon Glass #include <trace.h> 112e192b24SSimon Glass #include <asm/io.h> 122e192b24SSimon Glass 132e192b24SSimon Glass static int get_args(int argc, char * const argv[], char **buff, 142e192b24SSimon Glass size_t *buff_ptr, size_t *buff_size) 152e192b24SSimon Glass { 162e192b24SSimon Glass if (argc < 2) 172e192b24SSimon Glass return -1; 182e192b24SSimon Glass if (argc < 4) { 192e192b24SSimon Glass *buff_size = getenv_ulong("profsize", 16, 0); 202e192b24SSimon Glass *buff = map_sysmem(getenv_ulong("profbase", 16, 0), 212e192b24SSimon Glass *buff_size); 222e192b24SSimon Glass *buff_ptr = getenv_ulong("profoffset", 16, 0); 232e192b24SSimon Glass } else { 242e192b24SSimon Glass *buff_size = simple_strtoul(argv[3], NULL, 16); 252e192b24SSimon Glass *buff = map_sysmem(simple_strtoul(argv[2], NULL, 16), 262e192b24SSimon Glass *buff_size); 272e192b24SSimon Glass *buff_ptr = 0; 282e192b24SSimon Glass }; 292e192b24SSimon Glass return 0; 302e192b24SSimon Glass } 312e192b24SSimon Glass 322e192b24SSimon Glass static int create_func_list(int argc, char * const argv[]) 332e192b24SSimon Glass { 342e192b24SSimon Glass size_t buff_size, avail, buff_ptr, used; 352e192b24SSimon Glass unsigned int needed; 362e192b24SSimon Glass char *buff; 372e192b24SSimon Glass int err; 382e192b24SSimon Glass 392e192b24SSimon Glass if (get_args(argc, argv, &buff, &buff_ptr, &buff_size)) 402e192b24SSimon Glass return -1; 412e192b24SSimon Glass 422e192b24SSimon Glass avail = buff_size - buff_ptr; 432e192b24SSimon Glass err = trace_list_functions(buff + buff_ptr, avail, &needed); 442e192b24SSimon Glass if (err) 452e192b24SSimon Glass printf("Error: truncated (%#x bytes needed)\n", needed); 46*5eca9779SSimon Glass used = min(avail, (size_t)needed); 472e192b24SSimon Glass printf("Function trace dumped to %08lx, size %#zx\n", 482e192b24SSimon Glass (ulong)map_to_sysmem(buff + buff_ptr), used); 492e192b24SSimon Glass setenv_hex("profbase", map_to_sysmem(buff)); 502e192b24SSimon Glass setenv_hex("profsize", buff_size); 512e192b24SSimon Glass setenv_hex("profoffset", buff_ptr + used); 522e192b24SSimon Glass 532e192b24SSimon Glass return 0; 542e192b24SSimon Glass } 552e192b24SSimon Glass 562e192b24SSimon Glass static int create_call_list(int argc, char * const argv[]) 572e192b24SSimon Glass { 582e192b24SSimon Glass size_t buff_size, avail, buff_ptr, used; 592e192b24SSimon Glass unsigned int needed; 602e192b24SSimon Glass char *buff; 612e192b24SSimon Glass int err; 622e192b24SSimon Glass 632e192b24SSimon Glass if (get_args(argc, argv, &buff, &buff_ptr, &buff_size)) 642e192b24SSimon Glass return -1; 652e192b24SSimon Glass 662e192b24SSimon Glass avail = buff_size - buff_ptr; 672e192b24SSimon Glass err = trace_list_calls(buff + buff_ptr, avail, &needed); 682e192b24SSimon Glass if (err) 692e192b24SSimon Glass printf("Error: truncated (%#x bytes needed)\n", needed); 70*5eca9779SSimon Glass used = min(avail, (size_t)needed); 712e192b24SSimon Glass printf("Call list dumped to %08lx, size %#zx\n", 722e192b24SSimon Glass (ulong)map_to_sysmem(buff + buff_ptr), used); 732e192b24SSimon Glass 742e192b24SSimon Glass setenv_hex("profbase", map_to_sysmem(buff)); 752e192b24SSimon Glass setenv_hex("profsize", buff_size); 762e192b24SSimon Glass setenv_hex("profoffset", buff_ptr + used); 772e192b24SSimon Glass 782e192b24SSimon Glass return 0; 792e192b24SSimon Glass } 802e192b24SSimon Glass 812e192b24SSimon Glass int do_trace(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 822e192b24SSimon Glass { 832e192b24SSimon Glass const char *cmd = argc < 2 ? NULL : argv[1]; 842e192b24SSimon Glass 852e192b24SSimon Glass if (!cmd) 862e192b24SSimon Glass return cmd_usage(cmdtp); 872e192b24SSimon Glass switch (*cmd) { 882e192b24SSimon Glass case 'p': 892e192b24SSimon Glass trace_set_enabled(0); 902e192b24SSimon Glass break; 912e192b24SSimon Glass case 'c': 922e192b24SSimon Glass if (create_call_list(argc, argv)) 932e192b24SSimon Glass return cmd_usage(cmdtp); 942e192b24SSimon Glass break; 952e192b24SSimon Glass case 'r': 962e192b24SSimon Glass trace_set_enabled(1); 972e192b24SSimon Glass break; 982e192b24SSimon Glass case 'f': 992e192b24SSimon Glass if (create_func_list(argc, argv)) 1002e192b24SSimon Glass return cmd_usage(cmdtp); 1012e192b24SSimon Glass break; 1022e192b24SSimon Glass case 's': 1032e192b24SSimon Glass trace_print_stats(); 1042e192b24SSimon Glass break; 1052e192b24SSimon Glass default: 1062e192b24SSimon Glass return CMD_RET_USAGE; 1072e192b24SSimon Glass } 1082e192b24SSimon Glass 1092e192b24SSimon Glass return 0; 1102e192b24SSimon Glass } 1112e192b24SSimon Glass 1122e192b24SSimon Glass U_BOOT_CMD( 1132e192b24SSimon Glass trace, 4, 1, do_trace, 1142e192b24SSimon Glass "trace utility commands", 1152e192b24SSimon Glass "stats - display tracing statistics\n" 1162e192b24SSimon Glass "trace pause - pause tracing\n" 1172e192b24SSimon Glass "trace resume - resume tracing\n" 1182e192b24SSimon Glass "trace funclist [<addr> <size>] - dump function list into buffer\n" 1192e192b24SSimon Glass "trace calls [<addr> <size>] " 1202e192b24SSimon Glass "- dump function call trace into buffer" 1212e192b24SSimon Glass ); 122