xref: /openbmc/qemu/target/i386/sev.c (revision aacdb844)
1 /*
2  * QEMU SEV support
3  *
4  * Copyright Advanced Micro Devices 2016-2018
5  *
6  * Author:
7  *      Brijesh Singh <brijesh.singh@amd.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  *
12  */
13 
14 #include "qemu/osdep.h"
15 
16 #include <linux/kvm.h>
17 #include <linux/psp-sev.h>
18 
19 #include <sys/ioctl.h>
20 
21 #include "qapi/error.h"
22 #include "qom/object_interfaces.h"
23 #include "qemu/base64.h"
24 #include "qemu/module.h"
25 #include "sysemu/kvm.h"
26 #include "sev_i386.h"
27 #include "sysemu/sysemu.h"
28 #include "sysemu/runstate.h"
29 #include "trace.h"
30 #include "migration/blocker.h"
31 #include "qom/object.h"
32 #include "exec/address-spaces.h"
33 #include "monitor/monitor.h"
34 #include "exec/confidential-guest-support.h"
35 
36 #define TYPE_SEV_GUEST "sev-guest"
37 OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
38 
39 
40 /**
41  * SevGuestState:
42  *
43  * The SevGuestState object is used for creating and managing a SEV
44  * guest.
45  *
46  * # $QEMU \
47  *         -object sev-guest,id=sev0 \
48  *         -machine ...,memory-encryption=sev0
49  */
50 struct SevGuestState {
51     ConfidentialGuestSupport parent_obj;
52 
53     /* configuration parameters */
54     char *sev_device;
55     uint32_t policy;
56     char *dh_cert_file;
57     char *session_file;
58     uint32_t cbitpos;
59     uint32_t reduced_phys_bits;
60 
61     /* runtime state */
62     uint32_t handle;
63     uint8_t api_major;
64     uint8_t api_minor;
65     uint8_t build_id;
66     uint64_t me_mask;
67     int sev_fd;
68     SevState state;
69     gchar *measurement;
70 };
71 
72 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
73 #define DEFAULT_SEV_DEVICE      "/dev/sev"
74 
75 static SevGuestState *sev_guest;
76 static Error *sev_mig_blocker;
77 
78 static const char *const sev_fw_errlist[] = {
79     "",
80     "Platform state is invalid",
81     "Guest state is invalid",
82     "Platform configuration is invalid",
83     "Buffer too small",
84     "Platform is already owned",
85     "Certificate is invalid",
86     "Policy is not allowed",
87     "Guest is not active",
88     "Invalid address",
89     "Bad signature",
90     "Bad measurement",
91     "Asid is already owned",
92     "Invalid ASID",
93     "WBINVD is required",
94     "DF_FLUSH is required",
95     "Guest handle is invalid",
96     "Invalid command",
97     "Guest is active",
98     "Hardware error",
99     "Hardware unsafe",
100     "Feature not supported",
101     "Invalid parameter"
102 };
103 
104 #define SEV_FW_MAX_ERROR      ARRAY_SIZE(sev_fw_errlist)
105 
106 static int
107 sev_ioctl(int fd, int cmd, void *data, int *error)
108 {
109     int r;
110     struct kvm_sev_cmd input;
111 
112     memset(&input, 0x0, sizeof(input));
113 
114     input.id = cmd;
115     input.sev_fd = fd;
116     input.data = (__u64)(unsigned long)data;
117 
118     r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
119 
120     if (error) {
121         *error = input.error;
122     }
123 
124     return r;
125 }
126 
127 static int
128 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
129 {
130     int r;
131     struct sev_issue_cmd arg;
132 
133     arg.cmd = cmd;
134     arg.data = (unsigned long)data;
135     r = ioctl(fd, SEV_ISSUE_CMD, &arg);
136     if (error) {
137         *error = arg.error;
138     }
139 
140     return r;
141 }
142 
143 static const char *
144 fw_error_to_str(int code)
145 {
146     if (code < 0 || code >= SEV_FW_MAX_ERROR) {
147         return "unknown error";
148     }
149 
150     return sev_fw_errlist[code];
151 }
152 
153 static bool
154 sev_check_state(const SevGuestState *sev, SevState state)
155 {
156     assert(sev);
157     return sev->state == state ? true : false;
158 }
159 
160 static void
161 sev_set_guest_state(SevGuestState *sev, SevState new_state)
162 {
163     assert(new_state < SEV_STATE__MAX);
164     assert(sev);
165 
166     trace_kvm_sev_change_state(SevState_str(sev->state),
167                                SevState_str(new_state));
168     sev->state = new_state;
169 }
170 
171 static void
172 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
173 {
174     int r;
175     struct kvm_enc_region range;
176     ram_addr_t offset;
177     MemoryRegion *mr;
178 
179     /*
180      * The RAM device presents a memory region that should be treated
181      * as IO region and should not be pinned.
182      */
183     mr = memory_region_from_host(host, &offset);
184     if (mr && memory_region_is_ram_device(mr)) {
185         return;
186     }
187 
188     range.addr = (__u64)(unsigned long)host;
189     range.size = size;
190 
191     trace_kvm_memcrypt_register_region(host, size);
192     r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
193     if (r) {
194         error_report("%s: failed to register region (%p+%#zx) error '%s'",
195                      __func__, host, size, strerror(errno));
196         exit(1);
197     }
198 }
199 
200 static void
201 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
202 {
203     int r;
204     struct kvm_enc_region range;
205     ram_addr_t offset;
206     MemoryRegion *mr;
207 
208     /*
209      * The RAM device presents a memory region that should be treated
210      * as IO region and should not have been pinned.
211      */
212     mr = memory_region_from_host(host, &offset);
213     if (mr && memory_region_is_ram_device(mr)) {
214         return;
215     }
216 
217     range.addr = (__u64)(unsigned long)host;
218     range.size = size;
219 
220     trace_kvm_memcrypt_unregister_region(host, size);
221     r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
222     if (r) {
223         error_report("%s: failed to unregister region (%p+%#zx)",
224                      __func__, host, size);
225     }
226 }
227 
228 static struct RAMBlockNotifier sev_ram_notifier = {
229     .ram_block_added = sev_ram_block_added,
230     .ram_block_removed = sev_ram_block_removed,
231 };
232 
233 static void
234 sev_guest_finalize(Object *obj)
235 {
236 }
237 
238 static char *
239 sev_guest_get_session_file(Object *obj, Error **errp)
240 {
241     SevGuestState *s = SEV_GUEST(obj);
242 
243     return s->session_file ? g_strdup(s->session_file) : NULL;
244 }
245 
246 static void
247 sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
248 {
249     SevGuestState *s = SEV_GUEST(obj);
250 
251     s->session_file = g_strdup(value);
252 }
253 
254 static char *
255 sev_guest_get_dh_cert_file(Object *obj, Error **errp)
256 {
257     SevGuestState *s = SEV_GUEST(obj);
258 
259     return g_strdup(s->dh_cert_file);
260 }
261 
262 static void
263 sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
264 {
265     SevGuestState *s = SEV_GUEST(obj);
266 
267     s->dh_cert_file = g_strdup(value);
268 }
269 
270 static char *
271 sev_guest_get_sev_device(Object *obj, Error **errp)
272 {
273     SevGuestState *sev = SEV_GUEST(obj);
274 
275     return g_strdup(sev->sev_device);
276 }
277 
278 static void
279 sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
280 {
281     SevGuestState *sev = SEV_GUEST(obj);
282 
283     sev->sev_device = g_strdup(value);
284 }
285 
286 static void
287 sev_guest_class_init(ObjectClass *oc, void *data)
288 {
289     object_class_property_add_str(oc, "sev-device",
290                                   sev_guest_get_sev_device,
291                                   sev_guest_set_sev_device);
292     object_class_property_set_description(oc, "sev-device",
293             "SEV device to use");
294     object_class_property_add_str(oc, "dh-cert-file",
295                                   sev_guest_get_dh_cert_file,
296                                   sev_guest_set_dh_cert_file);
297     object_class_property_set_description(oc, "dh-cert-file",
298             "guest owners DH certificate (encoded with base64)");
299     object_class_property_add_str(oc, "session-file",
300                                   sev_guest_get_session_file,
301                                   sev_guest_set_session_file);
302     object_class_property_set_description(oc, "session-file",
303             "guest owners session parameters (encoded with base64)");
304 }
305 
306 static void
307 sev_guest_instance_init(Object *obj)
308 {
309     SevGuestState *sev = SEV_GUEST(obj);
310 
311     sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
312     sev->policy = DEFAULT_GUEST_POLICY;
313     object_property_add_uint32_ptr(obj, "policy", &sev->policy,
314                                    OBJ_PROP_FLAG_READWRITE);
315     object_property_add_uint32_ptr(obj, "handle", &sev->handle,
316                                    OBJ_PROP_FLAG_READWRITE);
317     object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
318                                    OBJ_PROP_FLAG_READWRITE);
319     object_property_add_uint32_ptr(obj, "reduced-phys-bits",
320                                    &sev->reduced_phys_bits,
321                                    OBJ_PROP_FLAG_READWRITE);
322 }
323 
324 /* sev guest info */
325 static const TypeInfo sev_guest_info = {
326     .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
327     .name = TYPE_SEV_GUEST,
328     .instance_size = sizeof(SevGuestState),
329     .instance_finalize = sev_guest_finalize,
330     .class_init = sev_guest_class_init,
331     .instance_init = sev_guest_instance_init,
332     .interfaces = (InterfaceInfo[]) {
333         { TYPE_USER_CREATABLE },
334         { }
335     }
336 };
337 
338 static SevGuestState *
339 lookup_sev_guest_info(const char *id)
340 {
341     Object *obj;
342     SevGuestState *info;
343 
344     obj = object_resolve_path_component(object_get_objects_root(), id);
345     if (!obj) {
346         return NULL;
347     }
348 
349     info = (SevGuestState *)
350             object_dynamic_cast(obj, TYPE_SEV_GUEST);
351     if (!info) {
352         return NULL;
353     }
354 
355     return info;
356 }
357 
358 bool
359 sev_enabled(void)
360 {
361     return !!sev_guest;
362 }
363 
364 uint64_t
365 sev_get_me_mask(void)
366 {
367     return sev_guest ? sev_guest->me_mask : ~0;
368 }
369 
370 uint32_t
371 sev_get_cbit_position(void)
372 {
373     return sev_guest ? sev_guest->cbitpos : 0;
374 }
375 
376 uint32_t
377 sev_get_reduced_phys_bits(void)
378 {
379     return sev_guest ? sev_guest->reduced_phys_bits : 0;
380 }
381 
382 SevInfo *
383 sev_get_info(void)
384 {
385     SevInfo *info;
386 
387     info = g_new0(SevInfo, 1);
388     info->enabled = sev_enabled();
389 
390     if (info->enabled) {
391         info->api_major = sev_guest->api_major;
392         info->api_minor = sev_guest->api_minor;
393         info->build_id = sev_guest->build_id;
394         info->policy = sev_guest->policy;
395         info->state = sev_guest->state;
396         info->handle = sev_guest->handle;
397     }
398 
399     return info;
400 }
401 
402 static int
403 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
404                  size_t *cert_chain_len, Error **errp)
405 {
406     guchar *pdh_data = NULL;
407     guchar *cert_chain_data = NULL;
408     struct sev_user_data_pdh_cert_export export = {};
409     int err, r;
410 
411     /* query the certificate length */
412     r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
413     if (r < 0) {
414         if (err != SEV_RET_INVALID_LEN) {
415             error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
416                        r, err, fw_error_to_str(err));
417             return 1;
418         }
419     }
420 
421     pdh_data = g_new(guchar, export.pdh_cert_len);
422     cert_chain_data = g_new(guchar, export.cert_chain_len);
423     export.pdh_cert_address = (unsigned long)pdh_data;
424     export.cert_chain_address = (unsigned long)cert_chain_data;
425 
426     r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
427     if (r < 0) {
428         error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
429                    r, err, fw_error_to_str(err));
430         goto e_free;
431     }
432 
433     *pdh = pdh_data;
434     *pdh_len = export.pdh_cert_len;
435     *cert_chain = cert_chain_data;
436     *cert_chain_len = export.cert_chain_len;
437     return 0;
438 
439 e_free:
440     g_free(pdh_data);
441     g_free(cert_chain_data);
442     return 1;
443 }
444 
445 SevCapability *
446 sev_get_capabilities(Error **errp)
447 {
448     SevCapability *cap = NULL;
449     guchar *pdh_data = NULL;
450     guchar *cert_chain_data = NULL;
451     size_t pdh_len = 0, cert_chain_len = 0;
452     uint32_t ebx;
453     int fd;
454 
455     if (!kvm_enabled()) {
456         error_setg(errp, "KVM not enabled");
457         return NULL;
458     }
459     if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
460         error_setg(errp, "SEV is not enabled in KVM");
461         return NULL;
462     }
463 
464     fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
465     if (fd < 0) {
466         error_setg_errno(errp, errno, "Failed to open %s",
467                          DEFAULT_SEV_DEVICE);
468         return NULL;
469     }
470 
471     if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
472                          &cert_chain_data, &cert_chain_len, errp)) {
473         goto out;
474     }
475 
476     cap = g_new0(SevCapability, 1);
477     cap->pdh = g_base64_encode(pdh_data, pdh_len);
478     cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
479 
480     host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
481     cap->cbitpos = ebx & 0x3f;
482 
483     /*
484      * When SEV feature is enabled, we loose one bit in guest physical
485      * addressing.
486      */
487     cap->reduced_phys_bits = 1;
488 
489 out:
490     g_free(pdh_data);
491     g_free(cert_chain_data);
492     close(fd);
493     return cap;
494 }
495 
496 static int
497 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
498 {
499     gsize sz;
500     gchar *base64;
501     GError *error = NULL;
502 
503     if (!g_file_get_contents(filename, &base64, &sz, &error)) {
504         error_report("failed to read '%s' (%s)", filename, error->message);
505         g_error_free(error);
506         return -1;
507     }
508 
509     *data = g_base64_decode(base64, len);
510     return 0;
511 }
512 
513 static int
514 sev_launch_start(SevGuestState *sev)
515 {
516     gsize sz;
517     int ret = 1;
518     int fw_error, rc;
519     struct kvm_sev_launch_start *start;
520     guchar *session = NULL, *dh_cert = NULL;
521 
522     start = g_new0(struct kvm_sev_launch_start, 1);
523 
524     start->handle = sev->handle;
525     start->policy = sev->policy;
526     if (sev->session_file) {
527         if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
528             goto out;
529         }
530         start->session_uaddr = (unsigned long)session;
531         start->session_len = sz;
532     }
533 
534     if (sev->dh_cert_file) {
535         if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
536             goto out;
537         }
538         start->dh_uaddr = (unsigned long)dh_cert;
539         start->dh_len = sz;
540     }
541 
542     trace_kvm_sev_launch_start(start->policy, session, dh_cert);
543     rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
544     if (rc < 0) {
545         error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
546                 __func__, ret, fw_error, fw_error_to_str(fw_error));
547         goto out;
548     }
549 
550     sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
551     sev->handle = start->handle;
552     ret = 0;
553 
554 out:
555     g_free(start);
556     g_free(session);
557     g_free(dh_cert);
558     return ret;
559 }
560 
561 static int
562 sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
563 {
564     int ret, fw_error;
565     struct kvm_sev_launch_update_data update;
566 
567     if (!addr || !len) {
568         return 1;
569     }
570 
571     update.uaddr = (__u64)(unsigned long)addr;
572     update.len = len;
573     trace_kvm_sev_launch_update_data(addr, len);
574     ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
575                     &update, &fw_error);
576     if (ret) {
577         error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
578                 __func__, ret, fw_error, fw_error_to_str(fw_error));
579     }
580 
581     return ret;
582 }
583 
584 static void
585 sev_launch_get_measure(Notifier *notifier, void *unused)
586 {
587     SevGuestState *sev = sev_guest;
588     int ret, error;
589     guchar *data;
590     struct kvm_sev_launch_measure *measurement;
591 
592     if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
593         return;
594     }
595 
596     measurement = g_new0(struct kvm_sev_launch_measure, 1);
597 
598     /* query the measurement blob length */
599     ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
600                     measurement, &error);
601     if (!measurement->len) {
602         error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
603                      __func__, ret, error, fw_error_to_str(errno));
604         goto free_measurement;
605     }
606 
607     data = g_new0(guchar, measurement->len);
608     measurement->uaddr = (unsigned long)data;
609 
610     /* get the measurement blob */
611     ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
612                     measurement, &error);
613     if (ret) {
614         error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
615                      __func__, ret, error, fw_error_to_str(errno));
616         goto free_data;
617     }
618 
619     sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
620 
621     /* encode the measurement value and emit the event */
622     sev->measurement = g_base64_encode(data, measurement->len);
623     trace_kvm_sev_launch_measurement(sev->measurement);
624 
625 free_data:
626     g_free(data);
627 free_measurement:
628     g_free(measurement);
629 }
630 
631 char *
632 sev_get_launch_measurement(void)
633 {
634     if (sev_guest &&
635         sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
636         return g_strdup(sev_guest->measurement);
637     }
638 
639     return NULL;
640 }
641 
642 static Notifier sev_machine_done_notify = {
643     .notify = sev_launch_get_measure,
644 };
645 
646 static void
647 sev_launch_finish(SevGuestState *sev)
648 {
649     int ret, error;
650     Error *local_err = NULL;
651 
652     trace_kvm_sev_launch_finish();
653     ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
654     if (ret) {
655         error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
656                      __func__, ret, error, fw_error_to_str(error));
657         exit(1);
658     }
659 
660     sev_set_guest_state(sev, SEV_STATE_RUNNING);
661 
662     /* add migration blocker */
663     error_setg(&sev_mig_blocker,
664                "SEV: Migration is not implemented");
665     ret = migrate_add_blocker(sev_mig_blocker, &local_err);
666     if (local_err) {
667         error_report_err(local_err);
668         error_free(sev_mig_blocker);
669         exit(1);
670     }
671 }
672 
673 static void
674 sev_vm_state_change(void *opaque, int running, RunState state)
675 {
676     SevGuestState *sev = opaque;
677 
678     if (running) {
679         if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
680             sev_launch_finish(sev);
681         }
682     }
683 }
684 
685 int
686 sev_guest_init(const char *id)
687 {
688     SevGuestState *sev;
689     char *devname;
690     int ret, fw_error;
691     uint32_t ebx;
692     uint32_t host_cbitpos;
693     struct sev_user_data_status status = {};
694 
695     ret = ram_block_discard_disable(true);
696     if (ret) {
697         error_report("%s: cannot disable RAM discard", __func__);
698         return -1;
699     }
700 
701     sev = lookup_sev_guest_info(id);
702     if (!sev) {
703         error_report("%s: '%s' is not a valid '%s' object",
704                      __func__, id, TYPE_SEV_GUEST);
705         goto err;
706     }
707 
708     sev_guest = sev;
709     sev->state = SEV_STATE_UNINIT;
710 
711     host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
712     host_cbitpos = ebx & 0x3f;
713 
714     if (host_cbitpos != sev->cbitpos) {
715         error_report("%s: cbitpos check failed, host '%d' requested '%d'",
716                      __func__, host_cbitpos, sev->cbitpos);
717         goto err;
718     }
719 
720     if (sev->reduced_phys_bits < 1) {
721         error_report("%s: reduced_phys_bits check failed, it should be >=1,"
722                      " requested '%d'", __func__, sev->reduced_phys_bits);
723         goto err;
724     }
725 
726     sev->me_mask = ~(1UL << sev->cbitpos);
727 
728     devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
729     sev->sev_fd = open(devname, O_RDWR);
730     if (sev->sev_fd < 0) {
731         error_report("%s: Failed to open %s '%s'", __func__,
732                      devname, strerror(errno));
733     }
734     g_free(devname);
735     if (sev->sev_fd < 0) {
736         goto err;
737     }
738 
739     ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
740                              &fw_error);
741     if (ret) {
742         error_report("%s: failed to get platform status ret=%d "
743                      "fw_error='%d: %s'", __func__, ret, fw_error,
744                      fw_error_to_str(fw_error));
745         goto err;
746     }
747     sev->build_id = status.build;
748     sev->api_major = status.api_major;
749     sev->api_minor = status.api_minor;
750 
751     trace_kvm_sev_init();
752     ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, &fw_error);
753     if (ret) {
754         error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
755                      __func__, ret, fw_error, fw_error_to_str(fw_error));
756         goto err;
757     }
758 
759     ret = sev_launch_start(sev);
760     if (ret) {
761         error_report("%s: failed to create encryption context", __func__);
762         goto err;
763     }
764 
765     ram_block_notifier_add(&sev_ram_notifier);
766     qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
767     qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
768 
769     return 0;
770 err:
771     sev_guest = NULL;
772     ram_block_discard_disable(false);
773     return -1;
774 }
775 
776 int
777 sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
778 {
779     if (!sev_guest) {
780         return 0;
781     }
782 
783     /* if SEV is in update state then encrypt the data else do nothing */
784     if (sev_check_state(sev_guest, SEV_STATE_LAUNCH_UPDATE)) {
785         int ret = sev_launch_update_data(sev_guest, ptr, len);
786         if (ret < 0) {
787             error_setg(errp, "failed to encrypt pflash rom");
788             return ret;
789         }
790     }
791 
792     return 0;
793 }
794 
795 int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
796                              uint64_t gpa, Error **errp)
797 {
798     struct kvm_sev_launch_secret input;
799     g_autofree guchar *data = NULL, *hdr = NULL;
800     int error, ret = 1;
801     void *hva;
802     gsize hdr_sz = 0, data_sz = 0;
803     MemoryRegion *mr = NULL;
804 
805     if (!sev_guest) {
806         error_setg(errp, "SEV: SEV not enabled.");
807         return 1;
808     }
809 
810     /* secret can be injected only in this state */
811     if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
812         error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
813                      sev_guest->state);
814         return 1;
815     }
816 
817     hdr = g_base64_decode(packet_hdr, &hdr_sz);
818     if (!hdr || !hdr_sz) {
819         error_setg(errp, "SEV: Failed to decode sequence header");
820         return 1;
821     }
822 
823     data = g_base64_decode(secret, &data_sz);
824     if (!data || !data_sz) {
825         error_setg(errp, "SEV: Failed to decode data");
826         return 1;
827     }
828 
829     hva = gpa2hva(&mr, gpa, data_sz, errp);
830     if (!hva) {
831         error_prepend(errp, "SEV: Failed to calculate guest address: ");
832         return 1;
833     }
834 
835     input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
836     input.hdr_len = hdr_sz;
837 
838     input.trans_uaddr = (uint64_t)(unsigned long)data;
839     input.trans_len = data_sz;
840 
841     input.guest_uaddr = (uint64_t)(unsigned long)hva;
842     input.guest_len = data_sz;
843 
844     trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
845                                 input.trans_uaddr, input.trans_len);
846 
847     ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
848                     &input, &error);
849     if (ret) {
850         error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
851                      ret, error, fw_error_to_str(error));
852         return ret;
853     }
854 
855     return 0;
856 }
857 
858 static void
859 sev_register_types(void)
860 {
861     type_register_static(&sev_guest_info);
862 }
863 
864 type_init(sev_register_types);
865