1.. SPDX-License-Identifier: GPL-2.0
2
3===================================
4Intel Trust Domain Extensions (TDX)
5===================================
6
7Overview
8========
9Intel's Trust Domain Extensions (TDX) protect confidential guest VMs from the
10host and physical attacks.  A CPU-attested software module called 'the TDX
11module' runs inside a new CPU isolated range to provide the functionalities to
12manage and run protected VMs, a.k.a, TDX guests or TDs.
13
14Please refer to [1] for the whitepaper, specifications and other resources.
15
16This documentation describes TDX-specific KVM ABIs.  The TDX module needs to be
17initialized before it can be used by KVM to run any TDX guests.  The host
18core-kernel provides the support of initializing the TDX module, which is
19described in the Documentation/arch/x86/tdx.rst.
20
21API description
22===============
23
24KVM_MEMORY_ENCRYPT_OP
25---------------------
26:Type: vm ioctl, vcpu ioctl
27
28For TDX operations, KVM_MEMORY_ENCRYPT_OP is re-purposed to be generic
29ioctl with TDX specific sub-ioctl() commands.
30
31::
32
33  /* Trust Domain Extensions sub-ioctl() commands. */
34  enum kvm_tdx_cmd_id {
35          KVM_TDX_CAPABILITIES = 0,
36          KVM_TDX_INIT_VM,
37          KVM_TDX_INIT_VCPU,
38          KVM_TDX_INIT_MEM_REGION,
39          KVM_TDX_FINALIZE_VM,
40          KVM_TDX_GET_CPUID,
41
42          KVM_TDX_CMD_NR_MAX,
43  };
44
45  struct kvm_tdx_cmd {
46        /* enum kvm_tdx_cmd_id */
47        __u32 id;
48        /* flags for sub-command. If sub-command doesn't use this, set zero. */
49        __u32 flags;
50        /*
51         * data for each sub-command. An immediate or a pointer to the actual
52         * data in process virtual address.  If sub-command doesn't use it,
53         * set zero.
54         */
55        __u64 data;
56        /*
57         * Auxiliary error code.  The sub-command may return TDX SEAMCALL
58         * status code in addition to -Exxx.
59         */
60        __u64 hw_error;
61  };
62
63KVM_TDX_CAPABILITIES
64--------------------
65:Type: vm ioctl
66:Returns: 0 on success, <0 on error
67
68Return the TDX capabilities that current KVM supports with the specific TDX
69module loaded in the system.  It reports what features/capabilities are allowed
70to be configured to the TDX guest.
71
72- id: KVM_TDX_CAPABILITIES
73- flags: must be 0
74- data: pointer to struct kvm_tdx_capabilities
75- hw_error: must be 0
76
77::
78
79  struct kvm_tdx_capabilities {
80        __u64 supported_attrs;
81        __u64 supported_xfam;
82        __u64 reserved[254];
83
84        /* Configurable CPUID bits for userspace */
85        struct kvm_cpuid2 cpuid;
86  };
87
88
89KVM_TDX_INIT_VM
90---------------
91:Type: vm ioctl
92:Returns: 0 on success, <0 on error
93
94Perform TDX specific VM initialization.  This needs to be called after
95KVM_CREATE_VM and before creating any VCPUs.
96
97- id: KVM_TDX_INIT_VM
98- flags: must be 0
99- data: pointer to struct kvm_tdx_init_vm
100- hw_error: must be 0
101
102::
103
104  struct kvm_tdx_init_vm {
105          __u64 attributes;
106          __u64 xfam;
107          __u64 mrconfigid[6];          /* sha384 digest */
108          __u64 mrowner[6];             /* sha384 digest */
109          __u64 mrownerconfig[6];       /* sha384 digest */
110
111          /* The total space for TD_PARAMS before the CPUIDs is 256 bytes */
112          __u64 reserved[12];
113
114        /*
115         * Call KVM_TDX_INIT_VM before vcpu creation, thus before
116         * KVM_SET_CPUID2.
117         * This configuration supersedes KVM_SET_CPUID2s for VCPUs because the
118         * TDX module directly virtualizes those CPUIDs without VMM.  The user
119         * space VMM, e.g. qemu, should make KVM_SET_CPUID2 consistent with
120         * those values.  If it doesn't, KVM may have wrong idea of vCPUIDs of
121         * the guest, and KVM may wrongly emulate CPUIDs or MSRs that the TDX
122         * module doesn't virtualize.
123         */
124          struct kvm_cpuid2 cpuid;
125  };
126
127
128KVM_TDX_INIT_VCPU
129-----------------
130:Type: vcpu ioctl
131:Returns: 0 on success, <0 on error
132
133Perform TDX specific VCPU initialization.
134
135- id: KVM_TDX_INIT_VCPU
136- flags: must be 0
137- data: initial value of the guest TD VCPU RCX
138- hw_error: must be 0
139
140KVM_TDX_INIT_MEM_REGION
141-----------------------
142:Type: vcpu ioctl
143:Returns: 0 on success, <0 on error
144
145Initialize @nr_pages TDX guest private memory starting from @gpa with userspace
146provided data from @source_addr.
147
148Note, before calling this sub command, memory attribute of the range
149[gpa, gpa + nr_pages] needs to be private.  Userspace can use
150KVM_SET_MEMORY_ATTRIBUTES to set the attribute.
151
152If KVM_TDX_MEASURE_MEMORY_REGION flag is specified, it also extends measurement.
153
154- id: KVM_TDX_INIT_MEM_REGION
155- flags: currently only KVM_TDX_MEASURE_MEMORY_REGION is defined
156- data: pointer to struct kvm_tdx_init_mem_region
157- hw_error: must be 0
158
159::
160
161  #define KVM_TDX_MEASURE_MEMORY_REGION   (1UL << 0)
162
163  struct kvm_tdx_init_mem_region {
164          __u64 source_addr;
165          __u64 gpa;
166          __u64 nr_pages;
167  };
168
169
170KVM_TDX_FINALIZE_VM
171-------------------
172:Type: vm ioctl
173:Returns: 0 on success, <0 on error
174
175Complete measurement of the initial TD contents and mark it ready to run.
176
177- id: KVM_TDX_FINALIZE_VM
178- flags: must be 0
179- data: must be 0
180- hw_error: must be 0
181
182
183KVM_TDX_GET_CPUID
184-----------------
185:Type: vcpu ioctl
186:Returns: 0 on success, <0 on error
187
188Get the CPUID values that the TDX module virtualizes for the TD guest.
189When it returns -E2BIG, the user space should allocate a larger buffer and
190retry. The minimum buffer size is updated in the nent field of the
191struct kvm_cpuid2.
192
193- id: KVM_TDX_GET_CPUID
194- flags: must be 0
195- data: pointer to struct kvm_cpuid2 (in/out)
196- hw_error: must be 0 (out)
197
198::
199
200  struct kvm_cpuid2 {
201	  __u32 nent;
202	  __u32 padding;
203	  struct kvm_cpuid_entry2 entries[0];
204  };
205
206  struct kvm_cpuid_entry2 {
207	  __u32 function;
208	  __u32 index;
209	  __u32 flags;
210	  __u32 eax;
211	  __u32 ebx;
212	  __u32 ecx;
213	  __u32 edx;
214	  __u32 padding[3];
215  };
216
217KVM TDX creation flow
218=====================
219In addition to the standard KVM flow, new TDX ioctls need to be called.  The
220control flow is as follows:
221
222#. Check system wide capability
223
224   * KVM_CAP_VM_TYPES: Check if VM type is supported and if KVM_X86_TDX_VM
225     is supported.
226
227#. Create VM
228
229   * KVM_CREATE_VM
230   * KVM_TDX_CAPABILITIES: Query TDX capabilities for creating TDX guests.
231   * KVM_CHECK_EXTENSION(KVM_CAP_MAX_VCPUS): Query maximum VCPUs the TD can
232     support at VM level (TDX has its own limitation on this).
233   * KVM_SET_TSC_KHZ: Configure TD's TSC frequency if a different TSC frequency
234     than host is desired.  This is Optional.
235   * KVM_TDX_INIT_VM: Pass TDX specific VM parameters.
236
237#. Create VCPU
238
239   * KVM_CREATE_VCPU
240   * KVM_TDX_INIT_VCPU: Pass TDX specific VCPU parameters.
241   * KVM_SET_CPUID2: Configure TD's CPUIDs.
242   * KVM_SET_MSRS: Configure TD's MSRs.
243
244#. Initialize initial guest memory
245
246   * Prepare content of initial guest memory.
247   * KVM_TDX_INIT_MEM_REGION: Add initial guest memory.
248   * KVM_TDX_FINALIZE_VM: Finalize the measurement of the TDX guest.
249
250#. Run VCPU
251
252References
253==========
254
255https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/documentation.html
256