xref: /rk3399_rockchip-uboot/cmd/trace.c (revision 2e192b245ed36a63bab0ef576999a95e23f60ecd)
1*2e192b24SSimon Glass /*
2*2e192b24SSimon Glass  * Copyright (c) 2011 The Chromium OS Authors.
3*2e192b24SSimon Glass  *
4*2e192b24SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
5*2e192b24SSimon Glass  */
6*2e192b24SSimon Glass 
7*2e192b24SSimon Glass #include <common.h>
8*2e192b24SSimon Glass #include <command.h>
9*2e192b24SSimon Glass #include <mapmem.h>
10*2e192b24SSimon Glass #include <trace.h>
11*2e192b24SSimon Glass #include <asm/io.h>
12*2e192b24SSimon Glass 
13*2e192b24SSimon Glass static int get_args(int argc, char * const argv[], char **buff,
14*2e192b24SSimon Glass 		    size_t *buff_ptr, size_t *buff_size)
15*2e192b24SSimon Glass {
16*2e192b24SSimon Glass 	if (argc < 2)
17*2e192b24SSimon Glass 		return -1;
18*2e192b24SSimon Glass 	if (argc < 4) {
19*2e192b24SSimon Glass 		*buff_size = getenv_ulong("profsize", 16, 0);
20*2e192b24SSimon Glass 		*buff = map_sysmem(getenv_ulong("profbase", 16, 0),
21*2e192b24SSimon Glass 				   *buff_size);
22*2e192b24SSimon Glass 		*buff_ptr = getenv_ulong("profoffset", 16, 0);
23*2e192b24SSimon Glass 	} else {
24*2e192b24SSimon Glass 		*buff_size = simple_strtoul(argv[3], NULL, 16);
25*2e192b24SSimon Glass 		*buff = map_sysmem(simple_strtoul(argv[2], NULL, 16),
26*2e192b24SSimon Glass 				   *buff_size);
27*2e192b24SSimon Glass 		*buff_ptr = 0;
28*2e192b24SSimon Glass 	};
29*2e192b24SSimon Glass 	return 0;
30*2e192b24SSimon Glass }
31*2e192b24SSimon Glass 
32*2e192b24SSimon Glass static int create_func_list(int argc, char * const argv[])
33*2e192b24SSimon Glass {
34*2e192b24SSimon Glass 	size_t buff_size, avail, buff_ptr, used;
35*2e192b24SSimon Glass 	unsigned int needed;
36*2e192b24SSimon Glass 	char *buff;
37*2e192b24SSimon Glass 	int err;
38*2e192b24SSimon Glass 
39*2e192b24SSimon Glass 	if (get_args(argc, argv, &buff, &buff_ptr, &buff_size))
40*2e192b24SSimon Glass 		return -1;
41*2e192b24SSimon Glass 
42*2e192b24SSimon Glass 	avail = buff_size - buff_ptr;
43*2e192b24SSimon Glass 	err = trace_list_functions(buff + buff_ptr, avail, &needed);
44*2e192b24SSimon Glass 	if (err)
45*2e192b24SSimon Glass 		printf("Error: truncated (%#x bytes needed)\n", needed);
46*2e192b24SSimon Glass 	used = min(avail, needed);
47*2e192b24SSimon Glass 	printf("Function trace dumped to %08lx, size %#zx\n",
48*2e192b24SSimon Glass 	       (ulong)map_to_sysmem(buff + buff_ptr), used);
49*2e192b24SSimon Glass 	setenv_hex("profbase", map_to_sysmem(buff));
50*2e192b24SSimon Glass 	setenv_hex("profsize", buff_size);
51*2e192b24SSimon Glass 	setenv_hex("profoffset", buff_ptr + used);
52*2e192b24SSimon Glass 
53*2e192b24SSimon Glass 	return 0;
54*2e192b24SSimon Glass }
55*2e192b24SSimon Glass 
56*2e192b24SSimon Glass static int create_call_list(int argc, char * const argv[])
57*2e192b24SSimon Glass {
58*2e192b24SSimon Glass 	size_t buff_size, avail, buff_ptr, used;
59*2e192b24SSimon Glass 	unsigned int needed;
60*2e192b24SSimon Glass 	char *buff;
61*2e192b24SSimon Glass 	int err;
62*2e192b24SSimon Glass 
63*2e192b24SSimon Glass 	if (get_args(argc, argv, &buff, &buff_ptr, &buff_size))
64*2e192b24SSimon Glass 		return -1;
65*2e192b24SSimon Glass 
66*2e192b24SSimon Glass 	avail = buff_size - buff_ptr;
67*2e192b24SSimon Glass 	err = trace_list_calls(buff + buff_ptr, avail, &needed);
68*2e192b24SSimon Glass 	if (err)
69*2e192b24SSimon Glass 		printf("Error: truncated (%#x bytes needed)\n", needed);
70*2e192b24SSimon Glass 	used = min(avail, needed);
71*2e192b24SSimon Glass 	printf("Call list dumped to %08lx, size %#zx\n",
72*2e192b24SSimon Glass 	       (ulong)map_to_sysmem(buff + buff_ptr), used);
73*2e192b24SSimon Glass 
74*2e192b24SSimon Glass 	setenv_hex("profbase", map_to_sysmem(buff));
75*2e192b24SSimon Glass 	setenv_hex("profsize", buff_size);
76*2e192b24SSimon Glass 	setenv_hex("profoffset", buff_ptr + used);
77*2e192b24SSimon Glass 
78*2e192b24SSimon Glass 	return 0;
79*2e192b24SSimon Glass }
80*2e192b24SSimon Glass 
81*2e192b24SSimon Glass int do_trace(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
82*2e192b24SSimon Glass {
83*2e192b24SSimon Glass 	const char *cmd = argc < 2 ? NULL : argv[1];
84*2e192b24SSimon Glass 
85*2e192b24SSimon Glass 	if (!cmd)
86*2e192b24SSimon Glass 		return cmd_usage(cmdtp);
87*2e192b24SSimon Glass 	switch (*cmd) {
88*2e192b24SSimon Glass 	case 'p':
89*2e192b24SSimon Glass 		trace_set_enabled(0);
90*2e192b24SSimon Glass 		break;
91*2e192b24SSimon Glass 	case 'c':
92*2e192b24SSimon Glass 		if (create_call_list(argc, argv))
93*2e192b24SSimon Glass 			return cmd_usage(cmdtp);
94*2e192b24SSimon Glass 		break;
95*2e192b24SSimon Glass 	case 'r':
96*2e192b24SSimon Glass 		trace_set_enabled(1);
97*2e192b24SSimon Glass 		break;
98*2e192b24SSimon Glass 	case 'f':
99*2e192b24SSimon Glass 		if (create_func_list(argc, argv))
100*2e192b24SSimon Glass 			return cmd_usage(cmdtp);
101*2e192b24SSimon Glass 		break;
102*2e192b24SSimon Glass 	case 's':
103*2e192b24SSimon Glass 		trace_print_stats();
104*2e192b24SSimon Glass 		break;
105*2e192b24SSimon Glass 	default:
106*2e192b24SSimon Glass 		return CMD_RET_USAGE;
107*2e192b24SSimon Glass 	}
108*2e192b24SSimon Glass 
109*2e192b24SSimon Glass 	return 0;
110*2e192b24SSimon Glass }
111*2e192b24SSimon Glass 
112*2e192b24SSimon Glass U_BOOT_CMD(
113*2e192b24SSimon Glass 	trace,	4,	1,	do_trace,
114*2e192b24SSimon Glass 	"trace utility commands",
115*2e192b24SSimon Glass 	"stats                        - display tracing statistics\n"
116*2e192b24SSimon Glass 	"trace pause                        - pause tracing\n"
117*2e192b24SSimon Glass 	"trace resume                       - resume tracing\n"
118*2e192b24SSimon Glass 	"trace funclist [<addr> <size>]     - dump function list into buffer\n"
119*2e192b24SSimon Glass 	"trace calls  [<addr> <size>]       "
120*2e192b24SSimon Glass 		"- dump function call trace into buffer"
121*2e192b24SSimon Glass );
122