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