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