xref: /openbmc/qemu/hw/ppc/pef.c (revision 13b1e9667737132440f4d500c31cb69320c6b15a)
16c8ebe30SDavid Gibson /*
26c8ebe30SDavid Gibson  * PEF (Protected Execution Facility) for POWER support
36c8ebe30SDavid Gibson  *
46c8ebe30SDavid Gibson  * Copyright Red Hat.
56c8ebe30SDavid Gibson  *
66c8ebe30SDavid Gibson  * This work is licensed under the terms of the GNU GPL, version 2 or later.
76c8ebe30SDavid Gibson  * See the COPYING file in the top-level directory.
86c8ebe30SDavid Gibson  *
96c8ebe30SDavid Gibson  */
106c8ebe30SDavid Gibson 
116c8ebe30SDavid Gibson #include "qemu/osdep.h"
126c8ebe30SDavid Gibson 
136c8ebe30SDavid Gibson #include "qapi/error.h"
146c8ebe30SDavid Gibson #include "qom/object_interfaces.h"
156c8ebe30SDavid Gibson #include "sysemu/kvm.h"
166c8ebe30SDavid Gibson #include "migration/blocker.h"
176c8ebe30SDavid Gibson #include "exec/confidential-guest-support.h"
186c8ebe30SDavid Gibson 
196c8ebe30SDavid Gibson #define TYPE_PEF_GUEST "pef-guest"
206c8ebe30SDavid Gibson OBJECT_DECLARE_SIMPLE_TYPE(PefGuest, PEF_GUEST)
216c8ebe30SDavid Gibson 
226c8ebe30SDavid Gibson typedef struct PefGuest PefGuest;
236c8ebe30SDavid Gibson typedef struct PefGuestClass PefGuestClass;
246c8ebe30SDavid Gibson 
256c8ebe30SDavid Gibson struct PefGuestClass {
266c8ebe30SDavid Gibson     ConfidentialGuestSupportClass parent_class;
276c8ebe30SDavid Gibson };
286c8ebe30SDavid Gibson 
296c8ebe30SDavid Gibson /**
306c8ebe30SDavid Gibson  * PefGuest:
316c8ebe30SDavid Gibson  *
326c8ebe30SDavid Gibson  * The PefGuest object is used for creating and managing a PEF
336c8ebe30SDavid Gibson  * guest.
346c8ebe30SDavid Gibson  *
356c8ebe30SDavid Gibson  * # $QEMU \
366c8ebe30SDavid Gibson  *         -object pef-guest,id=pef0 \
376c8ebe30SDavid Gibson  *         -machine ...,confidential-guest-support=pef0
386c8ebe30SDavid Gibson  */
396c8ebe30SDavid Gibson struct PefGuest {
406c8ebe30SDavid Gibson     ConfidentialGuestSupport parent_obj;
416c8ebe30SDavid Gibson };
426c8ebe30SDavid Gibson 
kvmppc_svm_init(ConfidentialGuestSupport * cgs,Error ** errp)43b873ed83SDaniel Henrique Barboza static int kvmppc_svm_init(ConfidentialGuestSupport *cgs, Error **errp)
446c8ebe30SDavid Gibson {
456c8ebe30SDavid Gibson #ifdef CONFIG_KVM
466742eefcSDavid Gibson     static Error *pef_mig_blocker;
476742eefcSDavid Gibson 
486c8ebe30SDavid Gibson     if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_SECURE_GUEST)) {
496c8ebe30SDavid Gibson         error_setg(errp,
506c8ebe30SDavid Gibson                    "KVM implementation does not support Secure VMs (is an ultravisor running?)");
516c8ebe30SDavid Gibson         return -1;
526c8ebe30SDavid Gibson     } else {
536c8ebe30SDavid Gibson         int ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_SECURE_GUEST, 0, 1);
546c8ebe30SDavid Gibson 
556c8ebe30SDavid Gibson         if (ret < 0) {
566c8ebe30SDavid Gibson             error_setg(errp,
576c8ebe30SDavid Gibson                        "Error enabling PEF with KVM");
586c8ebe30SDavid Gibson             return -1;
596c8ebe30SDavid Gibson         }
606c8ebe30SDavid Gibson     }
616c8ebe30SDavid Gibson 
626742eefcSDavid Gibson     /* add migration blocker */
636742eefcSDavid Gibson     error_setg(&pef_mig_blocker, "PEF: Migration is not implemented");
646742eefcSDavid Gibson     /* NB: This can fail if --only-migratable is used */
65c8a7fc51SSteve Sistare     migrate_add_blocker(&pef_mig_blocker, &error_fatal);
666742eefcSDavid Gibson 
67b873ed83SDaniel Henrique Barboza     cgs->ready = true;
68b873ed83SDaniel Henrique Barboza 
696c8ebe30SDavid Gibson     return 0;
706c8ebe30SDavid Gibson #else
716c8ebe30SDavid Gibson     g_assert_not_reached();
726c8ebe30SDavid Gibson #endif
736c8ebe30SDavid Gibson }
746c8ebe30SDavid Gibson 
756c8ebe30SDavid Gibson /*
766c8ebe30SDavid Gibson  * Don't set error if KVM_PPC_SVM_OFF ioctl is invoked on kernels
776c8ebe30SDavid Gibson  * that don't support this ioctl.
786c8ebe30SDavid Gibson  */
kvmppc_svm_off(Error ** errp)796c8ebe30SDavid Gibson static int kvmppc_svm_off(Error **errp)
806c8ebe30SDavid Gibson {
816c8ebe30SDavid Gibson #ifdef CONFIG_KVM
826c8ebe30SDavid Gibson     int rc;
836c8ebe30SDavid Gibson 
846c8ebe30SDavid Gibson     rc = kvm_vm_ioctl(KVM_STATE(current_accel()), KVM_PPC_SVM_OFF);
856c8ebe30SDavid Gibson     if (rc && rc != -ENOTTY) {
866c8ebe30SDavid Gibson         error_setg_errno(errp, -rc, "KVM_PPC_SVM_OFF ioctl failed");
876c8ebe30SDavid Gibson         return rc;
886c8ebe30SDavid Gibson     }
896c8ebe30SDavid Gibson     return 0;
906c8ebe30SDavid Gibson #else
916c8ebe30SDavid Gibson     g_assert_not_reached();
926c8ebe30SDavid Gibson #endif
936c8ebe30SDavid Gibson }
946c8ebe30SDavid Gibson 
pef_kvm_init(ConfidentialGuestSupport * cgs,Error ** errp)95*00a238b1SXiaoyao Li static int pef_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
966c8ebe30SDavid Gibson {
976c8ebe30SDavid Gibson     if (!object_dynamic_cast(OBJECT(cgs), TYPE_PEF_GUEST)) {
986c8ebe30SDavid Gibson         return 0;
996c8ebe30SDavid Gibson     }
1006c8ebe30SDavid Gibson 
1016c8ebe30SDavid Gibson     if (!kvm_enabled()) {
1026c8ebe30SDavid Gibson         error_setg(errp, "PEF requires KVM");
1036c8ebe30SDavid Gibson         return -1;
1046c8ebe30SDavid Gibson     }
1056c8ebe30SDavid Gibson 
106b873ed83SDaniel Henrique Barboza     return kvmppc_svm_init(cgs, errp);
1076c8ebe30SDavid Gibson }
1086c8ebe30SDavid Gibson 
pef_kvm_reset(ConfidentialGuestSupport * cgs,Error ** errp)109*00a238b1SXiaoyao Li static int pef_kvm_reset(ConfidentialGuestSupport *cgs, Error **errp)
1106c8ebe30SDavid Gibson {
1116c8ebe30SDavid Gibson     if (!object_dynamic_cast(OBJECT(cgs), TYPE_PEF_GUEST)) {
1126c8ebe30SDavid Gibson         return 0;
1136c8ebe30SDavid Gibson     }
1146c8ebe30SDavid Gibson 
1156c8ebe30SDavid Gibson     /*
1166c8ebe30SDavid Gibson      * If we don't have KVM we should never have been able to
1176c8ebe30SDavid Gibson      * initialize PEF, so we should never get this far
1186c8ebe30SDavid Gibson      */
1196c8ebe30SDavid Gibson     assert(kvm_enabled());
1206c8ebe30SDavid Gibson 
1216c8ebe30SDavid Gibson     return kvmppc_svm_off(errp);
1226c8ebe30SDavid Gibson }
1236c8ebe30SDavid Gibson 
1246c8ebe30SDavid Gibson OBJECT_DEFINE_TYPE_WITH_INTERFACES(PefGuest,
1256c8ebe30SDavid Gibson                                    pef_guest,
1266c8ebe30SDavid Gibson                                    PEF_GUEST,
1276c8ebe30SDavid Gibson                                    CONFIDENTIAL_GUEST_SUPPORT,
1286c8ebe30SDavid Gibson                                    { TYPE_USER_CREATABLE },
1296c8ebe30SDavid Gibson                                    { NULL })
1306c8ebe30SDavid Gibson 
pef_guest_class_init(ObjectClass * oc,void * data)1316c8ebe30SDavid Gibson static void pef_guest_class_init(ObjectClass *oc, void *data)
1326c8ebe30SDavid Gibson {
133*00a238b1SXiaoyao Li     ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
134*00a238b1SXiaoyao Li 
135*00a238b1SXiaoyao Li     klass->kvm_init = pef_kvm_init;
136*00a238b1SXiaoyao Li     klass->kvm_reset = pef_kvm_reset;
1376c8ebe30SDavid Gibson }
1386c8ebe30SDavid Gibson 
pef_guest_init(Object * obj)1396c8ebe30SDavid Gibson static void pef_guest_init(Object *obj)
1406c8ebe30SDavid Gibson {
1416c8ebe30SDavid Gibson }
1426c8ebe30SDavid Gibson 
pef_guest_finalize(Object * obj)1436c8ebe30SDavid Gibson static void pef_guest_finalize(Object *obj)
1446c8ebe30SDavid Gibson {
1456c8ebe30SDavid Gibson }
146