From 5d0225cdf0a0e151577eecca07aceae1bf291a9b Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Mon, 24 Apr 2023 16:00:29 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Don't allocate from handle_host_mem_abort There shouldn't be any reason to ever need allocating from the host stage-2 pool during mem aborts now that the base page-table structure is pinned. To prevent future regressions in this area, introduce a new sanity check that will warn when hyp_page_alloc() is used from the mem wrong paths. Bug: 264070847 Change-Id: I7a7c606fe01558790e4ffcd3534f8976caf48bd0 Signed-off-by: Quentin Perret --- arch/arm64/kvm/hyp/nvhe/mem_protect.c | 29 ++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index a158beff7057..905e50f2d49e 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -79,10 +79,35 @@ static void hyp_unlock_component(void) hyp_spin_unlock(&pkvm_pgd_lock); } +static void assert_host_can_alloc(void) +{ + /* We can always get back to the host from guest context */ + if (read_sysreg(vttbr_el2) != kvm_get_vttbr(&host_mmu.arch.mmu)) + return; + + /* + * An error code must be returned to EL1 to handle memory allocation + * failures cleanly. That's doable for explicit calls into higher + * ELs, but not so much for other EL2 entry reasons such as mem aborts. + * Thankfully we don't need memory allocation in these cases by + * construction, so let's enforce the invariant. + */ + switch (ESR_ELx_EC(read_sysreg(esr_el2))) { + case ESR_ELx_EC_HVC64: + case ESR_ELx_EC_SMC64: + break; + default: + WARN_ON(1); + } +} + static void *host_s2_zalloc_pages_exact(size_t size) { - void *addr = hyp_alloc_pages(&host_s2_pool, get_order(size)); + void *addr; + assert_host_can_alloc(); + + addr = hyp_alloc_pages(&host_s2_pool, get_order(size)); hyp_split_page(hyp_virt_to_page(addr)); /* @@ -97,6 +122,8 @@ static void *host_s2_zalloc_pages_exact(size_t size) static void *host_s2_zalloc_page(void *pool) { + assert_host_can_alloc(); + return hyp_alloc_pages(pool, 0); }