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