]> Git Repo - qemu.git/blob - target/i386/sev.c
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20190716' into staging
[qemu.git] / target / i386 / sev.c
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
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 "trace.h"
29 #include "migration/blocker.h"
30
31 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
32 #define DEFAULT_SEV_DEVICE      "/dev/sev"
33
34 static SEVState *sev_state;
35 static Error *sev_mig_blocker;
36
37 static 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
65 static int
66 sev_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
86 static int
87 sev_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
102 static const char *
103 fw_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
112 static bool
113 sev_check_state(SevState state)
114 {
115     assert(sev_state);
116     return sev_state->state == state ? true : false;
117 }
118
119 static void
120 sev_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
130 static void
131 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
132 {
133     int r;
134     struct kvm_enc_region range;
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     }
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
159 static void
160 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
161 {
162     int r;
163     struct kvm_enc_region range;
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     }
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
187 static struct RAMBlockNotifier sev_ram_notifier = {
188     .ram_block_added = sev_ram_block_added,
189     .ram_block_removed = sev_ram_block_removed,
190 };
191
192 static void
193 qsev_guest_finalize(Object *obj)
194 {
195 }
196
197 static char *
198 qsev_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
205 static void
206 qsev_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
213 static char *
214 qsev_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
221 static void
222 qsev_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
229 static char *
230 qsev_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
237 static void
238 qsev_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
245 static void
246 qsev_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
268 static void
269 qsev_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
279 static void
280 qsev_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
290 static void
291 qsev_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
301 static void
302 qsev_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
312 static void
313 qsev_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
323 static void
324 qsev_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
334 static void
335 qsev_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
345 static void
346 qsev_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
356 static void
357 qsev_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 */
375 static 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
389 static QSevGuestInfo *
390 lookup_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
409 bool
410 sev_enabled(void)
411 {
412     return sev_state ? true : false;
413 }
414
415 uint64_t
416 sev_get_me_mask(void)
417 {
418     return sev_state ? sev_state->me_mask : ~0;
419 }
420
421 uint32_t
422 sev_get_cbit_position(void)
423 {
424     return sev_state ? sev_state->cbitpos : 0;
425 }
426
427 uint32_t
428 sev_get_reduced_phys_bits(void)
429 {
430     return sev_state ? sev_state->reduced_phys_bits : 0;
431 }
432
433 SevInfo *
434 sev_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
453 static int
454 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
455                  size_t *cert_chain_len)
456 {
457     guchar *pdh_data = NULL;
458     guchar *cert_chain_data = NULL;
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
490 e_free:
491     g_free(pdh_data);
492     g_free(cert_chain_data);
493     return 1;
494 }
495
496 SevCapability *
497 sev_get_capabilities(void)
498 {
499     SevCapability *cap = NULL;
500     guchar *pdh_data = NULL;
501     guchar *cert_chain_data = NULL;
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)) {
515         goto out;
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
531 out:
532     g_free(pdh_data);
533     g_free(cert_chain_data);
534     close(fd);
535     return cap;
536 }
537
538 static int
539 sev_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
554 static int
555 sev_launch_start(SEVState *s)
556 {
557     gsize sz;
558     int ret = 1;
559     int fw_error, rc;
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) {
572             goto out;
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) {
580             goto out;
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);
587     rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
588     if (rc < 0) {
589         error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
590                 __func__, ret, fw_error, fw_error_to_str(fw_error));
591         goto out;
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;
599     ret = 0;
600
601 out:
602     g_free(start);
603     g_free(session);
604     g_free(dh_cert);
605     return ret;
606 }
607
608 static int
609 sev_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
631 static void
632 sev_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
672 free_data:
673     g_free(data);
674 free_measurement:
675     g_free(measurement);
676 }
677
678 char *
679 sev_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
689 static Notifier sev_machine_done_notify = {
690     .notify = sev_launch_get_measure,
691 };
692
693 static void
694 sev_launch_finish(SEVState *s)
695 {
696     int ret, error;
697     Error *local_err = NULL;
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);
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     }
718 }
719
720 static void
721 sev_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
732 void *
733 sev_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
742     sev_state = s = g_new0(SEVState, 1);
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
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));
777     }
778     g_free(devname);
779     if (s->sev_fd < 0) {
780         goto err;
781     }
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
803     ret = sev_launch_start(s);
804     if (ret) {
805         error_report("%s: failed to create encryption context", __func__);
806         goto err;
807     }
808
809     ram_block_notifier_add(&sev_ram_notifier);
810     qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
811     qemu_add_vm_change_state_handler(sev_vm_state_change, s);
812
813     return s;
814 err:
815     g_free(sev_state);
816     sev_state = NULL;
817     return NULL;
818 }
819
820 int
821 sev_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
833 static void
834 sev_register_types(void)
835 {
836     type_register_static(&qsev_guest_info);
837 }
838
839 type_init(sev_register_types);
This page took 0.07251 seconds and 4 git commands to generate.