[PATCH v1 1/1] process: export symbols for fork/exit tracing functions
jim.tsai
Wei-chin.Tsai at mediatek.com
Mon Jun 12 08:15:41 PDT 2023
Export the tracing function "sched_process_fork" and
"sched_process_exit" for process statistics.
Change-Id: I67dcdcb26371cd7a495ff0b210361742b1a2088e
Signed-off-by: jim.tsai <Wei-chin.Tsai at mediatek.com>
---
drivers/misc/mediatek_mbraink/Kconfig | 7 +
drivers/misc/mediatek_mbraink/Makefile | 5 +
drivers/misc/mediatek_mbraink/mbraink_data.c | 417 ++++++++++++++++++
drivers/misc/mediatek_mbraink/mbraink_data.h | 67 +++
.../mbraink_ioctl_struct_define.h | 44 ++
drivers/misc/mediatek_mbraink/mbraink_main.c | 277 ++++++++++++
drivers/misc/mediatek_mbraink/mbraink_main.h | 32 ++
kernel/exit.c | 2 +
kernel/fork.c | 2 +
9 files changed, 853 insertions(+)
create mode 100644 drivers/misc/mediatek_mbraink/Kconfig
create mode 100644 drivers/misc/mediatek_mbraink/Makefile
create mode 100644 drivers/misc/mediatek_mbraink/mbraink_data.c
create mode 100644 drivers/misc/mediatek_mbraink/mbraink_data.h
create mode 100644 drivers/misc/mediatek_mbraink/mbraink_ioctl_struct_define.h
create mode 100644 drivers/misc/mediatek_mbraink/mbraink_main.c
create mode 100644 drivers/misc/mediatek_mbraink/mbraink_main.h
diff --git a/drivers/misc/mediatek_mbraink/Kconfig b/drivers/misc/mediatek_mbraink/Kconfig
new file mode 100644
index 000000000000..615c1043a866
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/Kconfig
@@ -0,0 +1,7 @@
+config MTK_MBRAINK
+ tristate "MTK MBRAINK support"
+ help
+ MBRAINK is a MediaTek in-house kernel module which can
+ communicate with android MBrain.
+ Set Y to enable this feature.
+ If unsure, Set N to stay with legancy feature.
diff --git a/drivers/misc/mediatek_mbraink/Makefile b/drivers/misc/mediatek_mbraink/Makefile
new file mode 100644
index 000000000000..8d75b41a8097
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/Makefile
@@ -0,0 +1,5 @@
+subdir-ccflags-y += -Wformat
+
+obj-${CONFIG_MTK_MBRAINK} += mtk_mbraink.o
+
+mtk_mbraink-objs += mbraink_data.o mbraink_main.o
diff --git a/drivers/misc/mediatek_mbraink/mbraink_data.c b/drivers/misc/mediatek_mbraink/mbraink_data.c
new file mode 100644
index 000000000000..5c793a8c262d
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_data.c
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/rtc.h>
+#include <linux/sched/clock.h>
+#include <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/cdev.h>
+#include <linux/proc_fs.h>
+#include <linux/sched/signal.h>
+#include <linux/pid_namespace.h>
+#include <linux/mm.h>
+#include <linux/sched/mm.h>
+#include <linux/sched/task.h>
+#include <linux/pagewalk.h>
+#include <linux/shmem_fs.h>
+#include <linux/pagemap.h>
+#include <linux/mempolicy.h>
+#include <linux/rmap.h>
+#include <linux/sched/cputime.h>
+#include <linux/math64.h>
+#include <linux/refcount.h>
+#include <linux/ctype.h>
+#include <linux/stddef.h>
+#include <linux/cred.h>
+#include <linux/spinlock.h>
+#include <linux/rtc.h>
+#include <linux/sched/clock.h>
+#include <trace/events/sched.h>
+#include <linux/mm_inline.h>
+
+#include "mbraink_data.h"
+
+/*spinlock for mbraink tracing pidlist*/
+static DEFINE_SPINLOCK(tracing_pidlist_lock);
+/*Please make sure that tracing pidlist is protected by spinlock*/
+struct mbraink_tracing_pidlist mbraink_tracing_pidlist_data[MAX_TRACE_NUM];
+
+#if IS_ENABLED(CONFIG_ANON_VMA_NAME)
+struct anon_vma_name *mbraink_anon_vma_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_file)
+ return NULL;
+
+ return vma->anon_name;
+}
+#else
+struct anon_vma_name *mbraink_anon_vma_name(struct vm_area_struct *vma)
+{
+ return NULL;
+}
+#endif
+
+void mbraink_map_vma(struct vm_area_struct *vma, unsigned long cur_pss,
+ unsigned long *native_heap, unsigned long *java_heap)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ const char *name = NULL;
+
+ if (vma->vm_file)
+ return;
+ /*
+ * Print the dentry name for named mappings, and a
+ * special [heap] marker for the heap:
+ */
+
+ if (vma->vm_ops && vma->vm_ops->name) {
+ name = vma->vm_ops->name(vma);
+ if (name) {
+ if (strncmp(name, "dev/ashmem/libc malloc", 23) == 0)
+ (*native_heap) += cur_pss;
+ return;
+ }
+ }
+
+ name = arch_vma_name(vma);
+ if (!name) {
+ struct anon_vma_name *anon_name;
+
+ if (!mm)
+ return;
+
+ if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
+ (*native_heap) += cur_pss;
+ return;
+ }
+
+ if (vma->vm_start <= vma->vm_mm->start_stack &&
+ vma->vm_end >= vma->vm_mm->start_stack)
+ return;
+
+ anon_name = mbraink_anon_vma_name(vma);
+ if (anon_name) {
+ if (strstr(anon_name->name, "scudo"))
+ (*native_heap) += cur_pss;
+ else if (strstr(anon_name->name, "libc_malloc"))
+ (*native_heap) += cur_pss;
+ else if (strstr(anon_name->name, "GWP-ASan"))
+ (*native_heap) += cur_pss;
+ else if (strstr(anon_name->name, "dalvik-alloc space"))
+ (*java_heap) += cur_pss;
+ else if (strstr(anon_name->name, "dalvik-main space"))
+ (*java_heap) += cur_pss;
+ else if (strstr(anon_name->name, "dalvik-large object space"))
+ (*java_heap) += cur_pss;
+ else if (strstr(anon_name->name, "dalvik-free list large object space"))
+ (*java_heap) += cur_pss;
+ else if (strstr(anon_name->name, "dalvik-non moving space"))
+ (*java_heap) += cur_pss;
+ else if (strstr(anon_name->name, "dalvik-zygote space"))
+ (*java_heap) += cur_pss;
+ }
+ }
+}
+
+void mbraink_get_process_memory_info(pid_t current_pid,
+ struct mbraink_process_memory_data *process_memory_buffer)
+{
+ struct task_struct *t = NULL;
+ struct mm_struct *mm = NULL;
+ struct vm_area_struct *vma = NULL;
+ struct mem_size_stats mss;
+ unsigned short pid_count = 0;
+ unsigned long pss, uss, rss, swap, cur_pss;
+ unsigned long java_heap = 0, native_heap = 0;
+ struct vma_iterator vmi;
+
+ memset(process_memory_buffer, 0, sizeof(struct mbraink_process_memory_data));
+ process_memory_buffer->pid = 0;
+
+ read_lock(&tasklist_lock);
+ for_each_process(t) {
+ if (t->pid <= current_pid)
+ continue;
+
+ mm = t->mm;
+ if (mm) {
+ java_heap = 0;
+ native_heap = 0;
+ pid_count = process_memory_buffer->pid_count;
+
+ process_memory_buffer->drv_data[pid_count].pid =
+ (unsigned short)(t->pid);
+ process_memory_buffer->pid =
+ (unsigned short)(t->pid);
+
+ memset(&mss, 0, sizeof(mss));
+ get_task_struct(t);
+ mmgrab(mm);
+ read_unlock(&tasklist_lock);
+ mmap_read_lock(mm);
+ vma_iter_init(&vmi, mm, 0);
+ for_each_vma(vmi, vma) {
+ cur_pss = (unsigned long)(mss.pss >> PSS_SHIFT);
+ smap_gather_stats(vma, &mss, 0);
+ cur_pss =
+ ((unsigned long)(mss.pss >> PSS_SHIFT)) - cur_pss;
+ cur_pss = cur_pss / 1024;
+ mbraink_map_vma(vma, cur_pss, &native_heap, &java_heap);
+ }
+ mmap_read_unlock(mm);
+ read_lock(&tasklist_lock);
+ mmdrop(mm);
+ put_task_struct(t);
+
+ pss = (unsigned long)(mss.pss >> PSS_SHIFT) / 1024;
+ uss = (mss.private_clean + mss.private_dirty) / 1024;
+ rss = (mss.resident) / 1024;
+ swap = (mss.swap) / 1024;
+
+ process_memory_buffer->drv_data[pid_count].pss = pss;
+ process_memory_buffer->drv_data[pid_count].uss = uss;
+ process_memory_buffer->drv_data[pid_count].rss = rss;
+ process_memory_buffer->drv_data[pid_count].swap = swap;
+ process_memory_buffer->drv_data[pid_count].java_heap =
+ java_heap;
+ process_memory_buffer->drv_data[pid_count].native_heap =
+ native_heap;
+ process_memory_buffer->pid_count++;
+
+ break;
+ }
+ }
+ read_unlock(&tasklist_lock);
+}
+
+/*****************************************************************
+ * Note: this function can only be used during tracing function
+ * This function is only used in tracing function so that there
+ * is no need for task t spinlock protection
+ *****************************************************************/
+static u64 mbraink_get_specific_process_jiffies(struct task_struct *t)
+{
+ u64 stime = 0, utime = 0, cutime = 0, cstime = 0;
+ u64 process_jiffies = 0;
+
+ if (t->pid == t->tgid) {
+ cutime = t->signal->cutime;
+ cstime = t->signal->cstime;
+ if (t->flags & PF_KTHREAD)
+ task_cputime_adjusted(t, &utime, &stime);
+ else
+ thread_group_cputime_adjusted(t, &utime, &stime);
+
+ process_jiffies = nsec_to_clock_t(utime) +
+ nsec_to_clock_t(stime) +
+ nsec_to_clock_t(cutime) +
+ nsec_to_clock_t(cstime);
+ } else {
+ task_cputime_adjusted(t, &utime, &stime);
+ process_jiffies = nsec_to_clock_t(utime) + nsec_to_clock_t(stime);
+ }
+
+ return process_jiffies;
+}
+
+/***************************************************************
+ * Note: this function can only be used during tracing function
+ * This function is only used in tracing function so that there
+ * is no need for task t spinlock protection
+ **************************************************************/
+static u16 mbraink_get_specific_process_uid(struct task_struct *t)
+{
+ const struct cred *cred = NULL;
+ u16 val = 0;
+
+ cred = get_task_cred(t);
+ val = cred->uid.val;
+ put_cred(cred);
+
+ return val;
+}
+
+static void mbraink_trace_sched_process_exit(void *data, struct task_struct *t)
+{
+ int i = 0;
+ struct timespec64 tv = { 0 };
+ unsigned long flags;
+
+ if (t->pid == t->tgid) {
+ spin_lock_irqsave(&tracing_pidlist_lock, flags);
+ for (i = 0; i < MAX_TRACE_NUM; i++) {
+ if (mbraink_tracing_pidlist_data[i].pid == (unsigned short)t->pid) {
+ ktime_get_real_ts64(&tv);
+ mbraink_tracing_pidlist_data[i].end =
+ (tv.tv_sec * 1000) + (tv.tv_nsec / 1000000);
+ mbraink_tracing_pidlist_data[i].jiffies =
+ mbraink_get_specific_process_jiffies(t);
+ mbraink_tracing_pidlist_data[i].dirty = true;
+
+ break;
+ }
+ }
+ if (i == MAX_TRACE_NUM) {
+ for (i = 0; i < MAX_TRACE_NUM; i++) {
+ if (mbraink_tracing_pidlist_data[i].pid == 0) {
+ mbraink_tracing_pidlist_data[i].pid =
+ (unsigned short)(t->pid);
+ mbraink_tracing_pidlist_data[i].tgid =
+ (unsigned short)(t->tgid);
+ mbraink_tracing_pidlist_data[i].uid =
+ mbraink_get_specific_process_uid(t);
+ mbraink_tracing_pidlist_data[i].priority =
+ t->prio - MAX_RT_PRIO;
+ memcpy(mbraink_tracing_pidlist_data[i].name,
+ t->comm, TASK_COMM_LEN);
+ ktime_get_real_ts64(&tv);
+ mbraink_tracing_pidlist_data[i].end =
+ (tv.tv_sec * 1000) + (tv.tv_nsec / 1000000);
+ mbraink_tracing_pidlist_data[i].jiffies =
+ mbraink_get_specific_process_jiffies(t);
+ mbraink_tracing_pidlist_data[i].dirty = true;
+
+ break;
+ }
+ }
+ if (i == MAX_TRACE_NUM) {
+ pr_info("%s pid=%u:%s.\n", __func__, t->pid, t->comm);
+ memset(mbraink_tracing_pidlist_data, 0,
+ sizeof(struct mbraink_tracing_pidlist) * MAX_TRACE_NUM);
+ }
+ }
+ spin_unlock_irqrestore(&tracing_pidlist_lock, flags);
+ }
+}
+
+static void mbraink_trace_sched_process_fork(void *data, struct task_struct *t,
+ struct task_struct *p)
+{
+ int i = 0;
+ struct timespec64 tv = { 0 };
+ unsigned long flags;
+
+ if (p->pid == p->tgid) {
+ spin_lock_irqsave(&tracing_pidlist_lock, flags);
+ for (i = 0; i < MAX_TRACE_NUM; i++) {
+ if (mbraink_tracing_pidlist_data[i].pid == 0) {
+ mbraink_tracing_pidlist_data[i].pid = (unsigned short)(p->pid);
+ mbraink_tracing_pidlist_data[i].tgid = (unsigned short)(p->tgid);
+ mbraink_tracing_pidlist_data[i].uid =
+ mbraink_get_specific_process_uid(p);
+ mbraink_tracing_pidlist_data[i].priority = p->prio - MAX_RT_PRIO;
+ memcpy(mbraink_tracing_pidlist_data[i].name,
+ p->comm, TASK_COMM_LEN);
+ ktime_get_real_ts64(&tv);
+ mbraink_tracing_pidlist_data[i].start =
+ (tv.tv_sec * 1000) + (tv.tv_nsec / 1000000);
+ mbraink_tracing_pidlist_data[i].dirty = true;
+ break;
+ }
+ }
+
+ if (i == MAX_TRACE_NUM) {
+ pr_info("%s child_pid=%u:%s.\n", __func__, p->pid, p->comm);
+ memset(mbraink_tracing_pidlist_data, 0,
+ sizeof(struct mbraink_tracing_pidlist) * MAX_TRACE_NUM);
+ }
+ spin_unlock_irqrestore(&tracing_pidlist_lock, flags);
+ }
+}
+
+int mbraink_process_tracer_init(void)
+{
+ int ret = 0;
+
+ memset(mbraink_tracing_pidlist_data, 0,
+ sizeof(struct mbraink_tracing_pidlist) * MAX_TRACE_NUM);
+
+ ret = register_trace_sched_process_fork(mbraink_trace_sched_process_fork, NULL);
+ if (ret) {
+ pr_notice("register_trace_sched_process_fork failed.\n");
+ goto register_trace_sched_process_fork;
+ }
+ ret = register_trace_sched_process_exit(mbraink_trace_sched_process_exit, NULL);
+ if (ret) {
+ pr_notice("register register_trace_sched_process_exit failed.\n");
+ goto register_trace_sched_process_exit;
+ }
+
+ return ret;
+
+register_trace_sched_process_exit:
+ unregister_trace_sched_process_fork(mbraink_trace_sched_process_fork, NULL);
+register_trace_sched_process_fork:
+ return ret;
+}
+
+void mbraink_process_tracer_exit(void)
+{
+ unregister_trace_sched_process_fork(mbraink_trace_sched_process_fork, NULL);
+ unregister_trace_sched_process_exit(mbraink_trace_sched_process_exit, NULL);
+}
+
+void mbraink_get_tracing_pid_info(unsigned short current_idx,
+ struct mbraink_tracing_pid_data *tracing_pid_buffer)
+{
+ int i = 0;
+ int ret = 0;
+ unsigned long flags;
+ unsigned short tracing_count = 0;
+
+ spin_lock_irqsave(&tracing_pidlist_lock, flags);
+
+ memset(tracing_pid_buffer, 0, sizeof(struct mbraink_tracing_pid_data));
+
+ for (i = current_idx; i < MAX_TRACE_NUM; i++) {
+ if (mbraink_tracing_pidlist_data[i].dirty == false) {
+ continue;
+ } else {
+ tracing_count = tracing_pid_buffer->tracing_count;
+ if (tracing_count < MAX_TRACE_PID_NUM) {
+ tracing_pid_buffer->drv_data[tracing_count].pid =
+ mbraink_tracing_pidlist_data[i].pid;
+ tracing_pid_buffer->drv_data[tracing_count].tgid =
+ mbraink_tracing_pidlist_data[i].tgid;
+ tracing_pid_buffer->drv_data[tracing_count].uid =
+ mbraink_tracing_pidlist_data[i].uid;
+ tracing_pid_buffer->drv_data[tracing_count].priority =
+ mbraink_tracing_pidlist_data[i].priority;
+ memcpy(tracing_pid_buffer->drv_data[tracing_count].name,
+ mbraink_tracing_pidlist_data[i].name, TASK_COMM_LEN);
+ tracing_pid_buffer->drv_data[tracing_count].start =
+ mbraink_tracing_pidlist_data[i].start;
+ tracing_pid_buffer->drv_data[tracing_count].end =
+ mbraink_tracing_pidlist_data[i].end;
+ tracing_pid_buffer->drv_data[tracing_count].jiffies =
+ mbraink_tracing_pidlist_data[i].jiffies;
+ tracing_pid_buffer->tracing_count++;
+ /*Deal with the end process record*/
+ if (mbraink_tracing_pidlist_data[i].end != 0) {
+ mbraink_tracing_pidlist_data[i].pid = 0;
+ mbraink_tracing_pidlist_data[i].tgid = 0;
+ mbraink_tracing_pidlist_data[i].uid = 0;
+ mbraink_tracing_pidlist_data[i].priority = 0;
+ memset(mbraink_tracing_pidlist_data[i].name,
+ 0, TASK_COMM_LEN);
+ mbraink_tracing_pidlist_data[i].start = 0;
+ mbraink_tracing_pidlist_data[i].end = 0;
+ mbraink_tracing_pidlist_data[i].jiffies = 0;
+ mbraink_tracing_pidlist_data[i].dirty = false;
+ } else {
+ mbraink_tracing_pidlist_data[i].dirty = false;
+ }
+ } else {
+ ret = -1;
+ tracing_pid_buffer->tracing_idx = i;
+ break;
+ }
+ }
+ }
+ pr_info("%s: current_idx = %u, count = %u\n",
+ __func__, tracing_pid_buffer->tracing_idx, tracing_pid_buffer->tracing_count);
+ spin_unlock_irqrestore(&tracing_pidlist_lock, flags);
+}
diff --git a/drivers/misc/mediatek_mbraink/mbraink_data.h b/drivers/misc/mediatek_mbraink/mbraink_data.h
new file mode 100644
index 000000000000..c10ec1083b79
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_data.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+#ifndef MBRAINK_DATA_H
+#define MBRAINK_DATA_H
+#include <linux/string_helpers.h>
+#include <linux/sched.h>
+#include <linux/sched/task.h>
+#include <linux/mm_types.h>
+#include <linux/pid.h>
+
+#include "mbraink_ioctl_struct_define.h"
+
+#define PSS_SHIFT 12
+#define MAX_RT_PRIO 100
+#define MAX_TRACE_NUM 3072
+
+struct mbraink_tracing_pidlist {
+ unsigned short pid;
+ unsigned short tgid;
+ unsigned short uid;
+ int priority;
+ char name[TASK_COMM_LEN];
+ long long start;
+ long long end;
+ u64 jiffies;
+ bool dirty;
+};
+
+struct mem_size_stats {
+ unsigned long resident;
+ unsigned long shared_clean;
+ unsigned long shared_dirty;
+ unsigned long private_clean;
+ unsigned long private_dirty;
+ unsigned long referenced;
+ unsigned long anonymous;
+ unsigned long lazyfree;
+ unsigned long anonymous_thp;
+ unsigned long shmem_thp;
+ unsigned long file_thp;
+ unsigned long swap;
+ unsigned long shared_hugetlb;
+ unsigned long private_hugetlb;
+ u64 pss;
+ u64 pss_anon;
+ u64 pss_file;
+ u64 pss_shmem;
+ u64 pss_locked;
+ u64 swap_pss;
+ bool check_shmem_swap;
+};
+
+void mbraink_get_process_memory_info(pid_t current_pid,
+ struct mbraink_process_memory_data *process_memory_buffer);
+int mbraink_process_tracer_init(void);
+void mbraink_process_tracer_exit(void);
+void mbraink_get_tracing_pid_info(unsigned short current_idx,
+ struct mbraink_tracing_pid_data *tracing_pid_buffer);
+void smap_gather_stats(struct vm_area_struct *vma,
+ struct mem_size_stats *mss, unsigned long start);
+
+void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st);
+void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st);
+u64 nsec_to_clock_t(u64 x);
+#endif
diff --git a/drivers/misc/mediatek_mbraink/mbraink_ioctl_struct_define.h b/drivers/misc/mediatek_mbraink/mbraink_ioctl_struct_define.h
new file mode 100644
index 000000000000..8395cf3b3702
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_ioctl_struct_define.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+#ifndef MBRAINK_IOCTL_STRUCT_H
+#define MBRAINK_IOCTL_STRUCT_H
+
+#define MAX_MEM_STRUCT_SZ 4
+#define MAX_TRACE_PID_NUM 16
+
+struct mbraink_process_memory_struct {
+ unsigned short pid;
+ unsigned long pss;
+ unsigned long uss;
+ unsigned long rss;
+ unsigned long swap;
+ unsigned long java_heap;
+ unsigned long native_heap;
+};
+
+struct mbraink_process_memory_data {
+ unsigned short pid;
+ unsigned short pid_count;
+ struct mbraink_process_memory_struct drv_data[MAX_MEM_STRUCT_SZ];
+};
+
+struct mbraink_tracing_pid {
+ unsigned short pid;
+ unsigned short tgid;
+ unsigned short uid;
+ int priority;
+ char name[TASK_COMM_LEN];
+ long long start;
+ long long end;
+ u64 jiffies;
+};
+
+struct mbraink_tracing_pid_data {
+ unsigned short tracing_idx;
+ unsigned short tracing_count;
+ struct mbraink_tracing_pid drv_data[MAX_TRACE_PID_NUM];
+};
+
+#endif
diff --git a/drivers/misc/mediatek_mbraink/mbraink_main.c b/drivers/misc/mediatek_mbraink/mbraink_main.c
new file mode 100644
index 000000000000..34bbc152b448
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_main.c
@@ -0,0 +1,277 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/compat.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+
+#include "mbraink_main.h"
+#include "mbraink_data.h"
+
+struct mbraink_data mbraink_priv;
+
+static int mbraink_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static int mbraink_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static long mbraink_ioctl(struct file *filp,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ long ret = 0;
+
+ switch (cmd) {
+ case RO_PROCESS_MEMORY:
+ {
+ struct mbraink_process_memory_data process_memory_buffer;
+
+ pid_t pid = 1;
+
+ if (copy_from_user(&process_memory_buffer,
+ (struct mbraink_process_memory_data *)arg,
+ sizeof(process_memory_buffer))) {
+ pr_notice("copy process memory info from user Err!\n");
+ return -EPERM;
+ }
+
+ if (process_memory_buffer.pid > PID_MAX_DEFAULT ||
+ process_memory_buffer.pid_count > PID_MAX_DEFAULT) {
+ pr_notice("process memory: Invalid pid_idx %u or pid_count %u\n",
+ process_memory_buffer.pid, process_memory_buffer.pid_count);
+ return -EINVAL;
+ }
+ pid = process_memory_buffer.pid;
+
+ mbraink_get_process_memory_info(pid, &process_memory_buffer);
+
+ if (copy_to_user((struct mbraink_process_memory_data *)arg,
+ &process_memory_buffer,
+ sizeof(process_memory_buffer))) {
+ pr_notice("Copy process_memory_info to UserSpace error!\n");
+ return -EPERM;
+ }
+ break;
+ }
+ case RO_TRACE_PROCESS:
+ {
+ struct mbraink_tracing_pid_data tracing_pid_buffer;
+
+ unsigned short tracing_idx = 0;
+
+ if (copy_from_user(&tracing_pid_buffer,
+ (struct mbraink_tracing_pid_data *)arg,
+ sizeof(tracing_pid_buffer))) {
+ pr_notice("copy tracing_pid_buffer data from user Err!\n");
+ return -EPERM;
+ }
+
+ if (tracing_pid_buffer.tracing_idx > MAX_TRACE_NUM) {
+ pr_notice("invalid tracing_idx %u !\n",
+ tracing_pid_buffer.tracing_idx);
+ return -EINVAL;
+ }
+ tracing_idx = tracing_pid_buffer.tracing_idx;
+
+ mbraink_get_tracing_pid_info(tracing_idx, &tracing_pid_buffer);
+
+ if (copy_to_user((struct mbraink_tracing_pid_data *)arg,
+ &tracing_pid_buffer,
+ sizeof(tracing_pid_buffer))) {
+ pr_notice("Copy tracing_pid_buffer to UserSpace error!\n");
+ return -EPERM;
+ }
+ break;
+ }
+ default:
+ pr_notice("illegal ioctl number %u.\n", cmd);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+#if IS_ENABLED(CONFIG_COMPAT)
+static long mbraink_compat_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ return mbraink_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+static const struct file_operations mbraink_fops = {
+ .owner = THIS_MODULE,
+ .open = mbraink_open,
+ .release = mbraink_release,
+ .unlocked_ioctl = mbraink_ioctl,
+#if IS_ENABLED(CONFIG_COMPAT)
+ .compat_ioctl = mbraink_compat_ioctl,
+#endif
+};
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+static int mbraink_suspend(struct device *dev)
+{
+ int ret;
+
+ ret = pm_generic_suspend(dev);
+
+ return ret;
+}
+
+static int mbraink_resume(struct device *dev)
+{
+ int ret;
+
+ ret = pm_generic_resume(dev);
+
+ return ret;
+}
+
+static const struct dev_pm_ops mbraink_class_dev_pm_ops = {
+ .suspend = mbraink_suspend,
+ .resume = mbraink_resume,
+};
+
+#define MBRAINK_CLASS_DEV_PM_OPS (&mbraink_class_dev_pm_ops)
+#else
+#define MBRAINK_CLASS_DEV_PM_OPS NULL
+#endif /*end of CONFIG_PM_SLEEP*/
+
+static void class_create_release(struct class *cls)
+{
+ /*do nothing because the mbraink class is not from malloc*/
+}
+
+static struct class mbraink_class = {
+ .name = "mbraink_host",
+ .owner = THIS_MODULE,
+ .class_release = class_create_release,
+ .pm = MBRAINK_CLASS_DEV_PM_OPS,
+};
+
+static void device_create_release(struct device *dev)
+{
+ /*do nothing because the mbraink device is not from malloc*/
+}
+
+static struct device mbraink_device = {
+ .init_name = "mbraink",
+ .release = device_create_release,
+ .parent = NULL,
+ .driver_data = NULL,
+ .class = NULL,
+ .devt = 0,
+};
+
+static int mbraink_dev_init(void)
+{
+ dev_t mbraink_dev_no = 0;
+
+ /*Allocating Major number*/
+ if ((alloc_chrdev_region(&mbraink_dev_no, 0, 1, CHRDEV_NAME)) < 0) {
+ pr_notice("Cannot allocate major number %u\n",
+ mbraink_dev_no);
+ return -EBADF;
+ }
+ pr_info("[MBK_INFO] %s: Major = %u Minor = %u\n",
+ __func__, MAJOR(mbraink_dev_no),
+ MINOR(mbraink_dev_no));
+
+ /*Initialize cdev structure*/
+ cdev_init(&mbraink_priv.mbraink_cdev, &mbraink_fops);
+
+ /*Adding character device to the system*/
+ if ((cdev_add(&mbraink_priv.mbraink_cdev, mbraink_dev_no, 1)) < 0) {
+ pr_notice("Cannot add the device to the system\n");
+ goto r_class;
+ }
+
+ /*Register mbraink class*/
+ if (class_register(&mbraink_class)) {
+ pr_notice("Cannot register the mbraink class %s\n",
+ mbraink_class.name);
+ goto r_class;
+ }
+
+ /*add mbraink device into mbraink_class host,
+ *and assign the character device id to mbraink device
+ */
+
+ mbraink_device.devt = mbraink_dev_no;
+ mbraink_device.class = &mbraink_class;
+
+ /*Register mbraink device*/
+ if (device_register(&mbraink_device)) {
+ pr_notice("Cannot register the Device %s\n",
+ mbraink_device.init_name);
+ goto r_device;
+ }
+ pr_info("[MBK_INFO] %s: Mbraink device init done.\n", __func__);
+
+ return 0;
+
+r_device:
+ class_unregister(&mbraink_class);
+r_class:
+ unregister_chrdev_region(mbraink_dev_no, 1);
+
+ return -EPERM;
+}
+
+static int mbraink_init(void)
+{
+ int ret = 0;
+
+ ret = mbraink_dev_init();
+ if (ret)
+ pr_notice("mbraink device init failed.\n");
+
+ ret = mbraink_process_tracer_init();
+ if (ret)
+ pr_notice("mbraink tracer init failed.\n");
+
+ return ret;
+}
+
+static void mbraink_dev_exit(void)
+{
+ device_unregister(&mbraink_device);
+ mbraink_device.class = NULL;
+
+ class_unregister(&mbraink_class);
+ cdev_del(&mbraink_priv.mbraink_cdev);
+ unregister_chrdev_region(mbraink_device.devt, 1);
+
+ pr_info("[MBK_INFO] %s: MBraink device exit done, major:minor %u:%u\n",
+ __func__,
+ MAJOR(mbraink_device.devt),
+ MINOR(mbraink_device.devt));
+}
+
+static void mbraink_exit(void)
+{
+ mbraink_dev_exit();
+ mbraink_process_tracer_exit();
+}
+
+module_init(mbraink_init);
+module_exit(mbraink_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("<Wei-chin.Tsai at mediatek.com>");
+MODULE_DESCRIPTION("MBraink Linux Device Driver");
+MODULE_VERSION("1.0");
diff --git a/drivers/misc/mediatek_mbraink/mbraink_main.h b/drivers/misc/mediatek_mbraink/mbraink_main.h
new file mode 100644
index 000000000000..0bb3847cdffb
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_main.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#ifndef MBRAINK_MAIN_H
+#define MBRAINK_MAIN_H
+
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/pid.h>
+
+#include "mbraink_ioctl_struct_define.h"
+
+#define IOC_MAGIC 'k'
+
+/*Mbrain Delegate Info List*/
+#define PROCESS_MEMORY_INFO '4'
+#define TRACE_PROCESS_INFO 'a'
+
+/*Mbrain Delegate IOCTL List*/
+#define RO_PROCESS_MEMORY _IOR(IOC_MAGIC, PROCESS_MEMORY_INFO, \
+ struct mbraink_process_memory_data*)
+#define RO_TRACE_PROCESS _IOR(IOC_MAGIC, TRACE_PROCESS_INFO, \
+ struct mbraink_tracing_pid_data*)
+
+struct mbraink_data {
+#define CHRDEV_NAME "mbraink_chrdev"
+ struct cdev mbraink_cdev;
+};
+
+#endif /*end of MBRAINK_MAIN_H*/
diff --git a/kernel/exit.c b/kernel/exit.c
index edb50b4c9972..410a3de14e09 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -81,6 +81,8 @@
*/
static unsigned int oops_limit = 10000;
+EXPORT_TRACEPOINT_SYMBOL_GPL(sched_process_exit);
+
#ifdef CONFIG_SYSCTL
static struct ctl_table kern_exit_table[] = {
{
diff --git a/kernel/fork.c b/kernel/fork.c
index f81985dcc4bd..8fba356fb7c2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -142,6 +142,8 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */
+EXPORT_TRACEPOINT_SYMBOL_GPL(sched_process_fork);
+
#ifdef CONFIG_PROVE_RCU
int lockdep_tasklist_lock_is_held(void)
{
--
2.18.0
More information about the linux-arm-kernel
mailing list