* Re: [PATCH 1/2] KVM: SEV: IBPB-on-Entry guest support
From: Kim Phillips @ 2026-01-29 0:38 UTC (permalink / raw)
To: Borislav Petkov
Cc: linux-kernel, kvm, linux-coco, x86, Sean Christopherson,
Paolo Bonzini, K Prateek Nayak, Nikunj A Dadhania, Tom Lendacky,
Michael Roth, Naveen Rao, David Kaplan, stable
In-Reply-To: <20260128192312.GQaXpiIL4YFmQB2LKL@fat_crate.local>
Hi Boris,
On 1/28/26 1:23 PM, Borislav Petkov wrote:
> On Mon, Jan 26, 2026 at 04:42:04PM -0600, Kim Phillips wrote:
>> The SEV-SNP IBPB-on-Entry feature does not require a guest-side
>> implementation. The feature was added in Zen5 h/w, after the first
>> SNP Zen implementation, and thus was not accounted for when the
>> initial set of SNP features were added to the kernel.
>>
>> In its abundant precaution, commit 8c29f0165405 ("x86/sev: Add SEV-SNP
>> guest feature negotiation support") included SEV_STATUS' IBPB-on-Entry
>> bit as a reserved bit, thereby masking guests from using the feature.
>>
>> Unmask the bit, to allow guests to take advantage of the feature on
>> hypervisor kernel versions that support it: Amend the SEV_STATUS MSR
>> SNP_RESERVED_MASK to exclude bit 23 (IbpbOnEntry).
> Do not explain what the patch does.
For that last paragraph, how about:
"Allow guests to make use of IBPB-on-Entry when supported by the
hypervisor, as the bit is now architecturally defined and safe to
expose."
?
>> Fixes: 8c29f0165405 ("x86/sev: Add SEV-SNP guest feature negotiation support")
>> Cc: Nikunj A Dadhania <nikunj@amd.com>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> CC: Borislav Petkov (AMD) <bp@alien8.de>
>> CC: Michael Roth <michael.roth@amd.com>
>> Cc: stable@kernel.org
> I guess...
Hopefully a bitfield will be carved out for these
no-explicit-guest-implementation-required bits by hardware such that we
won't need to do this again.
>> diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
>> index 4d3566bb1a93..9016a6b00bc7 100644
>> --- a/arch/x86/include/asm/msr-index.h
>> +++ b/arch/x86/include/asm/msr-index.h
>> @@ -735,7 +735,10 @@
>> #define MSR_AMD64_SNP_SMT_PROT BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT)
>> #define MSR_AMD64_SNP_SECURE_AVIC_BIT 18
>> #define MSR_AMD64_SNP_SECURE_AVIC BIT_ULL(MSR_AMD64_SNP_SECURE_AVIC_BIT)
>> -#define MSR_AMD64_SNP_RESV_BIT 19
>> +#define MSR_AMD64_SNP_RESERVED_BITS19_22 GENMASK_ULL(22, 19)
>> +#define MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT 23
>> +#define MSR_AMD64_SNP_IBPB_ON_ENTRY BIT_ULL(MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT)
> Why isn't this part of SNP_FEATURES_PRESENT?
>
> If this feature doesn't require guest-side support, then it is trivially
> present, no?
SNP_FEATURES_PRESENT is for the non-trivial variety: Its bits get set as
part of the patchseries that add the explicit guest support *code*.
I believe 'features' like PREVENT_HOST_IBS are similar in this regard.
>> +#define MSR_AMD64_SNP_RESV_BIT 24
>> #define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT)
>> #define MSR_AMD64_SAVIC_CONTROL 0xc0010138
>> #define MSR_AMD64_SAVIC_EN_BIT 0
>> --
> I guess this is a fix of sorts and I could take it in now once all review
> comments have been addressed...
Cool, thanks.
Kim
^ permalink raw reply
* Re: [PATCH v3 09/26] coco/tdx-host: Expose P-SEAMLDR information via sysfs
From: Dave Hansen @ 2026-01-29 0:08 UTC (permalink / raw)
To: Chao Gao, linux-coco, linux-kernel, kvm, x86
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma, Farrah Chen
In-Reply-To: <20260123145645.90444-10-chao.gao@intel.com>
On 1/23/26 06:55, Chao Gao wrote:
...
> diff --git a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host b/Documentation/ABI/testing/sysfs-devices-faux-tdx-host
> index 901abbae2e61..a3f155977016 100644
> --- a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host
> +++ b/Documentation/ABI/testing/sysfs-devices-faux-tdx-host
> @@ -4,3 +4,28 @@ Description: (RO) Report the version of the loaded TDX Module. The TDX Module
> version is formatted as x.y.z, where "x" is the major version,
> "y" is the minor version and "z" is the update version. Versions
> are used for bug reporting, TDX Module updates and etc.
> +
> +What: /sys/devices/faux/tdx_host/seamldr/version
> +Contact: linux-coco@lists.linux.dev
> +Description: (RO) Report the version of the loaded SEAM loader. The SEAM
> + loader version is formatted as x.y.z, where "x" is the major
> + version, "y" is the minor version and "z" is the update version.
> + Versions are used for bug reporting and compatibility check.
checks ^
> +What: /sys/devices/faux/tdx_host/seamldr/num_remaining_updates
> +Contact: linux-coco@lists.linux.dev
> +Description: (RO) Report the number of remaining updates that can be performed.
> + The CPU keeps track of TCB versions for each TDX Module that
> + has been loaded. Since this tracking database has finite
> + capacity, there's a maximum number of Module updates that can
> + be performed.
Is it really the CPU? Or some SEAM software construct?
> + After each successful update, the number reduces by one. Once it
> + reaches zero, further updates will fail until next reboot. The
> + number is always zero if P-SEAMLDR doesn't support updates.
> +
> + See Intel® Trust Domain Extensions - SEAM Loader (SEAMLDR)
> + Interface Specification Chapter 3.3 "SEAMLDR_INFO" and Chapter
> + 4.2 "SEAMLDR.INSTALL" for more information. The documentation is
> + available at:
> + https://cdrdv2-public.intel.com/739045/intel-tdx-seamldr-interface-specification.pdf
Zap the URL. It's just going bit rot. Keep the document name. That's
googleable.
> diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-host/tdx-host.c
> index 0424933b2560..f4ce89522806 100644
> --- a/drivers/virt/coco/tdx-host/tdx-host.c
> +++ b/drivers/virt/coco/tdx-host/tdx-host.c
> @@ -11,6 +11,7 @@
> #include <linux/sysfs.h>
>
> #include <asm/cpu_device_id.h>
> +#include <asm/seamldr.h>
> #include <asm/tdx.h>
>
> static const struct x86_cpu_id tdx_host_ids[] = {
> @@ -40,7 +41,64 @@ static struct attribute *tdx_host_attrs[] = {
> &dev_attr_version.attr,
> NULL,
> };
> -ATTRIBUTE_GROUPS(tdx_host);
> +
> +struct attribute_group tdx_host_group = {
> + .attrs = tdx_host_attrs,
> +};
> +
> +#ifdef CONFIG_INTEL_TDX_MODULE_UPDATE
> +static ssize_t seamldr_version_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + const struct seamldr_info *info = seamldr_get_info();
Uhh... seamldr_get_info() calls down into the SEAMLDR. It happily zaps
the VMCS and this is surely a slow thing. This also has 0444 permissions
which means *ANYONE* can call this. Constantly. As fast as they can make
a few syscalls.
Right?
Are there any concerns about making SEAMLDR calls? Are there any
system-wide performance implications? How long of an interrupt-blocking
blip is there for this?
Also, what's the locking around seamldr_get_info()? It writes into a
global, shared structure. I guess you disabled interrupts so it's
preempt safe at least. <sigh>
I guess it won't change *that* much. But, sheesh, it seems like an
awfully bad idea to have lots of CPUs writing into a common data
structure all at the same time.
^ permalink raw reply
* Re: [PATCH v3 08/26] x86/virt/seamldr: Retrieve P-SEAMLDR information
From: Dave Hansen @ 2026-01-28 23:57 UTC (permalink / raw)
To: Chao Gao, linux-coco, linux-kernel, kvm, x86
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma, Farrah Chen,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin
In-Reply-To: <20260123145645.90444-9-chao.gao@intel.com>
On 1/23/26 06:55, Chao Gao wrote:
> +static struct seamldr_info seamldr_info __aligned(256);
I also wonder if this should be __read_mostly or even read-only after
boot. Is it ever modified?
^ permalink raw reply
* Re: [PATCH v3 08/26] x86/virt/seamldr: Retrieve P-SEAMLDR information
From: Dave Hansen @ 2026-01-28 23:54 UTC (permalink / raw)
To: Chao Gao, linux-coco, linux-kernel, kvm, x86
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma, Farrah Chen,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin
In-Reply-To: <20260123145645.90444-9-chao.gao@intel.com>
On 1/23/26 06:55, Chao Gao wrote:
> P-SEAMLDR returns its information e.g., version and supported features, in
> response to the SEAMLDR.INFO SEAMCALL.
>
> This information is useful for userspace. For example, the admin can decide
> which TDX module versions are compatible with the P-SEAMLDR according to
> the P-SEAMLDR version.
>
> Add and export seamldr_get_info() which retrieves P-SEAMLDR information by
I don't need to know what the function name is. That's in the code.
> invoking SEAMLDR.INFO SEAMCALL in preparation for exposing P-SEAMLDR
> version and other necessary information to userspace.
I also want to know what spec you are getting this out of.
I think it's also worth calling out that there are SEAMLDR calls for both:
SEAMLDR_INFO
and
SEAMLDR_SEAMINFO
Which is astonishingly confusing. Please have mercy on folks that are
looking through the docs for the first time and explain this.
> diff --git a/arch/x86/include/asm/seamldr.h b/arch/x86/include/asm/seamldr.h
> new file mode 100644
> index 000000000000..d1e9f6e16e8d
> --- /dev/null
> +++ b/arch/x86/include/asm/seamldr.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ASM_X86_SEAMLDR_H
> +#define _ASM_X86_SEAMLDR_H
> +
> +#include <linux/types.h>
> +
> +struct seamldr_info {
/*
* This called the "SEAMLDR_INFO" data structure and is defined
* in "SEAM Loader (SEAMLDR) Interface Specification".
*/
> + u32 version;
> + u32 attributes;
> + u32 vendor_id;
> + u32 build_date;
> + u16 build_num;
> + u16 minor_version;
> + u16 major_version;
> + u16 update_version;
> + u8 reserved0[4];
Why not label this:
u32 acm_x2apicid: /* unused by kernel */
?
> + u32 num_remaining_updates;
> + u8 reserved1[224];
> +} __packed;
> +
> +#ifdef CONFIG_INTEL_TDX_MODULE_UPDATE
> +const struct seamldr_info *seamldr_get_info(void);
> +#else
> +static inline const struct seamldr_info *seamldr_get_info(void) { return NULL; }
> +#endif
> +
> +#endif
> diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamldr.c
> index b99d73f7bb08..6a83ae405fac 100644
> --- a/arch/x86/virt/vmx/tdx/seamldr.c
> +++ b/arch/x86/virt/vmx/tdx/seamldr.c
> @@ -9,9 +9,16 @@
> #include <linux/irqflags.h>
> #include <linux/types.h>
>
> +#include <asm/seamldr.h>
> +
> #include "seamcall.h"
>
> -static __maybe_unused int seamldr_call(u64 fn, struct tdx_module_args *args)
> +/* P-SEAMLDR SEAMCALL leaf function */
> +#define P_SEAMLDR_INFO 0x8000000000000000
/*
* The SEAMLDR.INFO documentation requires
* this to be aligned to a 256-byte boundary.
*/
> +static struct seamldr_info seamldr_info __aligned(256);
> +
> +static inline int seamldr_call(u64 fn, struct tdx_module_args *args)
> {
> unsigned long flags;
> u64 vmcs;
> @@ -54,3 +61,11 @@ static __maybe_unused int seamldr_call(u64 fn, struct tdx_module_args *args)
> WARN_ONCE(1, "Failed to save/restore the current VMCS");
> return -EIO;
> }
> +
> +const struct seamldr_info *seamldr_get_info(void)
> +{
> + struct tdx_module_args args = { .rcx = __pa(&seamldr_info) };
> +
> + return seamldr_call(P_SEAMLDR_INFO, &args) ? NULL : &seamldr_info;
> +}
> +EXPORT_SYMBOL_FOR_MODULES(seamldr_get_info, "tdx-host");
I'd also prefer a
BUILD_BUG_ON(sizeof(struct seamldr_info) != 2048);
just as a sanity check. It doesn't cost anything and it makes sure that
as you muck around with reserved fields and padding that there's at
least one check making sure it's OK.
^ permalink raw reply
* Re: [PATCH v3 07/26] x86/virt/seamldr: Introduce a wrapper for P-SEAMLDR SEAMCALLs
From: Dave Hansen @ 2026-01-28 23:36 UTC (permalink / raw)
To: Chao Gao, linux-coco, linux-kernel, kvm, x86
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma, Farrah Chen,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin
In-Reply-To: <20260123145645.90444-8-chao.gao@intel.com>
On 1/23/26 06:55, Chao Gao wrote:
...
> +static __maybe_unused int seamldr_call(u64 fn, struct tdx_module_args *args)
> +{
> + unsigned long flags;
> + u64 vmcs;
> + int ret;
> +
> + if (!is_seamldr_call(fn))
> + return -EINVAL;
Why is this here? We shouldn't be silently papering over kernel bugs.
This is a WARN_ON() at *best*, but it also begs the question of how a
non-SEAMLDR call even got here.
> + /*
> + * SEAMRET from P-SEAMLDR invalidates the current VMCS. Save/restore
> + * the VMCS across P-SEAMLDR SEAMCALLs to avoid clobbering KVM state.
> + * Disable interrupts as KVM is allowed to do VMREAD/VMWRITE in IRQ
> + * context (but not NMI context).
> + */
I think you mean:
WARN_ON(in_nmi());
> + local_irq_save(flags);
> +
> + asm goto("1: vmptrst %0\n\t"
> + _ASM_EXTABLE(1b, %l[error])
> + : "=m" (vmcs) : : "cc" : error);
I'd much rather this be wrapped up in a helper function. We shouldn't
have to look at the horrors of inline assembly like this.
But this *REALLY* wants the KVM folks to look at it. One argument is
that with the inline assembly this is nice and self-contained. The other
argument is that this completely ignores all existing KVM infrastructure
and is parallel VMCS management.
I'd be shocked if this is the one and only place in the whole kernel
that can unceremoniously zap VMX state.
I'd *bet* that you don't really need to do the vmptrld and that KVM can
figure it out because it can vmptrld on demand anyway. Something along
the lines of:
local_irq_disable();
list_for_each(handwaving...)
vmcs_clear();
ret = seamldr_prerr(fn, args);
local_irq_enable();
Basically, zap this CPU's vmcs state and then make KVM reload it at some
later time.
I'm sure Sean and Paolo will tell me if I'm crazy.
> diff --git a/drivers/virt/coco/tdx-host/Kconfig b/drivers/virt/coco/tdx-host/Kconfig
> index e58bad148a35..6a9199e6c2c6 100644
> --- a/drivers/virt/coco/tdx-host/Kconfig
> +++ b/drivers/virt/coco/tdx-host/Kconfig
> @@ -8,3 +8,13 @@ config TDX_HOST_SERVICES
>
> Say y or m if enabling support for confidential virtual machine
> support (CONFIG_INTEL_TDX_HOST). The module is called tdx_host.ko
> +
> +config INTEL_TDX_MODULE_UPDATE
> + bool "Intel TDX module runtime update"
> + depends on TDX_HOST_SERVICES
> + help
> + This enables the kernel to support TDX module runtime update. This
> + allows the admin to update the TDX module to another compatible
> + version without the need to terminate running TDX guests.
... as opposed to the method that the kernel has to update the module
without terminating guests? ;)
> + If unsure, say N.
Let's call this:
config
INTEL_TDX_ONLY_DISABLE_THIS_IF_YOU_HATE_SECURITY_AND_IF_YOU_DO_WHY_ARE_YOU_RUNNING_TDX?
Can we have question marks in config symbol names? ;)
But, seriously, what the heck? Who would disable security updates for
their confidential computing infrastructure? Is this some kind of
intelligence test for our users so that if someone disables it we can
just laugh at them?
^ permalink raw reply
* Re: [PATCH v3 07/26] x86/virt/seamldr: Introduce a wrapper for P-SEAMLDR SEAMCALLs
From: Dave Hansen @ 2026-01-28 23:04 UTC (permalink / raw)
To: Chao Gao, linux-coco, linux-kernel, kvm, x86
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma, Farrah Chen,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin
In-Reply-To: <20260123145645.90444-8-chao.gao@intel.com>
On 1/23/26 06:55, Chao Gao wrote:
> SEAMRET from the P-SEAMLDR clears the current VMCS structure pointed
> to by the current-VMCS pointer. A VMM that invokes the P-SEAMLDR
> using SEAMCALL must reload the current-VMCS, if required, using the
> VMPTRLD instruction.
That seems pretty mean.
This is going to need a lot more justification for why this is an
absolutely necessary requirement.
KVM folks, are you OK with this?
^ permalink raw reply
* Re: [PATCH v3 06/26] x86/virt/tdx: Prepare to support P-SEAMLDR SEAMCALLs
From: Dave Hansen @ 2026-01-28 23:03 UTC (permalink / raw)
To: Chao Gao, linux-coco, linux-kernel, kvm, x86
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma, Farrah Chen,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin
In-Reply-To: <20260123145645.90444-7-chao.gao@intel.com>
On 1/23/26 06:55, Chao Gao wrote:
> P-SEAMLDR is another component alongside the TDX module within the
> protected SEAM range. P-SEAMLDR can update the TDX module at runtime.
> Software can talk with P-SEAMLDR via SEAMCALLs with the bit 63 of RAX
> (leaf number) set to 1 (a.k.a P-SEAMLDR SEAMCALLs).
This text kinda bugs me. It's OK, but needs improvement.
First, don't explain the ABI in the changelog. Nobody cares that it's
bit 63.
Background:
The TDX architecture uses the "SEAMCALL" instruction to
communicate with SEAM mode software. Right now, the only SEAM
mode software that the kernel communicates with is the TDX
module. But, there are actually some components that run in SEAM
mode but that are separate from the TDX module: that SEAM
loaders. Right now, the only component that communicates with
them is the BIOS which loads the TDX module itself at boot. But,
to support updating the TDX module, the kernel now needs to be
able to talk to one of the the SEAM loaders: the Persistent
loader or "P-SEAMLDR".
Then do this part:
> P-SEAMLDR SEAMCALLs differ from SEAMCALLs of the TDX module in terms of
> error codes and the handling of the current VMCS.
Except I don't even know how the TDX module handles the current VMCS.
That probably needs to be in there. Or, it should be brought up in the
patch itself that implements this. Or, uplifted to the cover letter.
> In preparation for adding support for P-SEAMLDR SEAMCALLs, do the two
> following changes to SEAMCALL low-level helpers:
>
> 1) Tweak sc_retry() to retry on "lack of entropy" errors reported by
> P-SEAMLDR because it uses a different error code.
>
> 2) Add seamldr_err() to log error messages on P-SEAMLDR SEAMCALL failures.
> diff --git a/arch/x86/virt/vmx/tdx/seamcall.h b/arch/x86/virt/vmx/tdx/seamcall.h
> index 0912e03fabfe..256f71d6ca70 100644
> --- a/arch/x86/virt/vmx/tdx/seamcall.h
> +++ b/arch/x86/virt/vmx/tdx/seamcall.h
> @@ -34,15 +34,28 @@ static __always_inline u64 __seamcall_dirty_cache(sc_func_t func, u64 fn,
> return func(fn, args);
> }
>
> +#define SEAMLDR_RND_NO_ENTROPY 0x8000000000030001ULL
<sigh>
#define TDX_RND_NO_ENTROPY 0x8000020300000000ULL
So they're not even close values. They're not consistent or even a bit
off or anything.
Honestly, this needs a justification for why this was done this way. Why
can't "SEAM mode" be a monolithic thing from the kernel's perspective?
> +#define SEAMLDR_SEAMCALL_MASK _BITUL(63)
> +
> +static inline bool is_seamldr_call(u64 fn)
> +{
> + return fn & SEAMLDR_SEAMCALL_MASK;
> +}
> +
> static __always_inline u64 sc_retry(sc_func_t func, u64 fn,
> struct tdx_module_args *args)
> {
> + u64 retry_code = TDX_RND_NO_ENTROPY;
> int retry = RDRAND_RETRY_LOOPS;
> u64 ret;
>
> + if (unlikely(is_seamldr_call(fn)))
> + retry_code = SEAMLDR_RND_NO_ENTROPY;
(un)likey() has two uses:
1. It's in performance critical code and compilers have been
demonstrated to be generating bad code.
2. It's in code where it's not obvious what the fast path is
and (un)likey() makes the code more readable.
Which one is this?
Second, this is nitpicky, but I'd rather this be:
if (is_seamldr_call(fn))
retry_code = SEAMLDR_RND_NO_ENTROPY;
else
retry_code = TDX_RND_NO_ENTROPY;
or even:
retry_code = TDX_RND_NO_ENTROPY;
if (is_seamldr_call(fn))
retry_code = SEAMLDR_RND_NO_ENTROPY;
That makes it trivial that 'retry_code' can only have two values. It's
nitpicky because the original initialization is so close.
> do {
> ret = func(fn, args);
> - } while (ret == TDX_RND_NO_ENTROPY && --retry);
> + } while (ret == retry_code && --retry);
>
> return ret;
> }
> @@ -68,6 +81,16 @@ static inline void seamcall_err_ret(u64 fn, u64 err,
> args->r9, args->r10, args->r11);
> }
>
> +static inline void seamldr_err(u64 fn, u64 err, struct tdx_module_args *args)
> +{
> + /*
> + * Note: P-SEAMLDR leaf numbers are printed in hex as they have
> + * bit 63 set, making them hard to read and understand if printed
> + * in decimal
> + */
> + pr_err("P-SEAMLDR (%llx) failed: %#016llx\n", fn, err);
> +}
Oh, lovely.
Didn't you just propose changing the module SEAMCALL leaf numbers in
decimal? Isn't it a little crazy to do one in decimal and the other in hex?
I'd really rather just see the TDX documentation changed.
But, honestly, I'd probably just leave the thing in hex, drop this hunk,
and go thwack someone that writes TDX module documentation instead.
> static __always_inline int sc_retry_prerr(sc_func_t func,
> sc_err_func_t err_func,
> u64 fn, struct tdx_module_args *args)
> @@ -96,4 +119,7 @@ static __always_inline int sc_retry_prerr(sc_func_t func,
> #define seamcall_prerr_ret(__fn, __args) \
> sc_retry_prerr(__seamcall_ret, seamcall_err_ret, (__fn), (__args))
>
> +#define seamldr_prerr(__fn, __args) \
> + sc_retry_prerr(__seamcall, seamldr_err, (__fn), (__args))
> +
> #endif
So, honestly, for me, it's a NAK for this whole patch.
Go change the P-SEAMLDR to use the same error code as the TDX module,
and fix the documentation. No kernel changes, please.
^ permalink raw reply
* Re: [PATCH v3 24/26] x86/virt/seamldr: Extend sigstruct to 16KB
From: Huang, Kai @ 2026-01-28 23:01 UTC (permalink / raw)
To: kvm@vger.kernel.org, linux-coco@lists.linux.dev,
linux-kernel@vger.kernel.org, Gao, Chao, x86@kernel.org
Cc: dave.hansen@linux.intel.com, kas@kernel.org, mingo@redhat.com,
seanjc@google.com, Weiny, Ira, Chatre, Reinette,
tglx@linutronix.de, nik.borisov@suse.com, Verma, Vishal L,
hpa@zytor.com, sagis@google.com, Annapurve, Vishal,
Duan, Zhenzhong, Edgecombe, Rick P, paulmck@kernel.org,
bp@alien8.de, yilun.xu@linux.intel.com, Williams, Dan J
In-Reply-To: <20260123145645.90444-25-chao.gao@intel.com>
On Fri, 2026-01-23 at 06:55 -0800, Chao Gao wrote:
> Currently, each TDX Module has a 4KB sigstruct that is passed to the
> P-SEAMLDR during module updates to authenticate the TDX Module binary.
>
> Future TDX Module versions will pack additional information into the
> sigstruct, which will exceed the current 4KB size limit.
>
> To accommodate this, the sigstruct is being extended to support up to
> 16KB. Update seamldr_params and tdx-blob structures to handle the larger
> sigstruct size.
>
> Signed-off-by: Chao Gao <chao.gao@intel.com>
> ---
> arch/x86/virt/vmx/tdx/seamldr.c | 28 +++++++++++++++++++---------
> 1 file changed, 19 insertions(+), 9 deletions(-)
>
> diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamldr.c
> index d2d85114d6c4..9e77b24f659c 100644
> --- a/arch/x86/virt/vmx/tdx/seamldr.c
> +++ b/arch/x86/virt/vmx/tdx/seamldr.c
> @@ -29,6 +29,8 @@
> /* P-SEAMLDR can accept up to 496 4KB pages for TDX module binary */
> #define SEAMLDR_MAX_NR_MODULE_4KB_PAGES 496
>
> +#define SEAMLDR_MAX_NR_SIG_4KB_PAGES 4
> +
> /* scenario field in struct seamldr_params */
> #define SEAMLDR_SCENARIO_UPDATE 1
>
> @@ -40,8 +42,8 @@
> struct seamldr_params {
> u32 version;
> u32 scenario;
> - u64 sigstruct_pa;
> - u8 reserved[104];
> + u64 sigstruct_pa[SEAMLDR_MAX_NR_SIG_4KB_PAGES];
> + u8 reserved[80];
> u64 num_module_pages;
> u64 mod_pages_pa_list[SEAMLDR_MAX_NR_MODULE_4KB_PAGES];
> } __packed;
> @@ -121,7 +123,10 @@ static struct seamldr_params *alloc_seamldr_params(const void *module, unsigned
> if (module_size > SEAMLDR_MAX_NR_MODULE_4KB_PAGES * SZ_4K)
> return ERR_PTR(-EINVAL);
>
> - if (!IS_ALIGNED(module_size, SZ_4K) || sig_size != SZ_4K ||
> + if (sig_size > SEAMLDR_MAX_NR_SIG_4KB_PAGES * SZ_4K)
> + return ERR_PTR(-EINVAL);
> +
> + if (!IS_ALIGNED(module_size, SZ_4K) || !IS_ALIGNED(sig_size, SZ_4K) ||
> !IS_ALIGNED((unsigned long)module, SZ_4K) ||
> !IS_ALIGNED((unsigned long)sig, SZ_4K))
> return ERR_PTR(-EINVAL);
> @@ -132,12 +137,17 @@ static struct seamldr_params *alloc_seamldr_params(const void *module, unsigned
>
> params->scenario = SEAMLDR_SCENARIO_UPDATE;
>
> - /*
> - * Don't assume @sig is page-aligned although it is 4KB-aligned.
> - * Always add the in-page offset to get the physical address.
> - */
> - params->sigstruct_pa = (vmalloc_to_pfn(sig) << PAGE_SHIFT) +
> - ((unsigned long)sig & ~PAGE_MASK);
> + ptr = sig;
> + for (i = 0; i < sig_size / SZ_4K; i++) {
> + /*
> + * Don't assume @sig is page-aligned although it is 4KB-aligned.
> + * Always add the in-page offset to get the physical address.
> + */
> + params->sigstruct_pa[i] = (vmalloc_to_pfn(ptr) << PAGE_SHIFT) +
> + ((unsigned long)ptr & ~PAGE_MASK);
> + ptr += SZ_4K;
> + }
> +
> params->num_module_pages = module_size / SZ_4K;
>
> ptr = module;
Let's move the discussion here (from patch 13 -- sorry about that):
IIRC this patch just simply re-purposes couple of reserved space in
SEAMLDR_PARAMS (which is part of P-SEAMLDR ABI) w/o enumeration, explicit
opt-in whatever. The code change here doesn't even bump up its version.
IIUC, if this code run on an old platform where SEAMLDR.INSTALL still only
works with 4K SIGSTRUCT, the SEAMLDR.INSTALL will only see part of the
SIGSTRUCT thus will likely fail.
How can we know whether a given 'struct tdx_blob' can work on an platform or
not? Or am I missing anything?
^ permalink raw reply
* Re: [PATCH v3 13/26] x86/virt/seamldr: Allocate and populate a module update request
From: Huang, Kai @ 2026-01-28 22:33 UTC (permalink / raw)
To: Gao, Chao
Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, bp@alien8.de,
dave.hansen@linux.intel.com, kas@kernel.org, mingo@redhat.com,
Weiny, Ira, linux-kernel@vger.kernel.org, seanjc@google.com,
Verma, Vishal L, nik.borisov@suse.com, Chatre, Reinette,
hpa@zytor.com, sagis@google.com, Chen, Farrah, Duan, Zhenzhong,
tglx@linutronix.de, Edgecombe, Rick P, paulmck@kernel.org,
Annapurve, Vishal, yilun.xu@linux.intel.com, x86@kernel.org,
Williams, Dan J
In-Reply-To: <aXny+UkkEzU425k6@intel.com>
On Wed, 2026-01-28 at 19:28 +0800, Gao, Chao wrote:
> On Tue, Jan 27, 2026 at 11:21:06AM +0800, Huang, Kai wrote:
> >
> > > +/*
> > > + * Allocate and populate a seamldr_params.
> > > + * Note that both @module and @sig should be vmalloc'd memory.
> > > + */
> > > +static struct seamldr_params *alloc_seamldr_params(const void *module, unsigned int module_size,
> > > + const void *sig, unsigned int sig_size)
> > > +{
> > > + struct seamldr_params *params;
> > > + const u8 *ptr;
> > > + int i;
> > > +
> > > + BUILD_BUG_ON(sizeof(struct seamldr_params) != SZ_4K);
> > > + if (module_size > SEAMLDR_MAX_NR_MODULE_4KB_PAGES * SZ_4K)
> > > + return ERR_PTR(-EINVAL);
> > > +
> > > + if (!IS_ALIGNED(module_size, SZ_4K) || sig_size != SZ_4K ||
> > > + !IS_ALIGNED((unsigned long)module, SZ_4K) ||
> > > + !IS_ALIGNED((unsigned long)sig, SZ_4K))
> > > + return ERR_PTR(-EINVAL);
> > > +
> >
> > Based on the the blob format link below, we have
> >
> > struct tdx_blob
> > {
> > ...
> > _u64 sigstruct[256]; // 2KB sigstruct,intel_tdx_module.so.sigstruct
> > _u64 reserved2[256]; // Reserved space
> > ...
> > }
> >
> > So it's clear SIGSTRUCT is just 2KB and the second half 2KB is "reserved
> > space".
> >
> > Why is the "reserved space" treated as part of SIGSTRUCT here?
>
> Good question. Because the space is reserved for sigstruct expansion.
>
> The __current__ SEAMLDR ABI accepts one 4KB page, but all __existing__
> sigstructs are only 2KB.
>
Oh I see.
I think we have two perspectives here: 1) what P-SEAMLDR ABI requires for
module and sigstruct; 2) how does the kernel get them and pass to
alloc_seamldr_params().
IIUC, I now understand alloc_seamldr_params() is expecting the 'module',
'module_size', 'sig' and 'sig_size' to meet P-SEAMCALL's ABI.
Then would it be better to add a comment for the checks of 'module',
'module_size', 'sig' and 'sig_size' in alloc_seamldr_params() (below code)
that it is P-SEAMCALL ABI that has these requirement?
if (!IS_ALIGNED(module_size, SZ_4K) || sig_size != SZ_4K ||
!IS_ALIGNED((unsigned long)module, SZ_4K) ||
!IS_ALIGNED((unsigned long)sig, SZ_4K))
return ERR_PTR(-EINVAL);
Otherwise it's a bit confusing because these 4 arguments are passed to
alloc_seamldr_params() right from the layout of 'struct tdx_blob' which is a
"software-organized" structure which, theoretically, could have nothing to
do P-SEAMLDR ABI.
> so, tdx_blob currently defines a 2KB sigstruct field
> followed by 2KB of reserved space. We anticipate that sigstructs will
> eventually exceed 4KB, so we added reserved3[N*512] to accommodate future
> growth.
>
> You're right. The current tdx_blob definition doesn't clearly indicate that
> reserved2/3 are actually part of the sigstruct.
>
> Does this revised tdx_blob definition make that clearer and better align with
> this patch?
>
Yes it's clearer, from the perspective that how it matches your code to
calculate 'sig_size'.
> The idea is to make tdx_blob generic enough to clearly represent:
> a 4KB header, followed by 4KB-aligned sigstruct, followed by the TDX Module
> binary. Current SEAMLDR ABI details or current sigstruct sizes are irrelevant.
>
> struct tdx_blob
> {
> _u16 version; // Version number
> _u16 checksum; // Checksum of the entire blob should be zero
> _u32 offset_of_module; // Offset of the module binary intel_tdx_module.bin in bytes
> _u8 signature[8]; // Must be "TDX-BLOB"
> _u32 length; // The length in bytes of the entire blob
> _u32 reserved0; // Reserved space
> _u64 reserved1[509]; // Reserved space
> _u64 sigstruct[512 + N*512]; // sigstruct, 4KB aligned
>
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> _u8 module[]; // intel_tdx_module.bin, 4KB aligned, to the end of the file
> }
>
>
> >
A side topic:
I checked the SEAMLDR.INSTALL. It appears the only requirement of the
SIGSTRUCT is it is 4K aligned. There's no where in the ABI (certainly not
in SEAMLDR_PARAMS) to tell how does SEAMLDR.INSTALL verifies the size of
SIGSTRUCT.
Is this right?
When we bumping SIGSTRUCT to a larger size, do we have some kinda
enumeration that reports such?
From your patch 24, IIUC I don't see such enumeration or explicit opt-in,
because you just changes the layout of SEAMLDR_PARAM w/o even changing it's
version.
[...]
> > But I think if we add 'sigstruct' to the 'struct tdx_blob', e.g.,
> >
> > struct tdx_blob {
> > u16 version;
> > ...
> > u64 rsvd2[509];
> > u64 sigstruct[256];
> > u64 rsvd3[256];
> > u64 data;
> > } __packed;
> >
> > .. we can just use
> >
> > sig = blob->sigstruct;
> > sig_size = 2K (or 4K I don't quite follow);
> >
> > which is clearer to read IMHO?
>
> The problem is hard-coding the sigstruct size to 2KB/4KB. This will soon no
> longer hold.
>
> But
> sig = blob->data;
> sig_size = blob->offset_of_module - sizeof(struct tdx_blob);
>
> doesn't make that assumption, making it more future-proof.
Sure. I am certainly fine with making it future-proof (albeit arguably you
could also change the way that how sig_size is calculated in the future,
i.e., in your patch 24).
But the real point is the code here needs to reflect the 'struct tdx_blob'
description in the doc. But with the current doc I don't see they match to
each other:
The doc says SIGSTRUCT is 2K but the code says it's 4K.
So I think you need to update the 'struct tdx_blob' description in the doc
to justify such code.
Btw, I think the link
https://github.com/intel/tdx-module-binaries/blob/main/blob_structure.txt
is subject to change, both the link itself and it's content.
Do you think we should just make the layout of 'struct tdx_blob' as a
documentation patch and include that to this series?
^ permalink raw reply
* Re: [PATCH v3 2/2] x86/sev: Add support to unaccept memory after hot-remove
From: Pratik R. Sampat @ 2026-01-28 22:25 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-mm, linux-coco, x86, linux-kernel, tglx, mingo, bp,
dave.hansen, kas, ardb, david, osalvador, thomas.lendacky,
michael.roth
In-Reply-To: <20260128130800.40adb423627ff6d8ffce7ccd@linux-foundation.org>
Hi Dave, Andrew
On 1/28/26 3:08 PM, Andrew Morton wrote:
> On Wed, 28 Jan 2026 14:41:05 -0600 "Pratik R. Sampat" <prsampat@amd.com> wrote:
>
>> Transition memory to the shared state during a hot-remove operation so
>> that it can be re-used by the hypervisor. This also applies when memory
>> is intended to be hotplugged back in later, as those pages will need to
>> be re-accepted after crossing the trust boundary.
>>
>> ...
>>
>> @@ -623,6 +624,7 @@ static inline int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call,
>> return -ENOTTY;
>> }
>> static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
>> +static inline void snp_unaccept_memory(phys_addr_t start, phys_addr_t end) { }
>> static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
>> static inline u64 sev_get_status(void) { return 0; }
>> static inline void sev_show_status(void) { }
>> diff --git a/arch/x86/include/asm/unaccepted_memory.h b/arch/x86/include/asm/unaccepted_memory.h
>> index f5937e9866ac..8715be843e65 100644
>> --- a/arch/x86/include/asm/unaccepted_memory.h
>> +++ b/arch/x86/include/asm/unaccepted_memory.h
>> @@ -18,6 +18,15 @@ static inline void arch_accept_memory(phys_addr_t start, phys_addr_t end)
>> }
>> }
>>
>> +static inline void arch_unaccept_memory(phys_addr_t start, phys_addr_t end)
>> +{
>> + if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) {
>> + snp_unaccept_memory(start, end);
>> + } else {
>> + panic("Cannot unaccept memory: unknown platform\n");
>
> Seems severe. Dropping a WARN() and continuing would be preferred.
>
> What exactly happened here? Am I correct in thinking that the check in
> snp_unaccept_memory() makes this a cant-happen?
>
You're right, a WARN() is probably more appropriate here.
Based on my rudimentary understanding of TDX from Kiryl, TDX module is
what maintains this metadata for the HPA.
So, maybe the WARN could just be:
"Cannot unaccept memory: VMM responsible for unaccepting memory" for
TDX? Or, we could let it fall-through for TDX (if and when there is
support for that)
>> --- a/drivers/firmware/efi/unaccepted_memory.c
>> +++ b/drivers/firmware/efi/unaccepted_memory.c
>> @@ -157,6 +157,52 @@ void accept_memory(phys_addr_t start, unsigned long size)
>> spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
>> }
>>
>> +void unaccept_memory(phys_addr_t start, unsigned long size)
>> +{
>> + unsigned long range_start, range_end, bitrange_end;
>> + struct efi_unaccepted_memory *unaccepted;
>> + phys_addr_t end = start + size;
>> + u64 unit_size, phys_base;
>> + unsigned long flags;
>> +
>> + unaccepted = efi_get_unaccepted_table();
>> + if (!unaccepted)
>> + return;
>> +
>> + phys_base = unaccepted->phys_base;
>> + unit_size = unaccepted->unit_size;
>> +
>> + if (start < unaccepted->phys_base)
>> + start = unaccepted->phys_base;
>
> max()?
>
>> + if (end < unaccepted->phys_base)
>> + return;
>> +
>> + start -= phys_base;
>> + end -= phys_base;
>> +
>> + /* Make sure not to overrun the bitmap */
>> + if (end > unaccepted->size * unit_size * BITS_PER_BYTE)
>> + end = unaccepted->size * unit_size * BITS_PER_BYTE;
>
> min()?
>
> If you like min() and max(). Sometimes I find them annoying - need to mentally
> expand them to figure out what's going on.
Same! :-)
That is why I just aped the implementation from its counterpart
accept_memory() but can definitely do it this way and shave off a couple
of lines.
Thanks,
--Pratik
>
>> + range_start = start / unit_size;
>> + bitrange_end = DIV_ROUND_UP(end, unit_size);
>> +
>> + /* Only unaccept memory that was previously accepted in the range */
>> + spin_lock_irqsave(&unaccepted_memory_lock, flags);
>> + for_each_clear_bitrange_from(range_start, range_end, unaccepted->bitmap,
>> + bitrange_end) {
>> + unsigned long phys_start, phys_end;
>> + unsigned long len = range_end - range_start;
>> +
>> + phys_start = range_start * unit_size + phys_base;
>> + phys_end = range_end * unit_size + phys_base;
>> +
>> + arch_unaccept_memory(phys_start, phys_end);
>> + bitmap_set(unaccepted->bitmap, range_start, len);
>> + }
>> + spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
>> +}
>
^ permalink raw reply
* Re: [PATCH v3 2/2] x86/sev: Add support to unaccept memory after hot-remove
From: Dave Hansen @ 2026-01-28 21:15 UTC (permalink / raw)
To: Pratik R. Sampat, linux-mm, linux-coco, x86, linux-kernel
Cc: tglx, mingo, bp, dave.hansen, kas, ardb, akpm, david, osalvador,
thomas.lendacky, michael.roth
In-Reply-To: <20260128204105.508855-3-prsampat@amd.com>
On 1/28/26 12:41, Pratik R. Sampat wrote:
> +static inline void arch_unaccept_memory(phys_addr_t start, phys_addr_t end)
> +{
> + if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) {
> + snp_unaccept_memory(start, end);
> + } else {
> + panic("Cannot unaccept memory: unknown platform\n");
> + }
> +}
This panic() is pretty nasty.
Can't we just disable memory hotplug up front if it's:
!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)
?
^ permalink raw reply
* Re: [PATCH v3 2/2] x86/sev: Add support to unaccept memory after hot-remove
From: Andrew Morton @ 2026-01-28 21:08 UTC (permalink / raw)
To: Pratik R. Sampat
Cc: linux-mm, linux-coco, x86, linux-kernel, tglx, mingo, bp,
dave.hansen, kas, ardb, david, osalvador, thomas.lendacky,
michael.roth
In-Reply-To: <20260128204105.508855-3-prsampat@amd.com>
On Wed, 28 Jan 2026 14:41:05 -0600 "Pratik R. Sampat" <prsampat@amd.com> wrote:
> Transition memory to the shared state during a hot-remove operation so
> that it can be re-used by the hypervisor. This also applies when memory
> is intended to be hotplugged back in later, as those pages will need to
> be re-accepted after crossing the trust boundary.
>
> ...
>
> @@ -623,6 +624,7 @@ static inline int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call,
> return -ENOTTY;
> }
> static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
> +static inline void snp_unaccept_memory(phys_addr_t start, phys_addr_t end) { }
> static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
> static inline u64 sev_get_status(void) { return 0; }
> static inline void sev_show_status(void) { }
> diff --git a/arch/x86/include/asm/unaccepted_memory.h b/arch/x86/include/asm/unaccepted_memory.h
> index f5937e9866ac..8715be843e65 100644
> --- a/arch/x86/include/asm/unaccepted_memory.h
> +++ b/arch/x86/include/asm/unaccepted_memory.h
> @@ -18,6 +18,15 @@ static inline void arch_accept_memory(phys_addr_t start, phys_addr_t end)
> }
> }
>
> +static inline void arch_unaccept_memory(phys_addr_t start, phys_addr_t end)
> +{
> + if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) {
> + snp_unaccept_memory(start, end);
> + } else {
> + panic("Cannot unaccept memory: unknown platform\n");
Seems severe. Dropping a WARN() and continuing would be preferred.
What exactly happened here? Am I correct in thinking that the check in
snp_unaccept_memory() makes this a cant-happen?
> --- a/drivers/firmware/efi/unaccepted_memory.c
> +++ b/drivers/firmware/efi/unaccepted_memory.c
> @@ -157,6 +157,52 @@ void accept_memory(phys_addr_t start, unsigned long size)
> spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
> }
>
> +void unaccept_memory(phys_addr_t start, unsigned long size)
> +{
> + unsigned long range_start, range_end, bitrange_end;
> + struct efi_unaccepted_memory *unaccepted;
> + phys_addr_t end = start + size;
> + u64 unit_size, phys_base;
> + unsigned long flags;
> +
> + unaccepted = efi_get_unaccepted_table();
> + if (!unaccepted)
> + return;
> +
> + phys_base = unaccepted->phys_base;
> + unit_size = unaccepted->unit_size;
> +
> + if (start < unaccepted->phys_base)
> + start = unaccepted->phys_base;
max()?
> + if (end < unaccepted->phys_base)
> + return;
> +
> + start -= phys_base;
> + end -= phys_base;
> +
> + /* Make sure not to overrun the bitmap */
> + if (end > unaccepted->size * unit_size * BITS_PER_BYTE)
> + end = unaccepted->size * unit_size * BITS_PER_BYTE;
min()?
If you like min() and max(). Sometimes I find them annoying - need to mentally
expand them to figure out what's going on.
> + range_start = start / unit_size;
> + bitrange_end = DIV_ROUND_UP(end, unit_size);
> +
> + /* Only unaccept memory that was previously accepted in the range */
> + spin_lock_irqsave(&unaccepted_memory_lock, flags);
> + for_each_clear_bitrange_from(range_start, range_end, unaccepted->bitmap,
> + bitrange_end) {
> + unsigned long phys_start, phys_end;
> + unsigned long len = range_end - range_start;
> +
> + phys_start = range_start * unit_size + phys_base;
> + phys_end = range_end * unit_size + phys_base;
> +
> + arch_unaccept_memory(phys_start, phys_end);
> + bitmap_set(unaccepted->bitmap, range_start, len);
> + }
> + spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
> +}
^ permalink raw reply
* [PATCH v3 2/2] x86/sev: Add support to unaccept memory after hot-remove
From: Pratik R. Sampat @ 2026-01-28 20:41 UTC (permalink / raw)
To: linux-mm, linux-coco, x86, linux-kernel
Cc: tglx, mingo, bp, dave.hansen, kas, ardb, akpm, david, osalvador,
thomas.lendacky, michael.roth, prsampat
In-Reply-To: <20260128204105.508855-1-prsampat@amd.com>
Transition memory to the shared state during a hot-remove operation so
that it can be re-used by the hypervisor. This also applies when memory
is intended to be hotplugged back in later, as those pages will need to
be re-accepted after crossing the trust boundary.
Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
---
arch/x86/coco/sev/core.c | 13 ++++++
arch/x86/include/asm/sev.h | 2 +
arch/x86/include/asm/unaccepted_memory.h | 9 ++++
drivers/firmware/efi/unaccepted_memory.c | 56 ++++++++++++++++++++++++
include/linux/mm.h | 9 ++++
mm/memory_hotplug.c | 2 +
6 files changed, 91 insertions(+)
diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index 9ae3b11754e6..63d8f44b76eb 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -703,6 +703,19 @@ void snp_accept_memory(phys_addr_t start, phys_addr_t end)
set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE);
}
+void snp_unaccept_memory(phys_addr_t start, phys_addr_t end)
+{
+ unsigned long vaddr, npages;
+
+ if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+ return;
+
+ vaddr = (unsigned long)__va(start);
+ npages = (end - start) >> PAGE_SHIFT;
+
+ set_pages_state(vaddr, npages, SNP_PAGE_STATE_SHARED);
+}
+
static int vmgexit_ap_control(u64 event, struct sev_es_save_area *vmsa, u32 apic_id)
{
bool create = event != SVM_VMGEXIT_AP_DESTROY;
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 0e6c0940100f..3327de663793 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -514,6 +514,7 @@ bool snp_init(struct boot_params *bp);
void snp_dmi_setup(void);
int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, struct svsm_attest_call *input);
void snp_accept_memory(phys_addr_t start, phys_addr_t end);
+void snp_unaccept_memory(phys_addr_t start, phys_addr_t end);
u64 snp_get_unsupported_features(u64 status);
u64 sev_get_status(void);
void sev_show_status(void);
@@ -623,6 +624,7 @@ static inline int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call,
return -ENOTTY;
}
static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
+static inline void snp_unaccept_memory(phys_addr_t start, phys_addr_t end) { }
static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
static inline u64 sev_get_status(void) { return 0; }
static inline void sev_show_status(void) { }
diff --git a/arch/x86/include/asm/unaccepted_memory.h b/arch/x86/include/asm/unaccepted_memory.h
index f5937e9866ac..8715be843e65 100644
--- a/arch/x86/include/asm/unaccepted_memory.h
+++ b/arch/x86/include/asm/unaccepted_memory.h
@@ -18,6 +18,15 @@ static inline void arch_accept_memory(phys_addr_t start, phys_addr_t end)
}
}
+static inline void arch_unaccept_memory(phys_addr_t start, phys_addr_t end)
+{
+ if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) {
+ snp_unaccept_memory(start, end);
+ } else {
+ panic("Cannot unaccept memory: unknown platform\n");
+ }
+}
+
static inline struct efi_unaccepted_memory *efi_get_unaccepted_table(void)
{
if (efi.unaccepted == EFI_INVALID_TABLE_ADDR)
diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c
index 5a4c8b0f56c8..9f1d594dba33 100644
--- a/drivers/firmware/efi/unaccepted_memory.c
+++ b/drivers/firmware/efi/unaccepted_memory.c
@@ -157,6 +157,52 @@ void accept_memory(phys_addr_t start, unsigned long size)
spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
}
+void unaccept_memory(phys_addr_t start, unsigned long size)
+{
+ unsigned long range_start, range_end, bitrange_end;
+ struct efi_unaccepted_memory *unaccepted;
+ phys_addr_t end = start + size;
+ u64 unit_size, phys_base;
+ unsigned long flags;
+
+ unaccepted = efi_get_unaccepted_table();
+ if (!unaccepted)
+ return;
+
+ phys_base = unaccepted->phys_base;
+ unit_size = unaccepted->unit_size;
+
+ if (start < unaccepted->phys_base)
+ start = unaccepted->phys_base;
+ if (end < unaccepted->phys_base)
+ return;
+
+ start -= phys_base;
+ end -= phys_base;
+
+ /* Make sure not to overrun the bitmap */
+ if (end > unaccepted->size * unit_size * BITS_PER_BYTE)
+ end = unaccepted->size * unit_size * BITS_PER_BYTE;
+
+ range_start = start / unit_size;
+ bitrange_end = DIV_ROUND_UP(end, unit_size);
+
+ /* Only unaccept memory that was previously accepted in the range */
+ spin_lock_irqsave(&unaccepted_memory_lock, flags);
+ for_each_clear_bitrange_from(range_start, range_end, unaccepted->bitmap,
+ bitrange_end) {
+ unsigned long phys_start, phys_end;
+ unsigned long len = range_end - range_start;
+
+ phys_start = range_start * unit_size + phys_base;
+ phys_end = range_end * unit_size + phys_base;
+
+ arch_unaccept_memory(phys_start, phys_end);
+ bitmap_set(unaccepted->bitmap, range_start, len);
+ }
+ spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
+}
+
bool range_contains_unaccepted_memory(phys_addr_t start, unsigned long size)
{
struct efi_unaccepted_memory *unaccepted;
@@ -227,6 +273,16 @@ void accept_hotplug_memory(phys_addr_t start, unsigned long size)
arch_accept_memory(start, start + size);
}
+void unaccept_hotplug_memory(phys_addr_t start, unsigned long size)
+{
+ if (range_contains_unaccepted_memory(start, size)) {
+ unaccept_memory(start, size);
+ return;
+ }
+
+ arch_unaccept_memory(start, start + size);
+}
+
#ifdef CONFIG_PROC_VMCORE
static bool unaccepted_memory_vmcore_pfn_is_ram(struct vmcore_cb *cb,
unsigned long pfn)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2d3c1ea40606..faefaa9b92c6 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4504,7 +4504,9 @@ int set_anon_vma_name(unsigned long addr, unsigned long size,
bool range_contains_unaccepted_memory(phys_addr_t start, unsigned long size);
void accept_memory(phys_addr_t start, unsigned long size);
+void unaccept_memory(phys_addr_t start, unsigned long size);
void accept_hotplug_memory(phys_addr_t start, unsigned long size);
+void unaccept_hotplug_memory(phys_addr_t start, unsigned long size);
#else
@@ -4518,10 +4520,17 @@ static inline void accept_memory(phys_addr_t start, unsigned long size)
{
}
+static inline void unaccept_memory(phys_addr_t start, unsigned long size)
+{
+}
+
static inline void accept_hotplug_memory(phys_addr_t start, unsigned long size)
{
}
+static inline void unaccept_hotplug_memory(phys_addr_t start, unsigned long size)
+{
+}
#endif
static inline bool pfn_is_unaccepted_memory(unsigned long pfn)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 549ccfd190ee..21b87f2af930 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -2240,6 +2240,8 @@ static int try_remove_memory(u64 start, u64 size)
mem_hotplug_begin();
+ unaccept_hotplug_memory(start, size);
+
rc = memory_blocks_have_altmaps(start, size);
if (rc < 0) {
mem_hotplug_done();
--
2.52.0
^ permalink raw reply related
* [PATCH v3 1/2] mm/memory_hotplug: Add support to accept memory during hot-add
From: Pratik R. Sampat @ 2026-01-28 20:41 UTC (permalink / raw)
To: linux-mm, linux-coco, x86, linux-kernel
Cc: tglx, mingo, bp, dave.hansen, kas, ardb, akpm, david, osalvador,
thomas.lendacky, michael.roth, prsampat
In-Reply-To: <20260128204105.508855-1-prsampat@amd.com>
Confidential computing guests require memory to be accepted before use.
The unaccepted memory bitmap maintained by firmware does not track
most hotplugged memory ranges apart from system memory annotated to be
cold plugged at boot.
Explicitly validate and transition the newly added memory to a private
state, making it usable by the guest.
Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
---
drivers/firmware/efi/unaccepted_memory.c | 18 ++++++++++++++++++
include/linux/mm.h | 5 +++++
mm/memory_hotplug.c | 2 ++
3 files changed, 25 insertions(+)
diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c
index c2c067eff634..5a4c8b0f56c8 100644
--- a/drivers/firmware/efi/unaccepted_memory.c
+++ b/drivers/firmware/efi/unaccepted_memory.c
@@ -209,6 +209,24 @@ bool range_contains_unaccepted_memory(phys_addr_t start, unsigned long size)
return ret;
}
+/*
+ * Unaccepted memory bitmap only covers initial boot memory and not the
+ * hotpluggable range that is part of SRAT parsing. However, some initial memory
+ * with the attribute EFI_MEMORY_HOT_PLUGGABLE can indicate boot time memory
+ * that can be hot-removed. Hence, handle acceptance in accordance with the
+ * unaccepted bitmap. Otherwise, perform the state change for the memory range
+ * up-front.
+ */
+void accept_hotplug_memory(phys_addr_t start, unsigned long size)
+{
+ if (range_contains_unaccepted_memory(start, size)) {
+ accept_memory(start, size);
+ return;
+ }
+
+ arch_accept_memory(start, start + size);
+}
+
#ifdef CONFIG_PROC_VMCORE
static bool unaccepted_memory_vmcore_pfn_is_ram(struct vmcore_cb *cb,
unsigned long pfn)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 15076261d0c2..2d3c1ea40606 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4504,6 +4504,7 @@ int set_anon_vma_name(unsigned long addr, unsigned long size,
bool range_contains_unaccepted_memory(phys_addr_t start, unsigned long size);
void accept_memory(phys_addr_t start, unsigned long size);
+void accept_hotplug_memory(phys_addr_t start, unsigned long size);
#else
@@ -4517,6 +4518,10 @@ static inline void accept_memory(phys_addr_t start, unsigned long size)
{
}
+static inline void accept_hotplug_memory(phys_addr_t start, unsigned long size)
+{
+}
+
#endif
static inline bool pfn_is_unaccepted_memory(unsigned long pfn)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index a63ec679d861..549ccfd190ee 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1567,6 +1567,8 @@ int add_memory_resource(int nid, struct resource *res, mhp_t mhp_flags)
if (!strcmp(res->name, "System RAM"))
firmware_map_add_hotplug(start, start + size, "System RAM");
+ accept_hotplug_memory(start, size);
+
/* device_online() will take the lock when calling online_pages() */
mem_hotplug_done();
--
2.52.0
^ permalink raw reply related
* [PATCH v3 0/2] SEV-SNP Unaccepted Memory Hotplug
From: Pratik R. Sampat @ 2026-01-28 20:41 UTC (permalink / raw)
To: linux-mm, linux-coco, x86, linux-kernel
Cc: tglx, mingo, bp, dave.hansen, kas, ardb, akpm, david, osalvador,
thomas.lendacky, michael.roth, prsampat
Guest memory hot-plug/remove via the QEMU monitor is used by virtual
machines to dynamically scale the memory capacity of a system with
virtually zero downtime to the guest. For confidential VMs, memory has
to be first accepted before it can be used. Add support to accept
memory that has been hot-added and revert back it's state for
hypervisors to be able to use the pages during hot-remove.
Usage (for SNP guests)
----------------------
Step1: Spawn a QEMU SNP guest with the additional parameter of slots and
maximum possible memory, along with the initial memory as below:
"-m X,slots=Y,maxmem=Z".
Step2: Once the guest is booted, launch the qemu monitor and hotplug
the memory as follows:
(qemu) object_add memory-backend-memfd,id=mem1,size=1G
(qemu) device_add pc-dimm,id=dimm1,memdev=mem1
Memory is accepted up-front when added to the guest.
If using auto-onlining by either:
a) echo online > /sys/devices/system/memory/auto_online_blocks, OR
b) enable CONFIG_MHP_DEFAULT_ONLINE_TYPE_* while compiling kernel
Memory should show up automatically.
Otherwise, memory can also be onlined by echoing 1 to the newly added
blocks in: /sys/devices/system/memory/memoryXX/online
Step3: memory can be hot-removed using the qemu monitor using:
(qemu) device_remove dimm1
(qemu) object_remove mem1
Tip: Enable the kvm_convert_memory event in QEMU to observe memory
conversions between private and shared during hotplug/remove.
The series is based on
git.kernel.org/pub/scm/virt/kvm/kvm.git next
Comments and feedback appreciated!
Changelog Patch v2..v3:
-----------------------
https://lore.kernel.org/all/20260112202300.43546-1-prsampat@amd.com/
1. Account for cold-plugged memory at boot and introduce proper handling
of the unaccepted bitmap during both hotplug and remove. (Kiryl)
2. #include<asm/unaccepted_memory.h> within memory_hotplug caused build
failures on non-x86 archs (Andrew). Instead of introducing
#if-deffery to have arch agnostic fall throughs, create hotplug
specific helper functions since we now also need to take care of
managing the bitmaps due to 1. as well.
Changelog RFC..Patch v2:
------------------------
https://lore.kernel.org/all/20251125175753.1428857-1-prsampat@amd.com/
Based on feedback from the RFC, reworked the series to accept memory
upfront on hotplug. This is done for two reasons:
1. Avoids modifying the unaccepted bitmap. Extending the bitmap would
require either:
* Dynamically allocating the bitmap, which would need changes to EFI
struct definitions, or
* Pre-allocating a larger bitmap to accommodate hotpluggable memory.
This poses challenges since e820 is parsed before SRAT, which
contains the actual memory ranges information.
2. There are currently no known use-cases that would benefit from lazy
acceptance of hotplugged ranges which warrants this additional
complexity.
Pratik R. Sampat (2):
mm/memory_hotplug: Add support to accept memory during hot-add
x86/sev: Add support to unaccept memory after hot-remove
arch/x86/coco/sev/core.c | 13 +++++
arch/x86/include/asm/sev.h | 2 +
arch/x86/include/asm/unaccepted_memory.h | 9 +++
drivers/firmware/efi/unaccepted_memory.c | 74 ++++++++++++++++++++++++
include/linux/mm.h | 14 +++++
mm/memory_hotplug.c | 4 ++
6 files changed, 116 insertions(+)
--
2.52.0
^ permalink raw reply
* Re: [PATCH 1/2] KVM: SEV: IBPB-on-Entry guest support
From: Borislav Petkov @ 2026-01-28 19:23 UTC (permalink / raw)
To: Kim Phillips
Cc: linux-kernel, kvm, linux-coco, x86, Sean Christopherson,
Paolo Bonzini, K Prateek Nayak, Nikunj A Dadhania, Tom Lendacky,
Michael Roth, Naveen Rao, David Kaplan, stable
In-Reply-To: <20260126224205.1442196-2-kim.phillips@amd.com>
On Mon, Jan 26, 2026 at 04:42:04PM -0600, Kim Phillips wrote:
> The SEV-SNP IBPB-on-Entry feature does not require a guest-side
> implementation. The feature was added in Zen5 h/w, after the first
> SNP Zen implementation, and thus was not accounted for when the
> initial set of SNP features were added to the kernel.
>
> In its abundant precaution, commit 8c29f0165405 ("x86/sev: Add SEV-SNP
> guest feature negotiation support") included SEV_STATUS' IBPB-on-Entry
> bit as a reserved bit, thereby masking guests from using the feature.
>
> Unmask the bit, to allow guests to take advantage of the feature on
> hypervisor kernel versions that support it: Amend the SEV_STATUS MSR
> SNP_RESERVED_MASK to exclude bit 23 (IbpbOnEntry).
Do not explain what the patch does.
> Fixes: 8c29f0165405 ("x86/sev: Add SEV-SNP guest feature negotiation support")
> Cc: Nikunj A Dadhania <nikunj@amd.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> CC: Borislav Petkov (AMD) <bp@alien8.de>
> CC: Michael Roth <michael.roth@amd.com>
> Cc: stable@kernel.org
I guess...
> diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
> index 4d3566bb1a93..9016a6b00bc7 100644
> --- a/arch/x86/include/asm/msr-index.h
> +++ b/arch/x86/include/asm/msr-index.h
> @@ -735,7 +735,10 @@
> #define MSR_AMD64_SNP_SMT_PROT BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT)
> #define MSR_AMD64_SNP_SECURE_AVIC_BIT 18
> #define MSR_AMD64_SNP_SECURE_AVIC BIT_ULL(MSR_AMD64_SNP_SECURE_AVIC_BIT)
> -#define MSR_AMD64_SNP_RESV_BIT 19
> +#define MSR_AMD64_SNP_RESERVED_BITS19_22 GENMASK_ULL(22, 19)
> +#define MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT 23
> +#define MSR_AMD64_SNP_IBPB_ON_ENTRY BIT_ULL(MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT)
Why isn't this part of SNP_FEATURES_PRESENT?
If this feature doesn't require guest-side support, then it is trivially
present, no?
> +#define MSR_AMD64_SNP_RESV_BIT 24
> #define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT)
> #define MSR_AMD64_SAVIC_CONTROL 0xc0010138
> #define MSR_AMD64_SAVIC_EN_BIT 0
> --
I guess this is a fix of sorts and I could take it in now once all review
comments have been addressed...
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply
* Re: [PATCH 2/2] KVM: SEV: Add support for IBPB-on-Entry
From: Tom Lendacky @ 2026-01-28 19:08 UTC (permalink / raw)
To: Kim Phillips, linux-kernel, kvm, linux-coco, x86
Cc: Sean Christopherson, Paolo Bonzini, K Prateek Nayak,
Nikunj A Dadhania, Michael Roth, Borislav Petkov, Borislav Petkov,
Naveen Rao, David Kaplan
In-Reply-To: <20260126224205.1442196-3-kim.phillips@amd.com>
On 1/26/26 16:42, Kim Phillips wrote:
> 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
> Signed-off-by: Kim Phillips <kim.phillips@amd.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
> arch/x86/include/asm/cpufeatures.h | 1 +
> arch/x86/include/asm/svm.h | 1 +
> arch/x86/kvm/svm/sev.c | 9 ++++++++-
> 3 files changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
> index c01fdde465de..3ce5dff36f78 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 edde36097ddc..eebc65ec948f 100644
> --- a/arch/x86/include/asm/svm.h
> +++ b/arch/x86/include/asm/svm.h
> @@ -306,6 +306,7 @@ 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 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 ea515cf41168..8a6d25db0c00 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -3165,8 +3165,15 @@ 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))
> + if (!sev_snp_enabled)
> + return;
> + /* the following feature bit checks are SNP specific */
> +
> + 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;
> }
>
> void sev_hardware_unsetup(void)
^ permalink raw reply
* Re: [PATCH 1/2] KVM: SEV: IBPB-on-Entry guest support
From: Tom Lendacky @ 2026-01-28 19:02 UTC (permalink / raw)
To: Kim Phillips, linux-kernel, kvm, linux-coco, x86
Cc: Sean Christopherson, Paolo Bonzini, K Prateek Nayak,
Nikunj A Dadhania, Michael Roth, Borislav Petkov, Borislav Petkov,
Naveen Rao, David Kaplan, stable
In-Reply-To: <20260126224205.1442196-2-kim.phillips@amd.com>
On 1/26/26 16:42, Kim Phillips wrote:
> The SEV-SNP IBPB-on-Entry feature does not require a guest-side
> implementation. The feature was added in Zen5 h/w, after the first
> SNP Zen implementation, and thus was not accounted for when the
> initial set of SNP features were added to the kernel.
>
> In its abundant precaution, commit 8c29f0165405 ("x86/sev: Add SEV-SNP
> guest feature negotiation support") included SEV_STATUS' IBPB-on-Entry
> bit as a reserved bit, thereby masking guests from using the feature.
>
> Unmask the bit, to allow guests to take advantage of the feature on
> hypervisor kernel versions that support it: Amend the SEV_STATUS MSR
> SNP_RESERVED_MASK to exclude bit 23 (IbpbOnEntry).
>
> Fixes: 8c29f0165405 ("x86/sev: Add SEV-SNP guest feature negotiation support")
> Cc: Nikunj A Dadhania <nikunj@amd.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> CC: Borislav Petkov (AMD) <bp@alien8.de>
> CC: Michael Roth <michael.roth@amd.com>
> Cc: stable@kernel.org
> Signed-off-by: Kim Phillips <kim.phillips@amd.com>
With the change to the subject line...
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
> arch/x86/boot/compressed/sev.c | 1 +
> arch/x86/coco/sev/core.c | 1 +
> arch/x86/include/asm/msr-index.h | 5 ++++-
> 3 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
> index c8c1464b3a56..2b639703b8dd 100644
> --- a/arch/x86/boot/compressed/sev.c
> +++ b/arch/x86/boot/compressed/sev.c
> @@ -188,6 +188,7 @@ bool sev_es_check_ghcb_fault(unsigned long address)
> MSR_AMD64_SNP_RESERVED_BIT13 | \
> MSR_AMD64_SNP_RESERVED_BIT15 | \
> MSR_AMD64_SNP_SECURE_AVIC | \
> + MSR_AMD64_SNP_RESERVED_BITS19_22 | \
> MSR_AMD64_SNP_RESERVED_MASK)
>
> #ifdef CONFIG_AMD_SECURE_AVIC
> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> index 9ae3b11754e6..13f608117411 100644
> --- a/arch/x86/coco/sev/core.c
> +++ b/arch/x86/coco/sev/core.c
> @@ -122,6 +122,7 @@ static const char * const sev_status_feat_names[] = {
> [MSR_AMD64_SNP_VMSA_REG_PROT_BIT] = "VMSARegProt",
> [MSR_AMD64_SNP_SMT_PROT_BIT] = "SMTProt",
> [MSR_AMD64_SNP_SECURE_AVIC_BIT] = "SecureAVIC",
> + [MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT] = "IBPBOnEntry",
> };
>
> /*
> diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
> index 4d3566bb1a93..9016a6b00bc7 100644
> --- a/arch/x86/include/asm/msr-index.h
> +++ b/arch/x86/include/asm/msr-index.h
> @@ -735,7 +735,10 @@
> #define MSR_AMD64_SNP_SMT_PROT BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT)
> #define MSR_AMD64_SNP_SECURE_AVIC_BIT 18
> #define MSR_AMD64_SNP_SECURE_AVIC BIT_ULL(MSR_AMD64_SNP_SECURE_AVIC_BIT)
> -#define MSR_AMD64_SNP_RESV_BIT 19
> +#define MSR_AMD64_SNP_RESERVED_BITS19_22 GENMASK_ULL(22, 19)
> +#define MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT 23
> +#define MSR_AMD64_SNP_IBPB_ON_ENTRY BIT_ULL(MSR_AMD64_SNP_IBPB_ON_ENTRY_BIT)
> +#define MSR_AMD64_SNP_RESV_BIT 24
> #define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT)
> #define MSR_AMD64_SAVIC_CONTROL 0xc0010138
> #define MSR_AMD64_SAVIC_EN_BIT 0
^ permalink raw reply
* Re: [PATCH v3 00/26] Runtime TDX Module update support
From: Sagi Shahar @ 2026-01-28 17:52 UTC (permalink / raw)
To: Chao Gao
Cc: linux-coco, linux-kernel, kvm, x86, reinette.chatre, ira.weiny,
kai.huang, dan.j.williams, yilun.xu, vannapurve, paulmck,
nik.borisov, zhenzhong.duan, seanjc, rick.p.edgecombe, kas,
dave.hansen, vishal.l.verma, Borislav Petkov, H. Peter Anvin,
Ingo Molnar, Paolo Bonzini, Thomas Gleixner
In-Reply-To: <20260123145645.90444-1-chao.gao@intel.com>
On Fri, Jan 23, 2026 at 9:00 AM Chao Gao <chao.gao@intel.com> wrote:
>
> Hi Reviewers,
>
> With this posting, I'm hoping to collect more Reviewed-by or Acked-by tags.
> Dave, since this version is still light on acks, it might not be ready for
> your review.
>
> Changelog:
> v2->v3:
> - Make this series self-contained and independently runnable, testable and
> reviewable by
>
> * Including dependent patches such as TDX Module version exposure and TDX
> faux device creation
I see "x86/virt/tdx: Retrieve TDX module version" and "x86/virt/tdx:
Print TDX module version during init" in the github link but I don't
see them as part of this series. Were they posted/accepted as part of
a different series?
Trying to build this series without them fails since
tdx_sysinfo.version is undefined.
>
> * Removing dependency on Sean's VMXON cleanups for now, the tdx-host device
> simply checks that the TDX module is initialized, regardless of when or
> who performed the initialization.
>
> Note: If the KVM module is unloaded, all services exposed by the tdx-host
> device will fail. This shouldn't be a big issue since proper errors will
> be returned to userspace, similar to other failure cases.
>
> - Handle updates during update-sensitive times and documented expectations for
> TDX Module updates
> - Rework how updates are aborted when errors occur midway
> - Map Linux error codes to firmware upload error codes
> - Preserve bit 63 in P-SEAMLDR SEAMCALL leaf numbers and display them in hex
> - Do not fail the entire tdx-host device when update features encounter errors
> - Drop superfluous is_visible() function for P-SEAMLDR sysfs nodes
> - Add support for sigstruct sizes up to 16KB
> - Move CONFIG_INTEL_TDX_MODULE_UPDATE kconfig entry under TDX_HOST_SERVICES
> - Various cleanups and changelog improvements for clarity and consistency
> - Collect review tags from ZhenZhong and Jonathan
> - v2: https://lore.kernel.org/linux-coco/20251001025442.427697-1-chao.gao@intel.com/
>
> This series adds support for runtime TDX Module updates that preserve
> running TDX guests. It is also available at:
>
> https://github.com/gaochaointel/linux-dev/commits/tdx-module-updates-v3/
>
> == Background ==
>
> Intel TDX isolates Trusted Domains (TDs), or confidential guests, from the
> host. A key component of Intel TDX is the TDX Module, which enforces
> security policies to protect the memory and CPU states of TDs from the
> host. However, the TDX Module is software that require updates.
>
> == Problems ==
>
> Currently, the TDX Module is loaded by the BIOS at boot time, and the only
> way to update it is through a reboot, which results in significant system
> downtime. Users expect the TDX Module to be updatable at runtime without
> disrupting TDX guests.
>
> == Solution ==
>
> On TDX platforms, P-SEAMLDR[1] is a component within the protected SEAM
> range. It is loaded by the BIOS and provides the host with functions to
> install a TDX Module at runtime.
>
> Implement a TDX Module update facility via the fw_upload mechanism. Given
> that there is variability in which module update to load based on features,
> fix levels, and potentially reloading the same version for error recovery
> scenarios, the explicit userspace chosen payload flexibility of fw_upload
> is attractive.
>
> This design allows the kernel to accept a bitstream instead of loading a
> named file from the filesystem, as the module selection and policy
> enforcement for TDX Modules are quite complex (see more in patch 8). By
> doing so, much of this complexity is shifted out of the kernel. The kernel
> need to expose information, such as the TDX Module version, to userspace.
> Userspace must understand the TDX Module versioning scheme and update
> policy to select the appropriate TDX Module (see "TDX Module Versioning"
> below).
>
> In the unlikely event the update fails, for example userspace picks an
> incompatible update image, or the image is otherwise corrupted, all TDs
> will experience SEAMCALL failures and be killed. The recovery of TD
> operation from that event requires a reboot.
>
> Given there is no mechanism to quiesce SEAMCALLs, the TDs themselves must
> pause execution over an update. The most straightforward way to meet the
> 'pause TDs while update executes' constraint is to run the update in
> stop_machine() context. All other evaluated solutions export more
> complexity to KVM, or exports more fragility to userspace.
>
> == How to test this series ==
>
> First, load kvm-intel.ko and tdx-host.ko if they haven't been loaded:
>
> # modprobe -r kvm_intel
> # modprobe kvm_intel tdx=1
> # modprobe tdx-host
>
> Then, use the userspace tool below to select the appropriate TDX module and
> install it via the interfaces exposed by this series:
>
> # git clone https://github.com/intel/tdx-module-binaries
> # cd tdx-module-binaries
> # python version_select_and_load.py --update
>
> == Other information relevant to Runtime TDX Module updates ==
>
> === TDX Module versioning ===
>
> Each TDX Module is assigned a version number x.y.z, where x represents the
> "major" version, y the "minor" version, and z the "update" version.
>
> Runtime TDX Module updates are restricted to Z-stream releases.
>
> Note that Z-stream releases do not necessarily guarantee compatibility. A
> new release may not be compatible with all previous versions. To address this,
> Intel provides a separate file containing compatibility information, which
> specifies the minimum module version required for a particular update. This
> information is referenced by the tool to determine if two modules are
> compatible.
>
> === TCB Stability ===
>
> Updates change the TCB as viewed by attestation reports. In TDX there is
> a distinction between launch-time version and current version where
> runtime TDX Module updates cause that latter version number to change,
> subject to Z-stream constraints.
>
> The concern that a malicious host may attack confidential VMs by loading
> insecure updates was addressed by Alex in [3]. Similarly, the scenario
> where some "theoretical paranoid tenant" in the cloud wants to audit
> updates and stop trusting the host after updates until audit completion
> was also addressed in [4]. Users not in the cloud control the host machine
> and can manage updates themselves, so they don't have these concerns.
>
> See more about the implications of current TCB version changes in
> attestation as summarized by Dave in [5].
>
> === TDX Module Distribution Model ===
>
> At a high level, Intel publishes all TDX Modules on the github [2], along
> with a mapping_file.json which documents the compatibility information
> about each TDX Module and a userspace tool to install the TDX Module. OS
> vendors can package these modules and distribute them. Administrators
> install the package and use the tool to select the appropriate TDX Module
> and install it via the interfaces exposed by this series.
>
> [1]: https://cdrdv2.intel.com/v1/dl/getContent/733584
> [2]: https://github.com/intel/tdx-module-binaries
> [3]: https://lore.kernel.org/all/665c5ae0-4b7c-4852-8995-255adf7b3a2f@amazon.com/
> [4]: https://lore.kernel.org/all/5d1da767-491b-4077-b472-2cc3d73246d6@amazon.com/
> [5]: https://lore.kernel.org/all/94d6047e-3b7c-4bc1-819c-85c16ff85abf@intel.com/
>
> Chao Gao (25):
> x86/virt/tdx: Print SEAMCALL leaf numbers in decimal
> x86/virt/tdx: Use %# prefix for hex values in SEAMCALL error messages
> coco/tdx-host: Introduce a "tdx_host" device
> coco/tdx-host: Expose TDX Module version
> x86/virt/tdx: Prepare to support P-SEAMLDR SEAMCALLs
> x86/virt/seamldr: Introduce a wrapper for P-SEAMLDR SEAMCALLs
> x86/virt/seamldr: Retrieve P-SEAMLDR information
> coco/tdx-host: Expose P-SEAMLDR information via sysfs
> coco/tdx-host: Implement FW_UPLOAD sysfs ABI for TDX Module updates
> x86/virt/seamldr: Block TDX Module updates if any CPU is offline
> x86/virt/seamldr: Verify availability of slots for TDX Module updates
> x86/virt/seamldr: Allocate and populate a module update request
> x86/virt/seamldr: Introduce skeleton for TDX Module updates
> x86/virt/seamldr: Abort updates if errors occurred midway
> x86/virt/seamldr: Shut down the current TDX module
> x86/virt/tdx: Reset software states after TDX module shutdown
> x86/virt/seamldr: Log TDX Module update failures
> x86/virt/seamldr: Install a new TDX Module
> x86/virt/seamldr: Do TDX per-CPU initialization after updates
> x86/virt/tdx: Establish contexts for the new TDX Module
> x86/virt/tdx: Update tdx_sysinfo and check features post-update
> x86/virt/tdx: Enable TDX Module runtime updates
> x86/virt/seamldr: Extend sigstruct to 16KB
> x86/virt/tdx: Avoid updates during update-sensitive operations
> coco/tdx-host: Set and document TDX Module update expectations
>
> Kai Huang (1):
> x86/virt/tdx: Move low level SEAMCALL helpers out of <asm/tdx.h>
>
> .../ABI/testing/sysfs-devices-faux-tdx-host | 76 ++++
> arch/x86/include/asm/seamldr.h | 29 ++
> arch/x86/include/asm/tdx.h | 66 +--
> arch/x86/include/asm/tdx_global_metadata.h | 5 +
> arch/x86/kvm/vmx/tdx_errno.h | 2 -
> arch/x86/virt/vmx/tdx/Makefile | 1 +
> arch/x86/virt/vmx/tdx/seamcall.h | 125 ++++++
> arch/x86/virt/vmx/tdx/seamldr.c | 398 ++++++++++++++++++
> arch/x86/virt/vmx/tdx/tdx.c | 153 ++++---
> arch/x86/virt/vmx/tdx/tdx.h | 11 +-
> arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 13 +
> drivers/virt/coco/Kconfig | 2 +
> drivers/virt/coco/Makefile | 1 +
> drivers/virt/coco/tdx-host/Kconfig | 22 +
> drivers/virt/coco/tdx-host/Makefile | 1 +
> drivers/virt/coco/tdx-host/tdx-host.c | 260 ++++++++++++
> 16 files changed, 1064 insertions(+), 101 deletions(-)
> create mode 100644 Documentation/ABI/testing/sysfs-devices-faux-tdx-host
> create mode 100644 arch/x86/include/asm/seamldr.h
> create mode 100644 arch/x86/virt/vmx/tdx/seamcall.h
> create mode 100644 arch/x86/virt/vmx/tdx/seamldr.c
> create mode 100644 drivers/virt/coco/tdx-host/Kconfig
> create mode 100644 drivers/virt/coco/tdx-host/Makefile
> create mode 100644 drivers/virt/coco/tdx-host/tdx-host.c
>
> --
> 2.47.3
>
>
^ permalink raw reply
* Re: [PATCH v3 05/26] coco/tdx-host: Expose TDX Module version
From: Dave Hansen @ 2026-01-28 17:01 UTC (permalink / raw)
To: Chao Gao, linux-coco, linux-kernel, kvm, x86
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma
In-Reply-To: <20260123145645.90444-6-chao.gao@intel.com>
On 1/23/26 06:55, Chao Gao wrote:
...
> This approach follows the pattern used by microcode updates and
> other CoCo implementations:
>
> 1. AMD has a PCI device for the PSP for SEV which provides an
> existing place to hang their equivalent metadata.
>
> 2. ARM CCA will likely have a faux device (although it isn't obvious
> if they have a need to export version information there) [1]
>
> 3. Microcode revisions are exposed as CPU device attributes
I kinda disagree with the idea that this follows existing patterns. It
uses a *NEW* pattern.
AMD doesn't use a faux device because they *HAVE* a PCI device in their
architecture. TDX doesn't have a PCI device in its hardware architecture.
ARM CCA doesn't exist in the tree.
CPU microcode doesn't use a faux device. For good reason. The microcode
version is *actually* per-cpu. It can differ between CPU cores. The TDX
module version is not per-cpu. There's one and only one global module.
This is the reason that we need a global, unique device for TDX.
I'm not saying that being new is a bad thing. But let's not pretend this
is following any kind of existing pattern. Let's explain *why* it needs
to be different.
^ permalink raw reply
* Re: [PATCH v1 01/14] x86/realmode: remove I/O port paravirtualization
From: Borislav Petkov @ 2026-01-28 17:01 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Thomas Gleixner, Ingo Molnar, Dave Hansen, Uros Bizjak,
Petr Mladek, Andrew Morton, Kees Cook, Peter Zijlstra (Intel),
Nathan Chancellor, Kiryl Shutsemau, Rick Edgecombe, linux-kernel,
linux-coco, x86
In-Reply-To: <20260120195407.1163051-2-hpa@zytor.com>
On Tue, Jan 20, 2026 at 11:53:53AM -0800, H. Peter Anvin wrote:
> In commit:
>
> eb4ea1ae8f45 x86/boot: Port I/O: Allow to hook up alternative helpers
We do this format for referencing commits:
eb4ea1ae8f45 ("x86/boot: Port I/O: Allow to hook up alternative helpers")
> ... paravirtualization hooks were added to (some!) of the port I/O
> functions. However, they were only ever used in the 32/64-bit
> "compressed" directory, and never made any sense in the real-mode
> code, which is notoriously size sensitive.
>
> Without these hooks, <asm/shared/io.h> is usable directly, so mode
s/mode/move/
Otherwise, LGTM.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply
* Re: [PATCH v3 04/26] coco/tdx-host: Introduce a "tdx_host" device
From: Dave Hansen @ 2026-01-28 16:53 UTC (permalink / raw)
To: Tony Lindgren, Chao Gao
Cc: linux-coco, linux-kernel, kvm, x86, reinette.chatre, ira.weiny,
kai.huang, dan.j.williams, yilun.xu, sagis, vannapurve, paulmck,
nik.borisov, zhenzhong.duan, seanjc, rick.p.edgecombe, kas,
dave.hansen, vishal.l.verma, Jonathan Cameron, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, H. Peter Anvin
In-Reply-To: <aXc5Y_VAuGQWsWZX@tlindgre-MOBL1>
On 1/26/26 01:52, Tony Lindgren wrote:
> On Fri, Jan 23, 2026 at 06:55:12AM -0800, Chao Gao wrote:
>> --- /dev/null
>> +++ b/drivers/virt/coco/tdx-host/tdx-host.c
>> @@ -0,0 +1,43 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * TDX host user interface driver
>> + *
>> + * Copyright (C) 2025 Intel Corporation
>> + */
> Just a nit, the year has changed so could be updated.
Folks, please stop this.
You can ask an patch author *if* this should be updated. But if they're
just last year's work, then the year needs to stay 2025. This isn't some
mechanical thing that you flip over when the year changes. You change it
when you meaningfully change the work.
^ permalink raw reply
* Re: [PATCH v3 03/26] x86/virt/tdx: Move low level SEAMCALL helpers out of <asm/tdx.h>
From: Dave Hansen @ 2026-01-28 16:37 UTC (permalink / raw)
To: Chao Gao, linux-coco, linux-kernel, kvm, x86
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin
In-Reply-To: <20260123145645.90444-4-chao.gao@intel.com>
On 1/23/26 06:55, Chao Gao wrote:
> +++ b/arch/x86/virt/vmx/tdx/seamcall.h
Moving the code to a local header is a good thing. The more private
these things are, the better.
I _do_ like when I see these things have a label in the filename like:
internal.h
or even:
seamcall_internal.h
That really catches your eye. It would also be ideal to have a small
blurb at the top of the file to say what its scope is, just to explain
what folks should be adding to it or not.
If you get a chance to add those, all the better. But either way:
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
^ permalink raw reply
* Re: [PATCH v3 03/26] x86/virt/tdx: Move low level SEAMCALL helpers out of <asm/tdx.h>
From: Dave Hansen @ 2026-01-28 16:31 UTC (permalink / raw)
To: Chao Gao, Binbin Wu
Cc: linux-coco, linux-kernel, kvm, x86, reinette.chatre, ira.weiny,
kai.huang, dan.j.williams, yilun.xu, sagis, vannapurve, paulmck,
nik.borisov, zhenzhong.duan, seanjc, rick.p.edgecombe, kas,
dave.hansen, vishal.l.verma, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, H. Peter Anvin
In-Reply-To: <aXoEQP0jyXgR6ohs@intel.com>
On 1/28/26 04:42, Chao Gao wrote:
>>> diff --git a/arch/x86/virt/vmx/tdx/seamcall.h b/arch/x86/virt/vmx/tdx/seamcall.h
>>> new file mode 100644
>>> index 000000000000..0912e03fabfe
>>> --- /dev/null
>>> +++ b/arch/x86/virt/vmx/tdx/seamcall.h
>>> @@ -0,0 +1,99 @@
>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>> +/* Copyright (C) 2025 Intel Corporation */
>> Should this be updated to 2026?
> Yes. And I may drop the copyright notice if it is not necessary.
No.
The copyright is to document the timing of a creative action. Moving
code is not a creative action.
If you want to remove it, do it in another patch. If you move code, just
_move_ _the_ _code_. You can _maybe_ clean up whitespace if you want to
along the way. But that's it. Don't muck with it unless you have a
reason. A *good* reason.
^ permalink raw reply
* Re: [PATCH v3 01/26] x86/virt/tdx: Print SEAMCALL leaf numbers in decimal
From: Dave Hansen @ 2026-01-28 16:26 UTC (permalink / raw)
To: Chao Gao, linux-coco, linux-kernel, kvm, x86
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma,
Kirill A. Shutemov, Farrah Chen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, H. Peter Anvin
In-Reply-To: <20260123145645.90444-2-chao.gao@intel.com>
On 1/23/26 06:55, Chao Gao wrote:
> Both TDX spec and kernel defines SEAMCALL leaf numbers as decimal. Printing
> them in hex makes no sense. Correct it.
This patch has zero to do with "Runtime TDX Module update support". Why
is it in this series?
^ permalink raw reply
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