static int walk_system_ram(struct resource *res, void *arg)
{
- struct damon_addr_range *a = arg;
+ struct resource *a = arg;
- if (a->end - a->start < resource_size(res)) {
+ if (resource_size(a) < resource_size(res)) {
a->start = res->start;
- a->end = res->end + 1;
+ a->end = res->end;
}
return 0;
}
+static unsigned long damon_res_to_core_addr(resource_size_t ra,
+ unsigned long addr_unit)
+{
+ /*
+ * Use div_u64() for avoiding linking errors related with __udivdi3,
+ * __aeabi_uldivmod, or similar problems. This should also improve the
+ * performance optimization (read div_u64() comment for the detail).
+ */
+ if (sizeof(ra) == 8 && sizeof(addr_unit) == 4)
+ return div_u64(ra, addr_unit);
+ return ra / addr_unit;
+}
+
/*
* 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.
*/
static bool damon_find_biggest_system_ram(unsigned long *start,
- unsigned long *end)
+ unsigned long *end, unsigned long addr_unit)
{
- struct damon_addr_range arg = {};
+ struct resource res = {};
- walk_system_ram_res(0, ULONG_MAX, &arg, walk_system_ram);
- if (arg.end <= arg.start)
+ walk_system_ram_res(0, -1, &res, walk_system_ram);
+ *start = damon_res_to_core_addr(res.start, addr_unit);
+ *end = damon_res_to_core_addr(res.end + 1, addr_unit);
+ if (*end <= *start)
return false;
-
- *start = arg.start;
- *end = arg.end;
return true;
}
return -EINVAL;
if (!*start && !*end &&
- !damon_find_biggest_system_ram(start, end))
+ !damon_find_biggest_system_ram(start, end, 1))
return -EINVAL;
addr_range.start = *start;