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