13d8536b4Sopenharmony_ci/*
23d8536b4Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
33d8536b4Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
43d8536b4Sopenharmony_ci *
53d8536b4Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
63d8536b4Sopenharmony_ci * are permitted provided that the following conditions are met:
73d8536b4Sopenharmony_ci *
83d8536b4Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
93d8536b4Sopenharmony_ci *    conditions and the following disclaimer.
103d8536b4Sopenharmony_ci *
113d8536b4Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
123d8536b4Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
133d8536b4Sopenharmony_ci *    provided with the distribution.
143d8536b4Sopenharmony_ci *
153d8536b4Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
163d8536b4Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
173d8536b4Sopenharmony_ci *    permission.
183d8536b4Sopenharmony_ci *
193d8536b4Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
203d8536b4Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
213d8536b4Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223d8536b4Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
233d8536b4Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
243d8536b4Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
253d8536b4Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
263d8536b4Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
273d8536b4Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
283d8536b4Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
293d8536b4Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
303d8536b4Sopenharmony_ci */
313d8536b4Sopenharmony_ci
323d8536b4Sopenharmony_ci#include "los_trace_pri.h"
333d8536b4Sopenharmony_ci#include "trace_pipeline.h"
343d8536b4Sopenharmony_ci#include "los_memory.h"
353d8536b4Sopenharmony_ci#include "securec.h"
363d8536b4Sopenharmony_ci
373d8536b4Sopenharmony_ci#if (LOSCFG_RECORDER_MODE_OFFLINE == 1)
383d8536b4Sopenharmony_ci#define BITS_NUM_FOR_TASK_ID 16
393d8536b4Sopenharmony_ci
403d8536b4Sopenharmony_ciLITE_OS_SEC_BSS STATIC TraceOfflineHeaderInfo g_traceRecoder;
413d8536b4Sopenharmony_ciLITE_OS_SEC_BSS STATIC UINT32 g_tidMask[LOSCFG_BASE_CORE_TSK_LIMIT] = {0};
423d8536b4Sopenharmony_ci
433d8536b4Sopenharmony_ciUINT32 OsTraceGetMaskTid(UINT32 tid)
443d8536b4Sopenharmony_ci{
453d8536b4Sopenharmony_ci    return tid | ((tid < LOSCFG_BASE_CORE_TSK_LIMIT) ? g_tidMask[tid] << BITS_NUM_FOR_TASK_ID : 0); /* tid < 65535 */
463d8536b4Sopenharmony_ci}
473d8536b4Sopenharmony_ci
483d8536b4Sopenharmony_ciUINT32 OsTraceBufInit(UINT32 size)
493d8536b4Sopenharmony_ci{
503d8536b4Sopenharmony_ci    UINT32 headSize;
513d8536b4Sopenharmony_ci    VOID *buf = NULL;
523d8536b4Sopenharmony_ci    headSize = sizeof(OfflineHead) + sizeof(ObjData) * LOSCFG_TRACE_OBJ_MAX_NUM;
533d8536b4Sopenharmony_ci    if (size <= headSize) {
543d8536b4Sopenharmony_ci        TRACE_ERROR("trace buf size not enough than 0x%x\n", headSize);
553d8536b4Sopenharmony_ci        return LOS_ERRNO_TRACE_BUF_TOO_SMALL;
563d8536b4Sopenharmony_ci    }
573d8536b4Sopenharmony_ci
583d8536b4Sopenharmony_ci    buf = LOS_MemAlloc(m_aucSysMem0, size);
593d8536b4Sopenharmony_ci    if (buf == NULL) {
603d8536b4Sopenharmony_ci        return LOS_ERRNO_TRACE_NO_MEMORY;
613d8536b4Sopenharmony_ci    }
623d8536b4Sopenharmony_ci
633d8536b4Sopenharmony_ci    (VOID)memset_s(buf, size, 0, size);
643d8536b4Sopenharmony_ci    g_traceRecoder.head = (OfflineHead *)buf;
653d8536b4Sopenharmony_ci    g_traceRecoder.head->baseInfo.bigLittleEndian = TRACE_BIGLITTLE_WORD;
663d8536b4Sopenharmony_ci    g_traceRecoder.head->baseInfo.version         = TRACE_VERSION(TRACE_MODE_OFFLINE);
673d8536b4Sopenharmony_ci    g_traceRecoder.head->baseInfo.clockFreq       = g_sysClock;
683d8536b4Sopenharmony_ci    g_traceRecoder.head->objSize                  = sizeof(ObjData);
693d8536b4Sopenharmony_ci    g_traceRecoder.head->frameSize                = sizeof(TraceEventFrame);
703d8536b4Sopenharmony_ci    g_traceRecoder.head->objOffset                = sizeof(OfflineHead);
713d8536b4Sopenharmony_ci    g_traceRecoder.head->frameOffset              = headSize;
723d8536b4Sopenharmony_ci    g_traceRecoder.head->totalLen                 = size;
733d8536b4Sopenharmony_ci
743d8536b4Sopenharmony_ci    g_traceRecoder.ctrl.curIndex       = 0;
753d8536b4Sopenharmony_ci    g_traceRecoder.ctrl.curObjIndex    = 0;
763d8536b4Sopenharmony_ci    g_traceRecoder.ctrl.maxObjCount    = LOSCFG_TRACE_OBJ_MAX_NUM;
773d8536b4Sopenharmony_ci    g_traceRecoder.ctrl.maxRecordCount = (size - headSize) / sizeof(TraceEventFrame);
783d8536b4Sopenharmony_ci    g_traceRecoder.ctrl.objBuf         = (ObjData *)((UINTPTR)buf + g_traceRecoder.head->objOffset);
793d8536b4Sopenharmony_ci    g_traceRecoder.ctrl.frameBuf       = (TraceEventFrame *)((UINTPTR)buf + g_traceRecoder.head->frameOffset);
803d8536b4Sopenharmony_ci
813d8536b4Sopenharmony_ci    return LOS_OK;
823d8536b4Sopenharmony_ci}
833d8536b4Sopenharmony_ci
843d8536b4Sopenharmony_ciVOID OsTraceObjAdd(UINT32 eventType, UINT32 taskId)
853d8536b4Sopenharmony_ci{
863d8536b4Sopenharmony_ci    UINT32 intSave;
873d8536b4Sopenharmony_ci    UINT32 index;
883d8536b4Sopenharmony_ci    ObjData *obj = NULL;
893d8536b4Sopenharmony_ci
903d8536b4Sopenharmony_ci    TRACE_LOCK(intSave);
913d8536b4Sopenharmony_ci    /* add obj begin */
923d8536b4Sopenharmony_ci    index = g_traceRecoder.ctrl.curObjIndex;
933d8536b4Sopenharmony_ci    if (index >= LOSCFG_TRACE_OBJ_MAX_NUM) { /* do nothing when config LOSCFG_TRACE_OBJ_MAX_NUM = 0 */
943d8536b4Sopenharmony_ci        TRACE_UNLOCK(intSave);
953d8536b4Sopenharmony_ci        return;
963d8536b4Sopenharmony_ci    }
973d8536b4Sopenharmony_ci    obj = &g_traceRecoder.ctrl.objBuf[index];
983d8536b4Sopenharmony_ci
993d8536b4Sopenharmony_ci    if (taskId < LOSCFG_BASE_CORE_TSK_LIMIT) {
1003d8536b4Sopenharmony_ci        g_tidMask[taskId]++;
1013d8536b4Sopenharmony_ci    }
1023d8536b4Sopenharmony_ci
1033d8536b4Sopenharmony_ci    OsTraceSetObj(obj, OS_TCB_FROM_TID(taskId));
1043d8536b4Sopenharmony_ci
1053d8536b4Sopenharmony_ci    g_traceRecoder.ctrl.curObjIndex++;
1063d8536b4Sopenharmony_ci    if (g_traceRecoder.ctrl.curObjIndex >= g_traceRecoder.ctrl.maxObjCount) {
1073d8536b4Sopenharmony_ci        g_traceRecoder.ctrl.curObjIndex = 0; /* turn around */
1083d8536b4Sopenharmony_ci    }
1093d8536b4Sopenharmony_ci    /* add obj end */
1103d8536b4Sopenharmony_ci    TRACE_UNLOCK(intSave);
1113d8536b4Sopenharmony_ci}
1123d8536b4Sopenharmony_ci
1133d8536b4Sopenharmony_ciVOID OsTraceWriteOrSendEvent(const TraceEventFrame *frame)
1143d8536b4Sopenharmony_ci{
1153d8536b4Sopenharmony_ci    UINT16 index;
1163d8536b4Sopenharmony_ci    UINT32 intSave;
1173d8536b4Sopenharmony_ci
1183d8536b4Sopenharmony_ci    TRACE_LOCK(intSave);
1193d8536b4Sopenharmony_ci    index = g_traceRecoder.ctrl.curIndex;
1203d8536b4Sopenharmony_ci    (VOID)memcpy_s(&g_traceRecoder.ctrl.frameBuf[index], sizeof(TraceEventFrame), frame, sizeof(TraceEventFrame));
1213d8536b4Sopenharmony_ci
1223d8536b4Sopenharmony_ci    g_traceRecoder.ctrl.curIndex++;
1233d8536b4Sopenharmony_ci    if (g_traceRecoder.ctrl.curIndex >= g_traceRecoder.ctrl.maxRecordCount) {
1243d8536b4Sopenharmony_ci        g_traceRecoder.ctrl.curIndex = 0;
1253d8536b4Sopenharmony_ci    }
1263d8536b4Sopenharmony_ci    TRACE_UNLOCK(intSave);
1273d8536b4Sopenharmony_ci}
1283d8536b4Sopenharmony_ci
1293d8536b4Sopenharmony_ciVOID OsTraceReset(VOID)
1303d8536b4Sopenharmony_ci{
1313d8536b4Sopenharmony_ci    UINT32 intSave;
1323d8536b4Sopenharmony_ci    UINT32 bufLen;
1333d8536b4Sopenharmony_ci
1343d8536b4Sopenharmony_ci    TRACE_LOCK(intSave);
1353d8536b4Sopenharmony_ci    bufLen = sizeof(TraceEventFrame) * g_traceRecoder.ctrl.maxRecordCount;
1363d8536b4Sopenharmony_ci    (VOID)memset_s(g_traceRecoder.ctrl.frameBuf, bufLen, 0, bufLen);
1373d8536b4Sopenharmony_ci    g_traceRecoder.ctrl.curIndex = 0;
1383d8536b4Sopenharmony_ci    TRACE_UNLOCK(intSave);
1393d8536b4Sopenharmony_ci}
1403d8536b4Sopenharmony_ci
1413d8536b4Sopenharmony_ciSTATIC VOID OsTraceInfoObj(VOID)
1423d8536b4Sopenharmony_ci{
1433d8536b4Sopenharmony_ci    UINT32 i;
1443d8536b4Sopenharmony_ci    ObjData *obj = &g_traceRecoder.ctrl.objBuf[0];
1453d8536b4Sopenharmony_ci
1463d8536b4Sopenharmony_ci    if (g_traceRecoder.ctrl.maxObjCount > 0) {
1473d8536b4Sopenharmony_ci        PRINTK("CurObjIndex = %u\n", g_traceRecoder.ctrl.curObjIndex);
1483d8536b4Sopenharmony_ci        PRINTK("Index   TaskID   TaskPrio   TaskName \n");
1493d8536b4Sopenharmony_ci        for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++, obj++) {
1503d8536b4Sopenharmony_ci            PRINTK("%-7u 0x%-6x %-10u %s\n", i, obj->id, obj->prio, obj->name);
1513d8536b4Sopenharmony_ci        }
1523d8536b4Sopenharmony_ci        PRINTK("\n");
1533d8536b4Sopenharmony_ci    }
1543d8536b4Sopenharmony_ci}
1553d8536b4Sopenharmony_ci
1563d8536b4Sopenharmony_ciSTATIC VOID OsTraceInfoEventTitle(VOID)
1573d8536b4Sopenharmony_ci{
1583d8536b4Sopenharmony_ci    PRINTK("CurEvtIndex = %u\n", g_traceRecoder.ctrl.curIndex);
1593d8536b4Sopenharmony_ci
1603d8536b4Sopenharmony_ci    PRINTK("Index   Time(cycles)      EventType      CurTask   Identity      ");
1613d8536b4Sopenharmony_ci#if (LOSCFG_TRACE_FRAME_CORE_MSG == 1)
1623d8536b4Sopenharmony_ci    PRINTK("cpuId    hwiActive    taskLockCnt    ");
1633d8536b4Sopenharmony_ci#endif
1643d8536b4Sopenharmony_ci#if (LOSCFG_TRACE_FRAME_EVENT_COUNT == 1)
1653d8536b4Sopenharmony_ci    PRINTK("eventCount    ");
1663d8536b4Sopenharmony_ci#endif
1673d8536b4Sopenharmony_ci    if (LOSCFG_TRACE_FRAME_MAX_PARAMS > 0) {
1683d8536b4Sopenharmony_ci        PRINTK("params    ");
1693d8536b4Sopenharmony_ci    }
1703d8536b4Sopenharmony_ci    PRINTK("\n");
1713d8536b4Sopenharmony_ci}
1723d8536b4Sopenharmony_ci
1733d8536b4Sopenharmony_ciSTATIC VOID OsTraceInfoEventData(VOID)
1743d8536b4Sopenharmony_ci{
1753d8536b4Sopenharmony_ci    UINT32 i, j;
1763d8536b4Sopenharmony_ci    TraceEventFrame *frame = &g_traceRecoder.ctrl.frameBuf[0];
1773d8536b4Sopenharmony_ci
1783d8536b4Sopenharmony_ci    for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++, frame++) {
1793d8536b4Sopenharmony_ci        PRINTK("%-7u 0x%-15llx 0x%-12x 0x%-7x 0x%-11x ", i, (UINT32)frame->curTime, frame->eventType,
1803d8536b4Sopenharmony_ci            frame->curTask, frame->identity);
1813d8536b4Sopenharmony_ci#if (LOSCFG_TRACE_FRAME_CORE_MSG == 1)
1823d8536b4Sopenharmony_ci        UINT32 taskLockCnt = frame->core.taskLockCnt;
1833d8536b4Sopenharmony_ci#if (LOSCFG_KERNEL_SMP == 1)
1843d8536b4Sopenharmony_ci        /*
1853d8536b4Sopenharmony_ci         * For smp systems, TRACE_LOCK will request taskLock, and this counter
1863d8536b4Sopenharmony_ci         * will increase by 1 in that case.
1873d8536b4Sopenharmony_ci         */
1883d8536b4Sopenharmony_ci        taskLockCnt -= 1;
1893d8536b4Sopenharmony_ci#endif
1903d8536b4Sopenharmony_ci        PRINTK("%-11u %-11u %-11u", frame->core.cpuId, frame->core.hwiActive, taskLockCnt);
1913d8536b4Sopenharmony_ci#endif
1923d8536b4Sopenharmony_ci#if (LOSCFG_TRACE_FRAME_EVENT_COUNT == 1)
1933d8536b4Sopenharmony_ci        PRINTK("%-11u", frame->eventCount);
1943d8536b4Sopenharmony_ci#endif
1953d8536b4Sopenharmony_ci        for (j = 0; j < LOSCFG_TRACE_FRAME_MAX_PARAMS; j++) {
1963d8536b4Sopenharmony_ci            PRINTK("0x%-11x", frame->params[j]);
1973d8536b4Sopenharmony_ci        }
1983d8536b4Sopenharmony_ci        PRINTK("\n");
1993d8536b4Sopenharmony_ci    }
2003d8536b4Sopenharmony_ci}
2013d8536b4Sopenharmony_ci
2023d8536b4Sopenharmony_ciSTATIC VOID OsTraceInfoDisplay(VOID)
2033d8536b4Sopenharmony_ci{
2043d8536b4Sopenharmony_ci    OfflineHead *head = g_traceRecoder.head;
2053d8536b4Sopenharmony_ci
2063d8536b4Sopenharmony_ci    PRINTK("*******TraceInfo begin*******\n");
2073d8536b4Sopenharmony_ci    PRINTK("clockFreq = %u\n", head->baseInfo.clockFreq);
2083d8536b4Sopenharmony_ci
2093d8536b4Sopenharmony_ci    OsTraceInfoObj();
2103d8536b4Sopenharmony_ci
2113d8536b4Sopenharmony_ci    OsTraceInfoEventTitle();
2123d8536b4Sopenharmony_ci    OsTraceInfoEventData();
2133d8536b4Sopenharmony_ci
2143d8536b4Sopenharmony_ci    PRINTK("*******TraceInfo end*******\n");
2153d8536b4Sopenharmony_ci}
2163d8536b4Sopenharmony_ci
2173d8536b4Sopenharmony_ci#if (LOSCFG_TRACE_CLIENT_INTERACT == 1)
2183d8536b4Sopenharmony_ciSTATIC VOID OsTraceSendInfo(VOID)
2193d8536b4Sopenharmony_ci{
2203d8536b4Sopenharmony_ci    UINT32 i;
2213d8536b4Sopenharmony_ci    ObjData *obj = NULL;
2223d8536b4Sopenharmony_ci    TraceEventFrame *frame = NULL;
2233d8536b4Sopenharmony_ci
2243d8536b4Sopenharmony_ci    OsTraceDataSend(HEAD, sizeof(OfflineHead), (UINT8 *)g_traceRecoder.head);
2253d8536b4Sopenharmony_ci
2263d8536b4Sopenharmony_ci    obj = &g_traceRecoder.ctrl.objBuf[0];
2273d8536b4Sopenharmony_ci    for (i = 0; i < g_traceRecoder.ctrl.maxObjCount; i++) {
2283d8536b4Sopenharmony_ci        OsTraceDataSend(OBJ, sizeof(ObjData), (UINT8 *)(obj + i));
2293d8536b4Sopenharmony_ci    }
2303d8536b4Sopenharmony_ci
2313d8536b4Sopenharmony_ci    frame = &g_traceRecoder.ctrl.frameBuf[0];
2323d8536b4Sopenharmony_ci    for (i = 0; i < g_traceRecoder.ctrl.maxRecordCount; i++) {
2333d8536b4Sopenharmony_ci        OsTraceDataSend(EVENT, sizeof(TraceEventFrame), (UINT8 *)(frame + i));
2343d8536b4Sopenharmony_ci    }
2353d8536b4Sopenharmony_ci}
2363d8536b4Sopenharmony_ci#endif
2373d8536b4Sopenharmony_ci
2383d8536b4Sopenharmony_ciVOID OsTraceRecordDump(BOOL toClient)
2393d8536b4Sopenharmony_ci{
2403d8536b4Sopenharmony_ci    if (!toClient) {
2413d8536b4Sopenharmony_ci        OsTraceInfoDisplay();
2423d8536b4Sopenharmony_ci        return;
2433d8536b4Sopenharmony_ci    }
2443d8536b4Sopenharmony_ci
2453d8536b4Sopenharmony_ci#if (LOSCFG_TRACE_CLIENT_INTERACT == 1)
2463d8536b4Sopenharmony_ci    OsTraceSendInfo();
2473d8536b4Sopenharmony_ci#endif
2483d8536b4Sopenharmony_ci}
2493d8536b4Sopenharmony_ci
2503d8536b4Sopenharmony_ciOfflineHead *OsTraceRecordGet(VOID)
2513d8536b4Sopenharmony_ci{
2523d8536b4Sopenharmony_ci    return g_traceRecoder.head;
2533d8536b4Sopenharmony_ci}
2543d8536b4Sopenharmony_ci
2553d8536b4Sopenharmony_ci#endif /* LOSCFG_RECORDER_MODE_OFFLINE == 1 */
256