diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index 4523cc6f2725..61b524129366 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -65,6 +65,7 @@ static void __init sort_memblock_regions(void) static int __init register_memblock_regions(void) { struct memblock_region *reg; + bool pvmfw_in_mem = false; for_each_mem_region(reg) { if (*hyp_memblock_nr_ptr >= HYP_MEMBLOCK_REGIONS) @@ -72,6 +73,27 @@ static int __init register_memblock_regions(void) hyp_memory[*hyp_memblock_nr_ptr] = *reg; (*hyp_memblock_nr_ptr)++; + + if (!*pvmfw_size || pvmfw_in_mem || + !memblock_addrs_overlap(reg->base, reg->size, *pvmfw_base, *pvmfw_size)) + continue; + /* If the pvmfw region overlaps a memblock, it must be a subset */ + if (*pvmfw_base < reg->base || + (*pvmfw_base + *pvmfw_size) > (reg->base + reg->size)) + return -EINVAL; + pvmfw_in_mem = true; + } + + if (*pvmfw_size && !pvmfw_in_mem) { + if (*hyp_memblock_nr_ptr >= HYP_MEMBLOCK_REGIONS) + return -ENOMEM; + + hyp_memory[*hyp_memblock_nr_ptr] = (struct memblock_region) { + .base = *pvmfw_base, + .size = *pvmfw_size, + .flags = MEMBLOCK_NOMAP, + }; + (*hyp_memblock_nr_ptr)++; } sort_memblock_regions();