On 10/21/26 7:47 PM, Lorenzo Pieralisi wrote:
On Fri, Oct 02, 2026 at 01:45:40PM +1000, Gavin Shan wrote:
On 9/4/26 5:35 AM, Mathieu Poirier wrote:
From: Jean-Philippe Brucker <[email protected]>

Once the Realm descriptor has been created, tell KVM to transfer runtime
images (kernel, DT, and rootfs) from guest memory to Realm memory.

Signed-off-by: Jean-Philippe Brucker <[email protected]>
Signed-off-by: Lorenzo Pieralisi <[email protected]>
Signed-off-by: Mathieu Poirier <[email protected]>
---
   target/arm/kvm-rme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++
   1 file changed, 76 insertions(+)

diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c
index 9985f5daba89..c082a5d8f3d1 100644
--- a/target/arm/kvm-rme.c
+++ b/target/arm/kvm-rme.c
@@ -15,6 +15,7 @@
   #include "migration/blocker.h"
   #include "qapi/error.h"
   #include "qemu/error-report.h"
+#include "qemu/memalign.h"
   #include "qom/object_interfaces.h"
   #include "system/confidential-guest-support.h"
   #include "system/kvm.h"
@@ -43,12 +44,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, 
rme_guest, RME_GUEST,
   static RmeGuest *rme_guest;
+static int rme_populate_range(const RmeRamRegion *region, bool measure,
+                              Error **errp)
+{
+    int ret;
+    void *buffer;
+    hwaddr size = region->size;
+    hwaddr base = region->base;
+    hwaddr start = QEMU_ALIGN_DOWN(base, RME_PAGE_SIZE);
+    hwaddr end = QEMU_ALIGN_UP(base + size, RME_PAGE_SIZE);
+    struct kvm_arm_rmi_populate populate_args;
+    size_t aligned_size = ROUND_UP(region->size, qemu_real_host_page_size());

s/qemu_real_host_page_size()/RME_PAGE_SIZE

It will always have to be qemu_real_host_page_size(), KVM configures it
that way.

+
+    if (!region->data) {
+        return -ENODEV;
+    }
+
+    ret = kvm_set_memory_attributes_private(start, end - start);
+    if (ret) {
+        error_report("RME: failed to configure initial"
+                     "private guest memory");
+        return ret;
+    }
+
+    /* Allocate page-aligned memory */
+    buffer = qemu_memalign(qemu_real_host_page_size(), aligned_size);
+
+    if (!buffer) {
+        return -ENOMEM;
+    }
+
+    memset(buffer, 0, aligned_size);
+    memcpy(buffer, region->data, region->size);
+
+    populate_args = (struct kvm_arm_rmi_populate) {
+        .base = start,
+        .size = end - start,
+        .source_uaddr = (uintptr_t)buffer,
+        .flags = measure ? KVM_ARM_RMI_POPULATE_FLAGS_MEASURE : 0,
+    };
+
+    while (populate_args.size > 0) {
+        ret = kvm_vm_ioctl(kvm_state, KVM_ARM_RMI_POPULATE, &populate_args, 0);
+        if (ret) {
+            error_setg_errno(errp, -ret,
+                "failed to populate realm [0x%"HWADDR_PRIx", 
0x%"HWADDR_PRIx")",
+                start, end);
+            break;
+        }
+    }
+
+    qemu_vfree(buffer);
+
+    return ret;
+}
+

I doubt that the unaligned regions (RmeRamRegion) are allowed. For example,
the region [4KB 64KB+4KB] is turned to the aligned range [0 128KB] when 
RME_PAGE_SIZE
is 64KB. The question is how do we know the added regions due to the alignment
([0 4KB] and [64KB+4KB 128KB]) are safe for kvm_vm_ioctl(KVM_ARM_RMI_POPULATE).

Getting back to this because it is important. Can you define "safe" here ?

I think it is VMM's role to load with the required alignment and make
sure it does not double populate (that is anyway prevented by KVM), what was
your concern here to make sure we are in agreement ?


For example, there are two regions are populated: [0 4KB] and [4KB 64KB] on a 
64KB
host. With the alignment considered, we're populating [0 64KB] for region [0 
4KB],
and [0 64KB] for [4KB 64KB]. [0 64KB] are populated for twice. Is this allowed 
by
TF-RMM? If it's allowed by TF-RMM, the data populated in the first time is 
overwritten
by the second population.

Thanks,
Gavin

Thanks,
Lorenzo

I guess we probably just reject unaligned regions if they're not expected.

Even if the unaligned regions are allowed, they seem not well handled.

- @aligned_size is still 64KB instead of the 128KB ?
- In "memcpy(buffer, region->data, region->size);", the blob data would be 
copied to
   [4KB, 4KB+64KB]. However, we're copying the data to [0 64KB] now.

+static void rme_populate_ram_region(gpointer data, gpointer err)
+{
+    Error **errp = err;
+    const RmeRamRegion *region = data;
+
+    if (*errp) {
+        return;
+    }
+
+    rme_populate_range(region, /* measure */ true, errp);
+}
+
   static void rme_vm_state_change(void *opaque, bool running, RunState state)
   {
+    Error *errp = NULL;
+
       if (!running) {
           return;
       }
+    g_slist_foreach(rme_guest->ram_regions, rme_populate_ram_region, &errp);
+    g_slist_free_full(g_steal_pointer(&rme_guest->ram_regions), g_free);
+    if (errp) {
+        return;
+    }
+
       kvm_mark_guest_state_protected();
   }

Thanks,
Gavin




Reply via email to