From: Andrey Ryabinin <arbn@yandex-team.com>
To: linux-kernel@vger.kernel.org
Cc: Alexander Graf <graf@amazon.com>,
James Gowans <jgowans@amazon.com>,
Mike Rapoport <rppt@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
linux-mm@kvack.org, Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H . Peter Anvin" <hpa@zytor.com>,
Eric Biederman <ebiederm@xmission.com>,
kexec@lists.infradead.org, Pratyush Yadav <ptyadav@amazon.de>,
Jason Gunthorpe <jgg@nvidia.com>,
Pasha Tatashin <pasha.tatashin@soleen.com>,
David Rientjes <rientjes@google.com>,
Andrey Ryabinin <arbn@yandex-team.com>
Subject: [PATCH v2 3/7] kexec: exclude control pages from the destination addresses
Date: Mon, 10 Mar 2025 13:03:14 +0100 [thread overview]
Message-ID: <20250310120318.2124-4-arbn@yandex-team.com> (raw)
In-Reply-To: <20250310120318.2124-1-arbn@yandex-team.com>
Kexec relies on control pages allocated after all destination ranges
have been chosen. To be able to preserve memory across kexec we need
to be able to pick destination ranges after the control pages
allocated. Add check for control pages to locate_mem_hole() callbacks
so it excludes control pages, hence we can allocate them in any order.
Signed-off-by: Andrey Ryabinin <arbn@yandex-team.com>
---
kernel/kexec_core.c | 18 ++++++++++++++++++
kernel/kexec_file.c | 18 ++++--------------
kernel/kexec_internal.h | 3 +++
3 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index c0bdc1686154..647ab5705c37 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -264,6 +264,24 @@ int kimage_is_destination_range(struct kimage *image,
return 0;
}
+int kimage_is_control_page(struct kimage *image,
+ unsigned long start,
+ unsigned long end)
+{
+
+ struct page *page;
+
+ list_for_each_entry(page, &image->control_pages, lru) {
+ unsigned long pstart, pend;
+ pstart = page_to_boot_pfn(page) << PAGE_SHIFT;
+ pend = pstart + PAGE_SIZE * (1 << page_private(page)) - 1;
+ if ((end >= pstart) && (start <= pend))
+ return 1;
+ }
+
+ return 0;
+}
+
static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order)
{
struct page *pages;
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index a024ff379133..8ecd34071bfa 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -464,7 +464,8 @@ static int locate_mem_hole_top_down(unsigned long start, unsigned long end,
* Make sure this does not conflict with any of existing
* segments
*/
- if (kimage_is_destination_range(image, temp_start, temp_end)) {
+ if (kimage_is_destination_range(image, temp_start, temp_end) ||
+ kimage_is_control_page(image, temp_start, temp_end)) {
temp_start = temp_start - PAGE_SIZE;
continue;
}
@@ -498,7 +499,8 @@ static int locate_mem_hole_bottom_up(unsigned long start, unsigned long end,
* Make sure this does not conflict with any of existing
* segments
*/
- if (kimage_is_destination_range(image, temp_start, temp_end)) {
+ if (kimage_is_destination_range(image, temp_start, temp_end) ||
+ kimage_is_control_page(image, temp_start, temp_end)) {
temp_start = temp_start + PAGE_SIZE;
continue;
}
@@ -671,18 +673,6 @@ int kexec_add_buffer(struct kexec_buf *kbuf)
if (kbuf->image->nr_segments >= KEXEC_SEGMENT_MAX)
return -EINVAL;
- /*
- * Make sure we are not trying to add buffer after allocating
- * control pages. All segments need to be placed first before
- * any control pages are allocated. As control page allocation
- * logic goes through list of segments to make sure there are
- * no destination overlaps.
- */
- if (!list_empty(&kbuf->image->control_pages)) {
- WARN_ON(1);
- return -EINVAL;
- }
-
/* Ensure minimum alignment needed for segments. */
kbuf->memsz = ALIGN(kbuf->memsz, PAGE_SIZE);
kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h
index d35d9792402d..12e655a70e25 100644
--- a/kernel/kexec_internal.h
+++ b/kernel/kexec_internal.h
@@ -14,6 +14,9 @@ int kimage_load_segment(struct kimage *image, struct kexec_segment *segment);
void kimage_terminate(struct kimage *image);
int kimage_is_destination_range(struct kimage *image,
unsigned long start, unsigned long end);
+int kimage_is_control_page(struct kimage *image,
+ unsigned long start,
+ unsigned long end);
/*
* Whatever is used to serialize accesses to the kexec_crash_image needs to be
--
2.45.3
next prev parent reply other threads:[~2025-03-10 12:04 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-10 12:03 [PATCH v2 0/7] KSTATE: a mechanism to migrate some part of the kernel state across kexec Andrey Ryabinin
2025-03-10 12:03 ` [PATCH v2 1/7] kstate: Add kstate - a mechanism to describe and migrate " Andrey Ryabinin
2025-03-10 12:03 ` [PATCH v2 2/7] kstate, kexec, x86: transfer kstate data " Andrey Ryabinin
2025-03-10 12:03 ` Andrey Ryabinin [this message]
2025-03-10 12:03 ` [PATCH v2 4/7] kexec, kstate: delay loading of kexec segments Andrey Ryabinin
2025-03-11 11:31 ` kernel test robot
2025-03-11 12:25 ` kernel test robot
2025-03-10 12:03 ` [PATCH v2 5/7] x86, kstate: Add the ability to preserve memory pages across kexec Andrey Ryabinin
2025-03-10 12:03 ` [PATCH v2 6/7] kexec, kstate: save kstate data before kexec'ing Andrey Ryabinin
2025-03-10 12:03 ` [PATCH v2 7/7] kstate, test: add test module for testing kstate subsystem Andrey Ryabinin
2025-03-11 2:27 ` [PATCH v2 0/7] KSTATE: a mechanism to migrate some part of the kernel state across kexec Cong Wang
2025-03-11 12:19 ` Andrey Ryabinin
2025-04-28 23:01 ` Chris Li
2025-04-28 23:01 ` Chris Li
2025-05-05 14:35 ` Andrey Ryabinin
2025-05-07 6:11 ` Chris Li
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=20250310120318.2124-4-arbn@yandex-team.com \
--to=arbn@yandex-team.com \
--cc=akpm@linux-foundation.org \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=ebiederm@xmission.com \
--cc=graf@amazon.com \
--cc=hpa@zytor.com \
--cc=jgg@nvidia.com \
--cc=jgowans@amazon.com \
--cc=kexec@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mingo@redhat.com \
--cc=pasha.tatashin@soleen.com \
--cc=ptyadav@amazon.de \
--cc=rientjes@google.com \
--cc=rppt@kernel.org \
--cc=tglx@linutronix.de \
--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