aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
Diffstat (limited to 'mm')
-rw-r--r--mm/damon/core.c77
1 files changed, 72 insertions, 5 deletions
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 @@ done:
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.