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