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:
committed by
Treehugger Robot
parent
7f0e1ddf29
commit
e9f270f15d
+10
-14
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user