tracesrv/tracecore/btrace_handler/src/TraceCorePrintfTraceHandler.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 <e32def.h>
       
    18 #include <e32btrace.h>
       
    19 
       
    20 #include "TraceCore.h"
       
    21 #include "TraceCorePrintfTraceHandler.h"
       
    22 #include "TraceCoreDebug.h"
       
    23 #include "TraceCoreConstants.h"
       
    24 #include "TraceCoreActivation.h"
       
    25 
       
    26 #include "OstTraceDefinitions.h"
       
    27 #ifdef OST_TRACE_COMPILER_IN_USE
       
    28 #include "TraceCorePrintfTraceHandlerTraces.h"
       
    29 #endif
       
    30 #include "TraceCoreTComArgMacro.h"
       
    31 
       
    32 
       
    33 #ifdef __SMP__
       
    34 #include <nkernsmp/nkern.h>
       
    35 static TInt gIrqState = 0;
       
    36 TSpinLock gSpinLock(TSpinLock::TSpinLock::EOrderBTrace);
       
    37 #define __LOCK() gIrqState=__SPIN_LOCK_IRQSAVE( gSpinLock );
       
    38 #define __UNLOCK() __SPIN_UNLOCK_IRQRESTORE(gSpinLock, gIrqState);
       
    39 #else 
       
    40 #define __LOCK()
       
    41 #define __UNLOCK()
       
    42 #endif
       
    43 
       
    44 // Constants
       
    45 #define GRP_SHIFT 16
       
    46 
       
    47 #ifdef ADD_OST_HEADER_TO_PRINTF
       
    48 const TUint KDWordShift = 32;
       
    49 const TUint KDWordMask = 0xFFFFFFFF;
       
    50 const TUint KNanoSeconds = 1000000000;
       
    51 
       
    52 /**
       
    53  * Musti timestamp mask. First 4 bits are reserved for flags
       
    54  */
       
    55 const TUint KTimestampMask = 0x0FFFFFFF;
       
    56 
       
    57 /**
       
    58  * Musti timestamp flags for XTIv2
       
    59  */
       
    60 const TUint KTimestampFlags = 0xD0000000;
       
    61 
       
    62 const TUint KTimestampLenght(8);
       
    63 #endif
       
    64 
       
    65 /**
       
    66  * String that is send to indicate a trace has been dropped
       
    67  */
       
    68 _LIT8(KDroppedTrace,"* Dropped Trace");
       
    69 
       
    70 /**
       
    71  * Static instance is needed when calling traces from handler function
       
    72  */
       
    73 DTraceCorePrintfTraceHandler* DTraceCorePrintfTraceHandler::iInstance = NULL;
       
    74 
       
    75 /**
       
    76  * State of the Printf activations
       
    77  */
       
    78 TBool DTraceCorePrintfTraceHandler::iKernPrintfActive = ETrue;
       
    79 TBool DTraceCorePrintfTraceHandler::iRDebugPrintfActive = ETrue;
       
    80 TBool DTraceCorePrintfTraceHandler::iPlatSecPrintfActive = ETrue;
       
    81 
       
    82 /**
       
    83  * Constructor
       
    84  */
       
    85 DTraceCorePrintfTraceHandler::DTraceCorePrintfTraceHandler()
       
    86 : iPrintfHandler( NULL )
       
    87     {
       
    88     }
       
    89 
       
    90 
       
    91 /**
       
    92  * Destructor
       
    93  */
       
    94 DTraceCorePrintfTraceHandler::~DTraceCorePrintfTraceHandler()
       
    95     {
       
    96     DTraceCorePrintfTraceHandler::iInstance = NULL;
       
    97     }
       
    98 	
       
    99 
       
   100 /**
       
   101  * Initializes Printf handler
       
   102  */
       
   103 TInt DTraceCorePrintfTraceHandler::Init()
       
   104     {    
       
   105     TC_TRACE( ETraceLevelFlow, Kern::Printf( ">DTraceCorePrintfTraceHandler::Init()" ) );
       
   106     // Register to TraceCore
       
   107     TInt ret = Register();
       
   108     if ( ret == KErrNone )
       
   109         {
       
   110         DTraceCorePrintfTraceHandler::iInstance = this;      
       
   111         RegisterNotificationReceiver( KKernelHooksOSTComponentUID, BTrace::ERDebugPrintf );
       
   112     	RegisterNotificationReceiver( KKernelHooksOSTComponentUID, BTrace::EKernPrintf );
       
   113     	RegisterNotificationReceiver( KKernelHooksOSTComponentUID, BTrace::EPlatsecPrintf );
       
   114         }
       
   115     
       
   116     //activate printf group IDs by default
       
   117     DTraceCore* traceCore = DTraceCore::GetInstance();
       
   118     if (traceCore)
       
   119         {
       
   120         MTraceCoreActivation* activation = traceCore->GetActivation( KKernelHooksOSTComponentUID );
       
   121         if ( activation )
       
   122             {
       
   123              activation->ActivateTrace( KKernelHooksOSTComponentUID, BTrace::ERDebugPrintf );
       
   124              activation->ActivateTrace( KKernelHooksOSTComponentUID, BTrace::EKernPrintf  );
       
   125              activation->ActivateTrace( KKernelHooksOSTComponentUID, BTrace::EPlatsecPrintf  );
       
   126             }
       
   127         }
       
   128     
       
   129     TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCorePrintfTraceHandler::Init() - %d", ret ) );
       
   130     return ret;
       
   131     }
       
   132 
       
   133     
       
   134 /**
       
   135  * Prepares for writer change
       
   136  * 
       
   137  * @param aWriter Pointer to writer
       
   138  */       
       
   139 void DTraceCorePrintfTraceHandler::PrepareSetWriter( DTraceCoreWriter* aWriter )
       
   140     {
       
   141     OstTrace1( TRACE_FLOW, DTRACECOREPRINTFTRACEHANDLER_PREPARESETWRITER_ENTRY, "> DTraceCorePrintfTraceHandler::PrepareSetWriter 0x%x", ( TUint )( aWriter ) );
       
   142 
       
   143     TBool validMedia = aWriter != NULL;
       
   144     
       
   145     if ( validMedia )
       
   146         {
       
   147         DTraceCoreHandler::PrepareSetWriter( aWriter );
       
   148         // SetTraceHandler is not called if it has already been called before
       
   149         if ( iPrintfHandler == NULL )
       
   150             {
       
   151 #ifndef TRACECORE_HANDLE_PRINTF_EXCLUDED  // define TRACECORE_HANDLE_PRINTF_EXCLUDED when debugging using printfs
       
   152             iPrintfHandler = Kern::SetTraceHandler( DTraceCorePrintfTraceHandler::PrintfHandler );
       
   153 #endif
       
   154             OstTraceExt2( TRACE_NORMAL, DTRACECOREPRINTFTRACEHANDLER_SETWRITER_HANDLER_STARTED,"DTraceCorePrintfTraceHandler::PrepareSetWriter - Printf trace routing started. Addr:0x%x WriterType:%d",(TInt)aWriter, (TInt) aWriter->GetWriterType() );
       
   155             }
       
   156         }
       
   157     else
       
   158         {
       
   159         if ( aWriter == NULL )
       
   160             {
       
   161             OstTrace0( TRACE_NORMAL, DTRACECOREPRINTFTRACEHANDLER_PREPARESETWRITER_HANDLER_RESET,"DTraceCorePrintfTraceHandler::PrepareSetWriter - Printf trace routing stopped");
       
   162             DTraceCoreHandler::PrepareSetWriter( aWriter );
       
   163             
       
   164 #ifndef TRACECORE_HANDLE_PRINTF_EXCLUDED // define TRACECORE_HANDLE_PRINTF_EXCLUDED when debugging using printfs
       
   165             Kern::SetTraceHandler( iPrintfHandler );
       
   166 #endif
       
   167             iPrintfHandler = NULL;
       
   168             }
       
   169         else
       
   170             {
       
   171             OstTraceExt2( TRACE_NORMAL, DTRACECOREPRINTFTRACEHANDLER_PREPARESETWRITER_HANDLER_NOT_CHANGED,"DTraceCorePrintfTraceHandler::PrepareSetWriter - Printf trace routing was not changed Addr:0x%x WriterType:%d",(TUint)iWriter, (TInt) iWriter->GetWriterType() );
       
   172             }
       
   173         }
       
   174     }
       
   175 
       
   176 
       
   177 /*
       
   178 	Trace handler hook.
       
   179 	Should be able to run in any content (including ISR).
       
   180 	@param aText      Debug log. The content of the descriptor resides in kernel memory.
       
   181 	@param aTraceType Identifies the origin of the debug log.
       
   182 	@return Specifies whether the log is processed or not.
       
   183 		If ETrue,  the log is processed. Kernel will drop the log (it won't be passed to trace port - UART)
       
   184         If EFalse, the log is not processed. Kernel will pass the log to the trace port, as well.
       
   185 */
       
   186 TBool DTraceCorePrintfTraceHandler::PrintfHandler( const TDesC8& aText, TTraceSource aTraceSource )
       
   187     {
       
   188     __LOCK();
       
   189     
       
   190     // Print
       
   191     switch( aTraceSource )
       
   192         {
       
   193         case EKernelTrace:
       
   194             // Check if Kernel traces are on
       
   195             if ( DTraceCorePrintfTraceHandler::iKernPrintfActive )
       
   196                 {
       
   197                 HandleTrace( aText );
       
   198                 }
       
   199             break;  
       
   200         case EPlatSecTrace:
       
   201             // Check if PlatSec traces are on
       
   202             if ( DTraceCorePrintfTraceHandler::iPlatSecPrintfActive )
       
   203                 {
       
   204                 HandleTrace( aText );
       
   205                 }
       
   206             break;           
       
   207         case EUserTrace:
       
   208             // Check if User traces are on
       
   209             if ( DTraceCorePrintfTraceHandler::iRDebugPrintfActive )
       
   210                 {
       
   211                 HandleTrace( aText );
       
   212                 }
       
   213 
       
   214             break;
       
   215         default:
       
   216             break;            
       
   217         }
       
   218     
       
   219     __UNLOCK();
       
   220        
       
   221     return ETrue;
       
   222     }
       
   223 
       
   224 
       
   225 /**
       
   226 	Send the string to the active writer
       
   227  	@param aDes String to be printed out
       
   228  	
       
   229  	@note CR, LF and other special characters are not checked
       
   230  	@note, Tracing is not allowed from this method (esspecially on SMP system)
       
   231 */
       
   232 void DTraceCorePrintfTraceHandler::DebugPrint( const TDesC8& aDes )
       
   233     {
       
   234     // When a writer registers, Kern::SetTraceHandler is called to start printf routing
       
   235     // However, the iWriter member will be NULL for a brief period after Kern::SetTraceHandler
       
   236     //  -> Printf from an interrupt could crash this if NULL-check is not made
       
   237     if ( iWriter != NULL )
       
   238         {
       
   239         const TText8* pS = aDes.Ptr();
       
   240 #ifdef ADD_OST_HEADER_TO_PRINTF		
       
   241         TUint length = aDes.Length();
       
   242         const TText8* pE = pS + length;
       
   243 #else
       
   244         const TText8* pE = pS + aDes.Length();
       
   245 #endif
       
   246         const TUint32* chS_ptr = reinterpret_cast< const TUint32* >( pS );
       
   247         const TUint32* chE_ptr = reinterpret_cast< const TUint32* >( pE );
       
   248         
       
   249         if ( chS_ptr != chE_ptr )
       
   250             {
       
   251             // First send the printf start character
       
   252             TUint32 entryId = iWriter->WriteStart( EWriterEntryAscii );
       
   253             
       
   254 #ifdef ADD_OST_HEADER_TO_PRINTF    
       
   255             // DEBUG make sure we use this printfhandler:
       
   256             //iWriter->WriteData( entryId, (TUint8)0x39 );
       
   257             //  version(0x05);    // OST Base Protocol version "1.0" (v00-80-00_r1-04.pdf)
       
   258             //  entityId(0x01);   // Entity id TODO: check if this needs to change with CPU
       
   259             //  protocolId(0x02); // Ascii Trace Protocol (Not in MIPI specs 08 yet)
       
   260             
       
   261             iWriter->WriteData( entryId, ( TUint8 )0x05 ); // Version "0.5" because BTrace header included with protocol id 0x03
       
   262             iWriter->WriteData( entryId, ( TUint8 )0x01 ); // EntityId
       
   263             iWriter->WriteData( entryId, ( TUint8 )0x02 ); // Ascii trace ProtocolId (not specified in MIPI specs yet)
       
   264             
       
   265             length += KTimestampLenght;
       
   266             // Set length
       
   267             // If write size less than 256
       
   268             if(length < 256 )
       
   269             {
       
   270                 //  length(size);
       
   271                 iWriter->WriteData( entryId, ( TUint8 )length );
       
   272             
       
   273             }
       
   274             else
       
   275             {
       
   276                 //  extendedLengthBits0_7(0x00);
       
   277                 //  extendedLengthBits8_15(0x00);
       
   278                 //  extendedLengthBits16_23(0x00);
       
   279                 //  extendedLengthBits24_31(0x00);
       
   280                 iWriter->WriteData( entryId, ( TUint8 )0x00 ); // length field 0 if extended length in use
       
   281                 iWriter->WriteData( entryId, ( TUint32 )length ); // No swap, Length in protocol is little endian //SWAP_DATA( length ) );
       
   282             }
       
   283             
       
   284             // Write timestamp
       
   285         
       
   286             TUint64 timestamp = NKern::FastCounter();
       
   287             timestamp = (timestamp * KNanoSeconds ) / NKern::FastCounterFrequency();
       
   288             
       
   289             TUint32 timestampLSB = timestamp & KDWordMask;
       
   290             TUint32 timestampMSB = ( (timestamp >> KDWordShift ) & KTimestampMask ) | KTimestampFlags;
       
   291             
       
   292             iWriter->WriteData( entryId, SWAP_ID( timestampMSB ) );
       
   293         	iWriter->WriteData( entryId, SWAP_ID( timestampLSB ) );
       
   294             
       
   295             // DEBUG - END
       
   296 
       
   297 #endif
       
   298         	
       
   299             while ( chS_ptr + 1 <= chE_ptr )
       
   300                 {
       
   301                 // Print using 32bit write
       
   302                 TUint32 val = *( chS_ptr++ );
       
   303                 iWriter->WriteData( entryId, SWAP_DATA( val ) );
       
   304                 }    
       
   305             
       
   306             // Print the rest
       
   307             pS = ( TText8* )chS_ptr;
       
   308             if ( pS != pE )
       
   309                 {
       
   310                 while ( pS < pE )
       
   311                     {
       
   312                     iWriter->WriteData( entryId, *( pS++ ) );
       
   313                     }
       
   314                 }
       
   315             
       
   316             // End trace
       
   317             iWriter->WriteData( entryId, static_cast< TUint8 >( 0x00 ) );
       
   318             
       
   319             TWriteEndParams params(entryId, ETrue);
       
   320             iWriter->WriteEnd( params );
       
   321             }
       
   322         }
       
   323     }
       
   324 
       
   325 /**
       
   326  * Callback function for Trace Activation
       
   327  * 
       
   328  * @param aComponentId
       
   329  * @param aGroupId         
       
   330  */   
       
   331 void DTraceCorePrintfTraceHandler::TraceActivated( TUint32 TCOM_ARG(aComponentId), TUint16 aGroupId  )
       
   332     {
       
   333     OstTraceExt2( TRACE_FLOW, DTRACECOREPRINTFTRACEHANDLER_TRACEACTIVATED,"> DTraceCorePrintfTraceHandler::TraceActivated;aComponentId=0x%x;aGroupId=0x%x", (TUint) aComponentId, (TUint) aGroupId );
       
   334     
       
   335     switch( aGroupId )
       
   336     	{
       
   337     	case BTrace::EKernPrintf:
       
   338     		DTraceCorePrintfTraceHandler::iKernPrintfActive = ETrue;
       
   339     		break;
       
   340     	case BTrace::ERDebugPrintf:
       
   341     		DTraceCorePrintfTraceHandler::iRDebugPrintfActive = ETrue;
       
   342     		break;
       
   343     	case BTrace::EPlatsecPrintf:
       
   344     		DTraceCorePrintfTraceHandler::iPlatSecPrintfActive = ETrue;
       
   345     		break;
       
   346     	default:
       
   347     		break;	
       
   348     	}
       
   349     }
       
   350 		
       
   351 /**
       
   352  * Callback function for Trace Deactivation
       
   353  * 
       
   354  * @param aComponentId
       
   355  * @param aGroupId     
       
   356  */  
       
   357 void DTraceCorePrintfTraceHandler::TraceDeactivated( TUint32 TCOM_ARG(aComponentId), TUint16 aGroupId  )
       
   358     {
       
   359     OstTraceExt2( TRACE_FLOW, DTRACECOREPRINTFTRACEHANDLER_TRACEDEACTIVATED,"> DTraceCorePrintfTraceHandler::TraceDeactivated;aComponentId=0x%x;aGroupId=0x%x", (TUint) aComponentId, (TUint) aGroupId );
       
   360     
       
   361     switch( aGroupId )
       
   362     	{
       
   363     	case BTrace::EKernPrintf:
       
   364     		DTraceCorePrintfTraceHandler::iKernPrintfActive = EFalse;
       
   365     		break;
       
   366     	case BTrace::ERDebugPrintf:
       
   367     		DTraceCorePrintfTraceHandler::iRDebugPrintfActive = EFalse;
       
   368     		break;
       
   369     	case BTrace::EPlatsecPrintf:
       
   370     		DTraceCorePrintfTraceHandler::iPlatSecPrintfActive = EFalse;
       
   371     		break;
       
   372     	default:
       
   373     		break;	
       
   374     	}
       
   375     }
       
   376 
       
   377 /**
       
   378  * This method check if "dropped trace" notification must be sent and if so it
       
   379  * verify whether writer is able to send "dropped trace" and "new incomming trace".
       
   380  * If no the incomming trace is dropped and "dropped traces" flag is kept as set.
       
   381  *
       
   382  * @param aText Text-trace to send.
       
   383  */
       
   384 inline void DTraceCorePrintfTraceHandler::HandleTrace( const TDesC8& aText )
       
   385     {    
       
   386     if(!DTraceCorePrintfTraceHandler::iInstance || !DTraceCorePrintfTraceHandler::iInstance->iWriter)
       
   387         return; //no writer or no handler instance - don't even try to send data
       
   388     
       
   389     DTraceCore* tracecore = DTraceCore::GetInstance();
       
   390     DTraceCorePrintfTraceHandler* handler = DTraceCorePrintfTraceHandler::iInstance;
       
   391     DTraceCoreWriter* writer = handler->iWriter;
       
   392     
       
   393     if (tracecore->PreviousTraceDropped() )
       
   394         {
       
   395         if( writer->AbleToWrite(KDroppedTrace().Length()+aText.Length()))
       
   396             { 
       
   397             //send a "dropped trace" text trace and then the actual trace
       
   398             handler->DebugPrint(KDroppedTrace);
       
   399             handler->DebugPrint(aText);
       
   400             tracecore->SetPreviousTraceDropped(EFalse); //rested "dropped trace" flag
       
   401             }
       
   402 		else
       
   403 			{
       
   404 			//don't send anything to the buffer
       
   405 			}
       
   406         }
       
   407     else
       
   408         {
       
   409         // send the actual trace
       
   410         handler->DebugPrint(aText);    
       
   411         }
       
   412     }
       
   413 
       
   414 // End of File