diff options
Diffstat (limited to 'drivers/staging/nmf-cm/cm/engine/trace/src/panic.c')
-rw-r--r-- | drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 222 |
1 files changed, 222 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..9cb1a729a92 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -0,0 +1,222 @@ +/* + * 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> + + +/* + * 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_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; +} |