From: Zack Rusin <zack.rusin@broadcom.com>
To: Kiryl Shutsemau <kas@kernel.org>, Borislav Petkov <bp@alien8.de>,
x86@kernel.org, Dennis Zhou <dennis@kernel.org>,
Tejun Heo <tj@kernel.org>, Arnd Bergmann <arnd@arndb.de>,
Rick Edgecombe <rick.p.edgecombe@intel.com>,
Tom Lendacky <thomas.lendacky@amd.com>,
Wei Liu <wei.liu@kernel.org>, Dexuan Cui <decui@microsoft.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Vitaly Kuznetsov <vkuznets@redhat.com>
Cc: Ajay Kaher <ajay.kaher@broadcom.com>,
Alexey Makhalov <alexey.makhalov@broadcom.com>,
Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
Dave Hansen <dave.hansen@linux.intel.com>,
"H. Peter Anvin" <hpa@zytor.com>,
virtualization@lists.linux.dev,
bcm-kernel-feedback-list@broadcom.com,
linux-kernel@vger.kernel.org, Christoph Lameter <cl@gentwo.org>,
Andrew Morton <akpm@linux-foundation.org>,
Bo Gan <bo.gan@broadcom.com>,
linux-mm@kvack.org, linux-arch@vger.kernel.org,
linux-coco@lists.linux.dev, kvm@vger.kernel.org,
Jonathan Corbet <corbet@lwn.net>,
"K. Y. Srinivasan" <kys@microsoft.com>,
Haiyang Zhang <haiyangz@microsoft.com>,
Long Li <longli@microsoft.com>, Andy Lutomirski <luto@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org,
Nathan Chancellor <nathan@kernel.org>,
Kees Cook <kees@kernel.org>, Ashish Kalra <ashish.kalra@amd.com>
Subject: [PATCH v2 6/6] x86/percpu: Share decrypted storage before guest CPU setup
Date: Tue, 29 Sep 2026 00:02:55 -0400 [thread overview]
Message-ID: <20260929040256.543767-7-zack.rusin@broadcom.com> (raw)
In-Reply-To: <20260929040256.543767-1-zack.rusin@broadcom.com>
Convert every possible CPU's decrypted section after per-CPU setup and
before the boot CPU registers its buffers. This replaces KVM's object
loop and shares VMware steal-time storage without a driver conversion
path or readiness state.
UP KVM registers inside setup_arch(), so convert before guest_late_init()
there and move VMware's UP registration to that hook. Stop boot on a
conversion failure: inconsistent page state must not be published to the
hypervisor. Host SME keeps its existing mappings. Skip Hyper-V vTOM
per-CPU storage: its visibility callbacks require later Hyper-V
initialization.
Suggested-by: Kiryl Shutsemau <kas@kernel.org>
Link: https://lore.kernel.org/r/aqqGUAX65s4LdJkr@thinkstation
Link: https://lore.kernel.org/r/aqvxQoIoYhJTZpAC@thinkstation
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
---
arch/x86/hyperv/ivm.c | 4 ++++
arch/x86/include/asm/mem_encrypt.h | 2 ++
arch/x86/include/asm/x86_init.h | 2 ++
arch/x86/kernel/cpu/vmware.c | 2 +-
arch/x86/kernel/kvm.c | 35 -----------------------------------
arch/x86/kernel/setup.c | 2 ++
arch/x86/kernel/setup_percpu.c | 2 ++
arch/x86/mm/mem_encrypt.c | 22 ++++++++++++++++++++++
8 files changed, 35 insertions(+), 36 deletions(-)
diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
index 2ce4dfe53472..4a5c735c9c52 100644
--- a/arch/x86/hyperv/ivm.c
+++ b/arch/x86/hyperv/ivm.c
@@ -887,6 +887,10 @@ void __init hv_vtom_init(void)
cc_set_mask(ms_hyperv.shared_gpa_boundary);
physical_mask &= ms_hyperv.shared_gpa_boundary - 1;
+ /* vTOM has no early per-CPU consumers and needs the Hyper-V setup. */
+ x86_init.paging.skip_percpu_decryption = true;
+ x86_init.paging.early_decrypt_page = NULL;
+
x86_platform.hyper.is_private_mmio = hv_is_private_mmio;
x86_platform.guest.enc_cache_flush_required = hv_vtom_cache_flush_required;
x86_platform.guest.enc_tlb_flush_required = hv_vtom_tlb_flush_required;
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 4d81f693b1d3..05cf395407ef 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -21,11 +21,13 @@ 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_init_percpu(void);
int __init early_set_memory_decrypted(unsigned long vaddr, unsigned long size);
void __init early_set_page_decrypted(unsigned long addr, unsigned long alias);
#else
static inline void mem_encrypt_init(void) { }
static inline void __init mem_encrypt_setup_arch(void) { }
+static inline void __init mem_encrypt_init_percpu(void) { }
static inline int __init
early_set_memory_decrypted(unsigned long vaddr, unsigned long size) { return 0; }
#endif
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index e4131402c783..8d1597372eb6 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -76,10 +76,12 @@ struct x86_init_oem {
* Callback must call paging_init(). Called once after the
* direct mapping for phys memory is available.
* @early_decrypt_page: Share a direct-mapped page and its optional image alias
+ * @skip_percpu_decryption: Platform does not use early shared per-CPU data
*/
struct x86_init_paging {
void (*pagetable_init)(void);
int (*early_decrypt_page)(unsigned long addr, unsigned long alias);
+ bool skip_percpu_decryption;
};
/**
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 34b73573b108..b477cc027b18 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -366,7 +366,7 @@ static void __init vmware_paravirt_ops_setup(void)
vmware_cpu_down_prepare) < 0)
pr_err("vmware_guest: Failed to install cpu hotplug callbacks\n");
#else
- vmware_guest_cpu_init();
+ x86_init.hyper.guest_late_init = vmware_guest_cpu_init;
#endif
}
}
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 6b0a5861ccb8..acb3b7b18ebe 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -429,34 +429,6 @@ static u64 kvm_steal_clock(int cpu)
return steal;
}
-static inline __init void __set_percpu_decrypted(void *ptr, unsigned long size)
-{
- early_set_memory_decrypted((unsigned long) ptr, size);
-}
-
-/*
- * Iterate through all possible CPUs and map the memory region pointed
- * by apf_reason, steal_time and kvm_apic_eoi as decrypted at once.
- *
- * Note: we iterate through all possible CPUs to ensure that CPUs
- * hotplugged will have their per-cpu variable already mapped as
- * decrypted.
- */
-static void __init sev_map_percpu_data(void)
-{
- int cpu;
-
- if (cc_vendor != CC_VENDOR_AMD ||
- !cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
- return;
-
- for_each_possible_cpu(cpu) {
- __set_percpu_decrypted(&per_cpu(apf_reason, cpu), sizeof(apf_reason));
- __set_percpu_decrypted(&per_cpu(steal_time, cpu), sizeof(steal_time));
- __set_percpu_decrypted(&per_cpu(kvm_apic_eoi, cpu), sizeof(kvm_apic_eoi));
- }
-}
-
static void kvm_guest_cpu_offline(bool shutdown)
{
kvm_disable_steal_time();
@@ -709,12 +681,6 @@ arch_initcall(kvm_alloc_cpumask);
static void __init kvm_smp_prepare_boot_cpu(void)
{
- /*
- * Map the per-cpu variables as decrypted before kvm_guest_cpu_init()
- * shares the guest physical address with the hypervisor.
- */
- sev_map_percpu_data();
-
kvm_guest_cpu_init();
native_smp_prepare_boot_cpu();
kvm_spinlock_init();
@@ -868,7 +834,6 @@ static void __init kvm_guest_init(void)
kvm_cpu_online, kvm_cpu_down_prepare) < 0)
pr_err("failed to install cpu hotplug callbacks\n");
#else
- sev_map_percpu_data();
kvm_guest_cpu_init();
#endif
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index cda6adb9f69c..8eebd85e59af 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1251,6 +1251,8 @@ void __init setup_arch(char **cmdline_p)
io_apic_init_mappings();
+ if (!IS_ENABLED(CONFIG_SMP))
+ mem_encrypt_init_percpu();
x86_init.hyper.guest_late_init();
e820__reserve_resources();
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index c83c61e0b20a..8526ad37a81b 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -5,6 +5,7 @@
#include <linux/export.h>
#include <linux/init.h>
#include <linux/memblock.h>
+#include <linux/mem_encrypt.h>
#include <linux/percpu.h>
#include <linux/kexec.h>
#include <linux/crash_dump.h>
@@ -234,4 +235,5 @@ void __init setup_per_cpu_areas(void)
* this call?
*/
sync_initial_page_table();
+ mem_encrypt_init_percpu();
}
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index c3e239a47b66..d3224607170d 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -13,6 +13,7 @@
#include <linux/cc_platform.h>
#include <linux/mem_encrypt.h>
#include <linux/pgalloc.h>
+#include <linux/percpu.h>
#include <linux/virtio_anchor.h>
#include <linux/iommu-dma.h>
@@ -24,6 +25,8 @@
#include "mm_internal.h"
+extern char __percpu __start_percpu_decrypted[], __end_percpu_decrypted[];
+
static pte_t * __init early_lookup_pte(unsigned long addr)
{
unsigned long pfn, step;
@@ -134,6 +137,25 @@ int __init early_set_memory_decrypted(unsigned long vaddr, unsigned long size)
return 0;
}
+void __init mem_encrypt_init_percpu(void)
+{
+ unsigned long size = __end_percpu_decrypted - __start_percpu_decrypted;
+ int cpu, ret;
+
+ if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT) ||
+ x86_init.paging.skip_percpu_decryption)
+ return;
+
+ for_each_possible_cpu(cpu) {
+ unsigned long addr = (unsigned long)
+ per_cpu_ptr(__start_percpu_decrypted, cpu);
+
+ ret = early_set_memory_decrypted(addr, size);
+ if (ret)
+ panic("Cannot share CPU %d per-CPU data (err=%d)", cpu, ret);
+ }
+}
+
/* Override for DMA direct allocation check - ARCH_HAS_FORCE_DMA_UNENCRYPTED */
bool force_dma_unencrypted(struct device *dev)
{
--
2.53.0
next prev parent reply other threads:[~2026-09-29 4:03 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 4:02 [PATCH v2 0/6] x86/percpu: Share decrypted storage before guest setup Zack Rusin
2026-09-29 4:02 ` [PATCH v2 1/6] percpu: Page-align decrypted data in UP kernels Zack Rusin
2026-09-29 4:09 ` sashiko-bot
2026-09-29 4:02 ` [PATCH v2 2/6] percpu: Bound decrypted storage for all x86 encrypted guests Zack Rusin
2026-09-29 4:12 ` sashiko-bot
2026-09-29 7:54 ` Peter Zijlstra
2026-09-29 17:12 ` Zack Rusin
2026-09-29 17:12 ` Zack Rusin
2026-09-29 17:12 ` Zack Rusin
2026-09-29 17:12 ` Zack Rusin
2026-09-29 17:12 ` Zack Rusin
2026-09-30 8:54 ` Peter Zijlstra
2026-09-29 4:02 ` [PATCH v2 3/6] x86/percpu: Require embedded allocation in " Zack Rusin
2026-09-29 4:07 ` sashiko-bot
2026-09-29 4:02 ` [PATCH v2 4/6] x86/mm: Provide common early memory decryption Zack Rusin
2026-09-29 4:14 ` sashiko-bot
2026-09-29 4:02 ` [PATCH v2 5/6] x86/tdx: Support early sharing of kernel data Zack Rusin
2026-09-29 4:14 ` sashiko-bot
2026-09-29 4:02 ` Zack Rusin [this message]
2026-09-29 4:14 ` [PATCH v2 6/6] x86/percpu: Share decrypted storage before guest CPU setup sashiko-bot
2026-09-29 5:39 ` [PATCH v2 0/6] x86/percpu: Share decrypted storage before guest setup Borislav Petkov
2026-09-29 17:25 ` Zack Rusin
2026-09-29 17:25 ` Zack Rusin
2026-09-29 17:25 ` Zack Rusin
2026-10-01 23:59 ` Borislav Petkov
2026-10-02 6:06 ` Zack Rusin
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=20260929040256.543767-7-zack.rusin@broadcom.com \
--to=zack.rusin@broadcom.com \
--cc=ajay.kaher@broadcom.com \
--cc=akpm@linux-foundation.org \
--cc=alexey.makhalov@broadcom.com \
--cc=arnd@arndb.de \
--cc=ashish.kalra@amd.com \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=bo.gan@broadcom.com \
--cc=bp@alien8.de \
--cc=cl@gentwo.org \
--cc=corbet@lwn.net \
--cc=dave.hansen@linux.intel.com \
--cc=decui@microsoft.com \
--cc=dennis@kernel.org \
--cc=haiyangz@microsoft.com \
--cc=hpa@zytor.com \
--cc=kas@kernel.org \
--cc=kees@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=kys@microsoft.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-doc@vger.kernel.org \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=longli@microsoft.com \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=nathan@kernel.org \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=rick.p.edgecombe@intel.com \
--cc=tglx@kernel.org \
--cc=thomas.lendacky@amd.com \
--cc=tj@kernel.org \
--cc=virtualization@lists.linux.dev \
--cc=vkuznets@redhat.com \
--cc=wei.liu@kernel.org \
--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 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.