Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Pankaj Gupta" <pankaj.gupta@amd.com>,
	"Thomas Gleixner" <tglx@kernel.org>,
	"Ingo Molnar" <mingo@redhat.com>,
	"Borislav Petkov" <bp@alien8.de>,
	"Dave Hansen" <dave.hansen@linux.intel.com>,
	x86@kernel.org
Cc: "H . Peter Anvin" <hpa@zytor.com>,
	"Tom Lendacky" <thomas.lendacky@amd.com>,
	"Ard Biesheuvel" <ardb@kernel.org>,
	"Kiryl Shutsemau" <kas@kernel.org>,
	"Mike Rapoport" <rppt@kernel.org>,
	linux-mm@kvack.org
Subject: Re: [PATCH] x86/unaccepted_memory: Do not accept ranges that are no longer E820 RAM
Date: Tue, 03 Nov 2026 11:31:44 +0000	[thread overview]
Message-ID: <sashiko-outbox-195153@kernel.org> (raw)
In-Reply-To: <20261102113127.161823-1-pankaj.gupta@amd.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] x86/unaccepted_memory: arch_accept_memory() desynchronizes unaccepted bitmap
- [High] x86/unaccepted_memory: unaligned E820 bounds passed to __arch_accept_memory()
--

commit f56630bdf157fa53e09d29e75f1fc454adb6cd1e
Author: Pankaj Gupta <pankaj.gupta@amd.com>

x86/unaccepted_memory: Do not accept ranges that are no longer E820 RAM

This commit updates arch_accept_memory() on x86 to iterate over e820_table
and only accept subranges that are marked as E820_TYPE_RAM. This avoids
attempting to accept memory holes removed via the memmap= command-line
parameter.

> diff --git a/arch/x86/include/asm/unaccepted_memory.h b/arch/x86/include/asm/unaccepted_memory.h
> index f5937e9866ac1..744f1a993352c 100644
> --- a/arch/x86/include/asm/unaccepted_memory.h
> +++ b/arch/x86/include/asm/unaccepted_memory.h
> @@ -2,10 +2,11 @@
>  #define _ASM_X86_UNACCEPTED_MEMORY_H
>  
>  #include <linux/efi.h>
> +#include <asm/e820/api.h>
>  #include <asm/tdx.h>
>  #include <asm/sev.h>
>  
> -static inline void arch_accept_memory(phys_addr_t start, phys_addr_t end)
> +static inline void __arch_accept_memory(phys_addr_t start, phys_addr_t end)
>  {
>  	/* Platform-specific memory-acceptance call goes here */
>  	if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) {
> @@ -18,6 +19,26 @@ static inline void arch_accept_memory(phys_addr_t start, phys_addr_t end)
>  	}
>  }
>  
> +static inline void arch_accept_memory(phys_addr_t start, phys_addr_t end)
> +{
> +	u32 i;
> +
> +	for (i = 0; i < e820_table->nr_entries; i++) {
> +		struct e820_entry *entry = &e820_table->entries[i];
> +		phys_addr_t s, e;
> +
> +		if (entry->type != E820_TYPE_RAM)
> +			continue;

[Severity: High]
Does skipping non-E820_TYPE_RAM ranges here desynchronize unaccepted->bitmap
from the actual hardware page acceptance state across kdump and kexec?

In drivers/firmware/efi/unaccepted_memory.c:accept_memory(), unit_size-aligned
range ends are extended by an extra unit_size to act as a guard page for
load_unaligned_zeropad(), and the bits in unaccepted->bitmap are cleared
unconditionally after arch_accept_memory() returns:

drivers/firmware/efi/unaccepted_memory.c:accept_memory() {
	...
	/*
	 * load_unaligned_zeropad() can lead to unwanted loads across page
	 * boundaries. The unwanted loads are typically harmless. Map an
	 * extra unit if the end of the requested range is aligned to
	 * unit_size to avoid page faults on unaccepted memory.
	 */
	if (!(end % unit_size))
		end += unit_size;
	...
		arch_accept_memory(phys_start, phys_end);

		spin_lock(&unaccepted_memory_lock);
		bitmap_clear(unaccepted->bitmap, range_start, len);
	...
}

When arch_accept_memory() skips a range that is not E820_TYPE_RAM in
e820_table, accept_memory() still clears its bit in unaccepted->bitmap even
though the pages were never accepted in hardware.

In a kdump kernel, e820_table only contains the crashkernel reservation as
E820_TYPE_RAM while the panicked kernel's remaining RAM is omitted from
e820_table. When the crash kernel accepts memory up to the 2 MiB-aligned end
of crashk_res, accept_memory() extends end by unit_size into the panicked
kernel's adjacent unaccepted RAM. arch_accept_memory() skips that range, but
accept_memory() clears its bit in unaccepted->bitmap. Later, when /proc/vmcore
is read, unaccepted_memory_vmcore_pfn_is_ram() checks
!pfn_is_unaccepted_memory(pfn), sees the cleared bit, and reads the
unaccepted page via read_from_oldmem(), crashing the kdump kernel.

A similar mismatch occurs with kexec: e820__memory_setup() populates
e820_table_kexec before parse_early_param() applies memmap= or mem= options
to e820_table, andarch/x86/kernel/kexec-bzimage64.c:setup_e820_entries()
passes e820_table_kexec to the next kernel while sharing the physical
efi.unaccepted table. Both kernel/kexec_core.c:sanity_check_segment_list()
(which calls accept_memory() on kexec segment destinations placed in
e820_table_kexec RAM) and the unit_size extension at the boundary before a
memmap= hole will clear bits in unaccepted->bitmap without accepting the
memory in hardware, causing the kexec load or the next kernel to fault on
those pages.

> +
> +		s = max_t(phys_addr_t, start, entry->addr);
> +		e = min_t(phys_addr_t, end, entry->addr + entry->size);
> +		if (s >= e)
> +			continue;
> +
> +		__arch_accept_memory(s, e);

[Severity: High]
What happens if entry->addr or entry->addr + entry->size is not aligned to
PAGE_SIZE?

Entries in e820_table can have byte-granular boundaries from firmware or
command-line options such as memmap= and mem=. When memblock is set up in
arch/x86/kernel/e820.c:e820__memblock_setup(), partial pages are trimmed via
memblock_trim_memory(PAGE_SIZE) and left unmapped in the direct map, whereas
e820_table retains the unaligned addresses.

Clamping s and e directly to entry->addr and entry->addr + entry->size can
therefore pass non-page-aligned boundaries to __arch_accept_memory(s, e):

1. On TDX, tdx_accept_memory() -> try_accept_one() requires start to be
   aligned to at least PG_LEVEL_4K and len to be at least PAGE_SIZE:

   arch/x86/coco/tdx/tdx-shared.c:try_accept_one() {
   	...
   	if (!IS_ALIGNED(start, accept_size))
   		return 0;

   	if (len < accept_size)
   		return 0;
   	...
   }

   An unaligned s or a trailing sub-page remainder causes tdx_accept_memory()
   to return false and __arch_accept_memory() to call
   panic("TDX: Failed to accept memory\n").

2. On SEV-SNP, snp_accept_memory() passes vaddr = (unsigned long)__va(start)
   and npages = (end - start) >> PAGE_SHIFT to set_pages_state(), which
   masks vaddr with PAGE_MASK. If s is not page-aligned, vaddr & PAGE_MASK
   rounds down into the unmapped partial page trimmed by
   memblock_trim_memory(PAGE_SIZE) and faults in pvalidate_pages(), while
   (e - s) >> PAGE_SHIFT can truncate npages and leave the last full page
   unaccepted.

Should s be rounded up with PAGE_ALIGN(s) and e rounded down with
PAGE_ALIGN_DOWN(e) before checking s >= e?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261102113127.161823-1-pankaj.gupta@amd.com?part=1


  parent reply	other threads:[~2026-11-03 11:31 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02 11:31 [PATCH] x86/unaccepted_memory: Do not accept ranges that are no longer E820 RAM Pankaj Gupta
2026-11-02 11:41 ` Ard Biesheuvel
2026-11-02 11:51   ` Gupta, Pankaj
2026-11-02 12:01     ` Gupta, Pankaj
2026-11-02 12:11       ` Ard Biesheuvel
2026-11-03 11:31         ` Gupta, Pankaj
2026-11-03 11:31 ` sashiko-bot [this message]
2026-11-04 11:41   ` Gupta, Pankaj

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=sashiko-outbox-195153@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=ardb@kernel.org \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=kas@kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mingo@redhat.com \
    --cc=pankaj.gupta@amd.com \
    --cc=rppt@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=tglx@kernel.org \
    --cc=thomas.lendacky@amd.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