* Re: [PATCH 1/2] x86/virt/tdx: Use PFN directly for mapping guest private memory
From: Sean Christopherson @ 2026-04-02 20:47 UTC (permalink / raw)
To: Dave Hansen
Cc: Yan Zhao, pbonzini, dave.hansen, tglx, mingo, bp, kas, x86,
linux-kernel, kvm, linux-coco, kai.huang, rick.p.edgecombe,
yilun.xu, vannapurve, ackerleytng, sagis, binbin.wu, xiaoyao.li,
isaku.yamahata
In-Reply-To: <a14531ab-f069-41f9-8c5c-9fe6f28a9454@intel.com>
On Thu, Mar 19, 2026, Dave Hansen wrote:
> On 3/18/26 17:57, Yan Zhao wrote:
> > Remove the completely unnecessary assumption that memory mapped into a TDX
> > guest is backed by refcounted struct page memory. From KVM's point of view,
> > TDH_MEM_PAGE_ADD and TDH_MEM_PAGE_AUG are glorified writes to PTEs, so they
> > have no business placing requirements on how KVM and guest_memfd manage
> > memory.
>
> I think this goes a bit too far.
>
> It's one thing to say that it's more convenient for KVM to stick with
> pfns because it's what KVM uses now. Or, that the goals of using 'struct
> page' can be accomplished other ways. It's quite another to say what
> other bits of the codebase have "business" doing.
>
> Sean, can we tone this down a _bit_ to help guide folks in the future?
I strongly disagree on this one. IMO, super low level APIs have no business
placing unnecessary requirements on callers. Requiring that the target memory
be convertible? A-ok because that's an actual requirement of the architecture.
Requiring or assuming anything about "struct page" or folios? Not ok.
This isn't a convenience thing, it's a core tenent of KVM guest memory managment.
KVM's MMUs work with PFNs, full stop. A PFN might have been acquired via GUP and
thus a refcounted struct page, but there is a hard boundary in KVM between getting
the page via GUP and installing the PFN into KVM's MMU.
KVM didn't always have a hard boundary, and it took us literally years to undo
the resulting messes. And the TDX hugepage support that was posted that pulled
information from "struct page" and/or its folio re-introduced the exact type of
flawed assumptions that we spent years purging from KVM.
So yeah, what I wrote was a strongly worded statement, but that was 100% intentional,
because I want to be crystal clear that requiring KVM to pass a struct page is a
complete non-starter for me.
> > Rip out the misguided struct page assumptions/constraints and instead have
>
> Could we maybe tone down the editorializing a bit, please? Folks can
> have honest disagreements about this stuff while not being "misguided".
FWIW, I'm not trying to say the intent or people's viewpoints were misguided, I'm
saying the code itself is misguided. AFAICT, the "struct page" stuff was added
to try to harden the TDX implementation, e.g. to guard against effective UAF of
memory that was assigned to a TD. But my viewpoint is that requiring a struct
page made the overall implemenation _less_ robust, and thus the code is misguided
because its justfication/reasoning was flawed.
> > the two SEAMCALL wrapper APIs take PFN directly. This ensures that for
> > future huge page support in S-EPT, the kernel doesn't pick up even worse
> > assumptions like "a hugepage must be contained in a single folio".
>
> I don't really understand what this is saying.
>
> Is the concern that KVM might want to set up page tables for memory that
> differ from how it was allocated? I'm a bit worried that this assumes
> something about folios that doesn't always hold.
Heh, the concern is that taking a page/folio in the SEAMCALL wrappers will lead
to assumptions that don't always hold. Specifically, the TDX hugepage support[*]
was building up assumptions that KVM would never attempt to install a hugepage
that didn't fit into a single folio:
+ if (start_idx + npages > folio_nr_pages(folio))
+ return TDX_OPERAND_INVALID;
[*] https://lore.kernel.org/all/20250807094132.4453-1-yan.y.zhao@intel.com
> I think the hugetlbfs gigantic support uses folios in at least a few
> spots today.
Yes, and the in-progress guest_memfd+HugeTLB work will also use folios. The
potential hiccup with the above folio_nr_pages() assumption is that KVM may want
to shatter folios to 4KiB granularity for tracking purposes, but still map
hugepage when memory is known to be physically contiguous.
That's where a lot of this is coming from. Taking a "struct page" is a bad
enough assumption on its own (that all TDX private memory is backed by struct page),
but even worse it's a slippery slope to even more bad assumptions (e.g. about how
guest_memfd internally manages its folios).
^ permalink raw reply
* [PATCH v3 6/6] KVM: SEV: Add support for SNP BTB Isolation
From: Kim Phillips @ 2026-04-02 20:25 UTC (permalink / raw)
To: linux-kernel, kvm, linux-coco, x86
Cc: Sean Christopherson, Paolo Bonzini, K Prateek Nayak,
Nikunj A Dadhania, Tom Lendacky, Michael Roth, Borislav Petkov,
Borislav Petkov, Naveen Rao, David Kaplan, Pawan Gupta,
Kim Phillips
In-Reply-To: <20260402202558.195005-1-kim.phillips@amd.com>
Advertise support for BTB Isolation via SEV_VMSA_FEATURES when SNP is
enabled, as all hardware that supports SNP also support BTB Isolation.
BTB Isolation is an optional feature that can be enabled by the guest to
ensure its guest Branch Target Buffers (BTBs) are not
affected by any context outside that guest.
SNP-active guests may choose to enable the Branch Target Buffer
Isolation mode through SEV_FEATURES bit 7 (BTBIsolation).
For more info, refer to page 615, Section 15.36.17 "Side-Channel
Protection", AMD64 Architecture Programmer's Manual Volume 2: System
Programming Part 2, Pub. 24593 Rev. 3.42 - March 2024 (see Link).
Link: https://bugzilla.kernel.org/attachment.cgi?id=306250
Cc: Sean Christopherson <seanjc@google.com>
Cc: Borislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: Kim Phillips <kim.phillips@amd.com>
---
v3: Reworded, Rebased on top of new SNP_ONLY_MASK etc. changes
v2: https://lore.kernel.org/kvm/20260203222405.4065706-3-kim.phillips@amd.com/
- Added Tom's Reviewed-by.
v1: https://lore.kernel.org/kvm/20260126224205.1442196-3-kim.phillips@amd.com/
arch/x86/include/asm/svm.h | 2 ++
arch/x86/kvm/svm/sev.c | 7 ++++++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 2a2b8705b2c0..d3a15a40a09b 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -305,10 +305,12 @@ static_assert((X2AVIC_4K_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AV
#define SVM_SEV_FEAT_RESTRICTED_INJECTION BIT(3)
#define SVM_SEV_FEAT_ALTERNATE_INJECTION BIT(4)
#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
+#define SVM_SEV_FEAT_BTB_ISOLATION BIT(7)
#define SVM_SEV_FEAT_SECURE_TSC BIT(9)
#define SVM_SEV_FEAT_IBPB_ON_ENTRY BIT(21)
#define SVM_SEV_FEAT_SNP_ONLY_MASK (SVM_SEV_FEAT_SNP_ACTIVE | \
+ SVM_SEV_FEAT_BTB_ISOLATION | \
SVM_SEV_FEAT_SECURE_TSC | \
SVM_SEV_FEAT_IBPB_ON_ENTRY)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 561023486253..733423000bc8 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3166,7 +3166,12 @@ void __init sev_hardware_setup(void)
sev_supported_vmsa_features |= SVM_SEV_FEAT_DEBUG_SWAP;
if (sev_snp_enabled) {
- sev_supported_vmsa_features |= SVM_SEV_FEAT_SNP_ACTIVE;
+ /*
+ * Some SNP-only features such as BTB Isolation are
+ * available on all systems that support SNP.
+ */
+ sev_supported_vmsa_features |= SVM_SEV_FEAT_SNP_ACTIVE |
+ SVM_SEV_FEAT_BTB_ISOLATION;
if (tsc_khz && cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC))
sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC;
--
2.43.0
^ permalink raw reply related
* [PATCH v3 5/6] KVM: SEV: Add support for IBPB-on-Entry
From: Kim Phillips @ 2026-04-02 20:25 UTC (permalink / raw)
To: linux-kernel, kvm, linux-coco, x86
Cc: Sean Christopherson, Paolo Bonzini, K Prateek Nayak,
Nikunj A Dadhania, Tom Lendacky, Michael Roth, Borislav Petkov,
Borislav Petkov, Naveen Rao, David Kaplan, Pawan Gupta,
Kim Phillips
In-Reply-To: <20260402202558.195005-1-kim.phillips@amd.com>
AMD EPYC 5th generation and above processors support IBPB-on-Entry
for SNP guests. By invoking an Indirect Branch Prediction Barrier
(IBPB) on VMRUN, old indirect branch predictions are prevented
from influencing indirect branches within the guest.
SNP guests may choose to enable IBPB-on-Entry by setting
SEV_FEATURES bit 21 (IbpbOnEntry).
Host support for IBPB on Entry is indicated by CPUID
Fn8000_001F[IbpbOnEntry], bit 31.
If supported, indicate support for IBPB on Entry in
sev_supported_vmsa_features bit 23 (IbpbOnEntry).
For more info, refer to page 615, Section 15.36.17 "Side-Channel
Protection", AMD64 Architecture Programmer's Manual Volume 2: System
Programming Part 2, Pub. 24593 Rev. 3.42 - March 2024 (see Link).
Link: https://bugzilla.kernel.org/attachment.cgi?id=306250
Cc: Sean Christopherson <seanjc@google.com>
Cc: Borislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: Kim Phillips <kim.phillips@amd.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
---
v3: Rebased on top of new SNP_ONLY_MASK etc. changes
v2: https://lore.kernel.org/kvm/20260203222405.4065706-3-kim.phillips@amd.com/
- Added Tom's Reviewed-by.
v1: https://lore.kernel.org/kvm/20260126224205.1442196-3-kim.phillips@amd.com/
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/asm/svm.h | 4 +++-
arch/x86/kvm/svm/sev.c | 3 +++
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index dbe104df339b..236411a1a86a 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -459,6 +459,7 @@
#define X86_FEATURE_ALLOWED_SEV_FEATURES (19*32+27) /* Allowed SEV Features */
#define X86_FEATURE_SVSM (19*32+28) /* "svsm" SVSM present */
#define X86_FEATURE_HV_INUSE_WR_ALLOWED (19*32+30) /* Allow Write to in-use hypervisor-owned pages */
+#define X86_FEATURE_IBPB_ON_ENTRY (19*32+31) /* SEV-SNP IBPB on VM Entry */
/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* No Nested Data Breakpoints */
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 4f844a72890c..2a2b8705b2c0 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -306,9 +306,11 @@ static_assert((X2AVIC_4K_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AV
#define SVM_SEV_FEAT_ALTERNATE_INJECTION BIT(4)
#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
#define SVM_SEV_FEAT_SECURE_TSC BIT(9)
+#define SVM_SEV_FEAT_IBPB_ON_ENTRY BIT(21)
#define SVM_SEV_FEAT_SNP_ONLY_MASK (SVM_SEV_FEAT_SNP_ACTIVE | \
- SVM_SEV_FEAT_SECURE_TSC)
+ SVM_SEV_FEAT_SECURE_TSC | \
+ SVM_SEV_FEAT_IBPB_ON_ENTRY)
#define VMCB_ALLOWED_SEV_FEATURES_VALID BIT_ULL(63)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 9663424c0cf0..561023486253 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3170,6 +3170,9 @@ void __init sev_hardware_setup(void)
if (tsc_khz && cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC))
sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC;
+
+ if (cpu_feature_enabled(X86_FEATURE_IBPB_ON_ENTRY))
+ sev_supported_vmsa_features |= SVM_SEV_FEAT_IBPB_ON_ENTRY;
}
}
--
2.43.0
^ permalink raw reply related
* [PATCH v3 4/6] KVM: SEV: Advertise SVM_SEV_FEAT_SNP_ACTIVE
From: Kim Phillips @ 2026-04-02 20:25 UTC (permalink / raw)
To: linux-kernel, kvm, linux-coco, x86
Cc: Sean Christopherson, Paolo Bonzini, K Prateek Nayak,
Nikunj A Dadhania, Tom Lendacky, Michael Roth, Borislav Petkov,
Borislav Petkov, Naveen Rao, David Kaplan, Pawan Gupta,
Kim Phillips
In-Reply-To: <20260402202558.195005-1-kim.phillips@amd.com>
Allow userspace to set the flag in kvm_sev_init.flags.
KVM still needs to set the flag for backwards compatibility, but
disallowing SVM_SEV_FEAT_SNP_ACTIVE for an SNP guest is "bizarre."
Suggested-by: Sean Christopherson <seanjc@google.com>
Cc: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/kvm/aaWog_UjW-M3412C@google.com/
Signed-off-by: Kim Phillips <kim.phillips@amd.com>
---
v3: new
arch/x86/include/asm/svm.h | 3 ++-
arch/x86/kvm/svm/sev.c | 8 ++++++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 7e3f9d92351a..4f844a72890c 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -307,7 +307,8 @@ static_assert((X2AVIC_4K_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AV
#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
#define SVM_SEV_FEAT_SECURE_TSC BIT(9)
-#define SVM_SEV_FEAT_SNP_ONLY_MASK SVM_SEV_FEAT_SECURE_TSC
+#define SVM_SEV_FEAT_SNP_ONLY_MASK (SVM_SEV_FEAT_SNP_ACTIVE | \
+ SVM_SEV_FEAT_SECURE_TSC)
#define VMCB_ALLOWED_SEV_FEATURES_VALID BIT_ULL(63)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 2b4f3c05e282..9663424c0cf0 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3165,8 +3165,12 @@ void __init sev_hardware_setup(void)
cpu_feature_enabled(X86_FEATURE_NO_NESTED_DATA_BP))
sev_supported_vmsa_features |= SVM_SEV_FEAT_DEBUG_SWAP;
- if (sev_snp_enabled && tsc_khz && cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC))
- sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC;
+ if (sev_snp_enabled) {
+ sev_supported_vmsa_features |= SVM_SEV_FEAT_SNP_ACTIVE;
+
+ if (tsc_khz && cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC))
+ sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC;
+ }
}
void sev_hardware_unsetup(void)
--
2.43.0
^ permalink raw reply related
* [PATCH v3 3/6] KVM: SEV: Disallow setting SNP-only features for non-SNP guests via a single mask
From: Kim Phillips @ 2026-04-02 20:25 UTC (permalink / raw)
To: linux-kernel, kvm, linux-coco, x86
Cc: Sean Christopherson, Paolo Bonzini, K Prateek Nayak,
Nikunj A Dadhania, Tom Lendacky, Michael Roth, Borislav Petkov,
Borislav Petkov, Naveen Rao, David Kaplan, Pawan Gupta,
Kim Phillips
In-Reply-To: <20260402202558.195005-1-kim.phillips@amd.com>
As SNP-only features get added, adding them to the valid_vmsa_features mask
in __sev_guest_init() often gets neglected. Add SVM_SEV_FEAT_SNP_ONLY_MASK
to help group these common features together.
Suggested-by: Sean Christopherson <seanjc@google.com>
Cc: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/kvm/aaWog_UjW-M3412C@google.com/
Signed-off-by: Kim Phillips <kim.phillips@amd.com>
---
v3: new
arch/x86/include/asm/svm.h | 2 ++
arch/x86/kvm/svm/sev.c | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index edde36097ddc..7e3f9d92351a 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -307,6 +307,8 @@ static_assert((X2AVIC_4K_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AV
#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
#define SVM_SEV_FEAT_SECURE_TSC BIT(9)
+#define SVM_SEV_FEAT_SNP_ONLY_MASK SVM_SEV_FEAT_SECURE_TSC
+
#define VMCB_ALLOWED_SEV_FEATURES_VALID BIT_ULL(63)
struct vmcb_seg {
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 3f9c1aa39a0a..2b4f3c05e282 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -456,7 +456,7 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
return -EINVAL;
if (!snp_active)
- valid_vmsa_features &= ~SVM_SEV_FEAT_SECURE_TSC;
+ valid_vmsa_features &= ~SVM_SEV_FEAT_SNP_ONLY_MASK;
if (data->vmsa_features & ~valid_vmsa_features)
return -EINVAL;
--
2.43.0
^ permalink raw reply related
* [PATCH v3 2/6] cpu/bugs: Allow spectre_v2=ibrs on x86 vendors other than Intel
From: Kim Phillips @ 2026-04-02 20:25 UTC (permalink / raw)
To: linux-kernel, kvm, linux-coco, x86
Cc: Sean Christopherson, Paolo Bonzini, K Prateek Nayak,
Nikunj A Dadhania, Tom Lendacky, Michael Roth, Borislav Petkov,
Borislav Petkov, Naveen Rao, David Kaplan, Pawan Gupta,
Kim Phillips, Dave Hansen, stable
In-Reply-To: <20260402202558.195005-1-kim.phillips@amd.com>
This is to prepare to allow legacy IBRS toggling on AMD systems,
where the BTB Isolation SEV-SNP feature can use it to optimize the
quick VM exit to re-entry path.
There is no reason this wasn't allowed in the first place, therefore
adding the cc: stable and Fixes: tags.
Fixes: 7c693f54c873 ("x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS")
Reported-by: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Borislav Petkov (AMD) <bp@alien8.de>
Cc: stable@kernel.org
Signed-off-by: Kim Phillips <kim.phillips@amd.com>
---
v3: No changes
v2: No changes
https://lore.kernel.org/kvm/20260311130611.2201214-3-kim.phillips@amd.com/
v1: https://lore.kernel.org/kvm/20260224180157.725159-3-kim.phillips@amd.com/
arch/x86/kernel/cpu/bugs.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index dfefbde10646..eed5a72a870c 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -2153,11 +2153,6 @@ static void __init spectre_v2_select_mitigation(void)
spectre_v2_cmd = SPECTRE_V2_CMD_AUTO;
}
- if (spectre_v2_cmd == SPECTRE_V2_CMD_IBRS && boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
- pr_err("IBRS selected but not Intel CPU. Switching to AUTO select\n");
- spectre_v2_cmd = SPECTRE_V2_CMD_AUTO;
- }
-
if (spectre_v2_cmd == SPECTRE_V2_CMD_IBRS && !boot_cpu_has(X86_FEATURE_IBRS)) {
pr_err("IBRS selected but CPU doesn't have IBRS. Switching to AUTO select\n");
spectre_v2_cmd = SPECTRE_V2_CMD_AUTO;
@@ -2250,7 +2245,8 @@ static void __init spectre_v2_apply_mitigation(void)
pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
if (spectre_v2_in_ibrs_mode(spectre_v2_enabled)) {
- if (boot_cpu_has(X86_FEATURE_AUTOIBRS)) {
+ if (boot_cpu_has(X86_FEATURE_AUTOIBRS) &&
+ spectre_v2_enabled != SPECTRE_V2_IBRS) {
msr_set_bit(MSR_EFER, _EFER_AUTOIBRS);
} else {
x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
--
2.43.0
^ permalink raw reply related
* [PATCH v3 1/6] cpu/bugs: Allow forcing Automatic IBRS with SNP active using spectre_v2=eibrs
From: Kim Phillips @ 2026-04-02 20:25 UTC (permalink / raw)
To: linux-kernel, kvm, linux-coco, x86
Cc: Sean Christopherson, Paolo Bonzini, K Prateek Nayak,
Nikunj A Dadhania, Tom Lendacky, Michael Roth, Borislav Petkov,
Borislav Petkov, Naveen Rao, David Kaplan, Pawan Gupta,
Kim Phillips, Dave Hansen, stable, kernel test robot
In-Reply-To: <20260402202558.195005-1-kim.phillips@amd.com>
spectre_v2=eibrs currently enables retpolines when SNP is enabled,
instead of AutoIBRS (EIBRS) because the commit that disabled
AutoIBRS if SNP is enabled stopped short of enabling
X86_FEATURE_IBRS_ENHANCED.
Change the logic to enable X86_FEATURE_IBRS_ENHANCED, and move the
decision to switch to retpolines in the default/"auto" case in
spectre_v2_select_mitigation(). This allows the existing
spectre_v2=eibrs logic to work as intended.
Also emit a performance loss warning for using AutoIBRS with
SNP enabled.
Fixes: acaa4b5c4c85 ("x86/speculation: Do not enable Automatic IBRS if SEV-SNP is enabled")
Reported-by: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Borislav Petkov (AMD) <bp@alien8.de>
Cc: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: stable@kernel.org
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202603121136.bc8zNsHS-lkp@intel.com/
Signed-off-by: Kim Phillips <kim.phillips@amd.com>
---
v3:
- Addressed Pawan Gupta's comment and remove wrong SPECTRE_V2_CMD_FORCE ("=on") check
- Addressed kernel test robot's !A || A && B is equivalent to !A || B warning
- Preferred to add new AutoIBRS with SEV-SNP enabled performance warning instead
of muting legacy IBRS in use vs. eIBRS messaging in the context of SNP, since
SNP users' IBRS performance varies whether they enable SNP BTB Isolation
v2: https://lore.kernel.org/kvm/20260311130611.2201214-2-kim.phillips@amd.com/
- Address Dave Hansen's comment to adhere to using the IBRS_ENHANCED
Intel feature flag also for AutoIBRS.
v1:
https://lore.kernel.org/kvm/20260224180157.725159-2-kim.phillips@amd.com/
arch/x86/kernel/cpu/bugs.c | 10 +++++++++-
arch/x86/kernel/cpu/common.c | 6 +-----
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 83f51cab0b1e..dfefbde10646 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -1658,6 +1658,7 @@ static inline const char *spectre_v2_module_string(void) { return ""; }
#define SPECTRE_V2_LFENCE_MSG "WARNING: LFENCE mitigation is not recommended for this CPU, data leaks possible!\n"
#define SPECTRE_V2_EIBRS_EBPF_MSG "WARNING: Unprivileged eBPF is enabled with eIBRS on, data leaks possible via Spectre v2 BHB attacks!\n"
#define SPECTRE_V2_EIBRS_LFENCE_EBPF_SMT_MSG "WARNING: Unprivileged eBPF is enabled with eIBRS+LFENCE mitigation and SMT, data leaks possible via Spectre v2 BHB attacks!\n"
+#define SPECTRE_V2_EIBRS_SNP_PERF_MSG "WARNING: AutoIBRS mitigation selected on SEV-SNP enabled CPU, this may cause unnecessary performance loss\n"
#define SPECTRE_V2_IBRS_PERF_MSG "WARNING: IBRS mitigation selected on Enhanced IBRS CPU, this may cause unnecessary performance loss\n"
#ifdef CONFIG_BPF_SYSCALL
@@ -2181,7 +2182,12 @@ static void __init spectre_v2_select_mitigation(void)
break;
fallthrough;
case SPECTRE_V2_CMD_FORCE:
- if (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED)) {
+ /*
+ * Don't use AutoIBRS when SNP is enabled because it degrades
+ * host userspace indirect branch performance.
+ */
+ if (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) &&
+ !boot_cpu_has(X86_FEATURE_SEV_SNP)) {
spectre_v2_enabled = SPECTRE_V2_EIBRS;
break;
}
@@ -2257,6 +2263,8 @@ static void __init spectre_v2_apply_mitigation(void)
return;
case SPECTRE_V2_EIBRS:
+ if (boot_cpu_has(X86_FEATURE_SEV_SNP))
+ pr_warn(SPECTRE_V2_EIBRS_SNP_PERF_MSG);
break;
case SPECTRE_V2_IBRS:
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4e1f0c4afe3a..0cdcbbedf883 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1485,13 +1485,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
/*
* AMD's AutoIBRS is equivalent to Intel's eIBRS - use the Intel feature
* flag and protect from vendor-specific bugs via the whitelist.
- *
- * Don't use AutoIBRS when SNP is enabled because it degrades host
- * userspace indirect branch performance.
*/
if ((x86_arch_cap_msr & ARCH_CAP_IBRS_ALL) ||
- (cpu_has(c, X86_FEATURE_AUTOIBRS) &&
- !cpu_feature_enabled(X86_FEATURE_SEV_SNP))) {
+ cpu_has(c, X86_FEATURE_AUTOIBRS)) {
setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
if (!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
!(x86_arch_cap_msr & ARCH_CAP_PBRSB_NO))
--
2.43.0
^ permalink raw reply related
* [PATCH v3 0/6] KVM: SEV: Add support for IBPB-on-Entry and BTB Isolation
From: Kim Phillips @ 2026-04-02 20:25 UTC (permalink / raw)
To: linux-kernel, kvm, linux-coco, x86
Cc: Sean Christopherson, Paolo Bonzini, K Prateek Nayak,
Nikunj A Dadhania, Tom Lendacky, Michael Roth, Borislav Petkov,
Borislav Petkov, Naveen Rao, David Kaplan, Pawan Gupta,
Kim Phillips
IBPB-on-Entry and BTB Isolation are supplemental Spectre V2 mitigations
available to SNP guests.
Patch 1 fixes a longstanding bug where users weren't able
to force Automatic IBRS on SNP enabled machines using spectre_v2=eibrs.
Patch 2 fixes another longstanding bug where users couldn't
select legacy / toggling SPEC_CTRL[IBRS] on AMD systems. Users of
the BTB Isolation feature may use IBRS to mitigate possible
performance degradation caused by BTB Isolation.
Patches 3 and 4 deal with a minor code refactoring as a result of
Sean's review of the v2 IBPB-on-Entry series.
Patch 5 adds support for IBPB-on-Entry.
Patch 6 adds support for BTB Isolation.
Based on current tip/master v7.0-rc6-423-g8726fc6dc93c
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
This v3 series now also available here:
https://github.com/AMDESE/linux/tree/btb-isol-latest
Advance qemu bits (to add feature on/off switches) available here:
https://github.com/AMDESE/qemu/tree/btb-isol-latest
Qemu bits will be posted upstream once kernel bits are merged.
They depend on Naveen Rao's "target/i386: SEV: Add support for
enabling VMSA SEV features":
https://lore.kernel.org/qemu-devel/cover.1761648149.git.naveen@kernel.org/
v3:
- Merged IBPB-on-Entry and BTB Isolation into single patchseries
- Addressed comments from Sean Christopherson, Pawan Gupta, kernel test robot
- Simplified unnecessarily complicated logic in spectre_v2=eibrs-with-SNP fix
- Reworded, rebased features on top of new SNP_ONLY_MASK etc. changes
v2:
[IBPB-on-Entry]
- https://lore.kernel.org/kvm/20260203222405.4065706-1-kim.phillips@amd.com/
- Change first patch's title (Nikunj)
- Add reviews-by (Nikunj, Tom)
- Change second patch's description to more generally explain what the patch does (Boris)
- Add new, third patch renaming SNP_FEATURES_PRESENT->SNP_FEATURES_IMPL
[BTB Isolation]
- https://lore.kernel.org/kvm/20260311130611.2201214-1-kim.phillips@amd.com/
- Patch 1/3:
- Address Dave Hansen's comment to adhere to using the IBRS_ENHANCED
Intel feature flag also for AutoIBRS.
v1:
[IBPB-on-Entry] https://lore.kernel.org/kvm/20260126224205.1442196-1-kim.phillips@amd.com/
[BTB Isolation] https://lore.kernel.org/kvm/20260224180157.725159-1-kim.phillips@amd.com/
Kim Phillips (6):
cpu/bugs: Allow forcing Automatic IBRS with SNP active using
spectre_v2=eibrs
cpu/bugs: Allow spectre_v2=ibrs on x86 vendors other than Intel
KVM: SEV: Disallow setting SNP-only features for non-SNP guests via a
single mask
KVM: SEV: Advertise SVM_SEV_FEAT_SNP_ACTIVE
KVM: SEV: Add support for IBPB-on-Entry
KVM: SEV: Add support for SNP BTB Isolation
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/asm/svm.h | 7 +++++++
arch/x86/kernel/cpu/bugs.c | 18 +++++++++++-------
arch/x86/kernel/cpu/common.c | 6 +-----
arch/x86/kvm/svm/sev.c | 18 +++++++++++++++---
5 files changed, 35 insertions(+), 15 deletions(-)
base-commit: 8726fc6dc93c62232fa625c1c91b97e21fff02b6
--
2.43.0
^ permalink raw reply
* Re: [PATCH v3 1/5] x86/tdx: Move TDX architectural error codes into <asm/shared/tdx_errno.h>
From: Verma, Vishal L @ 2026-04-02 18:18 UTC (permalink / raw)
To: seanjc@google.com
Cc: Gao, Chao, Edgecombe, Rick P, bp@alien8.de, x86@kernel.org,
kas@kernel.org, hpa@zytor.com, mingo@redhat.com,
linux-kernel@vger.kernel.org, dave.hansen@linux.intel.com,
tglx@kernel.org, pbonzini@redhat.com, linux-coco@lists.linux.dev,
kvm@vger.kernel.org
In-Reply-To: <ac6rtq-n0JNa_Oc0@google.com>
On Thu, 2026-04-02 at 10:47 -0700, Sean Christopherson wrote:
> On Thu, Apr 02, 2026, Vishal Verma wrote:
> > From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> >
> > Today there are two separate locations where TDX error codes are defined:
> >
> > arch/x86/include/asm/tdx.h
> > arch/x86/kvm/vmx/tdx_errno.h
> >
> > They have some overlap that is already defined similarly. Reduce the
> > duplication by unifying the architectural error codes at:
> >
> > asm/shared/tdx_errno.h
> >
> > ...and update the headers that contained the duplicated definitions to
> > include the new unified header.
> >
> > "asm/shared" is used for sharing TDX code between the early compressed
> > code and the normal kernel code. While the compressed code for the guest
> > doesn't use these error code header definitions today, it does make the
> > types of calls that return the values they define. So place the defines in
> > "shared" location so that it can, but leave such cleanups for future
> > changes.
> >
> > [Rick: enhance log]
> > [Vishal: reduce to a simple move of architectural defines only]
> > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
> > Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
> > Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
>
> Nit, when calling out minor amendments, IMO the blurb in the square braces should
> be after the previous SoB so that there's a clear, consistent chain of handling
> and ordering. I.e.
>
> Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
> [Rick: enhance log]
> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
> [Vishal: reduce to a simple move of architectural defines only]
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
>
> That makes it clear the Kirill signed off on something, then Rick tweaked the
> changelog and signed off on _that_, and Vishal came along and simplified the
> path.
>
That is indeed what I'm used to seeing/doing as well, I changed it to
this style after re-reading the tag ordering guidelines in maintainer-
tip.rst:
https://docs.kernel.org/process/maintainer-tip.html#ordering-of-commit-tags
If the handler made modifications to the patch or the changelog,
then this should be mentioned after the changelog text and above all
commit tags in the following format:
... changelog text ends.
[ handler: Replaced foo by bar and updated changelog ]
First-tag: .....
Although now I see I screwed even that up slightly - it calls for a blank
line after the [ ... ] notes.
^ permalink raw reply
* Re: [PATCH v3 1/5] x86/tdx: Move TDX architectural error codes into <asm/shared/tdx_errno.h>
From: Sean Christopherson @ 2026-04-02 17:47 UTC (permalink / raw)
To: Vishal Verma
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe, Paolo Bonzini,
linux-kernel, linux-coco, kvm, Chao Gao
In-Reply-To: <20260402-fuller_tdx_kexec_support-v3-1-34438d7094bf@intel.com>
On Thu, Apr 02, 2026, Vishal Verma wrote:
> From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
>
> Today there are two separate locations where TDX error codes are defined:
>
> arch/x86/include/asm/tdx.h
> arch/x86/kvm/vmx/tdx_errno.h
>
> They have some overlap that is already defined similarly. Reduce the
> duplication by unifying the architectural error codes at:
>
> asm/shared/tdx_errno.h
>
> ...and update the headers that contained the duplicated definitions to
> include the new unified header.
>
> "asm/shared" is used for sharing TDX code between the early compressed
> code and the normal kernel code. While the compressed code for the guest
> doesn't use these error code header definitions today, it does make the
> types of calls that return the values they define. So place the defines in
> "shared" location so that it can, but leave such cleanups for future
> changes.
>
> [Rick: enhance log]
> [Vishal: reduce to a simple move of architectural defines only]
> Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Nit, when calling out minor amendments, IMO the blurb in the square braces should
be after the previous SoB so that there's a clear, consistent chain of handling
and ordering. I.e.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
[Rick: enhance log]
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
[Vishal: reduce to a simple move of architectural defines only]
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
That makes it clear the Kirill signed off on something, then Rick tweaked the
changelog and signed off on _that_, and Vishal came along and simplified the
path.
Acked-by: Sean Christopherson <seanjc@google.com>
> Reviewed-by: Chao Gao <chao.gao@intel.com>
> ---
> arch/x86/include/asm/shared/tdx.h | 1 +
> arch/x86/{kvm/vmx => include/asm/shared}/tdx_errno.h | 7 +++----
> arch/x86/kvm/vmx/tdx.h | 1 -
> 3 files changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
> index 8bc074c8d7c6..6a1646fc2b2f 100644
> --- a/arch/x86/include/asm/shared/tdx.h
> +++ b/arch/x86/include/asm/shared/tdx.h
> @@ -4,6 +4,7 @@
>
> #include <linux/bits.h>
> #include <linux/types.h>
> +#include <asm/shared/tdx_errno.h>
>
> #define TDX_HYPERCALL_STANDARD 0
>
> diff --git a/arch/x86/kvm/vmx/tdx_errno.h b/arch/x86/include/asm/shared/tdx_errno.h
> similarity index 92%
> rename from arch/x86/kvm/vmx/tdx_errno.h
> rename to arch/x86/include/asm/shared/tdx_errno.h
> index 6ff4672c4181..3c1e8ce716e3 100644
> --- a/arch/x86/kvm/vmx/tdx_errno.h
> +++ b/arch/x86/include/asm/shared/tdx_errno.h
> @@ -1,8 +1,7 @@
> /* SPDX-License-Identifier: GPL-2.0 */
> /* architectural status code for SEAMCALL */
> -
> -#ifndef __KVM_X86_TDX_ERRNO_H
> -#define __KVM_X86_TDX_ERRNO_H
> +#ifndef _ASM_X86_SHARED_TDX_ERRNO_H
> +#define _ASM_X86_SHARED_TDX_ERRNO_H
>
> #define TDX_SEAMCALL_STATUS_MASK 0xFFFFFFFF00000000ULL
>
> @@ -37,4 +36,4 @@
> #define TDX_OPERAND_ID_SEPT 0x92
> #define TDX_OPERAND_ID_TD_EPOCH 0xa9
>
> -#endif /* __KVM_X86_TDX_ERRNO_H */
> +#endif /* _ASM_X86_SHARED_TDX_ERRNO_H */
> diff --git a/arch/x86/kvm/vmx/tdx.h b/arch/x86/kvm/vmx/tdx.h
> index b5cd2ffb303e..ac8323a68b16 100644
> --- a/arch/x86/kvm/vmx/tdx.h
> +++ b/arch/x86/kvm/vmx/tdx.h
> @@ -3,7 +3,6 @@
> #define __KVM_X86_VMX_TDX_H
>
> #include "tdx_arch.h"
> -#include "tdx_errno.h"
For the record, the defines in tdx_errno.h are only ever used by arch/x86/kvm/vmx/tdx.c,
and that file already included asm/shared/tdx.h by way of arch/x86/include/asm/tdx.h.
> #ifdef CONFIG_KVM_INTEL_TDX
> #include "common.h"
>
> --
> 2.53.0
>
^ permalink raw reply
* Re: [PATCH 2/2] x86/tdx: Accept hotplugged memory before online
From: Edgecombe, Rick P @ 2026-04-02 17:06 UTC (permalink / raw)
To: Reshetova, Elena, pbonzini@redhat.com, prsampat@amd.com
Cc: bp@alien8.de, marcandre.lureau@redhat.com, kas@kernel.org,
x86@kernel.org, linux-kernel@vger.kernel.org, mingo@redhat.com,
dave.hansen@linux.intel.com, Qiang, Chenyi, tglx@kernel.org,
hpa@zytor.com, kvm@vger.kernel.org, linux-coco@lists.linux.dev
In-Reply-To: <IA1PR11MB949557E04741169BA209A69EE751A@IA1PR11MB9495.namprd11.prod.outlook.com>
On Thu, 2026-04-02 at 08:18 +0000, Reshetova, Elena wrote:
> > Oh, I was just wondering if we could just zero the page on accept
> > failure for the case of already accepted. Handle the issue
> > internally
> > and actually go back to something like patch 1. Will it work for
> > SNP?
>
> I don't know about SNP, but if you are proposing to zero the page on
> double acceptance, this is not great from security pov.
Accept does zero the memory already. So the guest side operation is
doing an operation that says "make this memory usable in an known state
of zeros". And the operation complies. What is the difference?
> It creates a
> predictable behaviour primitive for the host to zero any data inside
> the confidential guest and it can be misused (think of zeroing out a
> page containing a cryptographic key).
If the host can trigger an accept somehow in the guest (via something
like this or other issue), then the host can also remove, then AUG the
page from the S-EPT. This will result in a normal accept which also
zeros the page.
So the part about whether a triggered accept succeeds or returns an
already accepted error is already under the control of the host. I.e.,
if we don't have the zeroing behavior, the host can already cause the
page to get zeroed. So I don't think anything is regressed. Both come
down to how careful the guest is about what it accepts.
^ permalink raw reply
* [PATCH] dma-buf: heaps: system: document system_cc_shared heap
From: Jiri Pirko @ 2026-04-02 14:11 UTC (permalink / raw)
To: dri-devel, linaro-mm-sig, iommu, linux-media
Cc: sumit.semwal, benjamin.gaignard, Brian.Starkey, jstultz,
tjmercier, christian.koenig, m.szyprowski, robin.murphy, jgg,
leon, sean.anderson, ptesarik, catalin.marinas, aneesh.kumar,
suzuki.poulose, steven.price, thomas.lendacky, john.allen,
ashish.kalra, suravee.suthikulpanit, linux-coco
From: Jiri Pirko <jiri@nvidia.com>
Document the system_cc_shared dma-buf heap that was introduced
recently. Describe its purpose, availability conditions and
relation to confidential computing VMs.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
Documentation/userspace-api/dma-buf-heaps.rst | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/userspace-api/dma-buf-heaps.rst b/Documentation/userspace-api/dma-buf-heaps.rst
index 05445c83b79a..591732393e7d 100644
--- a/Documentation/userspace-api/dma-buf-heaps.rst
+++ b/Documentation/userspace-api/dma-buf-heaps.rst
@@ -16,6 +16,14 @@ following heaps:
- The ``system`` heap allocates virtually contiguous, cacheable, buffers.
+ - The ``system_cc_shared`` heap allocates virtually contiguous, cacheable,
+ buffers using shared (decrypted) memory. It is only present on
+ confidential computing (CoCo) VMs where memory encryption is active
+ (e.g., AMD SEV, Intel TDX). The allocated pages have the encryption
+ bit cleared, making them accessible for device DMA without TDISP
+ support. On non-CoCo VMs configurations, this heap is
+ not registered.
+
- The ``default_cma_region`` heap allocates physically contiguous,
cacheable, buffers. Only present if a CMA region is present. Such a
region is usually created either through the kernel commandline
--
2.51.1
^ permalink raw reply related
* Re: [PATCH v5 0/2] dma-buf: heaps: system: add an option to allocate explicitly shared/decrypted memory
From: Jiri Pirko @ 2026-04-02 12:58 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Brian Starkey, dri-devel, linaro-mm-sig, iommu, linux-media,
sumit.semwal, benjamin.gaignard, jstultz, tjmercier,
christian.koenig, m.szyprowski, robin.murphy, leon, sean.anderson,
ptesarik, catalin.marinas, aneesh.kumar, suzuki.poulose,
steven.price, thomas.lendacky, john.allen, ashish.kalra,
suravee.suthikulpanit, linux-coco, nd
In-Reply-To: <20260402120254.GB2551565@ziepe.ca>
Thu, Apr 02, 2026 at 02:02:54PM +0200, jgg@ziepe.ca wrote:
>On Thu, Apr 02, 2026 at 10:52:34AM +0100, Brian Starkey wrote:
>> I'm not clear why the heap depends on !CONFIG_HIGHMEM, but I also
>> don't know anything about SEV/TDX.
>
>It is because the CC apis, set_memory_decrypted()/etc are slightly
>mis-designed. They take in a vaddr to represent the address instead of
>a phys_addr_t or a page *
>
>This means the user has to use page_address() and then the whole thing
>is incompatible with highmem.
>
>Which is fine, highmem and CC are never turned on together.
Yeah, I was wondering if it is worth sanitizing it, but decided to be on
the safe side, for unlikely oddities future may bring sake :)
^ permalink raw reply
* Re: [PATCH v5 2/2] dma-buf: heaps: system: add system_cc_shared heap for explicitly shared memory
From: Jiri Pirko @ 2026-04-02 12:56 UTC (permalink / raw)
To: Maxime Ripard
Cc: dri-devel, linaro-mm-sig, iommu, linux-media, sumit.semwal,
benjamin.gaignard, Brian.Starkey, jstultz, tjmercier,
christian.koenig, m.szyprowski, robin.murphy, jgg, leon,
sean.anderson, ptesarik, catalin.marinas, aneesh.kumar,
suzuki.poulose, steven.price, thomas.lendacky, john.allen,
ashish.kalra, suravee.suthikulpanit, linux-coco
In-Reply-To: <20260402-discreet-glossy-perch-bda4f9@houat>
Thu, Apr 02, 2026 at 02:23:12PM +0200, mripard@redhat.com wrote:
>Hi Jiri,
>
>On Wed, Mar 25, 2026 at 08:23:52PM +0100, Jiri Pirko wrote:
>> From: Jiri Pirko <jiri@nvidia.com>
>>
>> Add a new "system_cc_shared" dma-buf heap to allow userspace to
>> allocate shared (decrypted) memory for confidential computing (CoCo)
>> VMs.
>>
>> On CoCo VMs, guest memory is private by default. The hardware uses an
>> encryption bit in page table entries (C-bit on AMD SEV, "shared" bit on
>> Intel TDX) to control whether a given memory access is private or
>> shared. The kernel's direct map is set up as private,
>> so pages returned by alloc_pages() are private in the direct map
>> by default. To make this memory usable for devices that do not support
>> DMA to private memory (no TDISP support), it has to be explicitly
>> shared. A couple of things are needed to properly handle
>> shared memory for the dma-buf use case:
>>
>> - set_memory_decrypted() on the direct map after allocation:
>> Besides clearing the encryption bit in the direct map PTEs, this
>> also notifies the hypervisor about the page state change. On free,
>> the inverse set_memory_encrypted() must be called before returning
>> pages to the allocator. If re-encryption fails, pages
>> are intentionally leaked to prevent shared memory from being
>> reused as private.
>>
>> - pgprot_decrypted() for userspace and kernel virtual mappings:
>> Any new mapping of the shared pages, be it to userspace via
>> mmap or to kernel vmalloc space via vmap, creates PTEs independent
>> of the direct map. These must also have the encryption bit cleared,
>> otherwise accesses through them would see encrypted (garbage) data.
>>
>> - DMA_ATTR_CC_SHARED for DMA mapping:
>> Since the pages are already shared, the DMA API needs to be
>> informed via DMA_ATTR_CC_SHARED so it can map them correctly
>> as unencrypted for device access.
>>
>> On non-CoCo VMs, the system_cc_shared heap is not registered
>> to prevent misuse by userspace that does not understand
>> the security implications of explicitly shared memory.
>>
>> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
>
>I'm a bit late to the party, sorry.
>
>This new heap must be documented in
>Documentation/userspace-api/dma-buf-heaps.rst, but (and especially since
>it seems like it was merged already) it can be done as a follow-up
>patch.
Okay, will send a follow-up. Thanks!
>
>Maxime
^ permalink raw reply
* Re: [PATCH v5 2/2] dma-buf: heaps: system: add system_cc_shared heap for explicitly shared memory
From: Maxime Ripard @ 2026-04-02 12:23 UTC (permalink / raw)
To: Jiri Pirko
Cc: dri-devel, linaro-mm-sig, iommu, linux-media, sumit.semwal,
benjamin.gaignard, Brian.Starkey, jstultz, tjmercier,
christian.koenig, m.szyprowski, robin.murphy, jgg, leon,
sean.anderson, ptesarik, catalin.marinas, aneesh.kumar,
suzuki.poulose, steven.price, thomas.lendacky, john.allen,
ashish.kalra, suravee.suthikulpanit, linux-coco
In-Reply-To: <20260325192352.437608-3-jiri@resnulli.us>
[-- Attachment #1: Type: text/plain, Size: 2328 bytes --]
Hi Jiri,
On Wed, Mar 25, 2026 at 08:23:52PM +0100, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@nvidia.com>
>
> Add a new "system_cc_shared" dma-buf heap to allow userspace to
> allocate shared (decrypted) memory for confidential computing (CoCo)
> VMs.
>
> On CoCo VMs, guest memory is private by default. The hardware uses an
> encryption bit in page table entries (C-bit on AMD SEV, "shared" bit on
> Intel TDX) to control whether a given memory access is private or
> shared. The kernel's direct map is set up as private,
> so pages returned by alloc_pages() are private in the direct map
> by default. To make this memory usable for devices that do not support
> DMA to private memory (no TDISP support), it has to be explicitly
> shared. A couple of things are needed to properly handle
> shared memory for the dma-buf use case:
>
> - set_memory_decrypted() on the direct map after allocation:
> Besides clearing the encryption bit in the direct map PTEs, this
> also notifies the hypervisor about the page state change. On free,
> the inverse set_memory_encrypted() must be called before returning
> pages to the allocator. If re-encryption fails, pages
> are intentionally leaked to prevent shared memory from being
> reused as private.
>
> - pgprot_decrypted() for userspace and kernel virtual mappings:
> Any new mapping of the shared pages, be it to userspace via
> mmap or to kernel vmalloc space via vmap, creates PTEs independent
> of the direct map. These must also have the encryption bit cleared,
> otherwise accesses through them would see encrypted (garbage) data.
>
> - DMA_ATTR_CC_SHARED for DMA mapping:
> Since the pages are already shared, the DMA API needs to be
> informed via DMA_ATTR_CC_SHARED so it can map them correctly
> as unencrypted for device access.
>
> On non-CoCo VMs, the system_cc_shared heap is not registered
> to prevent misuse by userspace that does not understand
> the security implications of explicitly shared memory.
>
> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
I'm a bit late to the party, sorry.
This new heap must be documented in
Documentation/userspace-api/dma-buf-heaps.rst, but (and especially since
it seems like it was merged already) it can be done as a follow-up
patch.
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]
^ permalink raw reply
* [Invitation] bi-weekly guest_memfd upstream call on 2026-04-02
From: David Hildenbrand @ 2026-04-02 12:11 UTC (permalink / raw)
To: KVM, linux-mm@kvack.org, linux-coco@lists.linux.dev
Hi,
Late reminder :)
Our next guest_memfd upstream call is scheduled for today, Thursday,
2026-04-02 at 8:00 - 9:00am (GMT-07:00) Pacific Time - Vancouver.
We'll be using the following Google meet:
http://meet.google.com/wxp-wtju-jzw
The meeting notes can be found at [1], where we also link recordings and
collect current guest_memfd upstream proposals. If you want an google
calendar invitation that also covers all future meetings, just write me
or Ackerley a mail.
There is not a lot on the agenda: interaction with guest_memfd and
VM_DONTDUMP. So let's see what else comes up!
To put something to discuss onto the agenda, reply to this mail or add
them to the "Topics/questions for next meeting(s)" section in the
meeting notes as a comment.
[1]
https://docs.google.com/document/d/1M6766BzdY1Lhk7LiR5IqVR8B8mG3cr-cxTxOrAosPOk/edit?usp=sharing
--
Cheers,
David
^ permalink raw reply
* Re: [PATCH v5 0/2] dma-buf: heaps: system: add an option to allocate explicitly shared/decrypted memory
From: Jason Gunthorpe @ 2026-04-02 12:02 UTC (permalink / raw)
To: Brian Starkey
Cc: Jiri Pirko, dri-devel, linaro-mm-sig, iommu, linux-media,
sumit.semwal, benjamin.gaignard, jstultz, tjmercier,
christian.koenig, m.szyprowski, robin.murphy, leon, sean.anderson,
ptesarik, catalin.marinas, aneesh.kumar, suzuki.poulose,
steven.price, thomas.lendacky, john.allen, ashish.kalra,
suravee.suthikulpanit, linux-coco, nd
In-Reply-To: <4s75rtsmdfrze4rscbqzyrjyrko7n6sehe7agrngqag2cna5bz@eflmf4kwjocj>
On Thu, Apr 02, 2026 at 10:52:34AM +0100, Brian Starkey wrote:
> I'm not clear why the heap depends on !CONFIG_HIGHMEM, but I also
> don't know anything about SEV/TDX.
It is because the CC apis, set_memory_decrypted()/etc are slightly
mis-designed. They take in a vaddr to represent the address instead of
a phys_addr_t or a page *
This means the user has to use page_address() and then the whole thing
is incompatible with highmem.
Which is fine, highmem and CC are never turned on together.
Jason
^ permalink raw reply
* Re: [PATCH v2 27/31] coco/tdx-host: Implement SPDM session setup
From: Nikolay Borisov @ 2026-04-02 11:29 UTC (permalink / raw)
To: Xu Yilun, linux-coco, linux-pci, dan.j.williams, x86
Cc: chao.gao, dave.jiang, baolu.lu, yilun.xu, zhenzhong.duan, kvm,
rick.p.edgecombe, dave.hansen, kas, xiaoyao.li, vishal.l.verma,
linux-kernel
In-Reply-To: <20260327160132.2946114-28-yilun.xu@linux.intel.com>
On 27.03.26 г. 18:01 ч., Xu Yilun wrote:
> From: Zhenzhong Duan <zhenzhong.duan@intel.com>
>
> Implementation for a most straightforward SPDM session setup, using all
> default session options. Retrieve device info data from TDX Module which
> contains the SPDM negotiation results.
>
> TDH.SPDM.CONNECT/DISCONNECT are TDX Module Extension introduced
> SEAMCALLs which can run for longer periods and interruptible. But there
> is resource constraints that limit how many SEAMCALLs of this kind can
> run simultaneously. The current situation is One SEAMCALL at a time.
> Otherwise TDX_OPERAND_BUSY is returned. To avoid "broken indefinite"
> retry, a tdx_ext_lock is used to guard these SEAMCALLs.
>
> Co-developed-by: Xu Yilun <yilun.xu@linux.intel.com>
> Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
> ---
> arch/x86/include/asm/shared/tdx_errno.h | 2 +
> drivers/virt/coco/tdx-host/tdx-host.c | 301 +++++++++++++++++++++++-
> 2 files changed, 299 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/include/asm/shared/tdx_errno.h b/arch/x86/include/asm/shared/tdx_errno.h
> index 8bf6765cf082..7db04fe30378 100644
> --- a/arch/x86/include/asm/shared/tdx_errno.h
> +++ b/arch/x86/include/asm/shared/tdx_errno.h
> @@ -29,6 +29,8 @@
> #define TDX_EPT_WALK_FAILED 0xC0000B0000000000ULL
> #define TDX_EPT_ENTRY_STATE_INCORRECT 0xC0000B0D00000000ULL
> #define TDX_METADATA_FIELD_NOT_READABLE 0xC0000C0200000000ULL
> +#define TDX_SPDM_SESSION_KEY_REQUIRE_REFRESH 0xC0000F4500000000ULL
> +#define TDX_SPDM_REQUEST 0xC0000F5700000000ULL
>
> /*
> * SW-defined error codes.
> diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-host/tdx-host.c
> index 06f3d194e0a8..4d127b7c2591 100644
> --- a/drivers/virt/coco/tdx-host/tdx-host.c
> +++ b/drivers/virt/coco/tdx-host/tdx-host.c
> @@ -14,6 +14,7 @@
> #include <linux/pci-doe.h>
> #include <linux/pci-tsm.h>
> #include <linux/tsm.h>
> +#include <linux/vmalloc.h>
>
> #include <asm/cpu_device_id.h>
> #include <asm/tdx.h>
> @@ -32,8 +33,43 @@ MODULE_DEVICE_TABLE(x86cpu, tdx_host_ids);
> */
> static const struct tdx_sys_info *tdx_sysinfo;
>
> +#define TDISP_FUNC_ID GENMASK(15, 0)
> +#define TDISP_FUNC_ID_SEGMENT GENMASK(23, 16)
> +#define TDISP_FUNC_ID_SEG_VALID BIT(24)
> +
> +static inline u32 tdisp_func_id(struct pci_dev *pdev)
> +{
> + u32 func_id;
> +
> + func_id = FIELD_PREP(TDISP_FUNC_ID_SEGMENT, pci_domain_nr(pdev->bus));
> + if (func_id)
> + func_id |= TDISP_FUNC_ID_SEG_VALID;
This check implies pci_domain_nr returning 0 is considered invalid.
Other callers in the kernel seem to not care, they just use the domain
nr, so is this check spurious or intentional ?
> + func_id |= FIELD_PREP(TDISP_FUNC_ID,
> + PCI_DEVID(pdev->bus->number, pdev->devfn));
> +
> + return func_id;
> +}
> +
> +struct spdm_config_info_t {
> + u32 vmm_spdm_cap;
> +#define SPDM_CAP_HBEAT BIT(13)
> +#define SPDM_CAP_KEY_UPD BIT(14)
nit: move those defines above the struct definition, they just break the
reading flow as it is.
> + u8 spdm_session_policy;
> + u8 certificate_slot_mask;
> + u8 raw_bitstream_requested;
> +} __packed;
> +
> struct tdx_tsm_link {
> struct pci_tsm_pf0 pci;
> + u32 func_id;
> + struct page *in_msg;
> + struct page *out_msg;
> +
> + u64 spdm_id;
> + struct page *spdm_conf;
> + struct tdx_page_array *spdm_mt;
> + unsigned int dev_info_size;
> + void *dev_info_data;
> };
>
> static struct tdx_tsm_link *to_tdx_tsm_link(struct pci_tsm *tsm)
<snip>
> +
> +static void *tdx_dup_array_data(struct tdx_page_array *array,
> + unsigned int data_size)
> +{
> + unsigned int npages = (data_size + PAGE_SIZE - 1) / PAGE_SIZE;
nit: There's DIV_ROUND_UP
> + void *data, *dup_data;
> +
> + if (npages > array->nr_pages)
> + return NULL;
> +
> + data = vm_map_ram(array->pages, npages, -1);
> + if (!data)
> + return NULL;
> +
> + dup_data = kmemdup(data, data_size, GFP_KERNEL);
> + vm_unmap_ram(data, npages);
> +
> + return dup_data;
> +}
> +
<snip>
> +
> +DEFINE_FREE(tdx_spdm_session_teardown, struct tdx_tsm_link *,
> + if (!IS_ERR_OR_NULL(_T)) tdx_spdm_session_teardown(_T))
> +
> static int tdx_tsm_link_connect(struct pci_dev *pdev)
> {
> - return -ENXIO;
> + struct tdx_tsm_link *tlink = to_tdx_tsm_link(pdev->tsm);
> +
> + struct tdx_tsm_link *tlink_spdm __free(tdx_spdm_session_teardown) =
> + tdx_spdm_session_setup(tlink);
Is the free() really needed here, either the session is correctly setup
and tlink_spdm is returned. But if session_setup() files then what about
calling spdm_session_disconnect() on an unestablished session?
> + if (IS_ERR(tlink_spdm)) {
> + pci_err(pdev, "fail to setup spdm session\n");
> + return PTR_ERR(tlink_spdm);
> + }
> +
> + retain_and_null_ptr(tlink_spdm);
> +
> + return 0;
> }
>
<snip>
^ permalink raw reply
* Re: [PATCH v5 0/2] dma-buf: heaps: system: add an option to allocate explicitly shared/decrypted memory
From: Brian Starkey @ 2026-04-02 9:52 UTC (permalink / raw)
To: Jiri Pirko
Cc: dri-devel, linaro-mm-sig, iommu, linux-media, sumit.semwal,
benjamin.gaignard, jstultz, tjmercier, christian.koenig,
m.szyprowski, robin.murphy, jgg, leon, sean.anderson, ptesarik,
catalin.marinas, aneesh.kumar, suzuki.poulose, steven.price,
thomas.lendacky, john.allen, ashish.kalra, suravee.suthikulpanit,
linux-coco, nd
In-Reply-To: <20260325192352.437608-1-jiri@resnulli.us>
Hi,
I know I'm late to the party here...
Like John, I'm also not very close to this stuff any more, but I agree
with the other discussions: makes sense for this to be a separate
heap, and cc_shared makes sense too.
I'm not clear why the heap depends on !CONFIG_HIGHMEM, but I also
don't know anything about SEV/TDX.
-Brian
On Wed, Mar 25, 2026 at 08:23:50PM +0000, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@nvidia.com>
>
> Confidential computing (CoCo) VMs/guests, such as AMD SEV and Intel TDX,
> run with private/encrypted memory which creates a challenge
> for devices that do not support DMA to it (no TDISP support).
>
> For kernel-only DMA operations, swiotlb bounce buffering provides a
> transparent solution by copying data through shared memory.
> However, the only way to get this memory into userspace is via the DMA
> API's dma_alloc_pages()/dma_mmap_pages() type interfaces which limits
> the use of the memory to a single DMA device, and is incompatible with
> pin_user_pages().
>
> These limitations are particularly problematic for the RDMA subsystem
> which makes heavy use of pin_user_pages() and expects flexible memory
> usage between many different DMA devices.
>
> This patch series enables userspace to explicitly request shared
> (decrypted) memory allocations from new dma-buf system_cc_shared heap.
> Userspace can mmap this memory and pass the dma-buf fd to other
> existing importers such as RDMA or DRM devices to access the
> memory. The DMA API is improved to allow the dma heap exporter to DMA
> map the shared memory to each importing device.
>
> Based on dma-mapping-for-next e7442a68cd1ee797b585f045d348781e9c0dde0d
>
> Jiri Pirko (2):
> dma-mapping: introduce DMA_ATTR_CC_SHARED for shared memory
> dma-buf: heaps: system: add system_cc_shared heap for explicitly
> shared memory
>
> drivers/dma-buf/heaps/system_heap.c | 103 ++++++++++++++++++++++++++--
> include/linux/dma-mapping.h | 10 +++
> include/trace/events/dma.h | 3 +-
> kernel/dma/direct.h | 14 +++-
> kernel/dma/mapping.c | 13 +++-
> 5 files changed, 132 insertions(+), 11 deletions(-)
>
> --
> 2.51.1
>
^ permalink raw reply
* RE: [PATCH 2/2] x86/tdx: Accept hotplugged memory before online
From: Reshetova, Elena @ 2026-04-02 8:18 UTC (permalink / raw)
To: Edgecombe, Rick P, pbonzini@redhat.com, prsampat@amd.com
Cc: dave.hansen@linux.intel.com, marcandre.lureau@redhat.com,
kas@kernel.org, bp@alien8.de, linux-kernel@vger.kernel.org,
mingo@redhat.com, x86@kernel.org, Qiang, Chenyi, tglx@kernel.org,
hpa@zytor.com, kvm@vger.kernel.org, linux-coco@lists.linux.dev
In-Reply-To: <49e8b24d836c1883e83ad72d1ab279f9e3eb7455.camel@intel.com>
> On Mon, 2026-03-30 at 11:10 -0400, Pratik R. Sampat wrote:
> > SNP likely has an analogous issue too.
> > Failing to switch states on remove will cause that RMP entry to
> > remain validated. A malicious hypervisor could then remap this GPA to
> > another HPA which would put this in the Guest-Invalid state. On re-
> > hotplug if we ignore errors suggested by Patch 1 (in our case that'd
> > be PVALIDATE_FAIL_NOUPDATE error likely), we could have two RMP
> > entries for the same GPA and both being validated. This is dangerous
> > because hypervisor could swap these at will.
>
> Oh, I was just wondering if we could just zero the page on accept
> failure for the case of already accepted. Handle the issue internally
> and actually go back to something like patch 1. Will it work for SNP?
I don't know about SNP, but if you are proposing to zero the page on
double acceptance, this is not great from security pov. It creates a
predictable behaviour primitive for the host to zero any data inside
the confidential guest and it can be misused (think of zeroing out a
page containing a cryptographic key).
^ permalink raw reply
* Re: SVSM Development Call April 1st, 2026
From: Jörg Rödel @ 2026-04-02 7:54 UTC (permalink / raw)
To: coconut-svsm, linux-coco
In-Reply-To: <lbjylrvih3qk4irnbboktpadie4ldtqxzwyqarqubyvw6zkouw@j7kjwm2jts33>
Meeting minutes are now ready:
https://github.com/coconut-svsm/governance/pull/102
-Joerg
^ permalink raw reply
* [PATCH v3 5/5] x86/virt/tdx: Remove kexec docs
From: Vishal Verma @ 2026-04-02 6:32 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe,
Sean Christopherson, Paolo Bonzini
Cc: linux-kernel, linux-coco, kvm, Vishal Verma, Kai Huang
In-Reply-To: <20260402-fuller_tdx_kexec_support-v3-0-34438d7094bf@intel.com>
From: Rick Edgecombe <rick.p.edgecombe@intel.com>
Recent changes have removed the hard limitations for using kexec and
TDX together. So remove the section in the TDX docs.
Users on partial write erratums will need an updated TDX module to
handle the rare edge cases. The docs do not currently provide any
guidance on recommended TDX module versions, so don't keep a whole
section around to document this interaction.
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
Acked-by: Kai Huang <kai.huang@intel.com>
---
Documentation/arch/x86/tdx.rst | 7 -------
1 file changed, 7 deletions(-)
diff --git a/Documentation/arch/x86/tdx.rst b/Documentation/arch/x86/tdx.rst
index ff6b110291bc..1a3b5bac1021 100644
--- a/Documentation/arch/x86/tdx.rst
+++ b/Documentation/arch/x86/tdx.rst
@@ -138,13 +138,6 @@ If the platform has such erratum, the kernel prints additional message in
machine check handler to tell user the machine check may be caused by
kernel bug on TDX private memory.
-Kexec
-~~~~~~~
-
-Currently kexec doesn't work on the TDX platforms with the aforementioned
-erratum. It fails when loading the kexec kernel image. Otherwise it
-works normally.
-
Interaction vs S3 and deeper states
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
2.53.0
^ permalink raw reply related
* [PATCH v3 4/5] x86/tdx: Disable the TDX module during kexec and kdump
From: Vishal Verma @ 2026-04-02 6:32 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe,
Sean Christopherson, Paolo Bonzini
Cc: linux-kernel, linux-coco, kvm, Vishal Verma, Kai Huang
In-Reply-To: <20260402-fuller_tdx_kexec_support-v3-0-34438d7094bf@intel.com>
Use the TDH.SYS.DISABLE SEAMCALL, which disables the TDX module,
reclaims all memory resources assigned to TDX, and clears any
partial-write induced poison, to allow kexec and kdump on platforms with
the partial write errata.
On TDX-capable platforms with the partial write erratum, kexec has been
disabled because the new kernel could hit a machine check reading a
previously poisoned memory location.
Later TDX modules support TDH.SYS.DISABLE, which disables the module and
reclaims all TDX memory resources, allowing the new kernel to re-initialize
TDX from scratch. This operation also clears the old memory, cleaning up
any poison.
Add tdx_sys_disable() to tdx_shutdown(), which is called in the
syscore_shutdown path for kexec. This is done just before tdx_shutdown()
disables VMX on all CPUs.
For kdump, call tdx_sys_disable() in the crash path before
x86_virt_emergency_disable_virtualization_cpu() does VMXOFF.
Since this clears any poison on TDX-managed memory, remove the
X86_BUG_TDX_PW_MCE check in machine_kexec() that blocked kexec on
partial write errata platforms.
Co-developed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
Acked-by: Kai Huang <kai.huang@intel.com>
---
arch/x86/kernel/crash.c | 2 ++
arch/x86/kernel/machine_kexec_64.c | 16 ----------------
arch/x86/virt/vmx/tdx/tdx.c | 1 +
3 files changed, 3 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index cd796818d94d..623d4474631a 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -38,6 +38,7 @@
#include <linux/kdebug.h>
#include <asm/cpu.h>
#include <asm/reboot.h>
+#include <asm/tdx.h>
#include <asm/intel_pt.h>
#include <asm/crash.h>
#include <asm/cmdline.h>
@@ -112,6 +113,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
crash_smp_send_stop();
+ tdx_sys_disable();
x86_virt_emergency_disable_virtualization_cpu();
/*
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 0590d399d4f1..c3f4a389992d 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -347,22 +347,6 @@ int machine_kexec_prepare(struct kimage *image)
unsigned long reloc_end = (unsigned long)__relocate_kernel_end;
int result;
- /*
- * Some early TDX-capable platforms have an erratum. A kernel
- * partial write (a write transaction of less than cacheline
- * lands at memory controller) to TDX private memory poisons that
- * memory, and a subsequent read triggers a machine check.
- *
- * On those platforms the old kernel must reset TDX private
- * memory before jumping to the new kernel otherwise the new
- * kernel may see unexpected machine check. For simplicity
- * just fail kexec/kdump on those platforms.
- */
- if (boot_cpu_has_bug(X86_BUG_TDX_PW_MCE)) {
- pr_info_once("Not allowed on platform with tdx_pw_mce bug\n");
- return -EOPNOTSUPP;
- }
-
/* Setup the identity mapped 64bit page table */
result = init_pgtable(image, __pa(control_page));
if (result)
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 1ae558bcca3a..c0c6281b08a5 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -259,6 +259,7 @@ static void tdx_shutdown_cpu(void *ign)
static void tdx_shutdown(void *ign)
{
+ tdx_sys_disable();
on_each_cpu(tdx_shutdown_cpu, NULL, 1);
}
--
2.53.0
^ permalink raw reply related
* [PATCH v3 3/5] x86/virt/tdx: Add SEAMCALL wrapper for TDH.SYS.DISABLE
From: Vishal Verma @ 2026-04-02 6:32 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe,
Sean Christopherson, Paolo Bonzini
Cc: linux-kernel, linux-coco, kvm, Vishal Verma, Chao Gao, Kai Huang
In-Reply-To: <20260402-fuller_tdx_kexec_support-v3-0-34438d7094bf@intel.com>
Some early TDX-capable platforms have an erratum where a partial write
to TDX private memory can cause a machine check on a subsequent read.
On these platforms, kexec and kdump have been disabled in these cases,
because the old kernel cannot safely hand off TDX state to the new
kernel. Later TDX modules support the TDH.SYS.DISABLE SEAMCALL, which
provides a way to cleanly disable TDX and allow kexec to proceed.
The new SEAMCALL has an enumeration bit, but that is ignored. It is
expected that users will be using the latest TDX module, and the failure
mode for running the missing SEAMCALL on an older module is not fatal.
This can be a long running operation, and the time needed largely
depends on the amount of memory that has been allocated to TDs. If all
TDs have been destroyed prior to the sys_disable call, then it is fast,
with only needing to override the TDX module memory.
After the SEAMCALL completes, the TDX module is disabled and all memory
resources allocated to TDX are freed and reset. The next kernel can then
re-initialize the TDX module from scratch via the normal TDX bring-up
sequence.
The SEAMCALL can return two different error codes that expect a retry.
- TDX_INTERRUPTED_RESUMABLE can be returned in the case of a host
interrupt. However, it will not return until it makes some forward
progress, so we can expect to complete even in the case of interrupt
storms.
- TDX_SYS_BUSY will be returned on contention with other TDH.SYS.*
SEAMCALLs, however a side effect of TDH.SYS.DISABLE is that it will
block other SEAMCALLs once it gets going. So this contention will be
short lived.
So loop infinitely on either of these error codes, until success or other
error.
An error is printed if the SEAMCALL fails with anything other than the
error codes that cause retries, or 'synthesized' error codes produced
for #GP or #UD. e.g., an old module that has been properly initialized,
that doesn't implement SYS_DISABLE, returns TDX_OPERAND_INVALID. This
prints:
virt/tdx: TDH.SYS.DISABLE failed: 0xc000010000000000
But a system that doesn't have any TDX support at all doesn't print
anything.
Co-developed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
Acked-by: Kai Huang <kai.huang@intel.com>
---
arch/x86/include/asm/shared/tdx_errno.h | 1 +
arch/x86/include/asm/tdx.h | 3 +++
arch/x86/virt/vmx/tdx/tdx.h | 1 +
arch/x86/virt/vmx/tdx/tdx.c | 31 +++++++++++++++++++++++++++++++
4 files changed, 36 insertions(+)
diff --git a/arch/x86/include/asm/shared/tdx_errno.h b/arch/x86/include/asm/shared/tdx_errno.h
index 3c1e8ce716e3..ee411b360e20 100644
--- a/arch/x86/include/asm/shared/tdx_errno.h
+++ b/arch/x86/include/asm/shared/tdx_errno.h
@@ -13,6 +13,7 @@
#define TDX_NON_RECOVERABLE_TD_NON_ACCESSIBLE 0x6000000500000000ULL
#define TDX_NON_RECOVERABLE_TD_WRONG_APIC_MODE 0x6000000700000000ULL
#define TDX_INTERRUPTED_RESUMABLE 0x8000000300000000ULL
+#define TDX_SYS_BUSY 0x8000020200000000ULL
#define TDX_OPERAND_INVALID 0xC000010000000000ULL
#define TDX_OPERAND_BUSY 0x8000020000000000ULL
#define TDX_PREVIOUS_TLB_EPOCH_BUSY 0x8000020100000000ULL
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index bf83a974a0d5..15eac89b0afb 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -193,6 +193,8 @@ static inline int pg_level_to_tdx_sept_level(enum pg_level level)
return level - 1;
}
+void tdx_sys_disable(void);
+
u64 tdh_vp_enter(struct tdx_vp *vp, struct tdx_module_args *args);
u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page);
u64 tdh_mem_page_add(struct tdx_td *td, u64 gpa, struct page *page, struct page *source, u64 *ext_err1, u64 *ext_err2);
@@ -224,6 +226,7 @@ static inline void tdx_init(void) { }
static inline u32 tdx_get_nr_guest_keyids(void) { return 0; }
static inline const char *tdx_dump_mce_info(struct mce *m) { return NULL; }
static inline const struct tdx_sys_info *tdx_get_sysinfo(void) { return NULL; }
+static inline void tdx_sys_disable(void) { }
#endif /* CONFIG_INTEL_TDX_HOST */
#endif /* !__ASSEMBLER__ */
diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
index dde219c823b4..e2cf2dd48755 100644
--- a/arch/x86/virt/vmx/tdx/tdx.h
+++ b/arch/x86/virt/vmx/tdx/tdx.h
@@ -46,6 +46,7 @@
#define TDH_PHYMEM_PAGE_WBINVD 41
#define TDH_VP_WR 43
#define TDH_SYS_CONFIG 45
+#define TDH_SYS_DISABLE 69
/*
* SEAMCALL leaf:
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 1b2d854ba664..1ae558bcca3a 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -37,6 +37,7 @@
#include <asm/msr.h>
#include <asm/cpufeature.h>
#include <asm/tdx.h>
+#include <asm/shared/tdx_errno.h>
#include <asm/cpu_device_id.h>
#include <asm/processor.h>
#include <asm/mce.h>
@@ -1947,3 +1948,33 @@ u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, struct page *page)
return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args);
}
EXPORT_SYMBOL_FOR_KVM(tdh_phymem_page_wbinvd_hkid);
+
+void tdx_sys_disable(void)
+{
+ struct tdx_module_args args = {};
+ u64 ret;
+
+ /*
+ * Don't loop forever.
+ *
+ * - TDX_INTERRUPTED_RESUMABLE guarantees forward progress between
+ * calls.
+ *
+ * - TDX_SYS_BUSY could be returned due to contention with other
+ * TDH.SYS.* SEAMCALLs, but will lock out *new* TDH.SYS.* SEAMCALLs,
+ * so that SYS.DISABLE can eventually make progress.
+ *
+ * This is a 'destructive' SEAMCALL, in that no other SEAMCALL can be
+ * run after this until a full reinitialization is done.
+ */
+ do {
+ ret = seamcall(TDH_SYS_DISABLE, &args);
+ } while (ret == TDX_INTERRUPTED_RESUMABLE || ret == TDX_SYS_BUSY);
+
+ /*
+ * Print SEAMCALL failures, but not SW-defined error codes
+ * (SEAMCALL faulted with #GP/#UD, TDX not supported).
+ */
+ if (ret && (ret & TDX_SW_ERROR) != TDX_SW_ERROR)
+ pr_err("TDH.SYS.DISABLE failed: 0x%016llx\n", ret);
+}
--
2.53.0
^ permalink raw reply related
* [PATCH v3 2/5] x86/virt/tdx: Pull kexec cache flush logic into arch/x86
From: Vishal Verma @ 2026-04-02 6:32 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe,
Sean Christopherson, Paolo Bonzini
Cc: linux-kernel, linux-coco, kvm, Vishal Verma, Chao Gao, Kai Huang
In-Reply-To: <20260402-fuller_tdx_kexec_support-v3-0-34438d7094bf@intel.com>
From: Rick Edgecombe <rick.p.edgecombe@intel.com>
KVM tries to take care of some required cache flushing earlier in the
kexec path in order to be kind to some long standing races that can occur
later in the operation. Until recently, VMXOFF was handled within KVM.
Since VMX being enabled is required to make a SEAMCALL, it had the best
per-cpu scoped operation to plug the flushing into. So it is kicked off
from there.
This early kexec cache flushing in KVM happens via a syscore shutdown
callback. Now that VMX enablement control has moved to arch/x86, which has
grown its own syscore shutdown callback, it no longer make sense for it to
live in KVM. It fits better with the TDX enablement managing code.
In addition, future changes will add a SEAMCALL that happens immediately
before VMXOFF, which means the cache flush in KVM will be too late to
flush the cache before the last SEAMCALL. So move it to the newly added TDX
arch/x86 syscore shutdown handler.
Since tdx_cpu_flush_cache_for_kexec() is no longer needed by KVM, make it
static and remove the export. Since it is also not part of an operation
spread across disparate components, remove the redundant comments and
verbose naming.
In the existing KVM based code, CPU offline also funnels through
tdx_cpu_flush_cache_for_kexec(). Add an explicit WBINVD in
tdx_offline_cpu() as well, even though it may be redundant with WBINVD
done elsewhere during CPU offline (e.g. hlt_play_dead()). This avoids
relying on fragile code ordering for cache coherency safety.
[Vishal: add explicit WBINVD in tdx_offline_cpu()]
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
Acked-by: Kai Huang <kai.huang@intel.com>
Acked-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
Acked-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/include/asm/tdx.h | 6 ------
arch/x86/kvm/vmx/tdx.c | 10 ----------
arch/x86/virt/vmx/tdx/tdx.c | 46 ++++++++++++++++++++++++++-------------------
3 files changed, 27 insertions(+), 35 deletions(-)
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index a149740b24e8..bf83a974a0d5 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -226,11 +226,5 @@ static inline const char *tdx_dump_mce_info(struct mce *m) { return NULL; }
static inline const struct tdx_sys_info *tdx_get_sysinfo(void) { return NULL; }
#endif /* CONFIG_INTEL_TDX_HOST */
-#ifdef CONFIG_KEXEC_CORE
-void tdx_cpu_flush_cache_for_kexec(void);
-#else
-static inline void tdx_cpu_flush_cache_for_kexec(void) { }
-#endif
-
#endif /* !__ASSEMBLER__ */
#endif /* _ASM_X86_TDX_H */
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index b7264b533feb..50a5cfdbd33e 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -440,16 +440,6 @@ void tdx_disable_virtualization_cpu(void)
tdx_flush_vp(&arg);
}
local_irq_restore(flags);
-
- /*
- * Flush cache now if kexec is possible: this is necessary to avoid
- * having dirty private memory cachelines when the new kernel boots,
- * but WBINVD is a relatively expensive operation and doing it during
- * kexec can exacerbate races in native_stop_other_cpus(). Do it
- * now, since this is a safe moment and there is going to be no more
- * TDX activity on this CPU from this point on.
- */
- tdx_cpu_flush_cache_for_kexec();
}
#define TDX_SEAMCALL_RETRIES 10000
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index cb9b3210ab71..1b2d854ba664 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -184,6 +184,17 @@ static int tdx_online_cpu(unsigned int cpu)
return ret;
}
+static void tdx_cpu_flush_cache(void)
+{
+ lockdep_assert_preemption_disabled();
+
+ if (!this_cpu_read(cache_state_incoherent))
+ return;
+
+ wbinvd();
+ this_cpu_write(cache_state_incoherent, false);
+}
+
static int tdx_offline_cpu(unsigned int cpu)
{
int i;
@@ -220,12 +231,28 @@ static int tdx_offline_cpu(unsigned int cpu)
return -EBUSY;
done:
+ /*
+ * Flush cache on the CPU going offline to ensure no dirty
+ * cachelines of TDX private memory remain. This may be
+ * redundant with WBINVD done elsewhere during CPU offline
+ * (e.g. hlt_play_dead()), but do it explicitly for safety.
+ */
+ tdx_cpu_flush_cache();
x86_virt_put_ref(X86_FEATURE_VMX);
return 0;
}
static void tdx_shutdown_cpu(void *ign)
{
+ /*
+ * Flush cache in preparation for kexec - this is necessary to avoid
+ * having dirty private memory cachelines when the new kernel boots,
+ * but WBINVD is a relatively expensive operation and doing it during
+ * kexec can exacerbate races in native_stop_other_cpus(). Do it
+ * now, since this is a safe moment and there is going to be no more
+ * TDX activity on this CPU from this point on.
+ */
+ tdx_cpu_flush_cache();
x86_virt_put_ref(X86_FEATURE_VMX);
}
@@ -1920,22 +1947,3 @@ u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, struct page *page)
return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args);
}
EXPORT_SYMBOL_FOR_KVM(tdh_phymem_page_wbinvd_hkid);
-
-#ifdef CONFIG_KEXEC_CORE
-void tdx_cpu_flush_cache_for_kexec(void)
-{
- lockdep_assert_preemption_disabled();
-
- if (!this_cpu_read(cache_state_incoherent))
- return;
-
- /*
- * Private memory cachelines need to be clean at the time of
- * kexec. Write them back now, as the caller promises that
- * there should be no more SEAMCALLs on this CPU.
- */
- wbinvd();
- this_cpu_write(cache_state_incoherent, false);
-}
-EXPORT_SYMBOL_FOR_KVM(tdx_cpu_flush_cache_for_kexec);
-#endif
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox