| /* | 
 |  * 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) | 
 | { | 
 | } |