From: Baoquan He <bhe@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: catalin.marinas@arm.com, thunder.leizhen@huawei.com,
John.p.donnelly@oracle.com, kexec@lists.infradead.org,
linux-arm-kernel@lists.infradead.org, horms@kernel.org,
chenjiahao16@huawei.com, linux-riscv@lists.infradead.org,
x86@kernel.org, bp@alien8.de, Baoquan He <bhe@redhat.com>
Subject: [RFC PATCH 2/4] kdump: add generic functions to parse crashkernel and do reservation
Date: Mon, 19 Jun 2023 13:59:49 +0800 [thread overview]
Message-ID: <20230619055951.45620-3-bhe@redhat.com> (raw)
In-Reply-To: <20230619055951.45620-1-bhe@redhat.com>
In architecture like x86_64, arm64 and riscv, they have vast virtual
address space and usually have huge physical memory RAM. Their
crashkernel reservation doesn't have to be limited under 4G RAM,
but can be extended to the whole physical memory via crashkernel=,high
support.
Now add function parse_crashkernel_generic() to parse all possible
crashkernel parameters, including crashkernel=xM[@offset],
crashkernel=,high|low. And add function reserve_crashkernel_generic()
to reserve crashkernel memory if users specify any case of above
kernel pamameters.
This is preparation to simplify code of crashkernel=,high support
in architecutures.
Signed-off-by: Baoquan He <bhe@redhat.com>
---
include/linux/crash_core.h | 31 ++++++++
kernel/crash_core.c | 144 +++++++++++++++++++++++++++++++++++++
2 files changed, 175 insertions(+)
diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h
index 6ec10ed5c6a6..1b12868cad1b 100644
--- a/include/linux/crash_core.h
+++ b/include/linux/crash_core.h
@@ -84,4 +84,35 @@ int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
unsigned long long *crash_size, unsigned long long *crash_base);
+#ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
+int __init parse_crashkernel_generic(char *cmdline,
+ unsigned long long *crash_size,
+ unsigned long long *crash_base,
+ unsigned long long *low_size,
+ bool *high);
+
+void __init reserve_crashkernel_generic(char *cmdline,
+ unsigned long long crash_size,
+ unsigned long long crash_base,
+ unsigned long long crash_low_size,
+ bool high);
+#else
+
+static inline int __init parse_crashkernel_generic(char *cmdline,
+ unsigned long long *crash_size,
+ unsigned long long *crash_base,
+ unsigned long long *low_size,
+ bool *high)
+{
+ return 0;
+}
+
+static inline void __init reserve_crashkernel_generic(char *cmdline,
+ unsigned long long crash_size,
+ unsigned long long crash_base,
+ unsigned long long crash_low_size,
+ bool high)
+{}
+#endif
+
#endif /* LINUX_CRASH_CORE_H */
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index 57738ca0ee7f..b82dc8c970de 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -10,6 +10,9 @@
#include <linux/utsname.h>
#include <linux/vmalloc.h>
#include <linux/sizes.h>
+#include <linux/memblock.h>
+#include <linux/kexec.h>
+#include <linux/kmemleak.h>
#include <asm/page.h>
#include <asm/sections.h>
@@ -310,6 +313,147 @@ static int __init parse_crashkernel_dummy(char *arg)
}
early_param("crashkernel", parse_crashkernel_dummy);
+
+#ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
+int __init parse_crashkernel_generic(char *cmdline,
+ unsigned long long *crash_size,
+ unsigned long long *crash_base,
+ unsigned long long *low_size,
+ bool *high)
+{
+ int ret;
+
+ /* crashkernel=X[@offset] */
+ ret = parse_crashkernel_common(cmdline, memblock_phys_mem_size(),
+ crash_size, crash_base);
+ if (ret == -ENOENT) {
+ ret = parse_crashkernel_high(cmdline, 0, crash_size, crash_base);
+ if (ret || !*crash_size)
+ return -1;
+
+ /*
+ * crashkernel=Y,low can be specified or not, but invalid value
+ * is not allowed.
+ */
+ ret = parse_crashkernel_low(cmdline, 0, low_size, crash_base);
+ if (ret == -ENOENT)
+ *low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
+ else if (ret)
+ return -1;
+
+ *high = true;
+ } else if (ret || !*crash_size) {
+ /* The specified value is invalid */
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __init reserve_crashkernel_low(unsigned long long low_size)
+{
+#ifdef CONFIG_64BIT
+ unsigned long long low_base;
+
+ low_base = memblock_phys_alloc_range(low_size, CRASH_ALIGN, 0, CRASH_ADDR_LOW_MAX);
+ if (!low_base) {
+ pr_err("cannot allocate crashkernel low memory (size:0x%llx).\n", low_size);
+ return -ENOMEM;
+ }
+
+ pr_info("crashkernel low memory reserved: 0x%08llx - 0x%08llx (%lld MB)\n",
+ low_base, low_base + low_size, low_size >> 20);
+
+ crashk_low_res.start = low_base;
+ crashk_low_res.end = low_base + low_size - 1;
+ insert_resource(&iomem_resource, &crashk_low_res);
+#endif
+ return 0;
+}
+
+void __init reserve_crashkernel_generic(char *cmdline,
+ unsigned long long crash_size,
+ unsigned long long crash_base,
+ unsigned long long crash_low_size,
+ bool high)
+{
+ unsigned long long search_end = CRASH_ADDR_LOW_MAX, search_base = 0;
+ bool fixed_base = false;
+
+ /* User specifies base address explicitly. */
+ if (crash_base) {
+ fixed_base = true;
+ search_base = crash_base;
+ search_end = crash_base + crash_size;
+ }
+
+ if (high) {
+ search_base = CRASH_ADDR_LOW_MAX;
+ search_end = CRASH_ADDR_HIGH_MAX;
+ }
+
+retry:
+ crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN,
+ search_base, search_end);
+ if (!crash_base) {
+ /*
+ * For crashkernel=size[KMG]@offset[KMG], print out failure
+ * message if can't reserve the specified region.
+ */
+ if (fixed_base) {
+ pr_warn("crashkernel reservation failed - memory is in use.\n");
+ return;
+ }
+
+ /*
+ * For crashkernel=size[KMG], if the first attempt was for
+ * low memory, fall back to high memory, the minimum required
+ * low memory will be reserved later.
+ */
+ if (!high && search_end == CRASH_ADDR_LOW_MAX) {
+ search_end = CRASH_ADDR_HIGH_MAX;
+ search_base = CRASH_ADDR_LOW_MAX;
+ crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
+ goto retry;
+ }
+
+ /*
+ * For crashkernel=size[KMG],high, if the first attempt was
+ * for high memory, fall back to low memory.
+ */
+ if (high && search_end == CRASH_ADDR_HIGH_MAX) {
+ search_end = CRASH_ADDR_LOW_MAX;
+ search_base = 0;
+ goto retry;
+ }
+ pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
+ crash_size);
+ return;
+ }
+
+ if ((crash_base > CRASH_ADDR_LOW_MAX) &&
+ crash_low_size && reserve_crashkernel_low(crash_low_size)) {
+ memblock_phys_free(crash_base, crash_size);
+ return;
+ }
+
+ pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ crash_base, crash_base + crash_size, crash_size >> 20);
+
+ /*
+ * The crashkernel memory will be removed from the kernel linear
+ * map. Inform kmemleak so that it won't try to access it.
+ */
+ kmemleak_ignore_phys(crash_base);
+ if (crashk_low_res.end)
+ kmemleak_ignore_phys(crashk_low_res.start);
+
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
+ insert_resource(&iomem_resource, &crashk_res);
+}
+#endif
+
Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
void *data, size_t data_len)
{
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2023-06-19 6:00 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-19 5:59 [RFC PATCH 0/4] kdump: add generic functions to simplify crashkernel crashkernel in architecture Baoquan He
2023-06-19 5:59 ` [RFC PATCH 1/4] kdump: rename parse_crashkernel() to parse_crashkernel_common() Baoquan He
2023-06-19 5:59 ` Baoquan He [this message]
2023-06-19 5:59 ` [RFC PATCH 3/4] arm64: kdump: use generic interfaces to simplify crashkernel reservation code Baoquan He
2023-06-19 5:59 ` [RFC PATCH 4/4] x86: " Baoquan He
2023-06-19 6:09 ` [RFC PATCH 0/4] kdump: add generic functions to simplify crashkernel crashkernel in architecture Baoquan He
2023-07-08 2:15 ` Dave Young
2023-07-10 17:20 ` Philipp Rudo
2023-08-27 10:43 ` Baoquan He
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=20230619055951.45620-3-bhe@redhat.com \
--to=bhe@redhat.com \
--cc=John.p.donnelly@oracle.com \
--cc=bp@alien8.de \
--cc=catalin.marinas@arm.com \
--cc=chenjiahao16@huawei.com \
--cc=horms@kernel.org \
--cc=kexec@lists.infradead.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=thunder.leizhen@huawei.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;
as well as URLs for NNTP newsgroup(s).