@@ -129,13 +129,28 @@ struct tdx_td {
int tdcs_nr_pages;
/* TD control structure: */
struct page **tdcs_pages;
+
+ /* Size of `tdcx_pages` in struct tdx_vp */
+ int tdcx_nr_pages;
+};
+
+struct tdx_vp {
+ /* TDVP root page */
+ struct page *tdvpr_page;
+
+ /* TD vCPU control structure: */
+ struct page **tdcx_pages;
};
u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page);
+u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_page);
u64 tdh_mng_key_config(struct tdx_td *td);
u64 tdh_mng_create(struct tdx_td *td, u64 hkid);
+u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp);
u64 tdh_mng_key_freeid(struct tdx_td *td);
u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err);
+u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx);
+u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid);
#else
static inline void tdx_init(void) { }
static inline int tdx_cpu_enable(void) { return -ENODEV; }
@@ -5,6 +5,7 @@
* Intel Trusted Domain Extensions (TDX) support
*/
+#include "asm/page_types.h"
#define pr_fmt(fmt) "virt/tdx: " fmt
#include <linux/types.h>
@@ -1568,6 +1569,11 @@ static inline u64 tdx_tdr_pa(struct tdx_td *td)
return page_to_pfn(td->tdr_page) << PAGE_SHIFT;
}
+static inline u64 tdx_tdvpr_pa(struct tdx_vp *td)
+{
+ return page_to_pfn(td->tdvpr_page) << PAGE_SHIFT;
+}
+
/*
* 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.
@@ -1591,6 +1597,18 @@ u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page)
}
EXPORT_SYMBOL_GPL(tdh_mng_addcx);
+u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_page)
+{
+ struct tdx_module_args args = {
+ .rcx = page_to_pfn(tdcx_page) << PAGE_SHIFT,
+ .rdx = tdx_tdvpr_pa(vp),
+ };
+
+ tdx_clflush_page(tdcx_page);
+ return seamcall(TDH_VP_ADDCX, &args);
+}
+EXPORT_SYMBOL_GPL(tdh_vp_addcx);
+
u64 tdh_mng_key_config(struct tdx_td *td)
{
struct tdx_module_args args = {
@@ -1613,6 +1631,18 @@ u64 tdh_mng_create(struct tdx_td *td, u64 hkid)
}
EXPORT_SYMBOL_GPL(tdh_mng_create);
+u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp)
+{
+ struct tdx_module_args args = {
+ .rcx = tdx_tdvpr_pa(vp),
+ .rdx = tdx_tdr_pa(td),
+ };
+
+ tdx_clflush_page(vp->tdvpr_page);
+ return seamcall(TDH_VP_CREATE, &args);
+}
+EXPORT_SYMBOL_GPL(tdh_vp_create);
+
u64 tdh_mng_key_freeid(struct tdx_td *td)
{
struct tdx_module_args args = {
@@ -1639,3 +1669,26 @@ u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err)
}
EXPORT_SYMBOL_GPL(tdh_mng_init);
+u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx)
+{
+ struct tdx_module_args args = {
+ .rcx = tdx_tdvpr_pa(vp),
+ .rdx = initial_rcx,
+ };
+
+ return seamcall(TDH_VP_INIT, &args);
+}
+EXPORT_SYMBOL_GPL(tdh_vp_init);
+
+u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid)
+{
+ struct tdx_module_args args = {
+ .rcx = tdx_tdvpr_pa(vp),
+ .rdx = initial_rcx,
+ .r8 = x2apicid,
+ };
+
+ /* apicid requires version == 1. */
+ return seamcall(TDH_VP_INIT | (1ULL << TDX_VERSION_SHIFT), &args);
+}
+EXPORT_SYMBOL_GPL(tdh_vp_init_apicid);
@@ -18,10 +18,13 @@
* TDX module SEAMCALL leaf functions
*/
#define TDH_MNG_ADDCX 1
+#define TDH_VP_ADDCX 4
#define TDH_MNG_KEY_CONFIG 8
#define TDH_MNG_CREATE 9
+#define TDH_VP_CREATE 10
#define TDH_MNG_KEY_FREEID 20
#define TDH_MNG_INIT 21
+#define TDH_VP_INIT 22
#define TDH_PHYMEM_PAGE_RDMD 24
#define TDH_SYS_KEY_CONFIG 31
#define TDH_SYS_INIT 33
@@ -30,6 +33,14 @@
#define TDH_SYS_TDMR_INIT 36
#define TDH_SYS_CONFIG 45
+/*
+ * SEAMCALL leaf:
+ *
+ * Bit 15:0 Leaf number
+ * Bit 23:16 Version number
+ */
+#define TDX_VERSION_SHIFT 16
+
/* TDX page types */
#define PT_NDA 0x0
#define PT_RSVD 0x1