]> Git Repo - qemu.git/blame - target/i386/sev.c
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20190716' into staging
[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 <[email protected]>
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;
56e2ec94
AW
164 ram_addr_t offset;
165 MemoryRegion *mr;
166
167 /*
168 * The RAM device presents a memory region that should be treated
169 * as IO region and should not have been pinned.
170 */
171 mr = memory_region_from_host(host, &offset);
172 if (mr && memory_region_is_ram_device(mr)) {
173 return;
174 }
2b308e44
BS
175
176 range.addr = (__u64)(unsigned long)host;
177 range.size = size;
178
179 trace_kvm_memcrypt_unregister_region(host, size);
180 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
181 if (r) {
182 error_report("%s: failed to unregister region (%p+%#zx)",
183 __func__, host, size);
184 }
185}
186
187static struct RAMBlockNotifier sev_ram_notifier = {
188 .ram_block_added = sev_ram_block_added,
189 .ram_block_removed = sev_ram_block_removed,
190};
191
a9b4942f
BS
192static void
193qsev_guest_finalize(Object *obj)
194{
195}
196
197static char *
198qsev_guest_get_session_file(Object *obj, Error **errp)
199{
200 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
201
202 return s->session_file ? g_strdup(s->session_file) : NULL;
203}
204
205static void
206qsev_guest_set_session_file(Object *obj, const char *value, Error **errp)
207{
208 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
209
210 s->session_file = g_strdup(value);
211}
212
213static char *
214qsev_guest_get_dh_cert_file(Object *obj, Error **errp)
215{
216 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
217
218 return g_strdup(s->dh_cert_file);
219}
220
221static void
222qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
223{
224 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
225
226 s->dh_cert_file = g_strdup(value);
227}
228
229static char *
230qsev_guest_get_sev_device(Object *obj, Error **errp)
231{
232 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
233
234 return g_strdup(sev->sev_device);
235}
236
237static void
238qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
239{
240 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
241
242 sev->sev_device = g_strdup(value);
243}
244
245static void
246qsev_guest_class_init(ObjectClass *oc, void *data)
247{
248 object_class_property_add_str(oc, "sev-device",
249 qsev_guest_get_sev_device,
250 qsev_guest_set_sev_device,
251 NULL);
252 object_class_property_set_description(oc, "sev-device",
253 "SEV device to use", NULL);
254 object_class_property_add_str(oc, "dh-cert-file",
255 qsev_guest_get_dh_cert_file,
256 qsev_guest_set_dh_cert_file,
257 NULL);
258 object_class_property_set_description(oc, "dh-cert-file",
259 "guest owners DH certificate (encoded with base64)", NULL);
260 object_class_property_add_str(oc, "session-file",
261 qsev_guest_get_session_file,
262 qsev_guest_set_session_file,
263 NULL);
264 object_class_property_set_description(oc, "session-file",
265 "guest owners session parameters (encoded with base64)", NULL);
266}
267
268static void
269qsev_guest_set_handle(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->handle = value;
277}
278
279static void
280qsev_guest_set_policy(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->policy = value;
288}
289
290static void
291qsev_guest_set_cbitpos(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->cbitpos = value;
299}
300
301static void
302qsev_guest_set_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
303 void *opaque, Error **errp)
304{
305 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
306 uint32_t value;
307
308 visit_type_uint32(v, name, &value, errp);
309 sev->reduced_phys_bits = value;
310}
311
312static void
313qsev_guest_get_policy(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->policy;
320 visit_type_uint32(v, name, &value, errp);
321}
322
323static void
324qsev_guest_get_handle(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->handle;
331 visit_type_uint32(v, name, &value, errp);
332}
333
334static void
335qsev_guest_get_cbitpos(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->cbitpos;
342 visit_type_uint32(v, name, &value, errp);
343}
344
345static void
346qsev_guest_get_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
347 void *opaque, Error **errp)
348{
349 uint32_t value;
350 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
351
352 value = sev->reduced_phys_bits;
353 visit_type_uint32(v, name, &value, errp);
354}
355
356static void
357qsev_guest_init(Object *obj)
358{
359 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
360
361 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
362 sev->policy = DEFAULT_GUEST_POLICY;
363 object_property_add(obj, "policy", "uint32", qsev_guest_get_policy,
364 qsev_guest_set_policy, NULL, NULL, NULL);
365 object_property_add(obj, "handle", "uint32", qsev_guest_get_handle,
366 qsev_guest_set_handle, NULL, NULL, NULL);
367 object_property_add(obj, "cbitpos", "uint32", qsev_guest_get_cbitpos,
368 qsev_guest_set_cbitpos, NULL, NULL, NULL);
369 object_property_add(obj, "reduced-phys-bits", "uint32",
370 qsev_guest_get_reduced_phys_bits,
371 qsev_guest_set_reduced_phys_bits, NULL, NULL, NULL);
372}
373
374/* sev guest info */
375static const TypeInfo qsev_guest_info = {
376 .parent = TYPE_OBJECT,
377 .name = TYPE_QSEV_GUEST_INFO,
378 .instance_size = sizeof(QSevGuestInfo),
379 .instance_finalize = qsev_guest_finalize,
380 .class_size = sizeof(QSevGuestInfoClass),
381 .class_init = qsev_guest_class_init,
382 .instance_init = qsev_guest_init,
383 .interfaces = (InterfaceInfo[]) {
384 { TYPE_USER_CREATABLE },
385 { }
386 }
387};
388
d8575c6c
BS
389static QSevGuestInfo *
390lookup_sev_guest_info(const char *id)
391{
392 Object *obj;
393 QSevGuestInfo *info;
394
395 obj = object_resolve_path_component(object_get_objects_root(), id);
396 if (!obj) {
397 return NULL;
398 }
399
400 info = (QSevGuestInfo *)
401 object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO);
402 if (!info) {
403 return NULL;
404 }
405
406 return info;
407}
408
409bool
410sev_enabled(void)
411{
412 return sev_state ? true : false;
413}
414
415uint64_t
416sev_get_me_mask(void)
417{
418 return sev_state ? sev_state->me_mask : ~0;
419}
420
421uint32_t
422sev_get_cbit_position(void)
423{
424 return sev_state ? sev_state->cbitpos : 0;
425}
426
427uint32_t
428sev_get_reduced_phys_bits(void)
429{
430 return sev_state ? sev_state->reduced_phys_bits : 0;
431}
432
433SevInfo *
434sev_get_info(void)
435{
436 SevInfo *info;
437
438 info = g_new0(SevInfo, 1);
439 info->enabled = sev_state ? true : false;
440
441 if (info->enabled) {
442 info->api_major = sev_state->api_major;
443 info->api_minor = sev_state->api_minor;
444 info->build_id = sev_state->build_id;
445 info->policy = sev_state->policy;
446 info->state = sev_state->state;
447 info->handle = sev_state->handle;
448 }
449
450 return info;
451}
452
9f750794
BS
453static int
454sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
455 size_t *cert_chain_len)
456{
bf3175b4
PB
457 guchar *pdh_data = NULL;
458 guchar *cert_chain_data = NULL;
9f750794
BS
459 struct sev_user_data_pdh_cert_export export = {};
460 int err, r;
461
462 /* query the certificate length */
463 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
464 if (r < 0) {
465 if (err != SEV_RET_INVALID_LEN) {
466 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
467 r, err, fw_error_to_str(err));
468 return 1;
469 }
470 }
471
472 pdh_data = g_new(guchar, export.pdh_cert_len);
473 cert_chain_data = g_new(guchar, export.cert_chain_len);
474 export.pdh_cert_address = (unsigned long)pdh_data;
475 export.cert_chain_address = (unsigned long)cert_chain_data;
476
477 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
478 if (r < 0) {
479 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
480 r, err, fw_error_to_str(err));
481 goto e_free;
482 }
483
484 *pdh = pdh_data;
485 *pdh_len = export.pdh_cert_len;
486 *cert_chain = cert_chain_data;
487 *cert_chain_len = export.cert_chain_len;
488 return 0;
489
490e_free:
491 g_free(pdh_data);
492 g_free(cert_chain_data);
493 return 1;
494}
495
496SevCapability *
497sev_get_capabilities(void)
498{
bf3175b4
PB
499 SevCapability *cap = NULL;
500 guchar *pdh_data = NULL;
501 guchar *cert_chain_data = NULL;
9f750794
BS
502 size_t pdh_len = 0, cert_chain_len = 0;
503 uint32_t ebx;
504 int fd;
505
506 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
507 if (fd < 0) {
508 error_report("%s: Failed to open %s '%s'", __func__,
509 DEFAULT_SEV_DEVICE, strerror(errno));
510 return NULL;
511 }
512
513 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
514 &cert_chain_data, &cert_chain_len)) {
bf3175b4 515 goto out;
9f750794
BS
516 }
517
518 cap = g_new0(SevCapability, 1);
519 cap->pdh = g_base64_encode(pdh_data, pdh_len);
520 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
521
522 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
523 cap->cbitpos = ebx & 0x3f;
524
525 /*
526 * When SEV feature is enabled, we loose one bit in guest physical
527 * addressing.
528 */
529 cap->reduced_phys_bits = 1;
530
bf3175b4 531out:
9f750794
BS
532 g_free(pdh_data);
533 g_free(cert_chain_data);
9f750794
BS
534 close(fd);
535 return cap;
536}
537
620fd55c
BS
538static int
539sev_read_file_base64(const char *filename, guchar **data, gsize *len)
540{
541 gsize sz;
542 gchar *base64;
543 GError *error = NULL;
544
545 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
546 error_report("failed to read '%s' (%s)", filename, error->message);
547 return -1;
548 }
549
550 *data = g_base64_decode(base64, len);
551 return 0;
552}
553
554static int
555sev_launch_start(SEVState *s)
556{
557 gsize sz;
558 int ret = 1;
bf3175b4 559 int fw_error, rc;
620fd55c
BS
560 QSevGuestInfo *sev = s->sev_info;
561 struct kvm_sev_launch_start *start;
562 guchar *session = NULL, *dh_cert = NULL;
563
564 start = g_new0(struct kvm_sev_launch_start, 1);
565
566 start->handle = object_property_get_int(OBJECT(sev), "handle",
567 &error_abort);
568 start->policy = object_property_get_int(OBJECT(sev), "policy",
569 &error_abort);
570 if (sev->session_file) {
571 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
bf3175b4 572 goto out;
620fd55c
BS
573 }
574 start->session_uaddr = (unsigned long)session;
575 start->session_len = sz;
576 }
577
578 if (sev->dh_cert_file) {
579 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
bf3175b4 580 goto out;
620fd55c
BS
581 }
582 start->dh_uaddr = (unsigned long)dh_cert;
583 start->dh_len = sz;
584 }
585
586 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
bf3175b4
PB
587 rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
588 if (rc < 0) {
620fd55c
BS
589 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
590 __func__, ret, fw_error, fw_error_to_str(fw_error));
bf3175b4 591 goto out;
620fd55c
BS
592 }
593
594 object_property_set_int(OBJECT(sev), start->handle, "handle",
595 &error_abort);
596 sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE);
597 s->handle = start->handle;
598 s->policy = start->policy;
bf3175b4 599 ret = 0;
620fd55c 600
bf3175b4 601out:
620fd55c
BS
602 g_free(start);
603 g_free(session);
604 g_free(dh_cert);
bf3175b4 605 return ret;
620fd55c
BS
606}
607
b738d630
BS
608static int
609sev_launch_update_data(uint8_t *addr, uint64_t len)
610{
611 int ret, fw_error;
612 struct kvm_sev_launch_update_data update;
613
614 if (!addr || !len) {
615 return 1;
616 }
617
618 update.uaddr = (__u64)(unsigned long)addr;
619 update.len = len;
620 trace_kvm_sev_launch_update_data(addr, len);
621 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
622 &update, &fw_error);
623 if (ret) {
624 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
625 __func__, ret, fw_error, fw_error_to_str(fw_error));
626 }
627
628 return ret;
629}
630
c6c89c97
BS
631static void
632sev_launch_get_measure(Notifier *notifier, void *unused)
633{
634 int ret, error;
635 guchar *data;
636 SEVState *s = sev_state;
637 struct kvm_sev_launch_measure *measurement;
638
639 if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE)) {
640 return;
641 }
642
643 measurement = g_new0(struct kvm_sev_launch_measure, 1);
644
645 /* query the measurement blob length */
646 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE,
647 measurement, &error);
648 if (!measurement->len) {
649 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
650 __func__, ret, error, fw_error_to_str(errno));
651 goto free_measurement;
652 }
653
654 data = g_new0(guchar, measurement->len);
655 measurement->uaddr = (unsigned long)data;
656
657 /* get the measurement blob */
658 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE,
659 measurement, &error);
660 if (ret) {
661 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
662 __func__, ret, error, fw_error_to_str(errno));
663 goto free_data;
664 }
665
666 sev_set_guest_state(SEV_STATE_LAUNCH_SECRET);
667
668 /* encode the measurement value and emit the event */
669 s->measurement = g_base64_encode(data, measurement->len);
670 trace_kvm_sev_launch_measurement(s->measurement);
671
672free_data:
673 g_free(data);
674free_measurement:
675 g_free(measurement);
676}
677
678char *
679sev_get_launch_measurement(void)
680{
681 if (sev_state &&
682 sev_state->state >= SEV_STATE_LAUNCH_SECRET) {
683 return g_strdup(sev_state->measurement);
684 }
685
686 return NULL;
687}
688
689static Notifier sev_machine_done_notify = {
690 .notify = sev_launch_get_measure,
691};
692
5dd0df7e
BS
693static void
694sev_launch_finish(SEVState *s)
695{
696 int ret, error;
8fa4466d 697 Error *local_err = NULL;
5dd0df7e
BS
698
699 trace_kvm_sev_launch_finish();
700 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
701 if (ret) {
702 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
703 __func__, ret, error, fw_error_to_str(error));
704 exit(1);
705 }
706
707 sev_set_guest_state(SEV_STATE_RUNNING);
8fa4466d
BS
708
709 /* add migration blocker */
710 error_setg(&sev_mig_blocker,
711 "SEV: Migration is not implemented");
712 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
713 if (local_err) {
714 error_report_err(local_err);
715 error_free(sev_mig_blocker);
716 exit(1);
717 }
5dd0df7e
BS
718}
719
720static void
721sev_vm_state_change(void *opaque, int running, RunState state)
722{
723 SEVState *s = opaque;
724
725 if (running) {
726 if (!sev_check_state(SEV_STATE_RUNNING)) {
727 sev_launch_finish(s);
728 }
729 }
730}
731
d8575c6c
BS
732void *
733sev_guest_init(const char *id)
734{
735 SEVState *s;
736 char *devname;
737 int ret, fw_error;
738 uint32_t ebx;
739 uint32_t host_cbitpos;
740 struct sev_user_data_status status = {};
741
bf3175b4 742 sev_state = s = g_new0(SEVState, 1);
d8575c6c
BS
743 s->sev_info = lookup_sev_guest_info(id);
744 if (!s->sev_info) {
745 error_report("%s: '%s' is not a valid '%s' object",
746 __func__, id, TYPE_QSEV_GUEST_INFO);
747 goto err;
748 }
749
d8575c6c
BS
750 s->state = SEV_STATE_UNINIT;
751
752 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
753 host_cbitpos = ebx & 0x3f;
754
755 s->cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL);
756 if (host_cbitpos != s->cbitpos) {
757 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
758 __func__, host_cbitpos, s->cbitpos);
759 goto err;
760 }
761
762 s->reduced_phys_bits = object_property_get_int(OBJECT(s->sev_info),
763 "reduced-phys-bits", NULL);
764 if (s->reduced_phys_bits < 1) {
765 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
766 "' requested '%d'", __func__, s->reduced_phys_bits);
767 goto err;
768 }
769
770 s->me_mask = ~(1UL << s->cbitpos);
771
772 devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL);
773 s->sev_fd = open(devname, O_RDWR);
774 if (s->sev_fd < 0) {
775 error_report("%s: Failed to open %s '%s'", __func__,
776 devname, strerror(errno));
d8575c6c
BS
777 }
778 g_free(devname);
5d7bc72a
GK
779 if (s->sev_fd < 0) {
780 goto err;
781 }
d8575c6c
BS
782
783 ret = sev_platform_ioctl(s->sev_fd, SEV_PLATFORM_STATUS, &status,
784 &fw_error);
785 if (ret) {
786 error_report("%s: failed to get platform status ret=%d"
787 "fw_error='%d: %s'", __func__, ret, fw_error,
788 fw_error_to_str(fw_error));
789 goto err;
790 }
791 s->build_id = status.build;
792 s->api_major = status.api_major;
793 s->api_minor = status.api_minor;
794
795 trace_kvm_sev_init();
796 ret = sev_ioctl(s->sev_fd, KVM_SEV_INIT, NULL, &fw_error);
797 if (ret) {
798 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
799 __func__, ret, fw_error, fw_error_to_str(fw_error));
800 goto err;
801 }
802
620fd55c
BS
803 ret = sev_launch_start(s);
804 if (ret) {
805 error_report("%s: failed to create encryption context", __func__);
806 goto err;
807 }
808
2b308e44 809 ram_block_notifier_add(&sev_ram_notifier);
c6c89c97 810 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
5dd0df7e 811 qemu_add_vm_change_state_handler(sev_vm_state_change, s);
2b308e44 812
d8575c6c
BS
813 return s;
814err:
815 g_free(sev_state);
816 sev_state = NULL;
817 return NULL;
818}
819
b738d630
BS
820int
821sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
822{
823 assert(handle);
824
825 /* if SEV is in update state then encrypt the data else do nothing */
826 if (sev_check_state(SEV_STATE_LAUNCH_UPDATE)) {
827 return sev_launch_update_data(ptr, len);
828 }
829
830 return 0;
831}
832
a9b4942f
BS
833static void
834sev_register_types(void)
835{
836 type_register_static(&qsev_guest_info);
837}
838
839type_init(sev_register_types);
This page took 0.228367 seconds and 4 git commands to generate.