From 358f24a8c491d14a33b9e9f73722e9aec610135d Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Wed, 8 Nov 2023 15:34:02 +0000 Subject: [PATCH] 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 --- arch/arm64/include/asm/kvm_pkvm.h | 1 + arch/arm64/kvm/pkvm.c | 71 +++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h index c76724cb404e..c72e8089a473 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -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 { diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index b78c1b49505a..707ebd9a1ab3 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -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)