From: Pingfan Liu <kernelfans@gmail.com>
To: kexec@lists.infradead.org
Cc: Pingfan Liu <piliu@redhat.com>, Jiri Bohac <jbohac@suse.cz>,
Michal Hocko <mhocko@suse.com>, Philipp Rudo <prudo@redhat.com>,
Baoquan He <bhe@redhat.com>, Dave Young <dyoung@redhat.com>
Subject: [RFC 1/3] crash_dump: Parse the CMA's mem_map in kdump
Date: Mon, 18 Dec 2023 13:23:23 +0800 [thread overview]
Message-ID: <20231218052325.20982-2-kernelfans@gmail.com> (raw)
In-Reply-To: <20231218052325.20982-1-kernelfans@gmail.com>
From: Pingfan Liu <piliu@redhat.com>
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Philipp Rudo <prudo@redhat.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
To: kexec@lists.infradead.org
---
include/linux/kexec.h | 1 +
init/main.c | 4 +++
kernel/crash_dump.c | 80 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 85 insertions(+)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 8227455192b7..95e19c814c93 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -410,6 +410,7 @@ extern bool kexec_in_progress;
int crash_shrink_memory(unsigned long new_size);
ssize_t crash_get_memory_size(void);
+void kdump_kernel_reuse_mem(void);
#ifndef arch_kexec_protect_crashkres
/*
diff --git a/init/main.c b/init/main.c
index e24b0780fdff..ed90097caaa8 100644
--- a/init/main.c
+++ b/init/main.c
@@ -99,6 +99,7 @@
#include <linux/init_syscalls.h>
#include <linux/stackdepot.h>
#include <linux/randomize_kstack.h>
+#include <linux/kexec.h>
#include <net/net_namespace.h>
#include <asm/io.h>
@@ -1068,6 +1069,9 @@ void start_kernel(void)
arch_post_acpi_subsys_init();
kcsan_init();
+ /* */
+ kdump_kernel_reuse_mem();
+
/* Do the rest non-__init'ed, we're now alive */
arch_call_rest_init();
diff --git a/kernel/crash_dump.c b/kernel/crash_dump.c
index 92da32275af5..4605005f9534 100644
--- a/kernel/crash_dump.c
+++ b/kernel/crash_dump.c
@@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/export.h>
+#include <linux/cc_platform.h>
/*
* stores the physical address of elf header of crash image
@@ -39,3 +40,82 @@ static int __init setup_elfcorehdr(char *arg)
return end > arg ? 0 : -EINVAL;
}
early_param("elfcorehdr", setup_elfcorehdr);
+
+u64 kdump_cma_pfn;
+u64 kdump_cma_pg_cnt;
+u64 kdump_cma_pg_paddr;
+
+/* In old kernel, wreck should correspond to pfn */
+static void check_poison_page(struct page *wreck, int cnt, unsigned long pfn)
+{
+ int i = 0;
+ int order;
+ /* Info copied from old kernel */
+ struct page *check = wreck;
+ struct page *p;
+
+ /*
+ * Strictly check, but there is still a rare case, where both _refcnt and
+ * _mapcount are forged by some wrong code
+ */
+ for (; i < cnt; i += 1 << order) {
+ order = folio_order((struct folio *)check);
+ if (PageBuddy(check)) {
+ if (page_count(check) != 0 || total_mapcount(check) != 0)
+ goto fail;
+ if (check->index != 0)
+ goto fail;
+ if (check->lru.next != LIST_POISON1 ||
+ check->lru.prev != LIST_POISON2)
+ goto fail;
+
+ } else if (folio_test_anon((struct folio *)check)) {
+ /* check PAGE_MAPPING_ANON bit in mapping */
+ if (!((unsigned long)check->mapping & PAGE_MAPPING_ANON))
+ goto fail;
+ if (page_count(check) == 0)
+ goto fail;
+ if (total_mapcount(check) != page_count(check))
+ goto fail;
+ } else {
+ goto fail;
+ }
+
+ p = pfn_to_page(pfn);
+ for (int j = 0; j < 1 << order; j++)
+ ClearPageReserved(p + j);
+ __free_pages(p, order);
+
+fail:
+ check += 1 << order;
+ pfn += 1 << order;
+ }
+}
+
+void kdump_kernel_reuse_mem(void)
+{
+ u64 size;
+ struct page *wreck;
+ struct kvec kvec;
+ struct iov_iter iter;
+ char *buf;
+
+ if (!is_kdump_kernel())
+ return;
+
+ if (!kdump_cma_pfn || !kdump_cma_pg_cnt || !kdump_cma_pg_paddr)
+ return;
+
+ size = kdump_cma_pg_cnt * sizeof(struct page);
+ /* copy the wreck's page[] */
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf)
+ return;
+ wreck = (struct page *)buf;
+ kvec.iov_base = buf;
+ kvec.iov_len = size;
+ iov_iter_kvec(&iter, ITER_DEST, &kvec, 1, size);
+ read_from_oldmem(&iter, size, &kdump_cma_pg_paddr,
+ cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT));
+ check_poison_page(wreck, kdump_cma_pg_cnt, kdump_cma_pfn);
+}
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
next prev parent reply other threads:[~2023-12-18 5:23 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-18 5:23 [RFC 0/3] kdump: Check mem_map of CMA area in kdump Pingfan Liu
2023-12-18 5:23 ` Pingfan Liu [this message]
2023-12-18 5:23 ` [RFC 2/3] of: kexec: Set up properties for reusing CMA " Pingfan Liu
2023-12-18 5:23 ` [RFC 3/3] of: fdt: Parse properties of " Pingfan Liu
2023-12-18 15:19 ` [RFC 0/3] kdump: Check mem_map of CMA area " Michal Hocko
2023-12-19 15:20 ` Philipp Rudo
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=20231218052325.20982-2-kernelfans@gmail.com \
--to=kernelfans@gmail.com \
--cc=bhe@redhat.com \
--cc=dyoung@redhat.com \
--cc=jbohac@suse.cz \
--cc=kexec@lists.infradead.org \
--cc=mhocko@suse.com \
--cc=piliu@redhat.com \
--cc=prudo@redhat.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.