• 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 #if (LOSCFG_KERNEL_TRACE == 1)
49 LITE_OS_SEC_BSS STATIC UINT32 g_traceEventCount;
50 LITE_OS_SEC_BSS STATIC volatile enum TraceState g_traceState = TRACE_UNINIT;
51 LITE_OS_SEC_DATA_INIT STATIC volatile BOOL g_enableTrace = FALSE;
52 LITE_OS_SEC_BSS STATIC UINT32 g_traceMask = TRACE_DEFAULT_MASK;
53 
54 TRACE_EVENT_HOOK g_traceEventHook = NULL;
55 TRACE_DUMP_HOOK g_traceDumpHook = NULL;
56 
57 #if (LOSCFG_TRACE_CONTROL_AGENT == 1)
58 LITE_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 
64 LITE_OS_SEC_BSS STATIC TRACE_HWI_FILTER_HOOK g_traceHwiFliterHook = NULL;
65 
66 #if (LOSCFG_KERNEL_SMP == 1)
67 LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_traceSpin);
68 #endif
69 
OsTraceHwiFilter(UINT32 hwiNum)70 STATIC_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 
OsTraceSetFrame(TraceEventFrame * frame,UINT32 eventType,UINTPTR identity,const UINTPTR * params,UINT16 paramCount)82 STATIC 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 
OsTraceSetObj(ObjData * obj,const LosTaskCB * tcb)118 VOID 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 
OsTraceHook(UINT32 eventType,UINTPTR identity,const UINTPTR * params,UINT16 paramCount)132 VOID 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 
OsTraceIsEnable(VOID)160 BOOL OsTraceIsEnable(VOID)
161 {
162     return g_enableTrace == TRUE;
163 }
164 
OsTraceHookInstall(VOID)165 STATIC 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)
OsTraceCmdIsValid(const TraceClientCmd * msg)174 STATIC BOOL OsTraceCmdIsValid(const TraceClientCmd *msg)
175 {
176     return ((msg->end == TRACE_CMD_END_CHAR) && (msg->cmd < TRACE_CMD_MAX_CODE));
177 }
178 
OsTraceCmdHandle(const TraceClientCmd * msg)179 STATIC 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 
TraceAgent(VOID)204 VOID 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 
OsCreateTraceAgentTask(VOID)219 STATIC 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 
OsTraceInit(VOID)237 UINT32 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;
288 LOS_ERREND:
289     TRACE_UNLOCK(intSave);
290     return ret;
291 }
292 
LOS_TraceStart(VOID)293 UINT32 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;
317 START_END:
318     TRACE_UNLOCK(intSave);
319     return ret;
320 }
321 
LOS_TraceStop(VOID)322 VOID 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();
334 STOP_END:
335     TRACE_UNLOCK(intSave);
336 }
337 
LOS_TraceEventMaskSet(UINT32 mask)338 VOID LOS_TraceEventMaskSet(UINT32 mask)
339 {
340     g_traceMask = mask & EVENT_MASK;
341 }
342 
LOS_TraceRecordDump(BOOL toClient)343 VOID 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 
LOS_TraceRecordGet(VOID)352 OfflineHead *LOS_TraceRecordGet(VOID)
353 {
354     return OsTraceRecordGet();
355 }
356 
LOS_TraceReset(VOID)357 VOID 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 
LOS_TraceHwiFilterHookReg(TRACE_HWI_FILTER_HOOK hook)367 VOID 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)
OsShellCmdTraceSetMask(INT32 argc,const CHAR ** argv)377 LITE_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 
OsShellCmdTraceDump(INT32 argc,const CHAR ** argv)396 LITE_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