From b4529be3bb55f643cecd6c3a40f40cc8446f5785 Mon Sep 17 00:00:00 2001 From: "jim.tsai" Date: Mon, 12 Jun 2023 22:10:10 +0800 Subject: [PATCH v1 1/1] memory: export symbols for process memory related functions Export symbols for arch_vma_name and smap_gather_stats functions so that we can detect the memory leak issues. Besides, we can know which memory type is leaked, too. Signed-off-by: jim.tsai --- arch/arm/kernel/process.c | 1 + 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 ++ fs/proc/task_mmu.c | 5 +- kernel/signal.c | 1 + 10 files changed, 854 insertions(+), 2 deletions(-) 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/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 0e8ff85890ad..df91412a1069 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -343,6 +343,7 @@ const char *arch_vma_name(struct vm_area_struct *vma) { return is_gate_vma(vma) ? "[vectors]" : NULL; } +EXPORT_SYMBOL_GPL(arch_vma_name); /* If possible, provide a placement hint at a random offset from the * stack for the sigpage and vdso pages. 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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(""); +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 +#include +#include + +#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/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 6259dd432eeb..814d7829a20b 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -773,8 +773,8 @@ static const struct mm_walk_ops smaps_shmem_walk_ops = { * * Use vm_start of @vma as the beginning address if @start is 0. */ -static void smap_gather_stats(struct vm_area_struct *vma, - struct mem_size_stats *mss, unsigned long start) +void smap_gather_stats(struct vm_area_struct *vma, + struct mem_size_stats *mss, unsigned long start) { const struct mm_walk_ops *ops = &smaps_walk_ops; @@ -809,6 +809,7 @@ static void smap_gather_stats(struct vm_area_struct *vma, else walk_page_range(vma->vm_mm, start, vma->vm_end, ops, mss); } +EXPORT_SYMBOL_GPL(smap_gather_stats); #define SEQ_PUT_DEC(str, val) \ seq_put_decimal_ull_width(m, str, (val) >> 10, 8) diff --git a/kernel/signal.c b/kernel/signal.c index b5370fe5c198..a1abe77fcdc3 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -4700,6 +4700,7 @@ __weak const char *arch_vma_name(struct vm_area_struct *vma) { return NULL; } +EXPORT_SYMBOL_GPL(arch_vma_name); static inline void siginfo_buildtime_checks(void) { -- 2.18.0