From nobody Sun May 24 19:35:39 2026 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8288D409628 for ; Fri, 22 May 2026 14:56:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.176.79.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779461765; cv=none; b=mwiFUu1uyIHo+W04YOmCG4Z75YTsXwzYSmidMf7veQAamxJ3i50Asrk0ohbm/YetlC6iMhQxfAewGEM2R4y2+VusXQLVxvBkDZPPUIbmQrIN/lLEAFUlch8/n0LFNDSploODgY6M0KJFmYZ9LwJjE+LLAjcvwrDMPORSLDFzz5E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779461765; c=relaxed/simple; bh=iYAEINib+QsHuWUea3Xl3Q6healAGvKknbeoNJL5Tic=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=r74A81rgVa4FYmOWi7sjaxeaVK//XE+nxk5OD08CXdXKURci+nN9KGhv3OGXLQvgcBNUH2Ed37QG+HfjPqN7KS8akIIOEj0p69l6+T8pLBHS0v8gpAvznYRpxSsuPeZBF0+ekI35DTl9yaGoHxpqY6LBXwUqi95e4CXYVShxSZU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=185.176.79.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.18.224.83]) by frasgout.his.huawei.com (SkyGuard) with ESMTPS id 4gMSxp4s2czHnGcp; Fri, 22 May 2026 22:55:26 +0800 (CST) Received: from mscpeml500003.china.huawei.com (unknown [7.188.49.51]) by mail.maildlp.com (Postfix) with ESMTPS id 8B47840575; Fri, 22 May 2026 22:55:54 +0800 (CST) Received: from mscphis01197.huawei.com (10.123.65.218) by mscpeml500003.china.huawei.com (7.188.49.51) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 22 May 2026 17:55:54 +0300 From: To: , , , , , , , , , , Subject: [RFC PATCH v2 1/4] mm/damon: Generalize ctx_target creation for damon_ops_id and add vaddr support Date: Fri, 22 May 2026 14:55:15 +0000 Message-ID: <20260522145518.158910-2-gutierrez.asier@huawei-partners.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260522145518.158910-1-gutierrez.asier@huawei-partners.com> References: <20260522145518.158910-1-gutierrez.asier@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: mscpeml100003.china.huawei.com (10.199.174.67) To mscpeml500003.china.huawei.com (7.188.49.51) Content-Type: text/plain; charset="utf-8" From: Asier Gutierrez This patch adds a new function damon_modules_new_vaddr_ctx_target. Since ctx_target creation for vaddr and paddr is almost identical, the logic is extracted to a new function, damon_modules_new_ctx_target, and vaddr and paddr functions are left just as interfaces. This change was suggested earlier1 and it is needed to allow developers to create DAMON modules that use DAMON_OPS_VADDR targets. Signed-off-by: Asier Gutierrez Suggested-by: SeongJae Park --- mm/damon/modules-common.c | 33 +++++++++++++++++++++++++-------- mm/damon/modules-common.h | 3 +++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/mm/damon/modules-common.c b/mm/damon/modules-common.c index 86d58f8c4f63..35a4a89b6caa 100644 --- a/mm/damon/modules-common.c +++ b/mm/damon/modules-common.c @@ -9,13 +9,8 @@ =20 #include "modules-common.h" =20 -/* - * Allocate, set, and return a DAMON context for the physical address spac= e. - * @ctxp: Pointer to save the point to the newly created context - * @targetp: Pointer to save the point to the newly created target - */ -int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp, - struct damon_target **targetp) +static int _damon_modules_new_ctx_target(struct damon_ctx **ctxp, + struct damon_target **targetp, enum damon_ops_id id) { struct damon_ctx *ctx; struct damon_target *target; @@ -24,7 +19,7 @@ int damon_modules_new_paddr_ctx_target(struct damon_ctx *= *ctxp, if (!ctx) return -ENOMEM; =20 - if (damon_select_ops(ctx, DAMON_OPS_PADDR)) { + if (damon_select_ops(ctx, id)) { damon_destroy_ctx(ctx); return -EINVAL; } @@ -40,3 +35,25 @@ int damon_modules_new_paddr_ctx_target(struct damon_ctx = **ctxp, *targetp =3D target; return 0; } + +/* + * Allocate, set, and return a DAMON context for the physical address spac= e. + * @ctxp: Pointer to save the point to the newly created context + * @targetp: Pointer to save the point to the newly created target + */ +int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp, + struct damon_target **targetp) +{ + return _damon_modules_new_ctx_target(ctxp, targetp, DAMON_OPS_PADDR); +} + +/* + * Allocate, set, and return a DAMON context for the virtual address space. + * @ctxp: Pointer to save the point to the newly created context + * @targetp: Pointer to save the point to the newly created target + */ +int damon_modules_new_vaddr_ctx_target(struct damon_ctx **ctxp, + struct damon_target **targetp) +{ + return _damon_modules_new_ctx_target(ctxp, targetp, DAMON_OPS_VADDR); +} diff --git a/mm/damon/modules-common.h b/mm/damon/modules-common.h index f103ad556368..324b9cb4957e 100644 --- a/mm/damon/modules-common.h +++ b/mm/damon/modules-common.h @@ -47,3 +47,6 @@ =20 int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp, struct damon_target **targetp); + +int damon_modules_new_vaddr_ctx_target(struct damon_ctx **ctxp, + struct damon_target **targetp); --=20 2.43.0 From nobody Sun May 24 19:35:39 2026 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 821E23644C2 for ; Fri, 22 May 2026 14:56:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.176.79.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779461765; cv=none; b=crIjBRyWCwN+0+SFeT4tWOQ2TvkB7E9Vl0oMkM5D2CPef2G+gRBfXdhK9gHFLAInvrLyg1UvkOrVWAMGZ2D+IANjkRPkyZXSnBiw6i3ea3tw+CdKnNPn81VentSVlCCD28K1vlFka+X8fmbss9FeQ7L1Ixvkwo76yZBik4XOF5c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779461765; c=relaxed/simple; bh=N7l9RViDNHQ0LgRz4YPcQPkV/R75tA1dTGKSIKgVTQ0=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dMADeMazVO0CWAxzSOBKPpY8tvKSev48QvepW1oX/yW/oB2qnZQcQLZ6ZBgKHCx4SdnE0Ok7Ub9i33nM4bm0bNxch49DbGps2vYLo41Dlqja/a9FTNxhjiCCtdaCZm0ZpwNoG+57softKCK+W0f2VfbF7B4JGc65F97/UPL6I8U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=185.176.79.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.18.224.83]) by frasgout.his.huawei.com (SkyGuard) with ESMTPS id 4gMSxW09mfzJ46DW; Fri, 22 May 2026 22:55:11 +0800 (CST) Received: from mscpeml500003.china.huawei.com (unknown [7.188.49.51]) by mail.maildlp.com (Postfix) with ESMTPS id 9D36D40569; Fri, 22 May 2026 22:55:54 +0800 (CST) Received: from mscphis01197.huawei.com (10.123.65.218) by mscpeml500003.china.huawei.com (7.188.49.51) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 22 May 2026 17:55:54 +0300 From: To: , , , , , , , , , , Subject: [RFC PATCH v2 2/4] mm/damon: Introduce DAMOS_QUOTA_HUGEPAGE auto tuning Date: Fri, 22 May 2026 14:55:16 +0000 Message-ID: <20260522145518.158910-3-gutierrez.asier@huawei-partners.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260522145518.158910-1-gutierrez.asier@huawei-partners.com> References: <20260522145518.158910-1-gutierrez.asier@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: mscpeml100003.china.huawei.com (10.199.174.67) To mscpeml500003.china.huawei.com (7.188.49.51) Content-Type: text/plain; charset="utf-8" From: Asier Gutierrez Introduce DAMOS_QUOTA_HUGEPAGE auto tuning Add a new DAMOS quota goal metric to measure the amount of huge page consumption to total anonymous memory consumption ratio. Signed-off-by: Asier Gutierrez --- include/linux/damon.h | 1 + mm/damon/core.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/linux/damon.h b/include/linux/damon.h index c7a31572689b..8e15a674e893 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -177,6 +177,7 @@ enum damos_quota_goal_metric { DAMOS_QUOTA_ACTIVE_MEM_BP, DAMOS_QUOTA_INACTIVE_MEM_BP, DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BP, + DAMOS_QUOTA_HUGEPAGE, NR_DAMOS_QUOTA_GOAL_METRICS, }; =20 diff --git a/mm/damon/core.c b/mm/damon/core.c index 9f38deddcb30..1f1cf10aa241 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2536,6 +2536,18 @@ static unsigned int damos_get_in_active_mem_bp(bool = active_ratio) return mult_frac(inactive, 10000, total); } =20 +/* + * Returns anon hugepage memory to total anon memory use ratio. + */ +static unsigned int damos_get_used_hugepage_mem_bp(void) +{ + unsigned long used_hugepages, total_used; +=20 + used_hugepages =3D global_node_page_state(NR_ANON_THPS); + total_used =3D global_node_page_state(NR_ANON_MAPPED); + return mult_frac(used_hugepages, 10000, total_used); +} + static void damos_set_quota_goal_current_value(struct damon_ctx *c, struct damos *s, struct damos_quota_goal *goal) { @@ -2567,6 +2579,9 @@ static void damos_set_quota_goal_current_value(struct= damon_ctx *c, goal->current_value =3D damos_get_node_eligible_mem_bp(c, s, goal->nid); break; + case DAMOS_QUOTA_HUGEPAGE: + goal->current_value =3D damos_get_used_hugepage_mem_bp(); + break; default: break; } --=20 2.43.0 From nobody Sun May 24 19:35:39 2026 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 824B640803B for ; Fri, 22 May 2026 14:56:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.176.79.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779461766; cv=none; b=nzgfM3hJYVJv7DaO4iqdLiqq56OKHwQBp9kKjslv+/1357wudYyII60MOses2EZwO/zww47X9XLj+BB2b2CLXE5vhsBjRPOwWNM/FAru6shy3rwU4gIpUtx0wJiwiN+31FM2M5fkGApPwezndCdxGtuHwCcs+JSm6Yj5aaJSwYs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779461766; c=relaxed/simple; bh=ZZaI6DbWxqq8rVzeLx0fiwDysvjWBV92oOyrdS8DXy4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DJJtlgMjPUh7wt0ZZOzih1rBx4MiTHY9rlX8R+XNi3WjMXvKC8UD/2kuJcWuXxPzJuCsPqu/f3NggvtdZsjiZBqmtqDuXte5QrsF4uF/SFNs2vYRrWJw+l53PHoAGH6HSpKEOJgZ0WXa0TIWRtKd37U+mTjCOs9FZ+QSgsXI+i0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=185.176.79.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.18.224.83]) by frasgout.his.huawei.com (SkyGuard) with ESMTPS id 4gMSxp5vP0zHnGhq; Fri, 22 May 2026 22:55:26 +0800 (CST) Received: from mscpeml500003.china.huawei.com (unknown [7.188.49.51]) by mail.maildlp.com (Postfix) with ESMTPS id AF38440569; Fri, 22 May 2026 22:55:54 +0800 (CST) Received: from mscphis01197.huawei.com (10.123.65.218) by mscpeml500003.china.huawei.com (7.188.49.51) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 22 May 2026 17:55:54 +0300 From: To: , , , , , , , , , , Subject: [RFC PATCH v2 3/4] mm/damon: introduce DAMON_HUGEPAGE for hot region hugepage collapsing Date: Fri, 22 May 2026 14:55:17 +0000 Message-ID: <20260522145518.158910-4-gutierrez.asier@huawei-partners.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260522145518.158910-1-gutierrez.asier@huawei-partners.com> References: <20260522145518.158910-1-gutierrez.asier@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: mscpeml100003.china.huawei.com (10.199.174.67) To mscpeml500003.china.huawei.com (7.188.49.51) Content-Type: text/plain; charset="utf-8" From: Asier Gutierrez This patch introduces a new DAMON module (DAMON_HUGEPAGE) which collapses hot regions into huge pages. DAMON_HUGEPAGE operates in the virtual memory space, for a specific task. The user is expected to supply the PID of the task that is going to be monitored through the monitored_pid module variable. DAMON_HUGEPAGE uses the hugepage auto-tune mechanism to increase or decrease the aggressiveness of page collapsing. User autotuning is also available for additional tuning aggressiveness control. The module also includes changes to the DAMON compilation, so that the module can be enabled or disabled. Signed-off-by: Asier Gutierrez --- mm/damon/Kconfig | 7 + mm/damon/Makefile | 1 + mm/damon/hugepage.c (new) | 343 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 351 insertions(+) diff --git a/mm/damon/Kconfig b/mm/damon/Kconfig index 34631a44cdec..b615407cc13f 100644 --- a/mm/damon/Kconfig +++ b/mm/damon/Kconfig @@ -121,4 +121,11 @@ config DAMON_STAT_ENABLED_DEFAULT Whether to enable DAMON_STAT by default. Users can disable it in boot or runtime using its 'enabled' parameter. =20 +config DAMON_HUGEPAGE + bool "Build DAMON-based collapse of hot regions (DAMON_HUGEPAGE)" + depends on DAMON_VADDR + help + Collapse hot region into huge pages. Hot regions are determined by + DAMON-based sampling + endmenu diff --git a/mm/damon/Makefile b/mm/damon/Makefile index d8d6bf5f8bff..7cb55cc483f9 100644 --- a/mm/damon/Makefile +++ b/mm/damon/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_DAMON_SYSFS) +=3D sysfs-common.o sysfs-schemes= .o sysfs.o obj-$(CONFIG_DAMON_RECLAIM) +=3D modules-common.o reclaim.o obj-$(CONFIG_DAMON_LRU_SORT) +=3D modules-common.o lru_sort.o obj-$(CONFIG_DAMON_STAT) +=3D modules-common.o stat.o +obj-$(CONFIG_DAMON_HUGEPAGE) +=3D modules-common.o hugepage.o diff --git a/mm/damon/hugepage.c b/mm/damon/hugepage.c new file mode 100644 index 000000000000..1a09e6ebb911 --- /dev/null +++ b/mm/damon/hugepage.c @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2026 HUAWEI, Inc. + * https://www.huawei.com + * + * Author: Asier Gutierrez + */ + +#define pr_fmt(fmt) "damon-hugepage: " fmt + +#include +#include +#include + +#include "modules-common.h" + +#ifdef MODULE_PARAM_PREFIX +#undef MODULE_PARAM_PREFIX +#endif +#define MODULE_PARAM_PREFIX "damon_hugepage." + +/* + * Enable or disable DAMON_HUGEPAGE. + * + * You can enable DAMON_HUGEPAGE by setting the value of this parameter + * as ``Y``. Setting it as ``N`` disables DAMON_HUGEPAGE. + */ +static bool enabled __read_mostly; + +/* + * Make DAMON_HUGEPAGE reads the input parameters again, except ``enabled`= `. + * + * Input parameters that updated while DAMON_HUGEPAGE is running are not a= pplied + * by default. Once this parameter is set as ``Y``, DAMON_HUGEPAGE reads = values + * of parametrs except ``enabled`` again. Once the re-reading is done, th= is + * parameter is set as ``N``. If invalid parameters are found while the + * re-reading, DAMON_HUGEPAGE will be disabled. + */ +static bool commit_inputs __read_mostly; +module_param(commit_inputs, bool, 0600); + +/* + * Scale factor for DAMON_HUGEPAGE to ops address conversion. + * + * This parameter must not be set to 0. + */ +static unsigned long addr_unit __read_mostly =3D 1; + +static long monitored_pid; +module_param(monitored_pid, ulong, 0600); + +/* + * Time threshold for hot memory regions identification in microseconds. + * + * If a memory region has been accessed for this or longer time, + * DAMON_HUGEPAGE identifies the region as hot, and collapse it into a huge + * page. 100 microseconds by default. + */ +static unsigned long min_age __read_mostly =3D 100000; +module_param(min_age, ulong, 0600); + +static struct damos_quota damon_hugepage_quota =3D { + /* use up to 10 ms time, collapse up to 128 MiB per 1 sec by default */ + .ms =3D 10, + .sz =3D 128 * 1024 * 1024, + .reset_interval =3D 1000, + .weight_sz =3D 0, + .weight_nr_accesses =3D 1, + .weight_age =3D 1 +}; +DEFINE_DAMON_MODULES_DAMOS_QUOTAS(damon_hugepage_quota); + + +/* + * Desired ratio of huge pages use vs total anonymous memory usage. + * + * While keeping the caps that set by other quotas, DAMON_HUGEPAGE automat= ically + * increases and decreases the effective level of the quota to achieve the + * desired ratio. + * + * 100 bp by default. + */ +static unsigned long quota_percentage_hugepage __read_mostly =3D 100; +module_param(quota_percentage_hugepage, ulong, 0600); + +/* + * User-specifiable feedback for auto-tuning of the effective quota. + * + * While keeping the caps that set by other quotas, DAMON_HUGEPAGE automat= ically + * increases and decreases the effective level of the quota aiming receivi= ng this + * feedback of value ``10,000`` from the user. DAMON_HUGEPAGE assumes the= feedback + * value and the quota are positively proportional. Value zero means disa= bling + * this auto-tuning feature. + * + * Disabled by default. + * + */ +static unsigned long quota_autotune_feedback __read_mostly; +module_param(quota_autotune_feedback, ulong, 0600); + +/* + * PID of the DAMON thread + * + * If DAMON_HUGEPAGE is enabled, this becomes the PID of the worker thread. + * Else, -1. + */ +static int kdamond_pid __read_mostly =3D -1; +module_param(kdamond_pid, int, 0400); + +static struct damos_stat damon_hugepage_stat; +DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_hugepage_stat, + hugepage_tried_regions, hugepage_regions, quota_exceeds); + +static struct damon_attrs damon_hugepage_mon_attrs =3D { + .sample_interval =3D 5 * USEC_PER_MSEC, + .aggr_interval =3D 100 * USEC_PER_MSEC, + .ops_update_interval =3D 60 * USEC_PER_MSEC * MSEC_PER_SEC, + .min_nr_regions =3D 10, + .max_nr_regions =3D 1000, +}; +DEFINE_DAMON_MODULES_MON_ATTRS_PARAMS(damon_hugepage_mon_attrs); + +static struct damon_ctx *ctx; +static struct damon_target *target; + +static struct damos *damon_hugepage_new_scheme(void) +{ + struct damos_access_pattern pattern =3D { + /* Find regions having PMD_SIZE or larger size */ + .min_sz_region =3D PMD_SIZE, + .max_sz_region =3D ULONG_MAX, + .min_nr_accesses =3D 0, + .max_nr_accesses =3D UINT_MAX, + .min_age_region =3D min_age / + damon_hugepage_mon_attrs.aggr_interval, + .max_age_region =3D UINT_MAX, + }; + + return damon_new_scheme( + &pattern, + /* synchrounous partial collapse as soon as found */ + DAMOS_COLLAPSE, 0, + /* under the quota. */ + &damon_hugepage_quota, + &(struct damos_watermarks){}, NUMA_NO_NODE); +} + +static int damon_hugepage_apply_parameters(void) +{ + struct damon_ctx *param_ctx; + struct damon_target *param_target; + struct damos *scheme; + struct damos_quota_goal *goal; + struct pid *spid; + int err; + + err =3D damon_modules_new_vaddr_ctx_target(¶m_ctx, ¶m_target); + if (err) + return err; + + param_ctx->addr_unit =3D addr_unit; + param_ctx->min_region_sz =3D max(DAMON_MIN_REGION_SZ / addr_unit, 1); + + spid =3D find_get_pid(monitored_pid); + if (!spid) { + err =3D -EINVAL; + goto out; + } + + param_target->pid =3D spid; + + if (!damon_hugepage_mon_attrs.aggr_interval) { + err =3D -EINVAL; + goto out; + } + + err =3D damon_set_attrs(param_ctx, &damon_hugepage_mon_attrs); + if (err) + goto out; + + err =3D -ENOMEM; + scheme =3D damon_hugepage_new_scheme(); + if (!scheme) + goto out; + damon_set_schemes(param_ctx, &scheme, 1); + + goal =3D damos_new_quota_goal(DAMOS_QUOTA_HUGEPAGE, quota_percentage_huge= page); + if (!goal) + goto out; + damos_add_quota_goal(&scheme->quota, goal); + + if (quota_autotune_feedback) { + goal =3D damos_new_quota_goal(DAMOS_QUOTA_USER_INPUT, 10000); + if (!goal) + goto out; + goal->current_value =3D quota_autotune_feedback; + damos_add_quota_goal(&scheme->quota, goal); + } + + err =3D damon_commit_ctx(ctx, param_ctx); +out: + damon_destroy_ctx(param_ctx); + return err; +} + +static int damon_hugepage_handle_commit_inputs(void) +{ + int err; + + if (!commit_inputs) + return 0; + + err =3D damon_hugepage_apply_parameters(); + commit_inputs =3D false; + return err; +} + +static int damon_hugepage_damon_call_fn(void *arg) +{ + struct damon_ctx *c =3D arg; + struct damos *s; + + /* update the stats parameter */ + damon_for_each_scheme(s, c) + damon_hugepage_stat =3D s->stat; + + return damon_hugepage_handle_commit_inputs(); +} + +static struct damon_call_control call_control =3D { + .fn =3D damon_hugepage_damon_call_fn, + .repeat =3D true, +}; + +static int damon_hugepage_turn(bool on) +{ + int err; + + if (!on) { + err =3D damon_stop(&ctx, 1); + if (!err) + kdamond_pid =3D -1; + return err; + } + + err =3D damon_hugepage_apply_parameters(); + if (err) + return err; + + err =3D damon_start(&ctx, 1, true); + if (err) + return err; + kdamond_pid =3D damon_kdamond_pid(ctx); + if (kdamond_pid < 0) + return kdamond_pid; + return damon_call(ctx, &call_control); +} + +static int damon_hugepage_addr_unit_store(const char *val, + const struct kernel_param *kp) +{ + unsigned long input_addr_unit; + int err =3D kstrtoul(val, 0, &input_addr_unit); + + if (err) + return err; + if (!input_addr_unit) + return -EINVAL; + + addr_unit =3D input_addr_unit; + return 0; +} + +static const struct kernel_param_ops addr_unit_param_ops =3D { + .set =3D damon_hugepage_addr_unit_store, + .get =3D param_get_ulong, +}; + +module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600); +MODULE_PARM_DESC(addr_unit, + "Scale factor for DAMON_HUGEPAGE to ops address conversion (default: 1)"); + +static int damon_hugepage_enabled_store(const char *val, + const struct kernel_param *kp) +{ + bool is_enabled =3D enabled; + bool enable; + int err; + + err =3D kstrtobool(val, &enable); + if (err) + return err; + + if (is_enabled =3D=3D enable) + return 0; + + /* Called before init function. The function will handle this. */ + if (!damon_initialized()) + goto set_param_out; + + err =3D damon_hugepage_turn(enable); + if (err) + return err; + +set_param_out: + enabled =3D enable; + return err; +} + +static const struct kernel_param_ops enabled_param_ops =3D { + .set =3D damon_hugepage_enabled_store, + .get =3D param_get_bool, +}; + +module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); +MODULE_PARM_DESC(enabled, + "Enable or disable DAMON_HUGEPAGE (default: disabled)"); + +static int __init damon_hugepage_init(void) +{ + int err; + + if (!damon_initialized()) { + err =3D -ENOMEM; + goto out; + } + err =3D damon_modules_new_vaddr_ctx_target(&ctx, &target); + if (err) + goto out; + + call_control.data =3D ctx; + + /* 'enabled' has set before this function, probably via command line */ + if (enabled) + err =3D damon_hugepage_turn(true); + +out: + if (err && enabled) + enabled =3D false; + return err; +} + +module_init(damon_hugepage_init); --=20 2.43.0 From nobody Sun May 24 19:35:39 2026 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 824014028D2 for ; Fri, 22 May 2026 14:56:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.176.79.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779461765; cv=none; b=qIwj3Ck9u7tkP3synAF8tU6wDHfLS2ht1aq4DwFbEGzLCHySxspZHi1kP6mPseBktKmGKBGfvbfDkxyhOjLwB0sSnPCz8micHf6QsT+/f3x55NuKmLjczVb6pNOSaJn0XxOvHgp4cS4S3IBQTvkloUJXNdG3u/qk6d1Vz28R7+E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779461765; c=relaxed/simple; bh=Y2E3QYUE/omlVoaHS4iqzxl1aIXjpgNj2GecucvCqXI=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mE9kWf+IuC+ZstqCpnUJRVv4kdLUgQN9D3Z8YGzCnGC6PELO4E7jfCwgAJdz/ONCwa53GNtPIKv5VwNMQkha7q+h3IzogdQS9531mTb1HrIJh7XTVWiDaUuxovyfv8FTPJJl7H7rtCZhY3T10MJMmUN2ys22Sw58vVanr+AGeBg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com; spf=pass smtp.mailfrom=huawei-partners.com; arc=none smtp.client-ip=185.176.79.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei-partners.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei-partners.com Received: from mail.maildlp.com (unknown [172.18.224.150]) by frasgout.his.huawei.com (SkyGuard) with ESMTPS id 4gMSxW3fyczJ46Df; Fri, 22 May 2026 22:55:11 +0800 (CST) Received: from mscpeml500003.china.huawei.com (unknown [7.188.49.51]) by mail.maildlp.com (Postfix) with ESMTPS id 1DCAF40571; Fri, 22 May 2026 22:55:55 +0800 (CST) Received: from mscphis01197.huawei.com (10.123.65.218) by mscpeml500003.china.huawei.com (7.188.49.51) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 22 May 2026 17:55:54 +0300 From: To: , , , , , , , , , , Subject: [RFC PATCH v2 4/4] Documentation/admin-guide/mm/damon: add DAMON-based Hugepage Management documentation Date: Fri, 22 May 2026 14:55:18 +0000 Message-ID: <20260522145518.158910-5-gutierrez.asier@huawei-partners.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260522145518.158910-1-gutierrez.asier@huawei-partners.com> References: <20260522145518.158910-1-gutierrez.asier@huawei-partners.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: mscpeml100003.china.huawei.com (10.199.174.67) To mscpeml500003.china.huawei.com (7.188.49.51) Content-Type: text/plain; charset="utf-8" From: Asier Gutierrez Add documentation for the DAMON-based Hugepage Management (DAMON_HUGEPAGE) feature, which automatically manages huge pages by identifying cold memory regions and collapsing them back to regular pages. The documentation covers the module's features, operation, and all available module parameters. Signed-off-by: Asier Gutierrez --- .../admin-guide/mm/damon/hugepage.rst (new) | 258 ++++++++++++++++++ 1 file changed, 258 insertions(+) diff --git a/Documentation/admin-guide/mm/damon/hugepage.rst b/Documentatio= n/admin-guide/mm/damon/hugepage.rst new file mode 100644 index 000000000000..ee50cfa79281 --- /dev/null +++ b/Documentation/admin-guide/mm/damon/hugepage.rst @@ -0,0 +1,258 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +DAMON-based huge page collapsing +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +DAMON-based huge page collapsing (DAMON_HUGEPAGE) is a static kernel module +that aimed to collapse hot regions into huge pages. + +Where Proactive huge page collapsing is Required? +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The amount of available memory grows faster than the amount of TLB entries. +This leads to higher amount of TLB misses and excesive cycle wastes. Huge +pages are meant to solve this problem. However, huge pages usually lead to +memory fragmentation and memory waste. + +Collapsing selectively hot regions in a specific process can avoid big +memory fragmentation, while increasing TLB performance. + +DAMON_HUGEPAGE solves this by: + +- Identifying hot regions that have been accessed for a configured time +- Automatically collapsing the regions into huge pages back +- Auto tune the huge page usage ratio to meet desired targets +- Controlling the collapse rate with configurable quotas to avoid performa= nce + degradation + + +How It Works? +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +DAMON_HUGEPAGE uses kdamond to identify anonymous memory regions that are: + +1. Large enough to be backed by huge pages (``PMD_SIZE`` or larger) +2. Have been accessed for a configured time period + +Once identified, DAMON_HUGEPAGE triggers synchronous partial collapse of t= hose +regions. The collapse operation is controlled by quotas to limit the impac= t on +system performance. + +The module also supports automatic tuning of the collapse rate to achieve a +desired huge page usage ratio. Administrators can configure a target perce= ntage +of huge page usage vs total anonymous memory usage. + +Additionally, the module accepts manual feedback from system administrator= s to +adjust the effective quota level based on observed system behavior. + +Interface: Module Parameters +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + +To use this feature, you should first ensure your system is running on a k= ernel +that is built with ``CONFIG_DAMON_HUGEPAGE=3Dy``. + +To let sysadmins enable or disable it and tune for the given system, +DAMON_HUGEPAGE utilizes module parameters. That is, you can put +``damon_hugepage.=3D`` on the kernel boot command line o= r write +proper values to ``/sys/module/damon_hugepage/parameters/`` fil= es. + +Below are the description of each parameter. + +enabled +------- + +Enable or disable DAMON_HUGEPAGE. + +You can enable DAMON_HUGEPAGE by setting the value of this parameter as ``= Y``. +Setting it as ``N`` disables DAMON_HUGEPAGE. Note that DAMON_HUGEPAGE cou= ld do +no real monitoring and collapse due to the activation condition. + +commit_inputs +------------- + +Make DAMON_HUGEPAGE reads the input parameters again, except ``enabled``. + +Input parameters that updated while DAMON_HUGEPAGE is running are not appl= ied +by default. Once this parameter is set as ``Y``, DAMON_HUGEPAGE reads val= ues +of parametrs except ``enabled`` again. Once the re-reading is done, this +parameter is set as ``N``. If invalid parameters are found while the +re-reading, DAMON_HUGEPAGE will be disabled. + +Once ``Y`` is written to this parameter, the user must not write to any +parameters until reading ``commit_inputs`` again returns ``N``. If users +violate this rule, the kernel may exhibit undefined behavior. + +min_age +------- + +Time threshold for hot memory regions identification in microseconds. + +100 milliseconds by default. + +quota_ms +-------- + +Limit of time for the collapse in milliseconds. + +DAMON_HUGEPAGE tries to use only up to this time within a time window +(quota_reset_interval_ms) for trying collapse hot pages. This can be +used for limiting CPU consumption of DAMON_HUGEPAGE. If the value is zero= , the +limit is disabled. + +10 ms by default. + +quota_reset_interval_ms +----------------------- + +The time/size quota charge reset interval in milliseconds. + +The charget reset interval for the quota of time (quota_ms) and size +(quota_sz). That is, DAMON_HUGEPAGE does not try collapsing for more than +quota_ms milliseconds or quota_sz bytes within quota_reset_interval_ms +milliseconds. + +1 second by default. + +quota_autotune_feedback +----------------------- + +User-specifiable feedback for auto-tuning of the effective quota. + +While keeping the caps that set by other quotas, DAMON_HUGEPAGE automatica= lly +increases and decreases the effective level of the quota aiming receiving = this +feedback of value ``10,000`` from the user. DAMON_HUGEPAGE assumes the fe= edback +value and the quota are positively proportional. Value zero means disabli= ng +this auto-tuning feature. + +Disabled by default. + +monitored_pid +---------------- + +PID of the task that is going to be monitored for hot regions. + +quota_percentage_hugepage +---------------- + +Huge page consumption to total memory anonymous memory consumption ratio g= oal +in bp ``(10,000)``. DAMON_HUGEPAGE automatically increases and decreases p= age +collapse aggressiveness in order to achieve the given value. + +sample_interval +--------------- + +Sampling interval for the monitoring in microseconds. + +The sampling interval of DAMON for the cold memory monitoring. Please ref= er to +the DAMON documentation (:doc:`usage`) for more detail. + +aggr_interval +------------- + +Aggregation interval for the monitoring in microseconds. + +The aggregation interval of DAMON for the cold memory monitoring. Please +refer to the DAMON documentation (:doc:`usage`) for more detail. + +min_nr_regions +-------------- + +Minimum number of monitoring regions. + +The minimal number of monitoring regions of DAMON for the cold memory +monitoring. This can be used to set lower-bound of the monitoring quality. +But, setting this too high could result in increased monitoring overhead. +Please refer to the DAMON documentation (:doc:`usage`) for more detail. + +Note that this must be 3 or higher. Please refer to the :ref:`Monitoring +` section of the design document for the rationale +behind this lower bound. + +max_nr_regions +-------------- + +Maximum number of monitoring regions. + +The maximum number of monitoring regions of DAMON for the cold memory +monitoring. This can be used to set upper-bound of the monitoring overhea= d. +However, setting this too low could result in bad monitoring quality. Ple= ase +refer to the DAMON documentation (:doc:`usage`) for more detail. + +addr_unit +--------- + +A scale factor for memory addresses and bytes. + +This parameter is for setting and getting the :ref:`address unit +` parameter of the DAMON instance for DAMON_HUGEPA= GE. + +``monitor_region_start`` and ``monitor_region_end`` should be provided in = this +unit. For example, let's suppose ``addr_unit``, ``monitor_region_start`` = and +``monitor_region_end`` are set as ``1024``, ``0`` and ``10``, respectively. +Then DAMON_HUGEPAGE will work for 10 KiB length of physical address range = that +starts from address zero (``[0 * 1024, 10 * 1024)`` in bytes). + +``bytes_hugepage_tried_regions`` and ``bytes_hugepage_regions`` are also in +this unit. For example, let's suppose values of ``addr_unit``, +``bytes_hugepage_tried_regions`` and ``bytes_hugepage_regions`` are +``1048576``, ``42``, and ``32``, respectively. Then it means DAMON_HUGEPA= GE +tried to collapse 42 MiB memory and successfully collapse 32 MiB memory in +total. + +If unsure, use only the default value (``1``) and forget about this. + + +kdamond_pid +----------- + +PID of the DAMON thread. + +If DAMON_HUGEPAGE is enabled, this becomes the PID of the worker thread. = Else, +-1. + +nr_hugepage_tried_regions +------------------------ + +Number of memory regions that tried to be collapsed by DAMON_HUGEPAGE. + +bytes_hugepage_tried_regions +--------------------------- + +Total bytes of memory regions that tried to be collapsed by DAMON_HUGEPAGE. + +nr_hugepage_regions +-------------------- + +Number of memory regions that successfully be collapsed by DAMON_HUGEPAGE. + +bytes_hugepage_regions +----------------------- + +Total bytes of memory regions that successfully be collapsed by DAMON_HUGE= PAGE. + +nr_quota_exceeds +---------------- + +Number of times that the time/space quota limits have exceeded. + +Example +=3D=3D=3D=3D=3D=3D=3D + +Below runtime example commands make DAMON_HUGEPAGE to find memory regions = of=20 +the task with PID 1234 that have been accessed in the last 100 millseconds= or +more and pages out. The pagecollapsing is limited to be done only up to 1 = GiB +per second to avoid DAMON_HUGEPAGE consuming too much CPU time for the col= lapse +operation. :: + + # cd /sys/module/damon_hugepage/parameters + # echo 100000 > min_age + # echo $((1 * 1024 * 1024 * 1024)) > quota_sz + # echo 1000 > quota_reset_interval_ms + # echo 1234 > monitored_pid + # echo Y > enabled + +Note that this module (damon_hugepage) cannot run simultaneously with other +DAMON-based special-purpose modules. Refer to :ref:`DAMON design special +purpose modules exclusivity ` +for more details. --=20 2.43.0