1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Copyright (c) 2012 The Chromium OS Authors. 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+ 5*4882a593Smuzhiyun */ 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun #ifndef __TRACE_H 8*4882a593Smuzhiyun #define __TRACE_H 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun enum { 11*4882a593Smuzhiyun /* 12*4882a593Smuzhiyun * This affects the granularity of our trace. We can bin function 13*4882a593Smuzhiyun * entry points into groups on the basis that functions typically 14*4882a593Smuzhiyun * have a minimum size, so entry points can't appear any closer 15*4882a593Smuzhiyun * than this to each other. 16*4882a593Smuzhiyun * 17*4882a593Smuzhiyun * The value here assumes a minimum instruction size of 4 bytes, 18*4882a593Smuzhiyun * or that instructions are 2 bytes but there are at least 2 of 19*4882a593Smuzhiyun * them in every function. 20*4882a593Smuzhiyun * 21*4882a593Smuzhiyun * Increasing this value reduces the number of functions we can 22*4882a593Smuzhiyun * resolve, but reduces the size of the uintptr_t array used for 23*4882a593Smuzhiyun * our function list, which is the length of the code divided by 24*4882a593Smuzhiyun * this value. 25*4882a593Smuzhiyun */ 26*4882a593Smuzhiyun FUNC_SITE_SIZE = 4, /* distance between function sites */ 27*4882a593Smuzhiyun }; 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun enum trace_chunk_type { 30*4882a593Smuzhiyun TRACE_CHUNK_FUNCS, 31*4882a593Smuzhiyun TRACE_CHUNK_CALLS, 32*4882a593Smuzhiyun }; 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun /* A trace record for a function, as written to the profile output file */ 35*4882a593Smuzhiyun struct trace_output_func { 36*4882a593Smuzhiyun uint32_t offset; /* Function offset into code */ 37*4882a593Smuzhiyun uint32_t call_count; /* Number of times called */ 38*4882a593Smuzhiyun }; 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun /* A header at the start of the trace output buffer */ 41*4882a593Smuzhiyun struct trace_output_hdr { 42*4882a593Smuzhiyun enum trace_chunk_type type; /* Record type */ 43*4882a593Smuzhiyun uint32_t rec_count; /* Number of records */ 44*4882a593Smuzhiyun }; 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun /* Print statistics about traced function calls */ 47*4882a593Smuzhiyun void trace_print_stats(void); 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun /** 50*4882a593Smuzhiyun * Dump a list of functions and call counts into a buffer 51*4882a593Smuzhiyun * 52*4882a593Smuzhiyun * Each record in the buffer is a struct trace_func_stats. The 'needed' 53*4882a593Smuzhiyun * parameter returns the number of bytes needed to complete the operation, 54*4882a593Smuzhiyun * which may be more than buff_size if your buffer is too small. 55*4882a593Smuzhiyun * 56*4882a593Smuzhiyun * @param buff Buffer in which to place data, or NULL to count size 57*4882a593Smuzhiyun * @param buff_size Size of buffer 58*4882a593Smuzhiyun * @param needed Returns number of bytes used / needed 59*4882a593Smuzhiyun * @return 0 if ok, -1 on error (buffer exhausted) 60*4882a593Smuzhiyun */ 61*4882a593Smuzhiyun int trace_list_functions(void *buff, int buff_size, unsigned *needed); 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun /* Flags for ftrace_record */ 64*4882a593Smuzhiyun enum ftrace_flags { 65*4882a593Smuzhiyun FUNCF_EXIT = 0UL << 30, 66*4882a593Smuzhiyun FUNCF_ENTRY = 1UL << 30, 67*4882a593Smuzhiyun FUNCF_TEXTBASE = 2UL << 30, 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun FUNCF_TIMESTAMP_MASK = 0x3fffffff, 70*4882a593Smuzhiyun }; 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun #define TRACE_CALL_TYPE(call) ((call)->flags & 0xc0000000UL) 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun /* Information about a single function entry/exit */ 75*4882a593Smuzhiyun struct trace_call { 76*4882a593Smuzhiyun uint32_t func; /* Function offset */ 77*4882a593Smuzhiyun uint32_t caller; /* Caller function offset */ 78*4882a593Smuzhiyun uint32_t flags; /* Flags and timestamp */ 79*4882a593Smuzhiyun }; 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun int trace_list_calls(void *buff, int buff_size, unsigned int *needed); 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun /** 84*4882a593Smuzhiyun * Turn function tracing on and off 85*4882a593Smuzhiyun * 86*4882a593Smuzhiyun * Don't enable trace if it has not been initialised. 87*4882a593Smuzhiyun * 88*4882a593Smuzhiyun * @param enabled 1 to enable trace, 0 to disable 89*4882a593Smuzhiyun */ 90*4882a593Smuzhiyun void trace_set_enabled(int enabled); 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun int trace_early_init(void); 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun /** 95*4882a593Smuzhiyun * Init the trace system 96*4882a593Smuzhiyun * 97*4882a593Smuzhiyun * This should be called after relocation with a suitably large buffer 98*4882a593Smuzhiyun * (typically as large as the U-Boot text area) 99*4882a593Smuzhiyun * 100*4882a593Smuzhiyun * @param buff Pointer to trace buffer 101*4882a593Smuzhiyun * @param buff_size Size of trace buffer 102*4882a593Smuzhiyun */ 103*4882a593Smuzhiyun int trace_init(void *buff, size_t buff_size); 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun #endif 106