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