Merge branch 'master' of gitee.com:openharmony/kernel_linux_common_modules into local_common

Signed-off-by: caobaolong <caobaolong5@huawei.com>
This commit is contained in:
caobaolong
2023-10-19 03:30:22 +00:00
committed by Gitee
15 changed files with 573 additions and 2 deletions
+2 -2
View File
@@ -256,8 +256,8 @@ function nip_dissector(tvb, pinfo, treeitem)
offset = offset + 1
nd_icmp_tree:add(_code, tvb(offset, 1))
offset = offset + 1
nd_icmp_tree:add(_checksum, tvb(offset, 1))
offset = offset + 1
nd_icmp_tree:add(_checksum, tvb(offset, 2))
offset = offset + 2
if type == 1 then
local first_addr = tvb(offset, 1):uint()
local addr_len = get_nip_addr_len (first_addr)
+6
View File
@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
config UNIFIED_COLLECTION
def_bool $(success,$(srctree)/scripts/ohos-check-dir.sh $(srctree)/drivers/staging/ucollection)
tristate "Enable unified collection"
help
unified collection
+3
View File
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_UNIFIED_COLLECTION) += ucollection_process_cpu.o
obj-$(CONFIG_UNIFIED_COLLECTION) += unified_collection_driver.o
+32
View File
@@ -0,0 +1,32 @@
## 背景
当前系统需要获取进程的CPU维测数据,支持开发者性能问题分析,通过遍例所有进程的结点虽然可以获取所有进程的CPU使用率,但是该方法性能相对较差,为了提升获取效率,因此开僻了内核的设备结点,通过结点可能快速获取CPU的数据。
## ucollection(unified collection)模块
通过ioctl的方式向设备结点/dev/uncollection发送命令,内核根据不同的命令做不同的处理,返回相应的维测数据。
![framework](figures/collector_framework.png)
## 目录
统一采集设备的主要代码目录结构如下:
```
# 代码路径 /kernel/linux/common_modules/xpm
├── apply_ucollection.sh # XPM 头文件
├── figures # ReadMe 内嵌图例
├── Konfig
├── Makefile
├── README_zh.md
├── ucollection_process_cpu.c # 获取进程CPU数据
├── ucollection_process_cpu.h
├── unified_collection_data.h
├── unified_collection_driver.c # 注册/dev/ucollection设备
```
## 相关仓
[内核子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E5%86%85%E6%A0%B8%E5%AD%90%E7%B3%BB%E7%BB%9F.md)
[kernel_linux_5.10](https://gitee.com/openharmony/kernel_linux_5.10)
[kernel_linux_config](https://gitee.com/openharmony/kernel_linux_config)
[kernel_linux_build](https://gitee.com/openharmony/kernel_linux_build)
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2023 Huawei Device Co., Ltd.
#
# Description: Create a symbolic link for Unified Collection Driver in Linux 5.10
#
set -e
OHOS_SOURCE_ROOT=$1
KERNEL_BUILD_ROOT=$2
PRODUCT_NAME=$3
KERNEL_VERSION=$4
UNIFIED_COLLECTION_SOURCE_ROOT=$OHOS_SOURCE_ROOT/kernel/linux/common_modules/ucollection
function main()
{
pushd .
echo "create link $KERNEL_BUILD_ROOT/drivers/staging/ucollection/"
if [ ! -d "$KERNEL_BUILD_ROOT/drivers/staging/ucollection" ]; then
mkdir $KERNEL_BUILD_ROOT/drivers/staging/ucollection
fi
cd $KERNEL_BUILD_ROOT/drivers/staging/ucollection/
ln -s -f $(realpath --relative-to=$KERNEL_BUILD_ROOT/drivers/staging/ucollection/ $UNIFIED_COLLECTION_SOURCE_ROOT)/* ./
popd
}
main
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

+194
View File
@@ -0,0 +1,194 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include "ucollection_process_cpu.h"
#include <asm/div64.h>
#ifdef CONFIG_CPU_FREQ_TIMES
#include <linux/cpufreq_times.h>
#endif // CONFIG_CPU_FREQ_TIMES
#include <linux/sched/stat.h>
#include <linux/version.h>
#include <linux/uaccess.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
#include <linux/sched.h>
#include <linux/sched/cputime.h>
#include <linux/sched/signal.h>
#endif // LINUX_VERSION_CODE
#ifdef CONFIG_SMT_MODE_GOV
#include <platform_include/cee/linux/time_in_state.h>
#endif // CONFIG_SMT_MODE_GOV
#include "unified_collection_data.h"
#define NS_TO_MS 1000000
static char dmips_values[DMIPS_NUM];
unsigned long long __attribute__((weak)) get_proc_cpu_load(struct task_struct *task, char dmips[],
unsigned int dmips_num)
{
return 0;
}
static int get_cpu_num(void)
{
int core_num = 0;
int i = 0;
for_each_possible_cpu(i)
core_num++;
return core_num;
}
static unsigned long long get_process_load_cputime(struct task_struct *task)
{
unsigned long long proc_load_cputime = 0;
proc_load_cputime = get_proc_cpu_load(task, dmips_values, DMIPS_NUM);
return proc_load_cputime;
}
static void get_process_usage_cputime(struct task_struct *task, unsigned long long *ut, unsigned long long *st)
{
unsigned long long utime, stime;
thread_group_cputime_adjusted(task, &utime, &stime);
utime = utime + task->signal->cutime;
stime = stime + task->signal->cstime;
do_div(utime, NS_TO_MS);
do_div(stime, NS_TO_MS);
*ut = utime;
*st = stime;
}
static void get_process_load(struct task_struct *task, int cpu_num, int cur_count,
struct ucollection_process_cpu_entry __user *entry)
{
struct ucollection_process_cpu_item proc_cpu_entry;
memset(&proc_cpu_entry, 0, sizeof(struct ucollection_process_cpu_item));
proc_cpu_entry.pid = task->pid;
proc_cpu_entry.cpu_load_time = get_process_load_cputime(task);
get_process_usage_cputime(task, &proc_cpu_entry.cpu_usage_utime, &proc_cpu_entry.cpu_usage_stime);
(void)copy_to_user(&entry->datas[cur_count], &proc_cpu_entry, sizeof(struct ucollection_process_cpu_item));
}
static long ioctrl_collect_process_cpu(void __user *argp)
{
int cpu_num = 0;
struct task_struct *task = NULL;
struct ucollection_process_cpu_entry kentry;
struct ucollection_process_cpu_entry __user *entry = argp;
if (entry == NULL) {
pr_err("cpu entry is null");
return -EINVAL;
}
memset(&kentry, 0, sizeof(struct ucollection_process_cpu_entry));
(void)copy_from_user(&kentry, entry, sizeof(struct ucollection_process_cpu_entry));
cpu_num = get_cpu_num();
rcu_read_lock();
task = &init_task;
for_each_process(task) {
if (task->pid != task->tgid)
continue;
if (kentry.cur_count >= kentry.total_count) {
pr_err("process over total count");
break;
}
get_process_load(task, cpu_num, kentry.cur_count, entry);
kentry.cur_count++;
}
put_user(kentry.cur_count, &entry->cur_count);
rcu_read_unlock();
return 0;
}
static bool is_pid_alive(int pid)
{
struct task_struct *task = NULL;
task = pid_task(find_vpid(pid), PIDTYPE_PID);
if (task == NULL)
return false;
return pid_alive(task);
}
static long ioctrl_collect_the_process_cpu(void __user *argp)
{
int cpu_num = 0;
struct task_struct *task = NULL;
struct ucollection_process_cpu_entry kentry;
struct ucollection_process_cpu_entry __user *entry = argp;
if (entry == NULL) {
pr_err("cpu entry is null");
return -EINVAL;
}
memset(&kentry, 0, sizeof(struct ucollection_process_cpu_entry));
(void)copy_from_user(&kentry, entry, sizeof(struct ucollection_process_cpu_entry));
if (kentry.cur_count >= kentry.total_count) {
pr_err("current count over total count");
return -EINVAL;
}
rcu_read_lock();
if (!is_pid_alive(kentry.filter.pid)) {
pr_err("pid=%d is not alive", kentry.filter.pid);
rcu_read_unlock();
return -EINVAL;
}
task = find_task_by_vpid(kentry.filter.pid);
if (task == NULL) {
pr_err("can not get pid=%d", task->pid);
rcu_read_unlock();
return -EINVAL;
}
cpu_num = get_cpu_num();
get_process_load(task, cpu_num, kentry.cur_count, entry);
kentry.cur_count++;
put_user(kentry.cur_count, &entry->cur_count);
rcu_read_unlock();
return 0;
}
static long ioctrl_set_cpu_dmips(void __user *argp)
{
int i;
struct ucollection_cpu_dmips kentry;
struct ucollection_cpu_dmips __user *entry = argp;
memset(&kentry, 0, sizeof(struct ucollection_cpu_dmips));
(void)copy_from_user(&kentry, entry, sizeof(struct ucollection_cpu_dmips));
pr_info("set dimps %d cpus\n", kentry.total_count);
for (i = 0; i < DMIPS_NUM; i++) {
if (i >= kentry.total_count)
break;
get_user(dmips_values[i], &entry->dmips[i]);
pr_info("set dimps cpu[%d]=%d\n", i, dmips_values[i]);
}
return 0;
}
long unified_collection_collect_process_cpu(unsigned int cmd, void __user *argp)
{
long ret = 0;
switch(cmd) {
case IOCTRL_COLLECT_ALL_PROC_CPU:
ret = ioctrl_collect_process_cpu(argp);
break;
case IOCTRL_COLLECT_THE_PROC_CPU:
ret = ioctrl_collect_the_process_cpu(argp);
break;
case IOCTRL_SET_CPU_DMIPS:
ret = ioctrl_set_cpu_dmips(argp);
break;
default:
pr_err("handle ioctrl cmd %u, _IOC_TYPE(cmd)=%d", cmd, _IOC_TYPE(cmd));
ret = 0;
}
return ret;
}
+9
View File
@@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#ifndef __UCOLLECTION_PROCESS_CPU__
#define __UCOLLECTION_PROCESS_CPU__
long unified_collection_collect_process_cpu(unsigned int cmd, void __user *argp);
#endif // __UCOLLECTION_PROCESS_CPU__
+47
View File
@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#ifndef __UNIFIED_COLLECTION_DATA__
#define __UNIFIED_COLLECTION_DATA__
#include <linux/ioctl.h>
// kernel struct, modify at the same time
struct ucollection_process_cpu_item {
int pid;
unsigned long long cpu_usage_utime;
unsigned long long cpu_usage_stime;
unsigned long long cpu_load_time;
};
struct ucollection_process_filter {
int uid;
int pid;
int tid;
};
struct ucollection_process_cpu_entry {
int magic;
int total_count;
int cur_count;
struct ucollection_process_filter filter;
struct ucollection_process_cpu_item datas[];
};
struct ucollection_cpu_dmips {
int magic;
int total_count;
char dmips[];
};
#define IOCTRL_COLLECT_ALL_PROC_CPU_MAGIC 1
#define IOCTRL_COLLECT_THE_PROC_CPU_MAGIC 1
#define IOCTRL_SET_CPU_DMIPS_MAGIC 1
#define DMIPS_NUM 128
#define IOCTRL_COLLECT_CPU_BASE 0
#define IOCTRL_COLLECT_ALL_PROC_CPU _IOR(IOCTRL_COLLECT_CPU_BASE, 1, struct ucollection_process_cpu_entry)
#define IOCTRL_COLLECT_THE_PROC_CPU _IOR(IOCTRL_COLLECT_CPU_BASE, 2, struct ucollection_process_cpu_entry)
#define IOCTRL_SET_CPU_DMIPS _IOW(IOCTRL_COLLECT_CPU_BASE, 3, struct ucollection_cpu_dmips)
#endif // __UNIFIED_COLLECTION_DATA__
+90
View File
@@ -0,0 +1,90 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
#endif // CONFIG_COMPAT
#include "ucollection_process_cpu.h"
static long (*unified_collection_ioctl_cb[])(unsigned int cmd, void __user *argp) = {
unified_collection_collect_process_cpu /* IOCTRL_COLLECT_CPU */
};
static long unified_collection_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
void __user *argp = u64_to_user_ptr(arg);
const char *comm = NULL;
if ((_IOC_TYPE(cmd) >= ARRAY_SIZE(unified_collection_ioctl_cb)) ||
(unified_collection_ioctl_cb[_IOC_TYPE(cmd)] == NULL)) {
pr_err("invalid ioctrl cmd %u, _IOC_TYPE(cmd)=%d", cmd, _IOC_TYPE(cmd));
return -EINVAL;
}
return unified_collection_ioctl_cb[_IOC_TYPE(cmd)](cmd, argp);
}
#ifdef CONFIG_COMPAT
static long unified_collection_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
return unified_collection_ioctl(filp, cmd, (unsigned long) compat_ptr(arg));
}
#endif // CONFIG_COMPAT
static int unified_collection_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int unified_collection_release(struct inode *inode, struct file *filp)
{
return 0;
}
static const struct file_operations unified_collection_device_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = unified_collection_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = unified_collection_compat_ioctl,
#endif // CONFIG_COMPAT
.open = unified_collection_open,
.release = unified_collection_release,
};
static struct miscdevice unified_collection_device = {
.name = "ucollection",
.fops = &unified_collection_device_fops,
.minor = MISC_DYNAMIC_MINOR,
};
static int __init unified_collection_init(void)
{
int ret = misc_register(&unified_collection_device);
if (ret) {
pr_err("failed to register unified collection device");
return ret;
}
pr_info("register unified collection device successful");
return 0;
}
static void __exit unified_collection_exit(void)
{
pr_info("deregister unified collection device successful");
misc_deregister(&unified_collection_device);
}
module_init(unified_collection_init);
module_exit(unified_collection_exit);
MODULE_AUTHOR("OHOS");
MODULE_DESCRIPTION("Unified Collection Driver");
MODULE_LICENSE("GPL");
+9
View File
@@ -15,6 +15,15 @@ config SECURITY_XPM
mmap and etc. It can control not to execute an illegal signature
process.
config DSMM_DEVELOPER_ENABLE
bool "Enables device developer mode feature"
depends on SECURITY_XPM
default n
help
This option should only be enabled for the device support developer
mode feature. But whether or not developer mode is enabled on the
device ultimately depends on the developer_mode valude in cmdline.
config SECURITY_XPM_DEBUG
bool "Enables excutable permission manager debug mode"
depends on SECURITY_XPM
+1
View File
@@ -10,6 +10,7 @@ obj-$(CONFIG_SECURITY_XPM) += \
core/xpm_misc.o \
core/xpm_hck.o \
core/xpm_report.o \
core/dsmm_developer.o \
validator/elf_code_segment_info.o \
validator/exec_signature_info.o
+112
View File
@@ -0,0 +1,112 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/proc_fs.h>
#include "dsmm_developer.h"
#include "xpm_log.h"
#define DSMM_DIR "dsmm"
#define DSMM_DEVELOPER_FILE "developer"
#define DSMM_DEVELOPER_PARAM_NAME "const.security.developermode.state"
static struct proc_dir_entry *g_dsmm_dir;
static const char *g_developer_status[BUILD_VARIANT_MAX][DEVELOPER_PROC_STATUS_MAX] = {
{ DEVELOPER_STATUS_OFF, DEVELOPER_STATUS_ON, DEVELOPER_STATUS_OFF },
{ DEVELOPER_STATUS_ON, DEVELOPER_STATUS_ON, DEVELOPER_STATUS_OFF },
};
static int get_developer_status(uint32_t *status)
{
if (!strstr(saved_command_line, "developer_mode=")) {
*status = DEVELOPER_PROC_STATUS_NA;
} else if (strstr(saved_command_line, "developer_mode=1")) {
*status = DEVELOPER_PROC_STATUS_ON;
} else if (strstr(saved_command_line, "developer_mode=0")) {
*status = DEVELOPER_PROC_STATUS_OFF;
} else {
xpm_log_error("invalid developer_mode value in cmdline");
return -EINVAL;
}
return 0;
}
static int get_build_variant(uint32_t *variant)
{
if (strstr(saved_command_line, "buildvariant=user")) {
*variant = BUILD_VARIANT_USER;
} else if (strstr(saved_command_line, "buildvariant=eng")) {
*variant = BUILD_VARIANT_ENG;
} else {
xpm_log_error("invalid buildvariant value in cmdline");
return -EINVAL;
}
return 0;
}
const char *developer_mode_state(void)
{
uint32_t variant, status;
#ifdef CONFIG_DSMM_DEVELOPER_ENABLE
if (get_build_variant(&variant) || get_developer_status(&status)) {
xpm_log_error("get build variant or developer status failed");
return NULL;
}
return g_developer_status[variant][status];
#else
return DEVELOPER_STATUS_ON;
#endif
}
#define PROC_DEVELOPER_LEN 50
static ssize_t dsmm_read_developer_proc(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
size_t len;
char proc_developer[PROC_DEVELOPER_LEN] = {0};
const char *developer_state = developer_mode_state();
if (!developer_state) {
xpm_log_error("developer mode state invalid");
return 0;
}
len = snprintf(proc_developer, PROC_DEVELOPER_LEN - 1,
DSMM_DEVELOPER_PARAM_NAME"=%s", developer_state);
return simple_read_from_buffer(buf, count, pos, proc_developer, len);
}
static const struct proc_ops dsmm_proc_fops_developer = {
.proc_read = dsmm_read_developer_proc,
};
void dsmm_developer_proc_create(void)
{
g_dsmm_dir = proc_mkdir(DSMM_DIR, NULL);
if (!g_dsmm_dir) {
xpm_log_error("[%s] proc dir create failed", DSMM_DIR);
return;
}
if(!proc_create(DSMM_DEVELOPER_FILE, S_IRUGO, g_dsmm_dir,
&dsmm_proc_fops_developer)) {
xpm_log_error("[%s] proc file create failed",
DSMM_DEVELOPER_FILE);
}
}
void dsmm_developer_proc_clean(void)
{
if (!g_dsmm_dir)
return;
remove_proc_entry(DSMM_DEVELOPER_FILE, g_dsmm_dir);
remove_proc_entry(DSMM_DIR, NULL);
}
+6
View File
@@ -12,6 +12,7 @@
#include "xpm_misc.h"
#include "xpm_report.h"
#include "xpm_debugfs.h"
#include "dsmm_developer.h"
static int __init xpm_module_init(void)
{
@@ -35,6 +36,8 @@ static int __init xpm_module_init(void)
xpm_register_xpm_hooks();
xpm_register_hck_hooks();
dsmm_developer_proc_create();
xpm_log_info("xpm module init success");
return 0;
}
@@ -43,6 +46,9 @@ static void __exit xpm_module_exit(void)
{
xpm_deregister_misc_device();
xpm_debugfs_exit();
dsmm_developer_proc_clean();
xpm_log_info("xpm module exit success");
}
+31
View File
@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#ifndef DSMM_DEVELOPER_H
#define DSMM_DEVELOPER_H
#define DEVELOPER_STATUS_ON "true"
#define DEVELOPER_STATUS_OFF "false"
enum build_variant {
BUILD_VARIANT_USER = 0,
BUILD_VARIANT_ENG,
BUILD_VARIANT_MAX,
};
enum developer_proc_status {
DEVELOPER_PROC_STATUS_NA = 0,
DEVELOPER_PROC_STATUS_ON,
DEVELOPER_PROC_STATUS_OFF,
DEVELOPER_PROC_STATUS_MAX,
};
const char *developer_mode_state(void);
void dsmm_developer_proc_create(void);
void dsmm_developer_proc_clean(void);
#endif // DSMM_DEVELOPER_H