From: Kai Huang <kai.huang@intel.com>
To: dave.hansen@intel.com, bp@alien8.de, tglx@linutronix.de,
peterz@infradead.org, mingo@redhat.com, hpa@zytor.com,
thomas.lendacky@amd.com
Cc: x86@kernel.org, kas@kernel.org, rick.p.edgecombe@intel.com,
dwmw@amazon.co.uk, linux-kernel@vger.kernel.org,
pbonzini@redhat.com, seanjc@google.com, kvm@vger.kernel.org,
reinette.chatre@intel.com, isaku.yamahata@intel.com,
dan.j.williams@intel.com, ashish.kalra@amd.com,
nik.borisov@suse.com, chao.gao@intel.com, sagis@google.com,
farrah.chen@intel.com
Subject: [PATCH v6 3/7] x86/virt/tdx: Mark memory cache state incoherent when making SEAMCALL
Date: Thu, 14 Aug 2025 11:59:03 +1200 [thread overview]
Message-ID: <9b1fc0cf2f7b4df5bca77affbf770664d9c5e251.1755126788.git.kai.huang@intel.com> (raw)
In-Reply-To: <cover.1755126788.git.kai.huang@intel.com>
On TDX platforms, dirty cacheline aliases with and without encryption
bits can coexist, and the cpu can flush them back to memory in random
order. During kexec, the caches must be flushed before jumping to the
new kernel otherwise the dirty cachelines could silently corrupt the
memory used by the new kernel due to different encryption property.
A percpu boolean is used to mark whether the cache of a given CPU may be
in an incoherent state, and the kexec performs WBINVD on the CPUs with
that boolean turned on.
For TDX, only the TDX module or the TDX guests can generate dirty
cachelines of TDX private memory, i.e., they are only generated when the
kernel does a SEAMCALL.
Set that boolean when the kernel does SEAMCALL so that kexec can flush
the cache correctly.
The kernel provides both the __seamcall*() assembly functions and the
seamcall*() wrapper ones which additionally handle running out of
entropy error in a loop. Most of the SEAMCALLs are called using the
seamcall*(), except TDH.VP.ENTER and TDH.PHYMEM.PAGE.RDMD which are
called using __seamcall*() variant directly.
To cover the two special cases, add a new __seamcall_dirty_cache()
helper which only sets the percpu boolean and calls the __seamcall*(),
and change the special cases to use the new helper. To cover all other
SEAMCALLs, change seamcall*() to call the new helper.
For the SEAMCALLs invoked via seamcall*(), they can be made from both
task context and IRQ disabled context. Given SEAMCALL is just a lengthy
instruction (e.g., thousands of cycles) from kernel's point of view and
preempt_{disable|enable}() is cheap compared to it, just unconditionally
disable preemption during setting the boolean and making SEAMCALL.
Signed-off-by: Kai Huang <kai.huang@intel.com>
Tested-by: Farrah Chen <farrah.chen@intel.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
---
v5 -> v6:
- Rename do_seamcall() to __seamcall_dirty_cache() - Rick.
- Add Rick and Chao's RB.
v4 -> v5:
- Remove unneeded 'ret' local variable in do_seamcall() - Chao.
v3 -> v4:
- Set the boolean for TDH.VP.ENTER and TDH.PHYMEM.PAGE.RDMD. -Rick
- Update the first paragraph to make it shorter -- Rick
- Update changelog to mention the two special cases.
---
arch/x86/include/asm/tdx.h | 25 ++++++++++++++++++++++++-
arch/x86/virt/vmx/tdx/tdx.c | 4 ++--
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 7ddef3a69866..0922265c6bdc 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -102,10 +102,31 @@ u64 __seamcall_ret(u64 fn, struct tdx_module_args *args);
u64 __seamcall_saved_ret(u64 fn, struct tdx_module_args *args);
void tdx_init(void);
+#include <linux/preempt.h>
#include <asm/archrandom.h>
+#include <asm/processor.h>
typedef u64 (*sc_func_t)(u64 fn, struct tdx_module_args *args);
+static __always_inline u64 __seamcall_dirty_cache(sc_func_t func, u64 fn,
+ struct tdx_module_args *args)
+{
+ lockdep_assert_preemption_disabled();
+
+ /*
+ * SEAMCALLs are made to the TDX module and can generate dirty
+ * cachelines of TDX private memory. Mark cache state incoherent
+ * so that the cache can be flushed during kexec.
+ *
+ * This needs to be done before actually making the SEAMCALL,
+ * because kexec-ing CPU could send NMI to stop remote CPUs,
+ * in which case even disabling IRQ won't help here.
+ */
+ this_cpu_write(cache_state_incoherent, true);
+
+ return func(fn, args);
+}
+
static __always_inline u64 sc_retry(sc_func_t func, u64 fn,
struct tdx_module_args *args)
{
@@ -113,7 +134,9 @@ static __always_inline u64 sc_retry(sc_func_t func, u64 fn,
u64 ret;
do {
- ret = func(fn, args);
+ preempt_disable();
+ ret = __seamcall_dirty_cache(func, fn, args);
+ preempt_enable();
} while (ret == TDX_RND_NO_ENTROPY && --retry);
return ret;
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index c7a9a087ccaf..3ea6f587c81a 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1266,7 +1266,7 @@ static bool paddr_is_tdx_private(unsigned long phys)
return false;
/* Get page type from the TDX module */
- sret = __seamcall_ret(TDH_PHYMEM_PAGE_RDMD, &args);
+ sret = __seamcall_dirty_cache(__seamcall_ret, TDH_PHYMEM_PAGE_RDMD, &args);
/*
* The SEAMCALL will not return success unless there is a
@@ -1522,7 +1522,7 @@ noinstr __flatten u64 tdh_vp_enter(struct tdx_vp *td, struct tdx_module_args *ar
{
args->rcx = tdx_tdvpr_pa(td);
- return __seamcall_saved_ret(TDH_VP_ENTER, args);
+ return __seamcall_dirty_cache(__seamcall_saved_ret, TDH_VP_ENTER, args);
}
EXPORT_SYMBOL_GPL(tdh_vp_enter);
--
2.50.1
next prev parent reply other threads:[~2025-08-13 23:59 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-13 23:59 [PATCH v6 0/7] TDX host: kexec/kdump support Kai Huang
2025-08-13 23:59 ` [PATCH v6 1/7] x86/kexec: Consolidate relocate_kernel() function parameters Kai Huang
2025-08-15 10:46 ` Borislav Petkov
2025-08-18 1:15 ` Huang, Kai
2025-08-13 23:59 ` [PATCH v6 2/7] x86/sme: Use percpu boolean to control WBINVD during kexec Kai Huang
2025-08-19 19:28 ` Borislav Petkov
2025-08-19 21:57 ` Huang, Kai
2025-08-13 23:59 ` Kai Huang [this message]
2025-08-13 23:59 ` [PATCH v6 4/7] x86/kexec: Disable kexec/kdump on platforms with TDX partial write erratum Kai Huang
2025-08-13 23:59 ` [PATCH v6 5/7] x86/virt/tdx: Remove the !KEXEC_CORE dependency Kai Huang
2025-08-13 23:59 ` [PATCH v6 6/7] x86/virt/tdx: Update the kexec section in the TDX documentation Kai Huang
2025-08-13 23:59 ` [PATCH v6 7/7] KVM: TDX: Explicitly do WBINVD when no more TDX SEAMCALLs Kai Huang
2025-08-14 13:54 ` Sean Christopherson
2025-08-14 15:38 ` Edgecombe, Rick P
2025-08-14 18:00 ` Sean Christopherson
2025-08-14 22:19 ` Huang, Kai
2025-08-14 23:22 ` Sean Christopherson
2025-08-15 0:00 ` Huang, Kai
2025-08-19 10:31 ` Paolo Bonzini
2025-08-19 21:53 ` Huang, Kai
2025-08-20 9:51 ` Paolo Bonzini
2025-08-20 11:22 ` Huang, Kai
2025-08-20 20:35 ` Paolo Bonzini
2025-08-20 21:34 ` Huang, Kai
2025-08-20 15:39 ` Paolo Bonzini
2025-08-14 22:25 ` Huang, Kai
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=9b1fc0cf2f7b4df5bca77affbf770664d9c5e251.1755126788.git.kai.huang@intel.com \
--to=kai.huang@intel.com \
--cc=ashish.kalra@amd.com \
--cc=bp@alien8.de \
--cc=chao.gao@intel.com \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@intel.com \
--cc=dwmw@amazon.co.uk \
--cc=farrah.chen@intel.com \
--cc=hpa@zytor.com \
--cc=isaku.yamahata@intel.com \
--cc=kas@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=nik.borisov@suse.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=reinette.chatre@intel.com \
--cc=rick.p.edgecombe@intel.com \
--cc=sagis@google.com \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--cc=thomas.lendacky@amd.com \
--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;
as well as URLs for NNTP newsgroup(s).