1 /* 2 * QEMU SEV support 3 * 4 * Copyright Advanced Micro Devices 2016-2018 5 * 6 * Author: 7 * Brijesh Singh <brijesh.singh@amd.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 * 12 */ 13 14 #include "qemu/osdep.h" 15 16 #include <linux/kvm.h> 17 #include <linux/psp-sev.h> 18 19 #include <sys/ioctl.h> 20 21 #include "qapi/error.h" 22 #include "qom/object_interfaces.h" 23 #include "qemu/base64.h" 24 #include "qemu/module.h" 25 #include "sysemu/kvm.h" 26 #include "sev_i386.h" 27 #include "sysemu/sysemu.h" 28 #include "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 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 176 static struct RAMBlockNotifier sev_ram_notifier = { 177 .ram_block_added = sev_ram_block_added, 178 .ram_block_removed = sev_ram_block_removed, 179 }; 180 181 static void 182 qsev_guest_finalize(Object *obj) 183 { 184 } 185 186 static char * 187 qsev_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 194 static void 195 qsev_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 202 static char * 203 qsev_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 210 static void 211 qsev_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 218 static char * 219 qsev_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 226 static void 227 qsev_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 234 static void 235 qsev_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 257 static void 258 qsev_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 268 static void 269 qsev_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 279 static void 280 qsev_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 290 static void 291 qsev_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 301 static void 302 qsev_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 312 static void 313 qsev_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 323 static void 324 qsev_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 334 static void 335 qsev_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 345 static void 346 qsev_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 */ 364 static 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 378 static QSevGuestInfo * 379 lookup_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 398 bool 399 sev_enabled(void) 400 { 401 return sev_state ? true : false; 402 } 403 404 uint64_t 405 sev_get_me_mask(void) 406 { 407 return sev_state ? sev_state->me_mask : ~0; 408 } 409 410 uint32_t 411 sev_get_cbit_position(void) 412 { 413 return sev_state ? sev_state->cbitpos : 0; 414 } 415 416 uint32_t 417 sev_get_reduced_phys_bits(void) 418 { 419 return sev_state ? sev_state->reduced_phys_bits : 0; 420 } 421 422 SevInfo * 423 sev_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 442 static int 443 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain, 444 size_t *cert_chain_len) 445 { 446 guchar *pdh_data = NULL; 447 guchar *cert_chain_data = NULL; 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 479 e_free: 480 g_free(pdh_data); 481 g_free(cert_chain_data); 482 return 1; 483 } 484 485 SevCapability * 486 sev_get_capabilities(void) 487 { 488 SevCapability *cap = NULL; 489 guchar *pdh_data = NULL; 490 guchar *cert_chain_data = NULL; 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)) { 504 goto out; 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 520 out: 521 g_free(pdh_data); 522 g_free(cert_chain_data); 523 close(fd); 524 return cap; 525 } 526 527 static int 528 sev_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 543 static int 544 sev_launch_start(SEVState *s) 545 { 546 gsize sz; 547 int ret = 1; 548 int fw_error, rc; 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) { 561 goto out; 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) { 569 goto out; 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); 576 rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error); 577 if (rc < 0) { 578 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'", 579 __func__, ret, fw_error, fw_error_to_str(fw_error)); 580 goto out; 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; 588 ret = 0; 589 590 out: 591 g_free(start); 592 g_free(session); 593 g_free(dh_cert); 594 return ret; 595 } 596 597 static int 598 sev_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 620 static void 621 sev_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 661 free_data: 662 g_free(data); 663 free_measurement: 664 g_free(measurement); 665 } 666 667 char * 668 sev_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 678 static Notifier sev_machine_done_notify = { 679 .notify = sev_launch_get_measure, 680 }; 681 682 static void 683 sev_launch_finish(SEVState *s) 684 { 685 int ret, error; 686 Error *local_err = NULL; 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); 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 } 707 } 708 709 static void 710 sev_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 721 void * 722 sev_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 731 sev_state = s = g_new0(SEVState, 1); 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 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)); 766 } 767 g_free(devname); 768 if (s->sev_fd < 0) { 769 goto err; 770 } 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 792 ret = sev_launch_start(s); 793 if (ret) { 794 error_report("%s: failed to create encryption context", __func__); 795 goto err; 796 } 797 798 ram_block_notifier_add(&sev_ram_notifier); 799 qemu_add_machine_init_done_notifier(&sev_machine_done_notify); 800 qemu_add_vm_change_state_handler(sev_vm_state_change, s); 801 802 return s; 803 err: 804 g_free(sev_state); 805 sev_state = NULL; 806 return NULL; 807 } 808 809 int 810 sev_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 822 static void 823 sev_register_types(void) 824 { 825 type_register_static(&qsev_guest_info); 826 } 827 828 type_init(sev_register_types); 829