@@ -97,8 +97,10 @@ static inline long tdx_kvm_hypercall(unsigned int nr, unsigned long p1,
#ifdef CONFIG_INTEL_TDX_HOST
bool platform_tdx_enabled(void);
+int tdx_enable(void);
#else /* !CONFIG_INTEL_TDX_HOST */
static inline bool platform_tdx_enabled(void) { return false; }
+static inline int tdx_enable(void) { return -EINVAL; }
#endif /* CONFIG_INTEL_TDX_HOST */
#endif /* !__ASSEMBLY__ */
@@ -12,13 +12,25 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/printk.h>
+#include <linux/mutex.h>
#include <asm/msr.h>
#include <asm/tdx.h>
#include "tdx.h"
+/* Kernel defined TDX module status during module initialization. */
+enum tdx_module_status_t {
+ TDX_MODULE_UNKNOWN,
+ TDX_MODULE_INITIALIZED,
+ TDX_MODULE_ERROR
+};
+
static u32 tdx_keyid_start __ro_after_init;
static u32 nr_tdx_keyids __ro_after_init;
+static enum tdx_module_status_t tdx_module_status;
+/* Prevent concurrent attempts on TDX detection and initialization */
+static DEFINE_MUTEX(tdx_module_lock);
+
/*
* tdx_keyid_start and nr_tdx_keyids indicate that TDX is uninitialized.
* This is used in TDX initialization error paths to take it from
@@ -88,3 +100,84 @@ bool platform_tdx_enabled(void)
{
return !!nr_tdx_keyids;
}
+
+static int init_tdx_module(void)
+{
+ /*
+ * TODO:
+ *
+ * - Get TDX module information and TDX-capable memory regions.
+ * - Build the list of TDX-usable memory regions.
+ * - Construct a list of TDMRs to cover all TDX-usable memory
+ * regions.
+ * - Pick up one TDX private KeyID as the global KeyID.
+ * - Configure the TDMRs and the global KeyID to the TDX module.
+ * - Configure the global KeyID on all packages.
+ * - Initialize all TDMRs.
+ *
+ * Return error before all steps are done.
+ */
+ return -EINVAL;
+}
+
+static int __tdx_enable(void)
+{
+ int ret;
+
+ ret = init_tdx_module();
+ if (ret) {
+ pr_err_once("initialization failed (%d)\n", ret);
+ tdx_module_status = TDX_MODULE_ERROR;
+ /*
+ * Just return one universal error code.
+ * For now the caller cannot recover anyway.
+ */
+ return -EINVAL;
+ }
+
+ pr_info_once("TDX module initialized.\n");
+ tdx_module_status = TDX_MODULE_INITIALIZED;
+
+ return 0;
+}
+
+/**
+ * tdx_enable - Enable TDX by initializing the TDX module
+ *
+ * The caller must make sure all online cpus are in VMX operation before
+ * calling this function.
+ *
+ * This function can be called in parallel by multiple callers.
+ *
+ * Return 0 if TDX is enabled successfully, otherwise error.
+ */
+int tdx_enable(void)
+{
+ int ret;
+
+ if (!platform_tdx_enabled()) {
+ pr_err_once("initialization failed: TDX is disabled.\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&tdx_module_lock);
+
+ switch (tdx_module_status) {
+ case TDX_MODULE_UNKNOWN:
+ ret = __tdx_enable();
+ break;
+ case TDX_MODULE_INITIALIZED:
+ /* Already initialized, great, tell the caller. */
+ ret = 0;
+ break;
+ default:
+ /* Failed to initialize in the previous attempts */
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&tdx_module_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tdx_enable);