diff options
Diffstat (limited to 'src/usr/trace/trace.C')
-rw-r--r-- | src/usr/trace/trace.C | 697 |
1 files changed, 664 insertions, 33 deletions
diff --git a/src/usr/trace/trace.C b/src/usr/trace/trace.C index 38d9c5957..33a3de888 100644 --- a/src/usr/trace/trace.C +++ b/src/usr/trace/trace.C @@ -1,54 +1,685 @@ -#include <trace_adal.h> -#include <util/singleton.H> +/* TODO + * - Add support in for debug traces + * - Time support + * - FORMAT_PRINTF support + * + * + */ + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include <trace/interface.H> #include <stdarg.h> #include <arch/ppc.H> +#include <kernel/console.H> +#include <limits.h> +#include <stdlib.h> +#include <sys/task.h> +#include <sys/mutex.h> + +#include "trace.H" + +/******************************************************************************/ +// Namespace +/******************************************************************************/ +namespace TRACE +{ + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ + +#define TRAC_TIME_REAL 0 // upper 32 = seconds, lower 32 = microseconds +#define TRAC_TIME_50MHZ 1 +#define TRAC_TIME_200MHZ 2 +#define TRAC_TIME_167MHZ 3 // 166666667Hz +#define COMP_NAME_SIZE 16 + +// Global value used as a "timer" to provide tracing point32_t of reference +uint32_t g_trac_time_high = 0; +uint32_t g_trac_time_low = 0; + +// Global Mutex +mutex_t g_trac_mutex; + +// Global buffer +trace_desc_t *g_trac_global = NULL; + -#include "tracebuffer.H" -int32_t trace_adal_init_buffer(trace_desc_t * td, const char* comp, - const size_t size ) +/******************************************************************************/ +// trace_adal_init_buffer +/******************************************************************************/ +void trace_adal_init_buffer(trace_desc_t **o_td, const char* i_comp, + const size_t i_size ) { - // For now, just store the component name. - *td = (trace_desc_t) comp; - return 0; + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + if(*o_td == NULL) + { + if(g_trac_global == NULL) + { + // TODO - How do I make this pre-emption/mutli-threading safe? + g_trac_mutex = mutex_create(); + + printk("Global trace buffer is NULL so create and init it!\n"); + + g_trac_global = (trace_desc_t *)(malloc(PAGE_SIZE)); + char l_g_comp[TRAC_COMP_SIZE] = "GLOBAL"; + trace_init_values_buffer(g_trac_global, + l_g_comp); + + } + + // Just assign it to the global buffer since we only have + // one buffer + *o_td = g_trac_global; + printk("Assigned input trace descriptor to global buffer\n"); + } + + printk("*td = %lu\n",(unsigned long int)*o_td); + + return; } -int32_t trace_adal_write_all(const trace_desc_t td, - const enum trace_hash_val hash, - const char * fmt, - const uint32_t line, - const int32_t type, ...) +/******************************************************************************/ +// trace_init_values_buffer +/******************************************************************************/ +void trace_init_values_buffer(trace_desc_t *o_buf,const char *i_comp) { + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + // Initialize it to all 0's + memset(o_buf,0,(size_t)PAGE_SIZE); + + (o_buf)->ver = TRACE_BUF_VERSION; + (o_buf)->hdr_len = sizeof(trace_buf_head_t); + (o_buf)->time_flg = TRAC_TIME_167MHZ; + (o_buf)->endian_flg = 'B'; // Big Endian + memcpy((o_buf)->comp,i_comp,(size_t)COMP_NAME_SIZE); + (o_buf)->size = PAGE_SIZE; + (o_buf)->times_wrap = 0; + (o_buf)->next_free = sizeof(trace_buf_head_t); + + return; +} + +/******************************************************************************/ +// trace_adal_write_all +/******************************************************************************/ +void trace_adal_write_all(trace_desc_t *io_td, + const trace_hash_val i_hash, + const char * i_fmt, + const uint32_t i_line, + const int32_t i_type, ...) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int64_t l_rc = 0; + uint32_t l_entry_size = 0; + trace_entire_entry_t l_entry; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + // This code is incorrect for determining formatting but will work for now. - size_t size = 0; - const char* _fmt = fmt; + uint32_t num_args = 0; + const char* _fmt = i_fmt; while ('\0' != *_fmt) { if ('%' == *_fmt) - size++; + num_args++; _fmt++; } - traceEntry* entry = - Singleton<TraceBuffer>::instance().claimEntry(sizeof(traceEntry) + - sizeof(uint64_t) * size); + if(num_args > TRAC_MAX_ARGS) + { + printk ("Too many arguments: %u",num_args); + } + else if(io_td != NULL) + { + + // Calculate total space needed + l_entry_size = sizeof(trace_entry_stamp_t); + l_entry_size += sizeof(trace_entry_head_t); + + // We always add the size of the entry at the end of the trace entry + // so the parsing tool can easily walk the trace buffer stack so we + // need to add that on to total size + l_entry_size += sizeof(uint32_t); + + // Now add on size for acutal number of arguments we're tracing + l_entry_size += (num_args * sizeof(uint64_t)); + + // Word align the entry + l_entry_size = (l_entry_size + 3) & ~3; + + // Fill in the entry structure + l_entry.stamp.tid = (uint32_t)task_gettid(); // What is response to this in AME code? + + // Length is equal to size of data + l_entry.head.length = (num_args * sizeof(uint64_t)); + l_entry.head.tag = TRACE_FIELDTRACE; + l_entry.head.hash = i_hash; + l_entry.head.line = i_line; - entry->component = (uint64_t) td; - entry->tid = task_gettid(); - entry->length = sizeof(uint64_t) * size; - entry->hash = hash; - entry->timestamp = getTB(); - entry->line = line; + // Time stamp + *(l_entry.stamp.tb) = getTB(); - uint64_t* data = &entry->values[0]; + uint64_t* data = &l_entry.args[0]; - va_list args; - va_start(args, type); - for (size_t i = 0; i < size; i++) + va_list args; + va_start(args, i_type); + for (size_t i = 0; i < num_args; i++) + { + *data = va_arg(args, uint64_t); + data++; + } + va_end(args); + + // Now put total size at end of buffer + // Note that fsp-trace assumes this to be a 32 bit long word + uint32_t *l_size = (uint32_t *)&(l_entry.args[num_args]); + *l_size = l_entry_size; + + printk("l_entry_size = %u ttid = %u\n",l_entry_size,l_entry.stamp.tid); + + // We now have total size and need to reserve a part of the trace + // buffer for this + + // CRITICAL REGION START + l_rc = mutex_lock(g_trac_mutex); + if(l_rc != 0) + { + printk("trace_adal_write_all: Failed to get mutex"); + } + else + { + // Update the entry count + io_td->te_count++; + + trace_write_data(io_td, + (void *)&l_entry, + l_entry_size); + + l_rc = mutex_unlock(g_trac_mutex); + if(l_rc != 0) + { + // Badness + printk("trace_adal_write_all: Failed to release mutex"); + } + } + // CRITICAL REGION END + } + else { - *data = va_arg(args, uint64_t); - data++; + printk("trace_adal_write_all: User passed invalid parameter"); } - va_end(args); - return 0; + + return; } + +/******************************************************************************/ +// trace_adal_write_bin +/******************************************************************************/ +void trace_adal_write_bin(trace_desc_t *io_td,const trace_hash_val i_hash, + const uint32_t i_line, + const void *i_ptr, + const uint32_t i_size, + const int32_t type) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int64_t l_rc = 0; + uint32_t l_entry_size = 0; + trace_bin_entry_t l_entry; + + /*---------------------------------------------------------------------- --*/ + /* Code */ + /*------------------------------------------------------------------------*/ + do + { + + if((io_td == NULL) || (i_ptr == NULL) || (i_size == 0)) + { + break; + } + + // Calculate total space needed + l_entry_size = sizeof(trace_entry_stamp_t); + l_entry_size += sizeof(trace_entry_head_t); + + // We always add the size of the entry at the end of the trace entry + // so the parsing tool can easily walk the trace buffer stack so we + // need to add that on to total size + l_entry_size += sizeof(uint32_t); + + // Now add on size for acutal size of the binary data + l_entry_size += i_size; + + // Word align the entry + l_entry_size = (l_entry_size + 3) & ~3; + + // Fill in the entry structure + l_entry.stamp.tid = (uint32_t)task_gettid(); // What is response to this in AME code? + + // Length is equal to size of data + l_entry.head.length = i_size; + l_entry.head.tag = TRACE_FIELDBIN; + l_entry.head.hash = i_hash; + l_entry.head.line = i_line; + + // We now have total size and need to reserve a part of the trace + // buffer for this + + // Time stamp + *(l_entry.stamp.tb) = getTB(); + + // CRITICAL REGION START + l_rc = mutex_lock(g_trac_mutex); + if(l_rc != 0) + { + printk("trace_adal_write_bin: Failed to get mutex"); + } + else + { + + // Increment trace counter + io_td->te_count++;; + + // First write the header + trace_write_data(io_td, + (void *)&l_entry, + sizeof(l_entry)); + + // Now write the actual binary data + trace_write_data(io_td, + i_ptr, + i_size); + + // Now write the size at the end + trace_write_data(io_td, + (void *)&l_entry_size, + sizeof(l_entry_size)); + + // CRITICAL REGION END + l_rc = mutex_unlock(g_trac_mutex); + if(l_rc != 0) + { + // Badness + printk("trace_adal_write_bin: Failed to release mutex"); + } + } + + }while(0); + + return; +} + +/******************************************************************************/ +// trace_write_data +/******************************************************************************/ +void trace_write_data(trace_desc_t *io_td, + const void *i_ptr, + const uint32_t i_size) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + uint32_t l_total_size = i_size; + void *l_buf_ptr = NULL; + uint32_t l_offset = 0; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + do + { + + if(i_size > PAGE_SIZE) + { + printk("trace_write_data: Input size to large!"); + break; + } + + if((io_td->next_free + l_total_size) > PAGE_SIZE) + { + // copy what we can to end + l_buf_ptr = (char *)io_td + io_td->next_free; + l_buf_ptr = (void *) ( ((uint64_t) l_buf_ptr + 3) & ~3); + l_offset = PAGE_SIZE-io_td->next_free; + memcpy(l_buf_ptr,i_ptr,(size_t)l_offset); + + l_total_size -= l_offset; + + // Now adjust the main header of buffer + io_td->times_wrap++; + io_td->next_free = io_td->hdr_len; + } + + l_buf_ptr = (char *)io_td + io_td->next_free; + + // Word align the write - total size includes this allignment + l_buf_ptr = (void *) ( ((uint64_t) l_buf_ptr + 3) & ~3); + + memcpy(l_buf_ptr,(char *)i_ptr + l_offset,l_total_size); + + // Make sure size is correct for word allignment + // Note that this works with binary trace because only the binary data + // has the potential to be un-word aligned. If two parts of the binary + // trace had this problem then this code would not work. + l_total_size = (l_total_size + 3) & ~3; + io_td->next_free += l_total_size; + + }while(0); + + return; + +} + +/******************************************************************************/ +// TRAC_get_td - TODO +/******************************************************************************/ +trace_desc_t * trace_get_td(const char *i_comp) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + //uint32_t l_num_des = 0; + //uint32_t i=0; + //trace_desc_t * l_td = NULL; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + +#if 0 + l_num_des = sizeof(g_des_array) / sizeof(trace_descriptor_array_t); + + for(i=0;i<l_num_des;i++) + { + if(memcmp(i_comp,(g_des_array[i].entry)->comp,(size_t)COMP_NAME_SIZE) == 0) + { + // Found the component + l_td = g_des_array[i].entry; + break; + } + } +#endif + // Only one trace buffer currently + return(g_trac_global); +} + +/******************************************************************************/ +// trace_get_buffer - TODO +/******************************************************************************/ +int32_t trace_get_buffer(const trace_desc_t *i_td_ptr, + void *o_data) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int64_t l_rc = 0; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + if((i_td_ptr) && (o_data != NULL)) + { + // Get the lock + // TODO Mutex +#if 0 + l_rc = UTIL_MUTEX_GET(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT); + if(l_rc != 0) + { + // Badness + printk("TRAC_get_buffer: Failed to get mutex"); + } + else + { + l_rc = SUCCESS; + } +#endif + // Copy it's buffer into temp one + memcpy(o_data,i_td_ptr,(size_t)PAGE_SIZE); + + // Always try to release even if error above + // TODO - mutex + //UTIL_MUTEX_PUT(&g_trac_mutex); + } + else + { + printk("TRAC_get_buffer: Invalid parameter passed by caller"); + } + + return(l_rc); +} + +#if 0 +/******************************************************************************/ +// trace_get_buffer_partial - TODO +/******************************************************************************/ +// TODO +int32_t trace_get_buffer_partial(const trace_desc_t *i_td_ptr, + void *o_data, + uint32_t *io_size) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int32_t l_rc = 0; + char *l_full_buf = NULL; + trace_desc_t *l_head = NULL; + uint32_t l_part_size = 0; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + do + { + + if((i_td_ptr == NULL) || (o_data == NULL) || (io_size == NULL)) + { + printk("trace_get_buffer_partial: Invalid parameter passed by caller"); + l_rc = TRAC_INVALID_PARM; + if(io_size != NULL) + { + *io_size = 0; + } + break; + } + + if(*io_size < sizeof(trace_buf_head_t)) + { + // Need to at least have enough space for the header + printk("trace_get_buffer_partial: *io_size to small"); + l_rc = TRAC_MEM_BUFF_TO_SMALL; + *io_size = 0; + break; + } + + // First get the full buffer + l_rc = tx_byte_allocate(&tpmd_trac_debug_byte_pool, + (void **)&l_full_buf, + TPMD_TRACE_BUFFER_SIZE, + TX_NO_WAIT); + if(l_rc != TX_SUCCESS) + { + printk("trace_get_buffer_partial: Failure allocating memory for temp buffer"); + *io_size = 0; + l_rc = TRAC_MEM_ALLOC_FAIL; + break; + } + + l_rc = trace_get_buffer(i_td_ptr, + l_full_buf); + if(l_rc != 0) + { + printk("trace_get_buffer_partial: Failure in call to TRAC_get_buffer()"); + *io_size = 0; + break; + } + + // Now that we have full buffer, adjust it to be requested size + memset(o_data,0,(size_t)*io_size); + + if(*io_size > TPMD_TRACE_BUFFER_SIZE) + { + // It fits + *io_size = TPMD_TRACE_BUFFER_SIZE; + memcpy(o_data,l_full_buf,(size_t)*io_size); + break; + } + + l_head = (trace_desc_t *)l_full_buf; + memcpy(o_data,l_full_buf,(size_t)(l_head->hdr_len)); + l_head = (trace_desc_t *)o_data; + l_head->size = *io_size; + + if((l_head->next_free == l_head->hdr_len) && (l_head->times_wrap == 0)) + { + // No data in buffer so just return what we have + break; + } + + if(l_head->next_free > *io_size) + { + // We can't even fit in first part of buffer + // Make sure data size is larger than header length + // Otherwise, we will be accessing beyond memory + if(*io_size < l_head->hdr_len) + { + l_rc = TRAC_DATA_SIZE_LESS_THAN_HEADER_SIZE; + break; + } + l_part_size = *io_size - l_head->hdr_len; + + memcpy((UCHAR *)o_data+l_head->hdr_len, + l_full_buf+l_head->next_free-l_part_size, + (size_t)l_part_size); + + // Set pointer at beginning because this will be a + // "just wrapped" buffer. + l_head->next_free = l_head->hdr_len; + + // Buffer is now wrapped because we copied max data into it. + if(!l_head->times_wrap) + { + l_head->times_wrap = 1; + } + } + else + { + // First part of buffer fits fine + memcpy((UCHAR *)o_data+l_head->hdr_len, + l_full_buf+l_head->hdr_len, + (size_t)(l_head->next_free - l_head->hdr_len)); + + + // If it's wrapped then pick up some more data + if(l_head->times_wrap) + { + // Figure out how much room we have left + l_part_size = *io_size - l_head->next_free; + + memcpy((UCHAR *)o_data+l_head->next_free, + l_full_buf+TPMD_TRACE_BUFFER_SIZE-l_part_size, + (size_t)l_part_size); + + } + else + { + // No more data to get, make buffer look as small + // as possible + // add '+4' to avoid the need to mark it as wrapped + // (if the last byte of the buffer is filled + // next_free has to pointer to the first byte) + + l_head->size = l_head->next_free + 4; + + } + + } + + *io_size = l_head->size; + + }while(0); + + if(l_full_buf != NULL) + { + tx_byte_release(l_full_buf); + } + + return(l_rc); +} +#endif + +/******************************************************************************/ +// trace_reset_buf - TODO +/******************************************************************************/ +int32_t trace_reset_buf() +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int64_t l_rc = 0; + //uint32_t l_num_des = 0; + //uint32_t i=0; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + // Get mutex so no one traces +#if 0 + // TODO + l_rc = UTIL_MUTEX_GET(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT); + if(l_rc != TX_SUCCESS) + { + printk("trace_reset_buf: Failure trying to get mutex"); + // Badness + } + else + { + l_num_des = sizeof(g_des_array) / sizeof(trace_descriptor_array_t); + + for(i=0;i<l_num_des;i++) + { + // Initialize the buffer + l_rc = trace_init_values_buffer(g_des_array[i].entry, + g_des_array[i].comp); + if(l_rc) + { + printk("trace_reset_buf: Failure in call to trace_init_values_buffer()"); + break; + } + } + } + +#endif + // Always try to release even if fail above + // TODO - mutex + //UTIL_MUTEX_PUT(&g_trac_mutex); + + return(l_rc); +} + +} // namespace |