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