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