mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "tip-bot2 for David Woodhouse" <tip-bot2@linutronix.de>
To: linux-tip-commits@vger.kernel.org
Cc: David Woodhouse <dwmw@amazon.co.uk>,
	Ingo Molnar <mingo@kernel.org>, Baoquan He <bhe@redhat.com>,
	Vivek Goyal <vgoyal@redhat.com>, Dave Young <dyoung@redhat.com>,
	Eric Biederman <ebiederm@xmission.com>,
	Ard Biesheuvel <ardb@kernel.org>,
	"H. Peter Anvin" <hpa@zytor.com>,
	x86@kernel.org, linux-kernel@vger.kernel.org
Subject: [tip: x86/boot] x86/kexec: Allocate PGD for x86_64 transition page tables separately
Date: Fri, 06 Dec 2024 10:16:48 -0000	[thread overview]
Message-ID: <173348020896.412.11879703626968297198.tip-bot2@tip-bot2> (raw)
In-Reply-To: <20241205153343.3275139-6-dwmw2@infradead.org>

The following commit has been merged into the x86/boot branch of tip:

Commit-ID:     4b5bc2ec9a239bce261ffeafdd63571134102323
Gitweb:        https://git.kernel.org/tip/4b5bc2ec9a239bce261ffeafdd63571134102323
Author:        David Woodhouse <dwmw@amazon.co.uk>
AuthorDate:    Thu, 05 Dec 2024 15:05:11 
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Fri, 06 Dec 2024 10:41:59 +01:00

x86/kexec: Allocate PGD for x86_64 transition page tables separately

Now that the following fix:

  d0ceea662d45 ("x86/mm: Add _PAGE_NOPTISHADOW bit to avoid updating userspace page tables")

stops kernel_ident_mapping_init() from scribbling over the end of a
4KiB PGD by assuming the following 4KiB will be a userspace PGD,
there's no good reason for the kexec PGD to be part of a single
8KiB allocation with the control_code_page.

( It's not clear that that was the reason for x86_64 kexec doing it that
  way in the first place either; there were no comments to that effect and
  it seems to have been the case even before PTI came along. It looks like
  it was just a happy accident which prevented memory corruption on kexec. )

Either way, it definitely isn't needed now. Just allocate the PGD
separately on x86_64, like i386 already does.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Baoquan He <bhe@redhat.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Link: https://lore.kernel.org/r/20241205153343.3275139-6-dwmw2@infradead.org
---
 arch/x86/include/asm/kexec.h       | 18 +++++++++---
 arch/x86/kernel/machine_kexec_64.c | 45 +++++++++++++++--------------
 2 files changed, 38 insertions(+), 25 deletions(-)

diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index ae5482a..ccb8ff3 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -16,6 +16,7 @@
 # define PAGES_NR		4
 #endif
 
+# define KEXEC_CONTROL_PAGE_SIZE	4096
 # define KEXEC_CONTROL_CODE_MAX_SIZE	2048
 
 #ifndef __ASSEMBLY__
@@ -43,7 +44,6 @@ struct kimage;
 /* Maximum address we can use for the control code buffer */
 # define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
 
-# define KEXEC_CONTROL_PAGE_SIZE	4096
 
 /* The native architecture */
 # define KEXEC_ARCH KEXEC_ARCH_386
@@ -58,9 +58,6 @@ struct kimage;
 /* Maximum address we can use for the control pages */
 # define KEXEC_CONTROL_MEMORY_LIMIT     (MAXMEM-1)
 
-/* Allocate one page for the pdp and the second for the code */
-# define KEXEC_CONTROL_PAGE_SIZE  (4096UL + 4096UL)
-
 /* The native architecture */
 # define KEXEC_ARCH KEXEC_ARCH_X86_64
 #endif
@@ -145,6 +142,19 @@ struct kimage_arch {
 };
 #else
 struct kimage_arch {
+	/*
+	 * This is a kimage control page, as it must not overlap with either
+	 * source or destination address ranges.
+	 */
+	pgd_t *pgd;
+	/*
+	 * The virtual mapping of the control code page itself is used only
+	 * during the transition, while the current kernel's pages are all
+	 * in place. Thus the intermediate page table pages used to map it
+	 * are not control pages, but instead just normal pages obtained
+	 * with get_zeroed_page(). And have to be tracked (below) so that
+	 * they can be freed.
+	 */
 	p4d_t *p4d;
 	pud_t *pud;
 	pmd_t *pmd;
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 9c9ac60..7223c38 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -146,7 +146,8 @@ static void free_transition_pgtable(struct kimage *image)
 	image->arch.pte = NULL;
 }
 
-static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
+static int init_transition_pgtable(struct kimage *image, pgd_t *pgd,
+				   unsigned long control_page)
 {
 	pgprot_t prot = PAGE_KERNEL_EXEC_NOENC;
 	unsigned long vaddr, paddr;
@@ -157,7 +158,7 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
 	pte_t *pte;
 
 	vaddr = (unsigned long)relocate_kernel;
-	paddr = __pa(page_address(image->control_code_page)+PAGE_SIZE);
+	paddr = control_page;
 	pgd += pgd_index(vaddr);
 	if (!pgd_present(*pgd)) {
 		p4d = (p4d_t *)get_zeroed_page(GFP_KERNEL);
@@ -216,7 +217,7 @@ static void *alloc_pgt_page(void *data)
 	return p;
 }
 
-static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
+static int init_pgtable(struct kimage *image, unsigned long control_page)
 {
 	struct x86_mapping_info info = {
 		.alloc_pgt_page	= alloc_pgt_page,
@@ -225,12 +226,12 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 		.kernpg_flag	= _KERNPG_TABLE_NOENC,
 	};
 	unsigned long mstart, mend;
-	pgd_t *level4p;
 	int result;
 	int i;
 
-	level4p = (pgd_t *)__va(start_pgtable);
-	clear_page(level4p);
+	image->arch.pgd = alloc_pgt_page(image);
+	if (!image->arch.pgd)
+		return -ENOMEM;
 
 	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
 		info.page_flag   |= _PAGE_ENC;
@@ -244,8 +245,8 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 		mstart = pfn_mapped[i].start << PAGE_SHIFT;
 		mend   = pfn_mapped[i].end << PAGE_SHIFT;
 
-		result = kernel_ident_mapping_init(&info,
-						 level4p, mstart, mend);
+		result = kernel_ident_mapping_init(&info, image->arch.pgd,
+						   mstart, mend);
 		if (result)
 			return result;
 	}
@@ -260,8 +261,8 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 		mstart = image->segment[i].mem;
 		mend   = mstart + image->segment[i].memsz;
 
-		result = kernel_ident_mapping_init(&info,
-						 level4p, mstart, mend);
+		result = kernel_ident_mapping_init(&info, image->arch.pgd,
+						   mstart, mend);
 
 		if (result)
 			return result;
@@ -271,15 +272,19 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 	 * Prepare EFI systab and ACPI tables for kexec kernel since they are
 	 * not covered by pfn_mapped.
 	 */
-	result = map_efi_systab(&info, level4p);
+	result = map_efi_systab(&info, image->arch.pgd);
 	if (result)
 		return result;
 
-	result = map_acpi_tables(&info, level4p);
+	result = map_acpi_tables(&info, image->arch.pgd);
 	if (result)
 		return result;
 
-	return init_transition_pgtable(image, level4p);
+	/*
+	 * This must be last because the intermediate page table pages it
+	 * allocates will not be control pages and may overlap the image.
+	 */
+	return init_transition_pgtable(image, image->arch.pgd, control_page);
 }
 
 static void load_segments(void)
@@ -296,14 +301,14 @@ static void load_segments(void)
 
 int machine_kexec_prepare(struct kimage *image)
 {
-	unsigned long start_pgtable;
+	unsigned long control_page;
 	int result;
 
 	/* Calculate the offsets */
-	start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
+	control_page = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
 
 	/* Setup the identity mapped 64bit page table */
-	result = init_pgtable(image, start_pgtable);
+	result = init_pgtable(image, control_page);
 	if (result)
 		return result;
 
@@ -357,13 +362,12 @@ void machine_kexec(struct kimage *image)
 #endif
 	}
 
-	control_page = page_address(image->control_code_page) + PAGE_SIZE;
+	control_page = page_address(image->control_code_page);
 	__memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE);
 
 	page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page);
 	page_list[VA_CONTROL_PAGE] = (unsigned long)control_page;
-	page_list[PA_TABLE_PAGE] =
-	  (unsigned long)__pa(page_address(image->control_code_page));
+	page_list[PA_TABLE_PAGE] = (unsigned long)__pa(image->arch.pgd);
 
 	if (image->type == KEXEC_TYPE_DEFAULT)
 		page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page)
@@ -573,8 +577,7 @@ static void kexec_mark_crashkres(bool protect)
 
 	/* Don't touch the control code page used in crash_kexec().*/
 	control = PFN_PHYS(page_to_pfn(kexec_crash_image->control_code_page));
-	/* Control code page is located in the 2nd page. */
-	kexec_mark_range(crashk_res.start, control + PAGE_SIZE - 1, protect);
+	kexec_mark_range(crashk_res.start, control - 1, protect);
 	control += KEXEC_CONTROL_PAGE_SIZE;
 	kexec_mark_range(control, crashk_res.end, protect);
 }

  reply	other threads:[~2024-12-06 10:16 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-05 15:05 [PATCH v5 00/20] x86/kexec: Add exception handling for relocate_kernel and further yak-shaving David Woodhouse
2024-12-05 15:05 ` [PATCH v5 01/20] x86/kexec: Restore GDT on return from preserve_context kexec David Woodhouse
2024-12-06 10:16   ` [tip: x86/urgent] x86/kexec: Restore GDT on return from ::preserve_context kexec tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 02/20] x86/kexec: Clean up and document register use in relocate_kernel_64.S David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 03/20] x86/kexec: Use named labels in swap_pages " David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 04/20] x86/kexec: Only swap pages for preserve_context mode David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] x86/kexec: Only swap pages for ::preserve_context mode tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 05/20] x86/kexec: Allocate PGD for x86_64 transition page tables separately David Woodhouse
2024-12-06 10:16   ` tip-bot2 for David Woodhouse [this message]
2024-12-05 15:05 ` [PATCH v5 06/20] x86/kexec: Copy control page into place in machine_kexec_prepare() David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 07/20] x86/kexec: Invoke copy of relocate_kernel() instead of the original David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-14 23:08   ` [PATCH v5 07/20] " Nathan Chancellor
2024-12-15  7:19     ` David Woodhouse
2024-12-15 10:09     ` David Woodhouse
2024-12-16  5:49       ` Nathan Chancellor
2024-12-16  8:13         ` David Woodhouse
2024-12-16 12:09         ` David Woodhouse
2024-12-17 12:03           ` David Woodhouse
2024-12-18  9:03             ` Josh Poimboeuf
2024-12-18  9:44               ` David Woodhouse
2024-12-18 21:23                 ` Josh Poimboeuf
2024-12-18 22:27                   ` David Woodhouse
2024-12-19  0:20                     ` Josh Poimboeuf
2024-12-19 10:02                       ` David Woodhouse
2024-12-19 22:28                         ` Josh Poimboeuf
2024-12-05 15:05 ` [PATCH v5 08/20] x86/kexec: Move relocate_kernel to kernel .data section David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 09/20] x86/kexec: Add data section to relocate_kernel David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 10/20] x86/kexec: Drop page_list argument from relocate_kernel() David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 11/20] x86/kexec: Eliminate writes through kernel mapping of relocate_kernel page David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 12/20] x86/kexec: Clean up register usage in relocate_kernel() David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-05 15:05 ` [PATCH v5 13/20] x86/kexec: Mark relocate_kernel page as ROX instead of RWX David Woodhouse
2024-12-06 10:16   ` [tip: x86/boot] " tip-bot2 for David Woodhouse
2024-12-12  1:44   ` [PATCH v5 13/20] " Nathan Chancellor
2024-12-12 10:30     ` David Woodhouse
2024-12-12 15:04       ` Nathan Chancellor
2024-12-12 17:00         ` David Woodhouse
2024-12-12 17:42           ` Nathan Chancellor
2024-12-12 19:31             ` David Woodhouse
2024-12-12 20:11             ` [PATCH] x86/kexec: Only write through identity mapping of control page David Woodhouse
2024-12-12 20:31               ` Nathan Chancellor
2024-12-12 21:18               ` Dave Hansen
2024-12-12 21:32                 ` David Woodhouse
2024-12-12 21:43                   ` Dave Hansen
2024-12-12 21:59                     ` David Woodhouse
2024-12-12 23:08                     ` [PATCH] x86/kexec: Disable global pages before writing to " David Woodhouse
2024-12-13  7:51                       ` Ning, Hongyu
2024-12-13  6:47               ` [PATCH] x86/kexec: Only write through identity mapping of " Ning, Hongyu
2024-12-12  3:03   ` [PATCH v5 13/20] x86/kexec: Mark relocate_kernel page as ROX instead of RWX Ning, Hongyu
2024-12-12 10:13     ` David Woodhouse
2024-12-13  6:45       ` Ning, Hongyu
2024-12-13  7:01         ` David Woodhouse
2024-12-13  7:41         ` Ning, Hongyu
2024-12-05 15:05 ` [PATCH v5 14/20] x86/kexec: Add CONFIG_KEXEC_DEBUG option David Woodhouse
2024-12-05 15:05 ` [PATCH v5 15/20] x86/kexec: Debugging support: load a GDT David Woodhouse
2024-12-05 15:05 ` [PATCH v5 16/20] x86/kexec: Debugging support: Load an IDT and basic exception entry points David Woodhouse
2024-12-05 15:05 ` [PATCH v5 17/20] x86/kexec: Debugging support: Dump registers on exception David Woodhouse
2024-12-05 15:05 ` [PATCH v5 18/20] x86/kexec: Add 8250 serial port output David Woodhouse
2024-12-05 15:05 ` [PATCH v5 19/20] x86/kexec: Add 8250 MMIO " David Woodhouse
2024-12-05 15:05 ` [PATCH v5 20/20] [DO NOT MERGE] x86/kexec: Add int3 in kexec path for testing David Woodhouse

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=173348020896.412.11879703626968297198.tip-bot2@tip-bot2 \
    --to=tip-bot2@linutronix.de \
    --cc=ardb@kernel.org \
    --cc=bhe@redhat.com \
    --cc=dwmw@amazon.co.uk \
    --cc=dyoung@redhat.com \
    --cc=ebiederm@xmission.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=vgoyal@redhat.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

all inboxes | Powered by JetHome®