ANDROID: BACKPORT: KVM: arm64: Always unmap the pvmfw region at stage-2

The donation of the pvmfw region to pKVM is currently done transparently
as part of fix_host_ownership(). However, this function only runs over PA
ranges covered by the memblock list, although there is no guarantee for
the pvmfw region to be advertised in a memory node in DT. In this case,
the pKVM init will appear to succeed while silently keeping valid host
stage-2 mappings to the pvmfw region.

Fix this by forcefully registering the pvmfw region in the pKVM memblock
list.

BACKPORT: Fix usage of pvmfw_size and pvmfw_base which are pointers in
6.6 and earlier.

Bug: 278749606
Bug: 424382332
Reported-by: Bartłomiej Grzesik <bgrzesik@google.com>
Suggested-by: Will Deacon <willdeacon@google.com>
Change-Id: I8f5498df25debb432b7dffd1e40a8910bcec7b49
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
Quentin Perret
2025-06-23 13:39:53 +00:00
committed by Treehugger Robot
parent 3a0107a38e
commit 56cc224601

View File

@@ -65,6 +65,7 @@ static void __init sort_memblock_regions(void)
static int __init register_memblock_regions(void) static int __init register_memblock_regions(void)
{ {
struct memblock_region *reg; struct memblock_region *reg;
bool pvmfw_in_mem = false;
for_each_mem_region(reg) { for_each_mem_region(reg) {
if (*hyp_memblock_nr_ptr >= HYP_MEMBLOCK_REGIONS) 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_memory[*hyp_memblock_nr_ptr] = *reg;
(*hyp_memblock_nr_ptr)++; (*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(); sort_memblock_regions();