From: Alexander Graf <graf@amazon.com>
To: <linux-kernel@vger.kernel.org>
Cc: <linux-trace-kernel@vger.kernel.org>, <linux-mm@kvack.org>,
<devicetree@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<kexec@lists.infradead.org>, <linux-doc@vger.kernel.org>,
<x86@kernel.org>, Eric Biederman <ebiederm@xmission.com>,
"H. Peter Anvin" <hpa@zytor.com>,
Andy Lutomirski <luto@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
"Rob Herring" <robh+dt@kernel.org>,
Steven Rostedt <rostedt@goodmis.org>,
"Andrew Morton" <akpm@linux-foundation.org>,
Mark Rutland <mark.rutland@arm.com>,
"Tom Lendacky" <thomas.lendacky@amd.com>,
Ashish Kalra <ashish.kalra@amd.com>,
James Gowans <jgowans@amazon.com>,
Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>,
<arnd@arndb.de>, <pbonzini@redhat.com>,
<madvenka@linux.microsoft.com>,
Anthony Yznaga <anthony.yznaga@oracle.com>,
Usama Arif <usama.arif@bytedance.com>,
David Woodhouse <dwmw@amazon.co.uk>,
Benjamin Herrenschmidt <benh@kernel.crashing.org>
Subject: [PATCH v2 01/17] mm,memblock: Add support for scratch memory
Date: Fri, 22 Dec 2023 19:35:51 +0000 [thread overview]
Message-ID: <20231222193607.15474-2-graf@amazon.com> (raw)
In-Reply-To: <20231222193607.15474-1-graf@amazon.com>
With KHO (Kexec HandOver), we need a way to ensure that the new kernel
does not allocate memory on top of any memory regions that the previous
kernel was handing over. But to know where those are, we need to include
them in the reserved memblocks array which may not be big enough to hold
all allocations. To resize the array, we need to allocate memory. That
brings us into a catch 22 situation.
The solution to that is the scratch region: a safe region to operate in.
KHO provides a "scratch region" as part of its metadata. This scratch
region is a single, contiguous memory block that we know does not
contain any KHO allocations. We can exclusively allocate from there until
we finish kernel initialization to a point where it knows about all the
KHO memory reservations. We introduce a new memblock_set_scratch_only()
function that allows KHO to indicate that any memblock allocation must
happen from the scratch region.
Later, we may want to perform another KHO kexec. For that, we reuse the
same scratch region. To ensure that no eventually handed over data gets
allocated inside that scratch region, we flip the semantics of the scratch
region with memblock_clear_scratch_only(): After that call, no allocations
may happen from scratch memblock regions. We will lift that restriction
in the next patch.
Signed-off-by: Alexander Graf <graf@amazon.com>
---
include/linux/memblock.h | 19 +++++++++++++
mm/Kconfig | 4 +++
mm/memblock.c | 61 +++++++++++++++++++++++++++++++++++++++-
3 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index ae3bde302f70..14043f5b696f 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -42,6 +42,10 @@ extern unsigned long long max_possible_pfn;
* kernel resource tree.
* @MEMBLOCK_RSRV_NOINIT: memory region for which struct pages are
* not initialized (only for reserved regions).
+ * @MEMBLOCK_SCRATCH: memory region that kexec can pass to the next kernel in
+ * handover mode. During early boot, we do not know about all memory reservations
+ * yet, so we get scratch memory from the previous kernel that we know is good
+ * to use. It is the only memory that allocations may happen from in this phase.
*/
enum memblock_flags {
MEMBLOCK_NONE = 0x0, /* No special request */
@@ -50,6 +54,7 @@ enum memblock_flags {
MEMBLOCK_NOMAP = 0x4, /* don't add to kernel direct mapping */
MEMBLOCK_DRIVER_MANAGED = 0x8, /* always detected via a driver */
MEMBLOCK_RSRV_NOINIT = 0x10, /* don't initialize struct pages */
+ MEMBLOCK_SCRATCH = 0x20, /* scratch memory for kexec handover */
};
/**
@@ -129,6 +134,8 @@ int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
int memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t size);
+int memblock_mark_scratch(phys_addr_t base, phys_addr_t size);
+int memblock_clear_scratch(phys_addr_t base, phys_addr_t size);
void memblock_free_all(void);
void memblock_free(void *ptr, size_t size);
@@ -273,6 +280,11 @@ static inline bool memblock_is_driver_managed(struct memblock_region *m)
return m->flags & MEMBLOCK_DRIVER_MANAGED;
}
+static inline bool memblock_is_scratch(struct memblock_region *m)
+{
+ return m->flags & MEMBLOCK_SCRATCH;
+}
+
int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
unsigned long *end_pfn);
void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
@@ -610,5 +622,12 @@ static inline void early_memtest(phys_addr_t start, phys_addr_t end) { }
static inline void memtest_report_meminfo(struct seq_file *m) { }
#endif
+#ifdef CONFIG_MEMBLOCK_SCRATCH
+void memblock_set_scratch_only(void);
+void memblock_clear_scratch_only(void);
+#else
+static inline void memblock_set_scratch_only(void) { }
+static inline void memblock_clear_scratch_only(void) { }
+#endif
#endif /* _LINUX_MEMBLOCK_H */
diff --git a/mm/Kconfig b/mm/Kconfig
index 57cd378c73d6..384369e40f10 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -513,6 +513,10 @@ config ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP
config HAVE_MEMBLOCK_PHYS_MAP
bool
+# Enable memblock support for scratch memory which is needed for KHO
+config MEMBLOCK_SCRATCH
+ bool
+
config HAVE_FAST_GUP
depends on MMU
bool
diff --git a/mm/memblock.c b/mm/memblock.c
index 5a88d6d24d79..e89e6c8f9d75 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -106,6 +106,13 @@ unsigned long min_low_pfn;
unsigned long max_pfn;
unsigned long long max_possible_pfn;
+#ifdef CONFIG_MEMBLOCK_SCRATCH
+/* When set to true, only allocate from MEMBLOCK_SCRATCH ranges */
+static bool scratch_only;
+#else
+#define scratch_only false
+#endif
+
static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_MEMORY_REGIONS] __initdata_memblock;
static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock;
#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
@@ -168,6 +175,10 @@ bool __init_memblock memblock_has_mirror(void)
static enum memblock_flags __init_memblock choose_memblock_flags(void)
{
+ /* skip non-scratch memory for kho early boot allocations */
+ if (scratch_only)
+ return MEMBLOCK_SCRATCH;
+
return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE;
}
@@ -643,7 +654,7 @@ static int __init_memblock memblock_add_range(struct memblock_type *type,
#ifdef CONFIG_NUMA
WARN_ON(nid != memblock_get_region_node(rgn));
#endif
- WARN_ON(flags != rgn->flags);
+ WARN_ON(flags != (rgn->flags & ~MEMBLOCK_SCRATCH));
nr_new++;
if (insert) {
if (start_rgn == -1)
@@ -890,6 +901,18 @@ int __init_memblock memblock_physmem_add(phys_addr_t base, phys_addr_t size)
}
#endif
+#ifdef CONFIG_MEMBLOCK_SCRATCH
+__init_memblock void memblock_set_scratch_only(void)
+{
+ scratch_only = true;
+}
+
+__init_memblock void memblock_clear_scratch_only(void)
+{
+ scratch_only = false;
+}
+#endif
+
/**
* memblock_setclr_flag - set or clear flag for a memory region
* @type: memblock type to set/clear flag for
@@ -1015,6 +1038,33 @@ int __init_memblock memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t
MEMBLOCK_RSRV_NOINIT);
}
+/**
+ * memblock_mark_scratch - Mark a memory region with flag MEMBLOCK_SCRATCH.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Only memory regions marked with %MEMBLOCK_SCRATCH will be considered for
+ * allocations during early boot with kexec handover.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_mark_scratch(phys_addr_t base, phys_addr_t size)
+{
+ return memblock_setclr_flag(&memblock.memory, base, size, 1, MEMBLOCK_SCRATCH);
+}
+
+/**
+ * memblock_clear_scratch - Clear flag MEMBLOCK_SCRATCH for a specified region.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_clear_scratch(phys_addr_t base, phys_addr_t size)
+{
+ return memblock_setclr_flag(&memblock.memory, base, size, 0, MEMBLOCK_SCRATCH);
+}
+
static bool should_skip_region(struct memblock_type *type,
struct memblock_region *m,
int nid, int flags)
@@ -1046,6 +1096,14 @@ static bool should_skip_region(struct memblock_type *type,
if (!(flags & MEMBLOCK_DRIVER_MANAGED) && memblock_is_driver_managed(m))
return true;
+ /* In early alloc during kho, we can only consider scratch allocations */
+ if ((flags & MEMBLOCK_SCRATCH) && !memblock_is_scratch(m))
+ return true;
+
+ /* Leave scratch memory alone after scratch-only phase */
+ if (!(flags & MEMBLOCK_SCRATCH) && memblock_is_scratch(m))
+ return true;
+
return false;
}
@@ -2211,6 +2269,7 @@ static const char * const flagname[] = {
[ilog2(MEMBLOCK_MIRROR)] = "MIRROR",
[ilog2(MEMBLOCK_NOMAP)] = "NOMAP",
[ilog2(MEMBLOCK_DRIVER_MANAGED)] = "DRV_MNG",
+ [ilog2(MEMBLOCK_SCRATCH)] = "SCRATCH",
};
static int memblock_debug_show(struct seq_file *m, void *private)
--
2.40.1
Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879
next prev parent reply other threads:[~2023-12-22 19:36 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-22 19:35 [PATCH v2 00/17] kexec: Allow preservation of ftrace buffers Alexander Graf
2023-12-22 19:35 ` Alexander Graf [this message]
2023-12-22 19:35 ` [PATCH v2 02/17] memblock: Declare scratch memory as CMA Alexander Graf
2024-01-01 3:01 ` Stanislav Kinsburskii
2023-12-22 19:35 ` [PATCH v2 03/17] kexec: Add Kexec HandOver (KHO) generation helpers Alexander Graf
2023-12-22 19:35 ` [PATCH v2 04/17] kexec: Add KHO parsing support Alexander Graf
2024-01-01 3:33 ` Stanislav Kinsburskii
2024-01-15 13:27 ` Alexander Graf
2023-12-22 19:35 ` [PATCH v2 05/17] kexec: Add KHO support to kexec file loads Alexander Graf
2023-12-22 19:35 ` [PATCH v2 06/17] kexec: Add config option for KHO Alexander Graf
2023-12-22 19:35 ` [PATCH v2 07/17] kexec: Add documentation " Alexander Graf
2024-01-01 3:55 ` Stanislav Kinsburskii
2023-12-22 19:35 ` [PATCH v2 08/17] arm64: Add KHO support Alexander Graf
2023-12-22 19:35 ` [PATCH v2 09/17] x86: " Alexander Graf
2023-12-22 19:36 ` [PATCH v2 10/17] tracing: Initialize fields before registering Alexander Graf
2023-12-22 19:36 ` [PATCH v2 11/17] tracing: Introduce kho serialization Alexander Graf
2023-12-22 19:51 ` [PATCH v2 06/17] kexec: Add config option for KHO Alexander Graf
2023-12-22 19:51 ` [PATCH v2 07/17] kexec: Add documentation " Alexander Graf
2024-01-03 18:48 ` Rob Herring
2024-01-17 14:01 ` Alexander Graf
2024-01-17 16:54 ` Rob Herring
2024-01-17 17:00 ` Alexander Graf
2023-12-22 19:51 ` [PATCH v2 08/17] arm64: Add KHO support Alexander Graf
2023-12-22 19:51 ` [PATCH v2 09/17] x86: " Alexander Graf
2023-12-22 19:51 ` [PATCH v2 10/17] tracing: Initialize fields before registering Alexander Graf
2023-12-22 19:51 ` [PATCH v2 11/17] tracing: Introduce kho serialization Alexander Graf
2023-12-22 19:51 ` [PATCH v2 12/17] tracing: Add kho serialization of trace buffers Alexander Graf
2023-12-22 19:51 ` [PATCH v2 13/17] tracing: Recover trace buffers from kexec handover Alexander Graf
2023-12-22 19:51 ` [PATCH v2 14/17] tracing: Add kho serialization of trace events Alexander Graf
2023-12-22 19:51 ` [PATCH v2 15/17] tracing: Recover trace events from kexec handover Alexander Graf
2023-12-22 19:51 ` [PATCH v2 16/17] tracing: Add config option for " Alexander Graf
2023-12-22 19:51 ` [PATCH v2 17/17] devicetree: Add bindings for ftrace KHO Alexander Graf
2023-12-22 21:19 ` Rob Herring
2023-12-23 14:30 ` Krzysztof Kozlowski
2023-12-23 23:20 ` Alexander Graf
2023-12-24 8:58 ` Krzysztof Kozlowski
2024-01-02 14:53 ` Rob Herring
2024-01-02 15:20 ` Rob Herring
2024-01-17 13:56 ` Alexander Graf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231222193607.15474-2-graf@amazon.com \
--to=graf@amazon.com \
--cc=akpm@linux-foundation.org \
--cc=anthony.yznaga@oracle.com \
--cc=arnd@arndb.de \
--cc=ashish.kalra@amd.com \
--cc=benh@kernel.crashing.org \
--cc=devicetree@vger.kernel.org \
--cc=dwmw@amazon.co.uk \
--cc=ebiederm@xmission.com \
--cc=hpa@zytor.com \
--cc=jgowans@amazon.com \
--cc=kexec@lists.infradead.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=madvenka@linux.microsoft.com \
--cc=mark.rutland@arm.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=robh+dt@kernel.org \
--cc=rostedt@goodmis.org \
--cc=skinsburskii@linux.microsoft.com \
--cc=thomas.lendacky@amd.com \
--cc=usama.arif@bytedance.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox