xref: /openbmc/qemu/hw/ppc/pef.c (revision a9bc470ec208bd27a82100abc9dccf1b69f41b45)
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"
21  OBJECT_DECLARE_SIMPLE_TYPE(PefGuest, PEF_GUEST)
22  
23  typedef struct PefGuest PefGuest;
24  typedef struct PefGuestClass PefGuestClass;
25  
26  struct 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   */
40  struct PefGuest {
41      ConfidentialGuestSupport parent_obj;
42  };
43  
44  static 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   */
80  static 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  
96  int 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  
110  int 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  
125  OBJECT_DEFINE_TYPE_WITH_INTERFACES(PefGuest,
126                                     pef_guest,
127                                     PEF_GUEST,
128                                     CONFIDENTIAL_GUEST_SUPPORT,
129                                     { TYPE_USER_CREATABLE },
130                                     { NULL })
131  
132  static void pef_guest_class_init(ObjectClass *oc, void *data)
133  {
134  }
135  
136  static void pef_guest_init(Object *obj)
137  {
138  }
139  
140  static void pef_guest_finalize(Object *obj)
141  {
142  }
143