[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <50142a29010463f436dc5c4feb540e5de3bb09df.1744175097.git.donettom@linux.ibm.com>
Date: Wed, 9 Apr 2025 10:57:56 +0530
From: Donet Tom <donettom@...ux.ibm.com>
To: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
linux-kernel@...r.kernel.org, David Hildenbrand <david@...hat.com>,
Andrew Morton <akpm@...ux-foundation.org>, linux-mm@...ck.org,
Mike Rapoport <rppt@...nel.org>
Cc: Ritesh Harjani <ritesh.list@...il.com>, rafael@...nel.org,
Danilo Krummrich <dakr@...nel.org>, Donet Tom <donettom@...ux.ibm.com>
Subject: [PATCH 1/2] mm/memblock: Added a New Memblock Function to Check if the Current Node's Memblock Region Intersects with a Memory Block
A new function, curr_node_memblock_intersect_memory_block, has been
added to check if the current node's NID intersects with a memory block.
This function takes the start and end PFN of a memory block, along with
the node ID being registered. It then finds the memblock region of the
current node and check if the passed memory block intersects with it. If
there is an intersection, the function returns true; otherwise, itreturns
false.
There are two scenarios to consider during the search:
1. The memory block size is greater than the memblock region size.
This means that multiple memblocks can be present within a single
memory block. If the start or end of the memblock is within the
start and end of the memory block, it indicates that the memblock
is part of that memory block. Therefore, the memory block can be
added to the node where the memblock resides.
2. The memory block size is less than or equal to the memblock size
This means that multiple memory blocks can be part of a single memblock
region. If the start or end of the memory block is within the start and
end of the memblock, it indicates that the memory block is part of the
memblock. Therefore, the memory block can be added to the node where
the memblock resides.
In the current implementation, during node device initialization, to
find the memory block NID, it iterates over each PFN of the memory
block until it finds a match. On large systems, this can take a
long time.
With this function, the boot time is reduced.
Boot time without this function - 32TB RAM
==========================================
Startup finished in 1min 12.413s (kernel)
Boot time with this function - 32TB RAM
========================================
Startup finished in 18.031s (kernel)
Signed-off-by: Donet Tom <donettom@...ux.ibm.com>
---
include/linux/memblock.h | 2 ++
mm/memblock.c | 67 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index ef5a1ecc6e59..db87f7daa46c 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -277,6 +277,8 @@ static inline bool memblock_is_driver_managed(struct memblock_region *m)
int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
unsigned long *end_pfn);
+bool curr_node_memblock_intersect_memory_block(unsigned long start_pfn,
+ unsigned long end_pfn, int curr_nid);
void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
unsigned long *out_end_pfn, int *out_nid);
diff --git a/mm/memblock.c b/mm/memblock.c
index 0a53db4d9f7b..570ab7ac4dce 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -6,6 +6,8 @@
* Copyright (C) 2001 Peter Bergner.
*/
+#include "linux/stddef.h"
+#include "linux/types.h"
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
@@ -17,7 +19,7 @@
#include <linux/seq_file.h>
#include <linux/memblock.h>
#include <linux/mutex.h>
-
+#include <linux/minmax.h>
#include <asm/sections.h>
#include <linux/io.h>
@@ -1909,6 +1911,69 @@ bool __init_memblock memblock_is_map_memory(phys_addr_t addr)
return !memblock_is_nomap(&memblock.memory.regions[i]);
}
+/**
+ * curr_node_memblock_intersect_memory_block: checks if the current node's memblock
+ * region intersects with the memory block.
+ * @start_pfn: memory block start pfn
+ * @end_pfn: memory block end_pfn
+ * @curr_nid: Current node
+ *
+ * This function takes the start and end PFN of a memory block, as well as the node ID
+ * that is being registered. It then finds the memblock region of the current node and
+ * checks if the passed memory block intersects with the memblock. If there is an
+ * intersection, the function returns true; otherwise, it returns false.
+ *
+ * Return:
+ * If the current node's memblock region intersects with the memory block, it returns
+ * true; otherwise, it returns false.
+ */
+bool __init_memblock curr_node_memblock_intersect_memory_block(unsigned long start_pfn,
+ unsigned long end_pfn, int curr_nid)
+{
+ struct memblock_region *r;
+ unsigned long r_start, r_end;
+ unsigned long size = end_pfn - start_pfn;
+ unsigned long r_size = 0;
+
+ for_each_mem_region(r) {
+ r_start = PFN_DOWN(r->base);
+ r_end = PFN_DOWN(r->base + r->size);
+ r_size = r_end - r_start;
+
+ if (r->nid == curr_nid) {
+ if (size > r_size) {
+ /*
+ * The memory block size is greater than the memblock
+ * region size, meaning multiple memblocks can be present
+ * within a single memory block. If the memblock's start
+ * or end is within the memory block's start and end, It
+ * indicates that the memblock is part of this memory block.
+ * Therefore, the memory block can be added to the node
+ * where the memblock resides.
+ */
+ if (in_range(r_start, start_pfn, size) ||
+ in_range(r_end, start_pfn, size))
+ return true;
+ } else {
+ /*
+ * The memory block size is less than or equal to the
+ * memblock size, meaning multiple memory blocks can
+ * be part of a single memblock region. If the memory
+ * block's start or end is within the memblock's start
+ * and end, it indicates that the memory block is part of
+ * the memblock. Therefore, the memory block can be added
+ * to the node where the memblock resides.
+ */
+ if (in_range(start_pfn, r_start, r_size) ||
+ in_range(end_pfn, r_start, r_size))
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
unsigned long *start_pfn, unsigned long *end_pfn)
{
--
2.48.1
Powered by blists - more mailing lists