英特爾可信域擴充套件 (TDX)

概述

英特爾的可信域擴充套件 (TDX) 保護機密客戶虛擬機器免受主機和物理攻擊。一個名為“TDX 模組”的 CPU 認證軟體模組在一個新的 CPU 隔離範圍內執行,以提供管理和執行受保護虛擬機器(又稱 TDX 客戶機或 TD)的功能。

請參閱 [1] 獲取白皮書、規範和其他資源。

本文件描述了 TDX 特有的 KVM ABI。TDX 模組在使用 KVM 執行任何 TDX 客戶機之前需要進行初始化。主機核心核心提供初始化 TDX 模組的支援,具體描述請參見英特爾可信域擴充套件 (TDX)

API 描述

KVM_MEMORY_ENCRYPT_OP

型別:

VM ioctl, VCPU ioctl

對於 TDX 操作,KVM_MEMORY_ENCRYPT_OP 被重新用作帶有 TDX 特定子 ioctl() 命令的通用 ioctl。

/* Trust Domain Extensions sub-ioctl() commands. */
enum kvm_tdx_cmd_id {
        KVM_TDX_CAPABILITIES = 0,
        KVM_TDX_INIT_VM,
        KVM_TDX_INIT_VCPU,
        KVM_TDX_INIT_MEM_REGION,
        KVM_TDX_FINALIZE_VM,
        KVM_TDX_GET_CPUID,

        KVM_TDX_CMD_NR_MAX,
};

struct kvm_tdx_cmd {
      /* enum kvm_tdx_cmd_id */
      __u32 id;
      /* flags for sub-command. If sub-command doesn't use this, set zero. */
      __u32 flags;
      /*
       * data for each sub-command. An immediate or a pointer to the actual
       * data in process virtual address.  If sub-command doesn't use it,
       * set zero.
       */
      __u64 data;
      /*
       * Auxiliary error code.  The sub-command may return TDX SEAMCALL
       * status code in addition to -Exxx.
       */
      __u64 hw_error;
};

KVM_TDX_CAPABILITIES

型別:

VM ioctl

返回值:

成功時為 0,錯誤時為 <0

返回當前 KVM 在系統中載入特定 TDX 模組後支援的 TDX 功能。它報告允許為 TDX 客戶機配置哪些功能/特性。

  • id: KVM_TDX_CAPABILITIES

  • flags: 必須為 0

  • data: 指向 struct kvm_tdx_capabilities 的指標

  • hw_error: 必須為 0

struct kvm_tdx_capabilities {
      __u64 supported_attrs;
      __u64 supported_xfam;
      __u64 reserved[254];

      /* Configurable CPUID bits for userspace */
      struct kvm_cpuid2 cpuid;
};

KVM_TDX_INIT_VM

型別:

VM ioctl

返回值:

成功時為 0,錯誤時為 <0

執行 TDX 特定的 VM 初始化。這需要在呼叫 KVM_CREATE_VM 之後、建立任何 VCPU 之前呼叫。

  • id: KVM_TDX_INIT_VM

  • flags: 必須為 0

  • data: 指向 struct kvm_tdx_init_vm 的指標

  • hw_error: 必須為 0

struct kvm_tdx_init_vm {
        __u64 attributes;
        __u64 xfam;
        __u64 mrconfigid[6];          /* sha384 digest */
        __u64 mrowner[6];             /* sha384 digest */
        __u64 mrownerconfig[6];       /* sha384 digest */

        /* The total space for TD_PARAMS before the CPUIDs is 256 bytes */
        __u64 reserved[12];

      /*
       * Call KVM_TDX_INIT_VM before vcpu creation, thus before
       * KVM_SET_CPUID2.
       * This configuration supersedes KVM_SET_CPUID2s for VCPUs because the
       * TDX module directly virtualizes those CPUIDs without VMM.  The user
       * space VMM, e.g. qemu, should make KVM_SET_CPUID2 consistent with
       * those values.  If it doesn't, KVM may have wrong idea of vCPUIDs of
       * the guest, and KVM may wrongly emulate CPUIDs or MSRs that the TDX
       * module doesn't virtualize.
       */
        struct kvm_cpuid2 cpuid;
};

KVM_TDX_INIT_VCPU

型別:

VCPU ioctl

返回值:

成功時為 0,錯誤時為 <0

執行 TDX 特定的 VCPU 初始化。

  • id: KVM_TDX_INIT_VCPU

  • flags: 必須為 0

  • data: 客戶機 TD VCPU RCX 的初始值

  • hw_error: 必須為 0

KVM_TDX_INIT_MEM_REGION

型別:

VCPU ioctl

返回值:

成功時為 0,錯誤時為 <0

使用使用者空間提供的 @source_addr 資料,從 @gpa 開始初始化 @nr_pages 的 TDX 客戶機私有記憶體。

注意,在呼叫此子命令之前,範圍 [gpa, gpa + nr_pages] 的記憶體屬性需要是私有的。使用者空間可以使用 KVM_SET_MEMORY_ATTRIBUTES 來設定屬性。

如果指定了 KVM_TDX_MEASURE_MEMORY_REGION 標誌,它還會擴充套件測量。

  • id: KVM_TDX_INIT_MEM_REGION

  • flags: 目前僅定義了 KVM_TDX_MEASURE_MEMORY_REGION

  • data: 指向 struct kvm_tdx_init_mem_region 的指標

  • hw_error: 必須為 0

#define KVM_TDX_MEASURE_MEMORY_REGION   (1UL << 0)

struct kvm_tdx_init_mem_region {
        __u64 source_addr;
        __u64 gpa;
        __u64 nr_pages;
};

KVM_TDX_FINALIZE_VM

型別:

VM ioctl

返回值:

成功時為 0,錯誤時為 <0

完成初始 TD 內容的測量並標記為可執行。

  • id: KVM_TDX_FINALIZE_VM

  • flags: 必須為 0

  • data: 必須為 0

  • hw_error: 必須為 0

KVM_TDX_GET_CPUID

型別:

VCPU ioctl

返回值:

成功時為 0,錯誤時為 <0

獲取 TDX 模組為 TD 客戶機虛擬化的 CPUID 值。當返回 -E2BIG 時,使用者空間應分配更大的緩衝區並重試。最小緩衝區大小會在 struct kvm_cpuid2 的 nent 欄位中更新。

  • id: KVM_TDX_GET_CPUID

  • flags: 必須為 0

  • data: 指向 struct kvm_cpuid2 的指標 (輸入/輸出)

  • hw_error: 必須為 0 (輸出)

struct kvm_cpuid2 {
        __u32 nent;
        __u32 padding;
        struct kvm_cpuid_entry2 entries[0];
};

struct kvm_cpuid_entry2 {
        __u32 function;
        __u32 index;
        __u32 flags;
        __u32 eax;
        __u32 ebx;
        __u32 ecx;
        __u32 edx;
        __u32 padding[3];
};

KVM TDX 建立流程

除了標準的 KVM 流程外,還需要呼叫新的 TDX ioctl。控制流程如下

  1. 檢查系統範圍功能

    • KVM_CAP_VM_TYPES: 檢查是否支援 VM 型別以及是否支援 KVM_X86_TDX_VM。

  2. 建立 VM

    • KVM_CREATE_VM

    • KVM_TDX_CAPABILITIES: 查詢用於建立 TDX 客戶機的 TDX 功能。

    • KVM_CHECK_EXTENSION(KVM_CAP_MAX_VCPUS): 查詢 TD 在 VM 級別可以支援的最大 VCPU 數量 (TDX 在此方面有自己的限制)。

    • KVM_SET_TSC_KHZ: 如果需要與主機不同的 TSC 頻率,請配置 TD 的 TSC 頻率。這是可選的。

    • KVM_TDX_INIT_VM: 傳遞 TDX 特定的 VM 引數。

  3. 建立 VCPU

    • KVM_CREATE_VCPU

    • KVM_TDX_INIT_VCPU: 傳遞 TDX 特定的 VCPU 引數。

    • KVM_SET_CPUID2: 配置 TD 的 CPUID。

    • KVM_SET_MSRS: 配置 TD 的 MSR。

  4. 初始化初始客戶機記憶體

    • 準備初始客戶機記憶體的內容。

    • KVM_TDX_INIT_MEM_REGION: 新增初始客戶機記憶體。

    • KVM_TDX_FINALIZE_VM: 完成 TDX 客戶機的測量。

  5. 執行 VCPU

參考

https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/documentation.html