diff -r a151135b0cf9 -r aa2539c91954 tracesrv/tracecore/btrace_handler/src/TraceCorePrintfTraceHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tracesrv/tracecore/btrace_handler/src/TraceCorePrintfTraceHandler.cpp Fri Oct 08 14:56:39 2010 +0300 @@ -0,0 +1,414 @@ +// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Trace Core +// + +#include +#include + +#include "TraceCore.h" +#include "TraceCorePrintfTraceHandler.h" +#include "TraceCoreDebug.h" +#include "TraceCoreConstants.h" +#include "TraceCoreActivation.h" + +#include "OstTraceDefinitions.h" +#ifdef OST_TRACE_COMPILER_IN_USE +#include "TraceCorePrintfTraceHandlerTraces.h" +#endif +#include "TraceCoreTComArgMacro.h" + + +#ifdef __SMP__ +#include +static TInt gIrqState = 0; +TSpinLock gSpinLock(TSpinLock::TSpinLock::EOrderBTrace); +#define __LOCK() gIrqState=__SPIN_LOCK_IRQSAVE( gSpinLock ); +#define __UNLOCK() __SPIN_UNLOCK_IRQRESTORE(gSpinLock, gIrqState); +#else +#define __LOCK() +#define __UNLOCK() +#endif + +// Constants +#define GRP_SHIFT 16 + +#ifdef ADD_OST_HEADER_TO_PRINTF +const TUint KDWordShift = 32; +const TUint KDWordMask = 0xFFFFFFFF; +const TUint KNanoSeconds = 1000000000; + +/** + * Musti timestamp mask. First 4 bits are reserved for flags + */ +const TUint KTimestampMask = 0x0FFFFFFF; + +/** + * Musti timestamp flags for XTIv2 + */ +const TUint KTimestampFlags = 0xD0000000; + +const TUint KTimestampLenght(8); +#endif + +/** + * String that is send to indicate a trace has been dropped + */ +_LIT8(KDroppedTrace,"* Dropped Trace"); + +/** + * Static instance is needed when calling traces from handler function + */ +DTraceCorePrintfTraceHandler* DTraceCorePrintfTraceHandler::iInstance = NULL; + +/** + * State of the Printf activations + */ +TBool DTraceCorePrintfTraceHandler::iKernPrintfActive = ETrue; +TBool DTraceCorePrintfTraceHandler::iRDebugPrintfActive = ETrue; +TBool DTraceCorePrintfTraceHandler::iPlatSecPrintfActive = ETrue; + +/** + * Constructor + */ +DTraceCorePrintfTraceHandler::DTraceCorePrintfTraceHandler() +: iPrintfHandler( NULL ) + { + } + + +/** + * Destructor + */ +DTraceCorePrintfTraceHandler::~DTraceCorePrintfTraceHandler() + { + DTraceCorePrintfTraceHandler::iInstance = NULL; + } + + +/** + * Initializes Printf handler + */ +TInt DTraceCorePrintfTraceHandler::Init() + { + TC_TRACE( ETraceLevelFlow, Kern::Printf( ">DTraceCorePrintfTraceHandler::Init()" ) ); + // Register to TraceCore + TInt ret = Register(); + if ( ret == KErrNone ) + { + DTraceCorePrintfTraceHandler::iInstance = this; + RegisterNotificationReceiver( KKernelHooksOSTComponentUID, BTrace::ERDebugPrintf ); + RegisterNotificationReceiver( KKernelHooksOSTComponentUID, BTrace::EKernPrintf ); + RegisterNotificationReceiver( KKernelHooksOSTComponentUID, BTrace::EPlatsecPrintf ); + } + + //activate printf group IDs by default + DTraceCore* traceCore = DTraceCore::GetInstance(); + if (traceCore) + { + MTraceCoreActivation* activation = traceCore->GetActivation( KKernelHooksOSTComponentUID ); + if ( activation ) + { + activation->ActivateTrace( KKernelHooksOSTComponentUID, BTrace::ERDebugPrintf ); + activation->ActivateTrace( KKernelHooksOSTComponentUID, BTrace::EKernPrintf ); + activation->ActivateTrace( KKernelHooksOSTComponentUID, BTrace::EPlatsecPrintf ); + } + } + + TC_TRACE( ETraceLevelFlow, Kern::Printf( " DTraceCorePrintfTraceHandler::PrepareSetWriter 0x%x", ( TUint )( aWriter ) ); + + TBool validMedia = aWriter != NULL; + + if ( validMedia ) + { + DTraceCoreHandler::PrepareSetWriter( aWriter ); + // SetTraceHandler is not called if it has already been called before + if ( iPrintfHandler == NULL ) + { +#ifndef TRACECORE_HANDLE_PRINTF_EXCLUDED // define TRACECORE_HANDLE_PRINTF_EXCLUDED when debugging using printfs + iPrintfHandler = Kern::SetTraceHandler( DTraceCorePrintfTraceHandler::PrintfHandler ); +#endif + OstTraceExt2( TRACE_NORMAL, DTRACECOREPRINTFTRACEHANDLER_SETWRITER_HANDLER_STARTED,"DTraceCorePrintfTraceHandler::PrepareSetWriter - Printf trace routing started. Addr:0x%x WriterType:%d",(TInt)aWriter, (TInt) aWriter->GetWriterType() ); + } + } + else + { + if ( aWriter == NULL ) + { + OstTrace0( TRACE_NORMAL, DTRACECOREPRINTFTRACEHANDLER_PREPARESETWRITER_HANDLER_RESET,"DTraceCorePrintfTraceHandler::PrepareSetWriter - Printf trace routing stopped"); + DTraceCoreHandler::PrepareSetWriter( aWriter ); + +#ifndef TRACECORE_HANDLE_PRINTF_EXCLUDED // define TRACECORE_HANDLE_PRINTF_EXCLUDED when debugging using printfs + Kern::SetTraceHandler( iPrintfHandler ); +#endif + iPrintfHandler = NULL; + } + else + { + 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() ); + } + } + } + + +/* + Trace handler hook. + Should be able to run in any content (including ISR). + @param aText Debug log. The content of the descriptor resides in kernel memory. + @param aTraceType Identifies the origin of the debug log. + @return Specifies whether the log is processed or not. + If ETrue, the log is processed. Kernel will drop the log (it won't be passed to trace port - UART) + If EFalse, the log is not processed. Kernel will pass the log to the trace port, as well. +*/ +TBool DTraceCorePrintfTraceHandler::PrintfHandler( const TDesC8& aText, TTraceSource aTraceSource ) + { + __LOCK(); + + // Print + switch( aTraceSource ) + { + case EKernelTrace: + // Check if Kernel traces are on + if ( DTraceCorePrintfTraceHandler::iKernPrintfActive ) + { + HandleTrace( aText ); + } + break; + case EPlatSecTrace: + // Check if PlatSec traces are on + if ( DTraceCorePrintfTraceHandler::iPlatSecPrintfActive ) + { + HandleTrace( aText ); + } + break; + case EUserTrace: + // Check if User traces are on + if ( DTraceCorePrintfTraceHandler::iRDebugPrintfActive ) + { + HandleTrace( aText ); + } + + break; + default: + break; + } + + __UNLOCK(); + + return ETrue; + } + + +/** + Send the string to the active writer + @param aDes String to be printed out + + @note CR, LF and other special characters are not checked + @note, Tracing is not allowed from this method (esspecially on SMP system) +*/ +void DTraceCorePrintfTraceHandler::DebugPrint( const TDesC8& aDes ) + { + // When a writer registers, Kern::SetTraceHandler is called to start printf routing + // However, the iWriter member will be NULL for a brief period after Kern::SetTraceHandler + // -> Printf from an interrupt could crash this if NULL-check is not made + if ( iWriter != NULL ) + { + const TText8* pS = aDes.Ptr(); +#ifdef ADD_OST_HEADER_TO_PRINTF + TUint length = aDes.Length(); + const TText8* pE = pS + length; +#else + const TText8* pE = pS + aDes.Length(); +#endif + const TUint32* chS_ptr = reinterpret_cast< const TUint32* >( pS ); + const TUint32* chE_ptr = reinterpret_cast< const TUint32* >( pE ); + + if ( chS_ptr != chE_ptr ) + { + // First send the printf start character + TUint32 entryId = iWriter->WriteStart( EWriterEntryAscii ); + +#ifdef ADD_OST_HEADER_TO_PRINTF + // DEBUG make sure we use this printfhandler: + //iWriter->WriteData( entryId, (TUint8)0x39 ); + // version(0x05); // OST Base Protocol version "1.0" (v00-80-00_r1-04.pdf) + // entityId(0x01); // Entity id TODO: check if this needs to change with CPU + // protocolId(0x02); // Ascii Trace Protocol (Not in MIPI specs 08 yet) + + iWriter->WriteData( entryId, ( TUint8 )0x05 ); // Version "0.5" because BTrace header included with protocol id 0x03 + iWriter->WriteData( entryId, ( TUint8 )0x01 ); // EntityId + iWriter->WriteData( entryId, ( TUint8 )0x02 ); // Ascii trace ProtocolId (not specified in MIPI specs yet) + + length += KTimestampLenght; + // Set length + // If write size less than 256 + if(length < 256 ) + { + // length(size); + iWriter->WriteData( entryId, ( TUint8 )length ); + + } + else + { + // extendedLengthBits0_7(0x00); + // extendedLengthBits8_15(0x00); + // extendedLengthBits16_23(0x00); + // extendedLengthBits24_31(0x00); + iWriter->WriteData( entryId, ( TUint8 )0x00 ); // length field 0 if extended length in use + iWriter->WriteData( entryId, ( TUint32 )length ); // No swap, Length in protocol is little endian //SWAP_DATA( length ) ); + } + + // Write timestamp + + TUint64 timestamp = NKern::FastCounter(); + timestamp = (timestamp * KNanoSeconds ) / NKern::FastCounterFrequency(); + + TUint32 timestampLSB = timestamp & KDWordMask; + TUint32 timestampMSB = ( (timestamp >> KDWordShift ) & KTimestampMask ) | KTimestampFlags; + + iWriter->WriteData( entryId, SWAP_ID( timestampMSB ) ); + iWriter->WriteData( entryId, SWAP_ID( timestampLSB ) ); + + // DEBUG - END + +#endif + + while ( chS_ptr + 1 <= chE_ptr ) + { + // Print using 32bit write + TUint32 val = *( chS_ptr++ ); + iWriter->WriteData( entryId, SWAP_DATA( val ) ); + } + + // Print the rest + pS = ( TText8* )chS_ptr; + if ( pS != pE ) + { + while ( pS < pE ) + { + iWriter->WriteData( entryId, *( pS++ ) ); + } + } + + // End trace + iWriter->WriteData( entryId, static_cast< TUint8 >( 0x00 ) ); + + TWriteEndParams params(entryId, ETrue); + iWriter->WriteEnd( params ); + } + } + } + +/** + * Callback function for Trace Activation + * + * @param aComponentId + * @param aGroupId + */ +void DTraceCorePrintfTraceHandler::TraceActivated( TUint32 TCOM_ARG(aComponentId), TUint16 aGroupId ) + { + OstTraceExt2( TRACE_FLOW, DTRACECOREPRINTFTRACEHANDLER_TRACEACTIVATED,"> DTraceCorePrintfTraceHandler::TraceActivated;aComponentId=0x%x;aGroupId=0x%x", (TUint) aComponentId, (TUint) aGroupId ); + + switch( aGroupId ) + { + case BTrace::EKernPrintf: + DTraceCorePrintfTraceHandler::iKernPrintfActive = ETrue; + break; + case BTrace::ERDebugPrintf: + DTraceCorePrintfTraceHandler::iRDebugPrintfActive = ETrue; + break; + case BTrace::EPlatsecPrintf: + DTraceCorePrintfTraceHandler::iPlatSecPrintfActive = ETrue; + break; + default: + break; + } + } + +/** + * Callback function for Trace Deactivation + * + * @param aComponentId + * @param aGroupId + */ +void DTraceCorePrintfTraceHandler::TraceDeactivated( TUint32 TCOM_ARG(aComponentId), TUint16 aGroupId ) + { + OstTraceExt2( TRACE_FLOW, DTRACECOREPRINTFTRACEHANDLER_TRACEDEACTIVATED,"> DTraceCorePrintfTraceHandler::TraceDeactivated;aComponentId=0x%x;aGroupId=0x%x", (TUint) aComponentId, (TUint) aGroupId ); + + switch( aGroupId ) + { + case BTrace::EKernPrintf: + DTraceCorePrintfTraceHandler::iKernPrintfActive = EFalse; + break; + case BTrace::ERDebugPrintf: + DTraceCorePrintfTraceHandler::iRDebugPrintfActive = EFalse; + break; + case BTrace::EPlatsecPrintf: + DTraceCorePrintfTraceHandler::iPlatSecPrintfActive = EFalse; + break; + default: + break; + } + } + +/** + * This method check if "dropped trace" notification must be sent and if so it + * verify whether writer is able to send "dropped trace" and "new incomming trace". + * If no the incomming trace is dropped and "dropped traces" flag is kept as set. + * + * @param aText Text-trace to send. + */ +inline void DTraceCorePrintfTraceHandler::HandleTrace( const TDesC8& aText ) + { + if(!DTraceCorePrintfTraceHandler::iInstance || !DTraceCorePrintfTraceHandler::iInstance->iWriter) + return; //no writer or no handler instance - don't even try to send data + + DTraceCore* tracecore = DTraceCore::GetInstance(); + DTraceCorePrintfTraceHandler* handler = DTraceCorePrintfTraceHandler::iInstance; + DTraceCoreWriter* writer = handler->iWriter; + + if (tracecore->PreviousTraceDropped() ) + { + if( writer->AbleToWrite(KDroppedTrace().Length()+aText.Length())) + { + //send a "dropped trace" text trace and then the actual trace + handler->DebugPrint(KDroppedTrace); + handler->DebugPrint(aText); + tracecore->SetPreviousTraceDropped(EFalse); //rested "dropped trace" flag + } + else + { + //don't send anything to the buffer + } + } + else + { + // send the actual trace + handler->DebugPrint(aText); + } + } + +// End of File