qemu/hw/ppc/pef.c
<<
>>
Prefs
   1/*
   2 * PEF (Protected Execution Facility) for POWER support
   3 *
   4 * Copyright Red Hat.
   5 *
   6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   7 * See the COPYING file in the top-level directory.
   8 *
   9 */
  10
  11#include "qemu/osdep.h"
  12
  13#include "qapi/error.h"
  14#include "qom/object_interfaces.h"
  15#include "sysemu/kvm.h"
  16#include "migration/blocker.h"
  17#include "exec/confidential-guest-support.h"
  18#include "hw/ppc/pef.h"
  19
  20#define TYPE_PEF_GUEST "pef-guest"
  21OBJECT_DECLARE_SIMPLE_TYPE(PefGuest, PEF_GUEST)
  22
  23typedef struct PefGuest PefGuest;
  24typedef struct PefGuestClass PefGuestClass;
  25
  26struct PefGuestClass {
  27    ConfidentialGuestSupportClass parent_class;
  28};
  29
  30/**
  31 * PefGuest:
  32 *
  33 * The PefGuest object is used for creating and managing a PEF
  34 * guest.
  35 *
  36 * # $QEMU \
  37 *         -object pef-guest,id=pef0 \
  38 *         -machine ...,confidential-guest-support=pef0
  39 */
  40struct PefGuest {
  41    ConfidentialGuestSupport parent_obj;
  42};
  43
  44static int kvmppc_svm_init(ConfidentialGuestSupport *cgs, Error **errp)
  45{
  46#ifdef CONFIG_KVM
  47    static Error *pef_mig_blocker;
  48
  49    if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_SECURE_GUEST)) {
  50        error_setg(errp,
  51                   "KVM implementation does not support Secure VMs (is an ultravisor running?)");
  52        return -1;
  53    } else {
  54        int ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_SECURE_GUEST, 0, 1);
  55
  56        if (ret < 0) {
  57            error_setg(errp,
  58                       "Error enabling PEF with KVM");
  59            return -1;
  60        }
  61    }
  62
  63    /* add migration blocker */
  64    error_setg(&pef_mig_blocker, "PEF: Migration is not implemented");
  65    /* NB: This can fail if --only-migratable is used */
  66    migrate_add_blocker(pef_mig_blocker, &error_fatal);
  67
  68    cgs->ready = true;
  69
  70    return 0;
  71#else
  72    g_assert_not_reached();
  73#endif
  74}
  75
  76/*
  77 * Don't set error if KVM_PPC_SVM_OFF ioctl is invoked on kernels
  78 * that don't support this ioctl.
  79 */
  80static int kvmppc_svm_off(Error **errp)
  81{
  82#ifdef CONFIG_KVM
  83    int rc;
  84
  85    rc = kvm_vm_ioctl(KVM_STATE(current_accel()), KVM_PPC_SVM_OFF);
  86    if (rc && rc != -ENOTTY) {
  87        error_setg_errno(errp, -rc, "KVM_PPC_SVM_OFF ioctl failed");
  88        return rc;
  89    }
  90    return 0;
  91#else
  92    g_assert_not_reached();
  93#endif
  94}
  95
  96int pef_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
  97{
  98    if (!object_dynamic_cast(OBJECT(cgs), TYPE_PEF_GUEST)) {
  99        return 0;
 100    }
 101
 102    if (!kvm_enabled()) {
 103        error_setg(errp, "PEF requires KVM");
 104        return -1;
 105    }
 106
 107    return kvmppc_svm_init(cgs, errp);
 108}
 109
 110int pef_kvm_reset(ConfidentialGuestSupport *cgs, Error **errp)
 111{
 112    if (!object_dynamic_cast(OBJECT(cgs), TYPE_PEF_GUEST)) {
 113        return 0;
 114    }
 115
 116    /*
 117     * If we don't have KVM we should never have been able to
 118     * initialize PEF, so we should never get this far
 119     */
 120    assert(kvm_enabled());
 121
 122    return kvmppc_svm_off(errp);
 123}
 124
 125OBJECT_DEFINE_TYPE_WITH_INTERFACES(PefGuest,
 126                                   pef_guest,
 127                                   PEF_GUEST,
 128                                   CONFIDENTIAL_GUEST_SUPPORT,
 129                                   { TYPE_USER_CREATABLE },
 130                                   { NULL })
 131
 132static void pef_guest_class_init(ObjectClass *oc, void *data)
 133{
 134}
 135
 136static void pef_guest_init(Object *obj)
 137{
 138}
 139
 140static void pef_guest_finalize(Object *obj)
 141{
 142}
 143