ANDROID: KVM: arm64: devices: Register assignable devices as moveable

To prevent assignable devices MMIO from being unmapped under
pressure, register them as moveable memory.

Unfortunately, as moveable memory is registered very early at boot,
while devices are registered later after pKVM init and IOMMU driver
register, we would have some duplicate code parsing assignable
devices from the device tree.

Bug: 357781595
Bug: 348382247
Change-Id: I5957c5f7c10f435a970409195825259dc65072ad
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2023-11-08 15:34:02 +00:00
parent 0e3c9e4c42
commit 358f24a8c4
2 changed files with 50 additions and 22 deletions
+1
View File
@@ -268,6 +268,7 @@ static inline bool kvm_pvm_ext_allowed(long ext)
enum pkvm_moveable_reg_type {
PKVM_MREG_MEMORY,
PKVM_MREG_PROTECTED_RANGE,
PKVM_MREG_ASSIGN_MMIO,
};
struct pkvm_moveable_reg {
+49 -22
View File
@@ -110,11 +110,39 @@ static void __init sort_moveable_regs(void)
NULL);
}
static int __init register_moveable_fdt_resource(struct device_node *np,
enum pkvm_moveable_reg_type type)
{
struct resource res;
u64 start, size;
unsigned int j = 0;
unsigned int i = kvm_nvhe_sym(pkvm_moveable_regs_nr);
while(!of_address_to_resource(np, j, &res)) {
if (i >= PKVM_NR_MOVEABLE_REGS)
return -ENOMEM;
start = res.start;
size = resource_size(&res);
if (!PAGE_ALIGNED(start) || !PAGE_ALIGNED(size))
return -EINVAL;
moveable_regs[i].start = start;
moveable_regs[i].size = size;
moveable_regs[i].type = type;
i++;
j++;
}
kvm_nvhe_sym(pkvm_moveable_regs_nr) = i;
return 0;
}
static int __init register_moveable_regions(void)
{
struct memblock_region *reg;
struct device_node *np;
int i = 0;
int i = 0, ret = 0, idx = 0;
for_each_mem_region(reg) {
if (i >= PKVM_NR_MOVEABLE_REGS)
@@ -124,34 +152,33 @@ static int __init register_moveable_regions(void)
moveable_regs[i].type = PKVM_MREG_MEMORY;
i++;
}
kvm_nvhe_sym(pkvm_moveable_regs_nr) = i;
for_each_compatible_node(np, NULL, "pkvm,protected-region") {
struct resource res;
u64 start, size;
int ret;
if (i >= PKVM_NR_MOVEABLE_REGS)
return -ENOMEM;
ret = of_address_to_resource(np, 0, &res);
ret = register_moveable_fdt_resource(np, PKVM_MREG_PROTECTED_RANGE);
if (ret)
return ret;
start = res.start;
size = resource_size(&res);
if (!PAGE_ALIGNED(start) || !PAGE_ALIGNED(size))
return -EINVAL;
moveable_regs[i].start = start;
moveable_regs[i].size = size;
moveable_regs[i].type = PKVM_MREG_PROTECTED_RANGE;
i++;
goto out_fail;
}
for_each_compatible_node(np, NULL, PKVM_DEVICE_ASSIGN_COMPAT) {
struct of_phandle_args args;
while (!of_parse_phandle_with_fixed_args(np, "devices", 1, idx, &args)) {
idx++;
ret = register_moveable_fdt_resource(args.np, PKVM_MREG_ASSIGN_MMIO);
of_node_put(args.np);
if (ret)
goto out_fail;
}
}
kvm_nvhe_sym(pkvm_moveable_regs_nr) = i;
sort_moveable_regs();
return 0;
return ret;
out_fail:
of_node_put(np);
kvm_nvhe_sym(pkvm_moveable_regs_nr) = 0;
return ret;
}
void __init kvm_hyp_reserve(void)