1/* 2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this list of 9 * conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 * of conditions and the following disclaimer in the documentation and/or other materials 13 * provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used 16 * to endorse or promote products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include "los_trace_pri.h" 33#include "trace_pipeline.h" 34#include "los_memory.h" 35#include "securec.h" 36 37#if (LOSCFG_RECORDER_MODE_OFFLINE == 1) 38#define BITS_NUM_FOR_TASK_ID 16 39 40LITE_OS_SEC_BSS STATIC TraceOfflineHeaderInfo g_traceRecoder; 41LITE_OS_SEC_BSS STATIC UINT32 g_tidMask[LOSCFG_BASE_CORE_TSK_LIMIT] = {0}; 42 43UINT32 OsTraceGetMaskTid(UINT32 tid) 44{ 45 return tid | ((tid < LOSCFG_BASE_CORE_TSK_LIMIT) ? g_tidMask[tid] << BITS_NUM_FOR_TASK_ID : 0); /* tid < 65535 */ 46} 47 48UINT32 OsTraceBufInit(UINT32 size) 49{ 50 UINT32 headSize; 51 VOID *buf = NULL; 52 headSize = sizeof(OfflineHead) + sizeof(ObjData) * LOSCFG_TRACE_OBJ_MAX_NUM; 53 if (size <= headSize) { 54 TRACE_ERROR("trace buf size not enough than 0x%x\n", headSize); 55 return LOS_ERRNO_TRACE_BUF_TOO_SMALL; 56 } 57 58 buf = LOS_MemAlloc(m_aucSysMem0, size); 59 if (buf == NULL) { 60 return LOS_ERRNO_TRACE_NO_MEMORY; 61 } 62 63 (VOID)memset_s(buf, size, 0, size); 64 g_traceRecoder.head = (OfflineHead *)buf; 65 g_traceRecoder.head->baseInfo.bigLittleEndian = TRACE_BIGLITTLE_WORD; 66 g_traceRecoder.head->baseInfo.version = TRACE_VERSION(TRACE_MODE_OFFLINE); 67 g_traceRecoder.head->baseInfo.clockFreq = g_sysClock; 68 g_traceRecoder.head->objSize = sizeof(ObjData); 69 g_traceRecoder.head->frameSize = sizeof(TraceEventFrame); 70 g_traceRecoder.head->objOffset = sizeof(OfflineHead); 71 g_traceRecoder.head->frameOffset = headSize; 72 g_traceRecoder.head->totalLen = size; 73 74 g_traceRecoder.ctrl.curIndex = 0; 75 g_traceRecoder.ctrl.curObjIndex = 0; 76 g_traceRecoder.ctrl.maxObjCount = LOSCFG_TRACE_OBJ_MAX_NUM; 77 g_traceRecoder.ctrl.maxRecordCount = (size - headSize) / sizeof(TraceEventFrame); 78 g_traceRecoder.ctrl.objBuf = (ObjData *)((UINTPTR)buf + g_traceRecoder.head->objOffset); 79 g_traceRecoder.ctrl.frameBuf = (TraceEventFrame *)((UINTPTR)buf + g_traceRecoder.head->frameOffset); 80 81 return LOS_OK; 82} 83 84VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId) 85{ 86 UINT32 intSave; 87 UINT32 index; 88 ObjData *obj = NULL; 89 90 TRACE_LOCK(intSave); 91 /* add obj begin */ 92 index = g_traceRecoder.ctrl.curObjIndex; 93 if (index >= LOSCFG_TRACE_OBJ_MAX_NUM) { /* do nothing when config LOSCFG_TRACE_OBJ_MAX_NUM = 0 */ 94 TRACE_UNLOCK(intSave); 95 return; 96 } 97 obj = &g_traceRecoder.ctrl.objBuf[index]; 98 99 if (taskId < LOSCFG_BASE_CORE_TSK_LIMIT) { 100 g_tidMask[taskId]++; 101 } 102 103 OsTraceSetObj(obj, OS_TCB_FROM_TID(taskId)); 104 105 g_traceRecoder.ctrl.curObjIndex++; 106 if (g_traceRecoder.ctrl.curObjIndex >= g_traceRecoder.ctrl.maxObjCount) { 107 g_traceRecoder.ctrl.curObjIndex = 0; /* turn around */ 108 } 109 /* add obj end */ 110 TRACE_UNLOCK(intSave); 111} 112 113VOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame) 114{ 115 UINT16 index; 116 UINT32 intSave; 117 118 TRACE_LOCK(intSave); 119 index = g_traceRecoder.ctrl.curIndex; 120 (VOID)memcpy_s(&g_traceRecoder.ctrl.frameBuf[index], sizeof(TraceEventFrame), frame, sizeof(TraceEventFrame)); 121 122 g_traceRecoder.ctrl.curIndex++; 123 if (g_traceRecoder.ctrl.curIndex >= g_traceRecoder.ctrl.maxRecordCount) { 124 g_traceRecoder.ctrl.curIndex = 0; 125 } 126 TRACE_UNLOCK(intSave); 127} 128 129VOID OsTraceReset(VOID) 130{ 131 UINT32 intSave; 132 UINT32 bufLen; 133 134 TRACE_LOCK(intSave); 135 bufLen = sizeof(TraceEventFrame) * g_traceRecoder.ctrl.maxRecordCount; 136 (VOID)memset_s(g_traceRecoder.ctrl.frameBuf, bufLen, 0, bufLen); 137 g_traceRecoder.ctrl.curIndex = 0; 138 TRACE_UNLOCK(intSave); 139} 140 141STATIC VOID OsTraceInfoObj(VOID) 142{ 143 UINT32 i; 144 ObjData *obj = &g_traceRecoder.ctrl.objBuf[0]; 145 146 if (g_traceRecoder.ctrl.maxObjCount > 0) { 147 PRINTK("CurObjIndex = %u\n", g_traceRecoder.ctrl.curObjIndex); 148 PRINTK("Index TaskID TaskPrio TaskName \n"); 149 for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++, obj++) { 150 PRINTK("%-7u 0x%-6x %-10u %s\n", i, obj->id, obj->prio, obj->name); 151 } 152 PRINTK("\n"); 153 } 154} 155 156STATIC VOID OsTraceInfoEventTitle(VOID) 157{ 158 PRINTK("CurEvtIndex = %u\n", g_traceRecoder.ctrl.curIndex); 159 160 PRINTK("Index Time(cycles) EventType CurTask Identity "); 161#if (LOSCFG_TRACE_FRAME_CORE_MSG == 1) 162 PRINTK("cpuId hwiActive taskLockCnt "); 163#endif 164#if (LOSCFG_TRACE_FRAME_EVENT_COUNT == 1) 165 PRINTK("eventCount "); 166#endif 167 if (LOSCFG_TRACE_FRAME_MAX_PARAMS > 0) { 168 PRINTK("params "); 169 } 170 PRINTK("\n"); 171} 172 173STATIC VOID OsTraceInfoEventData(VOID) 174{ 175 UINT32 i, j; 176 TraceEventFrame *frame = &g_traceRecoder.ctrl.frameBuf[0]; 177 178 for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++, frame++) { 179 PRINTK("%-7u 0x%-15llx 0x%-12x 0x%-7x 0x%-11x ", i, (UINT32)frame->curTime, frame->eventType, 180 frame->curTask, frame->identity); 181#if (LOSCFG_TRACE_FRAME_CORE_MSG == 1) 182 UINT32 taskLockCnt = frame->core.taskLockCnt; 183#if (LOSCFG_KERNEL_SMP == 1) 184 /* 185 * For smp systems, TRACE_LOCK will request taskLock, and this counter 186 * will increase by 1 in that case. 187 */ 188 taskLockCnt -= 1; 189#endif 190 PRINTK("%-11u %-11u %-11u", frame->core.cpuId, frame->core.hwiActive, taskLockCnt); 191#endif 192#if (LOSCFG_TRACE_FRAME_EVENT_COUNT == 1) 193 PRINTK("%-11u", frame->eventCount); 194#endif 195 for (j = 0; j < LOSCFG_TRACE_FRAME_MAX_PARAMS; j++) { 196 PRINTK("0x%-11x", frame->params[j]); 197 } 198 PRINTK("\n"); 199 } 200} 201 202STATIC VOID OsTraceInfoDisplay(VOID) 203{ 204 OfflineHead *head = g_traceRecoder.head; 205 206 PRINTK("*******TraceInfo begin*******\n"); 207 PRINTK("clockFreq = %u\n", head->baseInfo.clockFreq); 208 209 OsTraceInfoObj(); 210 211 OsTraceInfoEventTitle(); 212 OsTraceInfoEventData(); 213 214 PRINTK("*******TraceInfo end*******\n"); 215} 216 217#if (LOSCFG_TRACE_CLIENT_INTERACT == 1) 218STATIC VOID OsTraceSendInfo(VOID) 219{ 220 UINT32 i; 221 ObjData *obj = NULL; 222 TraceEventFrame *frame = NULL; 223 224 OsTraceDataSend(HEAD, sizeof(OfflineHead), (UINT8 *)g_traceRecoder.head); 225 226 obj = &g_traceRecoder.ctrl.objBuf[0]; 227 for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++) { 228 OsTraceDataSend(OBJ, sizeof(ObjData), (UINT8 *)(obj + i)); 229 } 230 231 frame = &g_traceRecoder.ctrl.frameBuf[0]; 232 for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++) { 233 OsTraceDataSend(EVENT, sizeof(TraceEventFrame), (UINT8 *)(frame + i)); 234 } 235} 236#endif 237 238VOID OsTraceRecordDump(BOOL toClient) 239{ 240 if (!toClient) { 241 OsTraceInfoDisplay(); 242 return; 243 } 244 245#if (LOSCFG_TRACE_CLIENT_INTERACT == 1) 246 OsTraceSendInfo(); 247#endif 248} 249 250OfflineHead *OsTraceRecordGet(VOID) 251{ 252 return g_traceRecoder.head; 253} 254 255#endif /* LOSCFG_RECORDER_MODE_OFFLINE == 1 */ 256