feat: L0-L1 支持Trace

1.【需求描述】
            L0~L1 支持Trace,提供两种工作模式:在线模式、离线缓存模式, 用于按时间线追踪系统事件,如任务切换、中断、ipc等。
        2.【方案描述】
            L0:
            (1).在内核模块预置静态代码桩
            (2).触发桩后,收集系统上下文信息
            (3).离线模式则写入内存,用户可通过dump导出;
            (4).在线模式通过pipeline对接IDE进行可视化解析和展示;
            L1:
            新增trace字符设备,位于"/dev/trace",通过对设备节点的read\write\ioctl,实现用户态trace;

        BREAKING CHANGE:
        1.新增一系列trace的对外API,位于los_trace.h中.
        LOS_TRACE_EASY简易插桩
        LOS_TRACE标准插桩
        LOS_TraceInit配置Trace缓冲区的地址和大小
        LOS_TraceStart开启事件记录
        LOS_TraceStop停止事件记录
        LOS_TraceRecordDump输出Trace缓冲区数据
        LOS_TraceRecordGet获取Trace缓冲区的首地址
        LOS_TraceReset清除Trace缓冲区中的事件
        LOS_TraceEventMaskSet设置事件掩码,仅记录某些模块的事件
        LOS_TraceHwiFilterHookReg注册过滤特定中断号事件的钩子函数

        Close #I46WA0

    Signed-off-by: LiteOS2021 <dinglu@huawei.com>

Change-Id: I6a8e64794c4852f2c2980993a06180e09ec6ee0d
This commit is contained in:
LiteOS2021
2021-08-31 16:36:04 +08:00
parent 658fafe83b
commit dc9ec6856f
62 changed files with 3972 additions and 1050 deletions

View File

@@ -40,14 +40,11 @@
#include "los_sched_pri.h"
#include "los_spinlock.h"
#include "los_task_pri.h"
#ifdef LOSCFG_KERNEL_TRACE
#include "los_trace.h"
#include "los_trace_frame.h"
#endif
#include "los_vm_lock.h"
#include "los_vm_map.h"
#include "los_vm_page.h"
#include "los_vm_phys.h"
#include "los_hook.h"
#define USE_TASKID_AS_HANDLE YES
#define USE_MMAP YES
@@ -93,7 +90,6 @@ STATIC UINT32 LiteIpcWrite(IpcContent *content);
STATIC UINT32 GetTid(UINT32 serviceHandle, UINT32 *taskID);
STATIC UINT32 HandleSpecialObjects(UINT32 dstTid, IpcListNode *node, BOOL isRollback);
STATIC const struct file_operations_vfs g_liteIpcFops = {
.open = LiteIpcOpen, /* open */
.close = LiteIpcClose, /* close */
@@ -101,47 +97,6 @@ STATIC const struct file_operations_vfs g_liteIpcFops = {
.mmap = LiteIpcMmap, /* mmap */
};
#ifdef LOSCFG_KERNEL_TRACE
typedef enum {
WRITE,
WRITE_DROP,
TRY_READ,
READ,
READ_DROP,
READ_TIMEOUT,
KILL,
OPERATION_NUM
} IpcOpertion;
const char *g_operStr[OPERATION_NUM] = {"WRITE", "WRITE_DROP", "TRY_READ", "READ", "READ_DROP", "READ_TIMEOUT"};
const char *g_msgTypeStr[MT_NUM] = {"REQUEST", "REPLY", "FAILED_REPLY", "DEATH_NOTIFY"};
const char *g_ipcStatusStr[2] = {"NOT_PEND", "PEND"};
LITE_OS_SEC_TEXT STATIC VOID IpcTrace(IpcMsg *msg, UINT32 operation, UINT32 ipcStatus, UINT32 msgType)
{
UINT32 curTid = LOS_CurTaskIDGet();
UINT32 curPid = LOS_GetCurrProcessID();
UINT32 srcTid;
UINT32 srcPid;
UINT32 dstTid;
UINT32 dstPid;
UINT32 ret = (msg == NULL) ? INVAILD_ID : GetTid(msg->target.handle, &dstTid);
if (operation <= WRITE_DROP) {
srcTid = curTid;
srcPid = curPid;
dstTid = ret ? INVAILD_ID : dstTid;
dstPid = ret ? INVAILD_ID : OS_TCB_FROM_TID(dstTid)->processID;
} else {
srcTid = (msg == NULL) ? INVAILD_ID : msg->taskID;
srcPid = (msg == NULL) ? INVAILD_ID : msg->processID;
dstTid = curTid;
dstPid = curPid;
}
UINT8 code = (msg == NULL) ? INVAILD_ID : (UINT8)msg->code;
LOS_Trace(LOS_TRACE_IPC, srcTid, srcPid, dstTid, dstPid, msgType, code, operation, ipcStatus);
}
#endif
LITE_OS_SEC_TEXT_INIT UINT32 OsLiteIpcInit(VOID)
{
UINT32 ret, i;
@@ -162,12 +117,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsLiteIpcInit(VOID)
for (i = 0; i < LOSCFG_BASE_CORE_PROCESS_LIMIT; i++) {
LOS_ListInit(&(g_ipcUsedNodelist[i]));
}
#ifdef LOSCFG_KERNEL_TRACE
ret = LOS_TraceReg(LOS_TRACE_IPC, OsIpcTrace, LOS_TRACE_IPC_NAME, LOS_TRACE_ENABLE);
if (ret != LOS_OK) {
PRINT_ERR("liteipc LOS_TraceReg failed:%d\n", ret);
}
#endif
return ret;
}
@@ -941,9 +891,14 @@ LITE_OS_SEC_TEXT STATIC UINT32 CheckPara(IpcContent *content, UINT32 *dstTid)
}
#if (USE_TIMESTAMP == YES)
if (now > msg->timestamp + LITEIPC_TIMEOUT_NS) {
#ifdef LOSCFG_KERNEL_TRACE
IpcTrace(msg, WRITE_DROP, 0, msg->type);
#ifdef LOSCFG_KERNEL_HOOK
ret = GetTid(msg->target.handle, dstTid);
if (ret != LOS_OK) {
*dstTid = INVAILD_ID;
}
#endif
OsHookCall(LOS_HOOK_TYPE_IPC_WRITE_DROP, msg, *dstTid,
(*dstTid == INVAILD_ID) ? INVAILD_ID : OS_TCB_FROM_TID(*dstTid)->processID, 0);
PRINT_ERR("A timeout reply, request timestamp:%lld, now:%lld\n", msg->timestamp, now);
return -ETIME;
}
@@ -999,9 +954,7 @@ LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcWrite(IpcContent *content)
SCHEDULER_LOCK(intSave);
LosTaskCB *tcb = OS_TCB_FROM_TID(dstTid);
LOS_ListTailInsert(&(tcb->msgListHead), &(buf->listNode));
#ifdef LOSCFG_KERNEL_TRACE
IpcTrace(&buf->msg, WRITE, tcb->ipcStatus, buf->msg.type);
#endif
OsHookCall(LOS_HOOK_TYPE_IPC_WRITE, &buf->msg, dstTid, tcb->processID, tcb->ipcStatus);
if (tcb->ipcStatus & IPC_THREAD_STATUS_PEND) {
tcb->ipcStatus &= ~IPC_THREAD_STATUS_PEND;
OsTaskWakeClearPendMask(tcb);
@@ -1059,15 +1012,11 @@ LITE_OS_SEC_TEXT STATIC UINT32 CheckRecievedMsg(IpcListNode *node, IpcContent *c
ret = -EINVAL;
}
if (ret != LOS_OK) {
#ifdef LOSCFG_KERNEL_TRACE
IpcTrace(&node->msg, READ_DROP, tcb->ipcStatus, node->msg.type);
#endif
OsHookCall(LOS_HOOK_TYPE_IPC_READ_DROP, &node->msg, tcb->ipcStatus);
(VOID)HandleSpecialObjects(LOS_CurTaskIDGet(), node, TRUE);
(VOID)LiteIpcNodeFree(LOS_GetCurrProcessID(), (VOID *)node);
} else {
#ifdef LOSCFG_KERNEL_TRACE
IpcTrace(&node->msg, READ, tcb->ipcStatus, node->msg.type);
#endif
OsHookCall(LOS_HOOK_TYPE_IPC_READ, &node->msg, tcb->ipcStatus);
}
return ret;
}
@@ -1087,24 +1036,18 @@ LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcRead(IpcContent *content)
do {
SCHEDULER_LOCK(intSave);
if (LOS_ListEmpty(listHead)) {
#ifdef LOSCFG_KERNEL_TRACE
IpcTrace(NULL, TRY_READ, tcb->ipcStatus, syncFlag ? MT_REPLY : MT_REQUEST);
#endif
OsHookCall(LOS_HOOK_TYPE_IPC_TRY_READ, syncFlag ? MT_REPLY : MT_REQUEST, tcb->ipcStatus);
tcb->ipcStatus |= IPC_THREAD_STATUS_PEND;
OsTaskWaitSetPendMask(OS_TASK_WAIT_LITEIPC, OS_INVALID_VALUE, timeout);
ret = OsSchedTaskWait(&g_ipcPendlist, timeout, TRUE);
if (ret == LOS_ERRNO_TSK_TIMEOUT) {
#ifdef LOSCFG_KERNEL_TRACE
IpcTrace(NULL, READ_TIMEOUT, tcb->ipcStatus, syncFlag ? MT_REPLY : MT_REQUEST);
#endif
OsHookCall(LOS_HOOK_TYPE_IPC_READ_TIMEOUT, syncFlag ? MT_REPLY : MT_REQUEST, tcb->ipcStatus);
SCHEDULER_UNLOCK(intSave);
return -ETIME;
}
if (OsTaskIsKilled(tcb)) {
#if (LOSCFG_KERNEL_TRACE == YES)
IpcTrace(NULL, KILL, tcb->ipcStatus, syncFlag ? MT_REPLY : MT_REQUEST);
#endif
OsHookCall(LOS_HOOK_TYPE_IPC_KILL, syncFlag ? MT_REPLY : MT_REQUEST, tcb->ipcStatus);
SCHEDULER_UNLOCK(intSave);
return -ERFKILL;
}