ANDROID: KVM: arm64: Fix loading pvmfw into a protected VM

We cannot stash a pointer into the OF driver's reserved_mem table
because this is now sorted *after* init functions are called. Hence
we can end up with a pointer to an arbitrary rmem region.

Instead copy out the required base and size fields.

Bug: 400034937
Bug: 357781595
Change-Id: I2e04e8400ba1ec59def7b73d0a97cc83a9e39873
Signed-off-by: Keir Fraser <keirf@google.com>
This commit is contained in:
Keir Fraser
2025-03-05 15:04:31 +00:00
committed by Treehugger Robot
parent 7f0e1ddf29
commit e9f270f15d
+10 -14
View File
@@ -41,9 +41,8 @@
DEFINE_STATIC_KEY_FALSE(kvm_protected_mode_initialized);
static struct reserved_mem *pkvm_firmware_mem;
static phys_addr_t *pvmfw_base = &kvm_nvhe_sym(pvmfw_base);
static phys_addr_t *pvmfw_size = &kvm_nvhe_sym(pvmfw_size);
static phys_addr_t pvmfw_base;
static phys_addr_t pvmfw_size;
static struct pkvm_moveable_reg *moveable_regs = kvm_nvhe_sym(pkvm_moveable_regs);
static struct memblock_region *hyp_memory = kvm_nvhe_sym(hyp_memory);
@@ -741,7 +740,7 @@ static int __init pkvm_firmware_rmem_init(struct reserved_mem *rmem)
{
unsigned long node = rmem->fdt_node;
if (pkvm_firmware_mem)
if (pvmfw_size)
return pkvm_firmware_rmem_err(rmem, "duplicate reservation");
if (!of_get_flat_dt_prop(node, "no-map", NULL))
@@ -756,9 +755,8 @@ static int __init pkvm_firmware_rmem_init(struct reserved_mem *rmem)
if (!PAGE_ALIGNED(rmem->size))
return pkvm_firmware_rmem_err(rmem, "size is not page-aligned");
*pvmfw_size = rmem->size;
*pvmfw_base = rmem->base;
pkvm_firmware_mem = rmem;
pvmfw_size = kvm_nvhe_sym(pvmfw_size) = rmem->size;
pvmfw_base = kvm_nvhe_sym(pvmfw_base) = rmem->base;
return 0;
}
RESERVEDMEM_OF_DECLARE(pkvm_firmware, "linux,pkvm-guest-firmware-memory",
@@ -769,12 +767,12 @@ static int __init pkvm_firmware_rmem_clear(void)
void *addr;
phys_addr_t size;
if (likely(!pkvm_firmware_mem))
if (likely(!pvmfw_size))
return 0;
kvm_info("Clearing pKVM firmware memory\n");
size = pkvm_firmware_mem->size;
addr = memremap(pkvm_firmware_mem->base, size, MEMREMAP_WB);
size = pvmfw_size;
addr = memremap(pvmfw_base, size, MEMREMAP_WB);
if (!addr)
return -EINVAL;
@@ -788,7 +786,7 @@ static int pkvm_vm_ioctl_set_fw_ipa(struct kvm *kvm, u64 ipa)
{
int ret = 0;
if (!pkvm_firmware_mem)
if (!pvmfw_size)
return -EINVAL;
mutex_lock(&kvm->lock);
@@ -807,9 +805,7 @@ static int pkvm_vm_ioctl_info(struct kvm *kvm,
struct kvm_protected_vm_info __user *info)
{
struct kvm_protected_vm_info kinfo = {
.firmware_size = pkvm_firmware_mem ?
pkvm_firmware_mem->size :
0,
.firmware_size = pvmfw_size,
};
return copy_to_user(info, &kinfo, sizeof(kinfo)) ? -EFAULT : 0;