diff --git a/platform/Kconfig b/platform/Kconfig index e65e839..5047d4a 100644 --- a/platform/Kconfig +++ b/platform/Kconfig @@ -107,3 +107,9 @@ config DRIVERS_HDF_PLATFORM_ADC help Answer Y to enable HDF platform adc driver. +config DRIVERS_HDF_PLATFORM_TRACE + bool "Enable HDF platform trace driver" + default n + depends on DRIVERS_HDF_PLATFORM + help + Answer Y to enable HDF platform trace driver. diff --git a/platform/fwk/Makefile b/platform/fwk/Makefile index 26c9c63..281f87f 100644 --- a/platform/fwk/Makefile +++ b/platform/fwk/Makefile @@ -21,4 +21,9 @@ obj-y += $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/fwk/platform_common.o \ $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/fwk/platform_queue.o \ $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/fwk/platform_dumper.o +ifeq ($(CONFIG_DRIVERS_HDF_PLATFORM_TRACE), y) +obj-y += $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/fwk/platform_trace_transfer.o \ + ./platform_trace.o +endif + obj-y += ./plat_common.o diff --git a/platform/fwk/platform_trace.c b/platform/fwk/platform_trace.c new file mode 100644 index 0000000..64a9243 --- /dev/null +++ b/platform/fwk/platform_trace.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include "platform_trace.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "osal_file.h" +#include "osal_mem.h" +#include "securec.h" +#include "stdarg.h" +#include +#include + +#define CREATE_TRACE_POINTS +#include + +#define PLATFORM_TRACE_MSG_MAX_LEN 512 +void PlatformTraceAddMsg(const char *module, const char *moduleFun, const char *fmt, ...) +{ + int length; + va_list argList; + char messages[PLATFORM_TRACE_MSG_MAX_LEN + 1] = {'\0'}; + if ((module == NULL) || (moduleFun == NULL)) { + HDF_LOGE("PlatformTraceAddMsg params illegal", module, moduleFun); + return; + } + + length = snprintf_s(messages, PLATFORM_TRACE_MSG_MAX_LEN + 1, PLATFORM_TRACE_MSG_MAX_LEN, + "module:%s function:%s params: ", module, moduleFun); + if (length < 0) { + HDF_LOGE("PlatformTraceAddMsg[%s][%s] generate messages fail[%d]!", module, moduleFun, length); + return; + } + + va_start(argList, fmt); + length = vsprintf_s(messages + length - 1, PLATFORM_TRACE_MSG_MAX_LEN, fmt, argList); + va_end(argList); + if (length < 0) { + HDF_LOGE("PlatformTraceAddMsg[%s][%s] generate messages fail[%d]!", module, moduleFun, length); + return; + } + + trace_platfrom_trace_record_messages(messages); +} + +void PlatformTraceAddUintMsg(int module, int moduleFun, uint infos[], uint8_t size) +{ + int ret; + int i; + char messages[PLATFORM_TRACE_MSG_MAX_LEN + 1] = {0}; + const char *moduleMean = PlatformTraceModuleExplainGet(module); + const char *moduleFunMean = PlatformTraceFunExplainGet(moduleFun); + if ((moduleMean == NULL) || (moduleFunMean == NULL)) { + HDF_LOGE("PlatformTraceAddUintMsg module[%d, %d] info illegal", module, moduleFun); + return; + } + + if ((size <= 0) || (size > PLATFORM_TRACE_UINT_PARAM_SIZE_MAX)) { + HDF_LOGE("PlatformTraceAddUintMsg %hhu size illegal", size); + return; + } + if ((module < PLATFORM_TRACE_MODULE_I2S) || (module >= PLATFORM_TRACE_MODULE_MAX)) { + HDF_LOGE("PlatformTraceAddUintMsg %d module illegal", module); + return; + } + if ((moduleFun < PLATFORM_TRACE_MODULE_I2S_FUN) || (moduleFun >= PLATFORM_TRACE_MODULE_MAX_FUN)) { + HDF_LOGE("PlatformTraceAddUintMsg %d moduleFun illegal", moduleFun); + return; + } + + ret = snprintf_s(messages, PLATFORM_TRACE_MSG_MAX_LEN + 1, PLATFORM_TRACE_MSG_MAX_LEN, + "module:%s function:%s params:", moduleMean, moduleFunMean); + if (ret < 0) { + HDF_LOGE("PlatformTraceAddUintMsg[%s][%s] generate messages fail[%d]!", moduleMean, moduleFunMean, ret); + return; + } + for (i = 0; i < size; i++) { + snprintf_s(messages + strlen(messages), PLATFORM_TRACE_MSG_MAX_LEN + 1 - strlen(messages), + PLATFORM_TRACE_MSG_MAX_LEN - strlen(messages), + "%d, ", infos[i]); + if ((ret < 0) || (strlen(messages) >= PLATFORM_TRACE_MSG_MAX_LEN)) { + HDF_LOGE("PlatformTraceAddUintMsg[%s][%s] generate messages fail[%d][%d]!", moduleMean, moduleFunMean, ret, strlen(messages)); + return; + } + } + + trace_platfrom_trace_record_messages(messages); + return; +} + +static bool TraceIsOpen() +{ +#ifndef CONFIG_TRACING + return false; +#else + return true; +#endif +} + +static ssize_t TraceFileWrite(OsalFile *file, const void *string, uint32_t length) +{ + ssize_t ret; + loff_t pos; + mm_segment_t org_fs; + struct file *fp = NULL; + + if (file == NULL || IS_ERR_OR_NULL(file->realFile) || string == NULL) { + HDF_LOGE("%s invalid param", __func__); + return HDF_ERR_INVALID_PARAM; + } + fp = (struct file *)file->realFile; + pos = fp->f_pos; + org_fs = get_fs(); + set_fs(KERNEL_DS); + + ret = vfs_write(fp, string, length, &pos); + set_fs(org_fs); + if (ret < 0) { + HDF_LOGE("%s write file length %d fail %d", __func__, length, ret); + return HDF_FAILURE; + } + + return ret; +} + +static ssize_t TraceFileRead(OsalFile *file, void *buf, uint32_t length) +{ + ssize_t ret; + mm_segment_t org_fs; + loff_t pos; + struct file *fp = NULL; + + if (file == NULL || IS_ERR_OR_NULL(file->realFile) || buf == NULL) { + HDF_LOGE("%s invalid param", __func__); + return HDF_ERR_INVALID_PARAM; + } + fp = (struct file *)file->realFile; + org_fs = get_fs(); + set_fs(KERNEL_DS); + pos = fp->f_pos; + + ret = vfs_read(fp, buf, length, &pos); + set_fs(org_fs); + if (ret < 0) { + HDF_LOGE("%s read file length %d fail %d", __func__, length, ret); + return HDF_FAILURE; + } + + return ret; +} + +#define TRACE_EVENT_ENABLE_PATH "/sys/kernel/debug/tracing/events/platform_trace_event/enable" +static int32_t TraceEventFileWrite(const char *enable) +{ + int32_t ret; + OsalFile file; + ret = OsalFileOpen(&file, TRACE_EVENT_ENABLE_PATH, OSAL_O_RDWR, OSAL_S_IWRITE); + if (ret < 0) { + HDF_LOGE("%s %d open err:%d %s", __func__, __LINE__, ret, TRACE_EVENT_ENABLE_PATH); + return ret; + } + + ret = TraceFileWrite(&file, enable, 1); + if (ret < 0) { + HDF_LOGE("%s %d write err:%d %s", __func__, __LINE__, ret, TRACE_EVENT_ENABLE_PATH); + OsalFileClose(&file); + return ret; + } + + OsalFileClose(&file); + return HDF_SUCCESS; +} + +int32_t PlatformTraceStart(void) +{ + if (!TraceIsOpen()) { + return HDF_SUCCESS; + } + TraceEventFileWrite("1"); + return HDF_SUCCESS; +} + +int32_t PlatformTraceStop(void) +{ + if (!TraceIsOpen()) { + return HDF_SUCCESS; + } + TraceEventFileWrite("0"); + return HDF_SUCCESS; +} + +#define TRACE_EVENT_READ_PATH "/sys/kernel/debug/tracing/trace" +#define TRACE_EVENT_READ_MATCH "platfrom_trace_record_messages" +#define TRACE_INFO_DUMPER_LEN 512 +#define TRACE_INFO_DUMPER_FILE_MAX_LEN 102400 +void PlatformTraceInfoDump(void) +{ + int32_t ret; + char buf[TRACE_INFO_DUMPER_LEN]; + OsalFile file; + int32_t len = 0; + off_t off; + if (!TraceIsOpen()) { + return; + } + ret = OsalFileOpen(&file, TRACE_EVENT_READ_PATH, OSAL_O_RDWR, OSAL_S_IREAD); + if (ret < 0) { + HDF_LOGE("PlatformTraceInfoDump open %s err:%d", TRACE_EVENT_READ_PATH, ret); + return; + } + + do { + if (memset_s(buf, TRACE_INFO_DUMPER_LEN, 0, TRACE_INFO_DUMPER_LEN) != EOK) { + break; + } + ret = TraceFileRead(&file, buf, TRACE_INFO_DUMPER_LEN - 1); + if (ret > 0) { + len += ret; + off = OsalFileLseek(&file, len, 0); + printk("%s", buf); + } + if ((len >= TRACE_INFO_DUMPER_FILE_MAX_LEN) || (off < 0)) { + HDF_LOGE("PlatformTraceInfoDump trace info too big[%d] or lseek error[%ld]", len, off); + break; + } + } while (ret > 0); + + OsalFileClose(&file); +} + +void PlatformTraceReset(void) +{ + return; +} diff --git a/test/Makefile b/test/Makefile index 9142ab8..dfc9ad1 100644 --- a/test/Makefile +++ b/test/Makefile @@ -33,6 +33,10 @@ obj-$(CONFIG_DRIVERS_HDF_PLATFORM) += $(HDF_FRAMWORK_TEST_ROOT)/platform/common/ $(HDF_FRAMWORK_TEST_ROOT)/platform/common/platform_dumper_test.o \ $(HDF_FRAMWORK_TEST_ROOT)/platform/entry/hdf_platform_core_entry_test.o +ifeq ($(CONFIG_DRIVERS_HDF_PLATFORM_TRACE), y) +obj-$(CONFIG_DRIVERS_HDF_PLATFORM) += $(HDF_FRAMWORK_TEST_ROOT)/platform/common/platform_trace_test.o +endif + obj-$(CONFIG_DRIVERS_HDF_PLATFORM_GPIO) += $(HDF_FRAMWORK_TEST_ROOT)/platform/common/gpio_test.o \ $(HDF_FRAMWORK_TEST_ROOT)/platform/common/gpio_driver_test.o \ $(HDF_FRAMWORK_TEST_ROOT)/platform/entry/hdf_gpio_entry_test.o