[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <3354385d-b1a0-416d-a3cd-53d515840b1c@intel.com>
Date: Wed, 14 Jan 2026 15:47:17 +0800
From: "Duan, Zhenzhong" <zhenzhong.duan@...el.com>
To: Chao Gao <chao.gao@...el.com>, <linux-coco@...ts.linux.dev>,
<linux-kernel@...r.kernel.org>, <x86@...nel.org>,
<reinette.chatre@...el.com>, <ira.weiny@...el.com>, <kai.huang@...el.com>,
<dan.j.williams@...el.com>, <yilun.xu@...ux.intel.com>, <sagis@...gle.com>,
<vannapurve@...gle.com>, <paulmck@...nel.org>, <nik.borisov@...e.com>
CC: Farrah Chen <farrah.chen@...el.com>, Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>, Dave Hansen
<dave.hansen@...ux.intel.com>, "H. Peter Anvin" <hpa@...or.com>, "Kirill A.
Shutemov" <kas@...nel.org>
Subject: Re: [PATCH v2 05/21] x86/virt/seamldr: Introduce a wrapper for
P-SEAMLDR SEAMCALLs
On 10/1/2025 10:52 AM, Chao Gao wrote:
> Software needs to talk with P-SEAMLDR via P-SEAMLDR SEAMCALLs. So, add a
> wrapper for P-SEAMLDR SEAMCALLs.
>
> Save and restore the current VMCS using VMPTRST and VMPTRLD instructions
> to avoid breaking KVM. Doing so is because P-SEAMLDR SEAMCALLs would
> invalidate the current VMCS as documented in IntelĀ® Trust Domain CPU
> Architectural Extensions (May 2021 edition) Chapter 2.3 [1]:
>
> 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.
>
> Disable interrupts to prevent KVM code from interfering with P-SEAMLDR
> SEAMCALLs. For example, if a vCPU is scheduled before the current VMCS is
> restored, it may encounter an invalid current VMCS, causing its VMX
> instruction to fail. Additionally, if KVM sends IPIs to invalidate a
> current VMCS and the invalidation occurs right after the current VMCS is
> saved, that VMCS will be reloaded after P-SEAMLDR SEAMCALLs, leading to
> unexpected behavior.
>
> NMIs are not a problem, as the only scenario where instructions relying on
> the current-VMCS are used is during guest PMI handling in KVM. This occurs
> immediately after VM exits with IRQ and NMI disabled, ensuring no
> interference with P-SEAMLDR SEAMCALLs.
>
> Signed-off-by: Chao Gao <chao.gao@...el.com>
> Tested-by: Farrah Chen <farrah.chen@...el.com>
> Link: https://cdrdv2.intel.com/v1/dl/getContent/733582 # [1]
> ---
> v2:
> - don't create a new, inferior framework to save/restore VMCS
> - use human-friendly language, just "current VMCS" rather than
> SDM term "current-VMCS pointer"
> - don't mix guard() with goto
> ---
> arch/x86/Kconfig | 10 ++++++
> arch/x86/virt/vmx/tdx/Makefile | 1 +
> arch/x86/virt/vmx/tdx/seamldr.c | 56 +++++++++++++++++++++++++++++++++
> 3 files changed, 67 insertions(+)
> create mode 100644 arch/x86/virt/vmx/tdx/seamldr.c
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 58d890fe2100..6b47383d2958 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -1905,6 +1905,16 @@ config INTEL_TDX_HOST
>
> If unsure, say N.
>
> +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 the same or any newer
> + version without the need to terminate running TDX guests.
> +
> + If unsure, say N.
> +
> config EFI
> bool "EFI runtime service support"
> depends on ACPI
> diff --git a/arch/x86/virt/vmx/tdx/Makefile b/arch/x86/virt/vmx/tdx/Makefile
> index 90da47eb85ee..26aea3531c36 100644
> --- a/arch/x86/virt/vmx/tdx/Makefile
> +++ b/arch/x86/virt/vmx/tdx/Makefile
> @@ -1,2 +1,3 @@
> # SPDX-License-Identifier: GPL-2.0-only
> obj-y += seamcall.o tdx.o
> +obj-$(CONFIG_INTEL_TDX_MODULE_UPDATE) += seamldr.o
Not clear if seamldr will support other features besides TDX module update,
if yes, maybe more general name CONFIG_INTEL_SEAMLDR?
> diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamldr.c
> new file mode 100644
> index 000000000000..b99d73f7bb08
> --- /dev/null
> +++ b/arch/x86/virt/vmx/tdx/seamldr.c
> @@ -0,0 +1,56 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright(c) 2025 Intel Corporation.
> + *
> + * Intel TDX module runtime update
> + */
> +#define pr_fmt(fmt) "seamldr: " fmt
> +
> +#include <linux/irqflags.h>
> +#include <linux/types.h>
> +
> +#include "seamcall.h"
> +
> +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;
> +
> + /*
> + * 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).
> + */
> + local_irq_save(flags);
> +
> + asm goto("1: vmptrst %0\n\t"
> + _ASM_EXTABLE(1b, %l[error])
> + : "=m" (vmcs) : : "cc" : error);
> +
> + ret = seamldr_prerr(fn, args);
> +
> + /*
> + * Restore the current VMCS pointer. VMPTSTR "returns" all ones if the
> + * current VMCS is invalid.
> + */
> + if (vmcs != -1ULL) {
> + asm goto("1: vmptrld %0\n\t"
> + "jna %l[error]\n\t"
> + _ASM_EXTABLE(1b, %l[error])
> + : : "m" (vmcs) : "cc" : error);
> + }
> +
> + local_irq_restore(flags);
> + return ret;
> +
> +error:
> + local_irq_restore(flags);
> +
> + WARN_ONCE(1, "Failed to save/restore the current VMCS");
> + return -EIO;
> +}
Powered by blists - more mailing lists