xref: /linux/Documentation/virt/kvm/x86/amd-memory-encryption.rst (revision ae22a94997b8a03dcb3c922857c203246711f9d4)
1.. SPDX-License-Identifier: GPL-2.0
2
3======================================
4Secure Encrypted Virtualization (SEV)
5======================================
6
7Overview
8========
9
10Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
11
12SEV is an extension to the AMD-V architecture which supports running
13virtual machines (VMs) under the control of a hypervisor. When enabled,
14the memory contents of a VM will be transparently encrypted with a key
15unique to that VM.
16
17The hypervisor can determine the SEV support through the CPUID
18instruction. The CPUID function 0x8000001f reports information related
19to SEV::
20
21	0x8000001f[eax]:
22			Bit[1] 	indicates support for SEV
23	    ...
24		  [ecx]:
25			Bits[31:0]  Number of encrypted guests supported simultaneously
26
27If support for SEV is present, MSR 0xc001_0010 (MSR_AMD64_SYSCFG) and MSR 0xc001_0015
28(MSR_K7_HWCR) can be used to determine if it can be enabled::
29
30	0xc001_0010:
31		Bit[23]	   1 = memory encryption can be enabled
32			   0 = memory encryption can not be enabled
33
34	0xc001_0015:
35		Bit[0]	   1 = memory encryption can be enabled
36			   0 = memory encryption can not be enabled
37
38When SEV support is available, it can be enabled in a specific VM by
39setting the SEV bit before executing VMRUN.::
40
41	VMCB[0x90]:
42		Bit[1]	    1 = SEV is enabled
43			    0 = SEV is disabled
44
45SEV hardware uses ASIDs to associate a memory encryption key with a VM.
46Hence, the ASID for the SEV-enabled guests must be from 1 to a maximum value
47defined in the CPUID 0x8000001f[ecx] field.
48
49SEV Key Management
50==================
51
52The SEV guest key management is handled by a separate processor called the AMD
53Secure Processor (AMD-SP). Firmware running inside the AMD-SP provides a secure
54key management interface to perform common hypervisor activities such as
55encrypting bootstrap code, snapshot, migrating and debugging the guest. For more
56information, see the SEV Key Management spec [api-spec]_
57
58The main ioctl to access SEV is KVM_MEMORY_ENCRYPT_OP.  If the argument
59to KVM_MEMORY_ENCRYPT_OP is NULL, the ioctl returns 0 if SEV is enabled
60and ``ENOTTY`` if it is disabled (on some older versions of Linux,
61the ioctl runs normally even with a NULL argument, and therefore will
62likely return ``EFAULT``).  If non-NULL, the argument to KVM_MEMORY_ENCRYPT_OP
63must be a struct kvm_sev_cmd::
64
65       struct kvm_sev_cmd {
66               __u32 id;
67               __u64 data;
68               __u32 error;
69               __u32 sev_fd;
70       };
71
72
73The ``id`` field contains the subcommand, and the ``data`` field points to
74another struct containing arguments specific to command.  The ``sev_fd``
75should point to a file descriptor that is opened on the ``/dev/sev``
76device, if needed (see individual commands).
77
78On output, ``error`` is zero on success, or an error code.  Error codes
79are defined in ``<linux/psp-dev.h>``.
80
81KVM implements the following commands to support common lifecycle events of SEV
82guests, such as launching, running, snapshotting, migrating and decommissioning.
83
841. KVM_SEV_INIT
85---------------
86
87The KVM_SEV_INIT command is used by the hypervisor to initialize the SEV platform
88context. In a typical workflow, this command should be the first command issued.
89
90The firmware can be initialized either by using its own non-volatile storage or
91the OS can manage the NV storage for the firmware using the module parameter
92``init_ex_path``. If the file specified by ``init_ex_path`` does not exist or
93is invalid, the OS will create or override the file with output from PSP.
94
95Returns: 0 on success, -negative on error
96
972. KVM_SEV_LAUNCH_START
98-----------------------
99
100The KVM_SEV_LAUNCH_START command is used for creating the memory encryption
101context. To create the encryption context, user must provide a guest policy,
102the owner's public Diffie-Hellman (PDH) key and session information.
103
104Parameters: struct  kvm_sev_launch_start (in/out)
105
106Returns: 0 on success, -negative on error
107
108::
109
110        struct kvm_sev_launch_start {
111                __u32 handle;           /* if zero then firmware creates a new handle */
112                __u32 policy;           /* guest's policy */
113
114                __u64 dh_uaddr;         /* userspace address pointing to the guest owner's PDH key */
115                __u32 dh_len;
116
117                __u64 session_addr;     /* userspace address which points to the guest session information */
118                __u32 session_len;
119        };
120
121On success, the 'handle' field contains a new handle and on error, a negative value.
122
123KVM_SEV_LAUNCH_START requires the ``sev_fd`` field to be valid.
124
125For more details, see SEV spec Section 6.2.
126
1273. KVM_SEV_LAUNCH_UPDATE_DATA
128-----------------------------
129
130The KVM_SEV_LAUNCH_UPDATE_DATA is used for encrypting a memory region. It also
131calculates a measurement of the memory contents. The measurement is a signature
132of the memory contents that can be sent to the guest owner as an attestation
133that the memory was encrypted correctly by the firmware.
134
135Parameters (in): struct  kvm_sev_launch_update_data
136
137Returns: 0 on success, -negative on error
138
139::
140
141        struct kvm_sev_launch_update {
142                __u64 uaddr;    /* userspace address to be encrypted (must be 16-byte aligned) */
143                __u32 len;      /* length of the data to be encrypted (must be 16-byte aligned) */
144        };
145
146For more details, see SEV spec Section 6.3.
147
1484. KVM_SEV_LAUNCH_MEASURE
149-------------------------
150
151The KVM_SEV_LAUNCH_MEASURE command is used to retrieve the measurement of the
152data encrypted by the KVM_SEV_LAUNCH_UPDATE_DATA command. The guest owner may
153wait to provide the guest with confidential information until it can verify the
154measurement. Since the guest owner knows the initial contents of the guest at
155boot, the measurement can be verified by comparing it to what the guest owner
156expects.
157
158If len is zero on entry, the measurement blob length is written to len and
159uaddr is unused.
160
161Parameters (in): struct  kvm_sev_launch_measure
162
163Returns: 0 on success, -negative on error
164
165::
166
167        struct kvm_sev_launch_measure {
168                __u64 uaddr;    /* where to copy the measurement */
169                __u32 len;      /* length of measurement blob */
170        };
171
172For more details on the measurement verification flow, see SEV spec Section 6.4.
173
1745. KVM_SEV_LAUNCH_FINISH
175------------------------
176
177After completion of the launch flow, the KVM_SEV_LAUNCH_FINISH command can be
178issued to make the guest ready for the execution.
179
180Returns: 0 on success, -negative on error
181
1826. KVM_SEV_GUEST_STATUS
183-----------------------
184
185The KVM_SEV_GUEST_STATUS command is used to retrieve status information about a
186SEV-enabled guest.
187
188Parameters (out): struct kvm_sev_guest_status
189
190Returns: 0 on success, -negative on error
191
192::
193
194        struct kvm_sev_guest_status {
195                __u32 handle;   /* guest handle */
196                __u32 policy;   /* guest policy */
197                __u8 state;     /* guest state (see enum below) */
198        };
199
200SEV guest state:
201
202::
203
204        enum {
205        SEV_STATE_INVALID = 0;
206        SEV_STATE_LAUNCHING,    /* guest is currently being launched */
207        SEV_STATE_SECRET,       /* guest is being launched and ready to accept the ciphertext data */
208        SEV_STATE_RUNNING,      /* guest is fully launched and running */
209        SEV_STATE_RECEIVING,    /* guest is being migrated in from another SEV machine */
210        SEV_STATE_SENDING       /* guest is getting migrated out to another SEV machine */
211        };
212
2137. KVM_SEV_DBG_DECRYPT
214----------------------
215
216The KVM_SEV_DEBUG_DECRYPT command can be used by the hypervisor to request the
217firmware to decrypt the data at the given memory region.
218
219Parameters (in): struct kvm_sev_dbg
220
221Returns: 0 on success, -negative on error
222
223::
224
225        struct kvm_sev_dbg {
226                __u64 src_uaddr;        /* userspace address of data to decrypt */
227                __u64 dst_uaddr;        /* userspace address of destination */
228                __u32 len;              /* length of memory region to decrypt */
229        };
230
231The command returns an error if the guest policy does not allow debugging.
232
2338. KVM_SEV_DBG_ENCRYPT
234----------------------
235
236The KVM_SEV_DEBUG_ENCRYPT command can be used by the hypervisor to request the
237firmware to encrypt the data at the given memory region.
238
239Parameters (in): struct kvm_sev_dbg
240
241Returns: 0 on success, -negative on error
242
243::
244
245        struct kvm_sev_dbg {
246                __u64 src_uaddr;        /* userspace address of data to encrypt */
247                __u64 dst_uaddr;        /* userspace address of destination */
248                __u32 len;              /* length of memory region to encrypt */
249        };
250
251The command returns an error if the guest policy does not allow debugging.
252
2539. KVM_SEV_LAUNCH_SECRET
254------------------------
255
256The KVM_SEV_LAUNCH_SECRET command can be used by the hypervisor to inject secret
257data after the measurement has been validated by the guest owner.
258
259Parameters (in): struct kvm_sev_launch_secret
260
261Returns: 0 on success, -negative on error
262
263::
264
265        struct kvm_sev_launch_secret {
266                __u64 hdr_uaddr;        /* userspace address containing the packet header */
267                __u32 hdr_len;
268
269                __u64 guest_uaddr;      /* the guest memory region where the secret should be injected */
270                __u32 guest_len;
271
272                __u64 trans_uaddr;      /* the hypervisor memory region which contains the secret */
273                __u32 trans_len;
274        };
275
27610. KVM_SEV_GET_ATTESTATION_REPORT
277----------------------------------
278
279The KVM_SEV_GET_ATTESTATION_REPORT command can be used by the hypervisor to query the attestation
280report containing the SHA-256 digest of the guest memory and VMSA passed through the KVM_SEV_LAUNCH
281commands and signed with the PEK. The digest returned by the command should match the digest
282used by the guest owner with the KVM_SEV_LAUNCH_MEASURE.
283
284If len is zero on entry, the measurement blob length is written to len and
285uaddr is unused.
286
287Parameters (in): struct kvm_sev_attestation
288
289Returns: 0 on success, -negative on error
290
291::
292
293        struct kvm_sev_attestation_report {
294                __u8 mnonce[16];        /* A random mnonce that will be placed in the report */
295
296                __u64 uaddr;            /* userspace address where the report should be copied */
297                __u32 len;
298        };
299
30011. KVM_SEV_SEND_START
301----------------------
302
303The KVM_SEV_SEND_START command can be used by the hypervisor to create an
304outgoing guest encryption context.
305
306If session_len is zero on entry, the length of the guest session information is
307written to session_len and all other fields are not used.
308
309Parameters (in): struct kvm_sev_send_start
310
311Returns: 0 on success, -negative on error
312
313::
314
315        struct kvm_sev_send_start {
316                __u32 policy;                 /* guest policy */
317
318                __u64 pdh_cert_uaddr;         /* platform Diffie-Hellman certificate */
319                __u32 pdh_cert_len;
320
321                __u64 plat_certs_uaddr;        /* platform certificate chain */
322                __u32 plat_certs_len;
323
324                __u64 amd_certs_uaddr;        /* AMD certificate */
325                __u32 amd_certs_len;
326
327                __u64 session_uaddr;          /* Guest session information */
328                __u32 session_len;
329        };
330
33112. KVM_SEV_SEND_UPDATE_DATA
332----------------------------
333
334The KVM_SEV_SEND_UPDATE_DATA command can be used by the hypervisor to encrypt the
335outgoing guest memory region with the encryption context creating using
336KVM_SEV_SEND_START.
337
338If hdr_len or trans_len are zero on entry, the length of the packet header and
339transport region are written to hdr_len and trans_len respectively, and all
340other fields are not used.
341
342Parameters (in): struct kvm_sev_send_update_data
343
344Returns: 0 on success, -negative on error
345
346::
347
348        struct kvm_sev_launch_send_update_data {
349                __u64 hdr_uaddr;        /* userspace address containing the packet header */
350                __u32 hdr_len;
351
352                __u64 guest_uaddr;      /* the source memory region to be encrypted */
353                __u32 guest_len;
354
355                __u64 trans_uaddr;      /* the destination memory region  */
356                __u32 trans_len;
357        };
358
35913. KVM_SEV_SEND_FINISH
360------------------------
361
362After completion of the migration flow, the KVM_SEV_SEND_FINISH command can be
363issued by the hypervisor to delete the encryption context.
364
365Returns: 0 on success, -negative on error
366
36714. KVM_SEV_SEND_CANCEL
368------------------------
369
370After completion of SEND_START, but before SEND_FINISH, the source VMM can issue the
371SEND_CANCEL command to stop a migration. This is necessary so that a cancelled
372migration can restart with a new target later.
373
374Returns: 0 on success, -negative on error
375
37615. KVM_SEV_RECEIVE_START
377-------------------------
378
379The KVM_SEV_RECEIVE_START command is used for creating the memory encryption
380context for an incoming SEV guest. To create the encryption context, the user must
381provide a guest policy, the platform public Diffie-Hellman (PDH) key and session
382information.
383
384Parameters: struct  kvm_sev_receive_start (in/out)
385
386Returns: 0 on success, -negative on error
387
388::
389
390        struct kvm_sev_receive_start {
391                __u32 handle;           /* if zero then firmware creates a new handle */
392                __u32 policy;           /* guest's policy */
393
394                __u64 pdh_uaddr;        /* userspace address pointing to the PDH key */
395                __u32 pdh_len;
396
397                __u64 session_uaddr;    /* userspace address which points to the guest session information */
398                __u32 session_len;
399        };
400
401On success, the 'handle' field contains a new handle and on error, a negative value.
402
403For more details, see SEV spec Section 6.12.
404
40516. KVM_SEV_RECEIVE_UPDATE_DATA
406-------------------------------
407
408The KVM_SEV_RECEIVE_UPDATE_DATA command can be used by the hypervisor to copy
409the incoming buffers into the guest memory region with encryption context
410created during the KVM_SEV_RECEIVE_START.
411
412Parameters (in): struct kvm_sev_receive_update_data
413
414Returns: 0 on success, -negative on error
415
416::
417
418        struct kvm_sev_launch_receive_update_data {
419                __u64 hdr_uaddr;        /* userspace address containing the packet header */
420                __u32 hdr_len;
421
422                __u64 guest_uaddr;      /* the destination guest memory region */
423                __u32 guest_len;
424
425                __u64 trans_uaddr;      /* the incoming buffer memory region  */
426                __u32 trans_len;
427        };
428
42917. KVM_SEV_RECEIVE_FINISH
430--------------------------
431
432After completion of the migration flow, the KVM_SEV_RECEIVE_FINISH command can be
433issued by the hypervisor to make the guest ready for execution.
434
435Returns: 0 on success, -negative on error
436
437References
438==========
439
440
441See [white-paper]_, [api-spec]_, [amd-apm]_ and [kvm-forum]_ for more info.
442
443.. [white-paper] https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
444.. [api-spec] https://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf
445.. [amd-apm] https://support.amd.com/TechDocs/24593.pdf (section 15.34)
446.. [kvm-forum]  https://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
447