From 324fcc6bc06fd1dd2152f3a52fcd7acd26589bb7 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Wed, 16 Oct 2024 10:53:06 -0700 Subject: [PATCH] ANDROID: virt: gunyah: Support boot context register values up to ULONG_MAX Values from (LONG_MAX, ULONG_MAX] aren't supported values by xarray. Allocate a container to store the value instead and insert the container to the xarray. Change-Id: Iaf6a50cc4d56ab2108e3e21f2dfc493cd518cb22 Bug: 373872273 Fixes: ed8ebd8c80c5 ("FROMLIST: virt: gunyah: Allow userspace to initialize context of primary vCPU") Signed-off-by: Elliot Berman Signed-off-by: Elliot Berman --- drivers/virt/gunyah/vm_mgr.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/virt/gunyah/vm_mgr.c b/drivers/virt/gunyah/vm_mgr.c index 83a2983ac3bc..5d9b4576fe30 100644 --- a/drivers/virt/gunyah/vm_mgr.c +++ b/drivers/virt/gunyah/vm_mgr.c @@ -551,6 +551,7 @@ static long gunyah_vm_set_boot_context(struct gunyah_vm *ghvm, struct gunyah_vm_boot_context *boot_ctx) { u8 reg_set, reg_index; /* to check values are reasonable */ + u64 *value; int ret; if (boot_ctx->reg & ~BOOT_CONTEXT_REG_MASK) @@ -585,8 +586,21 @@ static long gunyah_vm_set_boot_context(struct gunyah_vm *ghvm, goto out; } + /* + * allocate memory for the value because xarray supports [0, LONG_MAX] + * for values and we want [0, ULONG_MAX] + */ + value = kmalloc(sizeof(*value), GFP_KERNEL); + if (!value) { + ret = -ENOMEM; + goto out; + } + *value = boot_ctx->value; + ret = xa_err(xa_store(&ghvm->boot_context, boot_ctx->reg, - (void *)boot_ctx->value, GFP_KERNEL)); + value, GFP_KERNEL)); + if (ret) + kfree(value); out: up_read(&ghvm->status_lock); return ret; @@ -601,8 +615,9 @@ static inline int gunyah_vm_fill_boot_context(struct gunyah_vm *ghvm) xa_for_each(&ghvm->boot_context, id, entry) { reg_set = (id >> GUNYAH_VM_BOOT_CONTEXT_REG_SHIFT) & 0xff; reg_index = id & 0xff; - ret = gunyah_rm_vm_set_boot_context( - ghvm->rm, ghvm->vmid, reg_set, reg_index, (u64)entry); + ret = gunyah_rm_vm_set_boot_context(ghvm->rm, ghvm->vmid, + reg_set, reg_index, + *(u64 *)entry); if (ret) return ret; } @@ -976,6 +991,7 @@ static void _gunyah_vm_put(struct kref *kref) struct gunyah_vm *ghvm = container_of(kref, struct gunyah_vm, kref); struct gunyah_vm_gup_binding *b; unsigned long index = 0; + void *entry; int ret; /** @@ -1059,6 +1075,9 @@ static void _gunyah_vm_put(struct kref *kref) "Failed to deallocate vmid: %d\n", ret); } + xa_for_each(&ghvm->boot_context, index, entry) + kfree(entry); + xa_destroy(&ghvm->boot_context); gunyah_rm_put(ghvm->rm); mmdrop(ghvm->mm_s);