From f3f83a6edfc535e18f3de9ab8aa56fb7b4edb3f6 Mon Sep 17 00:00:00 2001 From: Jaewon Kim Date: Thu, 20 Apr 2023 12:17:49 +0900 Subject: [PATCH] ANDROID: memblock: take a region intersecting an unknown region There is case where reserved regions overlapped with already checked as unknown regions. To get more information of the name, size, so far we allowed only regions which are exactly matching with or located within the unknown region. For a region intersecting an unknown region, we did not take and just showed that duplicated information. So total size was not perfect. To fix this, let's allow to take even the intersecting region. Bug: 340432773 Signed-off-by: Jaewon Kim Link: https://lore.kernel.org/linux-mm/20240521023957.2587005-5-jaewon31.kim@samsung.com/ Change-Id: I3ab0bdcea5e9122f59b87e13afafc2c9b9606295 --- mm/memblock.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/mm/memblock.c b/mm/memblock.c index 04925e35eedd..28686dcb8b61 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -2090,20 +2090,54 @@ static bool __init_memblock memsize_update_nomap_region(const char *name, phys_a for (i = 0; i < memsize_rgn_count; i++) { rmem_rgn = &memsize_rgn[i]; + /* skip either !nomap, !unknown, !overlap */ if (!rmem_rgn->nomap) continue; if (strcmp(rmem_rgn->name, "unknown")) continue; - if (base < rmem_rgn->base) + if (base + size <= rmem_rgn->base) continue; - if (base + size > rmem_rgn->base + rmem_rgn->size) + if (base >= rmem_rgn->base + rmem_rgn->size) continue; + /* exactly same */ if (base == rmem_rgn->base && size == rmem_rgn->size) { memsize_get_valid_name(rmem_rgn->name, name); return true; } + /* bigger */ + if (base <= rmem_rgn->base && + base + size >= rmem_rgn->base + rmem_rgn->size) { + memsize_get_valid_name(rmem_rgn->name, name); + rmem_rgn->base = base; + rmem_rgn->size = size; + return true; + } + + /* intersect */ + if (base < rmem_rgn->base || + base + size > rmem_rgn->base + rmem_rgn->size) { + new_rgn = memsize_get_new_rgn(); + if (!new_rgn) + return true; + new_rgn->base = base; + new_rgn->size = size; + new_rgn->nomap = nomap; + new_rgn->reusable = false; + memsize_get_valid_name(new_rgn->name, name); + + if (base < rmem_rgn->base) { + rmem_rgn->size -= base + size - rmem_rgn->base; + rmem_rgn->base = base + size; + } else { + rmem_rgn->size -= rmem_rgn->base + + rmem_rgn->size - base; + } + return true; + } + + /* smaller */ new_rgn = memsize_get_new_rgn(); if (!new_rgn) return true;