1
2
3
4
5
6
7
8
9
10
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 "qemu/uuid.h"
26#include "sysemu/kvm.h"
27#include "sev_i386.h"
28#include "sysemu/sysemu.h"
29#include "sysemu/runstate.h"
30#include "trace.h"
31#include "migration/blocker.h"
32#include "qom/object.h"
33#include "exec/address-spaces.h"
34#include "monitor/monitor.h"
35#include "exec/confidential-guest-support.h"
36#include "hw/i386/pc.h"
37
38#define TYPE_SEV_GUEST "sev-guest"
39OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
40
41
42
43
44
45
46
47
48
49
50
51
52struct SevGuestState {
53 ConfidentialGuestSupport parent_obj;
54
55
56 char *sev_device;
57 uint32_t policy;
58 char *dh_cert_file;
59 char *session_file;
60 uint32_t cbitpos;
61 uint32_t reduced_phys_bits;
62
63
64 uint32_t handle;
65 uint8_t api_major;
66 uint8_t api_minor;
67 uint8_t build_id;
68 uint64_t me_mask;
69 int sev_fd;
70 SevState state;
71 gchar *measurement;
72
73 uint32_t reset_cs;
74 uint32_t reset_ip;
75 bool reset_data_valid;
76};
77
78#define DEFAULT_GUEST_POLICY 0x1
79#define DEFAULT_SEV_DEVICE "/dev/sev"
80
81#define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
82typedef struct __attribute__((__packed__)) SevInfoBlock {
83
84 uint32_t reset_addr;
85} SevInfoBlock;
86
87static SevGuestState *sev_guest;
88static Error *sev_mig_blocker;
89
90static const char *const sev_fw_errlist[] = {
91 "",
92 "Platform state is invalid",
93 "Guest state is invalid",
94 "Platform configuration is invalid",
95 "Buffer too small",
96 "Platform is already owned",
97 "Certificate is invalid",
98 "Policy is not allowed",
99 "Guest is not active",
100 "Invalid address",
101 "Bad signature",
102 "Bad measurement",
103 "Asid is already owned",
104 "Invalid ASID",
105 "WBINVD is required",
106 "DF_FLUSH is required",
107 "Guest handle is invalid",
108 "Invalid command",
109 "Guest is active",
110 "Hardware error",
111 "Hardware unsafe",
112 "Feature not supported",
113 "Invalid parameter"
114};
115
116#define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
117
118static int
119sev_ioctl(int fd, int cmd, void *data, int *error)
120{
121 int r;
122 struct kvm_sev_cmd input;
123
124 memset(&input, 0x0, sizeof(input));
125
126 input.id = cmd;
127 input.sev_fd = fd;
128 input.data = (__u64)(unsigned long)data;
129
130 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
131
132 if (error) {
133 *error = input.error;
134 }
135
136 return r;
137}
138
139static int
140sev_platform_ioctl(int fd, int cmd, void *data, int *error)
141{
142 int r;
143 struct sev_issue_cmd arg;
144
145 arg.cmd = cmd;
146 arg.data = (unsigned long)data;
147 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
148 if (error) {
149 *error = arg.error;
150 }
151
152 return r;
153}
154
155static const char *
156fw_error_to_str(int code)
157{
158 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
159 return "unknown error";
160 }
161
162 return sev_fw_errlist[code];
163}
164
165static bool
166sev_check_state(const SevGuestState *sev, SevState state)
167{
168 assert(sev);
169 return sev->state == state ? true : false;
170}
171
172static void
173sev_set_guest_state(SevGuestState *sev, SevState new_state)
174{
175 assert(new_state < SEV_STATE__MAX);
176 assert(sev);
177
178 trace_kvm_sev_change_state(SevState_str(sev->state),
179 SevState_str(new_state));
180 sev->state = new_state;
181}
182
183static void
184sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
185{
186 int r;
187 struct kvm_enc_region range;
188 ram_addr_t offset;
189 MemoryRegion *mr;
190
191
192
193
194
195 mr = memory_region_from_host(host, &offset);
196 if (mr && memory_region_is_ram_device(mr)) {
197 return;
198 }
199
200 range.addr = (__u64)(unsigned long)host;
201 range.size = size;
202
203 trace_kvm_memcrypt_register_region(host, size);
204 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
205 if (r) {
206 error_report("%s: failed to register region (%p+%#zx) error '%s'",
207 __func__, host, size, strerror(errno));
208 exit(1);
209 }
210}
211
212static void
213sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
214{
215 int r;
216 struct kvm_enc_region range;
217 ram_addr_t offset;
218 MemoryRegion *mr;
219
220
221
222
223
224 mr = memory_region_from_host(host, &offset);
225 if (mr && memory_region_is_ram_device(mr)) {
226 return;
227 }
228
229 range.addr = (__u64)(unsigned long)host;
230 range.size = size;
231
232 trace_kvm_memcrypt_unregister_region(host, size);
233 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
234 if (r) {
235 error_report("%s: failed to unregister region (%p+%#zx)",
236 __func__, host, size);
237 }
238}
239
240static struct RAMBlockNotifier sev_ram_notifier = {
241 .ram_block_added = sev_ram_block_added,
242 .ram_block_removed = sev_ram_block_removed,
243};
244
245static void
246sev_guest_finalize(Object *obj)
247{
248}
249
250static char *
251sev_guest_get_session_file(Object *obj, Error **errp)
252{
253 SevGuestState *s = SEV_GUEST(obj);
254
255 return s->session_file ? g_strdup(s->session_file) : NULL;
256}
257
258static void
259sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
260{
261 SevGuestState *s = SEV_GUEST(obj);
262
263 s->session_file = g_strdup(value);
264}
265
266static char *
267sev_guest_get_dh_cert_file(Object *obj, Error **errp)
268{
269 SevGuestState *s = SEV_GUEST(obj);
270
271 return g_strdup(s->dh_cert_file);
272}
273
274static void
275sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
276{
277 SevGuestState *s = SEV_GUEST(obj);
278
279 s->dh_cert_file = g_strdup(value);
280}
281
282static char *
283sev_guest_get_sev_device(Object *obj, Error **errp)
284{
285 SevGuestState *sev = SEV_GUEST(obj);
286
287 return g_strdup(sev->sev_device);
288}
289
290static void
291sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
292{
293 SevGuestState *sev = SEV_GUEST(obj);
294
295 sev->sev_device = g_strdup(value);
296}
297
298static void
299sev_guest_class_init(ObjectClass *oc, void *data)
300{
301 object_class_property_add_str(oc, "sev-device",
302 sev_guest_get_sev_device,
303 sev_guest_set_sev_device);
304 object_class_property_set_description(oc, "sev-device",
305 "SEV device to use");
306 object_class_property_add_str(oc, "dh-cert-file",
307 sev_guest_get_dh_cert_file,
308 sev_guest_set_dh_cert_file);
309 object_class_property_set_description(oc, "dh-cert-file",
310 "guest owners DH certificate (encoded with base64)");
311 object_class_property_add_str(oc, "session-file",
312 sev_guest_get_session_file,
313 sev_guest_set_session_file);
314 object_class_property_set_description(oc, "session-file",
315 "guest owners session parameters (encoded with base64)");
316}
317
318static void
319sev_guest_instance_init(Object *obj)
320{
321 SevGuestState *sev = SEV_GUEST(obj);
322
323 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
324 sev->policy = DEFAULT_GUEST_POLICY;
325 object_property_add_uint32_ptr(obj, "policy", &sev->policy,
326 OBJ_PROP_FLAG_READWRITE);
327 object_property_add_uint32_ptr(obj, "handle", &sev->handle,
328 OBJ_PROP_FLAG_READWRITE);
329 object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
330 OBJ_PROP_FLAG_READWRITE);
331 object_property_add_uint32_ptr(obj, "reduced-phys-bits",
332 &sev->reduced_phys_bits,
333 OBJ_PROP_FLAG_READWRITE);
334}
335
336
337static const TypeInfo sev_guest_info = {
338 .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
339 .name = TYPE_SEV_GUEST,
340 .instance_size = sizeof(SevGuestState),
341 .instance_finalize = sev_guest_finalize,
342 .class_init = sev_guest_class_init,
343 .instance_init = sev_guest_instance_init,
344 .interfaces = (InterfaceInfo[]) {
345 { TYPE_USER_CREATABLE },
346 { }
347 }
348};
349
350bool
351sev_enabled(void)
352{
353 return !!sev_guest;
354}
355
356bool
357sev_es_enabled(void)
358{
359 return sev_enabled() && (sev_guest->policy & SEV_POLICY_ES);
360}
361
362uint64_t
363sev_get_me_mask(void)
364{
365 return sev_guest ? sev_guest->me_mask : ~0;
366}
367
368uint32_t
369sev_get_cbit_position(void)
370{
371 return sev_guest ? sev_guest->cbitpos : 0;
372}
373
374uint32_t
375sev_get_reduced_phys_bits(void)
376{
377 return sev_guest ? sev_guest->reduced_phys_bits : 0;
378}
379
380SevInfo *
381sev_get_info(void)
382{
383 SevInfo *info;
384
385 info = g_new0(SevInfo, 1);
386 info->enabled = sev_enabled();
387
388 if (info->enabled) {
389 info->api_major = sev_guest->api_major;
390 info->api_minor = sev_guest->api_minor;
391 info->build_id = sev_guest->build_id;
392 info->policy = sev_guest->policy;
393 info->state = sev_guest->state;
394 info->handle = sev_guest->handle;
395 }
396
397 return info;
398}
399
400static int
401sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
402 size_t *cert_chain_len, Error **errp)
403{
404 guchar *pdh_data = NULL;
405 guchar *cert_chain_data = NULL;
406 struct sev_user_data_pdh_cert_export export = {};
407 int err, r;
408
409
410 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
411 if (r < 0) {
412 if (err != SEV_RET_INVALID_LEN) {
413 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
414 r, err, fw_error_to_str(err));
415 return 1;
416 }
417 }
418
419 pdh_data = g_new(guchar, export.pdh_cert_len);
420 cert_chain_data = g_new(guchar, export.cert_chain_len);
421 export.pdh_cert_address = (unsigned long)pdh_data;
422 export.cert_chain_address = (unsigned long)cert_chain_data;
423
424 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
425 if (r < 0) {
426 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
427 r, err, fw_error_to_str(err));
428 goto e_free;
429 }
430
431 *pdh = pdh_data;
432 *pdh_len = export.pdh_cert_len;
433 *cert_chain = cert_chain_data;
434 *cert_chain_len = export.cert_chain_len;
435 return 0;
436
437e_free:
438 g_free(pdh_data);
439 g_free(cert_chain_data);
440 return 1;
441}
442
443SevCapability *
444sev_get_capabilities(Error **errp)
445{
446 SevCapability *cap = NULL;
447 guchar *pdh_data = NULL;
448 guchar *cert_chain_data = NULL;
449 size_t pdh_len = 0, cert_chain_len = 0;
450 uint32_t ebx;
451 int fd;
452
453 if (!kvm_enabled()) {
454 error_setg(errp, "KVM not enabled");
455 return NULL;
456 }
457 if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
458 error_setg(errp, "SEV is not enabled in KVM");
459 return NULL;
460 }
461
462 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
463 if (fd < 0) {
464 error_setg_errno(errp, errno, "Failed to open %s",
465 DEFAULT_SEV_DEVICE);
466 return NULL;
467 }
468
469 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
470 &cert_chain_data, &cert_chain_len, errp)) {
471 goto out;
472 }
473
474 cap = g_new0(SevCapability, 1);
475 cap->pdh = g_base64_encode(pdh_data, pdh_len);
476 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
477
478 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
479 cap->cbitpos = ebx & 0x3f;
480
481
482
483
484
485 cap->reduced_phys_bits = 1;
486
487out:
488 g_free(pdh_data);
489 g_free(cert_chain_data);
490 close(fd);
491 return cap;
492}
493
494static int
495sev_read_file_base64(const char *filename, guchar **data, gsize *len)
496{
497 gsize sz;
498 gchar *base64;
499 GError *error = NULL;
500
501 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
502 error_report("failed to read '%s' (%s)", filename, error->message);
503 g_error_free(error);
504 return -1;
505 }
506
507 *data = g_base64_decode(base64, len);
508 return 0;
509}
510
511static int
512sev_launch_start(SevGuestState *sev)
513{
514 gsize sz;
515 int ret = 1;
516 int fw_error, rc;
517 struct kvm_sev_launch_start *start;
518 guchar *session = NULL, *dh_cert = NULL;
519
520 start = g_new0(struct kvm_sev_launch_start, 1);
521
522 start->handle = sev->handle;
523 start->policy = sev->policy;
524 if (sev->session_file) {
525 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
526 goto out;
527 }
528 start->session_uaddr = (unsigned long)session;
529 start->session_len = sz;
530 }
531
532 if (sev->dh_cert_file) {
533 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
534 goto out;
535 }
536 start->dh_uaddr = (unsigned long)dh_cert;
537 start->dh_len = sz;
538 }
539
540 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
541 rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
542 if (rc < 0) {
543 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
544 __func__, ret, fw_error, fw_error_to_str(fw_error));
545 goto out;
546 }
547
548 sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
549 sev->handle = start->handle;
550 ret = 0;
551
552out:
553 g_free(start);
554 g_free(session);
555 g_free(dh_cert);
556 return ret;
557}
558
559static int
560sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
561{
562 int ret, fw_error;
563 struct kvm_sev_launch_update_data update;
564
565 if (!addr || !len) {
566 return 1;
567 }
568
569 update.uaddr = (__u64)(unsigned long)addr;
570 update.len = len;
571 trace_kvm_sev_launch_update_data(addr, len);
572 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
573 &update, &fw_error);
574 if (ret) {
575 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
576 __func__, ret, fw_error, fw_error_to_str(fw_error));
577 }
578
579 return ret;
580}
581
582static int
583sev_launch_update_vmsa(SevGuestState *sev)
584{
585 int ret, fw_error;
586
587 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL, &fw_error);
588 if (ret) {
589 error_report("%s: LAUNCH_UPDATE_VMSA ret=%d fw_error=%d '%s'",
590 __func__, ret, fw_error, fw_error_to_str(fw_error));
591 }
592
593 return ret;
594}
595
596static void
597sev_launch_get_measure(Notifier *notifier, void *unused)
598{
599 SevGuestState *sev = sev_guest;
600 int ret, error;
601 guchar *data;
602 struct kvm_sev_launch_measure *measurement;
603
604 if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
605 return;
606 }
607
608 if (sev_es_enabled()) {
609
610 ret = sev_launch_update_vmsa(sev);
611 if (ret) {
612 exit(1);
613 }
614 }
615
616 measurement = g_new0(struct kvm_sev_launch_measure, 1);
617
618
619 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
620 measurement, &error);
621 if (!measurement->len) {
622 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
623 __func__, ret, error, fw_error_to_str(errno));
624 goto free_measurement;
625 }
626
627 data = g_new0(guchar, measurement->len);
628 measurement->uaddr = (unsigned long)data;
629
630
631 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
632 measurement, &error);
633 if (ret) {
634 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
635 __func__, ret, error, fw_error_to_str(errno));
636 goto free_data;
637 }
638
639 sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
640
641
642 sev->measurement = g_base64_encode(data, measurement->len);
643 trace_kvm_sev_launch_measurement(sev->measurement);
644
645free_data:
646 g_free(data);
647free_measurement:
648 g_free(measurement);
649}
650
651char *
652sev_get_launch_measurement(void)
653{
654 if (sev_guest &&
655 sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
656 return g_strdup(sev_guest->measurement);
657 }
658
659 return NULL;
660}
661
662static Notifier sev_machine_done_notify = {
663 .notify = sev_launch_get_measure,
664};
665
666static void
667sev_launch_finish(SevGuestState *sev)
668{
669 int ret, error;
670 Error *local_err = NULL;
671
672 trace_kvm_sev_launch_finish();
673 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
674 if (ret) {
675 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
676 __func__, ret, error, fw_error_to_str(error));
677 exit(1);
678 }
679
680 sev_set_guest_state(sev, SEV_STATE_RUNNING);
681
682
683 error_setg(&sev_mig_blocker,
684 "SEV: Migration is not implemented");
685 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
686 if (local_err) {
687 error_report_err(local_err);
688 error_free(sev_mig_blocker);
689 exit(1);
690 }
691}
692
693static void
694sev_vm_state_change(void *opaque, bool running, RunState state)
695{
696 SevGuestState *sev = opaque;
697
698 if (running) {
699 if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
700 sev_launch_finish(sev);
701 }
702 }
703}
704
705int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
706{
707 SevGuestState *sev
708 = (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
709 char *devname;
710 int ret, fw_error, cmd;
711 uint32_t ebx;
712 uint32_t host_cbitpos;
713 struct sev_user_data_status status = {};
714
715 if (!sev) {
716 return 0;
717 }
718
719 ret = ram_block_discard_disable(true);
720 if (ret) {
721 error_report("%s: cannot disable RAM discard", __func__);
722 return -1;
723 }
724
725 sev_guest = sev;
726 sev->state = SEV_STATE_UNINIT;
727
728 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
729 host_cbitpos = ebx & 0x3f;
730
731 if (host_cbitpos != sev->cbitpos) {
732 error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'",
733 __func__, host_cbitpos, sev->cbitpos);
734 goto err;
735 }
736
737 if (sev->reduced_phys_bits < 1) {
738 error_setg(errp, "%s: reduced_phys_bits check failed, it should be >=1,"
739 " requested '%d'", __func__, sev->reduced_phys_bits);
740 goto err;
741 }
742
743 sev->me_mask = ~(1UL << sev->cbitpos);
744
745 devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
746 sev->sev_fd = open(devname, O_RDWR);
747 if (sev->sev_fd < 0) {
748 error_setg(errp, "%s: Failed to open %s '%s'", __func__,
749 devname, strerror(errno));
750 g_free(devname);
751 goto err;
752 }
753 g_free(devname);
754
755 ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
756 &fw_error);
757 if (ret) {
758 error_setg(errp, "%s: failed to get platform status ret=%d "
759 "fw_error='%d: %s'", __func__, ret, fw_error,
760 fw_error_to_str(fw_error));
761 goto err;
762 }
763 sev->build_id = status.build;
764 sev->api_major = status.api_major;
765 sev->api_minor = status.api_minor;
766
767 if (sev_es_enabled()) {
768 if (!kvm_kernel_irqchip_allowed()) {
769 error_report("%s: SEV-ES guests require in-kernel irqchip support",
770 __func__);
771 goto err;
772 }
773
774 if (!(status.flags & SEV_STATUS_FLAGS_CONFIG_ES)) {
775 error_report("%s: guest policy requires SEV-ES, but "
776 "host SEV-ES support unavailable",
777 __func__);
778 goto err;
779 }
780 cmd = KVM_SEV_ES_INIT;
781 } else {
782 cmd = KVM_SEV_INIT;
783 }
784
785 trace_kvm_sev_init();
786 ret = sev_ioctl(sev->sev_fd, cmd, NULL, &fw_error);
787 if (ret) {
788 error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
789 __func__, ret, fw_error, fw_error_to_str(fw_error));
790 goto err;
791 }
792
793 ret = sev_launch_start(sev);
794 if (ret) {
795 error_setg(errp, "%s: failed to create encryption context", __func__);
796 goto err;
797 }
798
799 ram_block_notifier_add(&sev_ram_notifier);
800 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
801 qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
802
803 cgs->ready = true;
804
805 return 0;
806err:
807 sev_guest = NULL;
808 ram_block_discard_disable(false);
809 return -1;
810}
811
812int
813sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
814{
815 if (!sev_guest) {
816 return 0;
817 }
818
819
820 if (sev_check_state(sev_guest, SEV_STATE_LAUNCH_UPDATE)) {
821 int ret = sev_launch_update_data(sev_guest, ptr, len);
822 if (ret < 0) {
823 error_setg(errp, "failed to encrypt pflash rom");
824 return ret;
825 }
826 }
827
828 return 0;
829}
830
831int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
832 uint64_t gpa, Error **errp)
833{
834 struct kvm_sev_launch_secret input;
835 g_autofree guchar *data = NULL, *hdr = NULL;
836 int error, ret = 1;
837 void *hva;
838 gsize hdr_sz = 0, data_sz = 0;
839 MemoryRegion *mr = NULL;
840
841 if (!sev_guest) {
842 error_setg(errp, "SEV: SEV not enabled.");
843 return 1;
844 }
845
846
847 if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
848 error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
849 sev_guest->state);
850 return 1;
851 }
852
853 hdr = g_base64_decode(packet_hdr, &hdr_sz);
854 if (!hdr || !hdr_sz) {
855 error_setg(errp, "SEV: Failed to decode sequence header");
856 return 1;
857 }
858
859 data = g_base64_decode(secret, &data_sz);
860 if (!data || !data_sz) {
861 error_setg(errp, "SEV: Failed to decode data");
862 return 1;
863 }
864
865 hva = gpa2hva(&mr, gpa, data_sz, errp);
866 if (!hva) {
867 error_prepend(errp, "SEV: Failed to calculate guest address: ");
868 return 1;
869 }
870
871 input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
872 input.hdr_len = hdr_sz;
873
874 input.trans_uaddr = (uint64_t)(unsigned long)data;
875 input.trans_len = data_sz;
876
877 input.guest_uaddr = (uint64_t)(unsigned long)hva;
878 input.guest_len = data_sz;
879
880 trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
881 input.trans_uaddr, input.trans_len);
882
883 ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
884 &input, &error);
885 if (ret) {
886 error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
887 ret, error, fw_error_to_str(error));
888 return ret;
889 }
890
891 return 0;
892}
893
894static int
895sev_es_parse_reset_block(SevInfoBlock *info, uint32_t *addr)
896{
897 if (!info->reset_addr) {
898 error_report("SEV-ES reset address is zero");
899 return 1;
900 }
901
902 *addr = info->reset_addr;
903
904 return 0;
905}
906
907static int
908sev_es_find_reset_vector(void *flash_ptr, uint64_t flash_size,
909 uint32_t *addr)
910{
911 QemuUUID info_guid, *guid;
912 SevInfoBlock *info;
913 uint8_t *data;
914 uint16_t *len;
915
916
917
918
919
920 *addr = 0;
921
922
923
924
925
926
927
928
929
930 if (pc_system_ovmf_table_find(SEV_INFO_BLOCK_GUID, &data, NULL)) {
931 return sev_es_parse_reset_block((SevInfoBlock *)data, addr);
932 }
933
934
935
936
937
938 data = flash_ptr + flash_size - 0x20;
939
940 qemu_uuid_parse(SEV_INFO_BLOCK_GUID, &info_guid);
941 info_guid = qemu_uuid_bswap(info_guid);
942
943 guid = (QemuUUID *)(data - sizeof(info_guid));
944 if (!qemu_uuid_is_equal(guid, &info_guid)) {
945 error_report("SEV information block/Firmware GUID Table block not found in pflash rom");
946 return 1;
947 }
948
949 len = (uint16_t *)((uint8_t *)guid - sizeof(*len));
950 info = (SevInfoBlock *)(data - le16_to_cpu(*len));
951
952 return sev_es_parse_reset_block(info, addr);
953}
954
955void sev_es_set_reset_vector(CPUState *cpu)
956{
957 X86CPU *x86;
958 CPUX86State *env;
959
960
961 if (!sev_guest || !sev_guest->reset_data_valid) {
962 return;
963 }
964
965
966 if (cpu->cpu_index == 0) {
967 return;
968 }
969
970 x86 = X86_CPU(cpu);
971 env = &x86->env;
972
973 cpu_x86_load_seg_cache(env, R_CS, 0xf000, sev_guest->reset_cs, 0xffff,
974 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
975 DESC_R_MASK | DESC_A_MASK);
976
977 env->eip = sev_guest->reset_ip;
978}
979
980int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
981{
982 CPUState *cpu;
983 uint32_t addr;
984 int ret;
985
986 if (!sev_es_enabled()) {
987 return 0;
988 }
989
990 addr = 0;
991 ret = sev_es_find_reset_vector(flash_ptr, flash_size,
992 &addr);
993 if (ret) {
994 return ret;
995 }
996
997 if (addr) {
998 sev_guest->reset_cs = addr & 0xffff0000;
999 sev_guest->reset_ip = addr & 0x0000ffff;
1000 sev_guest->reset_data_valid = true;
1001
1002 CPU_FOREACH(cpu) {
1003 sev_es_set_reset_vector(cpu);
1004 }
1005 }
1006
1007 return 0;
1008}
1009
1010static void
1011sev_register_types(void)
1012{
1013 type_register_static(&sev_guest_info);
1014}
1015
1016type_init(sev_register_types);
1017