From 22c8a338c7900455180e80d4dcda94a33c01fe0c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 17 Nov 2022 15:32:08 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Check IPA range for pvmfw during guest donation When donating pages to the guest, we only check the first IPA in the range against the pvmfw loading range. Although this is fine for the page-at-a-time faulting path, it doesn't fit with the rest of the mem protection logic, which deals with the possibility of an arbitrarily sized contiguous address range. Rework the logic so that we check the whole IPA range during guest donation and trigger the pvmfw loading path if any of the pages intersect with the pvmfw region. Signed-off-by: Will Deacon Bug: 254819795 Change-Id: I6fef9f1898e65a95cab7f6a0ffa8aa422a8d5a91 Signed-off-by: Will Deacon Signed-off-by: Quentin Perret --- arch/arm64/kvm/hyp/include/nvhe/pkvm.h | 6 ++++-- arch/arm64/kvm/hyp/nvhe/mem_protect.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h index 65861da8b460..644dce2f9256 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h +++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h @@ -121,14 +121,16 @@ static inline bool pkvm_hyp_vm_has_pvmfw(struct pkvm_hyp_vm *vm) return vm->kvm.arch.pkvm.pvmfw_load_addr != PVMFW_INVALID_LOAD_ADDR; } -static inline bool pkvm_ipa_in_pvmfw_region(struct pkvm_hyp_vm *vm, u64 ipa) +static inline bool pkvm_ipa_range_has_pvmfw(struct pkvm_hyp_vm *vm, + u64 ipa_start, u64 ipa_end) { struct kvm_protected_vm *pkvm = &vm->kvm.arch.pkvm; + u64 pvmfw_load_end = pkvm->pvmfw_load_addr + pvmfw_size; if (!pkvm_hyp_vm_has_pvmfw(vm)) return false; - return ipa - pkvm->pvmfw_load_addr < pvmfw_size; + return ipa_end > pkvm->pvmfw_load_addr && ipa_start < pvmfw_load_end; } int pkvm_load_pvmfw_pages(struct pkvm_hyp_vm *vm, u64 ipa, phys_addr_t phys, diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index ba7f7564adb8..abed3fd9e0a2 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -1078,11 +1078,11 @@ static int guest_complete_donation(u64 addr, const struct pkvm_mem_transition *t u64 size = tx->nr_pages * PAGE_SIZE; int err; - if (tx->initiator.id == PKVM_ID_HOST && - pkvm_ipa_in_pvmfw_region(vm, addr)) { + if (pkvm_ipa_range_has_pvmfw(vm, addr, addr + size)) { if (WARN_ON(!pkvm_hyp_vcpu_is_protected(vcpu))) return -EPERM; + WARN_ON(tx->initiator.id != PKVM_ID_HOST); err = pkvm_load_pvmfw_pages(vm, addr, phys, size); if (err) return err;