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 "los_config.h" 36#include "securec.h" 37#include "trace_cnv.h" 38 39#if (LOSCFG_KERNEL_SMP == 1) 40#include "los_mp_pri.h" 41#endif 42 43#if (LOSCFG_SHELL == 1) 44#include "shcmd.h" 45#include "shell.h" 46#endif 47 48#if (LOSCFG_KERNEL_TRACE == 1) 49LITE_OS_SEC_BSS STATIC UINT32 g_traceEventCount; 50LITE_OS_SEC_BSS STATIC volatile enum TraceState g_traceState = TRACE_UNINIT; 51LITE_OS_SEC_DATA_INIT STATIC volatile BOOL g_enableTrace = FALSE; 52LITE_OS_SEC_BSS STATIC UINT32 g_traceMask = TRACE_DEFAULT_MASK; 53 54TRACE_EVENT_HOOK g_traceEventHook = NULL; 55TRACE_DUMP_HOOK g_traceDumpHook = NULL; 56 57#if (LOSCFG_TRACE_CONTROL_AGENT == 1) 58LITE_OS_SEC_BSS STATIC UINT32 g_traceTaskId; 59#endif 60 61#define EVENT_MASK 0xFFFFFFF0 62#define MIN(x, y) ((x) < (y) ? (x) : (y)) 63 64LITE_OS_SEC_BSS STATIC TRACE_HWI_FILTER_HOOK g_traceHwiFliterHook = NULL; 65 66#if (LOSCFG_KERNEL_SMP == 1) 67LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_traceSpin); 68#endif 69 70STATIC_INLINE BOOL OsTraceHwiFilter(UINT32 hwiNum) 71{ 72 BOOL ret = ((hwiNum == NUM_HAL_INTERRUPT_UART) || (hwiNum == OS_TICK_INT_NUM)); 73#if (LOSCFG_KERNEL_SMP == 1) 74 ret |= (hwiNum == LOS_MP_IPI_SCHEDULE); 75#endif 76 if (g_traceHwiFliterHook != NULL) { 77 ret |= g_traceHwiFliterHook(hwiNum); 78 } 79 return ret; 80} 81 82STATIC VOID OsTraceSetFrame(TraceEventFrame *frame, UINT32 eventType, UINTPTR identity, const UINTPTR *params, 83 UINT16 paramCount) 84{ 85 INT32 i; 86 UINT32 intSave; 87 88 (VOID)memset_s(frame, sizeof(TraceEventFrame), 0, sizeof(TraceEventFrame)); 89 90 if (paramCount > LOSCFG_TRACE_FRAME_MAX_PARAMS) { 91 paramCount = LOSCFG_TRACE_FRAME_MAX_PARAMS; 92 } 93 94 TRACE_LOCK(intSave); 95 frame->curTask = OsTraceGetMaskTid(LOS_CurTaskIDGet()); 96 frame->identity = identity; 97 frame->curTime = LOS_SysCycleGet(); 98 frame->eventType = eventType; 99 100#if (LOSCFG_TRACE_FRAME_CORE_MSG == 1) 101 frame->core.cpuId = ArchCurrCpuid(); 102 frame->core.hwiActive = OS_INT_ACTIVE ? TRUE : FALSE; 103 frame->core.taskLockCnt = MIN(OsPercpuGet()->taskLockCnt, 0xF); /* taskLockCnt is 4 bits, max value = 0xF */ 104 frame->core.paramCount = paramCount; 105#endif 106 107#if (LOSCFG_TRACE_FRAME_EVENT_COUNT == 1) 108 frame->eventCount = g_traceEventCount; 109 g_traceEventCount++; 110#endif 111 TRACE_UNLOCK(intSave); 112 113 for (i = 0; i < paramCount; i++) { 114 frame->params[i] = params[i]; 115 } 116} 117 118VOID OsTraceSetObj(ObjData *obj, const LosTaskCB *tcb) 119{ 120 errno_t ret; 121 (VOID)memset_s(obj, sizeof(ObjData), 0, sizeof(ObjData)); 122 123 obj->id = OsTraceGetMaskTid(tcb->taskID); 124 obj->prio = tcb->priority; 125 126 ret = strncpy_s(obj->name, LOSCFG_TRACE_OBJ_MAX_NAME_SIZE, tcb->taskName, LOSCFG_TRACE_OBJ_MAX_NAME_SIZE - 1); 127 if (ret != EOK) { 128 TRACE_ERROR("Task name copy failed!\n"); 129 } 130} 131 132VOID OsTraceHook(UINT32 eventType, UINTPTR identity, const UINTPTR *params, UINT16 paramCount) 133{ 134 if ((eventType == TASK_CREATE) || (eventType == TASK_PRIOSET)) { 135 OsTraceObjAdd(eventType, identity); /* handle important obj info, these can not be filtered */ 136 } 137 138 if ((g_enableTrace == TRUE) && (eventType & g_traceMask)) { 139 UINTPTR id = identity; 140 if (TRACE_GET_MODE_FLAG(eventType) == TRACE_HWI_FLAG) { 141 if (OsTraceHwiFilter(identity)) { 142 return; 143 } 144 } else if (TRACE_GET_MODE_FLAG(eventType) == TRACE_TASK_FLAG) { 145 id = OsTraceGetMaskTid(identity); 146 } else if (eventType == MEM_INFO_REQ) { 147 LOS_MEM_POOL_STATUS status; 148 LOS_MemInfoGet((VOID *)identity, &status); 149 LOS_TRACE(MEM_INFO, identity, status.totalUsedSize, status.totalFreeSize); 150 return; 151 } 152 153 TraceEventFrame frame; 154 OsTraceSetFrame(&frame, eventType, id, params, paramCount); 155 156 OsTraceWriteOrSendEvent(&frame); 157 } 158} 159 160BOOL OsTraceIsEnable(VOID) 161{ 162 return g_enableTrace == TRUE; 163} 164 165STATIC VOID OsTraceHookInstall(VOID) 166{ 167 g_traceEventHook = OsTraceHook; 168#if (LOSCFG_RECORDER_MODE_OFFLINE == 1) 169 g_traceDumpHook = OsTraceRecordDump; 170#endif 171} 172 173#if (LOSCFG_TRACE_CONTROL_AGENT == 1) 174STATIC BOOL OsTraceCmdIsValid(const TraceClientCmd *msg) 175{ 176 return ((msg->end == TRACE_CMD_END_CHAR) && (msg->cmd < TRACE_CMD_MAX_CODE)); 177} 178 179STATIC VOID OsTraceCmdHandle(const TraceClientCmd *msg) 180{ 181 if (!OsTraceCmdIsValid(msg)) { 182 return; 183 } 184 185 switch (msg->cmd) { 186 case TRACE_CMD_START: 187 LOS_TraceStart(); 188 break; 189 case TRACE_CMD_STOP: 190 LOS_TraceStop(); 191 break; 192 case TRACE_CMD_SET_EVENT_MASK: 193 /* 4 params(UINT8) composition the mask(UINT32) */ 194 LOS_TraceEventMaskSet(TRACE_MASK_COMBINE(msg->param1, msg->param2, msg->param3, msg->param4)); 195 break; 196 case TRACE_CMD_RECODE_DUMP: 197 LOS_TraceRecordDump(TRUE); 198 break; 199 default: 200 break; 201 } 202} 203 204VOID TraceAgent(VOID) 205{ 206 UINT32 ret; 207 TraceClientCmd msg; 208 209 while (1) { 210 (VOID)memset_s(&msg, sizeof(TraceClientCmd), 0, sizeof(TraceClientCmd)); 211 ret = OsTraceDataWait(); 212 if (ret == LOS_OK) { 213 OsTraceDataRecv((UINT8 *)&msg, sizeof(TraceClientCmd), 0); 214 OsTraceCmdHandle(&msg); 215 } 216 } 217} 218 219STATIC UINT32 OsCreateTraceAgentTask(VOID) 220{ 221 UINT32 ret; 222 TSK_INIT_PARAM_S taskInitParam; 223 224 (VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); 225 taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)TraceAgent; 226 taskInitParam.usTaskPrio = LOSCFG_TRACE_TASK_PRIORITY; 227 taskInitParam.pcName = "TraceAgent"; 228 taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 229#if (LOSCFG_KERNEL_SMP == 1) 230 taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid()); 231#endif 232 ret = LOS_TaskCreate(&g_traceTaskId, &taskInitParam); 233 return ret; 234} 235#endif 236 237UINT32 OsTraceInit(VOID) 238{ 239 UINT32 intSave; 240 UINT32 ret; 241 242 TRACE_LOCK(intSave); 243 if (g_traceState != TRACE_UNINIT) { 244 TRACE_ERROR("trace has been initialized already, the current state is :%d\n", g_traceState); 245 ret = LOS_ERRNO_TRACE_ERROR_STATUS; 246 goto LOS_ERREND; 247 } 248 249#if (LOSCFG_TRACE_CLIENT_INTERACT == 1) 250 ret = OsTracePipelineInit(); 251 if (ret != LOS_OK) { 252 goto LOS_ERREND; 253 } 254#endif 255 256#if (LOSCFG_TRACE_CONTROL_AGENT == 1) 257 ret = OsCreateTraceAgentTask(); 258 if (ret != LOS_OK) { 259 TRACE_ERROR("trace init create agentTask error :0x%x\n", ret); 260 goto LOS_ERREND; 261 } 262#endif 263 264#if (LOSCFG_RECORDER_MODE_OFFLINE == 1) 265 ret = OsTraceBufInit(LOSCFG_TRACE_BUFFER_SIZE); 266 if (ret != LOS_OK) { 267#if (LOSCFG_TRACE_CONTROL_AGENT == 1) 268 (VOID)LOS_TaskDelete(g_traceTaskId); 269#endif 270 goto LOS_ERREND; 271 } 272#endif 273 274 OsTraceHookInstall(); 275 OsTraceCnvInit(); 276 277 g_traceEventCount = 0; 278 279#if (LOSCFG_RECORDER_MODE_ONLINE == 1) /* Wait trace client to start trace */ 280 g_enableTrace = FALSE; 281 g_traceState = TRACE_INITED; 282#else 283 g_enableTrace = TRUE; 284 g_traceState = TRACE_STARTED; 285#endif 286 TRACE_UNLOCK(intSave); 287 return LOS_OK; 288LOS_ERREND: 289 TRACE_UNLOCK(intSave); 290 return ret; 291} 292 293UINT32 LOS_TraceStart(VOID) 294{ 295 UINT32 intSave; 296 UINT32 ret = LOS_OK; 297 298 TRACE_LOCK(intSave); 299 if (g_traceState == TRACE_STARTED) { 300 goto START_END; 301 } 302 303 if (g_traceState == TRACE_UNINIT) { 304 TRACE_ERROR("trace not inited, be sure LOS_TraceInit excute success\n"); 305 ret = LOS_ERRNO_TRACE_ERROR_STATUS; 306 goto START_END; 307 } 308 309 OsTraceNotifyStart(); 310 311 g_enableTrace = TRUE; 312 g_traceState = TRACE_STARTED; 313 314 TRACE_UNLOCK(intSave); 315 LOS_TRACE(MEM_INFO_REQ, m_aucSysMem0); 316 return ret; 317START_END: 318 TRACE_UNLOCK(intSave); 319 return ret; 320} 321 322VOID LOS_TraceStop(VOID) 323{ 324 UINT32 intSave; 325 326 TRACE_LOCK(intSave); 327 if (g_traceState != TRACE_STARTED) { 328 goto STOP_END; 329 } 330 331 g_enableTrace = FALSE; 332 g_traceState = TRACE_STOPED; 333 OsTraceNotifyStop(); 334STOP_END: 335 TRACE_UNLOCK(intSave); 336} 337 338VOID LOS_TraceEventMaskSet(UINT32 mask) 339{ 340 g_traceMask = mask & EVENT_MASK; 341} 342 343VOID LOS_TraceRecordDump(BOOL toClient) 344{ 345 if (g_traceState != TRACE_STOPED) { 346 TRACE_ERROR("trace dump must after trace stopped , the current state is : %d\n", g_traceState); 347 return; 348 } 349 OsTraceRecordDump(toClient); 350} 351 352OfflineHead *LOS_TraceRecordGet(VOID) 353{ 354 return OsTraceRecordGet(); 355} 356 357VOID LOS_TraceReset(VOID) 358{ 359 if (g_traceState == TRACE_UNINIT) { 360 TRACE_ERROR("trace not inited, be sure LOS_TraceInit excute success\n"); 361 return; 362 } 363 364 OsTraceReset(); 365} 366 367VOID LOS_TraceHwiFilterHookReg(TRACE_HWI_FILTER_HOOK hook) 368{ 369 UINT32 intSave; 370 371 TRACE_LOCK(intSave); 372 g_traceHwiFliterHook = hook; 373 TRACE_UNLOCK(intSave); 374} 375 376#if (LOSCFG_SHELL == 1) 377LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTraceSetMask(INT32 argc, const CHAR **argv) 378{ 379 size_t mask; 380 CHAR *endPtr = NULL; 381 382 if (argc >= 2) { /* 2:Just as number of parameters */ 383 PRINTK("\nUsage: trace_mask or trace_mask ID\n"); 384 return OS_ERROR; 385 } 386 387 if (argc == 0) { 388 mask = TRACE_DEFAULT_MASK; 389 } else { 390 mask = strtoul(argv[0], &endPtr, 0); 391 } 392 LOS_TraceEventMaskSet((UINT32)mask); 393 return LOS_OK; 394} 395 396LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTraceDump(INT32 argc, const CHAR **argv) 397{ 398 BOOL toClient; 399 CHAR *endPtr = NULL; 400 401 if (argc >= 2) { /* 2:Just as number of parameters */ 402 PRINTK("\nUsage: trace_dump or trace_dump [1/0]\n"); 403 return OS_ERROR; 404 } 405 406 if (argc == 0) { 407 toClient = FALSE; 408 } else { 409 toClient = strtoul(argv[0], &endPtr, 0) != 0 ? TRUE : FALSE; 410 } 411 LOS_TraceRecordDump(toClient); 412 return LOS_OK; 413} 414#endif 415 416#endif /* LOSCFG_KERNEL_TRACE == 1 */ 417