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 b1fb8957f3de..22c8afe21505 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" @@ -41,12 +42,87 @@ OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RmeGuest, rme_guest, RME_GUEST, static RmeGuest *rme_guest; +static int rme_populate_range(const RmeRamRegion *region, Error **errp) +{ + int ret; + void *buffer; + hwaddr size = region->size; + hwaddr base = region->base; + unsigned long page_size = qemu_real_host_page_size(); + hwaddr start = QEMU_ALIGN_DOWN(base, page_size); + hwaddr end = QEMU_ALIGN_UP(base + size, page_size); + size_t aligned_size = end - start; + struct kvm_arm_rmi_populate populate_args; + + if (!region->data) { + return -ENODEV; + } + + ret = kvm_set_memory_attributes_private(start, aligned_size); + if (ret) { + error_report("RME: failed to configure initial" + "private guest memory"); + return ret; + } + + /* Allocate page-aligned memory */ + buffer = qemu_memalign(page_size, aligned_size); + + if (!buffer) { + return -ENOMEM; + } + + memset(buffer, 0, aligned_size); + memcpy(buffer + (base - start), region->data, region->size); + + populate_args = (struct kvm_arm_rmi_populate) { + .base = start, + .size = aligned_size, + .source_uaddr = (uintptr_t)buffer, + .flags = KVM_ARM_RMI_POPULATE_FLAGS_MEASURE, + }; + + 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; +} + +static void rme_populate_ram_region(gpointer data, gpointer err) +{ + Error **errp = err; + const RmeRamRegion *region = data; + + if (*errp) { + return; + } + + rme_populate_range(region, 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(); } -- 2.43.0
