From 6c23c215a67f7b5863c8b36fa9f09c168b5c6033 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 7 Jul 2022 15:49:07 +0100 Subject: [PATCH] Revert "ANDROID: KVM: arm64: Flag pages needing poisoning in hyp_vmemmap" This reverts commit a0662e559d6237e1a37d1f3096e35ad2a071a9b7. Bug: 233587962 Signed-off-by: Will Deacon Change-Id: I5e5ddab37e7ebfc0c1f25120e39760064f99871b --- arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 1 + arch/arm64/kvm/hyp/include/nvhe/memory.h | 6 ---- arch/arm64/kvm/hyp/nvhe/mem_protect.c | 33 ++++++++++++++----- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h index e9eef7c2cebb..0118a3b6b943 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h @@ -58,6 +58,7 @@ typedef u32 pkvm_id; static const pkvm_id pkvm_host_id = 0; static const pkvm_id pkvm_hyp_id = (1 << 16); static const pkvm_id pkvm_ffa_id = pkvm_hyp_id + 1; /* Secure world */ +static const pkvm_id pkvm_host_poison = pkvm_ffa_id + 1; extern unsigned long hyp_nr_cpus; diff --git a/arch/arm64/kvm/hyp/include/nvhe/memory.h b/arch/arm64/kvm/hyp/include/nvhe/memory.h index 2723c6ce9b53..29f2ebe306bc 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/memory.h +++ b/arch/arm64/kvm/hyp/include/nvhe/memory.h @@ -7,12 +7,6 @@ #include -/* - * Accesses to struct hyp_page flags must be serialized by the host stage-2 - * page-table lock due to the lack of atomics at EL2. - */ -#define HOST_PAGE_NEED_POISONING BIT(0) - struct hyp_page { unsigned short refcount; u8 order; diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index 8758bc56de56..603d9e78ca1e 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -286,13 +286,17 @@ static int reclaim_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep, void * const arg) { kvm_pte_t pte = *ptep; - struct hyp_page *page; + phys_addr_t phys; if (!kvm_pte_valid(pte)) return 0; - page = hyp_phys_to_page(kvm_pte_to_phys(pte)); - page->flags |= HOST_PAGE_NEED_POISONING; + /* + * Only update the host stage-2 -- we're about to tear-down the guest + * stage-2 so no need to waste effort trying to keep it in sync. + */ + phys = kvm_pte_to_phys(pte); + BUG_ON(host_stage2_set_owner_locked(phys, PAGE_SIZE, pkvm_host_poison)); return 0; } @@ -516,6 +520,11 @@ static kvm_pte_t kvm_init_invalid_leaf_owner(pkvm_id owner_id) return FIELD_PREP(KVM_INVALID_PTE_OWNER_MASK, owner_id); } +static pkvm_id kvm_get_owner_id(kvm_pte_t pte) +{ + return FIELD_GET(KVM_INVALID_PTE_OWNER_MASK, pte); +} + int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, pkvm_id owner_id) { @@ -1855,7 +1864,7 @@ static int hyp_zero_page(phys_addr_t phys) int __pkvm_host_reclaim_page(u64 pfn) { u64 addr = hyp_pfn_to_phys(pfn); - struct hyp_page *page; + enum pkvm_page_state state; kvm_pte_t pte; int ret; @@ -1865,17 +1874,23 @@ int __pkvm_host_reclaim_page(u64 pfn) if (ret) goto unlock; - if (host_get_page_state(pte) == PKVM_PAGE_OWNED) + if (kvm_pte_valid(pte)) { + state = host_get_page_state(pte); + ret = (state == PKVM_PAGE_OWNED) ? 0 : -EPERM; goto unlock; + } - page = hyp_phys_to_page(addr); - if (page->flags & HOST_PAGE_NEED_POISONING) { + switch (kvm_get_owner_id(pte)) { + case pkvm_host_id: + ret = 0; + break; + case pkvm_host_poison: ret = hyp_zero_page(addr); if (ret) goto unlock; - page->flags &= ~HOST_PAGE_NEED_POISONING; ret = host_stage2_set_owner_locked(addr, PAGE_SIZE, pkvm_host_id); - } else { + break; + default: ret = -EPERM; }