diff --git a/mm/damon.c b/mm/damon.c
index 5d33b5d6504b..efb85bdf9400 100644
--- a/mm/damon.c
+++ b/mm/damon.c
@@ -195,6 +195,29 @@ static void damon_destroy_task(struct damon_task *t)
 	damon_free_task(t);
 }
 
+static struct damon_rule *damon_new_rule(
+		unsigned int min_sz_region, unsigned int max_sz_region,
+		unsigned int min_nr_accesses, unsigned int max_nr_accesses,
+		unsigned int min_age_region, unsigned int max_age_region,
+		enum damon_action action)
+{
+	struct damon_rule *ret;
+
+	ret = kmalloc(sizeof(struct damon_rule), GFP_KERNEL);
+	if (!ret)
+		return NULL;
+	ret->min_sz_region = min_sz_region;
+	ret->max_sz_region = max_sz_region;
+	ret->min_nr_accesses = min_nr_accesses;
+	ret->max_nr_accesses = max_nr_accesses;
+	ret->min_age_region = min_age_region;
+	ret->max_age_region = max_age_region;
+	ret->action = action;
+	INIT_LIST_HEAD(&ret->list);
+
+	return ret;
+}
+
 static void damon_add_rule(struct damon_ctx *ctx, struct damon_rule *r)
 {
 	list_add_tail(&r->list, &ctx->rules_list);
@@ -1266,6 +1289,130 @@ static ssize_t debugfs_monitor_on_write(struct file *file,
 	return ret;
 }
 
+static ssize_t damon_sprint_rules(struct damon_ctx *c, char *buf, ssize_t len)
+{
+	char *cursor = buf;
+	struct damon_rule *r;
+	int ret;
+
+	damon_for_each_rule(c, r) {
+		ret = snprintf(cursor, len, "%u %u %u %u %u %u %d\n",
+				r->min_sz_region, r->max_sz_region,
+				r->min_nr_accesses, r->max_nr_accesses,
+				r->min_age_region, r->max_age_region,
+				r->action);
+		cursor += ret;
+	}
+	return cursor - buf;
+}
+
+static ssize_t debugfs_rules_read(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct damon_ctx *ctx = &damon_user_ctx;
+	ssize_t len;
+	char *rules_buf;
+
+	rules_buf = kmalloc(sizeof(char) * 1024, GFP_KERNEL);
+
+	len = damon_sprint_rules(ctx, rules_buf, 1024);
+	len = simple_read_from_buffer(buf, count, ppos, rules_buf, len);
+
+	kfree(rules_buf);
+	return len;
+}
+
+static void damon_free_rules(struct damon_rule **rules, ssize_t nr_rules)
+{
+	ssize_t i;
+
+	for (i = 0; i < nr_rules; i++)
+		kfree(rules[i]);
+	kfree(rules);
+}
+
+/*
+ * Converts a string into an array of struct damon_rule pointers
+ *
+ * Returns an array of struct damon_rule pointers that converted, or NULL
+ * otherwise.
+ */
+static struct damon_rule **str_to_rules(const char *str, ssize_t len,
+				ssize_t *nr_rules)
+{
+	struct damon_rule *rule, **rules;
+	int pos = 0, parsed, ret;
+	unsigned int min_sz, max_sz, min_nr_a, max_nr_a, min_age, max_age;
+	int action;
+
+	rules = kmalloc_array(256, sizeof(struct damon_rule *), GFP_KERNEL);
+	if (!rules)
+		return NULL;
+
+	*nr_rules = 0;
+	while (pos < len && *nr_rules < 256) {
+		ret = sscanf(&str[pos], "%u %u %u %u %u %u %d%n",
+				&min_sz, &max_sz, &min_nr_a, &max_nr_a,
+				&min_age, &max_age, &action, &parsed);
+		pos += parsed;
+		if (ret != 7)
+			break;
+		if (action >= DAMON_ACTION_LEN) {
+			pr_err("wrong action %d\n", action);
+			goto error;
+		}
+
+		rule = damon_new_rule(min_sz, max_sz, min_nr_a, max_nr_a,
+				min_age, max_age, action);
+		if (!rule)
+			goto error;
+
+		rules[*nr_rules] = rule;
+		*nr_rules += 1;
+	}
+	return rules;
+error:
+	damon_free_rules(rules, *nr_rules);
+	return NULL;
+}
+
+static ssize_t debugfs_rules_write(struct file *file, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct damon_ctx *ctx = &damon_user_ctx;
+	char *rules_buf;
+	struct damon_rule **rules;
+	ssize_t nr_rules, ret;
+
+	rules_buf = kmalloc(sizeof(char) * 1024, GFP_KERNEL);
+	ret = simple_write_to_buffer(rules_buf, 1024, ppos, buf, count);
+	if (ret < 0) {
+		kfree(rules_buf);
+		return ret;
+	}
+
+	rules = str_to_rules(rules_buf, ret, &nr_rules);
+	if (!rules)
+		return -EINVAL;
+
+	spin_lock(&ctx->kdamond_lock);
+	if (ctx->kdamond)
+		goto monitor_running;
+
+	damon_set_rules(ctx, rules, nr_rules);
+	spin_unlock(&ctx->kdamond_lock);
+	kfree(rules_buf);
+	return ret;
+
+monitor_running:
+	spin_unlock(&ctx->kdamond_lock);
+	pr_err("%s: kdamond is running. Turn it off first.\n", __func__);
+	ret = -EINVAL;
+	damon_free_rules(rules, nr_rules);
+	kfree(rules_buf);
+	return ret;
+}
+
 static ssize_t damon_sprint_pids(struct damon_ctx *ctx, char *buf, ssize_t len)
 {
 	char *cursor = buf;
@@ -1468,6 +1615,12 @@ static const struct file_operations pids_fops = {
 	.write = debugfs_pids_write,
 };
 
+static const struct file_operations rules_fops = {
+	.owner = THIS_MODULE,
+	.read = debugfs_rules_read,
+	.write = debugfs_rules_write,
+};
+
 static const struct file_operations record_fops = {
 	.owner = THIS_MODULE,
 	.read = debugfs_record_read,
@@ -1484,10 +1637,10 @@ static struct dentry *debugfs_root;
 
 static int __init debugfs_init(void)
 {
-	const char * const file_names[] = {"attrs", "record",
+	const char * const file_names[] = {"attrs", "record", "rules",
 		"pids", "monitor_on"};
 	const struct file_operations *fops[] = {&attrs_fops, &record_fops,
-		&pids_fops, &monitor_on_fops};
+		&rules_fops, &pids_fops, &monitor_on_fops};
 	int i;
 
 	debugfs_root = debugfs_create_dir("damon", NULL);
