Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm/damon/core: support addr_unit on damon_find_biggest_system_ram()

damon_find_biggest_system_ram() sets an 'unsigned long' variable with
'resource_size_t' value. This is fundamentally wrong. On environments
such as ARM 32 bit machines having LPAE (Large Physical Address
Extensions), which DAMON supports, the size of 'unsigned long' may be
smaller than that of 'resource_size_t'. It is safe, though, since we
restrict the walk to be done only up to ULONG_MAX.

DAMON supports the address size gap using 'addr_unit'. We didn't add the
support to the function, just to make the initial support change small.
Now the support is reasonably settled. This kind of gap is only making
the code inconsistent and easy to be confused. Add the support of
'addr_unit' to the function, by letting callers pass the 'addr_unit' and
handling it in the function. All callers are passing 'addr_unit' 1,
though, to keep the old behavior.

[sj@kernel.org: verify found biggest system ram]
Link: https://lkml.kernel.org/r/20260317144725.88524-1-sj@kernel.org
Link: https://lkml.kernel.org/r/20260311052927.93921-3-sj@kernel.org
Signed-off-by: SeongJae Park <sj@kernel.org>
Cc: Yang yingliang <yangyingliang@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

SeongJae Park and committed by
Andrew Morton
b47dcc1a c63067e8

+23 -11
+23 -11
mm/damon/core.c
··· 3064 3064 3065 3065 static int walk_system_ram(struct resource *res, void *arg) 3066 3066 { 3067 - struct damon_addr_range *a = arg; 3067 + struct resource *a = arg; 3068 3068 3069 - if (a->end - a->start < resource_size(res)) { 3069 + if (resource_size(a) < resource_size(res)) { 3070 3070 a->start = res->start; 3071 - a->end = res->end + 1; 3071 + a->end = res->end; 3072 3072 } 3073 3073 return 0; 3074 + } 3075 + 3076 + static unsigned long damon_res_to_core_addr(resource_size_t ra, 3077 + unsigned long addr_unit) 3078 + { 3079 + /* 3080 + * Use div_u64() for avoiding linking errors related with __udivdi3, 3081 + * __aeabi_uldivmod, or similar problems. This should also improve the 3082 + * performance optimization (read div_u64() comment for the detail). 3083 + */ 3084 + if (sizeof(ra) == 8 && sizeof(addr_unit) == 4) 3085 + return div_u64(ra, addr_unit); 3086 + return ra / addr_unit; 3074 3087 } 3075 3088 3076 3089 /* ··· 3091 3078 * @start and @end, respectively. If no System RAM is found, returns false. 3092 3079 */ 3093 3080 static bool damon_find_biggest_system_ram(unsigned long *start, 3094 - unsigned long *end) 3081 + unsigned long *end, unsigned long addr_unit) 3095 3082 3096 3083 { 3097 - struct damon_addr_range arg = {}; 3084 + struct resource res = {}; 3098 3085 3099 - walk_system_ram_res(0, ULONG_MAX, &arg, walk_system_ram); 3100 - if (arg.end <= arg.start) 3086 + walk_system_ram_res(0, -1, &res, walk_system_ram); 3087 + *start = damon_res_to_core_addr(res.start, addr_unit); 3088 + *end = damon_res_to_core_addr(res.end + 1, addr_unit); 3089 + if (*end <= *start) 3101 3090 return false; 3102 - 3103 - *start = arg.start; 3104 - *end = arg.end; 3105 3091 return true; 3106 3092 } 3107 3093 ··· 3130 3118 return -EINVAL; 3131 3119 3132 3120 if (!*start && !*end && 3133 - !damon_find_biggest_system_ram(start, end)) 3121 + !damon_find_biggest_system_ram(start, end, 1)) 3134 3122 return -EINVAL; 3135 3123 3136 3124 addr_range.start = *start;