LKML Archive mirror
 help / color / mirror / Atom feed
From: "Wei-chin Tsai (蔡維晉)" <Wei-chin.Tsai@mediatek.com>
To: "willy@infradead.org" <willy@infradead.org>
Cc: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"Mel Lee (李奇錚)" <Mel.Lee@mediatek.com>,
	"linux-mediatek@lists.infradead.org"
	<linux-mediatek@lists.infradead.org>,
	"linux@armlinux.org.uk" <linux@armlinux.org.uk>,
	wsd_upstream <wsd_upstream@mediatek.com>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	"linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>,
	"matthias.bgg@gmail.com" <matthias.bgg@gmail.com>,
	"Ivan Tseng (曾志軒)" <ivan.tseng@mediatek.com>,
	"angelogioacchino.delregno@collabora.com"
	<angelogioacchino.delregno@collabora.com>
Subject: Re: [PATCH v1 1/1] memory: export symbols for process memory related functions
Date: Mon, 12 Jun 2023 14:21:06 +0000	[thread overview]
Message-ID: <c23e1fb3628bf0a32bd0eb491c9370b961e19fd1.camel@mediatek.com> (raw)
In-Reply-To: <ZIPCIpWPQbVqoI4q@casper.infradead.org>

[-- Attachment #1: Type: text/plain, Size: 1217 bytes --]

On Sat, 2023-06-10 at 01:21 +0100, Matthew Wilcox wrote:
>  	 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>  On Fri, Jun 09, 2023 at 04:09:01PM +0000, Wei-chin Tsai (蔡維晉) wrote:
> > > You haven't included any users of these new exports, so the
> initial
> > > reaction is going to be negative - please include the users of
> these
> > > new symbols in your patch set.
> > We use these two export functions from our kernel module to get a
> > specific user process's memory information and heap usage.
> Furthermore,
> > we can use such information to detect the memory leak issues. 
> > 
> > The example code is as follows:
> 
> No.  You need to be submitting the code that will use the symbol *at
> the
> same time* as the patch to export the symbol.  No example code
> showing
> how it could be used.  Because if the user isn't compelling, the
> patch
> to export the symbol won't be applied either.

Hi Matthew,

Got it. The following attached patch file
"v1-0001-memory-export-symbols-for-process-memory-related-.patch" is
the patch including the users of these new symbols. Thanks.

Regards,

Jim

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v1-0001-memory-export-symbols-for-process-memory-related-.patch --]
[-- Type: text/x-patch; name="v1-0001-memory-export-symbols-for-process-memory-related-.patch", Size: 28708 bytes --]

From b4529be3bb55f643cecd6c3a40f40cc8446f5785 Mon Sep 17 00:00:00 2001
From: "jim.tsai" <Wei-chin.Tsai@mediatek.com>
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 <Wei-chin.Tsai@mediatek.com>
---
 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 <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@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/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


  reply	other threads:[~2023-06-12 14:24 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20230609110902.13799-1-Wei-chin.Tsai@mediatek.com>
2023-06-09 11:20 ` [PATCH v1 1/1] memory: export symbols for process memory related functions Russell King (Oracle)
2023-06-09 16:09   ` Wei-chin Tsai (蔡維晉)
2023-06-10  0:21     ` Matthew Wilcox
2023-06-12 14:21       ` Wei-chin Tsai (蔡維晉) [this message]
2023-06-16  9:24         ` Matthias Brugger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c23e1fb3628bf0a32bd0eb491c9370b961e19fd1.camel@mediatek.com \
    --to=wei-chin.tsai@mediatek.com \
    --cc=Mel.Lee@mediatek.com \
    --cc=angelogioacchino.delregno@collabora.com \
    --cc=ivan.tseng@mediatek.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=linux@armlinux.org.uk \
    --cc=matthias.bgg@gmail.com \
    --cc=willy@infradead.org \
    --cc=wsd_upstream@mediatek.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).