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 object_class_property_set_description(oc, "sev-device", 253 "SEV device to use"); 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 object_class_property_set_description(oc, "dh-cert-file", 258 "guest owners DH certificate (encoded with base64)"); 259 object_class_property_add_str(oc, "session-file", 260 qsev_guest_get_session_file, 261 qsev_guest_set_session_file); 262 object_class_property_set_description(oc, "session-file", 263 "guest owners session parameters (encoded with base64)"); 264 } 265 266 static void 267 qsev_guest_init(Object *obj) 268 { 269 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); 270 271 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE); 272 sev->policy = DEFAULT_GUEST_POLICY; 273 object_property_add_uint32_ptr(obj, "policy", &sev->policy, 274 OBJ_PROP_FLAG_READWRITE); 275 object_property_add_uint32_ptr(obj, "handle", &sev->handle, 276 OBJ_PROP_FLAG_READWRITE); 277 object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos, 278 OBJ_PROP_FLAG_READWRITE); 279 object_property_add_uint32_ptr(obj, "reduced-phys-bits", 280 &sev->reduced_phys_bits, 281 OBJ_PROP_FLAG_READWRITE); 282 } 283 284 /* sev guest info */ 285 static const TypeInfo qsev_guest_info = { 286 .parent = TYPE_OBJECT, 287 .name = TYPE_QSEV_GUEST_INFO, 288 .instance_size = sizeof(QSevGuestInfo), 289 .instance_finalize = qsev_guest_finalize, 290 .class_size = sizeof(QSevGuestInfoClass), 291 .class_init = qsev_guest_class_init, 292 .instance_init = qsev_guest_init, 293 .interfaces = (InterfaceInfo[]) { 294 { TYPE_USER_CREATABLE }, 295 { } 296 } 297 }; 298 299 static QSevGuestInfo * 300 lookup_sev_guest_info(const char *id) 301 { 302 Object *obj; 303 QSevGuestInfo *info; 304 305 obj = object_resolve_path_component(object_get_objects_root(), id); 306 if (!obj) { 307 return NULL; 308 } 309 310 info = (QSevGuestInfo *) 311 object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO); 312 if (!info) { 313 return NULL; 314 } 315 316 return info; 317 } 318 319 bool 320 sev_enabled(void) 321 { 322 return sev_state ? true : false; 323 } 324 325 uint64_t 326 sev_get_me_mask(void) 327 { 328 return sev_state ? sev_state->me_mask : ~0; 329 } 330 331 uint32_t 332 sev_get_cbit_position(void) 333 { 334 return sev_state ? sev_state->cbitpos : 0; 335 } 336 337 uint32_t 338 sev_get_reduced_phys_bits(void) 339 { 340 return sev_state ? sev_state->reduced_phys_bits : 0; 341 } 342 343 SevInfo * 344 sev_get_info(void) 345 { 346 SevInfo *info; 347 348 info = g_new0(SevInfo, 1); 349 info->enabled = sev_state ? true : false; 350 351 if (info->enabled) { 352 info->api_major = sev_state->api_major; 353 info->api_minor = sev_state->api_minor; 354 info->build_id = sev_state->build_id; 355 info->policy = sev_state->policy; 356 info->state = sev_state->state; 357 info->handle = sev_state->handle; 358 } 359 360 return info; 361 } 362 363 static int 364 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain, 365 size_t *cert_chain_len) 366 { 367 guchar *pdh_data = NULL; 368 guchar *cert_chain_data = NULL; 369 struct sev_user_data_pdh_cert_export export = {}; 370 int err, r; 371 372 /* query the certificate length */ 373 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err); 374 if (r < 0) { 375 if (err != SEV_RET_INVALID_LEN) { 376 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)", 377 r, err, fw_error_to_str(err)); 378 return 1; 379 } 380 } 381 382 pdh_data = g_new(guchar, export.pdh_cert_len); 383 cert_chain_data = g_new(guchar, export.cert_chain_len); 384 export.pdh_cert_address = (unsigned long)pdh_data; 385 export.cert_chain_address = (unsigned long)cert_chain_data; 386 387 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err); 388 if (r < 0) { 389 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)", 390 r, err, fw_error_to_str(err)); 391 goto e_free; 392 } 393 394 *pdh = pdh_data; 395 *pdh_len = export.pdh_cert_len; 396 *cert_chain = cert_chain_data; 397 *cert_chain_len = export.cert_chain_len; 398 return 0; 399 400 e_free: 401 g_free(pdh_data); 402 g_free(cert_chain_data); 403 return 1; 404 } 405 406 SevCapability * 407 sev_get_capabilities(void) 408 { 409 SevCapability *cap = NULL; 410 guchar *pdh_data = NULL; 411 guchar *cert_chain_data = NULL; 412 size_t pdh_len = 0, cert_chain_len = 0; 413 uint32_t ebx; 414 int fd; 415 416 fd = open(DEFAULT_SEV_DEVICE, O_RDWR); 417 if (fd < 0) { 418 error_report("%s: Failed to open %s '%s'", __func__, 419 DEFAULT_SEV_DEVICE, strerror(errno)); 420 return NULL; 421 } 422 423 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len, 424 &cert_chain_data, &cert_chain_len)) { 425 goto out; 426 } 427 428 cap = g_new0(SevCapability, 1); 429 cap->pdh = g_base64_encode(pdh_data, pdh_len); 430 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len); 431 432 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL); 433 cap->cbitpos = ebx & 0x3f; 434 435 /* 436 * When SEV feature is enabled, we loose one bit in guest physical 437 * addressing. 438 */ 439 cap->reduced_phys_bits = 1; 440 441 out: 442 g_free(pdh_data); 443 g_free(cert_chain_data); 444 close(fd); 445 return cap; 446 } 447 448 static int 449 sev_read_file_base64(const char *filename, guchar **data, gsize *len) 450 { 451 gsize sz; 452 gchar *base64; 453 GError *error = NULL; 454 455 if (!g_file_get_contents(filename, &base64, &sz, &error)) { 456 error_report("failed to read '%s' (%s)", filename, error->message); 457 return -1; 458 } 459 460 *data = g_base64_decode(base64, len); 461 return 0; 462 } 463 464 static int 465 sev_launch_start(SEVState *s) 466 { 467 gsize sz; 468 int ret = 1; 469 int fw_error, rc; 470 QSevGuestInfo *sev = s->sev_info; 471 struct kvm_sev_launch_start *start; 472 guchar *session = NULL, *dh_cert = NULL; 473 474 start = g_new0(struct kvm_sev_launch_start, 1); 475 476 start->handle = object_property_get_int(OBJECT(sev), "handle", 477 &error_abort); 478 start->policy = object_property_get_int(OBJECT(sev), "policy", 479 &error_abort); 480 if (sev->session_file) { 481 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) { 482 goto out; 483 } 484 start->session_uaddr = (unsigned long)session; 485 start->session_len = sz; 486 } 487 488 if (sev->dh_cert_file) { 489 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) { 490 goto out; 491 } 492 start->dh_uaddr = (unsigned long)dh_cert; 493 start->dh_len = sz; 494 } 495 496 trace_kvm_sev_launch_start(start->policy, session, dh_cert); 497 rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error); 498 if (rc < 0) { 499 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'", 500 __func__, ret, fw_error, fw_error_to_str(fw_error)); 501 goto out; 502 } 503 504 object_property_set_int(OBJECT(sev), start->handle, "handle", 505 &error_abort); 506 sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE); 507 s->handle = start->handle; 508 s->policy = start->policy; 509 ret = 0; 510 511 out: 512 g_free(start); 513 g_free(session); 514 g_free(dh_cert); 515 return ret; 516 } 517 518 static int 519 sev_launch_update_data(uint8_t *addr, uint64_t len) 520 { 521 int ret, fw_error; 522 struct kvm_sev_launch_update_data update; 523 524 if (!addr || !len) { 525 return 1; 526 } 527 528 update.uaddr = (__u64)(unsigned long)addr; 529 update.len = len; 530 trace_kvm_sev_launch_update_data(addr, len); 531 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA, 532 &update, &fw_error); 533 if (ret) { 534 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'", 535 __func__, ret, fw_error, fw_error_to_str(fw_error)); 536 } 537 538 return ret; 539 } 540 541 static void 542 sev_launch_get_measure(Notifier *notifier, void *unused) 543 { 544 int ret, error; 545 guchar *data; 546 SEVState *s = sev_state; 547 struct kvm_sev_launch_measure *measurement; 548 549 if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE)) { 550 return; 551 } 552 553 measurement = g_new0(struct kvm_sev_launch_measure, 1); 554 555 /* query the measurement blob length */ 556 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE, 557 measurement, &error); 558 if (!measurement->len) { 559 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", 560 __func__, ret, error, fw_error_to_str(errno)); 561 goto free_measurement; 562 } 563 564 data = g_new0(guchar, measurement->len); 565 measurement->uaddr = (unsigned long)data; 566 567 /* get the measurement blob */ 568 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE, 569 measurement, &error); 570 if (ret) { 571 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", 572 __func__, ret, error, fw_error_to_str(errno)); 573 goto free_data; 574 } 575 576 sev_set_guest_state(SEV_STATE_LAUNCH_SECRET); 577 578 /* encode the measurement value and emit the event */ 579 s->measurement = g_base64_encode(data, measurement->len); 580 trace_kvm_sev_launch_measurement(s->measurement); 581 582 free_data: 583 g_free(data); 584 free_measurement: 585 g_free(measurement); 586 } 587 588 char * 589 sev_get_launch_measurement(void) 590 { 591 if (sev_state && 592 sev_state->state >= SEV_STATE_LAUNCH_SECRET) { 593 return g_strdup(sev_state->measurement); 594 } 595 596 return NULL; 597 } 598 599 static Notifier sev_machine_done_notify = { 600 .notify = sev_launch_get_measure, 601 }; 602 603 static void 604 sev_launch_finish(SEVState *s) 605 { 606 int ret, error; 607 Error *local_err = NULL; 608 609 trace_kvm_sev_launch_finish(); 610 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error); 611 if (ret) { 612 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'", 613 __func__, ret, error, fw_error_to_str(error)); 614 exit(1); 615 } 616 617 sev_set_guest_state(SEV_STATE_RUNNING); 618 619 /* add migration blocker */ 620 error_setg(&sev_mig_blocker, 621 "SEV: Migration is not implemented"); 622 ret = migrate_add_blocker(sev_mig_blocker, &local_err); 623 if (local_err) { 624 error_report_err(local_err); 625 error_free(sev_mig_blocker); 626 exit(1); 627 } 628 } 629 630 static void 631 sev_vm_state_change(void *opaque, int running, RunState state) 632 { 633 SEVState *s = opaque; 634 635 if (running) { 636 if (!sev_check_state(SEV_STATE_RUNNING)) { 637 sev_launch_finish(s); 638 } 639 } 640 } 641 642 void * 643 sev_guest_init(const char *id) 644 { 645 SEVState *s; 646 char *devname; 647 int ret, fw_error; 648 uint32_t ebx; 649 uint32_t host_cbitpos; 650 struct sev_user_data_status status = {}; 651 652 sev_state = s = g_new0(SEVState, 1); 653 s->sev_info = lookup_sev_guest_info(id); 654 if (!s->sev_info) { 655 error_report("%s: '%s' is not a valid '%s' object", 656 __func__, id, TYPE_QSEV_GUEST_INFO); 657 goto err; 658 } 659 660 s->state = SEV_STATE_UNINIT; 661 662 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL); 663 host_cbitpos = ebx & 0x3f; 664 665 s->cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL); 666 if (host_cbitpos != s->cbitpos) { 667 error_report("%s: cbitpos check failed, host '%d' requested '%d'", 668 __func__, host_cbitpos, s->cbitpos); 669 goto err; 670 } 671 672 s->reduced_phys_bits = object_property_get_int(OBJECT(s->sev_info), 673 "reduced-phys-bits", NULL); 674 if (s->reduced_phys_bits < 1) { 675 error_report("%s: reduced_phys_bits check failed, it should be >=1," 676 " requested '%d'", __func__, s->reduced_phys_bits); 677 goto err; 678 } 679 680 s->me_mask = ~(1UL << s->cbitpos); 681 682 devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL); 683 s->sev_fd = open(devname, O_RDWR); 684 if (s->sev_fd < 0) { 685 error_report("%s: Failed to open %s '%s'", __func__, 686 devname, strerror(errno)); 687 } 688 g_free(devname); 689 if (s->sev_fd < 0) { 690 goto err; 691 } 692 693 ret = sev_platform_ioctl(s->sev_fd, SEV_PLATFORM_STATUS, &status, 694 &fw_error); 695 if (ret) { 696 error_report("%s: failed to get platform status ret=%d " 697 "fw_error='%d: %s'", __func__, ret, fw_error, 698 fw_error_to_str(fw_error)); 699 goto err; 700 } 701 s->build_id = status.build; 702 s->api_major = status.api_major; 703 s->api_minor = status.api_minor; 704 705 trace_kvm_sev_init(); 706 ret = sev_ioctl(s->sev_fd, KVM_SEV_INIT, NULL, &fw_error); 707 if (ret) { 708 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'", 709 __func__, ret, fw_error, fw_error_to_str(fw_error)); 710 goto err; 711 } 712 713 ret = sev_launch_start(s); 714 if (ret) { 715 error_report("%s: failed to create encryption context", __func__); 716 goto err; 717 } 718 719 ram_block_notifier_add(&sev_ram_notifier); 720 qemu_add_machine_init_done_notifier(&sev_machine_done_notify); 721 qemu_add_vm_change_state_handler(sev_vm_state_change, s); 722 723 return s; 724 err: 725 g_free(sev_state); 726 sev_state = NULL; 727 return NULL; 728 } 729 730 int 731 sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) 732 { 733 assert(handle); 734 735 /* if SEV is in update state then encrypt the data else do nothing */ 736 if (sev_check_state(SEV_STATE_LAUNCH_UPDATE)) { 737 return sev_launch_update_data(ptr, len); 738 } 739 740 return 0; 741 } 742 743 static void 744 sev_register_types(void) 745 { 746 type_register_static(&qsev_guest_info); 747 } 748 749 type_init(sev_register_types); 750