From: Chao Gao <chao.gao@intel.com>
To: linux-coco@lists.linux.dev, x86@kernel.org, kvm@vger.kernel.org
Cc: seanjc@google.com, pbonzini@redhat.com, eddie.dong@intel.com,
kirill.shutemov@intel.com, dave.hansen@intel.com,
dan.j.williams@intel.com, kai.huang@intel.com,
isaku.yamahata@intel.com, elena.reshetova@intel.com,
rick.p.edgecombe@intel.com, Chao Gao <chao.gao@intel.com>,
Farrah Chen <farrah.chen@intel.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
"H. Peter Anvin" <hpa@zytor.com>,
"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>,
linux-kernel@vger.kernel.org
Subject: [RFC PATCH 08/20] x86/virt/seamldr: Implement FW_UPLOAD sysfs ABI for TD-Preserving Updates
Date: Fri, 23 May 2025 02:52:31 -0700 [thread overview]
Message-ID: <20250523095322.88774-9-chao.gao@intel.com> (raw)
In-Reply-To: <20250523095322.88774-1-chao.gao@intel.com>
Implement a fw_upload interface to coordinate TD-Preserving updates. The
explicit file selection capabilities of fw_upload is preferred over the
implicit file selection of request_firmware() for the following reasons:
a. Intel distributes all versions of the TDX module, allowing admins to
load any version rather than always defaulting to the latest. This
flexibility is necessary because future extensions may require reverting to
a previous version to clear fatal errors.
b. Some module version series are platform-specific. For example, the 1.5.x
series is for certain platform generations, while the 2.0.x series is
intended for others.
c. The update policy for TD-Preserving is non-linear at times. The latest
TDX module may not be TD-Preserving capable. For example, TDX module
1.5.x may be updated to 1.5.y but not to 1.5.y+1. This policy is documented
separately in a file released along with each TDX module release.
So, the default policy of "request_firmware()" of "always load latest", is
not suitable for TDX. Userspace needs to deploy a more sophisticated policy
check (i.e. latest may not be TD-Preserving capable), and there is
potential operator choice to consider.
Just have userspace pick rather than add kernel mechanism to change the
default policy of request_firmware().
Signed-off-by: Chao Gao <chao.gao@intel.com>
Tested-by: Farrah Chen <farrah.chen@intel.com>
---
arch/x86/Kconfig | 2 +
arch/x86/virt/vmx/tdx/seamldr.c | 77 +++++++++++++++++++++++++++++++++
arch/x86/virt/vmx/tdx/seamldr.h | 2 +
arch/x86/virt/vmx/tdx/tdx.c | 4 ++
4 files changed, 85 insertions(+)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 8b1e0986b7f8..31385104a6ee 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1935,6 +1935,8 @@ config INTEL_TDX_HOST
config INTEL_TDX_MODULE_UPDATE
bool "Intel TDX module runtime update"
depends on INTEL_TDX_HOST
+ select FW_LOADER
+ select FW_UPLOAD
help
This enables the kernel to support TDX module runtime update. This allows
the admin to upgrade the TDX module to a newer one without the need to
diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamldr.c
index b628555daf55..da862e71ebce 100644
--- a/arch/x86/virt/vmx/tdx/seamldr.c
+++ b/arch/x86/virt/vmx/tdx/seamldr.c
@@ -8,6 +8,8 @@
#include <linux/cleanup.h>
#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/gfp.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
@@ -32,6 +34,15 @@ struct seamldr_info {
u8 reserved1[224];
} __packed;
+
+#define TDX_FW_STATE_BITS 32
+#define TDX_FW_CANCEL 0
+struct tdx_status {
+ DECLARE_BITMAP(fw_state, TDX_FW_STATE_BITS);
+};
+
+struct fw_upload *tdx_fwl;
+static struct tdx_status tdx_status;
static struct seamldr_info seamldr_info __aligned(256);
static inline int seamldr_call(u64 fn, struct tdx_module_args *args)
@@ -101,3 +112,69 @@ int get_seamldr_info(void)
return seamldr_call(P_SEAMLDR_INFO, &args);
}
+
+static int seamldr_install_module(const u8 *data, u32 size)
+{
+ return -EOPNOTSUPP;
+}
+
+static enum fw_upload_err tdx_fw_prepare(struct fw_upload *fwl,
+ const u8 *data, u32 size)
+{
+ struct tdx_status *status = fwl->dd_handle;
+
+ if (test_and_clear_bit(TDX_FW_CANCEL, status->fw_state))
+ return FW_UPLOAD_ERR_CANCELED;
+
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err tdx_fw_write(struct fw_upload *fwl, const u8 *data,
+ u32 offset, u32 size, u32 *written)
+{
+ struct tdx_status *status = fwl->dd_handle;
+
+ if (test_and_clear_bit(TDX_FW_CANCEL, status->fw_state))
+ return FW_UPLOAD_ERR_CANCELED;
+
+ /*
+ * No partial write will be returned to callers so @offset should
+ * always be zero.
+ */
+ WARN_ON_ONCE(offset);
+ if (seamldr_install_module(data, size))
+ return FW_UPLOAD_ERR_FW_INVALID;
+
+ *written = size;
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err tdx_fw_poll_complete(struct fw_upload *fwl)
+{
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static void tdx_fw_cancel(struct fw_upload *fwl)
+{
+ struct tdx_status *status = fwl->dd_handle;
+
+ set_bit(TDX_FW_CANCEL, status->fw_state);
+}
+
+static const struct fw_upload_ops tdx_fw_ops = {
+ .prepare = tdx_fw_prepare,
+ .write = tdx_fw_write,
+ .poll_complete = tdx_fw_poll_complete,
+ .cancel = tdx_fw_cancel,
+};
+
+void seamldr_init(struct device *dev)
+{
+ int ret;
+
+ tdx_fwl = firmware_upload_register(THIS_MODULE, dev, "seamldr_upload",
+ &tdx_fw_ops, &tdx_status);
+ ret = PTR_ERR_OR_ZERO(tdx_fwl);
+ if (ret)
+ pr_err("failed to register module uploader %d\n", ret);
+}
diff --git a/arch/x86/virt/vmx/tdx/seamldr.h b/arch/x86/virt/vmx/tdx/seamldr.h
index 15597cb5036d..00fa3a4e9155 100644
--- a/arch/x86/virt/vmx/tdx/seamldr.h
+++ b/arch/x86/virt/vmx/tdx/seamldr.h
@@ -6,9 +6,11 @@
extern struct attribute_group seamldr_group;
#define SEAMLDR_GROUP (&seamldr_group)
int get_seamldr_info(void);
+void seamldr_init(struct device *dev);
#else
#define SEAMLDR_GROUP NULL
static inline int get_seamldr_info(void) { return 0; }
+static inline void seamldr_init(struct device *dev) { }
#endif
#endif
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index aa6a23d46494..22ffc15b4299 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1178,6 +1178,10 @@ static void tdx_subsys_init(void)
goto err_bus;
}
+ struct device *dev_root __free(put_device) = bus_get_dev_root(&tdx_subsys);
+ if (dev_root)
+ seamldr_init(dev_root);
+
return;
err_bus:
--
2.47.1
next prev parent reply other threads:[~2025-05-23 9:53 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-23 9:52 [RFC PATCH 00/20] TD-Preserving updates Chao Gao
2025-05-23 9:52 ` [RFC PATCH 01/20] x86/virt/tdx: Print SEAMCALL leaf numbers in decimal Chao Gao
2025-06-02 23:44 ` Huang, Kai
2025-05-23 9:52 ` [RFC PATCH 02/20] x86/virt/tdx: Prepare to support P-SEAMLDR SEAMCALLs Chao Gao
2025-06-04 12:22 ` Huang, Kai
2025-06-04 13:14 ` Chao Gao
2025-06-05 0:14 ` Huang, Kai
2025-05-23 9:52 ` [RFC PATCH 03/20] x86/virt/seamldr: Introduce a wrapper for " Chao Gao
2025-06-03 11:22 ` Nikolay Borisov
2025-06-09 7:53 ` Chao Gao
2025-06-09 8:02 ` Nikolay Borisov
2025-06-10 1:03 ` Chao Gao
2025-06-10 6:52 ` Nikolay Borisov
2025-06-10 15:02 ` Dave Hansen
2025-07-11 13:59 ` Sean Christopherson
2025-07-14 9:21 ` Chao Gao
2025-05-23 9:52 ` [RFC PATCH 04/20] x86/virt/tdx: Introduce a "tdx" subsystem and "tsm" device Chao Gao
2025-06-02 23:44 ` Huang, Kai
2025-06-05 8:34 ` Chao Gao
2025-07-31 20:17 ` dan.j.williams
2025-05-23 9:52 ` [RFC PATCH 05/20] x86/virt/tdx: Export tdx module attributes via sysfs Chao Gao
2025-06-02 23:49 ` Huang, Kai
2025-06-10 1:37 ` Chao Gao
2025-06-11 2:09 ` Huang, Kai
2025-06-11 7:45 ` Chao Gao
2025-05-23 9:52 ` [RFC PATCH 06/20] x86/virt/seamldr: Add a helper to read P-SEAMLDR information Chao Gao
2025-05-23 9:52 ` [RFC PATCH 07/20] x86/virt/tdx: Expose SEAMLDR information via sysfs Chao Gao
2025-07-29 4:55 ` Xu Yilun
2025-07-29 10:00 ` Chao Gao
2025-07-31 21:01 ` dan.j.williams
2025-08-01 2:07 ` Xu Yilun
2025-08-01 15:24 ` dan.j.williams
2025-08-04 7:00 ` Xu Yilun
2025-08-05 0:17 ` dan.j.williams
2025-08-05 0:47 ` Sean Christopherson
2025-08-05 4:02 ` dan.j.williams
2025-08-05 13:49 ` Sean Christopherson
2025-08-06 16:33 ` dan.j.williams
2025-08-06 3:03 ` Xu Yilun
2025-05-23 9:52 ` Chao Gao [this message]
2025-06-16 22:55 ` [RFC PATCH 08/20] x86/virt/seamldr: Implement FW_UPLOAD sysfs ABI for TD-Preserving Updates Sagi Shahar
2025-06-17 7:55 ` Chao Gao
2025-05-23 9:52 ` [RFC PATCH 09/20] x86/virt/seamldr: Allocate and populate a module update request Chao Gao
2025-05-23 9:52 ` [RFC PATCH 10/20] x86/virt/seamldr: Introduce skeleton for TD-Preserving updates Chao Gao
2025-05-23 9:52 ` [RFC PATCH 11/20] x86/virt/seamldr: Abort updates if errors occurred midway Chao Gao
2025-06-03 12:04 ` Nikolay Borisov
2025-06-09 2:37 ` Chao Gao
2025-05-23 9:52 ` [RFC PATCH 12/20] x86/virt/seamldr: Shut down the current TDX module Chao Gao
2025-06-03 12:36 ` Nikolay Borisov
2025-06-09 2:10 ` Chao Gao
2025-05-23 9:52 ` [RFC PATCH 13/20] x86/virt/tdx: Reset software states after TDX module shutdown Chao Gao
2025-05-23 9:52 ` [RFC PATCH 14/20] x86/virt/seamldr: Install a new TDX module Chao Gao
2025-05-23 9:52 ` [RFC PATCH 15/20] x86/virt/seamldr: Handle TD-Preserving update failures Chao Gao
2025-05-23 9:52 ` [RFC PATCH 16/20] x86/virt/seamldr: Do TDX cpu init after updates Chao Gao
2025-05-23 9:52 ` [RFC PATCH 17/20] x86/virt/tdx: Establish contexts for the new module Chao Gao
2025-05-23 9:52 ` [RFC PATCH 18/20] x86/virt/tdx: Update tdx_sysinfo and check features post-update Chao Gao
2025-05-23 9:52 ` [RFC PATCH 19/20] x86/virt/seamldr: Verify availability of slots for TD-Preserving updates Chao Gao
2025-05-23 9:52 ` [RFC PATCH 20/20] x86/virt/seamldr: Enable TD-Preserving Updates Chao Gao
2025-06-11 19:56 ` [RFC PATCH 00/20] TD-Preserving updates Sagi Shahar
2025-07-11 8:04 ` Chao Gao
2025-07-11 14:06 ` Sean Christopherson
2025-07-14 10:26 ` Chao Gao
2025-07-15 0:21 ` Paul E. McKenney
2025-07-16 7:30 ` Chao Gao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250523095322.88774-9-chao.gao@intel.com \
--to=chao.gao@intel.com \
--cc=bp@alien8.de \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=eddie.dong@intel.com \
--cc=elena.reshetova@intel.com \
--cc=farrah.chen@intel.com \
--cc=hpa@zytor.com \
--cc=isaku.yamahata@intel.com \
--cc=kai.huang@intel.com \
--cc=kirill.shutemov@intel.com \
--cc=kirill.shutemov@linux.intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=rick.p.edgecombe@intel.com \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®