From nobody Mon Jun 8 08:36:17 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 033393264CA for ; Thu, 4 Jun 2026 15:19:39 +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=1780586383; cv=none; b=fQnRNdnU0qjKY3XkQc9CHKylG1SWScTGlgybQ1plWNdn/4Pio+1yI0lYuXaUr8FNhCim932ZvaaciJplNWZhVLdSgOuap9m91OLd5uls/littNuBJ5bYoaEZnppwPTfaTpBNARUnqWzd4m6A6tzz42eID9FPm5fcQOE4GvWTpgY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780586383; c=relaxed/simple; bh=i4gvrQNNK6+MMsCQGn+t9qmcYrXvz2Yw2qMrW6EEorw=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ok4EEQlfK0fqqfwT4gLJGobv1JoJ4uQQhpD1XT1rQ2WyO4rZ+evV44+BlE0GfswSp5HpDFdpFNlHyC/9ikqLtrD3UcCswAgQQstiFp1W9/85A4GuQ6hXGck4OJqtO5jg+ndAHb0MEYVf9aMMRBbqnrgJjb/4vxWVbjoSrAwh0EA= 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 4gWSW75cDQzHnGjF; Thu, 4 Jun 2026 23:03:31 +0800 (CST) Received: from mscpeml500003.china.huawei.com (unknown [7.188.49.51]) by mail.maildlp.com (Postfix) with ESMTPS id 78C9A40569; Thu, 4 Jun 2026 23:04:25 +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; Thu, 4 Jun 2026 18:04:25 +0300 From: To: , , , , , , , , , , Subject: [RFC PATCH v3 1/4] mm/damon: Introduce DAMOS_QUOTA_HUGEPAGE auto tuning Date: Thu, 4 Jun 2026 15:03:34 +0000 Message-ID: <20260604150338.501128-2-gutierrez.asier@huawei-partners.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260604150338.501128-1-gutierrez.asier@huawei-partners.com> References: <20260604150338.501128-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 | 14 ++++++++++++++ 2 files changed, 15 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..7fc7477a353a 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2536,6 +2536,17 @@ static unsigned int damos_get_in_active_mem_bp(bool = active_ratio) return mult_frac(inactive, 10000, total); } =20 +static unsigned int damos_hugepage_mem_bp(void) +{ + unsigned long thp, total; + + thp =3D global_node_page_state(NR_ANON_THPS) + + global_node_page_state(NR_SHMEM_THPS) + + global_node_page_state(NR_FILE_THPS); + total =3D totalram_pages() - global_zone_page_state(NR_FREE_PAGES); + return mult_frac(thp, 10000, total); +} + static void damos_set_quota_goal_current_value(struct damon_ctx *c, struct damos *s, struct damos_quota_goal *goal) { @@ -2567,6 +2578,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_hugepage_mem_bp(); + break; default: break; } --=20 2.43.0 From nobody Mon Jun 8 08:36:17 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 4B83C33066D for ; Thu, 4 Jun 2026 15:24:23 +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=1780586664; cv=none; b=GKb55ViI67+1QhIC2m2z3pYBUidq3N+XN3zypzbyxtjpweZOpGNvjjK5b+6O1xLlCV/I2gjvgkI1W0cPFdZ0rl4ib63vYL6okWhzhT801twHGCGErly30Xid0jVkmjXbJF62nPfvabbjZShvRcB7cZbRyiBozUBxFgclAbm1qpI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780586664; c=relaxed/simple; bh=jPkEvV1MZRuNOhS2SOpYPLhB7spnLz/MN9mb0VrENG0=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kAG4BufOuPwW9O6vFpU2uGrnSqSpgMOHzzdMk9Am1KLxy0USGyxcMUt/2MqiltAL0ZbrIjjbZNHljbMdEFsSz43R9WXu6wYesstvUBFJ/uCoOJrtNN/fkrYZ0zP+XEJHfLKBhVpYUbykKKvsGoPH/vEtB2Z1sU5EudH1qwv01Ew= 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 4gWSX56FnjzJ468x; Thu, 4 Jun 2026 23:04:21 +0800 (CST) Received: from mscpeml500003.china.huawei.com (unknown [7.188.49.51]) by mail.maildlp.com (Postfix) with ESMTPS id 8E64D40569; Thu, 4 Jun 2026 23:04:25 +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; Thu, 4 Jun 2026 18:04:25 +0300 From: To: , , , , , , , , , , Subject: [RFC PATCH v3 2/4] mm/damon: Generalize ctx_target creation for damon_ops_id and add vaddr support Date: Thu, 4 Jun 2026 15:03:35 +0000 Message-ID: <20260604150338.501128-3-gutierrez.asier@huawei-partners.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260604150338.501128-1-gutierrez.asier@huawei-partners.com> References: <20260604150338.501128-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 | 31 +++++++++++++++++++++++++++---- mm/damon/modules-common.h | 3 +++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/mm/damon/modules-common.c b/mm/damon/modules-common.c index 86d58f8c4f63..9b0cc80378f8 100644 --- a/mm/damon/modules-common.c +++ b/mm/damon/modules-common.c @@ -10,12 +10,13 @@ #include "modules-common.h" =20 /* - * Allocate, set, and return a DAMON context for the physical address spac= e. + * Allocate, set, and return a DAMON context. * @ctxp: Pointer to save the point to the newly created context * @targetp: Pointer to save the point to the newly created target + * id: DAMOS op id. It can be VADDR or PADDR */ -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 +25,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 +41,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 Mon Jun 8 08:36:17 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 45A54334C1F for ; Thu, 4 Jun 2026 15:24:39 +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=1780586681; cv=none; b=j5bBD/5dt/WcROK7UPkfvj0u4vOzdqpXjMlfL/S8K3Xwp+NhLc0VeHl8g+kbXq+QEzflOrojvf5r+neDktYulFgx0dyPoLRgpXnGKTfjGsWMqs3mxMJV6CvmzSs8AnmkiuzW2SgyAK4PwwafoZhRE9Lg4bTI6viIgOraKFryk8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780586681; c=relaxed/simple; bh=BuDDOkvu9teO1TboNb2iPY2PuBn5dU462SQmNMRS3R4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sXSOglq9NygSk4eMAEYSNwH/oEgAbP92DBz4ixWYwbrqBkAwgoisqjz4tTz4agKvdKSNjRP8t7RbXnvS8ZF3tuj4fCdi/isnWY8GQ/BRjuLrtKZZAJ46VoDLl5l1Mv8sBMn3WnHYYM/d5/mhnegf216nfKzDMvjcLFgVfcsuAS8= 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 4gWSW76vkszHnGjM; Thu, 4 Jun 2026 23:03:31 +0800 (CST) Received: from mscpeml500003.china.huawei.com (unknown [7.188.49.51]) by mail.maildlp.com (Postfix) with ESMTPS id A381740569; Thu, 4 Jun 2026 23:04:25 +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; Thu, 4 Jun 2026 18:04:25 +0300 From: To: , , , , , , , , , , Subject: [RFC PATCH v3 3/4] mm/damon: introduce DAMON_HUGEPAGE for hot region hugepage collapsing Date: Thu, 4 Jun 2026 15:03:36 +0000 Message-ID: <20260604150338.501128-4-gutierrez.asier@huawei-partners.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260604150338.501128-1-gutierrez.asier@huawei-partners.com> References: <20260604150338.501128-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 (SAMPLE_DAMON_HUGEPAGE) which collapses hot regions into huge pages. SAMPLE_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. SAMPLE_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/Makefile | 8 +- samples/damon/Kconfig | 12 ++ samples/damon/Makefile | 2 + samples/damon/hugepage.c (new) | 350 +++++++++++++++++++++++++++++++++ 4 files changed, 368 insertions(+), 4 deletions(-) diff --git a/mm/damon/Makefile b/mm/damon/Makefile index d8d6bf5f8bff..16459ce40304 100644 --- a/mm/damon/Makefile +++ b/mm/damon/Makefile @@ -1,9 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 =20 -obj-y :=3D core.o +obj-y :=3D core.o modules-common.o obj-$(CONFIG_DAMON_VADDR) +=3D ops-common.o vaddr.o obj-$(CONFIG_DAMON_PADDR) +=3D ops-common.o paddr.o 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_RECLAIM) +=3D reclaim.o +obj-$(CONFIG_DAMON_LRU_SORT) +=3D lru_sort.o +obj-$(CONFIG_DAMON_STAT) +=3D stat.o diff --git a/samples/damon/Kconfig b/samples/damon/Kconfig index cbf96fd8a8bf..512f150aaabb 100644 --- a/samples/damon/Kconfig +++ b/samples/damon/Kconfig @@ -40,4 +40,16 @@ config SAMPLE_DAMON_MTIER =20 If unsure, say N. =20 +config SAMPLE_DAMON_HUGEPAGE + bool "Build DAMON-based collapse of hot regions (SAMPLE_DAMON_HUGEPAGE)" + depends on DAMON && DAMON_VADDR + help + This module monitors a certain PID provided by the user through + monitored_pid attribute. Hot regions are determined by DAMON-based + sampling. Collapsing occurs according to the quota goal using total + memory usage to huge page usage ratio. The ratio is set by the user + through a module attribute. + + If unsure, say N. + endmenu diff --git a/samples/damon/Makefile b/samples/damon/Makefile index 72f68cbf422a..f90845faec85 100644 --- a/samples/damon/Makefile +++ b/samples/damon/Makefile @@ -3,3 +3,5 @@ obj-$(CONFIG_SAMPLE_DAMON_WSSE) +=3D wsse.o obj-$(CONFIG_SAMPLE_DAMON_PRCL) +=3D prcl.o obj-$(CONFIG_SAMPLE_DAMON_MTIER) +=3D mtier.o +obj-$(CONFIG_SAMPLE_DAMON_HUGEPAGE) +=3D hugepage.o +ccflags-$(CONFIG_SAMPLE_DAMON_HUGEPAGE) +=3D -I$(srctree)/mm/damon diff --git a/samples/damon/hugepage.c b/samples/damon/hugepage.c new file mode 100644 index 000000000000..e24562c92348 --- /dev/null +++ b/samples/damon/hugepage.c @@ -0,0 +1,350 @@ +// 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 unsigned 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; + // align power of two + param_ctx->min_region_sz =3D max(DAMON_MIN_REGION_SZ / ALIGN(addr_unit, 2= ), 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; + + /* Monitored process may have exited. In that case, ctx->kdamon is set */ + /* to NULL. If enabled is set to 'off' through sysfs, we just set the */ + /* params and exit */ + if (!damon_is_running(ctx) && !enable) + goto set_param_out; + + /* 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 Mon Jun 8 08:36:17 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 4B8F2331A65 for ; Thu, 4 Jun 2026 15:24:23 +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=1780586665; cv=none; b=j669jRh/tZEqzuHA34c7vD/ua8c2AHXWBMjG0gH1VIF7+yG9Ccb2YWfJUe5xs53Y5PWDlULLR+XawHv5wi9TnvVDMO4vdatvShe4/hF6IuKILbZgEDH1dO0yh7Qp5qdVWf6JihUSNG+G+8k27q2gimoPZJQWd8aNeRLhm5rfRZE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780586665; c=relaxed/simple; bh=Rs7GhA5g+RkzcQQ+p2pjiZs3mso45DT8aIpre/DQK1g=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=STlTLWIRkeekm3bV+vDjf6Qpb8Et6wseBRNP6McYbWvYD9V5Gf/U6/Fl2gxCukVJDwxr1s/GIm97WxH/aj8ZxRYa5OE+o99wOfZt+SVkqVJ0+WjlaiHSagM/zkVXsSl4dnZ+nlx180xSVgQkYuUbF3x547Trq09yyiK8588V3T8= 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 4gWSX60SCWzJ468w; Thu, 4 Jun 2026 23:04:22 +0800 (CST) Received: from mscpeml500003.china.huawei.com (unknown [7.188.49.51]) by mail.maildlp.com (Postfix) with ESMTPS id BAB9A4057A; Thu, 4 Jun 2026 23:04:25 +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; Thu, 4 Jun 2026 18:04:25 +0300 From: To: , , , , , , , , , , Subject: [RFC PATCH v3 4/4] Documentation/admin-guide/mm/damon: add DAMON-based Hugepage Management Date: Thu, 4 Jun 2026 15:03:37 +0000 Message-ID: <20260604150338.501128-5-gutierrez.asier@huawei-partners.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260604150338.501128-1-gutierrez.asier@huawei-partners.com> References: <20260604150338.501128-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 (SAMPLE_DAMON_HUGEPAGE) feature, which automatically manages huge pages by identifying hot 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) | 271 ++++++++++++++++++ 1 file changed, 271 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..86104aaa4d1c --- /dev/null +++ b/Documentation/admin-guide/mm/damon/hugepage.rst @@ -0,0 +1,271 @@ +=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 +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=3D= =3D=3D=3D=3D=3D=3D=3D=3D + +DAMON-based huge page collapsing (SAMPLE_DAMON_HUGEPAGE) is a static kernel +module that aims 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=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 excessive 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. + +SAMPLE_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 + +SAMPLE_DAMON_HUGEPAGE uses kdamond to identify anonymous memory regions th= at +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, SAMPLE_DAMON_HUGEPAGE triggers synchronous partial collap= se +of those regions. The collapse operation is controlled by quotas to limit = the +impact 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, +SAMPLE_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 SAMPLE_DAMON_HUGEPAGE. + +You can enable SAMPLE_DAMON_HUGEPAGE by setting the value of this paramete= r as ``Y``. +Setting it as ``N`` disables SAMPLE_DAMON_HUGEPAGE. Note that SAMPLE_DAMO= N_HUGEPAGE +could do no real monitoring and collapse due to the activation condition. + +commit_inputs +------------- + +Make SAMPLE_DAMON_HUGEPAGE reads the input parameters again, except ``enab= led``. + +Input parameters that updated while SAMPLE_DAMON_HUGEPAGE is running are +not applied by default. Once this parameter is set as ``Y``, +SAMPLE_DAMON_HUGEPAGE reads values of parameters except ``enabled`` again. +Once the re-reading is done, this parameter is set as ``N``. If invalid +parameters are found while the re-reading, SAMPLE_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. + +SAMPLE_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 SAMPLE_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, SAMPLE_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_sz +-------- + +Limit of size of memory for the reclamation in bytes. + +SAMPLE_DAMON_HUGEPAGE charges amount of memory which it tried to collapse +regions into huge pages within a time window (quota_reset_interval_ms) and +makes no more than this limit is tried. This can be used for limiting +consumption of CPU and IO. If this value is zero, the limit is disabled. + +128 MiB by default. + +quota_autotune_feedback +----------------------- + +User-specifiable feedback for auto-tuning of the effective quota. + +While keeping the caps that set by other quotas, SAMPLE_DAMON_HUGEPAGE +automatically increases and decreases the effective level of the quota +aiming receiving this feedback of value ``10,000`` from the user. +SAMPLE_DAMON_HUGEPAGE assumes the feedback value and the quota are positiv= ely +proportional. Value zero means disabling 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)``. SAMPLE_DAMON_HUGEPAGE automatically increases and +decreases page 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 hot memory monitoring. Please refe= r 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 hot 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 hot 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 +SAMPLE_DAMON_HUGEPAGE. + +``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 SAMPLE_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 +SAMPLE_DAMON_HUGEPAGE tried to collapse 42 MiB memory and successfully col= lapse +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 SAMPLE_DAMON_HUGEPAGE is enabled, this becomes the PID of the worker th= read. +Else, -1. + +nr_hugepage_tried_regions +------------------------- + +Number of memory regions that tried to be collapsed by SAMPLE_DAMON_HUGEPA= GE. + +bytes_hugepage_tried_regions +---------------------------- + +Total bytes of memory regions that tried to be collapsed by SAMPLE_DAMON_H= UGEPAGE. + +nr_hugepage_regions +-------------------- + +Number of memory regions that successfully be collapsed by SAMPLE_DAMON_HU= GEPAGE. + +bytes_hugepage_regions +----------------------- + +Total bytes of memory regions that successfully be collapsed by SAMPLE_DAM= ON_HUGEPAGE. + +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 SAMPLE_DAMON_HUGEPAGE to find memory +regions of the task with PID 1234 that have been accessed in the last 100 +milliseconds or more and collpases those pages into huge pages. The page +collapsing is limited to be done only up to 1 GiB per second to avoid +SAMPLE_DAMON_HUGEPAGE consuming too much CPU time for the collapse operati= on. :: + + # 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 (SAMPLE_DAMON_HUGEPAGE) cannot run simultaneously +with other DAMON-based special-purpose modules. Refer to + :ref:`DAMON design special purpose modules exclusivity + ` for more details. \ No newline at end of file --=20 2.43.0