[RFC v3 11/24] target/arm/kvm-rme: Populate Realm with runtime images
Mathieu Poirier <[email protected]>
| Newsgroups | org.kernel.vger.kvm,org.nongnu.qemu-arm,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
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()); + + 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; +} + +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(); } -- 2.43.0