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