10d163575Sopenharmony_ci/*
20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
30d163575Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
40d163575Sopenharmony_ci *
50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
60d163575Sopenharmony_ci * are permitted provided that the following conditions are met:
70d163575Sopenharmony_ci *
80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
90d163575Sopenharmony_ci *    conditions and the following disclaimer.
100d163575Sopenharmony_ci *
110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
120d163575Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
130d163575Sopenharmony_ci *    provided with the distribution.
140d163575Sopenharmony_ci *
150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
160d163575Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
170d163575Sopenharmony_ci *    permission.
180d163575Sopenharmony_ci *
190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
300d163575Sopenharmony_ci */
310d163575Sopenharmony_ci
320d163575Sopenharmony_ci#include "los_trace_pri.h"
330d163575Sopenharmony_ci#include "trace_pipeline.h"
340d163575Sopenharmony_ci
350d163575Sopenharmony_ci#define BITS_NUM_FOR_TASK_ID 16
360d163575Sopenharmony_ci
370d163575Sopenharmony_ciLITE_OS_SEC_BSS STATIC TraceOfflineHeaderInfo g_traceRecoder;
380d163575Sopenharmony_ciLITE_OS_SEC_BSS STATIC UINT32 g_tidMask[LOSCFG_BASE_CORE_TSK_LIMIT] = {0};
390d163575Sopenharmony_ci
400d163575Sopenharmony_ciUINT32 OsTraceGetMaskTid(UINT32 tid)
410d163575Sopenharmony_ci{
420d163575Sopenharmony_ci    return tid | ((tid < LOSCFG_BASE_CORE_TSK_LIMIT) ? g_tidMask[tid] << BITS_NUM_FOR_TASK_ID : 0); /* tid < 65535 */
430d163575Sopenharmony_ci}
440d163575Sopenharmony_ci
450d163575Sopenharmony_ciUINT32 OsTraceBufInit(UINT32 size)
460d163575Sopenharmony_ci{
470d163575Sopenharmony_ci    UINT32 headSize;
480d163575Sopenharmony_ci    VOID *buf = NULL;
490d163575Sopenharmony_ci    headSize = sizeof(OfflineHead) + sizeof(ObjData) * LOSCFG_TRACE_OBJ_MAX_NUM;
500d163575Sopenharmony_ci    if (size <= headSize) {
510d163575Sopenharmony_ci        TRACE_ERROR("trace buf size not enough than 0x%x\n", headSize);
520d163575Sopenharmony_ci        return LOS_ERRNO_TRACE_BUF_TOO_SMALL;
530d163575Sopenharmony_ci    }
540d163575Sopenharmony_ci
550d163575Sopenharmony_ci
560d163575Sopenharmony_ci    buf = LOS_MemAlloc(m_aucSysMem0, size);
570d163575Sopenharmony_ci    if (buf == NULL) {
580d163575Sopenharmony_ci        return LOS_ERRNO_TRACE_NO_MEMORY;
590d163575Sopenharmony_ci    }
600d163575Sopenharmony_ci
610d163575Sopenharmony_ci    (VOID)memset_s(buf, size, 0, size);
620d163575Sopenharmony_ci    g_traceRecoder.head = (OfflineHead *)buf;
630d163575Sopenharmony_ci    g_traceRecoder.head->baseInfo.bigLittleEndian = TRACE_BIGLITTLE_WORD;
640d163575Sopenharmony_ci    g_traceRecoder.head->baseInfo.version         = TRACE_VERSION(TRACE_MODE_OFFLINE);
650d163575Sopenharmony_ci    g_traceRecoder.head->baseInfo.clockFreq       = OS_SYS_CLOCK;
660d163575Sopenharmony_ci    g_traceRecoder.head->objSize                  = sizeof(ObjData);
670d163575Sopenharmony_ci    g_traceRecoder.head->frameSize                = sizeof(TraceEventFrame);
680d163575Sopenharmony_ci    g_traceRecoder.head->objOffset                = sizeof(OfflineHead);
690d163575Sopenharmony_ci    g_traceRecoder.head->frameOffset              = headSize;
700d163575Sopenharmony_ci    g_traceRecoder.head->totalLen                 = size;
710d163575Sopenharmony_ci
720d163575Sopenharmony_ci    g_traceRecoder.ctrl.curIndex       = 0;
730d163575Sopenharmony_ci    g_traceRecoder.ctrl.curObjIndex    = 0;
740d163575Sopenharmony_ci    g_traceRecoder.ctrl.maxObjCount    = LOSCFG_TRACE_OBJ_MAX_NUM;
750d163575Sopenharmony_ci    g_traceRecoder.ctrl.maxRecordCount = (size - headSize) / sizeof(TraceEventFrame);
760d163575Sopenharmony_ci    g_traceRecoder.ctrl.objBuf         = (ObjData *)((UINTPTR)buf + g_traceRecoder.head->objOffset);
770d163575Sopenharmony_ci    g_traceRecoder.ctrl.frameBuf       = (TraceEventFrame *)((UINTPTR)buf + g_traceRecoder.head->frameOffset);
780d163575Sopenharmony_ci
790d163575Sopenharmony_ci    return LOS_OK;
800d163575Sopenharmony_ci}
810d163575Sopenharmony_ci
820d163575Sopenharmony_ciVOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId)
830d163575Sopenharmony_ci{
840d163575Sopenharmony_ci    UINT32 intSave;
850d163575Sopenharmony_ci    UINT32 index;
860d163575Sopenharmony_ci    ObjData *obj = NULL;
870d163575Sopenharmony_ci
880d163575Sopenharmony_ci    TRACE_LOCK(intSave);
890d163575Sopenharmony_ci    /* add obj begin */
900d163575Sopenharmony_ci    index = g_traceRecoder.ctrl.curObjIndex;
910d163575Sopenharmony_ci    if (index >= LOSCFG_TRACE_OBJ_MAX_NUM) { /* do nothing when config LOSCFG_TRACE_OBJ_MAX_NUM = 0 */
920d163575Sopenharmony_ci        TRACE_UNLOCK(intSave);
930d163575Sopenharmony_ci        return;
940d163575Sopenharmony_ci    }
950d163575Sopenharmony_ci    obj = &g_traceRecoder.ctrl.objBuf[index];
960d163575Sopenharmony_ci
970d163575Sopenharmony_ci    if (taskId < LOSCFG_BASE_CORE_TSK_LIMIT) {
980d163575Sopenharmony_ci        g_tidMask[taskId]++;
990d163575Sopenharmony_ci    }
1000d163575Sopenharmony_ci
1010d163575Sopenharmony_ci    OsTraceSetObj(obj, OS_TCB_FROM_TID(taskId));
1020d163575Sopenharmony_ci
1030d163575Sopenharmony_ci    g_traceRecoder.ctrl.curObjIndex++;
1040d163575Sopenharmony_ci    if (g_traceRecoder.ctrl.curObjIndex >= g_traceRecoder.ctrl.maxObjCount) {
1050d163575Sopenharmony_ci        g_traceRecoder.ctrl.curObjIndex = 0; /* turn around */
1060d163575Sopenharmony_ci    }
1070d163575Sopenharmony_ci    /* add obj end */
1080d163575Sopenharmony_ci    TRACE_UNLOCK(intSave);
1090d163575Sopenharmony_ci}
1100d163575Sopenharmony_ci
1110d163575Sopenharmony_ciVOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame)
1120d163575Sopenharmony_ci{
1130d163575Sopenharmony_ci    UINT16 index;
1140d163575Sopenharmony_ci    UINT32 intSave;
1150d163575Sopenharmony_ci
1160d163575Sopenharmony_ci    TRACE_LOCK(intSave);
1170d163575Sopenharmony_ci    index = g_traceRecoder.ctrl.curIndex;
1180d163575Sopenharmony_ci    (VOID)memcpy_s(&g_traceRecoder.ctrl.frameBuf[index], sizeof(TraceEventFrame), frame, sizeof(TraceEventFrame));
1190d163575Sopenharmony_ci
1200d163575Sopenharmony_ci    g_traceRecoder.ctrl.curIndex++;
1210d163575Sopenharmony_ci    if (g_traceRecoder.ctrl.curIndex >= g_traceRecoder.ctrl.maxRecordCount) {
1220d163575Sopenharmony_ci        g_traceRecoder.ctrl.curIndex = 0;
1230d163575Sopenharmony_ci    }
1240d163575Sopenharmony_ci    TRACE_UNLOCK(intSave);
1250d163575Sopenharmony_ci}
1260d163575Sopenharmony_ci
1270d163575Sopenharmony_ciVOID OsTraceReset(VOID)
1280d163575Sopenharmony_ci{
1290d163575Sopenharmony_ci    UINT32 intSave;
1300d163575Sopenharmony_ci    UINT32 bufLen;
1310d163575Sopenharmony_ci
1320d163575Sopenharmony_ci    TRACE_LOCK(intSave);
1330d163575Sopenharmony_ci    bufLen = sizeof(TraceEventFrame) * g_traceRecoder.ctrl.maxRecordCount;
1340d163575Sopenharmony_ci    (VOID)memset_s(g_traceRecoder.ctrl.frameBuf, bufLen, 0, bufLen);
1350d163575Sopenharmony_ci    g_traceRecoder.ctrl.curIndex = 0;
1360d163575Sopenharmony_ci    TRACE_UNLOCK(intSave);
1370d163575Sopenharmony_ci}
1380d163575Sopenharmony_ci
1390d163575Sopenharmony_ciSTATIC VOID OsTraceInfoObj(VOID)
1400d163575Sopenharmony_ci{
1410d163575Sopenharmony_ci    UINT32 i;
1420d163575Sopenharmony_ci    ObjData *obj = &g_traceRecoder.ctrl.objBuf[0];
1430d163575Sopenharmony_ci
1440d163575Sopenharmony_ci    if (g_traceRecoder.ctrl.maxObjCount > 0) {
1450d163575Sopenharmony_ci        PRINTK("CurObjIndex = %u\n", g_traceRecoder.ctrl.curObjIndex);
1460d163575Sopenharmony_ci        PRINTK("Index   TaskID   TaskPrio   TaskName \n");
1470d163575Sopenharmony_ci        for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++, obj++) {
1480d163575Sopenharmony_ci            PRINTK("%-7u 0x%-6x %-10u %s\n", i, obj->id, obj->prio, obj->name);
1490d163575Sopenharmony_ci        }
1500d163575Sopenharmony_ci        PRINTK("\n");
1510d163575Sopenharmony_ci    }
1520d163575Sopenharmony_ci}
1530d163575Sopenharmony_ci
1540d163575Sopenharmony_ciSTATIC VOID OsTraceInfoEventTitle(VOID)
1550d163575Sopenharmony_ci{
1560d163575Sopenharmony_ci    PRINTK("CurEvtIndex = %u\n", g_traceRecoder.ctrl.curIndex);
1570d163575Sopenharmony_ci
1580d163575Sopenharmony_ci    PRINTK("Index   Time(cycles)      EventType      CurPid   CurTask   Identity      ");
1590d163575Sopenharmony_ci#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
1600d163575Sopenharmony_ci    PRINTK("cpuid    hwiActive    taskLockCnt    ");
1610d163575Sopenharmony_ci#endif
1620d163575Sopenharmony_ci#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT
1630d163575Sopenharmony_ci    PRINTK("eventCount    ");
1640d163575Sopenharmony_ci#endif
1650d163575Sopenharmony_ci#ifdef LOS_TRACE_FRAME_LR
1660d163575Sopenharmony_ci    UINT32 i;
1670d163575Sopenharmony_ci    PRINTK("backtrace ");
1680d163575Sopenharmony_ci    for (i = 0; i < LOS_TRACE_LR_RECORD; i++) {
1690d163575Sopenharmony_ci        PRINTK("           ");
1700d163575Sopenharmony_ci    }
1710d163575Sopenharmony_ci#endif
1720d163575Sopenharmony_ci    if (LOSCFG_TRACE_FRAME_MAX_PARAMS > 0) {
1730d163575Sopenharmony_ci        PRINTK("params    ");
1740d163575Sopenharmony_ci    }
1750d163575Sopenharmony_ci    PRINTK("\n");
1760d163575Sopenharmony_ci}
1770d163575Sopenharmony_ci
1780d163575Sopenharmony_ciSTATIC VOID OsTraceInfoEventData(VOID)
1790d163575Sopenharmony_ci{
1800d163575Sopenharmony_ci    UINT32 i, j;
1810d163575Sopenharmony_ci    TraceEventFrame *frame = &g_traceRecoder.ctrl.frameBuf[0];
1820d163575Sopenharmony_ci
1830d163575Sopenharmony_ci    for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++, frame++) {
1840d163575Sopenharmony_ci        PRINTK("%-7u 0x%-15llx 0x%-12x 0x%-7x 0x%-7x 0x%-11x ", i, frame->curTime, frame->eventType,
1850d163575Sopenharmony_ci            frame->curPid, frame->curTask, frame->identity);
1860d163575Sopenharmony_ci#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
1870d163575Sopenharmony_ci        UINT32 taskLockCnt = frame->core.taskLockCnt;
1880d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_SMP
1890d163575Sopenharmony_ci        /*
1900d163575Sopenharmony_ci         * For smp systems, TRACE_LOCK will request taskLock, and this counter
1910d163575Sopenharmony_ci         * will increase by 1 in that case.
1920d163575Sopenharmony_ci         */
1930d163575Sopenharmony_ci        taskLockCnt -= 1;
1940d163575Sopenharmony_ci#endif
1950d163575Sopenharmony_ci        PRINTK("%-11u %-11u %-11u", frame->core.cpuid, frame->core.hwiActive, taskLockCnt);
1960d163575Sopenharmony_ci#endif
1970d163575Sopenharmony_ci#ifdef LOSCFG_TRACE_FRAME_EVENT_COUNT
1980d163575Sopenharmony_ci        PRINTK("%-11u", frame->eventCount);
1990d163575Sopenharmony_ci#endif
2000d163575Sopenharmony_ci#ifdef LOS_TRACE_FRAME_LR
2010d163575Sopenharmony_ci        for (j = 0; j < LOS_TRACE_LR_RECORD; j++) {
2020d163575Sopenharmony_ci            PRINTK("0x%-11x", frame->linkReg[j]);
2030d163575Sopenharmony_ci        }
2040d163575Sopenharmony_ci#endif
2050d163575Sopenharmony_ci        for (j = 0; j < LOSCFG_TRACE_FRAME_MAX_PARAMS; j++) {
2060d163575Sopenharmony_ci            PRINTK("0x%-11x", frame->params[j]);
2070d163575Sopenharmony_ci        }
2080d163575Sopenharmony_ci        PRINTK("\n");
2090d163575Sopenharmony_ci    }
2100d163575Sopenharmony_ci}
2110d163575Sopenharmony_ci
2120d163575Sopenharmony_ciSTATIC VOID OsTraceInfoDisplay(VOID)
2130d163575Sopenharmony_ci{
2140d163575Sopenharmony_ci    OfflineHead *head = g_traceRecoder.head;
2150d163575Sopenharmony_ci
2160d163575Sopenharmony_ci    PRINTK("*******TraceInfo begin*******\n");
2170d163575Sopenharmony_ci    PRINTK("clockFreq = %u\n", head->baseInfo.clockFreq);
2180d163575Sopenharmony_ci
2190d163575Sopenharmony_ci    OsTraceInfoObj();
2200d163575Sopenharmony_ci
2210d163575Sopenharmony_ci    OsTraceInfoEventTitle();
2220d163575Sopenharmony_ci    OsTraceInfoEventData();
2230d163575Sopenharmony_ci
2240d163575Sopenharmony_ci    PRINTK("*******TraceInfo end*******\n");
2250d163575Sopenharmony_ci}
2260d163575Sopenharmony_ci
2270d163575Sopenharmony_ci#ifdef LOSCFG_TRACE_CLIENT_INTERACT
2280d163575Sopenharmony_ciSTATIC VOID OsTraceSendInfo(VOID)
2290d163575Sopenharmony_ci{
2300d163575Sopenharmony_ci    UINT32 i;
2310d163575Sopenharmony_ci    ObjData *obj = NULL;
2320d163575Sopenharmony_ci    TraceEventFrame *frame = NULL;
2330d163575Sopenharmony_ci
2340d163575Sopenharmony_ci    OsTraceDataSend(HEAD, sizeof(OfflineHead), (UINT8 *)g_traceRecoder.head);
2350d163575Sopenharmony_ci
2360d163575Sopenharmony_ci    obj = &g_traceRecoder.ctrl.objBuf[0];
2370d163575Sopenharmony_ci    for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++) {
2380d163575Sopenharmony_ci        OsTraceDataSend(OBJ, sizeof(ObjData), (UINT8 *)(obj + i));
2390d163575Sopenharmony_ci    }
2400d163575Sopenharmony_ci
2410d163575Sopenharmony_ci    frame = &g_traceRecoder.ctrl.frameBuf[0];
2420d163575Sopenharmony_ci    for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++) {
2430d163575Sopenharmony_ci        OsTraceDataSend(EVENT, sizeof(TraceEventFrame), (UINT8 *)(frame + i));
2440d163575Sopenharmony_ci    }
2450d163575Sopenharmony_ci}
2460d163575Sopenharmony_ci#endif
2470d163575Sopenharmony_ci
2480d163575Sopenharmony_ciVOID OsTraceRecordDump(BOOL toClient)
2490d163575Sopenharmony_ci{
2500d163575Sopenharmony_ci    if (!toClient) {
2510d163575Sopenharmony_ci        OsTraceInfoDisplay();
2520d163575Sopenharmony_ci        return;
2530d163575Sopenharmony_ci    }
2540d163575Sopenharmony_ci
2550d163575Sopenharmony_ci#ifdef LOSCFG_TRACE_CLIENT_INTERACT
2560d163575Sopenharmony_ci    OsTraceSendInfo();
2570d163575Sopenharmony_ci#endif
2580d163575Sopenharmony_ci}
2590d163575Sopenharmony_ci
2600d163575Sopenharmony_ciOfflineHead *OsTraceRecordGet(VOID)
2610d163575Sopenharmony_ci{
2620d163575Sopenharmony_ci    return g_traceRecoder.head;
2630d163575Sopenharmony_ci}
264