summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/errl/errlentry.C78
-rw-r--r--src/usr/errl/test/errltest.H272
-rw-r--r--src/usr/trace/trace.C485
3 files changed, 537 insertions, 298 deletions
diff --git a/src/usr/errl/errlentry.C b/src/usr/errl/errlentry.C
index ee688dc86..553bdab8f 100644
--- a/src/usr/errl/errlentry.C
+++ b/src/usr/errl/errlentry.C
@@ -135,55 +135,75 @@ void ErrlEntry::appendToFFDC(ErrlUD * i_pErrlUD,
///////////////////////////////////////////////////////////////////////////////
// Return a Boolean indication of success.
-bool ErrlEntry::collectTrace(const char i_name[], const uint32_t i_max)
+bool ErrlEntry::collectTrace(const char i_name[], const uint64_t i_max)
{
- bool l_rc = false;
+ bool l_rc = false; // assume a problem.
+ char * l_pBuffer = NULL;
+ uint64_t l_cbOutput = 0;
+ uint64_t l_cbBuffer = 0;
do
{
- // By passing nil arguments, obtain the size of the buffer.
+ // By passing nil arguments 2 and 3, obtain the size of the buffer.
+ // Besides getting buffer size, it validates i_name.
uint64_t l_cbFull = TRACE::Trace::getTheInstance().getBuffer( i_name,
NULL,
0 );
if( 0 == l_cbFull )
{
+ // Problem, likely unknown trace buffer name.
TRACFCOMP( g_trac_errl,
- "ErrlEntry::collectTrace(): getBuffer(%s) rets zero.", i_name );
+ "ErrlEntry::collectTrace(): getBuffer(%s) rets zero.",i_name);
break;
}
- if( 0 == i_max )
+ if(( 0 == i_max ) || ( i_max >= l_cbFull ))
{
- // Full trace buffer desired. Allocate the buffer.
- char l_traceBuffer[ l_cbFull ];
-
- // Get the data into the buffer.
- TRACE::Trace::getTheInstance().getBuffer( i_name,
- l_traceBuffer,
- l_cbFull );
-
- // Save the trace buffer as a UD section on this.
- ErrlUD * l_udSection = new ErrlUD( l_traceBuffer,
- l_cbFull,
- ERRL_COMP_ID,
- ERRL_UDV_DEFAULT_VER_1,
- ERRL_UDT_TRACE );
-
- // Add the trace section to the vector of sections
- // for this error log.
- iv_SectionVector.push_back( l_udSection );
-
- l_rc = true;
+ // Full trace buffer desired
+ l_cbBuffer = l_cbFull;
+ }
+ else
+ {
+ // Partial buffer desired
+ l_cbBuffer = i_max;
+ }
+
+ // allocate the buffer
+ l_pBuffer = new char[ l_cbBuffer ];
+
+ // Get the data into the buffer.
+ l_cbOutput =
+ TRACE::Trace::getTheInstance().getBuffer( i_name,
+ l_pBuffer,
+ l_cbBuffer );
+
+ if( 0 == l_cbOutput )
+ {
+ // Problem.
+ TRACFCOMP( g_trac_errl,
+ "ErrlEntry::collectTrace(): getBuffer(%s,%ld) rets zero.",
+ i_name,
+ l_cbBuffer );
break;
}
- // else partial buffer desired... future sprint
- TRACFCOMP( g_trac_errl,
- "ErrlEntry::collectTrace(): partial buffer not impl'd" );
- break;
+ // Save the trace buffer as a UD section on this.
+ ErrlUD * l_udSection = new ErrlUD( l_pBuffer,
+ l_cbOutput,
+ ERRL_COMP_ID,
+ ERRL_UDV_DEFAULT_VER_1,
+ ERRL_UDT_TRACE );
+
+ // Add the trace section to the vector of sections
+ // for this error log.
+ iv_SectionVector.push_back( l_udSection );
+
+ l_rc = true;
}
while(0);
+ delete[] l_pBuffer;
+
return l_rc;
}
diff --git a/src/usr/errl/test/errltest.H b/src/usr/errl/test/errltest.H
index 94218aace..817bcee89 100644
--- a/src/usr/errl/test/errltest.H
+++ b/src/usr/errl/test/errltest.H
@@ -32,6 +32,7 @@
#include <cxxtest/TestSuite.H>
#include <errl/errlmanager.H>
#include <errl/errlentry.H>
+#include <trace/trace.H>
#include <hbotcompid.H>
#define TEST_REASON_CODE (ERRL_COMP_ID | 0x0F)
@@ -87,126 +88,203 @@ public:
uint64_t l_userData2 = TWO_UINT16_ONE_UINT32_TO_UINT64(l_16bit_1, l_16bit_2, l_32bit_2);
// yields 0x8000900390000003
- // Create an error log
- errlHndl_t l_err = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_INFORMATIONAL,
- TEST_MOD_ID,
- TEST_REASON_CODE,
- l_userData1,
- l_userData2);
- // Make sure log is created
- if (l_err == NULL)
+ do
{
- TS_FAIL("testErrl1: createErrlLog() outputs NULL pointer!");
- }
+ // Create an error log
+ errlHndl_t l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ TEST_MOD_ID,
+ TEST_REASON_CODE,
+ l_userData1,
+ l_userData2);
- // These addFFDC() calls return a pointer to class ERRORLOG::ErrlFFDC
- // but errlffdc.H is not publicly includable to give me the definition
- // for it. addFFDC() should return a Boolean indication of success.
- const char * pch = "martha washington";
- pffdc = l_err->addFFDC( ERRL_COMP_ID, pch, strlen( pch ), 1, 2 );
- if ( NULL == pffdc )
- {
- TS_FAIL("testErrl1: addFFDC() output NULL pointer");
- }
+ // Make sure log is created
+ if (l_err == NULL)
+ {
+ TS_FAIL("testErrl1: createErrlLog() outputs NULL pointer!");
+ break;
+ }
- // really short user data
- pch = "A";
- pffdc = l_err->addFFDC( DEVFW_COMP_ID, pch, strlen( pch ), 3, 4 );
- if ( NULL == pffdc )
- {
- TS_FAIL("testErrl1: addFFDC() output NULL pointer");
- }
- pch = "george washington";
- pffdc = l_err->addFFDC( DEVFW_COMP_ID, pch, strlen( pch ), 3, 4 );
- if ( NULL == pffdc )
- {
- TS_FAIL("testErrl1: addFFDC() output NULL pointer");
- }
+ // These addFFDC() calls return a pointer to class ERRORLOG::ErrlFFDC
+ // but errlffdc.H is not publicly includable to give me the definition
+ // for it. addFFDC() should return a Boolean indication of success.
- pch = "dwight eisenhour";
- pffdc = l_err->addFFDC( SCOM_COMP_ID, pch, strlen( pch ), 5, 6 );
- if ( NULL == pffdc )
- {
- TS_FAIL("testErrl1: addFFDC() output NULL pointer");
- }
+ const char * pch = "martha washington";
+ pffdc = l_err->addFFDC( ERRL_COMP_ID, pch, strlen( pch ), 1, 2 );
+ if ( NULL == pffdc )
+ {
+ TS_FAIL("testErrl1: addFFDC() output NULL pointer");
+ break;
+ }
- pch = "ronald ";
- pffdc = l_err->addFFDC( ERRL_COMP_ID, pch, strlen( pch ), 7, 8 );
- if ( NULL == pffdc )
- {
- TS_FAIL("testErrl1: addFFDC() output NULL pointer");
- }
+ // really short user data
+ pch = "A";
+ pffdc = l_err->addFFDC( DEVFW_COMP_ID, pch, strlen( pch ), 3, 4 );
+ if ( NULL == pffdc )
+ {
+ TS_FAIL("testErrl1: addFFDC() output NULL pointer");
+ break;
+ }
- // Append data to something already added.
- pch = "reagan";
- l_err->appendToFFDC( pffdc, pch, strlen(pch) );
+ pch = "george washington";
+ pffdc = l_err->addFFDC( DEVFW_COMP_ID, pch, strlen( pch ), 3, 4 );
+ if ( NULL == pffdc )
+ {
+ TS_FAIL("testErrl1: addFFDC() output NULL pointer");
+ break;
+ }
- // Collect trace
- fOK = l_err->collectTrace( "INITSVC" );
- if( !fOK )
- {
- TS_FAIL( "collectTrace(INITSVC) rets false." );
- }
+ pch = "dwight eisenhour";
+ pffdc = l_err->addFFDC( SCOM_COMP_ID, pch, strlen( pch ), 5, 6 );
+ if ( NULL == pffdc )
+ {
+ TS_FAIL("testErrl1: addFFDC() output NULL pointer");
+ break;
+ }
+
+ pch = "ronald ";
+ pffdc = l_err->addFFDC( ERRL_COMP_ID, pch, strlen( pch ), 7, 8 );
+ if ( NULL == pffdc )
+ {
+ TS_FAIL("testErrl1: addFFDC() output NULL pointer");
+ break;
+ }
+
+ // Append data to something already added.
+ pch = "reagan";
+ l_err->appendToFFDC( pffdc, pch, strlen(pch) );
+
+ // Collect trace
+ fOK = l_err->collectTrace( "INITSVC" );
+ if( !fOK )
+ {
+ TS_FAIL( "collectTrace(INITSVC) rets false." );
+ break;
+ }
+
+ // Assuming trace buffers are 0x800 in size, and you're going
+ // after a trace buffer that has wrapped, then a size almost as
+ // big as the buffer will exercise the wrapping code in
+ // trace::getBuffer()
+ fOK = l_err->collectTrace( "XSCOM" , 0x7D0 );
+ if( !fOK )
+ {
+ TS_FAIL( "collectTrace(XSCOM) rets false." );
+ break;
+ }
+
+ fOK = l_err->collectTrace( "UNKNOWN" );
+ if( fOK )
+ {
+ TS_FAIL( "collectTrace(UNKNOWN) rets true" );
+ break;
+ }
+
+ fOK = l_err->collectTrace( "TARG", sizeof(trace_buf_head_t)-2);
+ if( fOK )
+ {
+ // expect an error, buffer not big enough
+ TS_FAIL( "collectTrace(TARG,38) rets true" );
+ break;
+ }
+
+ fOK = l_err->collectTrace( "TARG", sizeof( trace_buf_head_t ));
+ if( !fOK )
+ {
+ // Buffer is big enough for the header only. It is
+ // supposed to work, although not terribly useful.
+ TS_FAIL( "collectTrace(TARG,40) rets false" );
+ break;
+ }
+
+ // sizeof( trace_buf_head_t ) + n bytes such that a single trace
+ // entry cannot fit into.
+ uint64_t l_cb = sizeof(trace_buf_head_t) + (sizeof(trace_bin_entry_t)/2);
+ fOK = l_err->collectTrace( "TARG", l_cb );
+ if( !fOK )
+ {
+ // cb is big enough for the header only, but no
+ // room for any entries.
+ TS_FAIL( "collectTrace(TARG,l_cb) rets false", l_cb );
+ break;
+ }
+
+ // Normal buffer sizes are 0x800 (2048), so passing
+ // something bigger is not expected to be an error.
+ // TODO: maybe after story "user selectable trace buffer sizes"
+ // TRAC_DEFAULT_BUFFER_SIZE (0x800) will be publicly available.
+ fOK = l_err->collectTrace( "TARG" , 4003 );
+ if( !fOK )
+ {
+ TS_FAIL( "collectTrace(TARG,4003) rets false" );
+ break;
+ }
+
+
+ // Add null data.
+ pffdc = l_err->addFFDC( ERRL_COMP_ID, NULL, 0, 9, 10 );
+ if ( NULL != pffdc )
+ {
+ TS_FAIL("testErrl1: addFFDC() returned non null");
+ break;
+ }
+
+ // Verify log data
+ if (l_err->sev() != ERRORLOG::ERRL_SEV_INFORMATIONAL)
+ {
+ TS_FAIL("testErrl1: createErrlLog() returns incorrect severity!");
+ break;
+ }
+
+ if (l_err->reasonCode() != TEST_REASON_CODE)
+ {
+ TS_FAIL("testErrl1: createErrlLog() returns incorrect reason code!");
+ break;
+ }
+
+ if (l_err->eventType() != ERRORLOG::ERRL_ETYPE_NOT_APPLICABLE)
+ {
+ TS_FAIL("testErrl1: createErrlLog() returns incorrect event type!");
+ break;
+ }
+
+ if (l_err->subSys() != ERRORLOG::EPUB_FIRMWARE_SUBSYS )
+ {
+ TS_FAIL("testErrl1: createErrlLog() returns incorrect sub system!");
+ break;
+ }
+
+ if (l_err->srcType() != ERRORLOG::SRC_ERR_INFO)
+ {
+ TS_FAIL("testErrl1: createErrlLog() returns incorrect SRC type!");
+ break;
+ }
+
+ if (l_err->termState() != ERRORLOG::TERM_STATE_UNKNOWN)
+ {
+ TS_FAIL("testErrl1: termState() returns incorrect term state!");
+ break;
+ }
- fOK = l_err->collectTrace( "XSCOM" );
- if( !fOK )
- {
- TS_FAIL( "collectTrace(XSCOM) rets false." );
- }
- fOK = l_err->collectTrace( "UNK" );
- if( fOK )
- {
- TS_FAIL( "collectTrace(UNK) rets true" );
- }
- // Add null data.
- pffdc = l_err->addFFDC( ERRL_COMP_ID, NULL, 0, 9, 10 );
- if ( NULL != pffdc )
- {
- TS_FAIL("testErrl1: addFFDC() returned non null");
- }
- // Verify log data
- else if (l_err->sev() != ERRORLOG::ERRL_SEV_INFORMATIONAL)
- {
- TS_FAIL("testErrl1: createErrlLog() returns incorrect severity!");
- }
- else if (l_err->reasonCode() != TEST_REASON_CODE)
- {
- TS_FAIL("testErrl1: createErrlLog() returns incorrect reason code!");
- }
- else if (l_err->eventType() != ERRORLOG::ERRL_ETYPE_NOT_APPLICABLE)
- {
- TS_FAIL("testErrl1: createErrlLog() returns incorrect event type!");
- }
- else if (l_err->subSys() != ERRORLOG::EPUB_FIRMWARE_SUBSYS )
- {
- TS_FAIL("testErrl1: createErrlLog() returns incorrect sub system!");
- }
- else if (l_err->srcType() != ERRORLOG::SRC_ERR_INFO)
- {
- TS_FAIL("testErrl1: createErrlLog() returns incorrect SRC type!");
- }
- else if (l_err->termState() != ERRORLOG::TERM_STATE_UNKNOWN)
- {
- TS_FAIL("testErrl1: termState() returns incorrect term state!");
- }
- else
- {
// Commit error log with different component ID.
errlCommit(l_err, FSI_COMP_ID);
+
// Make sure error log has been deleted by manager
if (l_err != NULL)
{
TS_FAIL("testErrl1: commitErrLog() did not delete error!");
+ break;
}
+
}
+ while(0);
}
/**
diff --git a/src/usr/trace/trace.C b/src/usr/trace/trace.C
index 447fad968..221270c48 100644
--- a/src/usr/trace/trace.C
+++ b/src/usr/trace/trace.C
@@ -20,13 +20,19 @@
// Origin: 30
//
// IBM_PROLOG_END
+
+/**
+ * @file trace.C
+ *
+ * @brief Implementation of class Trace
+ */
+
+
/* TODO
* - Add support in for debug trace enable/disable
* - FORMAT_PRINTF support
* - %s support
* - Multiple buffer support
- * - Prolog
- *
*
*/
@@ -43,11 +49,14 @@
#include <stdlib.h>
#include <sys/task.h>
#include <sys/sync.h>
-#include <string.h>
+#include <string_ext.h>
#include <util/align.H>
#include <trace/trace.H>
+
+
+
/******************************************************************************/
// Namespace
/******************************************************************************/
@@ -156,6 +165,9 @@ void Trace::initBuffer(trace_desc_t **o_td, const char* i_comp,
strcpy(l_comp, i_comp);
}
+ // make string upper case
+ strupr(l_comp);
+
// CRITICAL REGION START
mutex_lock(&iv_trac_mutex);
@@ -191,7 +203,7 @@ void Trace::initBuffer(trace_desc_t **o_td, const char* i_comp,
// TODO can't handle i_size yet - everything is coded
// around TRAC_DEFAULT_BUFFER_SIZE
l_td = static_cast<char *>(malloc(TRAC_DEFAULT_BUFFER_SIZE));
-
+
g_desc_array[i].td_entry =
reinterpret_cast<trace_desc_t *>(l_td);
@@ -331,10 +343,15 @@ void Trace::_trace_adal_write_all(trace_desc_t *io_td,
uint32_t num_4byte_args = 0; //fsp-trace counts 8-byte args as 2 4-byte args
const char* _fmt = i_fmt;
- // Save a copy
+ // Save a copy of input args because calling
+ // va_arg() on a va_list is a one-shot.
va_list l_args;
va_copy (l_args, i_args);
+
+ // Sum the sizes of the items in i_args in order to know how big to
+ // allocate the entry.
+
for (size_t i = 0; i <= strlen(_fmt); i++)
{
if ('%' == _fmt[i])
@@ -365,7 +382,8 @@ void Trace::_trace_adal_write_all(trace_desc_t *io_td,
//printk("Trace: STRING %s: strlen %d num_args %d l_data_size %d\n",
// l_str, static_cast<uint32_t>(l_strLen),
// num_args, l_data_size);
- //printk("Trace: l_str_map 0x%16llX\n", static_cast<long long>(l_str_map));
+ //printk("Trace: l_str_map 0x%16llX\n",
+ // static_cast<long long>(l_str_map));
}
else if ('c' == _fmt[i])
{
@@ -412,6 +430,9 @@ void Trace::_trace_adal_write_all(trace_desc_t *io_td,
}
}
+ va_end( i_args );
+
+
if((num_4byte_args <= TRAC_MAX_ARGS) && (io_td != NULL))
{
// Fill in the entry structure
@@ -427,7 +448,9 @@ void Trace::_trace_adal_write_all(trace_desc_t *io_td,
// Time stamp
convertTime(&l_entry.stamp);
- // Calculate total space needed
+ // Calculate total space needed for the entry, which is a
+ // combination of the data size from above, the entry
+ // headers, and an overall length field.
l_entry_size = l_data_size;
l_entry_size += sizeof(trace_entry_stamp_t);
l_entry_size += sizeof(trace_entry_head_t);
@@ -445,7 +468,9 @@ void Trace::_trace_adal_write_all(trace_desc_t *io_td,
memset(l_buffer, 0, l_data_size);
char * l_ptr = static_cast<char *> (l_buffer);
- // Now copy the arguments to the buffer
+ // Now copy the arguments to the buffer.
+
+
for (size_t i = 0; i < num_args; i++)
{
uint32_t l_strLen = 0;
@@ -654,12 +679,16 @@ void Trace::writeData(trace_desc_t *io_td,
if(i_size > (io_td->size-sizeof(trace_buf_head_t)))
{
+ // unreasonable size, caller is asking to write something
+ // that is very nearly the size of the entire buffer
break;
}
if((io_td->next_free + l_total_size) > io_td->size)
{
+ // Does not fit entirely, write what fits, and wrap the buffer.
+
// Get the pointer to current location in buffer
l_buf_ptr = reinterpret_cast<char *>(io_td) + io_td->next_free;
// Figure out the alignment
@@ -731,277 +760,389 @@ void Trace::convertTime(trace_entry_stamp_t *o_entry)
}
+
+
/******************************************************************************/
-// getTd
+// findTdByName
/******************************************************************************/
-trace_desc_t * Trace::getTd(const char *i_comp)
+trace_desc_t * Trace::findTdByName(const char *i_pName)
{
- /*------------------------------------------------------------------------*/
- /* Local Variables */
- /*------------------------------------------------------------------------*/
- uint32_t i=0;
trace_desc_t * l_td = NULL;
- char l_comp[COMP_NAME_SIZE] = {'\0'};
+ char l_comp[COMP_NAME_SIZE];
- /*------------------------------------------------------------------------*/
- /* Code */
- /*------------------------------------------------------------------------*/
- if (strlen(i_comp) != 0)
+ uint64_t i = strlen(i_pName);
+ if ( i )
{
- // Limit component name to 15 characters.
- if (strlen(i_comp) > (COMP_NAME_SIZE -1))
+ if ( i > (COMP_NAME_SIZE -1))
{
- memcpy(l_comp, i_comp, COMP_NAME_SIZE - 1);
+ // Limit component name.
+ memcpy(l_comp, i_pName, COMP_NAME_SIZE - 1);
+ l_comp[ COMP_NAME_SIZE - 1 ] = 0;
}
else
{
- strcpy(l_comp, i_comp);
+ strcpy( l_comp, i_pName );
}
- // Search all allocated component buffers
+ // Use upper case.
+ strupr( l_comp );
+
+ // Search the buffers array
for(i=0;
(i < (TRAC_MAX_NUM_BUFFERS - 1)) &&
(strlen(g_desc_array[i].comp) != 0);
i++)
{
- if(!strcmp(l_comp, g_desc_array[i].comp))
+ if(0 == strcmp(l_comp, g_desc_array[i].comp))
{
- // Found the component buffer
+ // Return this one.
l_td = g_desc_array[i].td_entry;
break;
}
}
- if (((TRAC_MAX_NUM_BUFFERS - 1) == i) &&
- (strlen(g_desc_array[i].comp) != 0))
-
- {
- // Must be the default buffer
- l_td = g_desc_array[i].td_entry;
- }
}
- return(l_td);
+ return l_td;
}
/*****************************************************************************/
-// getBuffer() called by ErrlEntry.CollectTrace()
-// Return how many bytes copied, or if given a null pointer or zero buffer
-// size, then return the size of the buffer.
+// getBuffer() called by ErrlEntry.collectTrace()
+// Return how many bytes copied to output buffer.
+// If given a null pointer or zero buffer then return the full size
+// of the buffer.
//
// Otherwise return zero on error; perhaps the component name/trace buffer
-// name is not found.
+// name is not found, or maybe the size of buffer given is too small to even
+// hold a trace buffer header.
uint64_t Trace::getBuffer( const char * i_pComp,
void * o_data,
- uint64_t i_bufferSize )
+ uint64_t i_size )
{
- int64_t l_rc = 0;
- trace_desc_t * l_pDescriptor = NULL;
+ const char * l_pchEntry = NULL; // use this to walk the entries
+ const char * l_pchEntryEOL = NULL; // end of list of entries
+ const char * l_pchTraceBuffer = NULL; // source buffer, including header
+ const char * l_pchTraceData = NULL; // source data, just past header
+ const char * l_pchTraceEOB = NULL; // end of source buffer
+ trace_buf_head_t * l_pCallerHeader = NULL; // output buffer, including header
+ trace_desc_t * l_pDescriptor = NULL;
+ uint64_t l_cbWrap = 0;
+ uint64_t l_rc = 0;
do
{
- l_pDescriptor = getTd( i_pComp );
+ l_pDescriptor = findTdByName( i_pComp );
if( NULL == l_pDescriptor )
{
+ // trace buffer name not found
break;
}
- if( ( NULL == o_data ) || ( 0 == i_bufferSize ))
+ if( (o_data == NULL) || (i_size == 0 ))
{
// return how big is the buffer.
- l_rc = TRAC_DEFAULT_BUFFER_SIZE;
+ l_rc = l_pDescriptor->size;
break;
}
- // Not to exceed buffer size.
- uint64_t l_copyCount = i_bufferSize;
- if( i_bufferSize > TRAC_DEFAULT_BUFFER_SIZE )
+ // Round size down to nearest 4-byte boundary.
+ i_size = ALIGN_DOWN_4(i_size);
+
+
+ if( i_size < sizeof(trace_buf_head_t))
{
- l_copyCount = TRAC_DEFAULT_BUFFER_SIZE;
+ // Need at least enough space for the header.
+ // printk("trace_get_buffer_partial: i_size too small");
+ break;
}
- // Get the lock
- mutex_lock(&iv_trac_mutex);
- // Copy buffer to caller's space
- memcpy( o_data, l_pDescriptor, (size_t)l_copyCount );
+ // Caller's destination buffer starts with a trace_buf_head_t.
+ l_pCallerHeader = static_cast<trace_buf_head_t*>(o_data);
- mutex_unlock(&iv_trac_mutex);
- l_rc = l_copyCount;
- }
- while( 0 );
- return l_rc;
-}
+ if( i_size >= l_pDescriptor->size )
+ {
+ // Caller's buffer is big enough to hold the whole buffer.
+ uint64_t l_copyCount = l_pDescriptor->size;
+ // Get the lock
+ mutex_lock(&iv_trac_mutex);
+ // If the buffer is not full, then the unused
+ // portion is just zeroes. Avoid copying the zeroes.
+ if( 0 == l_pDescriptor->times_wrap )
+ {
+ // Buffer has never wrapped, so copy the
+ // data up to the next-free offset.
+ l_copyCount = l_pDescriptor->next_free;
+ }
+ // Copy source buffer to caller's destination buffer
+ memcpy( o_data, l_pDescriptor, l_copyCount );
-#if 0
-/******************************************************************************/
-// getBufferPartial - TODO
-/******************************************************************************/
-// TODO
-int32_t Trace::getBufferPartial(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;
+ mutex_unlock(&iv_trac_mutex);
- /*------------------------------------------------------------------------*/
- /* Code */
- /*------------------------------------------------------------------------*/
+ // Update the header in the output buffer.
+ l_pCallerHeader->size = l_copyCount;
- 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;
- }
+ l_rc = l_copyCount;
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;
- }
+ // Input buffer size is smaller than source buffer size.
- // Now that we have full buffer, adjust it to be requested size
- memset(o_data,0,(size_t)*io_size);
+ mutex_lock(&iv_trac_mutex);
- if(*io_size > TPMD_TRACE_BUFFER_SIZE)
+ if((i_size >= l_pDescriptor->next_free) && (0 == l_pDescriptor->times_wrap))
{
- // It fits
- *io_size = TPMD_TRACE_BUFFER_SIZE;
- memcpy(o_data,l_full_buf,(size_t)*io_size);
- break;
- }
+ // The source buffer has not wrapped,
+ // and what is there fits into caller's buffer.
+ l_rc = l_pDescriptor->next_free;
+ memcpy( o_data, l_pDescriptor, l_rc );
- 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;
+ mutex_unlock(&iv_trac_mutex);
- if((l_head->next_free == l_head->hdr_len) && (l_head->times_wrap == 0))
- {
- // No data in buffer so just return what we have
+ // Update the header in the output buffer.
+ l_pCallerHeader->size = l_rc;
break;
}
- if(l_head->next_free > *io_size)
+
+ // Otherwise, walk the entries backwards because the word
+ // just prior to any entry is the length of the previous entry.
+ // Subtract this length from the current entry pointer to
+ // point to the previous entry. Wrap around as required.
+
+
+ // Trace descriptor points to base of source trace buffer.
+ l_pchTraceBuffer = reinterpret_cast<const char*>(l_pDescriptor);
+
+ // Source trace data resides just past the header.
+ l_pchTraceData = reinterpret_cast<const char *>(l_pDescriptor+1);
+
+ // EOB (end of buffer) of source trace buffer
+ l_pchTraceEOB = l_pchTraceBuffer + l_pDescriptor->size;
+
+ // useful when calculating locations of wrapped data
+ l_cbWrap = l_pDescriptor->size - sizeof(trace_buf_head_t);
+
+ // This is how much trace data caller's buffer can hold.
+ int l_cbToFill = i_size - sizeof(trace_buf_head_t);
+
+
+
+ // Start at next_free, which is not an actual entry.
+ // It is where the next entry write will go when it comes.
+ // It also marks the end of the list (EOL).
+ l_pchEntryEOL = l_pchTraceBuffer + l_pDescriptor->next_free;
+
+
+ // Walk backwards through the entries, looking for a point
+ // such that when walking the source entries from that
+ // point forward, those entries will fit into the
+ // destination buffer. Because of the cases handled above,
+ // this walking will not loop around back to where we started
+ // within the source buffer. Otherwise there would have to be
+ // tests made for wrapping and sensing when l_pchEntry passes
+ // l_pchEntryEOL. Note that trace entry structures and payload
+ // data may be wrapped anywhere on a 4-byte bound.
+
+
+ // Start here and work backwards.
+ l_pchEntry = l_pchEntryEOL;
+
+
+ do
{
- // 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)
+
+ if(( l_pchEntry == l_pchTraceData ) && (0 == l_pDescriptor->times_wrap))
{
- l_rc = TRAC_DATA_SIZE_LESS_THAN_HEADER_SIZE;
+ // Exit from this do loop with l_pchEntry the starting point.
+ // Probably not going to happen, because the non-wrap short
+ // buffer case was handled above.
+ // massert( 0 );
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;
+ // Determine the size of the entry prior to l_pchEntry. Normally,
+ // this length is found in the 4-byte word just before the start of any
+ // entry. However, trace code may wrap any given trace entry
+ // anywhere on a 4-byte word.
+
+ // massert( l_pchEntry >= l_pchTraceData );
+ // massert( l_pchEntry < l_pchTraceEOB );
+ // massert( 0 == (((uint64_t)(l_pchEntry)) & 3) );
+
+ // Length of previous entry is in prior 32-bit word.
+ const char * l_pchPreviousLength = l_pchEntry - sizeof(uint32_t);
+
+ if( l_pchPreviousLength < l_pchTraceData )
+ {
+ // I am at the start of the source data. Apply wrap byte count
+ // to find length up at the end of the buffer.
+ l_pchPreviousLength += l_cbWrap;
+
+ // Source buffer must have wrapped.
+ // massert( l_pDescriptor->times_wrap );
+ }
+
+ // Dereference and get the length of previous entry.
+ const uint32_t * l_p32;
+ l_p32 = reinterpret_cast<const uint32_t*>(l_pchPreviousLength);
+ int l_cbPrevious = *l_p32;
+
+
+
+ if(( l_cbToFill - l_cbPrevious ) < 0 )
+ {
+ // This one is too much. l_pchEntry is the starting point.
+ // This is the regular exit point from this loop.
+ break;
+ }
+
+
+ // Given the length of the previous one,
+ // assign a new value to l_pchEntry
+ l_pchEntry -= l_cbPrevious;
- // Buffer is now wrapped because we copied max data into it.
- if(!l_head->times_wrap)
+ if( l_pchEntry < l_pchTraceData )
{
- l_head->times_wrap = 1;
+ // Wrap.
+ l_pchEntry += l_cbWrap;
}
+
+ l_cbToFill -= l_cbPrevious;
+ // massert( l_cbToFill >= 0 );
}
- else
+ while( 1 );
+
+
+
+ // Having walked backwards, l_pchEntry is the starting point,
+ // All the entries forward of this point are supposed to fit
+ // into caller's data buffer.
+
+ // Count how many copied from source to destination buffer.
+ int l_entriesCopied = 0;
+ int l_bytesCopied = sizeof( trace_buf_head_t );
+
+ // Set up destination header.
+ memcpy( l_pCallerHeader, l_pDescriptor, sizeof(trace_buf_head_t));
+
+ // Caller's destination area for trace entry data, just past the
+ // buffer header.
+ char * l_pchDest = reinterpret_cast<char*>(l_pCallerHeader+1);
+
+
+ while( l_pchEntry != l_pchEntryEOL )
{
- // 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));
+ const trace_bin_entry_t * l_pEntry;
+ // Calculate how many bytes make up this entry. Value
+ // goes into l_cbEntry;
+ int l_cbEntry;
- // If it's wrapped then pick up some more data
- if(l_head->times_wrap)
+ if( (l_pchEntry + sizeof(trace_bin_entry_t)) > l_pchTraceEOB )
{
- // Figure out how much room we have left
- l_part_size = *io_size - l_head->next_free;
+ // This entry wraps. Copy this split-up
+ // trace_bin_entry_t to the callers destination buffer
+ // (save a malloc) then reference entry->head.length.
+
+ // Copy this much from the end of the source trace buffer.
+ int l_cb = l_pchTraceEOB - l_pchEntry;
+ memcpy( l_pchDest, l_pchEntry, l_cb );
- memcpy((UCHAR *)o_data+l_head->next_free,
- l_full_buf+TPMD_TRACE_BUFFER_SIZE-l_part_size,
- (size_t)l_part_size);
+ // Copy the rest from the start of data in the trace buffer.
+ int l_cbTheRest = sizeof( trace_bin_entry_t ) - l_cb;
+ memcpy( l_pchDest+l_cb, l_pchTraceData, l_cbTheRest );
+ // I just copied one of these into callers destination buffer.
+ l_pEntry = reinterpret_cast<trace_bin_entry_t*>(l_pchDest);
}
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)
+ // Otherwise, point the entry into the source buffer.
+ l_pEntry = reinterpret_cast<const trace_bin_entry_t*>(l_pchEntry);
+ }
- l_head->size = l_head->next_free + 4;
+ // Compute length of this entry. entry->head.length is the actual
+ // length of the trace data, and has to rounded up to next 4-byte
+ // boundary. The extra uint32 is where the size is stored.
+ l_cbEntry = ALIGN_4(l_pEntry->head.length) +
+ sizeof( trace_bin_entry_t ) +
+ sizeof( uint32_t );
+
+ if( (l_pchEntry + l_cbEntry) > l_pchTraceEOB )
+ {
+ // It wraps. Copy this split-up entry to the
+ // callers buffer.
+ int l_cb = l_pchTraceEOB - l_pchEntry;
+ memcpy( l_pchDest, l_pchEntry, l_cb );
+
+ // Copy the rest
+ int l_cbTheRest = l_cbEntry - l_cb;
+ memcpy( l_pchDest + l_cb, l_pchTraceData, l_cbTheRest );
+
+ // Assign l_pchEntry to next entry
+ l_pchEntry = l_pchTraceData + l_cbTheRest;
}
+ else
+ {
+ // Copy to destination buffer in one go.
+ memcpy( l_pchDest, l_pchEntry, l_cbEntry );
+
+ // Assign l_pchEntry to next entry
+ l_pchEntry += l_cbEntry;
+ }
+
+ l_bytesCopied += l_cbEntry;
+ // massert( 0 == ( l_bytesCopied & 3 ));
+
+ // massert( l_pchEntry >= l_pchTraceData );
+ // massert( l_pchEntry < l_pchTraceEOB );
+ // massert( 0 == (((uint64_t)(l_pchEntry)) & 3) );
+
+
+ // Increment new data destination pointer.
+ l_pchDest += l_cbEntry;
+ // massert( l_pchDest <= ((char*)l_pCallerHeader) + i_size );
+
+ // This will eventually go into destination header.
+ l_entriesCopied++;
}
- *io_size = l_head->size;
+ // Done looking at source buffer stuff.
+ mutex_unlock(&iv_trac_mutex);
- }while(0);
+ // Finish the caller's trace buffer header.
+ l_pCallerHeader->times_wrap = 0;
+ l_pCallerHeader->te_count = l_entriesCopied;
+ l_pCallerHeader->next_free = l_bytesCopied;
+ l_pCallerHeader->size = l_bytesCopied;
- if(l_full_buf != NULL)
- {
- tx_byte_release(l_full_buf);
+ // Return how many bytes written to output buffer.
+ l_rc = l_bytesCopied;
}
+ while(0);
- return(l_rc);
+ return l_rc;
}
-#endif
+
+
+
+
/******************************************************************************/
// resetBuf - TODO
OpenPOWER on IntegriCloud