ANDROID: KVM: arm64: Pin host stage-2 tables

Now that the host stage-2 page-table is entirely pre-populated in
__pkvm_init_finalize(), we know that by the end of this function, the
structure of the page-table will remain stable until the host calls in
the hypervisor to require e.g. a page-table changes (by e.g. running a
guest). This does not necessarily mean that no host mem aborts will
occur -- there may be null PTEs in the host stage-2 due to collapsed
block mappings from fix_host_ownership() for example -- but all those
aborts should be trivially handled without requiring structural changes
to the page-table. This has the nice side effect of guaranteeing that
host_mem_abort() will not allocate from the host stage-2 pool. In order
to ensure this desirable property is retained for the lifetime of the
system even in the presence of the coalescing feature, let's 'pin' the
structure of the page-table as-is by taking an additional reference
from each table entry.

Bug: 264070847
Change-Id: If870d7485cc38f6ad714901e710287911f111897
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
Quentin Perret 2023-04-03 13:46:40 +00:00 committed by Carlos Llamas
parent a8bba661e3
commit 452ef5ae7b

View File

@ -277,6 +277,29 @@ static int fix_hyp_pgtable_refcnt_walker(u64 addr, u64 end, u32 level,
return 0;
}
static int pin_table_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
enum kvm_pgtable_walk_flags flag, void * const arg)
{
struct kvm_pgtable_mm_ops *mm_ops = arg;
kvm_pte_t pte = *ptep;
if (kvm_pte_valid(pte))
mm_ops->get_page(kvm_pte_follow(pte, mm_ops));
return 0;
}
static int pin_host_tables(void)
{
struct kvm_pgtable_walker walker = {
.cb = pin_table_walker,
.flags = KVM_PGTABLE_WALK_TABLE_POST,
.arg = &host_mmu.mm_ops,
};
return kvm_pgtable_walk(&host_mmu.pgt, 0, BIT(host_mmu.pgt.ia_bits), &walker);
}
static int fix_host_ownership(void)
{
struct kvm_pgtable_walker walker = {
@ -373,6 +396,10 @@ void __noreturn __pkvm_init_finalise(void)
if (ret)
goto out;
ret = pin_host_tables();
if (ret)
goto out;
ret = hyp_ffa_init(ffa_proxy_pages);
if (ret)
goto out;