* [PATCH v2] x86/sev: Apply the RMP table e820 fixups before memblock is populated
@ 2026-10-20 20:28 Ashish Kalra
0 siblings, 0 replies; only message in thread
From: Ashish Kalra @ 2026-10-20 20:28 UTC (permalink / raw)
To: tglx, mingo, bp, dave.hansen, x86
Cc: hpa, luto, peterz, ardb, rppt, akpm, arnd, thomas.lendacky,
shivankg, linux-kernel, linux-coco
From: Ashish Kalra <ashish.kalra@amd.com>
When the start and/or end of the RMP table is not 2MB aligned,
snp_fixup_e820_tables() converts the 2MB chunk containing it from RAM to
reserved in the e820 tables, so that it is never used by the kernel (or
by a kexec-ed kernel) and SNP_INIT marks it HV-Fixed.
The fixups are done from mem_encrypt_setup_arch(), which runs after
max_pfn has been computed and after e820__memblock_setup() has populated
memblock from the e820 table. The RAM part of those chunks therefore
remains in memblock.memory. Commit 88a921aa3c6b ("x86/sev: Ensure that
RMP table fixups are reserved") dealt with one consequence of that, the
chunks still being allocatable, by additionally reserving them in
memblock, but memblock still describes them as memory.
That trips up the direct map setup. init_range_memory_mapping() maps the
memblock.memory ranges, so the RAM part of a chunk gets mapped. When a
subsequent, lower range is mapped, the trimming in phys_pmd_init() or
phys_pud_init() consults e820 instead, finds no RAM in the 2MB (or 1GB)
slot and clears the already populated entry. At boot this goes through
set_pmd_safe()/set_pud_safe() and triggers:
SEV-SNP: RMP table physical range [0x000000bf77900000 - 0x000000c037efffff]
SEV-SNP: Reserving start/end of RMP table on a 2MB boundary [0x000000bf77800000]
SEV-SNP: Reserving start/end of RMP table on a 2MB boundary [0x000000c037e00000]
...
init_memory_mapping: [mem 0xbf60000000-0xbf778fffff]
[mem 0xbf60000000-0xbf777fffff] page 2M
[mem 0xbf77800000-0xbf778fffff] page 4k
init_memory_mapping: [mem 0xbf40000000-0xbf5fffffff] page 2M
WARNING: arch/x86/mm/init_64.c:89 at phys_pmd_init+0x389/0x4b0, CPU#0: swapper/0
Call Trace:
phys_pud_init
phys_p4d_init
__kernel_physical_mapping_init
init_memory_mapping
init_range_memory_mapping
init_mem_mapping
setup_arch
start_kernel
and leaks the page table page that hung off the cleared entry.
None of the fixups depend on memblock: the RMP table is probed and
CC_ATTR_HOST_SEV_SNP is set from early_cpu_init(), and the segmented RMP
case only needs early_memremap(). They do depend on the e820 tables,
which are only built in e820__memory_setup() (which also populates
e820_table_kexec), so the fixups cannot run any earlier than that.
Move them into a new mem_encrypt_fixup_e820() called from setup_arch()
right after trim_bios_range(), before max_pfn is computed and memblock is
populated, so that both are derived from the final e820 table, and
finalize the table with e820__update_table(). mem_encrypt_setup_arch()
keeps the SWIOTLB sizing, which needs the memblock-derived memory size and
stays after e820__memblock_setup(). The memblock reservation is then no
longer needed and is removed.
Fixes: 400fea4b9651 ("x86/sev: Add callback to apply RMP table fixups for kexec")
Co-developed-by: Shivank Garg <shivankg@amd.com>
Signed-off-by: Shivank Garg <shivankg@amd.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
v2:
- Route the fixup through a new mem_encrypt_fixup_e820() wrapper instead of
calling snp_fixup_e820_tables() directly from setup_arch(). This keeps
the memory-encryption specifics out of setup.c (no <asm/sev.h> there) and
alongside mem_encrypt_setup_arch() in the mem_encrypt layer. No
functional change.
arch/x86/include/asm/mem_encrypt.h | 2 ++
arch/x86/kernel/setup.c | 1 +
arch/x86/mm/mem_encrypt.c | 14 +++++++-------
arch/x86/virt/svm/sev.c | 9 ++++-----
4 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index ea6494628cb0..f357df65cdd2 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -21,9 +21,11 @@ struct boot_params;
#ifdef CONFIG_X86_MEM_ENCRYPT
void __init mem_encrypt_init(void);
void __init mem_encrypt_setup_arch(void);
+void __init mem_encrypt_fixup_e820(void);
#else
static inline void mem_encrypt_init(void) { }
static inline void __init mem_encrypt_setup_arch(void) { }
+static inline void __init mem_encrypt_fixup_e820(void) { }
#endif
#ifdef CONFIG_AMD_MEM_ENCRYPT
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index cda6adb9f69c..b16b5d8fc569 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1029,6 +1029,7 @@ void __init setup_arch(char **cmdline_p)
e820_add_kernel_range();
trim_bios_range();
+ mem_encrypt_fixup_e820();
#ifdef CONFIG_X86_32
if (ppro_with_ram_bug()) {
pr_info("Applying PPro RAM bug workaround: punching 256 kB hole at 1.75 GB physical.\n");
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 95bae74fdab2..07146a63af11 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -99,18 +99,18 @@ void __init mem_encrypt_init(void)
print_mem_encrypt_feature_info();
}
+/* Fix up e820 for the RMP table before max_pfn and memblock use it. */
+void __init mem_encrypt_fixup_e820(void)
+{
+ if (cc_platform_has(CC_ATTR_HOST_SEV_SNP))
+ snp_fixup_e820_tables();
+}
+
void __init mem_encrypt_setup_arch(void)
{
phys_addr_t total_mem = memblock_phys_mem_size();
unsigned long size;
- /*
- * Do RMP table fixups after the e820 tables have been setup by
- * e820__memory_setup().
- */
- if (cc_platform_has(CC_ATTR_HOST_SEV_SNP))
- snp_fixup_e820_tables();
-
if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
return;
diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c
index bd70c4d0b774..73b359d3b743 100644
--- a/arch/x86/virt/svm/sev.c
+++ b/arch/x86/virt/svm/sev.c
@@ -207,8 +207,6 @@ static void __init __snp_fixup_e820_tables(u64 pa)
pr_info("Reserving start/end of RMP table on a 2MB boundary [0x%016llx]\n", pa);
e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
e820__range_update_table(e820_table_kexec, pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
- if (!memblock_is_region_reserved(pa, PMD_SIZE))
- memblock_reserve(pa, PMD_SIZE);
}
}
@@ -261,11 +259,12 @@ static void __init fixup_e820_tables_for_contiguous_rmp(void)
void __init snp_fixup_e820_tables(void)
{
- if (rmp_cfg & MSR_AMD64_SEG_RMP_ENABLED) {
+ if (rmp_cfg & MSR_AMD64_SEG_RMP_ENABLED)
fixup_e820_tables_for_segmented_rmp();
- } else {
+ else
fixup_e820_tables_for_contiguous_rmp();
- }
+
+ e820__update_table(e820_table);
}
static void clear_rmp(void)
base-commit: 250ee734115bca1c1f7a38d838909aa83cce87ae
--
2.43.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-20 20:28 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-20 20:28 [PATCH v2] x86/sev: Apply the RMP table e820 fixups before memblock is populated Ashish Kalra
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®