lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240521023957.2587005-4-jaewon31.kim@samsung.com>
Date: Tue, 21 May 2024 11:39:50 +0900
From: Jaewon Kim <jaewon31.kim@...sung.com>
To: rppt@...nel.org, vbabka@...e.cz, akpm@...ux-foundation.org
Cc: linux-mm@...ck.org, linux-kernel@...r.kernel.org,
	jaewon31.kim@...il.com, Jaewon Kim <jaewon31.kim@...sung.com>
Subject: [RESEND PATCH 03/10] memblock: handle overlapped reserved memory
 region

It is not common, but defining an overlapped region is possible.
Actually memblock_add_range allows to overlap with existing ones.

The memsize currently does not handle this overlapped case. But this
patch tries to handle one overlapped case.

Here's the case.

There is an unknown memsize region, which means the region was removed
and not passed at bootloader stage. And there is a reserved memory
region defined in device tree which is overlapped with the unknown
region.

We expect that information in device tree make the unknown region clear.
This patch handle the overlapped region with following conditions.

1) The already existing overlapped region should be unknown and no-map.
2) The newly added region should have a name, and its region should be
same with or part of the existing one.

Here is an example.

Before this patch, memsize shows both overlapped region.

0x0ea000000-0x0ed900000 0x03900000 (   58368 KB ) nomap unusable overlapped
0x0ea000000-0x0f1400000 0x07400000 (  118784 KB ) nomap unusable unknown

After this patch, the overlapped region is named.

0x0ea000000-0x0ed900000 0x03900000 (   58368 KB ) nomap unusable overlapped
0x0e9b00000-0x0ea000000 0x00500000 (    5120 KB ) nomap unusable unknown

Signed-off-by: Jaewon Kim <jaewon31.kim@...sung.com>
---
 mm/memblock.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/mm/memblock.c b/mm/memblock.c
index 5204ee71ae29..4a0506e14025 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -2060,6 +2060,73 @@ static void __init_memblock memsize_get_valid_name(char *valid_name, const char
 	valid_name[val_size] = '\0';
 }
 
+static inline struct memsize_rgn_struct * __init_memblock memsize_get_new_rgn(void)
+{
+	if (memsize_rgn_count == ARRAY_SIZE(memsize_rgn)) {
+		pr_err("not enough space on memsize_rgn\n");
+		return NULL;
+	}
+	return &memsize_rgn[memsize_rgn_count++];
+}
+
+static bool __init_memblock memsize_update_nomap_region(const char *name, phys_addr_t base,
+					phys_addr_t size, bool nomap)
+{
+	int i;
+	struct memsize_rgn_struct *rmem_rgn, *new_rgn;
+
+	if (!name)
+		return false;
+
+	for (i = 0; i < memsize_rgn_count; i++)	{
+		rmem_rgn = &memsize_rgn[i];
+
+		if (!rmem_rgn->nomap)
+			continue;
+		if (strcmp(rmem_rgn->name, "unknown"))
+			continue;
+		if (base < rmem_rgn->base)
+			continue;
+		if (base + size > rmem_rgn->base + rmem_rgn->size)
+			continue;
+
+		if (base == rmem_rgn->base && size == rmem_rgn->size) {
+			memsize_get_valid_name(rmem_rgn->name, name);
+			return true;
+		}
+
+		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 && size < rmem_rgn->size) {
+			rmem_rgn->base = base + size;
+			rmem_rgn->size -= size;
+		} else if (base + size == rmem_rgn->base + rmem_rgn->size) {
+			rmem_rgn->size -= size;
+		} else {
+			new_rgn = memsize_get_new_rgn();
+			if (!new_rgn)
+				return true;
+			new_rgn->base = base + size;
+			new_rgn->size = (rmem_rgn->base + rmem_rgn->size)
+					- (base + size);
+			new_rgn->nomap = nomap;
+			new_rgn->reusable = false;
+			strscpy(new_rgn->name, "unknown", sizeof(new_rgn->name));
+			rmem_rgn->size = base - rmem_rgn->base;
+		}
+		return true;
+	}
+
+	return false;
+}
+
 void __init_memblock memblock_memsize_record(const char *name, phys_addr_t base,
 			     phys_addr_t size, bool nomap, bool reusable)
 {
@@ -2070,7 +2137,14 @@ void __init_memblock memblock_memsize_record(const char *name, phys_addr_t base,
 		pr_err("not enough space on memsize_rgn\n");
 		return;
 	}
-	rgn = &memsize_rgn[memsize_rgn_count++];
+
+	if (memsize_update_nomap_region(name, base, size, nomap))
+		return;
+
+	rgn = memsize_get_new_rgn();
+	if (!rgn)
+		return;
+
 	rgn->base = base;
 	rgn->size = size;
 	rgn->nomap = nomap;
-- 
2.25.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ