요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
===================================
Intel Trust Domain Extensions (TDX)
===================================
Overview
========
Intel's Trust Domain Extensions (TDX) protect confidential guest VMs from the
host and physical attacks. A CPU-attested software module called 'the TDX
module' runs inside a new CPU isolated range to provide the functionalities to
manage and run protected VMs, a.k.a, TDX guests or TDs.
Please refer to [1] for the whitepaper, specifications and other resources.
This documentation describes TDX-specific KVM ABIs. The TDX module needs to be
initialized before it can be used by KVM to run any TDX guests. The host
core-kernel provides the support of initializing the TDX module, which is
described in the Documentation/arch/x86/tdx.rst.
API description
===============
KVM_MEMORY_ENCRYPT_OP
---------------------
:Type: vm ioctl, vcpu ioctl
For TDX operations, KVM_MEMORY_ENCRYPT_OP is re-purposed to be generic
ioctl with TDX specific sub-ioctl() commands.
::
/* 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
--------------------
:Type: vm ioctl
:Returns: 0 on success, <0 on error
Return the TDX capabilities that current KVM supports with the specific TDX
module loaded in the system. It reports what features/capabilities are allowed
to be configured to the TDX guest.
- id: KVM_TDX_CAPABILITIES
- flags: must be 0
- data: pointer to struct kvm_tdx_capabilities
- hw_error: must be 0
::
struct kvm_tdx_capabilities {
__u64 supported_attrs;
__u64 supported_xfam;
/* TDG.VP.VMCALL hypercalls executed in kernel and forwarded to
* userspace, respectively
*/
__u64 kernel_tdvmcallinfo_1_r11;
__u64 user_tdvmcallinfo_1_r11;
/* TDG.VP.VMCALL instruction executions subfunctions executed in kernel
* and forwarded to userspace, respectively
*/
__u64 kernel_tdvmcallinfo_1_r12;
__u64 user_tdvmcallinfo_1_r12;
__u64 reserved[250];
/* Configurable CPUID bits for userspace */
struct kvm_cpuid2 cpuid;
};
KVM_TDX_INIT_VM
---------------
:Type: vm ioctl
:Returns: 0 on success, <0 on error
Perform TDX specific VM initialization. This needs to be called after
KVM_CREATE_VM and before creating any VCPUs.
- id: KVM_TDX_INIT_VM
- flags: must be 0
- data: pointer to struct kvm_tdx_init_vm
- hw_error: must be 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
-----------------
:Type: vcpu ioctl
:Returns: 0 on success, <0 on error
Perform TDX specific VCPU initialization.
- id: KVM_TDX_INIT_VCPU
- flags: must be 0
- data: initial value of the guest TD VCPU RCX
- hw_error: must be 0
KVM_TDX_INIT_MEM_REGION
-----------------------
:Type: vcpu ioctl
:Returns: 0 on success, <0 on error
Initialize @nr_pages TDX guest private memory starting from @gpa with userspace
provided data from @source_addr.
Note, before calling this sub command, memory attribute of the range
[gpa, gpa + nr_pages] needs to be private. Userspace can use
KVM_SET_MEMORY_ATTRIBUTES to set the attribute.
If KVM_TDX_MEASURE_MEMORY_REGION flag is specified, it also extends measurement.
- id: KVM_TDX_INIT_MEM_REGION
- flags: currently only KVM_TDX_MEASURE_MEMORY_REGION is defined
- data: pointer to struct kvm_tdx_init_mem_region
- hw_error: must be 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
-------------------
:Type: vm ioctl
:Returns: 0 on success, <0 on error
Complete measurement of the initial TD contents and mark it ready to run.
- id: KVM_TDX_FINALIZE_VM
- flags: must be 0
- data: must be 0
- hw_error: must be 0
KVM_TDX_GET_CPUID
-----------------
:Type: vcpu ioctl
:Returns: 0 on success, <0 on error
Get the CPUID values that the TDX module virtualizes for the TD guest.
When it returns -E2BIG, the user space should allocate a larger buffer and
retry. The minimum buffer size is updated in the nent field of the
struct kvm_cpuid2.
- id: KVM_TDX_GET_CPUID
- flags: must be 0
- data: pointer to struct kvm_cpuid2 (in/out)
- hw_error: must be 0 (out)
::
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 creation flow
=====================
In addition to the standard KVM flow, new TDX ioctls need to be called. The
control flow is as follows:
#. Check system wide capability
* KVM_CAP_VM_TYPES: Check if VM type is supported and if KVM_X86_TDX_VM
is supported.
#. Create VM
* KVM_CREATE_VM
* KVM_TDX_CAPABILITIES: Query TDX capabilities for creating TDX guests.
* KVM_CHECK_EXTENSION(KVM_CAP_MAX_VCPUS): Query maximum VCPUs the TD can
support at VM level (TDX has its own limitation on this).
* KVM_SET_TSC_KHZ: Configure TD's TSC frequency if a different TSC frequency
than host is desired. This is Optional.
* KVM_TDX_INIT_VM: Pass TDX specific VM parameters.
#. Create VCPU
* KVM_CREATE_VCPU
* KVM_TDX_INIT_VCPU: Pass TDX specific VCPU parameters.
* KVM_SET_CPUID2: Configure TD's CPUIDs.
* KVM_SET_MSRS: Configure TD's MSRs.
#. Initialize initial guest memory
* Prepare content of initial guest memory.
* KVM_TDX_INIT_MEM_REGION: Add initial guest memory.
* KVM_TDX_FINALIZE_VM: Finalize the measurement of the TDX guest.
#. Run VCPU
References
==========
https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/documentation.html
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
TDX 보호 모델
1-21Intel TDX는 confidential guest VM을 host와 물리 공격으로부터 보호합니다. CPU가 attest한 TDX module이 새 CPU isolated range에서 실행되어 TDX guest 또는 Trust Domain(TD)을 관리하고 실행합니다.
이 문서는 TDX-specific KVM ABI를 정의합니다. KVM이 TD를 실행하기 전에 host core kernel이 TDX module을 초기화해야 하며 해당 절차는 `Documentation/arch/x86/tdx.rst`에 있습니다.
.. SPDX-License-Identifier: GPL-2.0
===================================
Intel Trust Domain Extensions (TDX)
===================================
Overview
========
Intel's Trust Domain Extensions (TDX) protect confidential guest VMs from the
host and physical attacks. A CPU-attested software module called 'the TDX
module' runs inside a new CPU isolated range to provide the functionalities to
manage and run protected VMs, a.k.a, TDX guests or TDs.
Please refer to [1] for the whitepaper, specifications and other resources.
This documentation describes TDX-specific KVM ABIs. The TDX module needs to be
initialized before it can be used by KVM to run any TDX guests. The host
core-kernel provides the support of initializing the TDX module, which is
described in the Documentation/arch/x86/tdx.rst.
API description
KVM_MEMORY_ENCRYPT_OP command envelope
22-62TDX는 VM·vCPU ioctl인 `KVM_MEMORY_ENCRYPT_OP`을 TDX sub-ioctl을 담는 generic command로 재사용합니다.
TDX 수명주기 subcommand입니다.
모든 subcommand의 공통 입력·출력입니다.
===============
KVM_MEMORY_ENCRYPT_OP
---------------------
:Type: vm ioctl, vcpu ioctl
For TDX operations, KVM_MEMORY_ENCRYPT_OP is re-purposed to be generic
ioctl with TDX specific sub-ioctl() commands.
::
/* 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
63-101현재 system의 TDX module과 KVM이 지원하는 capability 및 guest에 구성 가능한 기능을 반환합니다. flags와 hw_error 입력은 0, data는 `struct kvm_tdx_capabilities` pointer입니다.
TD attribute, XFAM, TDVMCALL 처리 위치와 CPUID를 보고합니다.
KVM_TDX_CAPABILITIES
--------------------
:Type: vm ioctl
:Returns: 0 on success, <0 on error
Return the TDX capabilities that current KVM supports with the specific TDX
module loaded in the system. It reports what features/capabilities are allowed
to be configured to the TDX guest.
- id: KVM_TDX_CAPABILITIES
- flags: must be 0
- data: pointer to struct kvm_tdx_capabilities
- hw_error: must be 0
::
struct kvm_tdx_capabilities {
__u64 supported_attrs;
__u64 supported_xfam;
/* TDG.VP.VMCALL hypercalls executed in kernel and forwarded to
* userspace, respectively
*/
__u64 kernel_tdvmcallinfo_1_r11;
__u64 user_tdvmcallinfo_1_r11;
/* TDG.VP.VMCALL instruction executions subfunctions executed in kernel
* and forwarded to userspace, respectively
*/
__u64 kernel_tdvmcallinfo_1_r12;
__u64 user_tdvmcallinfo_1_r12;
__u64 reserved[250];
/* Configurable CPUID bits for userspace */
struct kvm_cpuid2 cpuid;
};
KVM_TDX_INIT_VM
102-140`KVM_CREATE_VM` 뒤 어떤 vCPU도 만들기 전에 TDX-specific VM initialization을 수행합니다. attributes, XFAM과 SHA-384 measurement identity 값을 전달합니다.
TD_PARAMS의 identity와 CPUID 구성입니다.
이 CPUID 구성은 vCPU별 `KVM_SET_CPUID2`보다 우선합니다. QEMU 같은 VMM은 두 값을 일치시켜야 하며, 다르면 KVM이 guest vCPUID를 잘못 이해해 TDX module이 가상화하지 않는 CPUID나 MSR을 잘못 에뮬레이션할 수 있습니다.
KVM_TDX_INIT_VM
---------------
:Type: vm ioctl
:Returns: 0 on success, <0 on error
Perform TDX specific VM initialization. This needs to be called after
KVM_CREATE_VM and before creating any VCPUs.
- id: KVM_TDX_INIT_VM
- flags: must be 0
- data: pointer to struct kvm_tdx_init_vm
- hw_error: must be 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
141-152vCPU ioctl로 TDX-specific vCPU initialization을 수행합니다. flags와 hw_error는 0이며 data에 guest TD vCPU의 초기 RCX 값을 직접 전달합니다.
KVM_TDX_INIT_VCPU
-----------------
:Type: vcpu ioctl
:Returns: 0 on success, <0 on error
Perform TDX specific VCPU initialization.
- id: KVM_TDX_INIT_VCPU
- flags: must be 0
- data: initial value of the guest TD VCPU RCX
- hw_error: must be 0
KVM_TDX_INIT_MEM_REGION
153-182userspace `source_addr` data로 `gpa`부터 `nr_pages`개의 TD private memory를 초기화합니다. 호출 전 `[gpa, gpa + nr_pages]` range의 memory attribute를 `KVM_SET_MEMORY_ATTRIBUTES`로 private로 설정해야 합니다.
`KVM_TDX_MEASURE_MEMORY_REGION` flag를 주면 초기화와 함께 measurement를 확장합니다. 현재 정의된 flag는 이 bit 하나입니다.
초기 guest memory source와 target입니다.
KVM_TDX_INIT_MEM_REGION
-----------------------
:Type: vcpu ioctl
:Returns: 0 on success, <0 on error
Initialize @nr_pages TDX guest private memory starting from @gpa with userspace
provided data from @source_addr.
Note, before calling this sub command, memory attribute of the range
[gpa, gpa + nr_pages] needs to be private. Userspace can use
KVM_SET_MEMORY_ATTRIBUTES to set the attribute.
If KVM_TDX_MEASURE_MEMORY_REGION flag is specified, it also extends measurement.
- id: KVM_TDX_INIT_MEM_REGION
- flags: currently only KVM_TDX_MEASURE_MEMORY_REGION is defined
- data: pointer to struct kvm_tdx_init_mem_region
- hw_error: must be 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
183-195초기 TD content의 measurement를 완료하고 실행 가능 상태로 표시합니다. VM ioctl이며 flags, data, hw_error는 모두 0이어야 합니다.
KVM_TDX_FINALIZE_VM
-------------------
:Type: vm ioctl
:Returns: 0 on success, <0 on error
Complete measurement of the initial TD contents and mark it ready to run.
- id: KVM_TDX_FINALIZE_VM
- flags: must be 0
- data: must be 0
- hw_error: must be 0
KVM_TDX_GET_CPUID
196-229TDX module이 TD guest에 직접 가상화하는 CPUID 값을 조회합니다. `-E2BIG`이면 userspace는 `struct kvm_cpuid2.nent`에 갱신된 최소 크기에 맞춰 더 큰 buffer를 할당하고 재시도해야 합니다.
가변 길이 entry 배열입니다.
KVM_TDX_GET_CPUID
-----------------
:Type: vcpu ioctl
:Returns: 0 on success, <0 on error
Get the CPUID values that the TDX module virtualizes for the TD guest.
When it returns -E2BIG, the user space should allocate a larger buffer and
retry. The minimum buffer size is updated in the nent field of the
struct kvm_cpuid2.
- id: KVM_TDX_GET_CPUID
- flags: must be 0
- data: pointer to struct kvm_cpuid2 (in/out)
- hw_error: must be 0 (out)
::
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];
};
TDX VM 생성 흐름
230-264표준 KVM 흐름에 TDX ioctl을 삽입하는 순서입니다.
TDX는 자체 최대 vCPU 제한이 있으므로 VM level에서 `KVM_CHECK_EXTENSION(KVM_CAP_MAX_VCPUS)`를 확인합니다. host와 다른 TSC frequency가 필요할 때만 `KVM_SET_TSC_KHZ`를 선택적으로 사용합니다.
KVM TDX creation flow
=====================
In addition to the standard KVM flow, new TDX ioctls need to be called. The
control flow is as follows:
#. Check system wide capability
* KVM_CAP_VM_TYPES: Check if VM type is supported and if KVM_X86_TDX_VM
is supported.
#. Create VM
* KVM_CREATE_VM
* KVM_TDX_CAPABILITIES: Query TDX capabilities for creating TDX guests.
* KVM_CHECK_EXTENSION(KVM_CAP_MAX_VCPUS): Query maximum VCPUs the TD can
support at VM level (TDX has its own limitation on this).
* KVM_SET_TSC_KHZ: Configure TD's TSC frequency if a different TSC frequency
than host is desired. This is Optional.
* KVM_TDX_INIT_VM: Pass TDX specific VM parameters.
#. Create VCPU
* KVM_CREATE_VCPU
* KVM_TDX_INIT_VCPU: Pass TDX specific VCPU parameters.
* KVM_SET_CPUID2: Configure TD's CPUIDs.
* KVM_SET_MSRS: Configure TD's MSRs.
#. Initialize initial guest memory
* Prepare content of initial guest memory.
* KVM_TDX_INIT_MEM_REGION: Add initial guest memory.
* KVM_TDX_FINALIZE_VM: Finalize the measurement of the TDX guest.
#. Run VCPU
참고 자료
265-268Intel Trust Domain Extensions 개발 문서에서 whitepaper, specification과 추가 resource를 확인할 수 있습니다.
References
==========
https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/documentation.html
요약·해설
intel-tdx.rst:1-268Intel TDX KVM sub-ioctl ABI와 private memory measurement를 포함한 TD 생성 흐름입니다.
레지스터, 비트 필드, 구조체와 호출 순서를 원문 표기 및 줄 좌표와 함께 보존했습니다.