diff --git a/Documentation/admin-guide/mm/ksm.rst b/Documentation/admin-guide/mm/ksm.rst
index b244f0202a03..91326198e37f 100644
--- a/Documentation/admin-guide/mm/ksm.rst
+++ b/Documentation/admin-guide/mm/ksm.rst
@@ -32,7 +32,7 @@ are swapped back in: ksmd must rediscover their identity and merge again).
 Controlling KSM with madvise
 ============================
 
-KSM only operates on those areas of address space which an application
+KSM can operate on those areas of address space which an application
 has advised to be likely candidates for merging, by using the madvise(2)
 system call::
 
@@ -70,6 +70,28 @@ Applications should be considerate in their use of MADV_MERGEABLE,
 restricting its use to areas likely to benefit.  KSM's scans may use a lot
 of processing power: some installations will disable KSM for that reason.
 
+Controlling KSM with procfs
+===========================
+We can also control KSM with ``/proc/<pid>/ksm_enabled`` based on every
+process. KSM for each process can be entirely disabled (mostly for
+debugging purposes) or only enabled inside MADV_MERGEABLE regions (to avoid
+the risk of consuming more cpu resources to scan for ksmd) or enabled entirely
+for a process. This can be achieved with one of::
+
+    echo always > /proc/<pid>/ksm_enabled
+    echo madvise > /proc/<pid>/ksm_enabled
+    echo never > /proc/<pid>/ksm_enabled
+
+always:
+        force all anonymous and eligible VMAs of this process to be scanned
+        by ksmd.
+madvise:
+        the default state, unless user code call madvise, ksmd doesn't scan
+        this process.
+never:
+        this process will never be scanned by ksmd and no merged pages
+	occurred in this process.
+
 .. _ksm_sysfs:
 
 KSM daemon sysfs interface
diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
index 1bc91fb8c321..ea7e08a1c143 100644
--- a/Documentation/filesystems/proc.rst
+++ b/Documentation/filesystems/proc.rst
@@ -47,6 +47,7 @@ fixes/update part 1.1  Stefani Seibold <stefani@seibold.net>    June 9 2009
   3.10  /proc/<pid>/timerslack_ns - Task timerslack value
   3.11	/proc/<pid>/patch_state - Livepatch patch operation state
   3.12	/proc/<pid>/arch_status - Task architecture specific information
+  3.13  /proc/<pid>/ksm_enabled - Controlling KSM based on process
 
   4	Configuring procfs
   4.1	Mount options
@@ -2140,6 +2141,19 @@ AVX512_elapsed_ms
   the task is unlikely an AVX512 user, but depends on the workload and the
   scheduling scenario, it also could be a false negative mentioned above.
 
+3.13 /proc/<pid>/ksm_enabled - Controlling KSM based on process
+---------------------------------------------------------------
+When CONFIG_KSM is enabled, this file can be used to specify how this
+process's anonymous memory gets involved in KSM scanning.
+
+If writing "always" to this file, it will force all anonymous and eligible
+VMAs of this process to be scanned by ksmd.
+
+If writing "madvise" to this file, turn to the default state, unless user
+code call madvise, ksmd doesn't scan this process.
+
+If writing "never" to this file, this process will never be scanned by ksmd.
+
 Chapter 4: Configuring procfs
 =============================
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 617816168748..760ceeab4aa1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -96,6 +96,7 @@
 #include <linux/time_namespace.h>
 #include <linux/resctrl.h>
 #include <linux/cn_proc.h>
+#include <linux/ksm.h>
 #include <trace/events/oom.h>
 #include "internal.h"
 #include "fd.h"
@@ -3171,7 +3172,104 @@ static int proc_pid_ksm_merging_pages(struct seq_file *m, struct pid_namespace *
 
 	return 0;
 }
-#endif /* CONFIG_KSM */
+
+static int ksm_enabled_show(struct seq_file *m, void *v)
+{
+	struct inode *inode = m->private;
+	struct mm_struct *mm;
+	struct task_struct *task = get_proc_task(inode);
+
+	if (!task)
+		return -ESRCH;
+
+	mm = get_task_mm(task);
+	if (mm) {
+		if (mm->ksm_enabled == KSM_PROC_ALWAYS)
+			seq_puts(m, "[always] madvise never\n");
+		else if (mm->ksm_enabled == KSM_PROC_MADVISE)
+			seq_puts(m, "always [madvise] never\n");
+		else
+			seq_puts(m, "always madvise [never]\n");
+		mmput(mm);
+	}
+
+	put_task_struct(task);
+	return 0;
+}
+
+static ssize_t ksm_enabled_write(struct file *file, const char __user *buf,
+								size_t count, loff_t *ppos)
+{
+	struct task_struct *task;
+	struct mm_struct *mm;
+	char buffer[PROC_NUMBUF];
+	int value;
+	int err = 0;
+	long str_len;
+
+	if (count > sizeof(buffer) - 1)
+		count = sizeof(buffer) - 1;
+	str_len = strncpy_from_user(buffer, buf, count);
+	if (str_len < 0)
+		return -EFAULT;
+	buffer[str_len - 1] = '\0';
+
+	if (!strcmp("always", buffer))
+		value = KSM_PROC_ALWAYS;
+	else if (!strcmp("madvise", buffer))
+		value = KSM_PROC_MADVISE;
+	else if (!strcmp("never", buffer))
+		value = KSM_PROC_NEVER;
+	else
+		return -EINVAL;
+
+	task = get_proc_task(file_inode(file));
+	if (!task)
+		return -ESRCH;
+	mm = get_task_mm(task);
+	if (!mm)
+		goto out_put_task;
+
+	if (mm->ksm_enabled != value) {
+		if (mmap_write_lock_killable(mm)) {
+			err = -EINTR;
+			goto out_mmput;
+		}
+		if (value == KSM_PROC_NEVER)
+			mm->ksm_enabled = value;
+		else {
+			/*
+			 * No matter whether it's KSM_PROC_ALWAYS or KSM_PROC_MADVISE, we need
+			 * to recheck mm->flags to guarantee that this mm is in ksm_scan.
+			 */
+			if (!test_bit(MMF_VM_MERGEABLE, &mm->flags))
+				err = __ksm_enter(mm);
+			if (!err)
+				mm->ksm_enabled = value;
+		}
+		mmap_write_unlock(mm);
+	}
+
+out_mmput:
+	mmput(mm);
+out_put_task:
+	put_task_struct(task);
+	return err < 0 ? err : count;
+}
+
+static int ksm_enabled_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, ksm_enabled_show, inode);
+}
+
+static const struct file_operations proc_pid_ksm_enabled_operations = {
+	.open       = ksm_enabled_open,
+	.read		= seq_read,
+	.write		= ksm_enabled_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+#endif /*CONFIG_KSM */
 
 #ifdef CONFIG_STACKLEAK_METRICS
 static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
@@ -3306,6 +3404,7 @@ static const struct pid_entry tgid_base_stuff[] = {
 #endif
 #ifdef CONFIG_KSM
 	ONE("ksm_merging_pages",  S_IRUSR, proc_pid_ksm_merging_pages),
+	REG("ksm_enabled", S_IRUGO|S_IWUSR, proc_pid_ksm_enabled_operations),
 #endif
 };
 
@@ -3642,6 +3741,7 @@ static const struct pid_entry tid_base_stuff[] = {
 #endif
 #ifdef CONFIG_KSM
 	ONE("ksm_merging_pages",  S_IRUSR, proc_pid_ksm_merging_pages),
+	REG("ksm_enabled", S_IRUGO|S_IWUSR, proc_pid_ksm_enabled_operations),
 #endif
 };
 
diff --git a/include/linux/ksm.h b/include/linux/ksm.h
index 0b4f17418f64..29d23d208b54 100644
--- a/include/linux/ksm.h
+++ b/include/linux/ksm.h
@@ -19,6 +19,11 @@ struct stable_node;
 struct mem_cgroup;
 
 #ifdef CONFIG_KSM
+
+#define KSM_PROC_MADVISE	0
+#define KSM_PROC_ALWAYS		1
+#define KSM_PROC_NEVER		2
+
 int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
 		unsigned long end, int advice, unsigned long *vm_flags);
 int __ksm_enter(struct mm_struct *mm);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 417ef1519475..29fd4c84d08c 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -649,6 +649,16 @@ struct mm_struct {
 		 * merging.
 		 */
 		unsigned long ksm_merging_pages;
+
+		/*
+		 * Represent the state of this mm involing in KSM, with 3 states:
+		 * 1) KSM_PROC_ALWAYS:  force all anonymous VMAs of this process to
+		 *						be scanned.
+		 * 2) KSM_PROC_MADVISE: the default state, unless user code call
+		 *						madvise, don't scan this process.
+		 * 3) KSM_PROC_NEVER: never be involed in KSM.
+		 */
+		int ksm_enabled;
 #endif
 	} __randomize_layout;
 
diff --git a/mm/ksm.c b/mm/ksm.c
index 26da7f813f23..90cc8eda8bca 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -334,6 +334,35 @@ static void __init ksm_slab_free(void)
 	mm_slot_cache = NULL;
 }
 
+static bool vma_scannable(struct vm_area_struct *vma)
+{
+	unsigned long vm_flags = vma->vm_flags;
+	struct mm_struct *mm = vma->vm_mm;
+
+	if (mm->ksm_enabled == KSM_PROC_NEVER ||
+			(!(vma->vm_flags & VM_MERGEABLE) &&
+			mm->ksm_enabled != KSM_PROC_ALWAYS))
+		return false;
+
+	if (vm_flags & (VM_SHARED	| VM_MAYSHARE	|
+			VM_PFNMAP	| VM_IO | VM_DONTEXPAND |
+			VM_HUGETLB	| VM_MIXEDMAP))
+		return false;       /* just ignore this vma*/
+
+	if (vma_is_dax(vma))
+		return false;
+#ifdef VM_SAO
+	if (vm_flags & VM_SAO)
+		return false;
+#endif
+#ifdef VM_SPARC_ADI
+	if (vm_flags & VM_SPARC_ADI)
+		return false;
+#endif
+
+	return true;
+}
+
 static __always_inline bool is_stable_node_chain(struct stable_node *chain)
 {
 	return chain->rmap_hlist_len == STABLE_NODE_CHAIN;
@@ -523,7 +552,7 @@ static struct vm_area_struct *find_mergeable_vma(struct mm_struct *mm,
 	if (ksm_test_exit(mm))
 		return NULL;
 	vma = vma_lookup(mm, addr);
-	if (!vma || !(vma->vm_flags & VM_MERGEABLE) || !vma->anon_vma)
+	if (!vma || !vma_scannable(vma) || !vma->anon_vma)
 		return NULL;
 	return vma;
 }
@@ -990,7 +1019,7 @@ static int unmerge_and_remove_all_rmap_items(void)
 		for_each_vma(vmi, vma) {
 			if (ksm_test_exit(mm))
 				break;
-			if (!(vma->vm_flags & VM_MERGEABLE) || !vma->anon_vma)
+			if (!vma_scannable(vma) || !vma->anon_vma)
 				continue;
 			err = unmerge_ksm_pages(vma,
 						vma->vm_start, vma->vm_end);
@@ -2300,7 +2329,7 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page)
 		goto no_vmas;
 
 	for_each_vma(vmi, vma) {
-		if (!(vma->vm_flags & VM_MERGEABLE))
+		if (!vma_scannable(vma))
 			continue;
 		if (ksm_scan.address < vma->vm_start)
 			ksm_scan.address = vma->vm_start;
