diff options
Diffstat (limited to 'drivers/staging/nmf-cm/cm/engine/trace/src')
-rw-r--r-- | drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 331 | ||||
-rw-r--r-- | drivers/staging/nmf-cm/cm/engine/trace/src/trace.c | 221 |
2 files changed, 552 insertions, 0 deletions
diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c new file mode 100644 index 00000000000..e59d9f8b1ba --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -0,0 +1,331 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include <cm/inc/cm_type.h> +#include <cm/engine/component/inc/introspection.h> +#include <cm/engine/component/inc/bind.h> +#include <cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h> +#include <cm/engine/trace/inc/trace.h> +#include <cm/engine/api/control/irq_engine.h> + +#include <cm/engine/utils/inc/convert.h> +#include <share/communication/inc/nmf_service.h> + +PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataHandle = cm_DM_Alloc(domainId, SDRAM_EXT16, + TRACE_BUFFER_SIZE * sizeof(struct t_nmf_trace) / 2, CM_MM_ALIGN_WORD, TRUE); + if (state->traceDataHandle == INVALID_MEMORY_HANDLE) + return CM_NO_MORE_MEMORY; + else + { + t_uint32 mmdspAddr; + int i; + + state->traceDataAddr = (struct t_nmf_trace*)cm_DSP_GetHostLogicalAddress(state->traceDataHandle); + cm_DSP_GetDspAddress(state->traceDataHandle, &mmdspAddr); + cm_writeAttribute(state->instance, "rtos/commonpart/traceDataAddr", mmdspAddr); + + eeState[coreId].readTracePointer = 0; + eeState[coreId].lastReadedTraceRevision = 0; + + for(i = 0; i < TRACE_BUFFER_SIZE; i++) + state->traceDataAddr[i].revision = 0; + + return CM_OK; + } +} + +PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataAddr = 0; + cm_DM_Free(state->traceDataHandle, TRUE); +} + +static t_uint32 swapHalfWord(t_uint32 word) +{ + return (word >> 16) | (word << 16); +} + +PUBLIC EXPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( + t_nmf_core_id coreId, + struct t_nmf_trace *trace) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + t_uint32 foundRevision; + t_cm_trace_type type; + + OSAL_LOCK_API(); + if (state->traceDataAddr == NULL) { + type = CM_MPC_TRACE_NONE; + goto out; + } + + foundRevision = swapHalfWord(state->traceDataAddr[state->readTracePointer].revision); + + if(foundRevision <= state->lastReadedTraceRevision) + { + // It's an old trace forgot it + type = CM_MPC_TRACE_NONE; + } + else + { + struct t_nmf_trace *traceRaw; + + if(foundRevision == state->lastReadedTraceRevision + 1) + { + type = CM_MPC_TRACE_READ; + } + else + { + type = CM_MPC_TRACE_READ_OVERRUN; + /* + * If we find that revision is bigger, thus we are in overrun, then we take the writePointer + 1 which + * correspond to the older one. + * => Here there is a window where the MMDSP could update writePointer just after + */ + state->readTracePointer = (cm_readAttributeNoError(state->instance, "rtos/commonpart/writePointer") + 1) % TRACE_BUFFER_SIZE; + } + + traceRaw = &state->traceDataAddr[state->readTracePointer]; + + trace->timeStamp = swapHalfWord(traceRaw->timeStamp); + trace->componentId = swapHalfWord(traceRaw->componentId); + trace->traceId = swapHalfWord(traceRaw->traceId); + trace->paramOpt = swapHalfWord(traceRaw->paramOpt); + trace->componentHandle = swapHalfWord(traceRaw->componentHandle); + trace->parentHandle = swapHalfWord(traceRaw->parentHandle); + + trace->params[0] = swapHalfWord(traceRaw->params[0]); + trace->params[1] = swapHalfWord(traceRaw->params[1]); + trace->params[2] = swapHalfWord(traceRaw->params[2]); + trace->params[3] = swapHalfWord(traceRaw->params[3]); + + state->readTracePointer = (state->readTracePointer + 1) % TRACE_BUFFER_SIZE; + state->lastReadedTraceRevision = swapHalfWord(traceRaw->revision); + trace->revision = state->lastReadedTraceRevision; + } + +out: + OSAL_UNLOCK_API(); + + return type; +} + + +/* + * Panic + */ +const struct { + char* name; + unsigned int info1:1; + unsigned int PC:1; + unsigned int SP:1; + unsigned int interface:1; +} reason_descrs[] = { + {"NONE_PANIC", 0, 0, 0, 0}, + {"INTERNAL_PANIC", 1, 0, 0, 0}, + {"MPC_NOT_RESPONDING_PANIC", 0, 0, 0, 0}, /* Should not be useful since in that case CM_getServiceDescription() not call */ + {"USER_STACK_OVERFLOW", 0, 1, 1, 0}, + {"SYSTEM_STACK_OVERFLOW", 0, 1, 1, 0}, + {"UNALIGNED_LONG_ACCESS", 0, 1, 0, 0}, + {"EVENT_FIFO_OVERFLOW", 0, 0, 0, 1}, + {"PARAM_FIFO_OVERFLOW", 0, 0, 0, 1}, + {"INTERFACE_NOT_BINDED", 0, 1, 0, 0}, + {"USER_PANIC", 1, 0, 0, 0} +}; + +static t_component_instance* getCorrespondingInstance( + t_panic_reason panicReason, + t_uint32 panicThis, + t_dup_char *itfName, + t_cm_instance_handle *instHandle) { + t_component_instance *instance; + t_uint32 k; + + for (k=0; k<ComponentTable.idxMax; k++) { + if ((instance = componentEntry(k)) == NULL) + continue; + if(panicReason == PARAM_FIFO_OVERFLOW || + panicReason == EVENT_FIFO_OVERFLOW) { + // Panic has been generated by binding component, search the client who has call it + // and return the client handle (not the BC one). + int i; + + if(instance->thisAddress == panicThis && panicThis == 0) { + *itfName = "Internal NMF service"; + *instHandle = ENTRY2HANDLE(instance, k); + return instance; + } + + for(i = 0; i < instance->Template->requireNumber; i++) { + int nb = instance->Template->requires[i].collectionSize, j; + for(j = 0; j < nb; j++) { + if(instance->interfaceReferences[i][j].instance != NULL && + instance->interfaceReferences[i][j].instance != (t_component_instance *)NMF_HOST_COMPONENT && + instance->interfaceReferences[i][j].instance != (t_component_instance *)NMF_VOID_COMPONENT && + instance->interfaceReferences[i][j].instance->thisAddress == panicThis) + { + *itfName = instance->Template->requires[i].name; + *instHandle = ENTRY2HANDLE(instance, k); + return instance; + } + } + } + } else { + // The component which has generated the panic is the good one. + + if(instance->thisAddress == panicThis) { + *itfName = "?"; + *instHandle = ENTRY2HANDLE(instance, k); + return instance; + } + } + } + + *itfName = "?"; + *instHandle = 0; + return 0; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ReadMPCString( + t_nmf_core_id coreId, + t_uint32 dspAddress, + char * buffer, + t_uint32 bufferSize) { + + while(--bufferSize > 0) + { + char ch = cm_DSP_ReadXRamWord(coreId, dspAddress++); + if(ch == 0) + break; + + *buffer++ = ch; + }; + + *buffer = 0; + + // Reset panicReason + cm_writeAttribute(cm_EEM_getExecutiveEngine(coreId)->instance, + "rtos/commonpart/serviceReason", MPC_SERVICE_NONE); + + return CM_OK; +} + +/****************/ +/* Generic part */ +/****************/ +PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( + t_nmf_core_id coreId, + t_cm_service_type *srcType, + t_cm_service_description *srcDescr) +{ + t_uint32 serviceReason; + t_component_instance *ee; + + // Acknowledge interrupt (do it before resetting panicReason) + cm_DSP_AcknowledgeDspIrq(coreId, DSP2ARM_IRQ_1); + + ee = cm_EEM_getExecutiveEngine(coreId)->instance; + + // Read panicReason + serviceReason = cm_readAttributeNoError(ee, "rtos/commonpart/serviceReason"); + if(serviceReason == MPC_SERVICE_PRINT) + { + *srcType = CM_MPC_SERVICE_PRINT; + + srcDescr->u.print.dspAddress = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo0"); + srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); + srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); + } + else if(serviceReason == MPC_SERVICE_TRACE) + { + *srcType = CM_MPC_SERVICE_TRACE; + } + else if(serviceReason != MPC_SERVICE_NONE) + { + t_uint32 panicThis; + t_dup_char itfName; + t_component_instance *instance; + + *srcType = CM_MPC_SERVICE_PANIC; + srcDescr->u.panic.panicReason = (t_panic_reason)serviceReason; + srcDescr->u.panic.panicSource = MPC_EE; + srcDescr->u.panic.info.mpc.coreid = coreId; + + // Read panicThis + panicThis = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo0"); + + instance = getCorrespondingInstance(srcDescr->u.panic.panicReason, panicThis, &itfName, &srcDescr->u.panic.info.mpc.faultingComponent); + + LOG_INTERNAL(0, "Error: Panic(%s, %s), This=%x", cm_getDspName(coreId), + reason_descrs[srcDescr->u.panic.panicReason].name, (void*)panicThis, 0, 0, 0); + + if(reason_descrs[srcDescr->u.panic.panicReason].interface != 0) + { + LOG_INTERNAL(0, ", interface=%s", itfName, 0, 0, 0, 0, 0); + } + + if(reason_descrs[srcDescr->u.panic.panicReason].info1 != 0) + { + // Info 1 + srcDescr->u.panic.info.mpc.panicInfo1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); + + LOG_INTERNAL(0, ", Info=%x", srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0, 0); + } + + if(reason_descrs[srcDescr->u.panic.panicReason].PC != 0) + { + t_uint32 DspAddress = 0xFFFFFFFF; + t_uint32 DspSize = 0x0; + + // PC need to be read in rtos/commonpart/serviceInfo1 + srcDescr->u.panic.info.mpc.panicInfo1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); + + if(instance != 0) + { + cm_DSP_GetDspAddress(instance->memories[instance->Template->codeMemory->id], &DspAddress); + cm_DSP_GetDspMemoryHandleSize(instance->memories[instance->Template->codeMemory->id], &DspSize); + } + + if(DspAddress <= srcDescr->u.panic.info.mpc.panicInfo1 && + srcDescr->u.panic.info.mpc.panicInfo1 < (DspAddress + DspSize)) + LOG_INTERNAL(0, ", PC:off=%x <abs=%x>", + srcDescr->u.panic.info.mpc.panicInfo1 - DspAddress, + srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0); + else + LOG_INTERNAL(0, ", PC:<abs=%x>", srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0, 0); + } + + if(reason_descrs[srcDescr->u.panic.panicReason].SP != 0) + { + srcDescr->u.panic.info.mpc.panicInfo2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); + + LOG_INTERNAL(0, ", SP=%x", srcDescr->u.panic.info.mpc.panicInfo2, 0, 0, 0, 0, 0); + } + + LOG_INTERNAL(0, "\n", 0, 0, 0, 0, 0, 0); + + if(instance != 0) + { + LOG_INTERNAL(0, "Error: Component=%s<%s>\n", + instance->pathname, instance->Template->name, 0, 0, 0, 0); + } + + // We don't set rtos/commonpart/serviceReason = MPC_SERVICE_NONE, since we don't want the + // MMDSP to continue execution, and we put in in Panic state + cm_DSP_SetStatePanic(coreId); + } + else + { + *srcType = CM_MPC_SERVICE_NONE; + } + + return CM_OK; +} diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c b/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c new file mode 100644 index 00000000000..e27d3284ed2 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c @@ -0,0 +1,221 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include "../inc/trace.h" +#include "../inc/xtitrace.h" +#include <inc/nmf-tracedescription.h> +#include <inc/nmf-limits.h> +#include <cm/engine/utils/inc/string.h> +#include <cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h> + +t_bool cm_trace_enabled = FALSE; + +/* + * STM message dump + */ +#define HEADER(t, s) ((t) | (s << 16)) + +static void writeN(struct t_nmfTraceChannelHeader* header) +{ + t_uint64* data = (t_uint64*)header; + t_uint64 *end = (t_uint64*)(((unsigned int)data) + header->traceSize - sizeof(t_uint64)); + + while(data < end) + { + OSAL_Write64(CM_CHANNEL, 0, *data++); + } + + OSAL_Write64(CM_CHANNEL, 1, *data); +} + +void cm_TRC_Dump(void) +{ + t_uint32 i; + + cm_TRC_traceReset(); + + for (i=0; i<ComponentTable.idxMax; i++) + { + if (componentEntry(i) != NULL) + cm_TRC_traceLoadMap(TRACE_COMPONENT_COMMAND_ADD, componentEntry(i)); + } +} + +void cm_TRC_traceReset(void) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceReset trace; + + trace.header.v = HEADER(TRACE_TYPE_RESET, sizeof(trace)); + + trace.minorVersion = TRACE_MINOR_VERSION; + trace.majorVersion = TRACE_MAJOR_VERSION; + + writeN((struct t_nmfTraceChannelHeader*)&trace); + } +} + +void cm_TRC_traceLoadMap( + t_nmfTraceComponentCommandDescription command, + const t_component_instance* component) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceComponent trace; + + /* + * Generate instantiate trace + */ + trace.header.v = HEADER(TRACE_TYPE_COMPONENT, sizeof(trace)); + + trace.command = (t_uint16)command; + trace.domainId = (t_uint16)component->Template->dspId + 1; + trace.componentContext = (t_uint32)component->thisAddress; + trace.componentUserContext = (t_uint32)component; + cm_StringCopy((char*)trace.componentLocalName, component->pathname, MAX_COMPONENT_NAME_LENGTH); + cm_StringCopy((char*)trace.componentTemplateName, component->Template->name, MAX_TEMPLATE_NAME_LENGTH); + + writeN((struct t_nmfTraceChannelHeader*)&trace); + + if(command == TRACE_COMPONENT_COMMAND_ADD) + { + struct t_nmfTraceMethod tracemethod; + int i, j, k; + + /* + * Generate method trace + */ + tracemethod.header.v = HEADER(TRACE_TYPE_METHOD, sizeof(tracemethod)); + + tracemethod.domainId = (t_uint16)component->Template->dspId + 1; + tracemethod.componentContext = (t_uint32)component->thisAddress; + + for(i = 0; i < component->Template->provideNumber; i++) + { + t_interface_provide* provide = &component->Template->provides[i]; + t_interface_provide_loaded* provideLoaded = &component->Template->providesLoaded[i]; + + for(j = 0; j < provide->collectionSize; j++) + { + for(k = 0; k < provide->interface->methodNumber; k++) + { + tracemethod.methodId = provideLoaded->indexesLoaded[j][k].methodAddresses; + + cm_StringCopy((char*)tracemethod.methodName, provide->interface->methodNames[k], MAX_INTERFACE_METHOD_NAME_LENGTH); + + writeN((struct t_nmfTraceChannelHeader*)&tracemethod); + } + } + } + } + } +} + +void cm_TRC_traceBinding( + t_nmfTraceBindCommandDescription command, + const t_component_instance* clientComponent, const t_component_instance* serverComponent, + const char *requiredItfName, const char *providedItfName) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceBind trace; + + trace.header.v = HEADER(TRACE_TYPE_BIND, sizeof(trace)); + + trace.command = (t_uint16)command; + + if(clientComponent == ARM_TRACE_COMPONENT) // ARM + { + trace.clientDomainId = 0x1; + trace.clientComponentContext = 0x0; + } + else + { + trace.clientDomainId = (t_uint16)clientComponent->Template->dspId + 1; + trace.clientComponentContext = (t_uint32)clientComponent->thisAddress; + } + if(requiredItfName != NULL) + cm_StringCopy((char*)trace.requiredItfName, requiredItfName, MAX_INTERFACE_NAME_LENGTH); + else + trace.requiredItfName[0] = 0; + + if(serverComponent == NULL) + { // Unbind or VOID + trace.serverDomainId = 0; + trace.serverComponentContext = 0x0; + } + else if(serverComponent == ARM_TRACE_COMPONENT) + { // ARM + trace.serverDomainId = 0x1; + trace.serverComponentContext = 0x0; + } + else + { + trace.serverDomainId = (t_uint16)serverComponent->Template->dspId + 1; + trace.serverComponentContext = (t_uint32)serverComponent->thisAddress; + } + if(providedItfName != NULL) + cm_StringCopy((char*)trace.providedItfName, providedItfName, MAX_INTERFACE_NAME_LENGTH); + else + trace.providedItfName[0] = 0; + + writeN((struct t_nmfTraceChannelHeader*)&trace); + } +} + +void cm_TRC_traceCommunication( + t_nmfTraceCommunicationCommandDescription command, + t_nmf_core_id coreId, + t_nmf_core_id remoteCoreId) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceCommunication trace; + + trace.header.v = HEADER(TRACE_TYPE_COMMUNICATION, sizeof(trace)); + + trace.command = (t_uint16)command; + trace.domainId = (t_uint16)coreId + 1; + trace.remoteDomainId = (t_uint16)remoteCoreId + 1; + + writeN((struct t_nmfTraceChannelHeader*)&trace); + } +} + +void cm_TRC_traceMemAlloc(t_nmfTraceAllocatorCommandDescription command, t_uint8 allocId, t_uint32 memorySize, const char *allocname) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceAllocator trace; + + trace.header.v = HEADER(TRACE_TYPE_ALLOCATOR, sizeof(trace)); + + trace.command = (t_uint16)command; + trace.allocId = (t_uint16)allocId; + trace.size = memorySize; + cm_StringCopy((char*)trace.name, allocname, sizeof(trace.name)); + + writeN((struct t_nmfTraceChannelHeader*)&trace); + } +} + +void cm_TRC_traceMem(t_nmfTraceAllocCommandDescription command, t_uint8 allocId, t_uint32 startAddress, t_uint32 memorySize) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceAlloc trace; + + trace.header.v = HEADER(TRACE_TYPE_ALLOC, sizeof(trace)); + + trace.command = (t_uint16)command; + trace.allocId = (t_uint16)allocId; + trace.offset = startAddress; + trace.size = memorySize; + + writeN((struct t_nmfTraceChannelHeader*)&trace); + } +} + |