From: Yan Zhao <yan.y.zhao@intel.com>
To: pbonzini@redhat.com, seanjc@google.com, kvm@vger.kernel.org,
dave.hansen@linux.intel.com
Cc: rick.p.edgecombe@intel.com, kai.huang@intel.com,
adrian.hunter@intel.com, reinette.chatre@intel.com,
xiaoyao.li@intel.com, tony.lindgren@intel.com,
binbin.wu@linux.intel.com, dmatlack@google.com,
isaku.yamahata@intel.com, isaku.yamahata@gmail.com,
nik.borisov@suse.com, linux-kernel@vger.kernel.org,
x86@kernel.org
Subject: [PATCH v2 24/24] [HACK] KVM: TDX: Retry seamcall when TDX_OPERAND_BUSY with operand SEPT
Date: Tue, 12 Nov 2024 15:39:09 +0800 [thread overview]
Message-ID: <20241112073909.22326-1-yan.y.zhao@intel.com> (raw)
In-Reply-To: <20241112073327.21979-1-yan.y.zhao@intel.com>
From: Yuan Yao <yuan.yao@intel.com>
Temporary retry in SEAMCALL wrappers when the TDX module returns
TDX_OPERAND_BUSY with operand SEPT.
The TDX module has many internal locks to protect its resources. To avoid
staying in SEAM mode for too long, SEAMCALLs will return a TDX_OPERAND_BUSY
error code to the kernel instead of spinning on the locks.
Usually, callers of the SEAMCALL wrappers can avoid contentions by
implementing proper locks on their side. For example, KVM can efficiently
avoid the TDX module's lock contentions for resources like TDR, TDCS, KOT,
and TDVPR by taking locks within KVM or making a resource per-thread.
However, for performance reasons, callers like KVM may not want to use
exclusive locks to avoid internal contentions on the SEPT tree within the
TDX module. For instance, KVM allows TDH.VP.ENTER to run concurrently with
TDH.MEM.SEPT.ADD, TDH.MEM.PAGE.AUG, and TDH.MEM.PAGE.REMOVE.
Resources SHARED users EXCLUSIVE users
------------------------------------------------------------------------
SEPT tree TDH.MEM.SEPT.ADD TDH.VP.ENTER
TDH.MEM.PAGE.AUG TDH.MEM.SEPT.REMOVE
TDH.MEM.PAGE.REMOVE TDH.MEM.RANGE.BLOCK
Inside the TDX module, although TDH.VP.ENTER only acquires an exclusive
lock on the SEPT tree when zero-step mitigation is triggered, it is still
possible to encounter TDX_OPERAND_BUSY with operand SEPT in KVM. Retry in
the SEAMCALL wrappers temporarily until KVM either retries on the caller
side or finds a way to avoid the contentions.
Note:
The wrappers only retry for 16 times for the TDX_OPERAND_BUSY with operand
SEPT. Retries exceeding 16 times are rare.
SEAMCALLs TDH.MEM.* can also contend with TDCALL TDG.MEM.PAGE.ACCEPT,
returning TDX_OPERAND_BUSY without operand SEPT. Do not retry in the
SEAMCALL wrappers for such rare errors.
Let the callers handle these rare errors.
Signed-off-by: Yuan Yao <yuan.yao@intel.com>
Co-developed-by: Isaku Yamahata <isaku.yamahata@intel.com>
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Co-developed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Co-developed-by: Yan Zhao <yan.y.zhao@intel.com>
Signed-off-by: Yan Zhao <yan.y.zhao@intel.com>
---
TDX MMU part 2 v2:
- Updates the patch log. (Yan)
TDX MMU part 2 v1:
- Updates from seamcall overhaul (Kai)
v19:
- fix typo TDG.VP.ENTER => TDH.VP.ENTER,
TDX_OPRRAN_BUSY => TDX_OPERAND_BUSY
- drop the description on TDH.VP.ENTER as this patch doesn't touch
TDH.VP.ENTER
---
arch/x86/virt/vmx/tdx/tdx.c | 47 +++++++++++++++++++++++++++++++++----
1 file changed, 42 insertions(+), 5 deletions(-)
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 7e0574facfb0..04cb2f1d6deb 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1563,6 +1563,43 @@ void tdx_guest_keyid_free(unsigned int keyid)
}
EXPORT_SYMBOL_GPL(tdx_guest_keyid_free);
+/*
+ * TDX module acquires its internal lock for resources. It doesn't spin to get
+ * locks because of its restrictions of allowed execution time. Instead, it
+ * returns TDX_OPERAND_BUSY with an operand id.
+ *
+ * Multiple VCPUs can operate on SEPT. Also with zero-step attack mitigation,
+ * TDH.VP.ENTER may rarely acquire SEPT lock and release it when zero-step
+ * attack is suspected. It results in TDX_OPERAND_BUSY | TDX_OPERAND_ID_SEPT
+ * with TDH.MEM.* operation. Note: TDH.MEM.TRACK is an exception.
+ *
+ * Because TDP MMU uses read lock for scalability, spin lock around SEAMCALL
+ * spoils TDP MMU effort. Retry several times with the assumption that SEPT
+ * lock contention is rare. But don't loop forever to avoid lockup. Let TDP
+ * MMU retry.
+ */
+#define TDX_OPERAND_BUSY 0x8000020000000000ULL
+#define TDX_OPERAND_ID_SEPT 0x92
+
+#define TDX_ERROR_SEPT_BUSY (TDX_OPERAND_BUSY | TDX_OPERAND_ID_SEPT)
+
+static inline u64 tdx_seamcall_sept(u64 op, struct tdx_module_args *in)
+{
+#define SEAMCALL_RETRY_MAX 16
+ struct tdx_module_args args_in;
+ int retry = SEAMCALL_RETRY_MAX;
+ u64 ret;
+
+ do {
+ args_in = *in;
+ ret = seamcall_ret(op, in);
+ } while (ret == TDX_ERROR_SEPT_BUSY && retry-- > 0);
+
+ *in = args_in;
+
+ return ret;
+}
+
u64 tdh_mng_addcx(u64 tdr, u64 tdcs)
{
struct tdx_module_args args = {
@@ -1586,7 +1623,7 @@ u64 tdh_mem_page_add(u64 tdr, u64 gpa, u64 hpa, u64 source, u64 *rcx, u64 *rdx)
u64 ret;
clflush_cache_range(__va(hpa), PAGE_SIZE);
- ret = seamcall_ret(TDH_MEM_PAGE_ADD, &args);
+ ret = tdx_seamcall_sept(TDH_MEM_PAGE_ADD, &args);
*rcx = args.rcx;
*rdx = args.rdx;
@@ -1605,7 +1642,7 @@ u64 tdh_mem_sept_add(u64 tdr, u64 gpa, u64 level, u64 hpa, u64 *rcx, u64 *rdx)
u64 ret;
clflush_cache_range(__va(hpa), PAGE_SIZE);
- ret = seamcall_ret(TDH_MEM_SEPT_ADD, &args);
+ ret = tdx_seamcall_sept(TDH_MEM_SEPT_ADD, &args);
*rcx = args.rcx;
*rdx = args.rdx;
@@ -1636,7 +1673,7 @@ u64 tdh_mem_page_aug(u64 tdr, u64 gpa, u64 hpa, u64 *rcx, u64 *rdx)
u64 ret;
clflush_cache_range(__va(hpa), PAGE_SIZE);
- ret = seamcall_ret(TDH_MEM_PAGE_AUG, &args);
+ ret = tdx_seamcall_sept(TDH_MEM_PAGE_AUG, &args);
*rcx = args.rcx;
*rdx = args.rdx;
@@ -1653,7 +1690,7 @@ u64 tdh_mem_range_block(u64 tdr, u64 gpa, u64 level, u64 *rcx, u64 *rdx)
};
u64 ret;
- ret = seamcall_ret(TDH_MEM_RANGE_BLOCK, &args);
+ ret = tdx_seamcall_sept(TDH_MEM_RANGE_BLOCK, &args);
*rcx = args.rcx;
*rdx = args.rdx;
@@ -1882,7 +1919,7 @@ u64 tdh_mem_page_remove(u64 tdr, u64 gpa, u64 level, u64 *rcx, u64 *rdx)
};
u64 ret;
- ret = seamcall_ret(TDH_MEM_PAGE_REMOVE, &args);
+ ret = tdx_seamcall_sept(TDH_MEM_PAGE_REMOVE, &args);
*rcx = args.rcx;
*rdx = args.rdx;
--
2.43.2
next prev parent reply other threads:[~2024-11-12 7:41 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-12 7:33 [PATCH v2 00/24] TDX MMU Part 2 Yan Zhao
2024-11-12 7:34 ` [PATCH v2 01/24] KVM: x86/mmu: Implement memslot deletion for TDX Yan Zhao
2024-11-12 7:34 ` [PATCH v2 02/24] KVM: x86/tdp_mmu: Add a helper function to walk down the TDP MMU Yan Zhao
2024-11-12 7:35 ` [PATCH v2 03/24] KVM: x86/mmu: Do not enable page track for TD guest Yan Zhao
2024-11-12 7:35 ` [PATCH v2 04/24] KVM: VMX: Split out guts of EPT violation to common/exposed function Yan Zhao
2024-11-12 7:35 ` [PATCH v2 05/24] KVM: VMX: Teach EPT violation helper about private mem Yan Zhao
2024-11-12 7:35 ` [PATCH v2 06/24] KVM: TDX: Add accessors VMX VMCS helpers Yan Zhao
2024-11-12 7:36 ` [PATCH v2 07/24] KVM: TDX: Add load_mmu_pgd method for TDX Yan Zhao
2024-11-12 7:36 ` [PATCH v2 08/24] KVM: TDX: Set gfn_direct_bits to shared bit Yan Zhao
2024-11-12 7:36 ` [PATCH v2 09/24] x86/virt/tdx: Add SEAMCALL wrapper tdh_mem_sept_add() to add SEPT pages Yan Zhao
2024-11-12 7:36 ` [PATCH v2 10/24] x86/virt/tdx: Add SEAMCALL wrappers to add TD private pages Yan Zhao
2024-11-12 7:36 ` [PATCH v2 11/24] x86/virt/tdx: Add SEAMCALL wrappers to manage TDX TLB tracking Yan Zhao
2024-11-12 7:36 ` [PATCH v2 12/24] x86/virt/tdx: Add SEAMCALL wrappers to remove a TD private page Yan Zhao
2024-11-12 7:37 ` [PATCH v2 13/24] x86/virt/tdx: Add SEAMCALL wrappers for TD measurement of initial contents Yan Zhao
2024-11-12 7:37 ` [PATCH v2 14/24] KVM: TDX: Require TDP MMU and mmio caching for TDX Yan Zhao
2024-11-12 7:37 ` [PATCH v2 15/24] KVM: x86/mmu: Add setter for shadow_mmio_value Yan Zhao
2024-11-12 7:37 ` [PATCH v2 16/24] KVM: TDX: Set per-VM shadow_mmio_value to 0 Yan Zhao
2024-11-12 7:37 ` [PATCH v2 17/24] KVM: TDX: Handle TLB tracking for TDX Yan Zhao
2024-11-12 7:38 ` [PATCH v2 18/24] KVM: TDX: Implement hooks to propagate changes of TDP MMU mirror page table Yan Zhao
2024-11-12 7:38 ` [PATCH v2 19/24] KVM: TDX: Implement hook to get max mapping level of private pages Yan Zhao
2024-11-12 7:38 ` [PATCH v2 20/24] KVM: x86/mmu: Export kvm_tdp_map_page() Yan Zhao
2024-11-12 7:38 ` [PATCH v2 21/24] KVM: TDX: Add an ioctl to create initial guest memory Yan Zhao
2024-11-27 18:08 ` Nikolay Borisov
2024-11-28 2:20 ` Yan Zhao
2024-11-12 7:38 ` [PATCH v2 22/24] KVM: TDX: Finalize VM initialization Yan Zhao
2024-12-24 14:31 ` Paolo Bonzini
2025-01-07 7:44 ` Yan Zhao
2025-01-07 14:02 ` Paolo Bonzini
2025-01-08 2:18 ` Yan Zhao
2024-11-12 7:38 ` [PATCH v2 23/24] KVM: TDX: Handle vCPU dissociation Yan Zhao
2024-11-12 7:39 ` Yan Zhao [this message]
2024-11-21 11:51 ` [RFC PATCH 0/2] SEPT SEAMCALL retry proposal Yan Zhao
2024-11-21 11:56 ` [RFC PATCH 1/2] KVM: TDX: Retry in TDX when installing TD private/sept pages Yan Zhao
2024-11-21 11:57 ` [RFC PATCH 2/2] KVM: TDX: Kick off vCPUs when SEAMCALL is busy during TD page removal Yan Zhao
2024-11-26 0:47 ` Edgecombe, Rick P
2024-11-26 6:39 ` Yan Zhao
2024-12-17 23:29 ` Sean Christopherson
2024-12-18 5:45 ` Yan Zhao
2024-12-18 16:10 ` Sean Christopherson
2024-12-19 1:52 ` Yan Zhao
2024-12-19 2:39 ` Sean Christopherson
2024-12-19 3:03 ` Yan Zhao
2024-11-26 0:46 ` [RFC PATCH 0/2] SEPT SEAMCALL retry proposal Edgecombe, Rick P
2024-11-26 6:24 ` Yan Zhao
2024-12-13 1:01 ` Yan Zhao
2024-12-17 17:00 ` Edgecombe, Rick P
2024-12-17 23:18 ` Sean Christopherson
2024-12-10 18:21 ` [PATCH v2 00/24] TDX MMU Part 2 Paolo Bonzini
2024-12-24 14:33 ` Paolo Bonzini
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=20241112073909.22326-1-yan.y.zhao@intel.com \
--to=yan.y.zhao@intel.com \
--cc=adrian.hunter@intel.com \
--cc=binbin.wu@linux.intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=dmatlack@google.com \
--cc=isaku.yamahata@gmail.com \
--cc=isaku.yamahata@intel.com \
--cc=kai.huang@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nik.borisov@suse.com \
--cc=pbonzini@redhat.com \
--cc=reinette.chatre@intel.com \
--cc=rick.p.edgecombe@intel.com \
--cc=seanjc@google.com \
--cc=tony.lindgren@intel.com \
--cc=x86@kernel.org \
--cc=xiaoyao.li@intel.com \
/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