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