tracesrv/tracecore/btrace_handler/src/TraceCoreWriter.cpp
changeset 56 aa2539c91954
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
       
     1 // Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Trace Core
       
    15 // 
       
    16 
       
    17 #include "TraceCoreWriter.h"
       
    18 #include "TraceCore.h"
       
    19 #include "TraceCoreDebug.h"
       
    20 
       
    21 #include "TraceCoreConstants.h"
       
    22 #include "OstTraceDefinitions.h"
       
    23 #ifdef OST_TRACE_COMPILER_IN_USE
       
    24 #include "TraceCoreWriterTraces.h"
       
    25 #endif
       
    26 
       
    27 #ifdef WRITE_OST_HEADER
       
    28 
       
    29 const TUint KDWordShift = 32;
       
    30 const TUint KDWordMask = 0xFFFFFFFF;
       
    31 const TUint KNanoSeconds = 1000000000;
       
    32 
       
    33 /**
       
    34  * Musti timestamp mask. First 4 bits are reserved for flags
       
    35  */
       
    36 const TUint KTimestampMask = 0x0FFFFFFF;
       
    37 
       
    38 /**
       
    39  * Musti timestamp flags for XTIv2
       
    40  */
       
    41 const TUint KTimestampFlags = 0xD0000000;
       
    42 
       
    43 const TUint KComponentIdLength(4);
       
    44 const TUint KGroupIdLength(4);
       
    45 const TUint KTimestampLenght(8);
       
    46 
       
    47 #endif // WRITE_OST_HEADER
       
    48 
       
    49 /**
       
    50  * Constructor
       
    51  */
       
    52 EXPORT_C DTraceCoreWriter::DTraceCoreWriter( TWriterType aWriterType )
       
    53 : iWriterType( aWriterType )
       
    54     {
       
    55     }
       
    56 
       
    57 
       
    58 /**
       
    59  * Destructor
       
    60  */
       
    61 EXPORT_C DTraceCoreWriter::~DTraceCoreWriter()
       
    62     {
       
    63     Unregister();
       
    64     }
       
    65 
       
    66 
       
    67 /**
       
    68  * Registers this writer to TraceCore
       
    69  */
       
    70 EXPORT_C TInt DTraceCoreWriter::Register()
       
    71     {
       
    72     TInt ret= KErrGeneral;  
       
    73     // Get TraceCore
       
    74     DTraceCore* traceCore = DTraceCore::GetInstance();
       
    75     if ( traceCore != NULL )
       
    76         {
       
    77         // Register this writer
       
    78         ret = traceCore->RegisterWriter( *this );
       
    79         }
       
    80     OstTrace1( TRACE_BORDER, DTRACECOREWRITER_REGISTER_EXIT, "< DTraceCoreWriter::Register %d", ret );
       
    81     return ret;
       
    82     }
       
    83 
       
    84 
       
    85 /**
       
    86  * Unregisters this writer from TraceCore
       
    87  */
       
    88 void DTraceCoreWriter::Unregister()
       
    89     {
       
    90     // Get TraceCore
       
    91     DTraceCore* traceCore = DTraceCore::GetInstance();
       
    92     if ( traceCore != NULL )
       
    93         {
       
    94         // Unregister this writer
       
    95         traceCore->UnregisterWriter( *this );
       
    96         }
       
    97     }
       
    98 
       
    99 
       
   100 /**
       
   101  * Gets the writer type
       
   102  */
       
   103 TWriterType DTraceCoreWriter::GetWriterType()
       
   104     {
       
   105     return iWriterType;
       
   106     }
       
   107     
       
   108     
       
   109 /**
       
   110  * Outputs a TraceCore frame. This calls WriteStart, writes the component and group ID's,
       
   111  * calls WriteBTraceFrame and calls WriteEnd.
       
   112  * 
       
   113  * Tracing is not allowed from this method.
       
   114  *
       
   115  * @param aComponentId the component ID
       
   116  * @param aTraceWord The trace word containing the group ID and the trace ID to write
       
   117  * @param aHeader BTrace header
       
   118  * @param aHeader2 Extra header data
       
   119  * @param aContext The thread context in which this function was called
       
   120  * @param a1 The first trace parameter
       
   121  * @param a2 The second trace parameter
       
   122  * @param a3 The third trace parameter
       
   123  * @param aExtra Extra trace data
       
   124  * @param aPc The program counter value
       
   125  * @param aRecordSize The record size
       
   126  */
       
   127 EXPORT_C void DTraceCoreWriter::WriteTraceCoreFrame( const TUint32 aComponentId, const TUint32 aTraceWord, 
       
   128         TUint32 aHeader, TUint32 aHeader2, const TUint32 aContext, const TUint32 a1, 
       
   129         const TUint32 a2, const TUint32 a3, const TUint32 aExtra, const TUint32 aPc, TUint32 aRecordSize )
       
   130     {    
       
   131     //TODO: tidy up code from #ifdef's
       
   132     
       
   133 #ifdef USE_OPTIMIZED_WRITE
       
   134 	if ( iWriterType == EWriterTypeXTI ) 
       
   135 #else
       
   136     if ( false )
       
   137 #endif
       
   138 		{
       
   139 		}
       
   140 	else
       
   141 		{
       
   142 	    TUint32 entryId = WriteStart( EWriterEntryTrace );
       
   143 
       
   144 #ifdef WRITE_OST_HEADER
       
   145 	if ( iWriterType == EWriterTypeXTI )
       
   146 	    {
       
   147         // Size is in the beginning of the 
       
   148         TUint32 size = aRecordSize + KTimestampLenght + KComponentIdLength + KGroupIdLength; //+(aHeader & 0xff)
       
   149     #ifdef AUTOGEN_ADD_BTRACE_TIMESTAMP
       
   150         size += KTimestampSize;
       
   151     #endif
       
   152     
       
   153         // Decrease component, group and trace ID (8 bytes) from the size as they are also included in the BTrace
       
   154         // variables and they won't be written in the BTrace packet anymore
       
   155         size -= ( KA1Size + KA2Size );
       
   156         
       
   157         //  version(0x05);    // OST Base Protocol version "1.0" (v00-80-00_r1-04.pdf)
       
   158         //  entityId(0x01);   // Entity id TODO: check if this needs to change with CPU
       
   159         //  protocolId(0x03); // Simple Application Trace Protocol (Not in MIPI specs 08 yet)
       
   160         
       
   161         WriteData( entryId, ( TUint8 )0x05 ); // Version "0.5" because BTrace header included with protocol id 0x03
       
   162         WriteData( entryId, ( TUint8 )0x01 ); // EntityId
       
   163         WriteData( entryId, ( TUint8 )0x03 ); // ProtocolId (not specified in MIPI specs yet)
       
   164         
       
   165         // Set length
       
   166         // If write size less than 256
       
   167         if(size < 256 )
       
   168             {
       
   169             //  length(size);
       
   170             WriteData( entryId, ( TUint8 )size );
       
   171             
       
   172             }
       
   173         else
       
   174             {
       
   175             //  extendedLengthBits0_7(0x00);
       
   176             //  extendedLengthBits8_15(0x00);
       
   177             //  extendedLengthBits16_23(0x00);
       
   178             //  extendedLengthBits24_31(0x00);
       
   179             WriteData( entryId, ( TUint8 )0x00 ); // length field 0 if extended length in use
       
   180             //WriteData( entryId, ( TUint32 )size );// No swap, Length in protocol is little endian //SWAP_DATA( size ) );
       
   181             // Swap needed after all to make little endian in XTI trace??
       
   182             WriteData( entryId, ( TUint32 )SWAP_DATA( size ) );
       
   183             }
       
   184             
       
   185         // Write timestamp
       
   186         TUint64 timestamp = NKern::FastCounter();
       
   187         timestamp = (timestamp * KNanoSeconds ) / NKern::FastCounterFrequency();
       
   188         
       
   189         TUint32 timestampLSB = timestamp & KDWordMask;
       
   190         TUint32 timestampMSB = ( (timestamp >> KDWordShift ) & KTimestampMask ) | KTimestampFlags;
       
   191         
       
   192         WriteData( entryId, SWAP_ID( timestampMSB ) );
       
   193         WriteData( entryId, SWAP_ID( timestampLSB ) );
       
   194 	    }
       
   195         
       
   196     // Write Component  and groupid (including traceid )
       
   197     WriteData( entryId, SWAP_ID( aComponentId ) );
       
   198     WriteData( entryId, SWAP_ID( aTraceWord ) );          
       
   199         
       
   200 #else // WRITE_OST_HEADER 
       
   201     WriteData( entryId, SWAP_ID( aComponentId ) );
       
   202     WriteData( entryId, SWAP_ID( aTraceWord ) );
       
   203 #endif
       
   204     WriteBTraceFrame( entryId, aHeader, aHeader2, aContext, a1, a2, a3, aExtra, aPc, aRecordSize );
       
   205     
       
   206     WriteEnd( entryId );
       
   207 		}
       
   208 		
       
   209     }
       
   210 
       
   211 
       
   212 /**
       
   213  * Outputs a BTrace frame into this writer.
       
   214  * Tracing is not allowed from this method.
       
   215  *
       
   216  * @param aEntryId the entry ID returned by WriteStart
       
   217  * @param aHeader BTrace header
       
   218  * @param aHeader2 Extra header data
       
   219  * @param aContext The thread context in which this function was called
       
   220  * @param a1 The first trace parameter
       
   221  * @param a2 The second trace parameter
       
   222  * @param a3 The third trace parameter
       
   223  * @param aExtra Extra trace data
       
   224  * @param aPc The program counter value
       
   225  * @param aRecordSize The record size
       
   226  */
       
   227 void DTraceCoreWriter::WriteBTraceFrame( const TUint32 aEntryId, TUint32 aHeader, TUint32 aHeader2, 
       
   228         const TUint32 aContext, const TUint32 a1, const TUint32 a2, const TUint32 a3, 
       
   229         const TUint32 aExtra, const TUint32 aPc, TUint32 aRecordSize )
       
   230     {
       
   231     // BTrace frame header. Don't read size from the header because Multipart trace can bigger than can fit to one byte.
       
   232     TUint32 size = aRecordSize;
       
   233     TUint8 flags = static_cast< TUint8 >( ( aHeader >> ( BTrace::EFlagsIndex * KByteSize ) ) & KByteMask );
       
   234     TUint8 category = static_cast< TUint8 >( ( aHeader >> ( BTrace::ECategoryIndex * KByteSize ) ) & KByteMask );
       
   235     TUint8 subcategory = static_cast< TUint8 >( ( aHeader >> ( BTrace::ESubCategoryIndex * KByteSize ) ) & KByteMask );
       
   236     
       
   237     #ifdef __SMP__
       
   238 	// Header 2 always present and contains CPU number
       
   239 	// If Header2 not originally there, add 4 to size
       
   240 	if (!( flags & BTrace::EHeader2Present))
       
   241 		{
       
   242         flags |= BTrace::EHeader2Present;
       
   243         aHeader2 = 0;
       
   244         size += KHeader2Size;
       
   245 	    }
       
   246 	aHeader2 = (aHeader2 &~ BTrace::ECpuIdMask) | (NKern::CurrentCpu()<<20); 
       
   247 	#endif
       
   248     
       
   249     // If timestamp is added to frame, the timestamp flag is also set to the header
       
   250     // and the header size is increased by the size of the timestamp
       
   251 #ifdef AUTOGEN_ADD_BTRACE_TIMESTAMP
       
   252 	if (!( flags & BTrace::ETimestampPresent))
       
   253 	    {
       
   254 	    size += KTimestampSize;
       
   255 	    flags |= BTrace::ETimestampPresent;
       
   256 	    }
       
   257 #endif
       
   258 
       
   259     // In case of autogen and OST categories, the BTrace frame size needs to be adjusted
       
   260     // depending on whether the group / trace ID info is replicated into the
       
   261     // frame or not.
       
   262     if ( category == KCategoryNokiaAutogen )
       
   263         {
       
   264         // Group and trace ID's are not written -> Skip a1
       
   265         size -= KA1Size;
       
   266         }
       
   267         
       
   268     // Same applies to OST categories
       
   269     else if (category >= KMaxKernelCategory    && // category <= KMaxCategory && // Not needed since category is a TUint8
       
   270        	     category != KCategoryNokiaBranchCoverage)
       
   271         {
       
   272         // Component, group and trace ID's from a1 and a2 are skipped
       
   273         size -= ( KA1Size + KA2Size );
       
   274         }
       
   275     else
       
   276         {
       
   277         // Other categories do not have component / group / trace ID's
       
   278         // -> No flagging is needed here
       
   279         }
       
   280 
       
   281     // Insert possibly changed values to BTrace header
       
   282     TUint8 sizeToHeader = size;
       
   283     if (size >= KByteMask )
       
   284         {
       
   285         sizeToHeader = KByteMask;
       
   286         }
       
   287     
       
   288     aHeader = ( sizeToHeader << ( BTrace::ESizeIndex * KByteSize ) )
       
   289             | ( flags << ( BTrace::EFlagsIndex * KByteSize ) )
       
   290             | ( category << ( BTrace::ECategoryIndex * KByteSize ) )
       
   291             | ( subcategory << ( BTrace::ESubCategoryIndex * KByteSize ) );
       
   292     
       
   293     // Writes the header
       
   294     WriteData( aEntryId, SWAP_DATA( aHeader ) );
       
   295     size -= KHeaderSize; // Subtract header size
       
   296     
       
   297     if ( flags & BTrace::EHeader2Present )
       
   298         {
       
   299         WriteData( aEntryId, SWAP_DATA( aHeader2 ) );
       
   300     	size -= KHeader2Size;
       
   301         }
       
   302 
       
   303 #ifdef AUTOGEN_ADD_BTRACE_TIMESTAMP
       
   304     // Timestamp is written after header2
       
   305     TUint32 timestamp = NKern::FastCounter();
       
   306     WriteData( aEntryId, SWAP_DATA( timestamp ) );
       
   307     size -= KTimestampSize;
       
   308 #endif
       
   309 
       
   310     if ( flags & BTrace::EContextIdPresent )
       
   311         {
       
   312         WriteData( aEntryId, SWAP_DATA( aContext ) );
       
   313         size -= KContextIdSize;
       
   314         }
       
   315     if ( flags & BTrace::EPcPresent )
       
   316         {
       
   317         WriteData( aEntryId, SWAP_DATA( aPc ) );
       
   318         size -= KPcSize;
       
   319         }
       
   320     if ( flags & BTrace::EExtraPresent )
       
   321         {
       
   322         WriteData( aEntryId, SWAP_DATA( aExtra ) );
       
   323         size -= KExtraSize;
       
   324         }
       
   325     // If A1 is present, it is written
       
   326     if ( size >= KA1Size )
       
   327         {
       
   328         if ( category == KCategoryNokiaAutogen )
       
   329             {
       
   330             // Don't write anything
       
   331             }
       
   332         else if (category >= KMaxKernelCategory    && // category <= KMaxCategory && // Not needed since category is a TUint8
       
   333            	     category != KCategoryNokiaBranchCoverage)
       
   334             {
       
   335             // Don't write anything
       
   336             }
       
   337         else
       
   338             {
       
   339             WriteData( aEntryId, SWAP_DATA( a1 ) );
       
   340             size -= KA1Size;
       
   341             }
       
   342     
       
   343         // If A2 is present, it is written
       
   344         if ( size >= KA2Size )
       
   345             {
       
   346             if (category >= KMaxKernelCategory    && // category <= KMaxCategory && // Not needed since category is a TUint8
       
   347                 category != KCategoryNokiaBranchCoverage)
       
   348                 {
       
   349                 // In OST, group / trace ID is in a2 -> Not written
       
   350                 }
       
   351             else
       
   352                 {
       
   353                 WriteData( aEntryId, SWAP_DATA( a2 ) );
       
   354                 size -= KA2Size;
       
   355                 }
       
   356             
       
   357             // If there is 4 bytes of data left, A3 is written as is
       
   358             // If more, the data is read from buffer pointed by A3
       
   359             if ( size <= KA3Size && size > 0 )
       
   360                 {
       
   361                 WriteData( aEntryId, SWAP_DATA( a3 ) );
       
   362                 }
       
   363             else if ( size > 0 )
       
   364                 {
       
   365                 WriteRemainingBytes( aEntryId, size, a3 );
       
   366                 }
       
   367             }
       
   368         }
       
   369     }
       
   370 
       
   371     
       
   372 /**
       
   373  * Writes the remaining bytes if data is not 32-bit aligned
       
   374  */
       
   375 void DTraceCoreWriter::WriteRemainingBytes( TUint32 aEntryId, TUint32 aSize, TUint32 a3 )
       
   376     {
       
   377     TUint8 extra = aSize % 4; // CodForChk_Dis_Magic
       
   378     TUint32* ptr = ( TUint32* )a3;
       
   379     TUint32* end = ( TUint32* )( ( ( TUint8* )a3 ) + ( aSize - extra ) );
       
   380     TUint32 val;
       
   381     while( ptr < end )
       
   382         {
       
   383         val = *ptr++;
       
   384         WriteData( aEntryId, SWAP_DATA( val ) );
       
   385         }
       
   386     // Write remaining bytes and aligns to 32-bit boundary
       
   387     if ( extra > 0 )
       
   388         {
       
   389         TUint8* ptr8 = ( TUint8* )ptr;
       
   390         TUint8* end8 = ptr8 + extra;
       
   391         TUint8* alignEnd = ( TUint8* )( end + 1 );
       
   392         while ( ptr8 < alignEnd )
       
   393             {
       
   394             if ( ptr8 < end8 )
       
   395                 {
       
   396                 WriteData( aEntryId, *ptr8++ );
       
   397                 }
       
   398             else
       
   399                 {
       
   400                 WriteData( aEntryId, ( TUint8 )0 );
       
   401                 ptr8++;
       
   402                 }
       
   403             }
       
   404         }
       
   405     }
       
   406 
       
   407    
       
   408 EXPORT_C void DTraceCoreWriter::WriteEnd( const TWriteEndParams& aWriteEndParams )
       
   409     {
       
   410     WriteEnd( aWriteEndParams.iEntryId );
       
   411     }
       
   412 
       
   413 
       
   414 /**
       
   415  * Signal to TraceCore if there has been a dropped trace
       
   416  * 
       
   417  * @param aDropped ETrue if the writer dropped the trace - otherwise EFalse
       
   418  * 
       
   419  */
       
   420 
       
   421 EXPORT_C void DTraceCoreWriter::TraceDropped(TBool aDropped)
       
   422     {
       
   423     DTraceCore* tracecore = DTraceCore::GetInstance();
       
   424     tracecore->SetPreviousTraceDropped(aDropped);
       
   425     }
       
   426 
       
   427 
       
   428 /**
       
   429   * Interrogates tracecore if the last trace was dropped
       
   430   * 
       
   431   * @return  returns ETrue if the trace was dropped otherwise EFalse
       
   432   * 
       
   433   */
       
   434 EXPORT_C TBool DTraceCoreWriter::WasLastTraceDropped() const 
       
   435     {
       
   436     TBool ret = EFalse;
       
   437     DTraceCore* tracecore = DTraceCore::GetInstance();
       
   438     ret = tracecore->PreviousTraceDropped();
       
   439     return ret;
       
   440     }
       
   441 
       
   442 
       
   443 
       
   444 EXPORT_C TBool DTraceCoreWriter::AbleToWrite(TUint /*aTraceSize*/)
       
   445     {
       
   446     return ETrue;
       
   447     }
       
   448    
       
   449 // End of File