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