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_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
 280static void
 281qsev_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
 291static void
 292qsev_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
 302static void
 303qsev_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
 313static void
 314qsev_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
 324static void
 325qsev_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
 335static void
 336qsev_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
 346static void
 347qsev_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
 357static void
 358qsev_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 */
 376static 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
 390static QSevGuestInfo *
 391lookup_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
 410bool
 411sev_enabled(void)
 412{
 413    return sev_state ? true : false;
 414}
 415
 416uint64_t
 417sev_get_me_mask(void)
 418{
 419    return sev_state ? sev_state->me_mask : ~0;
 420}
 421
 422uint32_t
 423sev_get_cbit_position(void)
 424{
 425    return sev_state ? sev_state->cbitpos : 0;
 426}
 427
 428uint32_t
 429sev_get_reduced_phys_bits(void)
 430{
 431    return sev_state ? sev_state->reduced_phys_bits : 0;
 432}
 433
 434SevInfo *
 435sev_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
 454static int
 455sev_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
 491e_free:
 492    g_free(pdh_data);
 493    g_free(cert_chain_data);
 494    return 1;
 495}
 496
 497SevCapability *
 498sev_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
 532out:
 533    g_free(pdh_data);
 534    g_free(cert_chain_data);
 535    close(fd);
 536    return cap;
 537}
 538
 539static int
 540sev_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
 555static int
 556sev_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
 602out:
 603    g_free(start);
 604    g_free(session);
 605    g_free(dh_cert);
 606    return ret;
 607}
 608
 609static int
 610sev_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
 632static void
 633sev_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
 673free_data:
 674    g_free(data);
 675free_measurement:
 676    g_free(measurement);
 677}
 678
 679char *
 680sev_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
 690static Notifier sev_machine_done_notify = {
 691    .notify = sev_launch_get_measure,
 692};
 693
 694static void
 695sev_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
 721static void
 722sev_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
 733void *
 734sev_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;
 815err:
 816    g_free(sev_state);
 817    sev_state = NULL;
 818    return NULL;
 819}
 820
 821int
 822sev_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
 834static void
 835sev_register_types(void)
 836{
 837    type_register_static(&qsev_guest_info);
 838}
 839
 840type_init(sev_register_types);
 841