From: Rick Edgecombe <rick.p.edgecombe@intel.com>
To: kvm@vger.kernel.org, pbonzini@redhat.com, seanjc@google.com,
dave.hansen@intel.com
Cc: isaku.yamahata@gmail.com, kai.huang@intel.com,
linux-kernel@vger.kernel.org, tony.lindgren@linux.intel.com,
xiaoyao.li@intel.com, yan.y.zhao@intel.com,
rick.p.edgecombe@intel.com, x86@kernel.org,
adrian.hunter@intel.com,
Isaku Yamahata <isaku.yamahata@intel.com>,
Binbin Wu <binbin.wu@linux.intel.com>,
Yuan Yao <yuan.yao@intel.com>
Subject: [RFC PATCH 2/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX TD creation
Date: Fri, 15 Nov 2024 12:20:23 -0800 [thread overview]
Message-ID: <20241115202028.1585487-3-rick.p.edgecombe@intel.com> (raw)
In-Reply-To: <20241115202028.1585487-1-rick.p.edgecombe@intel.com>
Intel TDX protects guest VMs from malicious hosts and certain physical
attacks. It defines various control structures that hold state for things
like TDs or vCPUs. These control structures are stored in pages given to
the TDX module and encrypted with either the global KeyID or the guest
KeyIDs.
To manipulate these control structures the TDX module defines a few
SEAMCALLs. KVM will use these during the process of creating a TD as
follows:
1) Allocate a unique TDX KeyID for a new guest.
1) Call TDH.MNG.CREATE to create a "TD Root" (TDR) page, together with
the new allocated KeyID. Unlike the rest of the TDX guest, the TDR
page is crypto-protected by the 'global KeyID'.
2) Call the previously added TDH.MNG.KEY.CONFIG on each package to
configure the KeyID for the guest. After this step, the KeyID to
protect the guest is ready and the rest of the guest will be protected
by this KeyID.
3) Call TDH.MNG.ADDCX to add TD Control Structure (TDCS) pages.
4) Call TDH.MNG.INIT to initialize the TDCS.
To reclaim these pages for use by the kernel other SEAMCALLs are needed,
which will be added in future patches.
Add tdh_mng_addcx(), tdh_mng_create() and tdh_mng_init() to export these
SEAMCALLs so that KVM can use them to create TDs.
For SEAMCALLs that give a page to the TDX module to be encrypted, CLFLUSH
the page mapped with KeyID 0, such that any dirty cache lines don't write
back later and clobber TD memory or control structures. Don't worry about
the other MK-TME KeyIDs because the kernel doesn't use them. The TDX docs
specify that this flush is not needed unless the TDX module exposes the
CLFLUSH_BEFORE_ALLOC feature bit. Be conservative and always flush. Add a
helper function to facilitate this.
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Signed-off-by: Kai Huang <kai.huang@intel.com>
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Reviewed-by: Yuan Yao <yuan.yao@intel.com>
---
SEAMCALL RFC:
- Use struct tdx_td
- Introduce tdx_clflush_page() to hold CLFLUSH_BEFORE_ALLOC
explanation
uAPI breakout v2:
- Change to use 'u64' as function parameter to prepare to move
SEAMCALL wrappers to arch/x86. (Kai)
- Split to separate patch
- Move SEAMCALL wrappers from KVM to x86 core;
- Move TDH_xx macros from KVM to x86 core;
- Re-write log
uAPI breakout v1:
- Make argument to C wrapper function struct kvm_tdx * or
struct vcpu_tdx * .(Sean)
- Drop unused helpers (Kai)
- Fix bisectability issues in headers (Kai)
- Updates from seamcall overhaul (Kai)
v19:
- Update the commit message to match the patch by Yuan
- Use seamcall() and seamcall_ret() by paolo
v18:
- removed stub functions for __seamcall{,_ret}()
- Added Reviewed-by Binbin
- Make tdx_seamcall() use struct tdx_module_args instead of taking
each inputs.
---
arch/x86/include/asm/tdx.h | 3 +++
arch/x86/virt/vmx/tdx/tdx.c | 51 +++++++++++++++++++++++++++++++++++++
arch/x86/virt/vmx/tdx/tdx.h | 3 +++
3 files changed, 57 insertions(+)
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index ebee4260545f..4c4d092b7c8e 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -128,8 +128,11 @@ struct tdx_td {
hpa_t *tdcs;
};
+u64 tdh_mng_addcx(struct tdx_td *td, hpa_t tdcs);
u64 tdh_mng_key_config(struct tdx_td *td);
+u64 tdh_mng_create(struct tdx_td *td, hpa_t hkid);
u64 tdh_mng_key_freeid(struct tdx_td *td);
+u64 tdh_mng_init(struct tdx_td *td, u64 td_params, hpa_t *tdr);
#else
static inline void tdx_init(void) { }
static inline int tdx_cpu_enable(void) { return -ENODEV; }
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 20eb756b41de..311f8d85e18d 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1563,6 +1563,29 @@ void tdx_guest_keyid_free(unsigned int keyid)
}
EXPORT_SYMBOL_GPL(tdx_guest_keyid_free);
+/*
+ * The TDX module exposes a CLFLUSH_BEFORE_ALLOC bit to specify whether
+ * a CLFLUSH of pages is required before handing them to the TDX module.
+ * Be conservative and make the code simpler by doing the CLFLUSH
+ * unconditionally.
+ */
+static void tdx_clflush_page(hpa_t tdr)
+{
+ clflush_cache_range(__va(tdr), PAGE_SIZE);
+}
+
+u64 tdh_mng_addcx(struct tdx_td *td, hpa_t tdcs)
+{
+ struct tdx_module_args args = {
+ .rcx = tdcs,
+ .rdx = td->tdr,
+ };
+
+ tdx_clflush_page(tdcs);
+ return seamcall(TDH_MNG_ADDCX, &args);
+}
+EXPORT_SYMBOL_GPL(tdh_mng_addcx);
+
u64 tdh_mng_key_config(struct tdx_td *td)
{
struct tdx_module_args args = {
@@ -1573,6 +1596,18 @@ u64 tdh_mng_key_config(struct tdx_td *td)
}
EXPORT_SYMBOL_GPL(tdh_mng_key_config);
+u64 tdh_mng_create(struct tdx_td *td, hpa_t hkid)
+{
+ struct tdx_module_args args = {
+ .rcx = td->tdr,
+ .rdx = hkid,
+ };
+
+ tdx_clflush_page(td->tdr);
+ return seamcall(TDH_MNG_CREATE, &args);
+}
+EXPORT_SYMBOL_GPL(tdh_mng_create);
+
u64 tdh_mng_key_freeid(struct tdx_td *td)
{
@@ -1584,3 +1619,19 @@ u64 tdh_mng_key_freeid(struct tdx_td *td)
}
EXPORT_SYMBOL_GPL(tdh_mng_key_freeid);
+u64 tdh_mng_init(struct tdx_td *td, u64 td_params, hpa_t *tdr)
+{
+ struct tdx_module_args args = {
+ .rcx = td->tdr,
+ .rdx = td_params,
+ };
+ u64 ret;
+
+ ret = seamcall_ret(TDH_MNG_INIT, &args);
+
+ *tdr = args.rcx;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tdh_mng_init);
+
diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
index 95002e7ff4c5..b9287304f372 100644
--- a/arch/x86/virt/vmx/tdx/tdx.h
+++ b/arch/x86/virt/vmx/tdx/tdx.h
@@ -17,8 +17,11 @@
/*
* TDX module SEAMCALL leaf functions
*/
+#define TDH_MNG_ADDCX 1
#define TDH_MNG_KEY_CONFIG 8
+#define TDH_MNG_CREATE 9
#define TDH_MNG_KEY_FREEID 20
+#define TDH_MNG_INIT 21
#define TDH_PHYMEM_PAGE_RDMD 24
#define TDH_SYS_KEY_CONFIG 31
#define TDH_SYS_INIT 33
--
2.47.0
next prev parent reply other threads:[~2024-11-15 20:20 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-15 20:20 [RFC PATCH 0/6] SEAMCALL Wrappers Rick Edgecombe
2024-11-15 20:20 ` [RFC PATCH 1/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX KeyID management Rick Edgecombe
2024-11-22 18:04 ` Dave Hansen
2024-11-22 23:55 ` Sean Christopherson
2024-11-22 23:59 ` Dave Hansen
2024-11-23 0:08 ` Dave Hansen
2024-11-23 2:06 ` Edgecombe, Rick P
2024-11-27 18:15 ` Paolo Bonzini
2024-11-27 23:04 ` Edgecombe, Rick P
2024-11-25 15:44 ` Sean Christopherson
2024-11-25 15:46 ` Dave Hansen
2024-11-15 20:20 ` Rick Edgecombe [this message]
2024-11-15 20:20 ` [RFC PATCH 3/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX vCPU creation Rick Edgecombe
2024-11-15 20:20 ` [RFC PATCH 4/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX page cache management Rick Edgecombe
2024-11-15 20:20 ` [RFC PATCH 5/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX VM/vCPU field access Rick Edgecombe
2024-11-15 20:20 ` [RFC PATCH 6/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX flush operations Rick Edgecombe
2024-12-24 14:57 ` [RFC PATCH 0/6] SEAMCALL Wrappers 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=20241115202028.1585487-3-rick.p.edgecombe@intel.com \
--to=rick.p.edgecombe@intel.com \
--cc=adrian.hunter@intel.com \
--cc=binbin.wu@linux.intel.com \
--cc=dave.hansen@intel.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=pbonzini@redhat.com \
--cc=seanjc@google.com \
--cc=tony.lindgren@linux.intel.com \
--cc=x86@kernel.org \
--cc=xiaoyao.li@intel.com \
--cc=yan.y.zhao@intel.com \
--cc=yuan.yao@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