On 7/8/26 8:42 AM, Mathieu Poirier wrote:
From: Jean-Philippe Brucker <[email protected]>

Initialise an @rme_guest object and install a handler to get notified
when the Realm is ready to start.  That way we can finish reading the
Realm once we know everything is in place.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
Signed-off-by: Mathieu Poirier <[email protected]>
---
  target/arm/kvm-rme.c  | 50 +++++++++++++++++++++++++++++++++++++++++++
  target/arm/kvm-stub.c |  5 +++++
  target/arm/kvm.c      |  7 +++++-
  target/arm/kvm_arm.h  |  9 ++++++++
  4 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c
index 42e1d1e7b859..b86b9d6a25cb 100644
--- a/target/arm/kvm-rme.c
+++ b/target/arm/kvm-rme.c
@@ -13,6 +13,7 @@
  #include "kvm_arm.h"
  #include "migration/blocker.h"
  #include "qapi/error.h"
+#include "qemu/error-report.h"
  #include "qom/object_interfaces.h"
  #include "system/confidential-guest-support.h"
  #include "system/kvm.h"
@@ -29,14 +30,63 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, 
rme_guest, RME_GUEST,
                                            CONFIDENTIAL_GUEST_SUPPORT,
                                            { TYPE_USER_CREATABLE }, { })
+static RmeGuest *rme_guest;
+
+static void rme_vm_state_change(void *opaque, bool running, RunState state)
+{
+    if (!running) {
+        return;
+    }
+
+    kvm_mark_guest_state_protected();
+}
+
  static void rme_guest_class_init(ObjectClass *oc, const void *data)
  {
  }
static void rme_guest_init(Object *obj)
  {
+    if (rme_guest) {
+        error_report("a single instance of RmeGuest is supported");
+        exit(1);
+    }
+    rme_guest = RME_GUEST(obj);
  }
static void rme_guest_finalize(Object *obj)
  {
  }
+
+int kvm_arm_rme_init(MachineState *ms, KVMState *s)
+{
+    static Error *rme_mig_blocker;
+    ConfidentialGuestSupport *cgs = ms->cgs;
+
+    if (!rme_guest) {
+        return 0;
+    }
+
+    if (!cgs) {
+        error_report("missing -machine confidential-guest-support parameter");
+        return -EINVAL;
+    }
+
+    if (!kvm_vm_check_extension(s, KVM_CAP_ARM_RMI)) {
+        error_report("KVM doesn't support Realms");
+        return -ENODEV;
+    }
+
+    error_setg(&rme_mig_blocker, "RME: migration is not implemented");
+    migrate_add_blocker(&rme_mig_blocker, &error_fatal);
+
+    /*
+     * The realm activation is done last, when the VM starts, after all images
+     * have been loaded and all vcpus finalized.
+     */
+    qemu_add_vm_change_state_handler(rme_vm_state_change, NULL);
+
+    cgs->require_guest_memfd = true;
+    cgs->ready = true;
+    return 0;
+}

I think it's more reasonable to set ConfidentialGuestSupportClass::kvm_init to
kvm_arm_rme_init in rme_guest_class_init(). confidential_guest_kvm_init()
gets called in target/arm/kvm.c::kvm_arch_init(). With this, the pattern matches
with that for x86.

More details can be found from commit 631a2ac5a4be ("i386/tdx: Implement 
tdx_kvm_init()
to initialize TDX VM context").

Thanks,
Gavin

diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c
index 88cbe8d85c41..eec1ca3dd2e5 100644
--- a/target/arm/kvm-stub.c
+++ b/target/arm/kvm-stub.c
@@ -119,3 +119,8 @@ char *kvm_print_register_name(uint64_t regidx)
  {
      g_assert_not_reached();
  }
+
+int kvm_arm_rme_init(MachineState *ms, KVMState *s)
+{
+    g_assert_not_reached();
+}
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index ed99be7fd80c..28d5643d6779 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -660,7 +660,12 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
      hw_breakpoints = g_array_sized_new(true, true,
                                         sizeof(HWBreakpoint), max_hw_bps);
- return 0;
+    ret = kvm_arm_rme_init(ms, s);
+    if (ret) {
+        error_report("Failed to enable RME: %s", strerror(-ret));
+    }
+
+    return ret;
  }
unsigned long kvm_arch_vcpu_id(CPUState *cpu)
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index e7c40fb003e4..6d058b0e08a2 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -240,4 +240,13 @@ void arm_gic_cap_kvm_probe(GICCapability *v2, 
GICCapability *v3);
   */
  char *kvm_print_register_name(uint64_t regidx);
+/**
+ * kvm_arm_rme_init
+ * @ms: the machine state
+ * @s: State of KVM
+ *
+ * Prepare the machine to be a Realm, if the user enabled it.
+ */
+int kvm_arm_rme_init(MachineState *ms, KVMState *s);
+
  #endif


Reply via email to