@@ -1108,6 +1108,56 @@ static int config_global_keyid(void)
return ret;
}
+static int init_tdmr(struct tdmr_info *tdmr)
+{
+ u64 next;
+
+ /*
+ * Initializing a TDMR can be time consuming. To avoid long
+ * SEAMCALLs, the TDX module may only initialize a part of the
+ * TDMR in each call.
+ */
+ do {
+ struct tdx_module_output out;
+ int ret;
+
+ /* All 0's are unused parameters, they mean nothing. */
+ ret = seamcall(TDH_SYS_TDMR_INIT, tdmr->base, 0, 0, 0, NULL,
+ &out);
+ if (ret)
+ return ret;
+ /*
+ * RDX contains 'next-to-initialize' address if
+ * TDH.SYS.TDMR.INIT did not fully complete and
+ * should be retried.
+ */
+ next = out.rdx;
+ cond_resched();
+ /* Keep making SEAMCALLs until the TDMR is done */
+ } while (next < tdmr->base + tdmr->size);
+
+ return 0;
+}
+
+static int init_tdmrs(struct tdmr_info_list *tdmr_list)
+{
+ int i;
+
+ /*
+ * This operation is costly. It can be parallelized,
+ * but keep it simple for now.
+ */
+ for (i = 0; i < tdmr_list->nr_consumed_tdmrs; i++) {
+ int ret;
+
+ ret = init_tdmr(tdmr_entry(tdmr_list, i));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int init_tdx_module(void)
{
static DECLARE_PADDED_STRUCT(tdsysinfo_struct, tdsysinfo,
@@ -1168,15 +1218,9 @@ static int init_tdx_module(void)
if (ret)
goto out_free_pamts;
- /*
- * TODO:
- *
- * - Initialize all TDMRs.
- *
- * Return error before all steps are done.
- */
+ /* Initialize TDMRs to complete the TDX module initialization */
+ ret = init_tdmrs(&tdmr_list);
- ret = -EINVAL;
out_free_pamts:
if (ret) {
/*
@@ -21,6 +21,7 @@
#define TDH_SYS_INFO 32
#define TDH_SYS_CONFIG 45
#define TDH_SYS_KEY_CONFIG 31
+#define TDH_SYS_TDMR_INIT 36
struct cmr_info {
u64 base;