[PATCH 1/7] mm/damon: introduce damon_set_region_system_rams_default()

SeongJae Park
2026-04-29T04:12:37Z

damon_set_region_biggest_system_ram_default() sets the monitoring target
region as the caller requested. If the caller didn't specify the
region, it finds the biggest System RAM of the system and sets it as the
target region. When there are more than one considerable size of System
RAM resources in the system, the default target setup makes no sense.
Introduce a variant, namely damon_set_region_system_rams_default(). It
sets a physical address range that covers all System RAM resources as
the default target region.

Signed-off-by: SeongJae Park <sj@kernel.org>
---
include/linux/damon.h | 5 +++
mm/damon/core.c | 77 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/include/linux/damon.h b/include/linux/damon.h
index f2370a3a4a9a3..f656908b2d389 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -1010,6 +1010,11 @@ int damon_kdamond_pid(struct damon_ctx *ctx);
int damon_call(struct damon_ctx *ctx, struct damon_call_control *control);
int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control);

+int damon_set_region_system_rams_default(struct damon_target *t,
+ unsigned long *start, unsigned long *end,
+ unsigned long addr_unit,
+ unsigned long min_region_sz);
+
int damon_set_region_biggest_system_ram_default(struct damon_target *t,
unsigned long *start, unsigned long *end,
unsigned long addr_unit,
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 05e4bef367dbf..980a31cd3498e 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -3328,14 +3328,20 @@ static int kdamond_fn(void *data)
return 0;
}

-static int walk_system_ram(struct resource *res, void *arg)
+struct damon_system_ram_range_walk_arg {
+ bool walked;
+ struct resource res;
+};
+
+static int damon_system_ram_walk_fn(struct resource *res, void *arg)
{
- struct resource *a = arg;
+ struct damon_system_ram_range_walk_arg *a = arg;

- if (resource_size(a) < resource_size(res)) {
- a->start = res->start;
- a->end = res->end;
+ if (!a->walked) {
+ a->walked = true;
+ a->res.start = res->start;
}
+ a->res.end = res->end;
return 0;
}

@@ -3352,6 +3358,67 @@ static unsigned long damon_res_to_core_addr(resource_size_t ra,
return ra / addr_unit;
}

+static bool damon_find_system_rams_range(unsigned long *start,
+ unsigned long *end, unsigned long addr_unit)
+{
+ struct damon_system_ram_range_walk_arg arg = {};
+
+ walk_system_ram_res(0, -1, &arg, damon_system_ram_walk_fn);
+ if (!arg.walked)
+ return false;
+ *start = damon_res_to_core_addr(arg.res.start, addr_unit);
+ *end = damon_res_to_core_addr(arg.res.end + 1, addr_unit);
+ if (*end <= *start)
+ return false;
+ return true;
+}
+
+/**
+ * damon_set_region_system_rams_default() - Set the region of the given
+ * monitoring target as requested, or to cover all 'System RAM' resources.
+ * @t: The monitoring target to set the region.
+ * @start: The pointer to the start address of the region.
+ * @end: The pointer to the end address of the region.
+ * @addr_unit: The address unit for the damon_ctx of @t.
+ * @min_region_sz: Minimum region size.
+ *
+ * This function sets the region of @t as requested by @start and @end. If the
+ * values of @start and @end are zero, however, this function finds 'System
+ * RAM' resources and sets the region to cover all the resource. In the latter
+ * case, this function saves the start and the end addresseses of the first and
+ * the last resources in @start and @end, respectively.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+int damon_set_region_system_rams_default(struct damon_target *t,
+ unsigned long *start, unsigned long *end,
+ unsigned long addr_unit, unsigned long min_region_sz)
+{
+ struct damon_addr_range addr_range;
+
+ if (*start > *end)
+ return -EINVAL;
+
+ if (!*start && !*end &&
+ !damon_find_system_rams_range(start, end, addr_unit))
+ return -EINVAL;
+
+ addr_range.start = *start;
+ addr_range.end = *end;
+ return damon_set_regions(t, &addr_range, 1, min_region_sz);
+}
+
+static int walk_system_ram(struct resource *res, void *arg)
+{
+ struct resource *a = arg;
+
+ if (resource_size(a) < resource_size(res)) {
+ a->start = res->start;
+ a->end = res->end;
+ }
+ return 0;
+}
+
/*
* Find biggest 'System RAM' resource and store its start and end address in
* @start and @end, respectively. If no System RAM is found, returns false.
--
2.47.3