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