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 "securec.h"
36
37#if (LOSCFG_RECORDER_MODE_OFFLINE == 1)
38#define BITS_NUM_FOR_TASK_ID 16
39
40LITE_OS_SEC_BSS STATIC TraceOfflineHeaderInfo g_traceRecoder;
41LITE_OS_SEC_BSS STATIC UINT32 g_tidMask[LOSCFG_BASE_CORE_TSK_LIMIT] = {0};
42
43UINT32 OsTraceGetMaskTid(UINT32 tid)
44{
45    return tid | ((tid < LOSCFG_BASE_CORE_TSK_LIMIT) ? g_tidMask[tid] << BITS_NUM_FOR_TASK_ID : 0); /* tid < 65535 */
46}
47
48UINT32 OsTraceBufInit(UINT32 size)
49{
50    UINT32 headSize;
51    VOID *buf = NULL;
52    headSize = sizeof(OfflineHead) + sizeof(ObjData) * LOSCFG_TRACE_OBJ_MAX_NUM;
53    if (size <= headSize) {
54        TRACE_ERROR("trace buf size not enough than 0x%x\n", headSize);
55        return LOS_ERRNO_TRACE_BUF_TOO_SMALL;
56    }
57
58    buf = LOS_MemAlloc(m_aucSysMem0, size);
59    if (buf == NULL) {
60        return LOS_ERRNO_TRACE_NO_MEMORY;
61    }
62
63    (VOID)memset_s(buf, size, 0, size);
64    g_traceRecoder.head = (OfflineHead *)buf;
65    g_traceRecoder.head->baseInfo.bigLittleEndian = TRACE_BIGLITTLE_WORD;
66    g_traceRecoder.head->baseInfo.version         = TRACE_VERSION(TRACE_MODE_OFFLINE);
67    g_traceRecoder.head->baseInfo.clockFreq       = g_sysClock;
68    g_traceRecoder.head->objSize                  = sizeof(ObjData);
69    g_traceRecoder.head->frameSize                = sizeof(TraceEventFrame);
70    g_traceRecoder.head->objOffset                = sizeof(OfflineHead);
71    g_traceRecoder.head->frameOffset              = headSize;
72    g_traceRecoder.head->totalLen                 = size;
73
74    g_traceRecoder.ctrl.curIndex       = 0;
75    g_traceRecoder.ctrl.curObjIndex    = 0;
76    g_traceRecoder.ctrl.maxObjCount    = LOSCFG_TRACE_OBJ_MAX_NUM;
77    g_traceRecoder.ctrl.maxRecordCount = (size - headSize) / sizeof(TraceEventFrame);
78    g_traceRecoder.ctrl.objBuf         = (ObjData *)((UINTPTR)buf + g_traceRecoder.head->objOffset);
79    g_traceRecoder.ctrl.frameBuf       = (TraceEventFrame *)((UINTPTR)buf + g_traceRecoder.head->frameOffset);
80
81    return LOS_OK;
82}
83
84VOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId)
85{
86    UINT32 intSave;
87    UINT32 index;
88    ObjData *obj = NULL;
89
90    TRACE_LOCK(intSave);
91    /* add obj begin */
92    index = g_traceRecoder.ctrl.curObjIndex;
93    if (index >= LOSCFG_TRACE_OBJ_MAX_NUM) { /* do nothing when config LOSCFG_TRACE_OBJ_MAX_NUM = 0 */
94        TRACE_UNLOCK(intSave);
95        return;
96    }
97    obj = &g_traceRecoder.ctrl.objBuf[index];
98
99    if (taskId < LOSCFG_BASE_CORE_TSK_LIMIT) {
100        g_tidMask[taskId]++;
101    }
102
103    OsTraceSetObj(obj, OS_TCB_FROM_TID(taskId));
104
105    g_traceRecoder.ctrl.curObjIndex++;
106    if (g_traceRecoder.ctrl.curObjIndex >= g_traceRecoder.ctrl.maxObjCount) {
107        g_traceRecoder.ctrl.curObjIndex = 0; /* turn around */
108    }
109    /* add obj end */
110    TRACE_UNLOCK(intSave);
111}
112
113VOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame)
114{
115    UINT16 index;
116    UINT32 intSave;
117
118    TRACE_LOCK(intSave);
119    index = g_traceRecoder.ctrl.curIndex;
120    (VOID)memcpy_s(&g_traceRecoder.ctrl.frameBuf[index], sizeof(TraceEventFrame), frame, sizeof(TraceEventFrame));
121
122    g_traceRecoder.ctrl.curIndex++;
123    if (g_traceRecoder.ctrl.curIndex >= g_traceRecoder.ctrl.maxRecordCount) {
124        g_traceRecoder.ctrl.curIndex = 0;
125    }
126    TRACE_UNLOCK(intSave);
127}
128
129VOID OsTraceReset(VOID)
130{
131    UINT32 intSave;
132    UINT32 bufLen;
133
134    TRACE_LOCK(intSave);
135    bufLen = sizeof(TraceEventFrame) * g_traceRecoder.ctrl.maxRecordCount;
136    (VOID)memset_s(g_traceRecoder.ctrl.frameBuf, bufLen, 0, bufLen);
137    g_traceRecoder.ctrl.curIndex = 0;
138    TRACE_UNLOCK(intSave);
139}
140
141STATIC VOID OsTraceInfoObj(VOID)
142{
143    UINT32 i;
144    ObjData *obj = &g_traceRecoder.ctrl.objBuf[0];
145
146    if (g_traceRecoder.ctrl.maxObjCount > 0) {
147        PRINTK("CurObjIndex = %u\n", g_traceRecoder.ctrl.curObjIndex);
148        PRINTK("Index   TaskID   TaskPrio   TaskName \n");
149        for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++, obj++) {
150            PRINTK("%-7u 0x%-6x %-10u %s\n", i, obj->id, obj->prio, obj->name);
151        }
152        PRINTK("\n");
153    }
154}
155
156STATIC VOID OsTraceInfoEventTitle(VOID)
157{
158    PRINTK("CurEvtIndex = %u\n", g_traceRecoder.ctrl.curIndex);
159
160    PRINTK("Index   Time(cycles)      EventType      CurTask   Identity      ");
161#if (LOSCFG_TRACE_FRAME_CORE_MSG == 1)
162    PRINTK("cpuId    hwiActive    taskLockCnt    ");
163#endif
164#if (LOSCFG_TRACE_FRAME_EVENT_COUNT == 1)
165    PRINTK("eventCount    ");
166#endif
167    if (LOSCFG_TRACE_FRAME_MAX_PARAMS > 0) {
168        PRINTK("params    ");
169    }
170    PRINTK("\n");
171}
172
173STATIC VOID OsTraceInfoEventData(VOID)
174{
175    UINT32 i, j;
176    TraceEventFrame *frame = &g_traceRecoder.ctrl.frameBuf[0];
177
178    for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++, frame++) {
179        PRINTK("%-7u 0x%-15llx 0x%-12x 0x%-7x 0x%-11x ", i, (UINT32)frame->curTime, frame->eventType,
180            frame->curTask, frame->identity);
181#if (LOSCFG_TRACE_FRAME_CORE_MSG == 1)
182        UINT32 taskLockCnt = frame->core.taskLockCnt;
183#if (LOSCFG_KERNEL_SMP == 1)
184        /*
185         * For smp systems, TRACE_LOCK will request taskLock, and this counter
186         * will increase by 1 in that case.
187         */
188        taskLockCnt -= 1;
189#endif
190        PRINTK("%-11u %-11u %-11u", frame->core.cpuId, frame->core.hwiActive, taskLockCnt);
191#endif
192#if (LOSCFG_TRACE_FRAME_EVENT_COUNT == 1)
193        PRINTK("%-11u", frame->eventCount);
194#endif
195        for (j = 0; j < LOSCFG_TRACE_FRAME_MAX_PARAMS; j++) {
196            PRINTK("0x%-11x", frame->params[j]);
197        }
198        PRINTK("\n");
199    }
200}
201
202STATIC VOID OsTraceInfoDisplay(VOID)
203{
204    OfflineHead *head = g_traceRecoder.head;
205
206    PRINTK("*******TraceInfo begin*******\n");
207    PRINTK("clockFreq = %u\n", head->baseInfo.clockFreq);
208
209    OsTraceInfoObj();
210
211    OsTraceInfoEventTitle();
212    OsTraceInfoEventData();
213
214    PRINTK("*******TraceInfo end*******\n");
215}
216
217#if (LOSCFG_TRACE_CLIENT_INTERACT == 1)
218STATIC VOID OsTraceSendInfo(VOID)
219{
220    UINT32 i;
221    ObjData *obj = NULL;
222    TraceEventFrame *frame = NULL;
223
224    OsTraceDataSend(HEAD, sizeof(OfflineHead), (UINT8 *)g_traceRecoder.head);
225
226    obj = &g_traceRecoder.ctrl.objBuf[0];
227    for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++) {
228        OsTraceDataSend(OBJ, sizeof(ObjData), (UINT8 *)(obj + i));
229    }
230
231    frame = &g_traceRecoder.ctrl.frameBuf[0];
232    for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++) {
233        OsTraceDataSend(EVENT, sizeof(TraceEventFrame), (UINT8 *)(frame + i));
234    }
235}
236#endif
237
238VOID OsTraceRecordDump(BOOL toClient)
239{
240    if (!toClient) {
241        OsTraceInfoDisplay();
242        return;
243    }
244
245#if (LOSCFG_TRACE_CLIENT_INTERACT == 1)
246    OsTraceSendInfo();
247#endif
248}
249
250OfflineHead *OsTraceRecordGet(VOID)
251{
252    return g_traceRecoder.head;
253}
254
255#endif /* LOSCFG_RECORDER_MODE_OFFLINE == 1 */
256