From 452ef5ae7b72ad953c76269afdd045b05ba8083f Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Mon, 3 Apr 2023 13:46:40 +0000 Subject: [PATCH] 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 --- arch/arm64/kvm/hyp/nvhe/setup.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c index 569f3be83a17..c0f502c5edb2 100644 --- a/arch/arm64/kvm/hyp/nvhe/setup.c +++ b/arch/arm64/kvm/hyp/nvhe/setup.c @@ -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;